Mercurial > hg > truffle
annotate src/cpu/x86/vm/sharedRuntime_x86_32.cpp @ 3101:6ccb95c97e6d
IdealGraphVisualizer: Work around a problem with JSplitPane and the NetBeans editor: setDividerLocation() doesn't work when the split pane has not been layouted and painted yet. JSplitPane then initially uses a tiny width for the left editor component, which causes the editor to calculate invalid offsets and constantly throw exceptions, particularly on mouse events. Thus, defer adding the two components and setting the divider's location.
author | Peter Hofer <peter.hofer@jku.at> |
---|---|
date | Thu, 30 Jun 2011 12:17:27 +0200 |
parents | 3d58a4983660 |
children | 167b70ff3abc |
rev | line source |
---|---|
0 | 1 /* |
2245
638119ce7cfd
7009309: JSR 292: compiler/6991596/Test6991596.java crashes on fastdebug JDK7/b122
twisti
parents:
2177
diff
changeset
|
2 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1506
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1506
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1506
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "asm/assembler.hpp" | |
27 #include "assembler_x86.inline.hpp" | |
28 #include "code/debugInfoRec.hpp" | |
29 #include "code/icBuffer.hpp" | |
30 #include "code/vtableStubs.hpp" | |
31 #include "interpreter/interpreter.hpp" | |
32 #include "oops/compiledICHolderOop.hpp" | |
33 #include "prims/jvmtiRedefineClassesTrace.hpp" | |
34 #include "runtime/sharedRuntime.hpp" | |
35 #include "runtime/vframeArray.hpp" | |
36 #include "vmreg_x86.inline.hpp" | |
37 #ifdef COMPILER1 | |
38 #include "c1/c1_Runtime1.hpp" | |
39 #endif | |
40 #ifdef COMPILER2 | |
41 #include "opto/runtime.hpp" | |
42 #endif | |
0 | 43 |
44 #define __ masm-> | |
45 #ifdef COMPILER2 | |
46 UncommonTrapBlob *SharedRuntime::_uncommon_trap_blob; | |
47 #endif // COMPILER2 | |
48 | |
49 DeoptimizationBlob *SharedRuntime::_deopt_blob; | |
50 SafepointBlob *SharedRuntime::_polling_page_safepoint_handler_blob; | |
51 SafepointBlob *SharedRuntime::_polling_page_return_handler_blob; | |
52 RuntimeStub* SharedRuntime::_wrong_method_blob; | |
53 RuntimeStub* SharedRuntime::_ic_miss_blob; | |
54 RuntimeStub* SharedRuntime::_resolve_opt_virtual_call_blob; | |
55 RuntimeStub* SharedRuntime::_resolve_virtual_call_blob; | |
56 RuntimeStub* SharedRuntime::_resolve_static_call_blob; | |
57 | |
524
c9004fe53695
6792301: StackAlignmentInBytes not honored for compiled native methods
xlu
parents:
512
diff
changeset
|
58 const int StackAlignmentInSlots = StackAlignmentInBytes / VMRegImpl::stack_slot_size; |
c9004fe53695
6792301: StackAlignmentInBytes not honored for compiled native methods
xlu
parents:
512
diff
changeset
|
59 |
0 | 60 class RegisterSaver { |
61 enum { FPU_regs_live = 8 /*for the FPU stack*/+8/*eight more for XMM registers*/ }; | |
62 // Capture info about frame layout | |
63 enum layout { | |
64 fpu_state_off = 0, | |
65 fpu_state_end = fpu_state_off+FPUStateSizeInWords-1, | |
66 st0_off, st0H_off, | |
67 st1_off, st1H_off, | |
68 st2_off, st2H_off, | |
69 st3_off, st3H_off, | |
70 st4_off, st4H_off, | |
71 st5_off, st5H_off, | |
72 st6_off, st6H_off, | |
73 st7_off, st7H_off, | |
74 | |
75 xmm0_off, xmm0H_off, | |
76 xmm1_off, xmm1H_off, | |
77 xmm2_off, xmm2H_off, | |
78 xmm3_off, xmm3H_off, | |
79 xmm4_off, xmm4H_off, | |
80 xmm5_off, xmm5H_off, | |
81 xmm6_off, xmm6H_off, | |
82 xmm7_off, xmm7H_off, | |
83 flags_off, | |
84 rdi_off, | |
85 rsi_off, | |
86 ignore_off, // extra copy of rbp, | |
87 rsp_off, | |
88 rbx_off, | |
89 rdx_off, | |
90 rcx_off, | |
91 rax_off, | |
92 // The frame sender code expects that rbp will be in the "natural" place and | |
93 // will override any oopMap setting for it. We must therefore force the layout | |
94 // so that it agrees with the frame sender code. | |
95 rbp_off, | |
96 return_off, // slot for return address | |
97 reg_save_size }; | |
98 | |
99 | |
100 public: | |
101 | |
102 static OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words, | |
103 int* total_frame_words, bool verify_fpu = true); | |
104 static void restore_live_registers(MacroAssembler* masm); | |
105 | |
106 static int rax_offset() { return rax_off; } | |
107 static int rbx_offset() { return rbx_off; } | |
108 | |
109 // Offsets into the register save area | |
110 // Used by deoptimization when it is managing result register | |
111 // values on its own | |
112 | |
113 static int raxOffset(void) { return rax_off; } | |
114 static int rdxOffset(void) { return rdx_off; } | |
115 static int rbxOffset(void) { return rbx_off; } | |
116 static int xmm0Offset(void) { return xmm0_off; } | |
117 // This really returns a slot in the fp save area, which one is not important | |
118 static int fpResultOffset(void) { return st0_off; } | |
119 | |
120 // During deoptimization only the result register need to be restored | |
121 // all the other values have already been extracted. | |
122 | |
123 static void restore_result_registers(MacroAssembler* masm); | |
124 | |
125 }; | |
126 | |
127 OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, | |
128 int* total_frame_words, bool verify_fpu) { | |
129 | |
130 int frame_size_in_bytes = (reg_save_size + additional_frame_words) * wordSize; | |
131 int frame_words = frame_size_in_bytes / wordSize; | |
132 *total_frame_words = frame_words; | |
133 | |
134 assert(FPUStateSizeInWords == 27, "update stack layout"); | |
135 | |
136 // save registers, fpu state, and flags | |
137 // We assume caller has already has return address slot on the stack | |
138 // We push epb twice in this sequence because we want the real rbp, | |
304 | 139 // to be under the return like a normal enter and we want to use pusha |
0 | 140 // We push by hand instead of pusing push |
141 __ enter(); | |
304 | 142 __ pusha(); |
143 __ pushf(); | |
144 __ subptr(rsp,FPU_regs_live*sizeof(jdouble)); // Push FPU registers space | |
0 | 145 __ push_FPU_state(); // Save FPU state & init |
146 | |
147 if (verify_fpu) { | |
148 // Some stubs may have non standard FPU control word settings so | |
149 // only check and reset the value when it required to be the | |
150 // standard value. The safepoint blob in particular can be used | |
151 // in methods which are using the 24 bit control word for | |
152 // optimized float math. | |
153 | |
154 #ifdef ASSERT | |
155 // Make sure the control word has the expected value | |
156 Label ok; | |
157 __ cmpw(Address(rsp, 0), StubRoutines::fpu_cntrl_wrd_std()); | |
158 __ jccb(Assembler::equal, ok); | |
159 __ stop("corrupted control word detected"); | |
160 __ bind(ok); | |
161 #endif | |
162 | |
163 // Reset the control word to guard against exceptions being unmasked | |
164 // since fstp_d can cause FPU stack underflow exceptions. Write it | |
165 // into the on stack copy and then reload that to make sure that the | |
166 // current and future values are correct. | |
167 __ movw(Address(rsp, 0), StubRoutines::fpu_cntrl_wrd_std()); | |
168 } | |
169 | |
170 __ frstor(Address(rsp, 0)); | |
171 if (!verify_fpu) { | |
172 // Set the control word so that exceptions are masked for the | |
173 // following code. | |
174 __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); | |
175 } | |
176 | |
177 // Save the FPU registers in de-opt-able form | |
178 | |
179 __ fstp_d(Address(rsp, st0_off*wordSize)); // st(0) | |
180 __ fstp_d(Address(rsp, st1_off*wordSize)); // st(1) | |
181 __ fstp_d(Address(rsp, st2_off*wordSize)); // st(2) | |
182 __ fstp_d(Address(rsp, st3_off*wordSize)); // st(3) | |
183 __ fstp_d(Address(rsp, st4_off*wordSize)); // st(4) | |
184 __ fstp_d(Address(rsp, st5_off*wordSize)); // st(5) | |
185 __ fstp_d(Address(rsp, st6_off*wordSize)); // st(6) | |
186 __ fstp_d(Address(rsp, st7_off*wordSize)); // st(7) | |
187 | |
188 if( UseSSE == 1 ) { // Save the XMM state | |
189 __ movflt(Address(rsp,xmm0_off*wordSize),xmm0); | |
190 __ movflt(Address(rsp,xmm1_off*wordSize),xmm1); | |
191 __ movflt(Address(rsp,xmm2_off*wordSize),xmm2); | |
192 __ movflt(Address(rsp,xmm3_off*wordSize),xmm3); | |
193 __ movflt(Address(rsp,xmm4_off*wordSize),xmm4); | |
194 __ movflt(Address(rsp,xmm5_off*wordSize),xmm5); | |
195 __ movflt(Address(rsp,xmm6_off*wordSize),xmm6); | |
196 __ movflt(Address(rsp,xmm7_off*wordSize),xmm7); | |
197 } else if( UseSSE >= 2 ) { | |
198 __ movdbl(Address(rsp,xmm0_off*wordSize),xmm0); | |
199 __ movdbl(Address(rsp,xmm1_off*wordSize),xmm1); | |
200 __ movdbl(Address(rsp,xmm2_off*wordSize),xmm2); | |
201 __ movdbl(Address(rsp,xmm3_off*wordSize),xmm3); | |
202 __ movdbl(Address(rsp,xmm4_off*wordSize),xmm4); | |
203 __ movdbl(Address(rsp,xmm5_off*wordSize),xmm5); | |
204 __ movdbl(Address(rsp,xmm6_off*wordSize),xmm6); | |
205 __ movdbl(Address(rsp,xmm7_off*wordSize),xmm7); | |
206 } | |
207 | |
208 // Set an oopmap for the call site. This oopmap will map all | |
209 // oop-registers and debug-info registers as callee-saved. This | |
210 // will allow deoptimization at this safepoint to find all possible | |
211 // debug-info recordings, as well as let GC find all oops. | |
212 | |
213 OopMapSet *oop_maps = new OopMapSet(); | |
214 OopMap* map = new OopMap( frame_words, 0 ); | |
215 | |
216 #define STACK_OFFSET(x) VMRegImpl::stack2reg((x) + additional_frame_words) | |
217 | |
218 map->set_callee_saved(STACK_OFFSET( rax_off), rax->as_VMReg()); | |
219 map->set_callee_saved(STACK_OFFSET( rcx_off), rcx->as_VMReg()); | |
220 map->set_callee_saved(STACK_OFFSET( rdx_off), rdx->as_VMReg()); | |
221 map->set_callee_saved(STACK_OFFSET( rbx_off), rbx->as_VMReg()); | |
222 // rbp, location is known implicitly, no oopMap | |
223 map->set_callee_saved(STACK_OFFSET( rsi_off), rsi->as_VMReg()); | |
224 map->set_callee_saved(STACK_OFFSET( rdi_off), rdi->as_VMReg()); | |
225 map->set_callee_saved(STACK_OFFSET(st0_off), as_FloatRegister(0)->as_VMReg()); | |
226 map->set_callee_saved(STACK_OFFSET(st1_off), as_FloatRegister(1)->as_VMReg()); | |
227 map->set_callee_saved(STACK_OFFSET(st2_off), as_FloatRegister(2)->as_VMReg()); | |
228 map->set_callee_saved(STACK_OFFSET(st3_off), as_FloatRegister(3)->as_VMReg()); | |
229 map->set_callee_saved(STACK_OFFSET(st4_off), as_FloatRegister(4)->as_VMReg()); | |
230 map->set_callee_saved(STACK_OFFSET(st5_off), as_FloatRegister(5)->as_VMReg()); | |
231 map->set_callee_saved(STACK_OFFSET(st6_off), as_FloatRegister(6)->as_VMReg()); | |
232 map->set_callee_saved(STACK_OFFSET(st7_off), as_FloatRegister(7)->as_VMReg()); | |
233 map->set_callee_saved(STACK_OFFSET(xmm0_off), xmm0->as_VMReg()); | |
234 map->set_callee_saved(STACK_OFFSET(xmm1_off), xmm1->as_VMReg()); | |
235 map->set_callee_saved(STACK_OFFSET(xmm2_off), xmm2->as_VMReg()); | |
236 map->set_callee_saved(STACK_OFFSET(xmm3_off), xmm3->as_VMReg()); | |
237 map->set_callee_saved(STACK_OFFSET(xmm4_off), xmm4->as_VMReg()); | |
238 map->set_callee_saved(STACK_OFFSET(xmm5_off), xmm5->as_VMReg()); | |
239 map->set_callee_saved(STACK_OFFSET(xmm6_off), xmm6->as_VMReg()); | |
240 map->set_callee_saved(STACK_OFFSET(xmm7_off), xmm7->as_VMReg()); | |
241 // %%% This is really a waste but we'll keep things as they were for now | |
242 if (true) { | |
243 #define NEXTREG(x) (x)->as_VMReg()->next() | |
244 map->set_callee_saved(STACK_OFFSET(st0H_off), NEXTREG(as_FloatRegister(0))); | |
245 map->set_callee_saved(STACK_OFFSET(st1H_off), NEXTREG(as_FloatRegister(1))); | |
246 map->set_callee_saved(STACK_OFFSET(st2H_off), NEXTREG(as_FloatRegister(2))); | |
247 map->set_callee_saved(STACK_OFFSET(st3H_off), NEXTREG(as_FloatRegister(3))); | |
248 map->set_callee_saved(STACK_OFFSET(st4H_off), NEXTREG(as_FloatRegister(4))); | |
249 map->set_callee_saved(STACK_OFFSET(st5H_off), NEXTREG(as_FloatRegister(5))); | |
250 map->set_callee_saved(STACK_OFFSET(st6H_off), NEXTREG(as_FloatRegister(6))); | |
251 map->set_callee_saved(STACK_OFFSET(st7H_off), NEXTREG(as_FloatRegister(7))); | |
252 map->set_callee_saved(STACK_OFFSET(xmm0H_off), NEXTREG(xmm0)); | |
253 map->set_callee_saved(STACK_OFFSET(xmm1H_off), NEXTREG(xmm1)); | |
254 map->set_callee_saved(STACK_OFFSET(xmm2H_off), NEXTREG(xmm2)); | |
255 map->set_callee_saved(STACK_OFFSET(xmm3H_off), NEXTREG(xmm3)); | |
256 map->set_callee_saved(STACK_OFFSET(xmm4H_off), NEXTREG(xmm4)); | |
257 map->set_callee_saved(STACK_OFFSET(xmm5H_off), NEXTREG(xmm5)); | |
258 map->set_callee_saved(STACK_OFFSET(xmm6H_off), NEXTREG(xmm6)); | |
259 map->set_callee_saved(STACK_OFFSET(xmm7H_off), NEXTREG(xmm7)); | |
260 #undef NEXTREG | |
261 #undef STACK_OFFSET | |
262 } | |
263 | |
264 return map; | |
265 | |
266 } | |
267 | |
268 void RegisterSaver::restore_live_registers(MacroAssembler* masm) { | |
269 | |
270 // Recover XMM & FPU state | |
271 if( UseSSE == 1 ) { | |
272 __ movflt(xmm0,Address(rsp,xmm0_off*wordSize)); | |
273 __ movflt(xmm1,Address(rsp,xmm1_off*wordSize)); | |
274 __ movflt(xmm2,Address(rsp,xmm2_off*wordSize)); | |
275 __ movflt(xmm3,Address(rsp,xmm3_off*wordSize)); | |
276 __ movflt(xmm4,Address(rsp,xmm4_off*wordSize)); | |
277 __ movflt(xmm5,Address(rsp,xmm5_off*wordSize)); | |
278 __ movflt(xmm6,Address(rsp,xmm6_off*wordSize)); | |
279 __ movflt(xmm7,Address(rsp,xmm7_off*wordSize)); | |
280 } else if( UseSSE >= 2 ) { | |
281 __ movdbl(xmm0,Address(rsp,xmm0_off*wordSize)); | |
282 __ movdbl(xmm1,Address(rsp,xmm1_off*wordSize)); | |
283 __ movdbl(xmm2,Address(rsp,xmm2_off*wordSize)); | |
284 __ movdbl(xmm3,Address(rsp,xmm3_off*wordSize)); | |
285 __ movdbl(xmm4,Address(rsp,xmm4_off*wordSize)); | |
286 __ movdbl(xmm5,Address(rsp,xmm5_off*wordSize)); | |
287 __ movdbl(xmm6,Address(rsp,xmm6_off*wordSize)); | |
288 __ movdbl(xmm7,Address(rsp,xmm7_off*wordSize)); | |
289 } | |
290 __ pop_FPU_state(); | |
304 | 291 __ addptr(rsp, FPU_regs_live*sizeof(jdouble)); // Pop FPU registers |
292 | |
293 __ popf(); | |
294 __ popa(); | |
0 | 295 // Get the rbp, described implicitly by the frame sender code (no oopMap) |
304 | 296 __ pop(rbp); |
0 | 297 |
298 } | |
299 | |
300 void RegisterSaver::restore_result_registers(MacroAssembler* masm) { | |
301 | |
302 // Just restore result register. Only used by deoptimization. By | |
303 // now any callee save register that needs to be restore to a c2 | |
304 // caller of the deoptee has been extracted into the vframeArray | |
305 // and will be stuffed into the c2i adapter we create for later | |
306 // restoration so only result registers need to be restored here. | |
307 // | |
308 | |
309 __ frstor(Address(rsp, 0)); // Restore fpu state | |
310 | |
311 // Recover XMM & FPU state | |
312 if( UseSSE == 1 ) { | |
313 __ movflt(xmm0, Address(rsp, xmm0_off*wordSize)); | |
314 } else if( UseSSE >= 2 ) { | |
315 __ movdbl(xmm0, Address(rsp, xmm0_off*wordSize)); | |
316 } | |
304 | 317 __ movptr(rax, Address(rsp, rax_off*wordSize)); |
318 __ movptr(rdx, Address(rsp, rdx_off*wordSize)); | |
0 | 319 // Pop all of the register save are off the stack except the return address |
304 | 320 __ addptr(rsp, return_off * wordSize); |
0 | 321 } |
322 | |
323 // The java_calling_convention describes stack locations as ideal slots on | |
324 // a frame with no abi restrictions. Since we must observe abi restrictions | |
325 // (like the placement of the register window) the slots must be biased by | |
326 // the following value. | |
327 static int reg2offset_in(VMReg r) { | |
328 // Account for saved rbp, and return address | |
329 // This should really be in_preserve_stack_slots | |
330 return (r->reg2stack() + 2) * VMRegImpl::stack_slot_size; | |
331 } | |
332 | |
333 static int reg2offset_out(VMReg r) { | |
334 return (r->reg2stack() + SharedRuntime::out_preserve_stack_slots()) * VMRegImpl::stack_slot_size; | |
335 } | |
336 | |
337 // --------------------------------------------------------------------------- | |
338 // Read the array of BasicTypes from a signature, and compute where the | |
339 // arguments should go. Values in the VMRegPair regs array refer to 4-byte | |
340 // quantities. Values less than SharedInfo::stack0 are registers, those above | |
341 // refer to 4-byte stack slots. All stack slots are based off of the stack pointer | |
342 // as framesizes are fixed. | |
343 // VMRegImpl::stack0 refers to the first slot 0(sp). | |
344 // and VMRegImpl::stack0+1 refers to the memory word 4-byes higher. Register | |
345 // up to RegisterImpl::number_of_registers) are the 32-bit | |
346 // integer registers. | |
347 | |
348 // Pass first two oop/int args in registers ECX and EDX. | |
349 // Pass first two float/double args in registers XMM0 and XMM1. | |
350 // Doubles have precedence, so if you pass a mix of floats and doubles | |
351 // the doubles will grab the registers before the floats will. | |
352 | |
353 // Note: the INPUTS in sig_bt are in units of Java argument words, which are | |
354 // either 32-bit or 64-bit depending on the build. The OUTPUTS are in 32-bit | |
355 // units regardless of build. Of course for i486 there is no 64 bit build | |
356 | |
357 | |
358 // --------------------------------------------------------------------------- | |
359 // The compiled Java calling convention. | |
360 // Pass first two oop/int args in registers ECX and EDX. | |
361 // Pass first two float/double args in registers XMM0 and XMM1. | |
362 // Doubles have precedence, so if you pass a mix of floats and doubles | |
363 // the doubles will grab the registers before the floats will. | |
364 int SharedRuntime::java_calling_convention(const BasicType *sig_bt, | |
365 VMRegPair *regs, | |
366 int total_args_passed, | |
367 int is_outgoing) { | |
368 uint stack = 0; // Starting stack position for args on stack | |
369 | |
370 | |
371 // Pass first two oop/int args in registers ECX and EDX. | |
372 uint reg_arg0 = 9999; | |
373 uint reg_arg1 = 9999; | |
374 | |
375 // Pass first two float/double args in registers XMM0 and XMM1. | |
376 // Doubles have precedence, so if you pass a mix of floats and doubles | |
377 // the doubles will grab the registers before the floats will. | |
378 // CNC - TURNED OFF FOR non-SSE. | |
379 // On Intel we have to round all doubles (and most floats) at | |
380 // call sites by storing to the stack in any case. | |
381 // UseSSE=0 ==> Don't Use ==> 9999+0 | |
382 // UseSSE=1 ==> Floats only ==> 9999+1 | |
383 // UseSSE>=2 ==> Floats or doubles ==> 9999+2 | |
384 enum { fltarg_dontuse = 9999+0, fltarg_float_only = 9999+1, fltarg_flt_dbl = 9999+2 }; | |
385 uint fargs = (UseSSE>=2) ? 2 : UseSSE; | |
386 uint freg_arg0 = 9999+fargs; | |
387 uint freg_arg1 = 9999+fargs; | |
388 | |
389 // Pass doubles & longs aligned on the stack. First count stack slots for doubles | |
390 int i; | |
391 for( i = 0; i < total_args_passed; i++) { | |
392 if( sig_bt[i] == T_DOUBLE ) { | |
393 // first 2 doubles go in registers | |
394 if( freg_arg0 == fltarg_flt_dbl ) freg_arg0 = i; | |
395 else if( freg_arg1 == fltarg_flt_dbl ) freg_arg1 = i; | |
396 else // Else double is passed low on the stack to be aligned. | |
397 stack += 2; | |
398 } else if( sig_bt[i] == T_LONG ) { | |
399 stack += 2; | |
400 } | |
401 } | |
402 int dstack = 0; // Separate counter for placing doubles | |
403 | |
404 // Now pick where all else goes. | |
405 for( i = 0; i < total_args_passed; i++) { | |
406 // From the type and the argument number (count) compute the location | |
407 switch( sig_bt[i] ) { | |
408 case T_SHORT: | |
409 case T_CHAR: | |
410 case T_BYTE: | |
411 case T_BOOLEAN: | |
412 case T_INT: | |
413 case T_ARRAY: | |
414 case T_OBJECT: | |
415 case T_ADDRESS: | |
416 if( reg_arg0 == 9999 ) { | |
417 reg_arg0 = i; | |
418 regs[i].set1(rcx->as_VMReg()); | |
419 } else if( reg_arg1 == 9999 ) { | |
420 reg_arg1 = i; | |
421 regs[i].set1(rdx->as_VMReg()); | |
422 } else { | |
423 regs[i].set1(VMRegImpl::stack2reg(stack++)); | |
424 } | |
425 break; | |
426 case T_FLOAT: | |
427 if( freg_arg0 == fltarg_flt_dbl || freg_arg0 == fltarg_float_only ) { | |
428 freg_arg0 = i; | |
429 regs[i].set1(xmm0->as_VMReg()); | |
430 } else if( freg_arg1 == fltarg_flt_dbl || freg_arg1 == fltarg_float_only ) { | |
431 freg_arg1 = i; | |
432 regs[i].set1(xmm1->as_VMReg()); | |
433 } else { | |
434 regs[i].set1(VMRegImpl::stack2reg(stack++)); | |
435 } | |
436 break; | |
437 case T_LONG: | |
438 assert(sig_bt[i+1] == T_VOID, "missing Half" ); | |
439 regs[i].set2(VMRegImpl::stack2reg(dstack)); | |
440 dstack += 2; | |
441 break; | |
442 case T_DOUBLE: | |
443 assert(sig_bt[i+1] == T_VOID, "missing Half" ); | |
444 if( freg_arg0 == (uint)i ) { | |
445 regs[i].set2(xmm0->as_VMReg()); | |
446 } else if( freg_arg1 == (uint)i ) { | |
447 regs[i].set2(xmm1->as_VMReg()); | |
448 } else { | |
449 regs[i].set2(VMRegImpl::stack2reg(dstack)); | |
450 dstack += 2; | |
451 } | |
452 break; | |
453 case T_VOID: regs[i].set_bad(); break; | |
454 break; | |
455 default: | |
456 ShouldNotReachHere(); | |
457 break; | |
458 } | |
459 } | |
460 | |
461 // return value can be odd number of VMRegImpl stack slots make multiple of 2 | |
462 return round_to(stack, 2); | |
463 } | |
464 | |
465 // Patch the callers callsite with entry to compiled code if it exists. | |
466 static void patch_callers_callsite(MacroAssembler *masm) { | |
467 Label L; | |
468 __ verify_oop(rbx); | |
304 | 469 __ cmpptr(Address(rbx, in_bytes(methodOopDesc::code_offset())), (int32_t)NULL_WORD); |
0 | 470 __ jcc(Assembler::equal, L); |
471 // Schedule the branch target address early. | |
472 // Call into the VM to patch the caller, then jump to compiled callee | |
473 // rax, isn't live so capture return address while we easily can | |
304 | 474 __ movptr(rax, Address(rsp, 0)); |
475 __ pusha(); | |
476 __ pushf(); | |
0 | 477 |
478 if (UseSSE == 1) { | |
304 | 479 __ subptr(rsp, 2*wordSize); |
0 | 480 __ movflt(Address(rsp, 0), xmm0); |
481 __ movflt(Address(rsp, wordSize), xmm1); | |
482 } | |
483 if (UseSSE >= 2) { | |
304 | 484 __ subptr(rsp, 4*wordSize); |
0 | 485 __ movdbl(Address(rsp, 0), xmm0); |
486 __ movdbl(Address(rsp, 2*wordSize), xmm1); | |
487 } | |
488 #ifdef COMPILER2 | |
489 // C2 may leave the stack dirty if not in SSE2+ mode | |
490 if (UseSSE >= 2) { | |
491 __ verify_FPU(0, "c2i transition should have clean FPU stack"); | |
492 } else { | |
493 __ empty_FPU_stack(); | |
494 } | |
495 #endif /* COMPILER2 */ | |
496 | |
497 // VM needs caller's callsite | |
304 | 498 __ push(rax); |
0 | 499 // VM needs target method |
304 | 500 __ push(rbx); |
0 | 501 __ verify_oop(rbx); |
502 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::fixup_callers_callsite))); | |
304 | 503 __ addptr(rsp, 2*wordSize); |
0 | 504 |
505 if (UseSSE == 1) { | |
506 __ movflt(xmm0, Address(rsp, 0)); | |
507 __ movflt(xmm1, Address(rsp, wordSize)); | |
304 | 508 __ addptr(rsp, 2*wordSize); |
0 | 509 } |
510 if (UseSSE >= 2) { | |
511 __ movdbl(xmm0, Address(rsp, 0)); | |
512 __ movdbl(xmm1, Address(rsp, 2*wordSize)); | |
304 | 513 __ addptr(rsp, 4*wordSize); |
0 | 514 } |
515 | |
304 | 516 __ popf(); |
517 __ popa(); | |
0 | 518 __ bind(L); |
519 } | |
520 | |
521 | |
522 static void move_c2i_double(MacroAssembler *masm, XMMRegister r, int st_off) { | |
1506 | 523 int next_off = st_off - Interpreter::stackElementSize; |
524 __ movdbl(Address(rsp, next_off), r); | |
0 | 525 } |
526 | |
527 static void gen_c2i_adapter(MacroAssembler *masm, | |
528 int total_args_passed, | |
529 int comp_args_on_stack, | |
530 const BasicType *sig_bt, | |
531 const VMRegPair *regs, | |
532 Label& skip_fixup) { | |
533 // Before we get into the guts of the C2I adapter, see if we should be here | |
534 // at all. We've come from compiled code and are attempting to jump to the | |
535 // interpreter, which means the caller made a static call to get here | |
536 // (vcalls always get a compiled target if there is one). Check for a | |
537 // compiled target. If there is one, we need to patch the caller's call. | |
538 patch_callers_callsite(masm); | |
539 | |
540 __ bind(skip_fixup); | |
541 | |
542 #ifdef COMPILER2 | |
543 // C2 may leave the stack dirty if not in SSE2+ mode | |
544 if (UseSSE >= 2) { | |
545 __ verify_FPU(0, "c2i transition should have clean FPU stack"); | |
546 } else { | |
547 __ empty_FPU_stack(); | |
548 } | |
549 #endif /* COMPILER2 */ | |
550 | |
551 // Since all args are passed on the stack, total_args_passed * interpreter_ | |
552 // stack_element_size is the | |
553 // space we need. | |
1506 | 554 int extraspace = total_args_passed * Interpreter::stackElementSize; |
0 | 555 |
556 // Get return address | |
304 | 557 __ pop(rax); |
0 | 558 |
559 // set senderSP value | |
304 | 560 __ movptr(rsi, rsp); |
561 | |
562 __ subptr(rsp, extraspace); | |
0 | 563 |
564 // Now write the args into the outgoing interpreter space | |
565 for (int i = 0; i < total_args_passed; i++) { | |
566 if (sig_bt[i] == T_VOID) { | |
567 assert(i > 0 && (sig_bt[i-1] == T_LONG || sig_bt[i-1] == T_DOUBLE), "missing half"); | |
568 continue; | |
569 } | |
570 | |
571 // st_off points to lowest address on stack. | |
1506 | 572 int st_off = ((total_args_passed - 1) - i) * Interpreter::stackElementSize; |
573 int next_off = st_off - Interpreter::stackElementSize; | |
304 | 574 |
0 | 575 // Say 4 args: |
576 // i st_off | |
577 // 0 12 T_LONG | |
578 // 1 8 T_VOID | |
579 // 2 4 T_OBJECT | |
580 // 3 0 T_BOOL | |
581 VMReg r_1 = regs[i].first(); | |
582 VMReg r_2 = regs[i].second(); | |
583 if (!r_1->is_valid()) { | |
584 assert(!r_2->is_valid(), ""); | |
585 continue; | |
586 } | |
587 | |
588 if (r_1->is_stack()) { | |
589 // memory to memory use fpu stack top | |
590 int ld_off = r_1->reg2stack() * VMRegImpl::stack_slot_size + extraspace; | |
591 | |
592 if (!r_2->is_valid()) { | |
593 __ movl(rdi, Address(rsp, ld_off)); | |
304 | 594 __ movptr(Address(rsp, st_off), rdi); |
0 | 595 } else { |
596 | |
597 // ld_off == LSW, ld_off+VMRegImpl::stack_slot_size == MSW | |
598 // st_off == MSW, st_off-wordSize == LSW | |
599 | |
304 | 600 __ movptr(rdi, Address(rsp, ld_off)); |
601 __ movptr(Address(rsp, next_off), rdi); | |
602 #ifndef _LP64 | |
603 __ movptr(rdi, Address(rsp, ld_off + wordSize)); | |
604 __ movptr(Address(rsp, st_off), rdi); | |
605 #else | |
606 #ifdef ASSERT | |
607 // Overwrite the unused slot with known junk | |
608 __ mov64(rax, CONST64(0xdeadffffdeadaaaa)); | |
609 __ movptr(Address(rsp, st_off), rax); | |
610 #endif /* ASSERT */ | |
611 #endif // _LP64 | |
0 | 612 } |
613 } else if (r_1->is_Register()) { | |
614 Register r = r_1->as_Register(); | |
615 if (!r_2->is_valid()) { | |
616 __ movl(Address(rsp, st_off), r); | |
617 } else { | |
618 // long/double in gpr | |
304 | 619 NOT_LP64(ShouldNotReachHere()); |
620 // Two VMRegs can be T_OBJECT, T_ADDRESS, T_DOUBLE, T_LONG | |
621 // T_DOUBLE and T_LONG use two slots in the interpreter | |
622 if ( sig_bt[i] == T_LONG || sig_bt[i] == T_DOUBLE) { | |
623 // long/double in gpr | |
624 #ifdef ASSERT | |
625 // Overwrite the unused slot with known junk | |
626 LP64_ONLY(__ mov64(rax, CONST64(0xdeadffffdeadaaab))); | |
627 __ movptr(Address(rsp, st_off), rax); | |
628 #endif /* ASSERT */ | |
629 __ movptr(Address(rsp, next_off), r); | |
630 } else { | |
631 __ movptr(Address(rsp, st_off), r); | |
632 } | |
0 | 633 } |
634 } else { | |
635 assert(r_1->is_XMMRegister(), ""); | |
636 if (!r_2->is_valid()) { | |
637 __ movflt(Address(rsp, st_off), r_1->as_XMMRegister()); | |
638 } else { | |
639 assert(sig_bt[i] == T_DOUBLE || sig_bt[i] == T_LONG, "wrong type"); | |
640 move_c2i_double(masm, r_1->as_XMMRegister(), st_off); | |
641 } | |
642 } | |
643 } | |
644 | |
645 // Schedule the branch target address early. | |
304 | 646 __ movptr(rcx, Address(rbx, in_bytes(methodOopDesc::interpreter_entry_offset()))); |
0 | 647 // And repush original return address |
304 | 648 __ push(rax); |
0 | 649 __ jmp(rcx); |
650 } | |
651 | |
652 | |
653 static void move_i2c_double(MacroAssembler *masm, XMMRegister r, Register saved_sp, int ld_off) { | |
1506 | 654 int next_val_off = ld_off - Interpreter::stackElementSize; |
655 __ movdbl(r, Address(saved_sp, next_val_off)); | |
0 | 656 } |
657 | |
658 static void gen_i2c_adapter(MacroAssembler *masm, | |
659 int total_args_passed, | |
660 int comp_args_on_stack, | |
661 const BasicType *sig_bt, | |
662 const VMRegPair *regs) { | |
663 | |
664 // Note: rsi contains the senderSP on entry. We must preserve it since | |
665 // we may do a i2c -> c2i transition if we lose a race where compiled | |
666 // code goes non-entrant while we get args ready. | |
667 | |
668 // Pick up the return address | |
304 | 669 __ movptr(rax, Address(rsp, 0)); |
0 | 670 |
671 // Must preserve original SP for loading incoming arguments because | |
672 // we need to align the outgoing SP for compiled code. | |
304 | 673 __ movptr(rdi, rsp); |
0 | 674 |
675 // Cut-out for having no stack args. Since up to 2 int/oop args are passed | |
676 // in registers, we will occasionally have no stack args. | |
677 int comp_words_on_stack = 0; | |
678 if (comp_args_on_stack) { | |
679 // Sig words on the stack are greater-than VMRegImpl::stack0. Those in | |
680 // registers are below. By subtracting stack0, we either get a negative | |
681 // number (all values in registers) or the maximum stack slot accessed. | |
682 // int comp_args_on_stack = VMRegImpl::reg2stack(max_arg); | |
683 // Convert 4-byte stack slots to words. | |
684 comp_words_on_stack = round_to(comp_args_on_stack*4, wordSize)>>LogBytesPerWord; | |
685 // Round up to miminum stack alignment, in wordSize | |
686 comp_words_on_stack = round_to(comp_words_on_stack, 2); | |
304 | 687 __ subptr(rsp, comp_words_on_stack * wordSize); |
0 | 688 } |
689 | |
690 // Align the outgoing SP | |
304 | 691 __ andptr(rsp, -(StackAlignmentInBytes)); |
0 | 692 |
693 // push the return address on the stack (note that pushing, rather | |
694 // than storing it, yields the correct frame alignment for the callee) | |
304 | 695 __ push(rax); |
0 | 696 |
697 // Put saved SP in another register | |
698 const Register saved_sp = rax; | |
304 | 699 __ movptr(saved_sp, rdi); |
0 | 700 |
701 | |
702 // Will jump to the compiled code just as if compiled code was doing it. | |
703 // Pre-load the register-jump target early, to schedule it better. | |
304 | 704 __ movptr(rdi, Address(rbx, in_bytes(methodOopDesc::from_compiled_offset()))); |
0 | 705 |
706 // Now generate the shuffle code. Pick up all register args and move the | |
707 // rest through the floating point stack top. | |
708 for (int i = 0; i < total_args_passed; i++) { | |
709 if (sig_bt[i] == T_VOID) { | |
710 // Longs and doubles are passed in native word order, but misaligned | |
711 // in the 32-bit build. | |
712 assert(i > 0 && (sig_bt[i-1] == T_LONG || sig_bt[i-1] == T_DOUBLE), "missing half"); | |
713 continue; | |
714 } | |
715 | |
716 // Pick up 0, 1 or 2 words from SP+offset. | |
717 | |
718 assert(!regs[i].second()->is_valid() || regs[i].first()->next() == regs[i].second(), | |
719 "scrambled load targets?"); | |
720 // Load in argument order going down. | |
1506 | 721 int ld_off = (total_args_passed - i) * Interpreter::stackElementSize; |
0 | 722 // Point to interpreter value (vs. tag) |
1506 | 723 int next_off = ld_off - Interpreter::stackElementSize; |
0 | 724 // |
725 // | |
726 // | |
727 VMReg r_1 = regs[i].first(); | |
728 VMReg r_2 = regs[i].second(); | |
729 if (!r_1->is_valid()) { | |
730 assert(!r_2->is_valid(), ""); | |
731 continue; | |
732 } | |
733 if (r_1->is_stack()) { | |
734 // Convert stack slot to an SP offset (+ wordSize to account for return address ) | |
735 int st_off = regs[i].first()->reg2stack()*VMRegImpl::stack_slot_size + wordSize; | |
736 | |
737 // We can use rsi as a temp here because compiled code doesn't need rsi as an input | |
738 // and if we end up going thru a c2i because of a miss a reasonable value of rsi | |
739 // we be generated. | |
740 if (!r_2->is_valid()) { | |
741 // __ fld_s(Address(saved_sp, ld_off)); | |
742 // __ fstp_s(Address(rsp, st_off)); | |
743 __ movl(rsi, Address(saved_sp, ld_off)); | |
304 | 744 __ movptr(Address(rsp, st_off), rsi); |
0 | 745 } else { |
746 // Interpreter local[n] == MSW, local[n+1] == LSW however locals | |
747 // are accessed as negative so LSW is at LOW address | |
748 | |
749 // ld_off is MSW so get LSW | |
750 // st_off is LSW (i.e. reg.first()) | |
751 // __ fld_d(Address(saved_sp, next_off)); | |
752 // __ fstp_d(Address(rsp, st_off)); | |
304 | 753 // |
754 // We are using two VMRegs. This can be either T_OBJECT, T_ADDRESS, T_LONG, or T_DOUBLE | |
755 // the interpreter allocates two slots but only uses one for thr T_LONG or T_DOUBLE case | |
756 // So we must adjust where to pick up the data to match the interpreter. | |
757 // | |
758 // Interpreter local[n] == MSW, local[n+1] == LSW however locals | |
759 // are accessed as negative so LSW is at LOW address | |
760 | |
761 // ld_off is MSW so get LSW | |
762 const int offset = (NOT_LP64(true ||) sig_bt[i]==T_LONG||sig_bt[i]==T_DOUBLE)? | |
763 next_off : ld_off; | |
764 __ movptr(rsi, Address(saved_sp, offset)); | |
765 __ movptr(Address(rsp, st_off), rsi); | |
766 #ifndef _LP64 | |
767 __ movptr(rsi, Address(saved_sp, ld_off)); | |
768 __ movptr(Address(rsp, st_off + wordSize), rsi); | |
769 #endif // _LP64 | |
0 | 770 } |
771 } else if (r_1->is_Register()) { // Register argument | |
772 Register r = r_1->as_Register(); | |
773 assert(r != rax, "must be different"); | |
774 if (r_2->is_valid()) { | |
304 | 775 // |
776 // We are using two VMRegs. This can be either T_OBJECT, T_ADDRESS, T_LONG, or T_DOUBLE | |
777 // the interpreter allocates two slots but only uses one for thr T_LONG or T_DOUBLE case | |
778 // So we must adjust where to pick up the data to match the interpreter. | |
779 | |
780 const int offset = (NOT_LP64(true ||) sig_bt[i]==T_LONG||sig_bt[i]==T_DOUBLE)? | |
781 next_off : ld_off; | |
782 | |
783 // this can be a misaligned move | |
784 __ movptr(r, Address(saved_sp, offset)); | |
785 #ifndef _LP64 | |
0 | 786 assert(r_2->as_Register() != rax, "need another temporary register"); |
787 // Remember r_1 is low address (and LSB on x86) | |
788 // So r_2 gets loaded from high address regardless of the platform | |
304 | 789 __ movptr(r_2->as_Register(), Address(saved_sp, ld_off)); |
790 #endif // _LP64 | |
0 | 791 } else { |
792 __ movl(r, Address(saved_sp, ld_off)); | |
793 } | |
794 } else { | |
795 assert(r_1->is_XMMRegister(), ""); | |
796 if (!r_2->is_valid()) { | |
797 __ movflt(r_1->as_XMMRegister(), Address(saved_sp, ld_off)); | |
798 } else { | |
799 move_i2c_double(masm, r_1->as_XMMRegister(), saved_sp, ld_off); | |
800 } | |
801 } | |
802 } | |
803 | |
804 // 6243940 We might end up in handle_wrong_method if | |
805 // the callee is deoptimized as we race thru here. If that | |
806 // happens we don't want to take a safepoint because the | |
807 // caller frame will look interpreted and arguments are now | |
808 // "compiled" so it is much better to make this transition | |
809 // invisible to the stack walking code. Unfortunately if | |
810 // we try and find the callee by normal means a safepoint | |
811 // is possible. So we stash the desired callee in the thread | |
812 // and the vm will find there should this case occur. | |
813 | |
814 __ get_thread(rax); | |
304 | 815 __ movptr(Address(rax, JavaThread::callee_target_offset()), rbx); |
0 | 816 |
817 // move methodOop to rax, in case we end up in an c2i adapter. | |
818 // the c2i adapters expect methodOop in rax, (c2) because c2's | |
819 // resolve stubs return the result (the method) in rax,. | |
820 // I'd love to fix this. | |
304 | 821 __ mov(rax, rbx); |
0 | 822 |
823 __ jmp(rdi); | |
824 } | |
825 | |
826 // --------------------------------------------------------------- | |
827 AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm, | |
828 int total_args_passed, | |
829 int comp_args_on_stack, | |
830 const BasicType *sig_bt, | |
1187
cf0685d550f1
6911204: generated adapters with large signatures can fill up the code cache
never
parents:
926
diff
changeset
|
831 const VMRegPair *regs, |
cf0685d550f1
6911204: generated adapters with large signatures can fill up the code cache
never
parents:
926
diff
changeset
|
832 AdapterFingerPrint* fingerprint) { |
0 | 833 address i2c_entry = __ pc(); |
834 | |
835 gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs); | |
836 | |
837 // ------------------------------------------------------------------------- | |
838 // Generate a C2I adapter. On entry we know rbx, holds the methodOop during calls | |
839 // to the interpreter. The args start out packed in the compiled layout. They | |
840 // need to be unpacked into the interpreter layout. This will almost always | |
841 // require some stack space. We grow the current (compiled) stack, then repack | |
842 // the args. We finally end in a jump to the generic interpreter entry point. | |
843 // On exit from the interpreter, the interpreter will restore our SP (lest the | |
844 // compiled code, which relys solely on SP and not EBP, get sick). | |
845 | |
846 address c2i_unverified_entry = __ pc(); | |
847 Label skip_fixup; | |
848 | |
849 Register holder = rax; | |
850 Register receiver = rcx; | |
851 Register temp = rbx; | |
852 | |
853 { | |
854 | |
855 Label missed; | |
856 | |
857 __ verify_oop(holder); | |
304 | 858 __ movptr(temp, Address(receiver, oopDesc::klass_offset_in_bytes())); |
0 | 859 __ verify_oop(temp); |
860 | |
304 | 861 __ cmpptr(temp, Address(holder, compiledICHolderOopDesc::holder_klass_offset())); |
862 __ movptr(rbx, Address(holder, compiledICHolderOopDesc::holder_method_offset())); | |
0 | 863 __ jcc(Assembler::notEqual, missed); |
864 // Method might have been compiled since the call site was patched to | |
865 // interpreted if that is the case treat it as a miss so we can get | |
866 // the call site corrected. | |
304 | 867 __ cmpptr(Address(rbx, in_bytes(methodOopDesc::code_offset())), (int32_t)NULL_WORD); |
0 | 868 __ jcc(Assembler::equal, skip_fixup); |
869 | |
870 __ bind(missed); | |
871 __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); | |
872 } | |
873 | |
874 address c2i_entry = __ pc(); | |
875 | |
876 gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup); | |
877 | |
878 __ flush(); | |
1187
cf0685d550f1
6911204: generated adapters with large signatures can fill up the code cache
never
parents:
926
diff
changeset
|
879 return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry); |
0 | 880 } |
881 | |
882 int SharedRuntime::c_calling_convention(const BasicType *sig_bt, | |
883 VMRegPair *regs, | |
884 int total_args_passed) { | |
885 // We return the amount of VMRegImpl stack slots we need to reserve for all | |
886 // the arguments NOT counting out_preserve_stack_slots. | |
887 | |
888 uint stack = 0; // All arguments on stack | |
889 | |
890 for( int i = 0; i < total_args_passed; i++) { | |
891 // From the type and the argument number (count) compute the location | |
892 switch( sig_bt[i] ) { | |
893 case T_BOOLEAN: | |
894 case T_CHAR: | |
895 case T_FLOAT: | |
896 case T_BYTE: | |
897 case T_SHORT: | |
898 case T_INT: | |
899 case T_OBJECT: | |
900 case T_ARRAY: | |
901 case T_ADDRESS: | |
902 regs[i].set1(VMRegImpl::stack2reg(stack++)); | |
903 break; | |
904 case T_LONG: | |
905 case T_DOUBLE: // The stack numbering is reversed from Java | |
906 // Since C arguments do not get reversed, the ordering for | |
907 // doubles on the stack must be opposite the Java convention | |
908 assert(sig_bt[i+1] == T_VOID, "missing Half" ); | |
909 regs[i].set2(VMRegImpl::stack2reg(stack)); | |
910 stack += 2; | |
911 break; | |
912 case T_VOID: regs[i].set_bad(); break; | |
913 default: | |
914 ShouldNotReachHere(); | |
915 break; | |
916 } | |
917 } | |
918 return stack; | |
919 } | |
920 | |
921 // A simple move of integer like type | |
922 static void simple_move32(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { | |
923 if (src.first()->is_stack()) { | |
924 if (dst.first()->is_stack()) { | |
925 // stack to stack | |
926 // __ ld(FP, reg2offset(src.first()) + STACK_BIAS, L5); | |
927 // __ st(L5, SP, reg2offset(dst.first()) + STACK_BIAS); | |
304 | 928 __ movl2ptr(rax, Address(rbp, reg2offset_in(src.first()))); |
929 __ movptr(Address(rsp, reg2offset_out(dst.first())), rax); | |
0 | 930 } else { |
931 // stack to reg | |
304 | 932 __ movl2ptr(dst.first()->as_Register(), Address(rbp, reg2offset_in(src.first()))); |
0 | 933 } |
934 } else if (dst.first()->is_stack()) { | |
935 // reg to stack | |
304 | 936 // no need to sign extend on 64bit |
937 __ movptr(Address(rsp, reg2offset_out(dst.first())), src.first()->as_Register()); | |
0 | 938 } else { |
304 | 939 if (dst.first() != src.first()) { |
940 __ mov(dst.first()->as_Register(), src.first()->as_Register()); | |
941 } | |
0 | 942 } |
943 } | |
944 | |
945 // An oop arg. Must pass a handle not the oop itself | |
946 static void object_move(MacroAssembler* masm, | |
947 OopMap* map, | |
948 int oop_handle_offset, | |
949 int framesize_in_slots, | |
950 VMRegPair src, | |
951 VMRegPair dst, | |
952 bool is_receiver, | |
953 int* receiver_offset) { | |
954 | |
955 // Because of the calling conventions we know that src can be a | |
956 // register or a stack location. dst can only be a stack location. | |
957 | |
958 assert(dst.first()->is_stack(), "must be stack"); | |
959 // must pass a handle. First figure out the location we use as a handle | |
960 | |
961 if (src.first()->is_stack()) { | |
962 // Oop is already on the stack as an argument | |
963 Register rHandle = rax; | |
964 Label nil; | |
304 | 965 __ xorptr(rHandle, rHandle); |
966 __ cmpptr(Address(rbp, reg2offset_in(src.first())), (int32_t)NULL_WORD); | |
0 | 967 __ jcc(Assembler::equal, nil); |
304 | 968 __ lea(rHandle, Address(rbp, reg2offset_in(src.first()))); |
0 | 969 __ bind(nil); |
304 | 970 __ movptr(Address(rsp, reg2offset_out(dst.first())), rHandle); |
0 | 971 |
972 int offset_in_older_frame = src.first()->reg2stack() + SharedRuntime::out_preserve_stack_slots(); | |
973 map->set_oop(VMRegImpl::stack2reg(offset_in_older_frame + framesize_in_slots)); | |
974 if (is_receiver) { | |
975 *receiver_offset = (offset_in_older_frame + framesize_in_slots) * VMRegImpl::stack_slot_size; | |
976 } | |
977 } else { | |
978 // Oop is in an a register we must store it to the space we reserve | |
979 // on the stack for oop_handles | |
980 const Register rOop = src.first()->as_Register(); | |
981 const Register rHandle = rax; | |
982 int oop_slot = (rOop == rcx ? 0 : 1) * VMRegImpl::slots_per_word + oop_handle_offset; | |
983 int offset = oop_slot*VMRegImpl::stack_slot_size; | |
984 Label skip; | |
304 | 985 __ movptr(Address(rsp, offset), rOop); |
0 | 986 map->set_oop(VMRegImpl::stack2reg(oop_slot)); |
304 | 987 __ xorptr(rHandle, rHandle); |
988 __ cmpptr(rOop, (int32_t)NULL_WORD); | |
0 | 989 __ jcc(Assembler::equal, skip); |
304 | 990 __ lea(rHandle, Address(rsp, offset)); |
0 | 991 __ bind(skip); |
992 // Store the handle parameter | |
304 | 993 __ movptr(Address(rsp, reg2offset_out(dst.first())), rHandle); |
0 | 994 if (is_receiver) { |
995 *receiver_offset = offset; | |
996 } | |
997 } | |
998 } | |
999 | |
1000 // A float arg may have to do float reg int reg conversion | |
1001 static void float_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { | |
1002 assert(!src.second()->is_valid() && !dst.second()->is_valid(), "bad float_move"); | |
1003 | |
1004 // Because of the calling convention we know that src is either a stack location | |
1005 // or an xmm register. dst can only be a stack location. | |
1006 | |
1007 assert(dst.first()->is_stack() && ( src.first()->is_stack() || src.first()->is_XMMRegister()), "bad parameters"); | |
1008 | |
1009 if (src.first()->is_stack()) { | |
1010 __ movl(rax, Address(rbp, reg2offset_in(src.first()))); | |
304 | 1011 __ movptr(Address(rsp, reg2offset_out(dst.first())), rax); |
0 | 1012 } else { |
1013 // reg to stack | |
1014 __ movflt(Address(rsp, reg2offset_out(dst.first())), src.first()->as_XMMRegister()); | |
1015 } | |
1016 } | |
1017 | |
1018 // A long move | |
1019 static void long_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { | |
1020 | |
1021 // The only legal possibility for a long_move VMRegPair is: | |
1022 // 1: two stack slots (possibly unaligned) | |
1023 // as neither the java or C calling convention will use registers | |
1024 // for longs. | |
1025 | |
1026 if (src.first()->is_stack() && dst.first()->is_stack()) { | |
1027 assert(src.second()->is_stack() && dst.second()->is_stack(), "must be all stack"); | |
304 | 1028 __ movptr(rax, Address(rbp, reg2offset_in(src.first()))); |
1029 NOT_LP64(__ movptr(rbx, Address(rbp, reg2offset_in(src.second())))); | |
1030 __ movptr(Address(rsp, reg2offset_out(dst.first())), rax); | |
1031 NOT_LP64(__ movptr(Address(rsp, reg2offset_out(dst.second())), rbx)); | |
0 | 1032 } else { |
1033 ShouldNotReachHere(); | |
1034 } | |
1035 } | |
1036 | |
1037 // A double move | |
1038 static void double_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { | |
1039 | |
1040 // The only legal possibilities for a double_move VMRegPair are: | |
1041 // The painful thing here is that like long_move a VMRegPair might be | |
1042 | |
1043 // Because of the calling convention we know that src is either | |
1044 // 1: a single physical register (xmm registers only) | |
1045 // 2: two stack slots (possibly unaligned) | |
1046 // dst can only be a pair of stack slots. | |
1047 | |
1048 assert(dst.first()->is_stack() && (src.first()->is_XMMRegister() || src.first()->is_stack()), "bad args"); | |
1049 | |
1050 if (src.first()->is_stack()) { | |
1051 // source is all stack | |
304 | 1052 __ movptr(rax, Address(rbp, reg2offset_in(src.first()))); |
1053 NOT_LP64(__ movptr(rbx, Address(rbp, reg2offset_in(src.second())))); | |
1054 __ movptr(Address(rsp, reg2offset_out(dst.first())), rax); | |
1055 NOT_LP64(__ movptr(Address(rsp, reg2offset_out(dst.second())), rbx)); | |
0 | 1056 } else { |
1057 // reg to stack | |
1058 // No worries about stack alignment | |
1059 __ movdbl(Address(rsp, reg2offset_out(dst.first())), src.first()->as_XMMRegister()); | |
1060 } | |
1061 } | |
1062 | |
1063 | |
1064 void SharedRuntime::save_native_result(MacroAssembler *masm, BasicType ret_type, int frame_slots) { | |
1065 // We always ignore the frame_slots arg and just use the space just below frame pointer | |
1066 // which by this time is free to use | |
1067 switch (ret_type) { | |
1068 case T_FLOAT: | |
1069 __ fstp_s(Address(rbp, -wordSize)); | |
1070 break; | |
1071 case T_DOUBLE: | |
1072 __ fstp_d(Address(rbp, -2*wordSize)); | |
1073 break; | |
1074 case T_VOID: break; | |
1075 case T_LONG: | |
304 | 1076 __ movptr(Address(rbp, -wordSize), rax); |
1077 NOT_LP64(__ movptr(Address(rbp, -2*wordSize), rdx)); | |
0 | 1078 break; |
1079 default: { | |
304 | 1080 __ movptr(Address(rbp, -wordSize), rax); |
0 | 1081 } |
1082 } | |
1083 } | |
1084 | |
1085 void SharedRuntime::restore_native_result(MacroAssembler *masm, BasicType ret_type, int frame_slots) { | |
1086 // We always ignore the frame_slots arg and just use the space just below frame pointer | |
1087 // which by this time is free to use | |
1088 switch (ret_type) { | |
1089 case T_FLOAT: | |
1090 __ fld_s(Address(rbp, -wordSize)); | |
1091 break; | |
1092 case T_DOUBLE: | |
1093 __ fld_d(Address(rbp, -2*wordSize)); | |
1094 break; | |
1095 case T_LONG: | |
304 | 1096 __ movptr(rax, Address(rbp, -wordSize)); |
1097 NOT_LP64(__ movptr(rdx, Address(rbp, -2*wordSize))); | |
0 | 1098 break; |
1099 case T_VOID: break; | |
1100 default: { | |
304 | 1101 __ movptr(rax, Address(rbp, -wordSize)); |
0 | 1102 } |
1103 } | |
1104 } | |
1105 | |
1106 // --------------------------------------------------------------------------- | |
1107 // Generate a native wrapper for a given method. The method takes arguments | |
1108 // in the Java compiled code convention, marshals them to the native | |
1109 // convention (handlizes oops, etc), transitions to native, makes the call, | |
1110 // returns to java state (possibly blocking), unhandlizes any result and | |
1111 // returns. | |
1112 nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, | |
1113 methodHandle method, | |
2405
3d58a4983660
7022998: JSR 292 recursive method handle calls inline themselves infinitely
twisti
parents:
2245
diff
changeset
|
1114 int compile_id, |
0 | 1115 int total_in_args, |
1116 int comp_args_on_stack, | |
1117 BasicType *in_sig_bt, | |
1118 VMRegPair *in_regs, | |
1119 BasicType ret_type) { | |
1120 | |
1121 // An OopMap for lock (and class if static) | |
1122 OopMapSet *oop_maps = new OopMapSet(); | |
1123 | |
1124 // We have received a description of where all the java arg are located | |
1125 // on entry to the wrapper. We need to convert these args to where | |
1126 // the jni function will expect them. To figure out where they go | |
1127 // we convert the java signature to a C signature by inserting | |
1128 // the hidden arguments as arg[0] and possibly arg[1] (static method) | |
1129 | |
1130 int total_c_args = total_in_args + 1; | |
1131 if (method->is_static()) { | |
1132 total_c_args++; | |
1133 } | |
1134 | |
1135 BasicType* out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_c_args); | |
1136 VMRegPair* out_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_c_args); | |
1137 | |
1138 int argc = 0; | |
1139 out_sig_bt[argc++] = T_ADDRESS; | |
1140 if (method->is_static()) { | |
1141 out_sig_bt[argc++] = T_OBJECT; | |
1142 } | |
1143 | |
1144 int i; | |
1145 for (i = 0; i < total_in_args ; i++ ) { | |
1146 out_sig_bt[argc++] = in_sig_bt[i]; | |
1147 } | |
1148 | |
1149 | |
1150 // Now figure out where the args must be stored and how much stack space | |
1151 // they require (neglecting out_preserve_stack_slots but space for storing | |
1152 // the 1st six register arguments). It's weird see int_stk_helper. | |
1153 // | |
1154 int out_arg_slots; | |
1155 out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args); | |
1156 | |
1157 // Compute framesize for the wrapper. We need to handlize all oops in | |
1158 // registers a max of 2 on x86. | |
1159 | |
1160 // Calculate the total number of stack slots we will need. | |
1161 | |
1162 // First count the abi requirement plus all of the outgoing args | |
1163 int stack_slots = SharedRuntime::out_preserve_stack_slots() + out_arg_slots; | |
1164 | |
1165 // Now the space for the inbound oop handle area | |
1166 | |
1167 int oop_handle_offset = stack_slots; | |
1168 stack_slots += 2*VMRegImpl::slots_per_word; | |
1169 | |
1170 // Now any space we need for handlizing a klass if static method | |
1171 | |
1172 int klass_slot_offset = 0; | |
1173 int klass_offset = -1; | |
1174 int lock_slot_offset = 0; | |
1175 bool is_static = false; | |
1176 int oop_temp_slot_offset = 0; | |
1177 | |
1178 if (method->is_static()) { | |
1179 klass_slot_offset = stack_slots; | |
1180 stack_slots += VMRegImpl::slots_per_word; | |
1181 klass_offset = klass_slot_offset * VMRegImpl::stack_slot_size; | |
1182 is_static = true; | |
1183 } | |
1184 | |
1185 // Plus a lock if needed | |
1186 | |
1187 if (method->is_synchronized()) { | |
1188 lock_slot_offset = stack_slots; | |
1189 stack_slots += VMRegImpl::slots_per_word; | |
1190 } | |
1191 | |
1192 // Now a place (+2) to save return values or temp during shuffling | |
1193 // + 2 for return address (which we own) and saved rbp, | |
1194 stack_slots += 4; | |
1195 | |
1196 // Ok The space we have allocated will look like: | |
1197 // | |
1198 // | |
1199 // FP-> | | | |
1200 // |---------------------| | |
1201 // | 2 slots for moves | | |
1202 // |---------------------| | |
1203 // | lock box (if sync) | | |
1204 // |---------------------| <- lock_slot_offset (-lock_slot_rbp_offset) | |
1205 // | klass (if static) | | |
1206 // |---------------------| <- klass_slot_offset | |
1207 // | oopHandle area | | |
1208 // |---------------------| <- oop_handle_offset (a max of 2 registers) | |
1209 // | outbound memory | | |
1210 // | based arguments | | |
1211 // | | | |
1212 // |---------------------| | |
1213 // | | | |
1214 // SP-> | out_preserved_slots | | |
1215 // | |
1216 // | |
1217 // **************************************************************************** | |
1218 // WARNING - on Windows Java Natives use pascal calling convention and pop the | |
1219 // arguments off of the stack after the jni call. Before the call we can use | |
1220 // instructions that are SP relative. After the jni call we switch to FP | |
1221 // relative instructions instead of re-adjusting the stack on windows. | |
1222 // **************************************************************************** | |
1223 | |
1224 | |
1225 // Now compute actual number of stack words we need rounding to make | |
1226 // stack properly aligned. | |
524
c9004fe53695
6792301: StackAlignmentInBytes not honored for compiled native methods
xlu
parents:
512
diff
changeset
|
1227 stack_slots = round_to(stack_slots, StackAlignmentInSlots); |
0 | 1228 |
1229 int stack_size = stack_slots * VMRegImpl::stack_slot_size; | |
1230 | |
1231 intptr_t start = (intptr_t)__ pc(); | |
1232 | |
1233 // First thing make an ic check to see if we should even be here | |
1234 | |
1235 // We are free to use all registers as temps without saving them and | |
1236 // restoring them except rbp,. rbp, is the only callee save register | |
1237 // as far as the interpreter and the compiler(s) are concerned. | |
1238 | |
1239 | |
1240 const Register ic_reg = rax; | |
1241 const Register receiver = rcx; | |
1242 Label hit; | |
1243 Label exception_pending; | |
1244 | |
1245 | |
1246 __ verify_oop(receiver); | |
304 | 1247 __ cmpptr(ic_reg, Address(receiver, oopDesc::klass_offset_in_bytes())); |
0 | 1248 __ jcc(Assembler::equal, hit); |
1249 | |
1250 __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); | |
1251 | |
1252 // verified entry must be aligned for code patching. | |
1253 // and the first 5 bytes must be in the same cache line | |
1254 // if we align at 8 then we will be sure 5 bytes are in the same line | |
1255 __ align(8); | |
1256 | |
1257 __ bind(hit); | |
1258 | |
1259 int vep_offset = ((intptr_t)__ pc()) - start; | |
1260 | |
1261 #ifdef COMPILER1 | |
1262 if (InlineObjectHash && method->intrinsic_id() == vmIntrinsics::_hashCode) { | |
1263 // Object.hashCode can pull the hashCode from the header word | |
1264 // instead of doing a full VM transition once it's been computed. | |
1265 // Since hashCode is usually polymorphic at call sites we can't do | |
1266 // this optimization at the call site without a lot of work. | |
1267 Label slowCase; | |
1268 Register receiver = rcx; | |
1269 Register result = rax; | |
304 | 1270 __ movptr(result, Address(receiver, oopDesc::mark_offset_in_bytes())); |
0 | 1271 |
1272 // check if locked | |
304 | 1273 __ testptr(result, markOopDesc::unlocked_value); |
0 | 1274 __ jcc (Assembler::zero, slowCase); |
1275 | |
1276 if (UseBiasedLocking) { | |
1277 // Check if biased and fall through to runtime if so | |
304 | 1278 __ testptr(result, markOopDesc::biased_lock_bit_in_place); |
0 | 1279 __ jcc (Assembler::notZero, slowCase); |
1280 } | |
1281 | |
1282 // get hash | |
304 | 1283 __ andptr(result, markOopDesc::hash_mask_in_place); |
0 | 1284 // test if hashCode exists |
1285 __ jcc (Assembler::zero, slowCase); | |
304 | 1286 __ shrptr(result, markOopDesc::hash_shift); |
0 | 1287 __ ret(0); |
1288 __ bind (slowCase); | |
1289 } | |
1290 #endif // COMPILER1 | |
1291 | |
1292 // The instruction at the verified entry point must be 5 bytes or longer | |
1293 // because it can be patched on the fly by make_non_entrant. The stack bang | |
1294 // instruction fits that requirement. | |
1295 | |
1296 // Generate stack overflow check | |
1297 | |
1298 if (UseStackBanging) { | |
1299 __ bang_stack_with_offset(StackShadowPages*os::vm_page_size()); | |
1300 } else { | |
1301 // need a 5 byte instruction to allow MT safe patching to non-entrant | |
1302 __ fat_nop(); | |
1303 } | |
1304 | |
1305 // Generate a new frame for the wrapper. | |
1306 __ enter(); | |
1307 // -2 because return address is already present and so is saved rbp, | |
304 | 1308 __ subptr(rsp, stack_size - 2*wordSize); |
0 | 1309 |
1310 // Frame is now completed as far a size and linkage. | |
1311 | |
1312 int frame_complete = ((intptr_t)__ pc()) - start; | |
1313 | |
1314 // Calculate the difference between rsp and rbp,. We need to know it | |
1315 // after the native call because on windows Java Natives will pop | |
1316 // the arguments and it is painful to do rsp relative addressing | |
1317 // in a platform independent way. So after the call we switch to | |
1318 // rbp, relative addressing. | |
1319 | |
1320 int fp_adjustment = stack_size - 2*wordSize; | |
1321 | |
1322 #ifdef COMPILER2 | |
1323 // C2 may leave the stack dirty if not in SSE2+ mode | |
1324 if (UseSSE >= 2) { | |
1325 __ verify_FPU(0, "c2i transition should have clean FPU stack"); | |
1326 } else { | |
1327 __ empty_FPU_stack(); | |
1328 } | |
1329 #endif /* COMPILER2 */ | |
1330 | |
1331 // Compute the rbp, offset for any slots used after the jni call | |
1332 | |
1333 int lock_slot_rbp_offset = (lock_slot_offset*VMRegImpl::stack_slot_size) - fp_adjustment; | |
1334 int oop_temp_slot_rbp_offset = (oop_temp_slot_offset*VMRegImpl::stack_slot_size) - fp_adjustment; | |
1335 | |
1336 // We use rdi as a thread pointer because it is callee save and | |
1337 // if we load it once it is usable thru the entire wrapper | |
1338 const Register thread = rdi; | |
1339 | |
1340 // We use rsi as the oop handle for the receiver/klass | |
1341 // It is callee save so it survives the call to native | |
1342 | |
1343 const Register oop_handle_reg = rsi; | |
1344 | |
1345 __ get_thread(thread); | |
1346 | |
1347 | |
1348 // | |
1349 // We immediately shuffle the arguments so that any vm call we have to | |
1350 // make from here on out (sync slow path, jvmti, etc.) we will have | |
1351 // captured the oops from our caller and have a valid oopMap for | |
1352 // them. | |
1353 | |
1354 // ----------------- | |
1355 // The Grand Shuffle | |
1356 // | |
1357 // Natives require 1 or 2 extra arguments over the normal ones: the JNIEnv* | |
1358 // and, if static, the class mirror instead of a receiver. This pretty much | |
1359 // guarantees that register layout will not match (and x86 doesn't use reg | |
1360 // parms though amd does). Since the native abi doesn't use register args | |
1361 // and the java conventions does we don't have to worry about collisions. | |
1362 // All of our moved are reg->stack or stack->stack. | |
1363 // We ignore the extra arguments during the shuffle and handle them at the | |
1364 // last moment. The shuffle is described by the two calling convention | |
1365 // vectors we have in our possession. We simply walk the java vector to | |
1366 // get the source locations and the c vector to get the destinations. | |
1367 | |
1368 int c_arg = method->is_static() ? 2 : 1 ; | |
1369 | |
1370 // Record rsp-based slot for receiver on stack for non-static methods | |
1371 int receiver_offset = -1; | |
1372 | |
1373 // This is a trick. We double the stack slots so we can claim | |
1374 // the oops in the caller's frame. Since we are sure to have | |
1375 // more args than the caller doubling is enough to make | |
1376 // sure we can capture all the incoming oop args from the | |
1377 // caller. | |
1378 // | |
1379 OopMap* map = new OopMap(stack_slots * 2, 0 /* arg_slots*/); | |
1380 | |
1381 // Mark location of rbp, | |
1382 // map->set_callee_saved(VMRegImpl::stack2reg( stack_slots - 2), stack_slots * 2, 0, rbp->as_VMReg()); | |
1383 | |
1384 // We know that we only have args in at most two integer registers (rcx, rdx). So rax, rbx | |
1385 // Are free to temporaries if we have to do stack to steck moves. | |
1386 // All inbound args are referenced based on rbp, and all outbound args via rsp. | |
1387 | |
1388 for (i = 0; i < total_in_args ; i++, c_arg++ ) { | |
1389 switch (in_sig_bt[i]) { | |
1390 case T_ARRAY: | |
1391 case T_OBJECT: | |
1392 object_move(masm, map, oop_handle_offset, stack_slots, in_regs[i], out_regs[c_arg], | |
1393 ((i == 0) && (!is_static)), | |
1394 &receiver_offset); | |
1395 break; | |
1396 case T_VOID: | |
1397 break; | |
1398 | |
1399 case T_FLOAT: | |
1400 float_move(masm, in_regs[i], out_regs[c_arg]); | |
1401 break; | |
1402 | |
1403 case T_DOUBLE: | |
1404 assert( i + 1 < total_in_args && | |
1405 in_sig_bt[i + 1] == T_VOID && | |
1406 out_sig_bt[c_arg+1] == T_VOID, "bad arg list"); | |
1407 double_move(masm, in_regs[i], out_regs[c_arg]); | |
1408 break; | |
1409 | |
1410 case T_LONG : | |
1411 long_move(masm, in_regs[i], out_regs[c_arg]); | |
1412 break; | |
1413 | |
1414 case T_ADDRESS: assert(false, "found T_ADDRESS in java args"); | |
1415 | |
1416 default: | |
1417 simple_move32(masm, in_regs[i], out_regs[c_arg]); | |
1418 } | |
1419 } | |
1420 | |
1421 // Pre-load a static method's oop into rsi. Used both by locking code and | |
1422 // the normal JNI call code. | |
1423 if (method->is_static()) { | |
1424 | |
1425 // load opp into a register | |
1426 __ movoop(oop_handle_reg, JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror())); | |
1427 | |
1428 // Now handlize the static class mirror it's known not-null. | |
304 | 1429 __ movptr(Address(rsp, klass_offset), oop_handle_reg); |
0 | 1430 map->set_oop(VMRegImpl::stack2reg(klass_slot_offset)); |
1431 | |
1432 // Now get the handle | |
304 | 1433 __ lea(oop_handle_reg, Address(rsp, klass_offset)); |
0 | 1434 // store the klass handle as second argument |
304 | 1435 __ movptr(Address(rsp, wordSize), oop_handle_reg); |
0 | 1436 } |
1437 | |
1438 // Change state to native (we save the return address in the thread, since it might not | |
1439 // be pushed on the stack when we do a a stack traversal). It is enough that the pc() | |
1440 // points into the right code segment. It does not have to be the correct return pc. | |
1441 // We use the same pc/oopMap repeatedly when we call out | |
1442 | |
1443 intptr_t the_pc = (intptr_t) __ pc(); | |
1444 oop_maps->add_gc_map(the_pc - start, map); | |
1445 | |
1446 __ set_last_Java_frame(thread, rsp, noreg, (address)the_pc); | |
1447 | |
1448 | |
1449 // We have all of the arguments setup at this point. We must not touch any register | |
1450 // argument registers at this point (what if we save/restore them there are no oop? | |
1451 | |
1452 { | |
1453 SkipIfEqual skip_if(masm, &DTraceMethodProbes, 0); | |
1454 __ movoop(rax, JNIHandles::make_local(method())); | |
1455 __ call_VM_leaf( | |
1456 CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), | |
1457 thread, rax); | |
1458 } | |
1459 | |
610
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
304
diff
changeset
|
1460 // RedefineClasses() tracing support for obsolete method entry |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
304
diff
changeset
|
1461 if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) { |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
304
diff
changeset
|
1462 __ movoop(rax, JNIHandles::make_local(method())); |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
304
diff
changeset
|
1463 __ call_VM_leaf( |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
304
diff
changeset
|
1464 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:
304
diff
changeset
|
1465 thread, rax); |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
304
diff
changeset
|
1466 } |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
304
diff
changeset
|
1467 |
0 | 1468 // These are register definitions we need for locking/unlocking |
1469 const Register swap_reg = rax; // Must use rax, for cmpxchg instruction | |
1470 const Register obj_reg = rcx; // Will contain the oop | |
1471 const Register lock_reg = rdx; // Address of compiler lock object (BasicLock) | |
1472 | |
1473 Label slow_path_lock; | |
1474 Label lock_done; | |
1475 | |
1476 // Lock a synchronized method | |
1477 if (method->is_synchronized()) { | |
1478 | |
1479 | |
1480 const int mark_word_offset = BasicLock::displaced_header_offset_in_bytes(); | |
1481 | |
1482 // Get the handle (the 2nd argument) | |
304 | 1483 __ movptr(oop_handle_reg, Address(rsp, wordSize)); |
0 | 1484 |
1485 // Get address of the box | |
1486 | |
304 | 1487 __ lea(lock_reg, Address(rbp, lock_slot_rbp_offset)); |
0 | 1488 |
1489 // Load the oop from the handle | |
304 | 1490 __ movptr(obj_reg, Address(oop_handle_reg, 0)); |
0 | 1491 |
1492 if (UseBiasedLocking) { | |
1493 // Note that oop_handle_reg is trashed during this call | |
1494 __ biased_locking_enter(lock_reg, obj_reg, swap_reg, oop_handle_reg, false, lock_done, &slow_path_lock); | |
1495 } | |
1496 | |
1497 // Load immediate 1 into swap_reg %rax, | |
304 | 1498 __ movptr(swap_reg, 1); |
0 | 1499 |
1500 // Load (object->mark() | 1) into swap_reg %rax, | |
304 | 1501 __ orptr(swap_reg, Address(obj_reg, 0)); |
0 | 1502 |
1503 // Save (object->mark() | 1) into BasicLock's displaced header | |
304 | 1504 __ movptr(Address(lock_reg, mark_word_offset), swap_reg); |
0 | 1505 |
1506 if (os::is_MP()) { | |
1507 __ lock(); | |
1508 } | |
1509 | |
1510 // src -> dest iff dest == rax, else rax, <- dest | |
1511 // *obj_reg = lock_reg iff *obj_reg == rax, else rax, = *(obj_reg) | |
304 | 1512 __ cmpxchgptr(lock_reg, Address(obj_reg, 0)); |
0 | 1513 __ jcc(Assembler::equal, lock_done); |
1514 | |
1515 // Test if the oopMark is an obvious stack pointer, i.e., | |
1516 // 1) (mark & 3) == 0, and | |
1517 // 2) rsp <= mark < mark + os::pagesize() | |
1518 // These 3 tests can be done by evaluating the following | |
1519 // expression: ((mark - rsp) & (3 - os::vm_page_size())), | |
1520 // assuming both stack pointer and pagesize have their | |
1521 // least significant 2 bits clear. | |
1522 // NOTE: the oopMark is in swap_reg %rax, as the result of cmpxchg | |
1523 | |
304 | 1524 __ subptr(swap_reg, rsp); |
1525 __ andptr(swap_reg, 3 - os::vm_page_size()); | |
0 | 1526 |
1527 // Save the test result, for recursive case, the result is zero | |
304 | 1528 __ movptr(Address(lock_reg, mark_word_offset), swap_reg); |
0 | 1529 __ jcc(Assembler::notEqual, slow_path_lock); |
1530 // Slow path will re-enter here | |
1531 __ bind(lock_done); | |
1532 | |
1533 if (UseBiasedLocking) { | |
1534 // Re-fetch oop_handle_reg as we trashed it above | |
304 | 1535 __ movptr(oop_handle_reg, Address(rsp, wordSize)); |
0 | 1536 } |
1537 } | |
1538 | |
1539 | |
1540 // Finally just about ready to make the JNI call | |
1541 | |
1542 | |
1543 // get JNIEnv* which is first argument to native | |
1544 | |
304 | 1545 __ lea(rdx, Address(thread, in_bytes(JavaThread::jni_environment_offset()))); |
1546 __ movptr(Address(rsp, 0), rdx); | |
0 | 1547 |
1548 // Now set thread in native | |
1549 __ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_native); | |
1550 | |
1551 __ call(RuntimeAddress(method->native_function())); | |
1552 | |
1553 // WARNING - on Windows Java Natives use pascal calling convention and pop the | |
1554 // arguments off of the stack. We could just re-adjust the stack pointer here | |
1555 // and continue to do SP relative addressing but we instead switch to FP | |
1556 // relative addressing. | |
1557 | |
1558 // Unpack native results. | |
1559 switch (ret_type) { | |
1560 case T_BOOLEAN: __ c2bool(rax); break; | |
304 | 1561 case T_CHAR : __ andptr(rax, 0xFFFF); break; |
0 | 1562 case T_BYTE : __ sign_extend_byte (rax); break; |
1563 case T_SHORT : __ sign_extend_short(rax); break; | |
1564 case T_INT : /* nothing to do */ break; | |
1565 case T_DOUBLE : | |
1566 case T_FLOAT : | |
1567 // Result is in st0 we'll save as needed | |
1568 break; | |
1569 case T_ARRAY: // Really a handle | |
1570 case T_OBJECT: // Really a handle | |
1571 break; // can't de-handlize until after safepoint check | |
1572 case T_VOID: break; | |
1573 case T_LONG: break; | |
1574 default : ShouldNotReachHere(); | |
1575 } | |
1576 | |
1577 // Switch thread to "native transition" state before reading the synchronization state. | |
1578 // This additional state is necessary because reading and testing the synchronization | |
1579 // state is not atomic w.r.t. GC, as this scenario demonstrates: | |
1580 // Java thread A, in _thread_in_native state, loads _not_synchronized and is preempted. | |
1581 // VM thread changes sync state to synchronizing and suspends threads for GC. | |
1582 // Thread A is resumed to finish this native method, but doesn't block here since it | |
1583 // didn't see any synchronization is progress, and escapes. | |
1584 __ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_native_trans); | |
1585 | |
1586 if(os::is_MP()) { | |
1587 if (UseMembar) { | |
304 | 1588 // Force this write out before the read below |
1589 __ membar(Assembler::Membar_mask_bits( | |
1590 Assembler::LoadLoad | Assembler::LoadStore | | |
1591 Assembler::StoreLoad | Assembler::StoreStore)); | |
0 | 1592 } else { |
1593 // Write serialization page so VM thread can do a pseudo remote membar. | |
1594 // We use the current thread pointer to calculate a thread specific | |
1595 // offset to write to within the page. This minimizes bus traffic | |
1596 // due to cache line collision. | |
1597 __ serialize_memory(thread, rcx); | |
1598 } | |
1599 } | |
1600 | |
1601 if (AlwaysRestoreFPU) { | |
1602 // Make sure the control word is correct. | |
1603 __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); | |
1604 } | |
1605 | |
1606 // check for safepoint operation in progress and/or pending suspend requests | |
1607 { Label Continue; | |
1608 | |
1609 __ cmp32(ExternalAddress((address)SafepointSynchronize::address_of_state()), | |
1610 SafepointSynchronize::_not_synchronized); | |
1611 | |
1612 Label L; | |
1613 __ jcc(Assembler::notEqual, L); | |
1614 __ cmpl(Address(thread, JavaThread::suspend_flags_offset()), 0); | |
1615 __ jcc(Assembler::equal, Continue); | |
1616 __ bind(L); | |
1617 | |
1618 // Don't use call_VM as it will see a possible pending exception and forward it | |
1619 // and never return here preventing us from clearing _last_native_pc down below. | |
1620 // Also can't use call_VM_leaf either as it will check to see if rsi & rdi are | |
1621 // preserved and correspond to the bcp/locals pointers. So we do a runtime call | |
1622 // by hand. | |
1623 // | |
1624 save_native_result(masm, ret_type, stack_slots); | |
304 | 1625 __ push(thread); |
0 | 1626 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, |
1627 JavaThread::check_special_condition_for_native_trans))); | |
1628 __ increment(rsp, wordSize); | |
1629 // Restore any method result value | |
1630 restore_native_result(masm, ret_type, stack_slots); | |
1631 | |
1632 __ bind(Continue); | |
1633 } | |
1634 | |
1635 // change thread state | |
1636 __ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_Java); | |
1637 | |
1638 Label reguard; | |
1639 Label reguard_done; | |
1640 __ cmpl(Address(thread, JavaThread::stack_guard_state_offset()), JavaThread::stack_guard_yellow_disabled); | |
1641 __ jcc(Assembler::equal, reguard); | |
1642 | |
1643 // slow path reguard re-enters here | |
1644 __ bind(reguard_done); | |
1645 | |
1646 // Handle possible exception (will unlock if necessary) | |
1647 | |
1648 // native result if any is live | |
1649 | |
1650 // Unlock | |
1651 Label slow_path_unlock; | |
1652 Label unlock_done; | |
1653 if (method->is_synchronized()) { | |
1654 | |
1655 Label done; | |
1656 | |
1657 // Get locked oop from the handle we passed to jni | |
304 | 1658 __ movptr(obj_reg, Address(oop_handle_reg, 0)); |
0 | 1659 |
1660 if (UseBiasedLocking) { | |
1661 __ biased_locking_exit(obj_reg, rbx, done); | |
1662 } | |
1663 | |
1664 // Simple recursive lock? | |
1665 | |
304 | 1666 __ cmpptr(Address(rbp, lock_slot_rbp_offset), (int32_t)NULL_WORD); |
0 | 1667 __ jcc(Assembler::equal, done); |
1668 | |
1669 // Must save rax, if if it is live now because cmpxchg must use it | |
1670 if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { | |
1671 save_native_result(masm, ret_type, stack_slots); | |
1672 } | |
1673 | |
1674 // get old displaced header | |
304 | 1675 __ movptr(rbx, Address(rbp, lock_slot_rbp_offset)); |
0 | 1676 |
1677 // get address of the stack lock | |
304 | 1678 __ lea(rax, Address(rbp, lock_slot_rbp_offset)); |
0 | 1679 |
1680 // Atomic swap old header if oop still contains the stack lock | |
1681 if (os::is_MP()) { | |
1682 __ lock(); | |
1683 } | |
1684 | |
1685 // src -> dest iff dest == rax, else rax, <- dest | |
1686 // *obj_reg = rbx, iff *obj_reg == rax, else rax, = *(obj_reg) | |
304 | 1687 __ cmpxchgptr(rbx, Address(obj_reg, 0)); |
0 | 1688 __ jcc(Assembler::notEqual, slow_path_unlock); |
1689 | |
1690 // slow path re-enters here | |
1691 __ bind(unlock_done); | |
1692 if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { | |
1693 restore_native_result(masm, ret_type, stack_slots); | |
1694 } | |
1695 | |
1696 __ bind(done); | |
1697 | |
1698 } | |
1699 | |
1700 { | |
1701 SkipIfEqual skip_if(masm, &DTraceMethodProbes, 0); | |
1702 // Tell dtrace about this method exit | |
1703 save_native_result(masm, ret_type, stack_slots); | |
1704 __ movoop(rax, JNIHandles::make_local(method())); | |
1705 __ call_VM_leaf( | |
1706 CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), | |
1707 thread, rax); | |
1708 restore_native_result(masm, ret_type, stack_slots); | |
1709 } | |
1710 | |
1711 // We can finally stop using that last_Java_frame we setup ages ago | |
1712 | |
1713 __ reset_last_Java_frame(thread, false, true); | |
1714 | |
1715 // Unpack oop result | |
1716 if (ret_type == T_OBJECT || ret_type == T_ARRAY) { | |
1717 Label L; | |
304 | 1718 __ cmpptr(rax, (int32_t)NULL_WORD); |
0 | 1719 __ jcc(Assembler::equal, L); |
304 | 1720 __ movptr(rax, Address(rax, 0)); |
0 | 1721 __ bind(L); |
1722 __ verify_oop(rax); | |
1723 } | |
1724 | |
1725 // reset handle block | |
304 | 1726 __ movptr(rcx, Address(thread, JavaThread::active_handles_offset())); |
1727 | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
304
diff
changeset
|
1728 __ movptr(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); |
0 | 1729 |
1730 // Any exception pending? | |
304 | 1731 __ cmpptr(Address(thread, in_bytes(Thread::pending_exception_offset())), (int32_t)NULL_WORD); |
0 | 1732 __ jcc(Assembler::notEqual, exception_pending); |
1733 | |
1734 | |
1735 // no exception, we're almost done | |
1736 | |
1737 // check that only result value is on FPU stack | |
1738 __ verify_FPU(ret_type == T_FLOAT || ret_type == T_DOUBLE ? 1 : 0, "native_wrapper normal exit"); | |
1739 | |
1740 // Fixup floating pointer results so that result looks like a return from a compiled method | |
1741 if (ret_type == T_FLOAT) { | |
1742 if (UseSSE >= 1) { | |
1743 // Pop st0 and store as float and reload into xmm register | |
1744 __ fstp_s(Address(rbp, -4)); | |
1745 __ movflt(xmm0, Address(rbp, -4)); | |
1746 } | |
1747 } else if (ret_type == T_DOUBLE) { | |
1748 if (UseSSE >= 2) { | |
1749 // Pop st0 and store as double and reload into xmm register | |
1750 __ fstp_d(Address(rbp, -8)); | |
1751 __ movdbl(xmm0, Address(rbp, -8)); | |
1752 } | |
1753 } | |
1754 | |
1755 // Return | |
1756 | |
1757 __ leave(); | |
1758 __ ret(0); | |
1759 | |
1760 // Unexpected paths are out of line and go here | |
1761 | |
1762 // Slow path locking & unlocking | |
1763 if (method->is_synchronized()) { | |
1764 | |
1765 // BEGIN Slow path lock | |
1766 | |
1767 __ bind(slow_path_lock); | |
1768 | |
1769 // has last_Java_frame setup. No exceptions so do vanilla call not call_VM | |
1770 // args are (oop obj, BasicLock* lock, JavaThread* thread) | |
304 | 1771 __ push(thread); |
1772 __ push(lock_reg); | |
1773 __ push(obj_reg); | |
0 | 1774 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_locking_C))); |
304 | 1775 __ addptr(rsp, 3*wordSize); |
0 | 1776 |
1777 #ifdef ASSERT | |
1778 { Label L; | |
304 | 1779 __ cmpptr(Address(thread, in_bytes(Thread::pending_exception_offset())), (int)NULL_WORD); |
0 | 1780 __ jcc(Assembler::equal, L); |
1781 __ stop("no pending exception allowed on exit from monitorenter"); | |
1782 __ bind(L); | |
1783 } | |
1784 #endif | |
1785 __ jmp(lock_done); | |
1786 | |
1787 // END Slow path lock | |
1788 | |
1789 // BEGIN Slow path unlock | |
1790 __ bind(slow_path_unlock); | |
1791 | |
1792 // Slow path unlock | |
1793 | |
1794 if (ret_type == T_FLOAT || ret_type == T_DOUBLE ) { | |
1795 save_native_result(masm, ret_type, stack_slots); | |
1796 } | |
1797 // Save pending exception around call to VM (which contains an EXCEPTION_MARK) | |
1798 | |
304 | 1799 __ pushptr(Address(thread, in_bytes(Thread::pending_exception_offset()))); |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
304
diff
changeset
|
1800 __ movptr(Address(thread, in_bytes(Thread::pending_exception_offset())), NULL_WORD); |
0 | 1801 |
1802 | |
1803 // should be a peal | |
1804 // +wordSize because of the push above | |
304 | 1805 __ lea(rax, Address(rbp, lock_slot_rbp_offset)); |
1806 __ push(rax); | |
1807 | |
1808 __ push(obj_reg); | |
0 | 1809 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C))); |
304 | 1810 __ addptr(rsp, 2*wordSize); |
0 | 1811 #ifdef ASSERT |
1812 { | |
1813 Label L; | |
304 | 1814 __ cmpptr(Address(thread, in_bytes(Thread::pending_exception_offset())), (int32_t)NULL_WORD); |
0 | 1815 __ jcc(Assembler::equal, L); |
1816 __ stop("no pending exception allowed on exit complete_monitor_unlocking_C"); | |
1817 __ bind(L); | |
1818 } | |
1819 #endif /* ASSERT */ | |
1820 | |
304 | 1821 __ popptr(Address(thread, in_bytes(Thread::pending_exception_offset()))); |
0 | 1822 |
1823 if (ret_type == T_FLOAT || ret_type == T_DOUBLE ) { | |
1824 restore_native_result(masm, ret_type, stack_slots); | |
1825 } | |
1826 __ jmp(unlock_done); | |
1827 // END Slow path unlock | |
1828 | |
1829 } | |
1830 | |
1831 // SLOW PATH Reguard the stack if needed | |
1832 | |
1833 __ bind(reguard); | |
1834 save_native_result(masm, ret_type, stack_slots); | |
1835 { | |
1836 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages))); | |
1837 } | |
1838 restore_native_result(masm, ret_type, stack_slots); | |
1839 __ jmp(reguard_done); | |
1840 | |
1841 | |
1842 // BEGIN EXCEPTION PROCESSING | |
1843 | |
1844 // Forward the exception | |
1845 __ bind(exception_pending); | |
1846 | |
1847 // remove possible return value from FPU register stack | |
1848 __ empty_FPU_stack(); | |
1849 | |
1850 // pop our frame | |
1851 __ leave(); | |
1852 // and forward the exception | |
1853 __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); | |
1854 | |
1855 __ flush(); | |
1856 | |
1857 nmethod *nm = nmethod::new_native_nmethod(method, | |
2405
3d58a4983660
7022998: JSR 292 recursive method handle calls inline themselves infinitely
twisti
parents:
2245
diff
changeset
|
1858 compile_id, |
0 | 1859 masm->code(), |
1860 vep_offset, | |
1861 frame_complete, | |
1862 stack_slots / VMRegImpl::slots_per_word, | |
1863 (is_static ? in_ByteSize(klass_offset) : in_ByteSize(receiver_offset)), | |
1864 in_ByteSize(lock_slot_offset*VMRegImpl::stack_slot_size), | |
1865 oop_maps); | |
1866 return nm; | |
1867 | |
1868 } | |
1869 | |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1870 #ifdef HAVE_DTRACE_H |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1871 // --------------------------------------------------------------------------- |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1872 // 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:
0
diff
changeset
|
1873 // 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:
0
diff
changeset
|
1874 // 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:
0
diff
changeset
|
1875 // 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:
0
diff
changeset
|
1876 // 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:
0
diff
changeset
|
1877 // to dtrace. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1878 // |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1879 // 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:
0
diff
changeset
|
1880 // 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:
0
diff
changeset
|
1881 // 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:
0
diff
changeset
|
1882 // 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:
0
diff
changeset
|
1883 // 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:
0
diff
changeset
|
1884 // So any java string larger then this is truncated. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1885 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1886 nmethod *SharedRuntime::generate_dtrace_nmethod( |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1887 MacroAssembler *masm, methodHandle method) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1888 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1889 // 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:
0
diff
changeset
|
1890 // be single threaded in this method. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1891 assert(AdapterHandlerLibrary_lock->owned_by_self(), "must be"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1892 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1893 // 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:
0
diff
changeset
|
1894 int total_args_passed = method->size_of_parameters(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1895 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1896 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:
0
diff
changeset
|
1897 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:
0
diff
changeset
|
1898 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1899 // 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:
0
diff
changeset
|
1900 // 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:
0
diff
changeset
|
1901 // 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:
0
diff
changeset
|
1902 // 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:
0
diff
changeset
|
1903 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:
0
diff
changeset
|
1904 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:
0
diff
changeset
|
1905 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1906 int i=0; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1907 int total_strings = 0; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1908 int first_arg_to_pass = 0; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1909 int total_c_args = 0; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1910 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1911 if( !method->is_static() ) { // Pass in receiver first |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1912 in_sig_bt[i++] = T_OBJECT; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1913 first_arg_to_pass = 1; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1914 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1915 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1916 // We need to convert the java args to where a native (non-jni) function |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1917 // would expect them. To figure out where they go we convert the java |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1918 // signature to a C signature. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1919 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1920 SignatureStream ss(method->signature()); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1921 for ( ; !ss.at_return_type(); ss.next()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1922 BasicType bt = ss.type(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1923 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:
0
diff
changeset
|
1924 out_sig_bt[total_c_args++] = bt; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1925 if( bt == T_OBJECT) { |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
1926 Symbol* s = ss.as_symbol_or_null(); // symbol is created |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1927 if (s == vmSymbols::java_lang_String()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1928 total_strings++; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1929 out_sig_bt[total_c_args-1] = T_ADDRESS; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1930 } else if (s == vmSymbols::java_lang_Boolean() || |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1931 s == vmSymbols::java_lang_Character() || |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1932 s == vmSymbols::java_lang_Byte() || |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1933 s == vmSymbols::java_lang_Short() || |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1934 s == vmSymbols::java_lang_Integer() || |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1935 s == vmSymbols::java_lang_Float()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1936 out_sig_bt[total_c_args-1] = T_INT; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1937 } else if (s == vmSymbols::java_lang_Long() || |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1938 s == vmSymbols::java_lang_Double()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1939 out_sig_bt[total_c_args-1] = T_LONG; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1940 out_sig_bt[total_c_args++] = T_VOID; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1941 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1942 } else if ( bt == T_LONG || bt == T_DOUBLE ) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1943 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:
0
diff
changeset
|
1944 out_sig_bt[total_c_args++] = T_VOID; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1945 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1946 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1947 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1948 assert(i==total_args_passed, "validly parsed signature"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1949 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1950 // Now get the compiled-Java layout as input arguments |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1951 int comp_args_on_stack; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1952 comp_args_on_stack = SharedRuntime::java_calling_convention( |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1953 in_sig_bt, in_regs, total_args_passed, false); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1954 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1955 // 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:
0
diff
changeset
|
1956 // they require (neglecting out_preserve_stack_slots). |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1957 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1958 int out_arg_slots; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1959 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:
0
diff
changeset
|
1960 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1961 // 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:
0
diff
changeset
|
1962 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1963 // 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:
0
diff
changeset
|
1964 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:
0
diff
changeset
|
1965 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1966 // Now space for the string(s) we must convert |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1967 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1968 int* string_locs = NEW_RESOURCE_ARRAY(int, total_strings + 1); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1969 for (i = 0; i < total_strings ; i++) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1970 string_locs[i] = stack_slots; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1971 stack_slots += max_dtrace_string_size / VMRegImpl::stack_slot_size; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1972 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1973 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1974 // + 2 for return address (which we own) and saved rbp, |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1975 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1976 stack_slots += 2; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1977 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1978 // Ok The space we have allocated will look like: |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1979 // |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1980 // |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1981 // FP-> | | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1982 // |---------------------| |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1983 // | string[n] | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1984 // |---------------------| <- string_locs[n] |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1985 // | string[n-1] | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1986 // |---------------------| <- string_locs[n-1] |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1987 // | ... | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1988 // | ... | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1989 // |---------------------| <- string_locs[1] |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1990 // | string[0] | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1991 // |---------------------| <- string_locs[0] |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1992 // | outbound memory | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1993 // | based arguments | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1994 // | | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1995 // |---------------------| |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1996 // | | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1997 // SP-> | out_preserved_slots | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1998 // |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
1999 // |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2000 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2001 // 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:
0
diff
changeset
|
2002 // stack properly aligned. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2003 stack_slots = round_to(stack_slots, 2 * VMRegImpl::slots_per_word); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2004 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2005 int stack_size = stack_slots * VMRegImpl::stack_slot_size; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2006 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2007 intptr_t start = (intptr_t)__ pc(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2008 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2009 // 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:
0
diff
changeset
|
2010 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2011 // We are free to use all registers as temps without saving them and |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2012 // restoring them except rbp. rbp, is the only callee save register |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2013 // as far as the interpreter and the compiler(s) are concerned. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2014 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2015 const Register ic_reg = rax; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2016 const Register receiver = rcx; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2017 Label hit; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2018 Label exception_pending; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2019 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2020 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2021 __ verify_oop(receiver); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2022 __ cmpl(ic_reg, Address(receiver, oopDesc::klass_offset_in_bytes())); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2023 __ jcc(Assembler::equal, hit); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2024 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2025 __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2026 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2027 // verified entry must be aligned for code patching. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2028 // and the first 5 bytes must be in the same cache line |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2029 // if we align at 8 then we will be sure 5 bytes are in the same line |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2030 __ align(8); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2031 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2032 __ bind(hit); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2033 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2034 int vep_offset = ((intptr_t)__ pc()) - start; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2035 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2036 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2037 // 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:
0
diff
changeset
|
2038 // 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:
0
diff
changeset
|
2039 // instruction fits that requirement. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2040 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2041 // Generate stack overflow check |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2042 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2043 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2044 if (UseStackBanging) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2045 if (stack_size <= StackShadowPages*os::vm_page_size()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2046 __ bang_stack_with_offset(StackShadowPages*os::vm_page_size()); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2047 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2048 __ movl(rax, stack_size); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2049 __ bang_stack_size(rax, rbx); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2050 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2051 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2052 // need a 5 byte instruction to allow MT safe patching to non-entrant |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2053 __ fat_nop(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2054 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2055 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2056 assert(((int)__ pc() - start - vep_offset) >= 5, |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2057 "valid size for make_non_entrant"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2058 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2059 // Generate a new frame for the wrapper. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2060 __ enter(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2061 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2062 // -2 because return address is already present and so is saved rbp, |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2063 if (stack_size - 2*wordSize != 0) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2064 __ subl(rsp, stack_size - 2*wordSize); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2065 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2066 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2067 // 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:
0
diff
changeset
|
2068 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2069 int frame_complete = ((intptr_t)__ pc()) - start; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2070 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2071 // First thing we do store all the args as if we are doing the call. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2072 // Since the C calling convention is stack based that ensures that |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2073 // all the Java register args are stored before we need to convert any |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2074 // string we might have. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2075 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2076 int sid = 0; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2077 int c_arg, j_arg; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2078 int string_reg = 0; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2079 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2080 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:
0
diff
changeset
|
2081 j_arg < total_args_passed ; j_arg++, c_arg++ ) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2082 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2083 VMRegPair src = in_regs[j_arg]; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2084 VMRegPair dst = out_regs[c_arg]; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2085 assert(dst.first()->is_stack() || in_sig_bt[j_arg] == T_VOID, |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2086 "stack based abi assumed"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2087 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2088 switch (in_sig_bt[j_arg]) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2089 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2090 case T_ARRAY: |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2091 case T_OBJECT: |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2092 if (out_sig_bt[c_arg] == T_ADDRESS) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2093 // Any register based arg for a java string after the first |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2094 // will be destroyed by the call to get_utf so we store |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2095 // the original value in the location the utf string address |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2096 // will eventually be stored. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2097 if (src.first()->is_reg()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2098 if (string_reg++ != 0) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2099 simple_move32(masm, src, dst); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2100 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2101 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2102 } else if (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:
0
diff
changeset
|
2103 // need to unbox a one-word value |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2104 Register in_reg = rax; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2105 if ( src.first()->is_reg() ) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2106 in_reg = src.first()->as_Register(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2107 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2108 simple_move32(masm, src, in_reg->as_VMReg()); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2109 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2110 Label skipUnbox; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2111 __ movl(Address(rsp, reg2offset_out(dst.first())), NULL_WORD); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2112 if ( out_sig_bt[c_arg] == T_LONG ) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2113 __ movl(Address(rsp, reg2offset_out(dst.second())), NULL_WORD); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2114 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2115 __ testl(in_reg, in_reg); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2116 __ jcc(Assembler::zero, skipUnbox); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2117 assert(dst.first()->is_stack() && |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2118 (!dst.second()->is_valid() || dst.second()->is_stack()), |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2119 "value(s) must go into stack slots"); |
165
437d03ea40b1
6703888: Compressed Oops: use the 32-bits gap after klass in a object
kvn
parents:
116
diff
changeset
|
2120 |
437d03ea40b1
6703888: Compressed Oops: use the 32-bits gap after klass in a object
kvn
parents:
116
diff
changeset
|
2121 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
|
2122 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
|
2123 if ( bt == T_LONG ) { |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2124 __ movl(rbx, Address(in_reg, |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2125 box_offset + VMRegImpl::stack_slot_size)); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2126 __ movl(Address(rsp, reg2offset_out(dst.second())), rbx); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2127 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2128 __ movl(in_reg, Address(in_reg, box_offset)); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2129 __ movl(Address(rsp, reg2offset_out(dst.first())), in_reg); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2130 __ bind(skipUnbox); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2131 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2132 // Convert the arg to NULL |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2133 __ movl(Address(rsp, reg2offset_out(dst.first())), NULL_WORD); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2134 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2135 if (out_sig_bt[c_arg] == T_LONG) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2136 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:
0
diff
changeset
|
2137 ++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:
0
diff
changeset
|
2138 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2139 break; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2140 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2141 case T_VOID: |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2142 break; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2143 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2144 case T_FLOAT: |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2145 float_move(masm, src, dst); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2146 break; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2147 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2148 case T_DOUBLE: |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2149 assert( j_arg + 1 < total_args_passed && |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2150 in_sig_bt[j_arg + 1] == T_VOID, "bad arg list"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2151 double_move(masm, src, dst); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2152 break; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2153 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2154 case T_LONG : |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2155 long_move(masm, src, dst); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2156 break; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2157 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2158 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:
0
diff
changeset
|
2159 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2160 default: |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2161 simple_move32(masm, src, dst); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2162 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2163 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2164 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2165 // Now we must convert any string we have to utf8 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2166 // |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2167 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2168 for (sid = 0, j_arg = first_arg_to_pass, c_arg = 0 ; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2169 sid < total_strings ; j_arg++, c_arg++ ) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2170 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2171 if (out_sig_bt[c_arg] == T_ADDRESS) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2172 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2173 Address utf8_addr = Address( |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2174 rsp, string_locs[sid++] * VMRegImpl::stack_slot_size); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2175 __ leal(rax, utf8_addr); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2176 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2177 // The first string we find might still be in the original java arg |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2178 // register |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2179 VMReg orig_loc = in_regs[j_arg].first(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2180 Register string_oop; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2181 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2182 // This is where the argument will eventually reside |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2183 Address dest = Address(rsp, reg2offset_out(out_regs[c_arg].first())); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2184 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2185 if (sid == 1 && orig_loc->is_reg()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2186 string_oop = orig_loc->as_Register(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2187 assert(string_oop != rax, "smashed arg"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2188 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2189 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2190 if (orig_loc->is_reg()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2191 // Get the copy of the jls object |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2192 __ movl(rcx, dest); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2193 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2194 // arg is still in the original location |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2195 __ movl(rcx, Address(rbp, reg2offset_in(orig_loc))); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2196 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2197 string_oop = rcx; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2198 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2199 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2200 Label nullString; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2201 __ movl(dest, NULL_WORD); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2202 __ testl(string_oop, string_oop); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2203 __ jcc(Assembler::zero, nullString); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2204 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2205 // Now we can store the address of the utf string as the argument |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2206 __ movl(dest, rax); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2207 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2208 // And do the conversion |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2209 __ call_VM_leaf(CAST_FROM_FN_PTR( |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2210 address, SharedRuntime::get_utf), string_oop, rax); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2211 __ bind(nullString); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2212 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2213 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2214 if (in_sig_bt[j_arg] == T_OBJECT && out_sig_bt[c_arg] == T_LONG) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2215 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:
0
diff
changeset
|
2216 ++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:
0
diff
changeset
|
2217 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2218 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2219 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2220 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2221 // 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:
0
diff
changeset
|
2222 // patch in the trap |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2223 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2224 int patch_offset = ((intptr_t)__ pc()) - start; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2225 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2226 __ nop(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2227 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2228 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2229 // Return |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2230 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2231 __ leave(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2232 __ ret(0); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2233 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2234 __ flush(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2235 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2236 nmethod *nm = nmethod::new_dtrace_nmethod( |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2237 method, masm->code(), vep_offset, patch_offset, frame_complete, |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2238 stack_slots / VMRegImpl::slots_per_word); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2239 return nm; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2240 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2241 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2242 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2243 #endif // HAVE_DTRACE_H |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
2244 |
0 | 2245 // this function returns the adjust size (in number of words) to a c2i adapter |
2246 // activation for use during deoptimization | |
2247 int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals ) { | |
1506 | 2248 return (callee_locals - callee_parameters) * Interpreter::stackElementWords; |
0 | 2249 } |
2250 | |
2251 | |
2252 uint SharedRuntime::out_preserve_stack_slots() { | |
2253 return 0; | |
2254 } | |
2255 | |
2256 | |
2257 //------------------------------generate_deopt_blob---------------------------- | |
2258 void SharedRuntime::generate_deopt_blob() { | |
2259 // allocate space for the code | |
2260 ResourceMark rm; | |
2261 // setup code generation tools | |
2262 CodeBuffer buffer("deopt_blob", 1024, 1024); | |
2263 MacroAssembler* masm = new MacroAssembler(&buffer); | |
2264 int frame_size_in_words; | |
2265 OopMap* map = NULL; | |
2266 // Account for the extra args we place on the stack | |
2267 // by the time we call fetch_unroll_info | |
2268 const int additional_words = 2; // deopt kind, thread | |
2269 | |
2270 OopMapSet *oop_maps = new OopMapSet(); | |
2271 | |
2272 // ------------- | |
2273 // This code enters when returning to a de-optimized nmethod. A return | |
2274 // address has been pushed on the the stack, and return values are in | |
2275 // registers. | |
2276 // If we are doing a normal deopt then we were called from the patched | |
2277 // nmethod from the point we returned to the nmethod. So the return | |
2278 // address on the stack is wrong by NativeCall::instruction_size | |
2279 // We will adjust the value to it looks like we have the original return | |
2280 // address on the stack (like when we eagerly deoptimized). | |
2281 // In the case of an exception pending with deoptimized then we enter | |
2282 // with a return address on the stack that points after the call we patched | |
2283 // into the exception handler. We have the following register state: | |
2284 // rax,: exception | |
2285 // rbx,: exception handler | |
2286 // rdx: throwing pc | |
2287 // So in this case we simply jam rdx into the useless return address and | |
2288 // the stack looks just like we want. | |
2289 // | |
2290 // At this point we need to de-opt. We save the argument return | |
2291 // registers. We call the first C routine, fetch_unroll_info(). This | |
2292 // routine captures the return values and returns a structure which | |
2293 // describes the current frame size and the sizes of all replacement frames. | |
2294 // The current frame is compiled code and may contain many inlined | |
2295 // functions, each with their own JVM state. We pop the current frame, then | |
2296 // push all the new frames. Then we call the C routine unpack_frames() to | |
2297 // populate these frames. Finally unpack_frames() returns us the new target | |
2298 // address. Notice that callee-save registers are BLOWN here; they have | |
2299 // already been captured in the vframeArray at the time the return PC was | |
2300 // patched. | |
2301 address start = __ pc(); | |
2302 Label cont; | |
2303 | |
2304 // Prolog for non exception case! | |
2305 | |
2306 // Save everything in sight. | |
2307 | |
926
c8e2135f7e30
6829127: Deoptimization Failure on Specjvm98 _227_mtrt with -XX:+DeoptimizeALot since Hs11 b01
cfang
parents:
628
diff
changeset
|
2308 map = RegisterSaver::save_live_registers(masm, additional_words, &frame_size_in_words, false); |
0 | 2309 // Normal deoptimization |
304 | 2310 __ push(Deoptimization::Unpack_deopt); |
0 | 2311 __ jmp(cont); |
2312 | |
2313 int reexecute_offset = __ pc() - start; | |
2314 | |
2315 // Reexecute case | |
2316 // return address is the pc describes what bci to do re-execute at | |
2317 | |
2318 // No need to update map as each call to save_live_registers will produce identical oopmap | |
926
c8e2135f7e30
6829127: Deoptimization Failure on Specjvm98 _227_mtrt with -XX:+DeoptimizeALot since Hs11 b01
cfang
parents:
628
diff
changeset
|
2319 (void) RegisterSaver::save_live_registers(masm, additional_words, &frame_size_in_words, false); |
0 | 2320 |
304 | 2321 __ push(Deoptimization::Unpack_reexecute); |
0 | 2322 __ jmp(cont); |
2323 | |
2324 int exception_offset = __ pc() - start; | |
2325 | |
2326 // Prolog for exception case | |
2327 | |
2328 // all registers are dead at this entry point, except for rax, and | |
2329 // rdx which contain the exception oop and exception pc | |
2330 // respectively. Set them in TLS and fall thru to the | |
2331 // unpack_with_exception_in_tls entry point. | |
2332 | |
2333 __ get_thread(rdi); | |
304 | 2334 __ movptr(Address(rdi, JavaThread::exception_pc_offset()), rdx); |
2335 __ movptr(Address(rdi, JavaThread::exception_oop_offset()), rax); | |
0 | 2336 |
2337 int exception_in_tls_offset = __ pc() - start; | |
2338 | |
2339 // new implementation because exception oop is now passed in JavaThread | |
2340 | |
2341 // Prolog for exception case | |
2342 // All registers must be preserved because they might be used by LinearScan | |
2343 // Exceptiop oop and throwing PC are passed in JavaThread | |
2344 // tos: stack at point of call to method that threw the exception (i.e. only | |
2345 // args are on the stack, no return address) | |
2346 | |
2347 // make room on stack for the return address | |
2348 // It will be patched later with the throwing pc. The correct value is not | |
2349 // available now because loading it from memory would destroy registers. | |
304 | 2350 __ push(0); |
0 | 2351 |
2352 // Save everything in sight. | |
2353 | |
2354 // No need to update map as each call to save_live_registers will produce identical oopmap | |
926
c8e2135f7e30
6829127: Deoptimization Failure on Specjvm98 _227_mtrt with -XX:+DeoptimizeALot since Hs11 b01
cfang
parents:
628
diff
changeset
|
2355 (void) RegisterSaver::save_live_registers(masm, additional_words, &frame_size_in_words, false); |
0 | 2356 |
2357 // Now it is safe to overwrite any register | |
2358 | |
2359 // store the correct deoptimization type | |
304 | 2360 __ push(Deoptimization::Unpack_exception); |
0 | 2361 |
2362 // load throwing pc from JavaThread and patch it as the return address | |
2363 // of the current frame. Then clear the field in JavaThread | |
2364 __ get_thread(rdi); | |
304 | 2365 __ movptr(rdx, Address(rdi, JavaThread::exception_pc_offset())); |
2366 __ movptr(Address(rbp, wordSize), rdx); | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
304
diff
changeset
|
2367 __ movptr(Address(rdi, JavaThread::exception_pc_offset()), NULL_WORD); |
0 | 2368 |
2369 #ifdef ASSERT | |
2370 // verify that there is really an exception oop in JavaThread | |
304 | 2371 __ movptr(rax, Address(rdi, JavaThread::exception_oop_offset())); |
0 | 2372 __ verify_oop(rax); |
2373 | |
2374 // verify that there is no pending exception | |
2375 Label no_pending_exception; | |
304 | 2376 __ movptr(rax, Address(rdi, Thread::pending_exception_offset())); |
2377 __ testptr(rax, rax); | |
0 | 2378 __ jcc(Assembler::zero, no_pending_exception); |
2379 __ stop("must not have pending exception here"); | |
2380 __ bind(no_pending_exception); | |
2381 #endif | |
2382 | |
2383 __ bind(cont); | |
2384 | |
2385 // Compiled code leaves the floating point stack dirty, empty it. | |
2386 __ empty_FPU_stack(); | |
2387 | |
2388 | |
2389 // Call C code. Need thread and this frame, but NOT official VM entry | |
2390 // crud. We cannot block on this call, no GC can happen. | |
2391 __ get_thread(rcx); | |
304 | 2392 __ push(rcx); |
0 | 2393 // fetch_unroll_info needs to call last_java_frame() |
2394 __ set_last_Java_frame(rcx, noreg, noreg, NULL); | |
2395 | |
2396 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info))); | |
2397 | |
2398 // Need to have an oopmap that tells fetch_unroll_info where to | |
2399 // find any register it might need. | |
2400 | |
2401 oop_maps->add_gc_map( __ pc()-start, map); | |
2402 | |
2403 // Discard arg to fetch_unroll_info | |
304 | 2404 __ pop(rcx); |
0 | 2405 |
2406 __ get_thread(rcx); | |
2407 __ reset_last_Java_frame(rcx, false, false); | |
2408 | |
2409 // Load UnrollBlock into EDI | |
304 | 2410 __ mov(rdi, rax); |
0 | 2411 |
2412 // Move the unpack kind to a safe place in the UnrollBlock because | |
2413 // we are very short of registers | |
2414 | |
2415 Address unpack_kind(rdi, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes()); | |
2416 // retrieve the deopt kind from where we left it. | |
304 | 2417 __ pop(rax); |
0 | 2418 __ movl(unpack_kind, rax); // save the unpack_kind value |
2419 | |
2420 Label noException; | |
2421 __ cmpl(rax, Deoptimization::Unpack_exception); // Was exception pending? | |
2422 __ jcc(Assembler::notEqual, noException); | |
304 | 2423 __ movptr(rax, Address(rcx, JavaThread::exception_oop_offset())); |
2424 __ movptr(rdx, Address(rcx, JavaThread::exception_pc_offset())); | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
304
diff
changeset
|
2425 __ movptr(Address(rcx, JavaThread::exception_oop_offset()), NULL_WORD); |
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
304
diff
changeset
|
2426 __ movptr(Address(rcx, JavaThread::exception_pc_offset()), NULL_WORD); |
0 | 2427 |
2428 __ verify_oop(rax); | |
2429 | |
2430 // Overwrite the result registers with the exception results. | |
304 | 2431 __ movptr(Address(rsp, RegisterSaver::raxOffset()*wordSize), rax); |
2432 __ movptr(Address(rsp, RegisterSaver::rdxOffset()*wordSize), rdx); | |
0 | 2433 |
2434 __ bind(noException); | |
2435 | |
2436 // Stack is back to only having register save data on the stack. | |
2437 // Now restore the result registers. Everything else is either dead or captured | |
2438 // in the vframeArray. | |
2439 | |
2440 RegisterSaver::restore_result_registers(masm); | |
2441 | |
926
c8e2135f7e30
6829127: Deoptimization Failure on Specjvm98 _227_mtrt with -XX:+DeoptimizeALot since Hs11 b01
cfang
parents:
628
diff
changeset
|
2442 // Non standard control word may be leaked out through a safepoint blob, and we can |
c8e2135f7e30
6829127: Deoptimization Failure on Specjvm98 _227_mtrt with -XX:+DeoptimizeALot since Hs11 b01
cfang
parents:
628
diff
changeset
|
2443 // deopt at a poll point with the non standard control word. However, we should make |
c8e2135f7e30
6829127: Deoptimization Failure on Specjvm98 _227_mtrt with -XX:+DeoptimizeALot since Hs11 b01
cfang
parents:
628
diff
changeset
|
2444 // sure the control word is correct after restore_result_registers. |
c8e2135f7e30
6829127: Deoptimization Failure on Specjvm98 _227_mtrt with -XX:+DeoptimizeALot since Hs11 b01
cfang
parents:
628
diff
changeset
|
2445 __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); |
c8e2135f7e30
6829127: Deoptimization Failure on Specjvm98 _227_mtrt with -XX:+DeoptimizeALot since Hs11 b01
cfang
parents:
628
diff
changeset
|
2446 |
0 | 2447 // All of the register save area has been popped of the stack. Only the |
2448 // return address remains. | |
2449 | |
2450 // Pop all the frames we must move/replace. | |
2451 // | |
2452 // Frame picture (youngest to oldest) | |
2453 // 1: self-frame (no frame link) | |
2454 // 2: deopting frame (no frame link) | |
2455 // 3: caller of deopting frame (could be compiled/interpreted). | |
2456 // | |
2457 // Note: by leaving the return address of self-frame on the stack | |
2458 // and using the size of frame 2 to adjust the stack | |
2459 // when we are done the return to frame 3 will still be on the stack. | |
2460 | |
2461 // Pop deoptimized frame | |
304 | 2462 __ addptr(rsp, Address(rdi,Deoptimization::UnrollBlock::size_of_deoptimized_frame_offset_in_bytes())); |
0 | 2463 |
2464 // sp should be pointing at the return address to the caller (3) | |
2465 | |
2466 // Stack bang to make sure there's enough room for these interpreter frames. | |
2467 if (UseStackBanging) { | |
2468 __ movl(rbx, Address(rdi ,Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes())); | |
2469 __ bang_stack_size(rbx, rcx); | |
2470 } | |
2471 | |
2472 // Load array of frame pcs into ECX | |
304 | 2473 __ movptr(rcx,Address(rdi,Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes())); |
2474 | |
2475 __ pop(rsi); // trash the old pc | |
0 | 2476 |
2477 // Load array of frame sizes into ESI | |
304 | 2478 __ movptr(rsi,Address(rdi,Deoptimization::UnrollBlock::frame_sizes_offset_in_bytes())); |
0 | 2479 |
2480 Address counter(rdi, Deoptimization::UnrollBlock::counter_temp_offset_in_bytes()); | |
2481 | |
2482 __ movl(rbx, Address(rdi, Deoptimization::UnrollBlock::number_of_frames_offset_in_bytes())); | |
2483 __ movl(counter, rbx); | |
2484 | |
2485 // Pick up the initial fp we should save | |
304 | 2486 __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_fp_offset_in_bytes())); |
0 | 2487 |
2488 // Now adjust the caller's stack to make up for the extra locals | |
2489 // but record the original sp so that we can save it in the skeletal interpreter | |
2490 // frame and the stack walking of interpreter_sender will get the unextended sp | |
2491 // value and not the "real" sp value. | |
2492 | |
2493 Address sp_temp(rdi, Deoptimization::UnrollBlock::sender_sp_temp_offset_in_bytes()); | |
304 | 2494 __ movptr(sp_temp, rsp); |
2495 __ movl2ptr(rbx, Address(rdi, Deoptimization::UnrollBlock::caller_adjustment_offset_in_bytes())); | |
2496 __ subptr(rsp, rbx); | |
0 | 2497 |
2498 // Push interpreter frames in a loop | |
2499 Label loop; | |
2500 __ bind(loop); | |
304 | 2501 __ movptr(rbx, Address(rsi, 0)); // Load frame size |
0 | 2502 #ifdef CC_INTERP |
304 | 2503 __ subptr(rbx, 4*wordSize); // we'll push pc and ebp by hand and |
0 | 2504 #ifdef ASSERT |
304 | 2505 __ push(0xDEADDEAD); // Make a recognizable pattern |
2506 __ push(0xDEADDEAD); | |
0 | 2507 #else /* ASSERT */ |
304 | 2508 __ subptr(rsp, 2*wordSize); // skip the "static long no_param" |
0 | 2509 #endif /* ASSERT */ |
2510 #else /* CC_INTERP */ | |
304 | 2511 __ subptr(rbx, 2*wordSize); // we'll push pc and rbp, by hand |
0 | 2512 #endif /* CC_INTERP */ |
304 | 2513 __ pushptr(Address(rcx, 0)); // save return address |
0 | 2514 __ enter(); // save old & set new rbp, |
304 | 2515 __ subptr(rsp, rbx); // Prolog! |
2516 __ movptr(rbx, sp_temp); // sender's sp | |
0 | 2517 #ifdef CC_INTERP |
304 | 2518 __ movptr(Address(rbp, |
0 | 2519 -(sizeof(BytecodeInterpreter)) + in_bytes(byte_offset_of(BytecodeInterpreter, _sender_sp))), |
2520 rbx); // Make it walkable | |
2521 #else /* CC_INTERP */ | |
2522 // This value is corrected by layout_activation_impl | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
304
diff
changeset
|
2523 __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); |
304 | 2524 __ movptr(Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize), rbx); // Make it walkable |
0 | 2525 #endif /* CC_INTERP */ |
304 | 2526 __ movptr(sp_temp, rsp); // pass to next frame |
2527 __ addptr(rsi, wordSize); // Bump array pointer (sizes) | |
2528 __ addptr(rcx, wordSize); // Bump array pointer (pcs) | |
2529 __ decrementl(counter); // decrement counter | |
0 | 2530 __ jcc(Assembler::notZero, loop); |
304 | 2531 __ pushptr(Address(rcx, 0)); // save final return address |
0 | 2532 |
2533 // Re-push self-frame | |
2534 __ enter(); // save old & set new rbp, | |
2535 | |
2536 // Return address and rbp, are in place | |
2537 // We'll push additional args later. Just allocate a full sized | |
2538 // register save area | |
304 | 2539 __ subptr(rsp, (frame_size_in_words-additional_words - 2) * wordSize); |
0 | 2540 |
2541 // Restore frame locals after moving the frame | |
304 | 2542 __ movptr(Address(rsp, RegisterSaver::raxOffset()*wordSize), rax); |
2543 __ movptr(Address(rsp, RegisterSaver::rdxOffset()*wordSize), rdx); | |
0 | 2544 __ fstp_d(Address(rsp, RegisterSaver::fpResultOffset()*wordSize)); // Pop float stack and store in local |
2545 if( UseSSE>=2 ) __ movdbl(Address(rsp, RegisterSaver::xmm0Offset()*wordSize), xmm0); | |
2546 if( UseSSE==1 ) __ movflt(Address(rsp, RegisterSaver::xmm0Offset()*wordSize), xmm0); | |
2547 | |
2548 // Set up the args to unpack_frame | |
2549 | |
2550 __ pushl(unpack_kind); // get the unpack_kind value | |
2551 __ get_thread(rcx); | |
304 | 2552 __ push(rcx); |
0 | 2553 |
2554 // set last_Java_sp, last_Java_fp | |
2555 __ set_last_Java_frame(rcx, noreg, rbp, NULL); | |
2556 | |
2557 // Call C code. Need thread but NOT official VM entry | |
2558 // crud. We cannot block on this call, no GC can happen. Call should | |
2559 // restore return values to their stack-slots with the new SP. | |
2560 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames))); | |
2561 // Set an oopmap for the call site | |
2562 oop_maps->add_gc_map( __ pc()-start, new OopMap( frame_size_in_words, 0 )); | |
2563 | |
2564 // rax, contains the return result type | |
304 | 2565 __ push(rax); |
0 | 2566 |
2567 __ get_thread(rcx); | |
2568 __ reset_last_Java_frame(rcx, false, false); | |
2569 | |
2570 // Collect return values | |
304 | 2571 __ movptr(rax,Address(rsp, (RegisterSaver::raxOffset() + additional_words + 1)*wordSize)); |
2572 __ movptr(rdx,Address(rsp, (RegisterSaver::rdxOffset() + additional_words + 1)*wordSize)); | |
0 | 2573 |
2574 // Clear floating point stack before returning to interpreter | |
2575 __ empty_FPU_stack(); | |
2576 | |
2577 // Check if we should push the float or double return value. | |
2578 Label results_done, yes_double_value; | |
2579 __ cmpl(Address(rsp, 0), T_DOUBLE); | |
2580 __ jcc (Assembler::zero, yes_double_value); | |
2581 __ cmpl(Address(rsp, 0), T_FLOAT); | |
2582 __ jcc (Assembler::notZero, results_done); | |
2583 | |
2584 // return float value as expected by interpreter | |
2585 if( UseSSE>=1 ) __ movflt(xmm0, Address(rsp, (RegisterSaver::xmm0Offset() + additional_words + 1)*wordSize)); | |
2586 else __ fld_d(Address(rsp, (RegisterSaver::fpResultOffset() + additional_words + 1)*wordSize)); | |
2587 __ jmp(results_done); | |
2588 | |
2589 // return double value as expected by interpreter | |
2590 __ bind(yes_double_value); | |
2591 if( UseSSE>=2 ) __ movdbl(xmm0, Address(rsp, (RegisterSaver::xmm0Offset() + additional_words + 1)*wordSize)); | |
2592 else __ fld_d(Address(rsp, (RegisterSaver::fpResultOffset() + additional_words + 1)*wordSize)); | |
2593 | |
2594 __ bind(results_done); | |
2595 | |
2596 // Pop self-frame. | |
2597 __ leave(); // Epilog! | |
2598 | |
2599 // Jump to interpreter | |
2600 __ ret(0); | |
2601 | |
2602 // ------------- | |
2603 // make sure all code is generated | |
2604 masm->flush(); | |
2605 | |
2606 _deopt_blob = DeoptimizationBlob::create( &buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_in_words); | |
2607 _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset); | |
2608 } | |
2609 | |
2610 | |
2611 #ifdef COMPILER2 | |
2612 //------------------------------generate_uncommon_trap_blob-------------------- | |
2613 void SharedRuntime::generate_uncommon_trap_blob() { | |
2614 // allocate space for the code | |
2615 ResourceMark rm; | |
2616 // setup code generation tools | |
2617 CodeBuffer buffer("uncommon_trap_blob", 512, 512); | |
2618 MacroAssembler* masm = new MacroAssembler(&buffer); | |
2619 | |
2620 enum frame_layout { | |
2621 arg0_off, // thread sp + 0 // Arg location for | |
2622 arg1_off, // unloaded_class_index sp + 1 // calling C | |
2623 // The frame sender code expects that rbp will be in the "natural" place and | |
2624 // will override any oopMap setting for it. We must therefore force the layout | |
2625 // so that it agrees with the frame sender code. | |
2626 rbp_off, // callee saved register sp + 2 | |
2627 return_off, // slot for return address sp + 3 | |
2628 framesize | |
2629 }; | |
2630 | |
2631 address start = __ pc(); | |
2632 // Push self-frame. | |
304 | 2633 __ subptr(rsp, return_off*wordSize); // Epilog! |
0 | 2634 |
2635 // rbp, is an implicitly saved callee saved register (i.e. the calling | |
2636 // convention will save restore it in prolog/epilog) Other than that | |
2637 // there are no callee save registers no that adapter frames are gone. | |
304 | 2638 __ movptr(Address(rsp, rbp_off*wordSize), rbp); |
0 | 2639 |
2640 // Clear the floating point exception stack | |
2641 __ empty_FPU_stack(); | |
2642 | |
2643 // set last_Java_sp | |
2644 __ get_thread(rdx); | |
2645 __ set_last_Java_frame(rdx, noreg, noreg, NULL); | |
2646 | |
2647 // Call C code. Need thread but NOT official VM entry | |
2648 // crud. We cannot block on this call, no GC can happen. Call should | |
2649 // capture callee-saved registers as well as return values. | |
304 | 2650 __ movptr(Address(rsp, arg0_off*wordSize), rdx); |
0 | 2651 // argument already in ECX |
2652 __ movl(Address(rsp, arg1_off*wordSize),rcx); | |
2653 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap))); | |
2654 | |
2655 // Set an oopmap for the call site | |
2656 OopMapSet *oop_maps = new OopMapSet(); | |
2657 OopMap* map = new OopMap( framesize, 0 ); | |
2658 // No oopMap for rbp, it is known implicitly | |
2659 | |
2660 oop_maps->add_gc_map( __ pc()-start, map); | |
2661 | |
2662 __ get_thread(rcx); | |
2663 | |
2664 __ reset_last_Java_frame(rcx, false, false); | |
2665 | |
2666 // Load UnrollBlock into EDI | |
304 | 2667 __ movptr(rdi, rax); |
0 | 2668 |
2669 // Pop all the frames we must move/replace. | |
2670 // | |
2671 // Frame picture (youngest to oldest) | |
2672 // 1: self-frame (no frame link) | |
2673 // 2: deopting frame (no frame link) | |
2674 // 3: caller of deopting frame (could be compiled/interpreted). | |
2675 | |
2676 // Pop self-frame. We have no frame, and must rely only on EAX and ESP. | |
304 | 2677 __ addptr(rsp,(framesize-1)*wordSize); // Epilog! |
0 | 2678 |
2679 // Pop deoptimized frame | |
304 | 2680 __ movl2ptr(rcx, Address(rdi,Deoptimization::UnrollBlock::size_of_deoptimized_frame_offset_in_bytes())); |
2681 __ addptr(rsp, rcx); | |
0 | 2682 |
2683 // sp should be pointing at the return address to the caller (3) | |
2684 | |
2685 // Stack bang to make sure there's enough room for these interpreter frames. | |
2686 if (UseStackBanging) { | |
2687 __ movl(rbx, Address(rdi ,Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes())); | |
2688 __ bang_stack_size(rbx, rcx); | |
2689 } | |
2690 | |
2691 | |
2692 // Load array of frame pcs into ECX | |
2693 __ movl(rcx,Address(rdi,Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes())); | |
2694 | |
304 | 2695 __ pop(rsi); // trash the pc |
0 | 2696 |
2697 // Load array of frame sizes into ESI | |
304 | 2698 __ movptr(rsi,Address(rdi,Deoptimization::UnrollBlock::frame_sizes_offset_in_bytes())); |
0 | 2699 |
2700 Address counter(rdi, Deoptimization::UnrollBlock::counter_temp_offset_in_bytes()); | |
2701 | |
2702 __ movl(rbx, Address(rdi, Deoptimization::UnrollBlock::number_of_frames_offset_in_bytes())); | |
2703 __ movl(counter, rbx); | |
2704 | |
2705 // Pick up the initial fp we should save | |
304 | 2706 __ movptr(rbp, Address(rdi, Deoptimization::UnrollBlock::initial_fp_offset_in_bytes())); |
0 | 2707 |
2708 // Now adjust the caller's stack to make up for the extra locals | |
2709 // but record the original sp so that we can save it in the skeletal interpreter | |
2710 // frame and the stack walking of interpreter_sender will get the unextended sp | |
2711 // value and not the "real" sp value. | |
2712 | |
2713 Address sp_temp(rdi, Deoptimization::UnrollBlock::sender_sp_temp_offset_in_bytes()); | |
304 | 2714 __ movptr(sp_temp, rsp); |
2715 __ movl(rbx, Address(rdi, Deoptimization::UnrollBlock::caller_adjustment_offset_in_bytes())); | |
2716 __ subptr(rsp, rbx); | |
0 | 2717 |
2718 // Push interpreter frames in a loop | |
2719 Label loop; | |
2720 __ bind(loop); | |
304 | 2721 __ movptr(rbx, Address(rsi, 0)); // Load frame size |
0 | 2722 #ifdef CC_INTERP |
304 | 2723 __ subptr(rbx, 4*wordSize); // we'll push pc and ebp by hand and |
0 | 2724 #ifdef ASSERT |
304 | 2725 __ push(0xDEADDEAD); // Make a recognizable pattern |
2726 __ push(0xDEADDEAD); // (parm to RecursiveInterpreter...) | |
0 | 2727 #else /* ASSERT */ |
304 | 2728 __ subptr(rsp, 2*wordSize); // skip the "static long no_param" |
0 | 2729 #endif /* ASSERT */ |
2730 #else /* CC_INTERP */ | |
304 | 2731 __ subptr(rbx, 2*wordSize); // we'll push pc and rbp, by hand |
0 | 2732 #endif /* CC_INTERP */ |
304 | 2733 __ pushptr(Address(rcx, 0)); // save return address |
0 | 2734 __ enter(); // save old & set new rbp, |
304 | 2735 __ subptr(rsp, rbx); // Prolog! |
2736 __ movptr(rbx, sp_temp); // sender's sp | |
0 | 2737 #ifdef CC_INTERP |
304 | 2738 __ movptr(Address(rbp, |
0 | 2739 -(sizeof(BytecodeInterpreter)) + in_bytes(byte_offset_of(BytecodeInterpreter, _sender_sp))), |
2740 rbx); // Make it walkable | |
2741 #else /* CC_INTERP */ | |
2742 // This value is corrected by layout_activation_impl | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
304
diff
changeset
|
2743 __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD ); |
304 | 2744 __ movptr(Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize), rbx); // Make it walkable |
0 | 2745 #endif /* CC_INTERP */ |
304 | 2746 __ movptr(sp_temp, rsp); // pass to next frame |
2747 __ addptr(rsi, wordSize); // Bump array pointer (sizes) | |
2748 __ addptr(rcx, wordSize); // Bump array pointer (pcs) | |
2749 __ decrementl(counter); // decrement counter | |
0 | 2750 __ jcc(Assembler::notZero, loop); |
304 | 2751 __ pushptr(Address(rcx, 0)); // save final return address |
0 | 2752 |
2753 // Re-push self-frame | |
2754 __ enter(); // save old & set new rbp, | |
304 | 2755 __ subptr(rsp, (framesize-2) * wordSize); // Prolog! |
0 | 2756 |
2757 | |
2758 // set last_Java_sp, last_Java_fp | |
2759 __ get_thread(rdi); | |
2760 __ set_last_Java_frame(rdi, noreg, rbp, NULL); | |
2761 | |
2762 // Call C code. Need thread but NOT official VM entry | |
2763 // crud. We cannot block on this call, no GC can happen. Call should | |
2764 // restore return values to their stack-slots with the new SP. | |
304 | 2765 __ movptr(Address(rsp,arg0_off*wordSize),rdi); |
0 | 2766 __ movl(Address(rsp,arg1_off*wordSize), Deoptimization::Unpack_uncommon_trap); |
2767 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames))); | |
2768 // Set an oopmap for the call site | |
2769 oop_maps->add_gc_map( __ pc()-start, new OopMap( framesize, 0 ) ); | |
2770 | |
2771 __ get_thread(rdi); | |
2772 __ reset_last_Java_frame(rdi, true, false); | |
2773 | |
2774 // Pop self-frame. | |
2775 __ leave(); // Epilog! | |
2776 | |
2777 // Jump to interpreter | |
2778 __ ret(0); | |
2779 | |
2780 // ------------- | |
2781 // make sure all code is generated | |
2782 masm->flush(); | |
2783 | |
2784 _uncommon_trap_blob = UncommonTrapBlob::create(&buffer, oop_maps, framesize); | |
2785 } | |
2786 #endif // COMPILER2 | |
2787 | |
2788 //------------------------------generate_handler_blob------ | |
2789 // | |
2790 // Generate a special Compile2Runtime blob that saves all registers, | |
2791 // setup oopmap, and calls safepoint code to stop the compiled code for | |
2792 // a safepoint. | |
2793 // | |
2794 static SafepointBlob* generate_handler_blob(address call_ptr, bool cause_return) { | |
2795 | |
2796 // Account for thread arg in our frame | |
2797 const int additional_words = 1; | |
2798 int frame_size_in_words; | |
2799 | |
2800 assert (StubRoutines::forward_exception_entry() != NULL, "must be generated before"); | |
2801 | |
2802 ResourceMark rm; | |
2803 OopMapSet *oop_maps = new OopMapSet(); | |
2804 OopMap* map; | |
2805 | |
2806 // allocate space for the code | |
2807 // setup code generation tools | |
2808 CodeBuffer buffer("handler_blob", 1024, 512); | |
2809 MacroAssembler* masm = new MacroAssembler(&buffer); | |
2810 | |
2811 const Register java_thread = rdi; // callee-saved for VC++ | |
2812 address start = __ pc(); | |
2813 address call_pc = NULL; | |
2814 | |
2815 // If cause_return is true we are at a poll_return and there is | |
2816 // the return address on the stack to the caller on the nmethod | |
2817 // that is safepoint. We can leave this return on the stack and | |
2818 // effectively complete the return and safepoint in the caller. | |
2819 // Otherwise we push space for a return address that the safepoint | |
2820 // handler will install later to make the stack walking sensible. | |
2821 if( !cause_return ) | |
304 | 2822 __ push(rbx); // Make room for return address (or push it again) |
0 | 2823 |
2824 map = RegisterSaver::save_live_registers(masm, additional_words, &frame_size_in_words, false); | |
2825 | |
2826 // The following is basically a call_VM. However, we need the precise | |
2827 // address of the call in order to generate an oopmap. Hence, we do all the | |
2828 // work ourselves. | |
2829 | |
2830 // Push thread argument and setup last_Java_sp | |
2831 __ get_thread(java_thread); | |
304 | 2832 __ push(java_thread); |
0 | 2833 __ set_last_Java_frame(java_thread, noreg, noreg, NULL); |
2834 | |
2835 // if this was not a poll_return then we need to correct the return address now. | |
2836 if( !cause_return ) { | |
304 | 2837 __ movptr(rax, Address(java_thread, JavaThread::saved_exception_pc_offset())); |
2838 __ movptr(Address(rbp, wordSize), rax); | |
0 | 2839 } |
2840 | |
2841 // do the call | |
2842 __ call(RuntimeAddress(call_ptr)); | |
2843 | |
2844 // Set an oopmap for the call site. This oopmap will map all | |
2845 // oop-registers and debug-info registers as callee-saved. This | |
2846 // will allow deoptimization at this safepoint to find all possible | |
2847 // debug-info recordings, as well as let GC find all oops. | |
2848 | |
2849 oop_maps->add_gc_map( __ pc() - start, map); | |
2850 | |
2851 // Discard arg | |
304 | 2852 __ pop(rcx); |
0 | 2853 |
2854 Label noException; | |
2855 | |
2856 // Clear last_Java_sp again | |
2857 __ get_thread(java_thread); | |
2858 __ reset_last_Java_frame(java_thread, false, false); | |
2859 | |
304 | 2860 __ cmpptr(Address(java_thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD); |
0 | 2861 __ jcc(Assembler::equal, noException); |
2862 | |
2863 // Exception pending | |
2864 | |
2865 RegisterSaver::restore_live_registers(masm); | |
2866 | |
2867 __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); | |
2868 | |
2869 __ bind(noException); | |
2870 | |
2871 // Normal exit, register restoring and exit | |
2872 RegisterSaver::restore_live_registers(masm); | |
2873 | |
2874 __ ret(0); | |
2875 | |
2876 // make sure all code is generated | |
2877 masm->flush(); | |
2878 | |
2879 // Fill-out other meta info | |
2880 return SafepointBlob::create(&buffer, oop_maps, frame_size_in_words); | |
2881 } | |
2882 | |
2883 // | |
2884 // generate_resolve_blob - call resolution (static/virtual/opt-virtual/ic-miss | |
2885 // | |
2886 // Generate a stub that calls into vm to find out the proper destination | |
2887 // of a java call. All the argument registers are live at this point | |
2888 // but since this is generic code we don't know what they are and the caller | |
2889 // must do any gc of the args. | |
2890 // | |
2891 static RuntimeStub* generate_resolve_blob(address destination, const char* name) { | |
2892 assert (StubRoutines::forward_exception_entry() != NULL, "must be generated before"); | |
2893 | |
2894 // allocate space for the code | |
2895 ResourceMark rm; | |
2896 | |
2897 CodeBuffer buffer(name, 1000, 512); | |
2898 MacroAssembler* masm = new MacroAssembler(&buffer); | |
2899 | |
2900 int frame_size_words; | |
2901 enum frame_layout { | |
2902 thread_off, | |
2903 extra_words }; | |
2904 | |
2905 OopMapSet *oop_maps = new OopMapSet(); | |
2906 OopMap* map = NULL; | |
2907 | |
2908 int start = __ offset(); | |
2909 | |
2910 map = RegisterSaver::save_live_registers(masm, extra_words, &frame_size_words); | |
2911 | |
2912 int frame_complete = __ offset(); | |
2913 | |
2914 const Register thread = rdi; | |
2915 __ get_thread(rdi); | |
2916 | |
304 | 2917 __ push(thread); |
0 | 2918 __ set_last_Java_frame(thread, noreg, rbp, NULL); |
2919 | |
2920 __ call(RuntimeAddress(destination)); | |
2921 | |
2922 | |
2923 // Set an oopmap for the call site. | |
2924 // We need this not only for callee-saved registers, but also for volatile | |
2925 // registers that the compiler might be keeping live across a safepoint. | |
2926 | |
2927 oop_maps->add_gc_map( __ offset() - start, map); | |
2928 | |
2929 // rax, contains the address we are going to jump to assuming no exception got installed | |
2930 | |
304 | 2931 __ addptr(rsp, wordSize); |
0 | 2932 |
2933 // clear last_Java_sp | |
2934 __ reset_last_Java_frame(thread, true, false); | |
2935 // check for pending exceptions | |
2936 Label pending; | |
304 | 2937 __ cmpptr(Address(thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD); |
0 | 2938 __ jcc(Assembler::notEqual, pending); |
2939 | |
2940 // get the returned methodOop | |
304 | 2941 __ movptr(rbx, Address(thread, JavaThread::vm_result_offset())); |
2942 __ movptr(Address(rsp, RegisterSaver::rbx_offset() * wordSize), rbx); | |
2943 | |
2944 __ movptr(Address(rsp, RegisterSaver::rax_offset() * wordSize), rax); | |
0 | 2945 |
2946 RegisterSaver::restore_live_registers(masm); | |
2947 | |
2948 // We are back the the original state on entry and ready to go. | |
2949 | |
2950 __ jmp(rax); | |
2951 | |
2952 // Pending exception after the safepoint | |
2953 | |
2954 __ bind(pending); | |
2955 | |
2956 RegisterSaver::restore_live_registers(masm); | |
2957 | |
2958 // exception pending => remove activation and forward to exception handler | |
2959 | |
2960 __ get_thread(thread); | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
304
diff
changeset
|
2961 __ movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); |
304 | 2962 __ movptr(rax, Address(thread, Thread::pending_exception_offset())); |
0 | 2963 __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); |
2964 | |
2965 // ------------- | |
2966 // make sure all code is generated | |
2967 masm->flush(); | |
2968 | |
2969 // return the blob | |
2970 // frame_size_words or bytes?? | |
2971 return RuntimeStub::new_runtime_stub(name, &buffer, frame_complete, frame_size_words, oop_maps, true); | |
2972 } | |
2973 | |
2974 void SharedRuntime::generate_stubs() { | |
2975 | |
2976 _wrong_method_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method), | |
2977 "wrong_method_stub"); | |
2978 | |
2979 _ic_miss_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::handle_wrong_method_ic_miss), | |
2980 "ic_miss_stub"); | |
2981 | |
2982 _resolve_opt_virtual_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_opt_virtual_call_C), | |
2983 "resolve_opt_virtual_call"); | |
2984 | |
2985 _resolve_virtual_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_virtual_call_C), | |
2986 "resolve_virtual_call"); | |
2987 | |
2988 _resolve_static_call_blob = generate_resolve_blob(CAST_FROM_FN_PTR(address, SharedRuntime::resolve_static_call_C), | |
2989 "resolve_static_call"); | |
2990 | |
2991 _polling_page_safepoint_handler_blob = | |
2992 generate_handler_blob(CAST_FROM_FN_PTR(address, | |
2993 SafepointSynchronize::handle_polling_page_exception), false); | |
2994 | |
2995 _polling_page_return_handler_blob = | |
2996 generate_handler_blob(CAST_FROM_FN_PTR(address, | |
2997 SafepointSynchronize::handle_polling_page_exception), true); | |
2998 | |
2999 generate_deopt_blob(); | |
3000 #ifdef COMPILER2 | |
3001 generate_uncommon_trap_blob(); | |
3002 #endif // COMPILER2 | |
3003 } |