Mercurial > hg > graal-compiler
annotate src/cpu/x86/vm/c1_Runtime1_x86.cpp @ 2007:5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
Summary: C1 with profiling doesn't check whether the MDO has been really allocated, which can silently fail if the perm gen is full. The solution is to check if the allocation failed and bailout out of inlining or compilation.
Reviewed-by: kvn, never
author | iveresov |
---|---|
date | Thu, 02 Dec 2010 17:21:12 -0800 |
parents | ac637b7220d1 |
children | 06f017f7daa7 b1a2afa37ec4 |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1368
diff
changeset
|
2 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1368
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1368
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:
1368
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "c1/c1_Defs.hpp" | |
27 #include "c1/c1_MacroAssembler.hpp" | |
28 #include "c1/c1_Runtime1.hpp" | |
29 #include "interpreter/interpreter.hpp" | |
30 #include "nativeInst_x86.hpp" | |
31 #include "oops/compiledICHolderOop.hpp" | |
32 #include "oops/oop.inline.hpp" | |
33 #include "prims/jvmtiExport.hpp" | |
34 #include "register_x86.hpp" | |
35 #include "runtime/sharedRuntime.hpp" | |
36 #include "runtime/signature.hpp" | |
37 #include "runtime/vframeArray.hpp" | |
38 #include "vmreg_x86.inline.hpp" | |
0 | 39 |
40 | |
41 // Implementation of StubAssembler | |
42 | |
43 int StubAssembler::call_RT(Register oop_result1, Register oop_result2, address entry, int args_size) { | |
44 // setup registers | |
304 | 45 const Register thread = NOT_LP64(rdi) LP64_ONLY(r15_thread); // is callee-saved register (Visual C++ calling conventions) |
0 | 46 assert(!(oop_result1->is_valid() || oop_result2->is_valid()) || oop_result1 != oop_result2, "registers must be different"); |
47 assert(oop_result1 != thread && oop_result2 != thread, "registers must be different"); | |
48 assert(args_size >= 0, "illegal args_size"); | |
49 | |
304 | 50 #ifdef _LP64 |
51 mov(c_rarg0, thread); | |
52 set_num_rt_args(0); // Nothing on stack | |
53 #else | |
0 | 54 set_num_rt_args(1 + args_size); |
55 | |
56 // push java thread (becomes first argument of C function) | |
57 get_thread(thread); | |
304 | 58 push(thread); |
59 #endif // _LP64 | |
0 | 60 |
61 set_last_Java_frame(thread, noreg, rbp, NULL); | |
304 | 62 |
0 | 63 // do the call |
64 call(RuntimeAddress(entry)); | |
65 int call_offset = offset(); | |
66 // verify callee-saved register | |
67 #ifdef ASSERT | |
68 guarantee(thread != rax, "change this code"); | |
304 | 69 push(rax); |
0 | 70 { Label L; |
71 get_thread(rax); | |
304 | 72 cmpptr(thread, rax); |
0 | 73 jcc(Assembler::equal, L); |
74 int3(); | |
75 stop("StubAssembler::call_RT: rdi not callee saved?"); | |
76 bind(L); | |
77 } | |
304 | 78 pop(rax); |
0 | 79 #endif |
80 reset_last_Java_frame(thread, true, false); | |
81 | |
82 // discard thread and arguments | |
304 | 83 NOT_LP64(addptr(rsp, num_rt_args()*BytesPerWord)); |
0 | 84 |
85 // check for pending exceptions | |
86 { Label L; | |
304 | 87 cmpptr(Address(thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD); |
0 | 88 jcc(Assembler::equal, L); |
89 // exception pending => remove activation and forward to exception handler | |
304 | 90 movptr(rax, Address(thread, Thread::pending_exception_offset())); |
0 | 91 // make sure that the vm_results are cleared |
92 if (oop_result1->is_valid()) { | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
380
diff
changeset
|
93 movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); |
0 | 94 } |
95 if (oop_result2->is_valid()) { | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
380
diff
changeset
|
96 movptr(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD); |
0 | 97 } |
98 if (frame_size() == no_frame_size) { | |
99 leave(); | |
100 jump(RuntimeAddress(StubRoutines::forward_exception_entry())); | |
101 } else if (_stub_id == Runtime1::forward_exception_id) { | |
102 should_not_reach_here(); | |
103 } else { | |
104 jump(RuntimeAddress(Runtime1::entry_for(Runtime1::forward_exception_id))); | |
105 } | |
106 bind(L); | |
107 } | |
108 // get oop results if there are any and reset the values in the thread | |
109 if (oop_result1->is_valid()) { | |
304 | 110 movptr(oop_result1, Address(thread, JavaThread::vm_result_offset())); |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
380
diff
changeset
|
111 movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); |
0 | 112 verify_oop(oop_result1); |
113 } | |
114 if (oop_result2->is_valid()) { | |
304 | 115 movptr(oop_result2, Address(thread, JavaThread::vm_result_2_offset())); |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
380
diff
changeset
|
116 movptr(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD); |
0 | 117 verify_oop(oop_result2); |
118 } | |
119 return call_offset; | |
120 } | |
121 | |
122 | |
123 int StubAssembler::call_RT(Register oop_result1, Register oop_result2, address entry, Register arg1) { | |
304 | 124 #ifdef _LP64 |
125 mov(c_rarg1, arg1); | |
126 #else | |
127 push(arg1); | |
128 #endif // _LP64 | |
0 | 129 return call_RT(oop_result1, oop_result2, entry, 1); |
130 } | |
131 | |
132 | |
133 int StubAssembler::call_RT(Register oop_result1, Register oop_result2, address entry, Register arg1, Register arg2) { | |
304 | 134 #ifdef _LP64 |
135 if (c_rarg1 == arg2) { | |
136 if (c_rarg2 == arg1) { | |
137 xchgq(arg1, arg2); | |
138 } else { | |
139 mov(c_rarg2, arg2); | |
140 mov(c_rarg1, arg1); | |
141 } | |
142 } else { | |
143 mov(c_rarg1, arg1); | |
144 mov(c_rarg2, arg2); | |
145 } | |
146 #else | |
147 push(arg2); | |
148 push(arg1); | |
149 #endif // _LP64 | |
0 | 150 return call_RT(oop_result1, oop_result2, entry, 2); |
151 } | |
152 | |
153 | |
154 int StubAssembler::call_RT(Register oop_result1, Register oop_result2, address entry, Register arg1, Register arg2, Register arg3) { | |
304 | 155 #ifdef _LP64 |
156 // if there is any conflict use the stack | |
157 if (arg1 == c_rarg2 || arg1 == c_rarg3 || | |
158 arg2 == c_rarg1 || arg1 == c_rarg3 || | |
159 arg3 == c_rarg1 || arg1 == c_rarg2) { | |
160 push(arg3); | |
161 push(arg2); | |
162 push(arg1); | |
163 pop(c_rarg1); | |
164 pop(c_rarg2); | |
165 pop(c_rarg3); | |
166 } else { | |
167 mov(c_rarg1, arg1); | |
168 mov(c_rarg2, arg2); | |
169 mov(c_rarg3, arg3); | |
170 } | |
171 #else | |
172 push(arg3); | |
173 push(arg2); | |
174 push(arg1); | |
175 #endif // _LP64 | |
0 | 176 return call_RT(oop_result1, oop_result2, entry, 3); |
177 } | |
178 | |
179 | |
180 // Implementation of StubFrame | |
181 | |
182 class StubFrame: public StackObj { | |
183 private: | |
184 StubAssembler* _sasm; | |
185 | |
186 public: | |
187 StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments); | |
188 void load_argument(int offset_in_words, Register reg); | |
189 | |
190 ~StubFrame(); | |
191 }; | |
192 | |
193 | |
194 #define __ _sasm-> | |
195 | |
196 StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments) { | |
197 _sasm = sasm; | |
198 __ set_info(name, must_gc_arguments); | |
199 __ enter(); | |
200 } | |
201 | |
202 // load parameters that were stored with LIR_Assembler::store_parameter | |
203 // Note: offsets for store_parameter and load_argument must match | |
204 void StubFrame::load_argument(int offset_in_words, Register reg) { | |
205 // rbp, + 0: link | |
206 // + 1: return address | |
207 // + 2: argument with offset 0 | |
208 // + 3: argument with offset 1 | |
209 // + 4: ... | |
210 | |
304 | 211 __ movptr(reg, Address(rbp, (offset_in_words + 2) * BytesPerWord)); |
0 | 212 } |
213 | |
214 | |
215 StubFrame::~StubFrame() { | |
216 __ leave(); | |
217 __ ret(0); | |
218 } | |
219 | |
220 #undef __ | |
221 | |
222 | |
223 // Implementation of Runtime1 | |
224 | |
225 #define __ sasm-> | |
226 | |
304 | 227 const int float_regs_as_doubles_size_in_slots = pd_nof_fpu_regs_frame_map * 2; |
228 const int xmm_regs_as_doubles_size_in_slots = FrameMap::nof_xmm_regs * 2; | |
0 | 229 |
230 // Stack layout for saving/restoring all the registers needed during a runtime | |
231 // call (this includes deoptimization) | |
232 // Note: note that users of this frame may well have arguments to some runtime | |
233 // while these values are on the stack. These positions neglect those arguments | |
234 // but the code in save_live_registers will take the argument count into | |
235 // account. | |
236 // | |
304 | 237 #ifdef _LP64 |
238 #define SLOT2(x) x, | |
239 #define SLOT_PER_WORD 2 | |
240 #else | |
241 #define SLOT2(x) | |
242 #define SLOT_PER_WORD 1 | |
243 #endif // _LP64 | |
244 | |
0 | 245 enum reg_save_layout { |
304 | 246 // 64bit needs to keep stack 16 byte aligned. So we add some alignment dummies to make that |
247 // happen and will assert if the stack size we create is misaligned | |
248 #ifdef _LP64 | |
249 align_dummy_0, align_dummy_1, | |
250 #endif // _LP64 | |
251 dummy1, SLOT2(dummy1H) // 0, 4 | |
252 dummy2, SLOT2(dummy2H) // 8, 12 | |
0 | 253 // Two temps to be used as needed by users of save/restore callee registers |
304 | 254 temp_2_off, SLOT2(temp_2H_off) // 16, 20 |
255 temp_1_off, SLOT2(temp_1H_off) // 24, 28 | |
256 xmm_regs_as_doubles_off, // 32 | |
257 float_regs_as_doubles_off = xmm_regs_as_doubles_off + xmm_regs_as_doubles_size_in_slots, // 160 | |
258 fpu_state_off = float_regs_as_doubles_off + float_regs_as_doubles_size_in_slots, // 224 | |
259 // fpu_state_end_off is exclusive | |
260 fpu_state_end_off = fpu_state_off + (FPUStateSizeInWords / SLOT_PER_WORD), // 352 | |
261 marker = fpu_state_end_off, SLOT2(markerH) // 352, 356 | |
262 extra_space_offset, // 360 | |
263 #ifdef _LP64 | |
264 r15_off = extra_space_offset, r15H_off, // 360, 364 | |
265 r14_off, r14H_off, // 368, 372 | |
266 r13_off, r13H_off, // 376, 380 | |
267 r12_off, r12H_off, // 384, 388 | |
268 r11_off, r11H_off, // 392, 396 | |
269 r10_off, r10H_off, // 400, 404 | |
270 r9_off, r9H_off, // 408, 412 | |
271 r8_off, r8H_off, // 416, 420 | |
272 rdi_off, rdiH_off, // 424, 428 | |
273 #else | |
0 | 274 rdi_off = extra_space_offset, |
304 | 275 #endif // _LP64 |
276 rsi_off, SLOT2(rsiH_off) // 432, 436 | |
277 rbp_off, SLOT2(rbpH_off) // 440, 444 | |
278 rsp_off, SLOT2(rspH_off) // 448, 452 | |
279 rbx_off, SLOT2(rbxH_off) // 456, 460 | |
280 rdx_off, SLOT2(rdxH_off) // 464, 468 | |
281 rcx_off, SLOT2(rcxH_off) // 472, 476 | |
282 rax_off, SLOT2(raxH_off) // 480, 484 | |
283 saved_rbp_off, SLOT2(saved_rbpH_off) // 488, 492 | |
284 return_off, SLOT2(returnH_off) // 496, 500 | |
285 reg_save_frame_size, // As noted: neglects any parameters to runtime // 504 | |
286 | |
287 #ifdef _WIN64 | |
288 c_rarg0_off = rcx_off, | |
289 #else | |
290 c_rarg0_off = rdi_off, | |
291 #endif // WIN64 | |
0 | 292 |
293 // equates | |
294 | |
295 // illegal instruction handler | |
296 continue_dest_off = temp_1_off, | |
297 | |
298 // deoptimization equates | |
299 fp0_off = float_regs_as_doubles_off, // slot for java float/double return value | |
300 xmm0_off = xmm_regs_as_doubles_off, // slot for java float/double return value | |
301 deopt_type = temp_2_off, // slot for type of deopt in progress | |
302 ret_type = temp_1_off // slot for return type | |
303 }; | |
304 | |
305 | |
306 | |
307 // Save off registers which might be killed by calls into the runtime. | |
308 // Tries to smart of about FP registers. In particular we separate | |
309 // saving and describing the FPU registers for deoptimization since we | |
310 // have to save the FPU registers twice if we describe them and on P4 | |
311 // saving FPU registers which don't contain anything appears | |
312 // expensive. The deopt blob is the only thing which needs to | |
313 // describe FPU registers. In all other cases it should be sufficient | |
314 // to simply save their current value. | |
315 | |
316 static OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args, | |
317 bool save_fpu_registers = true) { | |
304 | 318 |
319 // In 64bit all the args are in regs so there are no additional stack slots | |
320 LP64_ONLY(num_rt_args = 0); | |
321 LP64_ONLY(assert((reg_save_frame_size * VMRegImpl::stack_slot_size) % 16 == 0, "must be 16 byte aligned");) | |
322 int frame_size_in_slots = reg_save_frame_size + num_rt_args; // args + thread | |
323 sasm->set_frame_size(frame_size_in_slots / VMRegImpl::slots_per_word ); | |
0 | 324 |
325 // record saved value locations in an OopMap | |
326 // locations are offsets from sp after runtime call; num_rt_args is number of arguments in call, including thread | |
304 | 327 OopMap* map = new OopMap(frame_size_in_slots, 0); |
0 | 328 map->set_callee_saved(VMRegImpl::stack2reg(rax_off + num_rt_args), rax->as_VMReg()); |
329 map->set_callee_saved(VMRegImpl::stack2reg(rcx_off + num_rt_args), rcx->as_VMReg()); | |
330 map->set_callee_saved(VMRegImpl::stack2reg(rdx_off + num_rt_args), rdx->as_VMReg()); | |
331 map->set_callee_saved(VMRegImpl::stack2reg(rbx_off + num_rt_args), rbx->as_VMReg()); | |
332 map->set_callee_saved(VMRegImpl::stack2reg(rsi_off + num_rt_args), rsi->as_VMReg()); | |
333 map->set_callee_saved(VMRegImpl::stack2reg(rdi_off + num_rt_args), rdi->as_VMReg()); | |
304 | 334 #ifdef _LP64 |
335 map->set_callee_saved(VMRegImpl::stack2reg(r8_off + num_rt_args), r8->as_VMReg()); | |
336 map->set_callee_saved(VMRegImpl::stack2reg(r9_off + num_rt_args), r9->as_VMReg()); | |
337 map->set_callee_saved(VMRegImpl::stack2reg(r10_off + num_rt_args), r10->as_VMReg()); | |
338 map->set_callee_saved(VMRegImpl::stack2reg(r11_off + num_rt_args), r11->as_VMReg()); | |
339 map->set_callee_saved(VMRegImpl::stack2reg(r12_off + num_rt_args), r12->as_VMReg()); | |
340 map->set_callee_saved(VMRegImpl::stack2reg(r13_off + num_rt_args), r13->as_VMReg()); | |
341 map->set_callee_saved(VMRegImpl::stack2reg(r14_off + num_rt_args), r14->as_VMReg()); | |
342 map->set_callee_saved(VMRegImpl::stack2reg(r15_off + num_rt_args), r15->as_VMReg()); | |
343 | |
344 // This is stupid but needed. | |
345 map->set_callee_saved(VMRegImpl::stack2reg(raxH_off + num_rt_args), rax->as_VMReg()->next()); | |
346 map->set_callee_saved(VMRegImpl::stack2reg(rcxH_off + num_rt_args), rcx->as_VMReg()->next()); | |
347 map->set_callee_saved(VMRegImpl::stack2reg(rdxH_off + num_rt_args), rdx->as_VMReg()->next()); | |
348 map->set_callee_saved(VMRegImpl::stack2reg(rbxH_off + num_rt_args), rbx->as_VMReg()->next()); | |
349 map->set_callee_saved(VMRegImpl::stack2reg(rsiH_off + num_rt_args), rsi->as_VMReg()->next()); | |
350 map->set_callee_saved(VMRegImpl::stack2reg(rdiH_off + num_rt_args), rdi->as_VMReg()->next()); | |
351 | |
352 map->set_callee_saved(VMRegImpl::stack2reg(r8H_off + num_rt_args), r8->as_VMReg()->next()); | |
353 map->set_callee_saved(VMRegImpl::stack2reg(r9H_off + num_rt_args), r9->as_VMReg()->next()); | |
354 map->set_callee_saved(VMRegImpl::stack2reg(r10H_off + num_rt_args), r10->as_VMReg()->next()); | |
355 map->set_callee_saved(VMRegImpl::stack2reg(r11H_off + num_rt_args), r11->as_VMReg()->next()); | |
356 map->set_callee_saved(VMRegImpl::stack2reg(r12H_off + num_rt_args), r12->as_VMReg()->next()); | |
357 map->set_callee_saved(VMRegImpl::stack2reg(r13H_off + num_rt_args), r13->as_VMReg()->next()); | |
358 map->set_callee_saved(VMRegImpl::stack2reg(r14H_off + num_rt_args), r14->as_VMReg()->next()); | |
359 map->set_callee_saved(VMRegImpl::stack2reg(r15H_off + num_rt_args), r15->as_VMReg()->next()); | |
360 #endif // _LP64 | |
0 | 361 |
362 if (save_fpu_registers) { | |
363 if (UseSSE < 2) { | |
364 int fpu_off = float_regs_as_doubles_off; | |
365 for (int n = 0; n < FrameMap::nof_fpu_regs; n++) { | |
366 VMReg fpu_name_0 = FrameMap::fpu_regname(n); | |
367 map->set_callee_saved(VMRegImpl::stack2reg(fpu_off + num_rt_args), fpu_name_0); | |
368 // %%% This is really a waste but we'll keep things as they were for now | |
369 if (true) { | |
370 map->set_callee_saved(VMRegImpl::stack2reg(fpu_off + 1 + num_rt_args), fpu_name_0->next()); | |
371 } | |
372 fpu_off += 2; | |
373 } | |
374 assert(fpu_off == fpu_state_off, "incorrect number of fpu stack slots"); | |
375 } | |
376 | |
377 if (UseSSE >= 2) { | |
378 int xmm_off = xmm_regs_as_doubles_off; | |
379 for (int n = 0; n < FrameMap::nof_xmm_regs; n++) { | |
380 VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg(); | |
381 map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0); | |
382 // %%% This is really a waste but we'll keep things as they were for now | |
383 if (true) { | |
384 map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + 1 + num_rt_args), xmm_name_0->next()); | |
385 } | |
386 xmm_off += 2; | |
387 } | |
388 assert(xmm_off == float_regs_as_doubles_off, "incorrect number of xmm registers"); | |
389 | |
390 } else if (UseSSE == 1) { | |
391 int xmm_off = xmm_regs_as_doubles_off; | |
392 for (int n = 0; n < FrameMap::nof_xmm_regs; n++) { | |
393 VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg(); | |
394 map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0); | |
395 xmm_off += 2; | |
396 } | |
397 assert(xmm_off == float_regs_as_doubles_off, "incorrect number of xmm registers"); | |
398 } | |
399 } | |
400 | |
401 return map; | |
402 } | |
403 | |
404 static OopMap* save_live_registers(StubAssembler* sasm, int num_rt_args, | |
405 bool save_fpu_registers = true) { | |
406 __ block_comment("save_live_registers"); | |
407 | |
304 | 408 // 64bit passes the args in regs to the c++ runtime |
409 int frame_size_in_slots = reg_save_frame_size NOT_LP64(+ num_rt_args); // args + thread | |
0 | 410 // frame_size = round_to(frame_size, 4); |
304 | 411 sasm->set_frame_size(frame_size_in_slots / VMRegImpl::slots_per_word ); |
0 | 412 |
304 | 413 __ pusha(); // integer registers |
0 | 414 |
415 // assert(float_regs_as_doubles_off % 2 == 0, "misaligned offset"); | |
416 // assert(xmm_regs_as_doubles_off % 2 == 0, "misaligned offset"); | |
417 | |
304 | 418 __ subptr(rsp, extra_space_offset * VMRegImpl::stack_slot_size); |
0 | 419 |
420 #ifdef ASSERT | |
304 | 421 __ movptr(Address(rsp, marker * VMRegImpl::stack_slot_size), (int32_t)0xfeedbeef); |
0 | 422 #endif |
423 | |
424 if (save_fpu_registers) { | |
425 if (UseSSE < 2) { | |
426 // save FPU stack | |
304 | 427 __ fnsave(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size)); |
0 | 428 __ fwait(); |
429 | |
430 #ifdef ASSERT | |
431 Label ok; | |
304 | 432 __ cmpw(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size), StubRoutines::fpu_cntrl_wrd_std()); |
0 | 433 __ jccb(Assembler::equal, ok); |
434 __ stop("corrupted control word detected"); | |
435 __ bind(ok); | |
436 #endif | |
437 | |
438 // Reset the control word to guard against exceptions being unmasked | |
439 // since fstp_d can cause FPU stack underflow exceptions. Write it | |
440 // into the on stack copy and then reload that to make sure that the | |
441 // current and future values are correct. | |
304 | 442 __ movw(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size), StubRoutines::fpu_cntrl_wrd_std()); |
443 __ frstor(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size)); | |
0 | 444 |
445 // Save the FPU registers in de-opt-able form | |
304 | 446 __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0)); |
447 __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8)); | |
448 __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16)); | |
449 __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24)); | |
450 __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32)); | |
451 __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40)); | |
452 __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48)); | |
453 __ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56)); | |
0 | 454 } |
455 | |
456 if (UseSSE >= 2) { | |
457 // save XMM registers | |
458 // XMM registers can contain float or double values, but this is not known here, | |
459 // so always save them as doubles. | |
460 // note that float values are _not_ converted automatically, so for float values | |
461 // the second word contains only garbage data. | |
304 | 462 __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0), xmm0); |
463 __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8), xmm1); | |
464 __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16), xmm2); | |
465 __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24), xmm3); | |
466 __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32), xmm4); | |
467 __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40), xmm5); | |
468 __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48), xmm6); | |
469 __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56), xmm7); | |
470 #ifdef _LP64 | |
471 __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 64), xmm8); | |
472 __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 72), xmm9); | |
473 __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 80), xmm10); | |
474 __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 88), xmm11); | |
475 __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 96), xmm12); | |
476 __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 104), xmm13); | |
477 __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 112), xmm14); | |
478 __ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 120), xmm15); | |
479 #endif // _LP64 | |
0 | 480 } else if (UseSSE == 1) { |
481 // save XMM registers as float because double not supported without SSE2 | |
304 | 482 __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0), xmm0); |
483 __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8), xmm1); | |
484 __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16), xmm2); | |
485 __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24), xmm3); | |
486 __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32), xmm4); | |
487 __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40), xmm5); | |
488 __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48), xmm6); | |
489 __ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56), xmm7); | |
0 | 490 } |
491 } | |
492 | |
493 // FPU stack must be empty now | |
494 __ verify_FPU(0, "save_live_registers"); | |
495 | |
496 return generate_oop_map(sasm, num_rt_args, save_fpu_registers); | |
497 } | |
498 | |
499 | |
500 static void restore_fpu(StubAssembler* sasm, bool restore_fpu_registers = true) { | |
501 if (restore_fpu_registers) { | |
502 if (UseSSE >= 2) { | |
503 // restore XMM registers | |
304 | 504 __ movdbl(xmm0, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0)); |
505 __ movdbl(xmm1, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8)); | |
506 __ movdbl(xmm2, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16)); | |
507 __ movdbl(xmm3, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24)); | |
508 __ movdbl(xmm4, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32)); | |
509 __ movdbl(xmm5, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40)); | |
510 __ movdbl(xmm6, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48)); | |
511 __ movdbl(xmm7, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56)); | |
512 #ifdef _LP64 | |
513 __ movdbl(xmm8, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 64)); | |
514 __ movdbl(xmm9, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 72)); | |
515 __ movdbl(xmm10, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 80)); | |
516 __ movdbl(xmm11, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 88)); | |
517 __ movdbl(xmm12, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 96)); | |
518 __ movdbl(xmm13, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 104)); | |
519 __ movdbl(xmm14, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 112)); | |
520 __ movdbl(xmm15, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 120)); | |
521 #endif // _LP64 | |
0 | 522 } else if (UseSSE == 1) { |
523 // restore XMM registers | |
304 | 524 __ movflt(xmm0, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 0)); |
525 __ movflt(xmm1, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 8)); | |
526 __ movflt(xmm2, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 16)); | |
527 __ movflt(xmm3, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 24)); | |
528 __ movflt(xmm4, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 32)); | |
529 __ movflt(xmm5, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 40)); | |
530 __ movflt(xmm6, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 48)); | |
531 __ movflt(xmm7, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 56)); | |
0 | 532 } |
533 | |
534 if (UseSSE < 2) { | |
304 | 535 __ frstor(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size)); |
0 | 536 } else { |
537 // check that FPU stack is really empty | |
538 __ verify_FPU(0, "restore_live_registers"); | |
539 } | |
540 | |
541 } else { | |
542 // check that FPU stack is really empty | |
543 __ verify_FPU(0, "restore_live_registers"); | |
544 } | |
545 | |
546 #ifdef ASSERT | |
547 { | |
548 Label ok; | |
304 | 549 __ cmpptr(Address(rsp, marker * VMRegImpl::stack_slot_size), (int32_t)0xfeedbeef); |
0 | 550 __ jcc(Assembler::equal, ok); |
551 __ stop("bad offsets in frame"); | |
552 __ bind(ok); | |
553 } | |
304 | 554 #endif // ASSERT |
0 | 555 |
304 | 556 __ addptr(rsp, extra_space_offset * VMRegImpl::stack_slot_size); |
0 | 557 } |
558 | |
559 | |
560 static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = true) { | |
561 __ block_comment("restore_live_registers"); | |
562 | |
563 restore_fpu(sasm, restore_fpu_registers); | |
304 | 564 __ popa(); |
0 | 565 } |
566 | |
567 | |
568 static void restore_live_registers_except_rax(StubAssembler* sasm, bool restore_fpu_registers = true) { | |
569 __ block_comment("restore_live_registers_except_rax"); | |
570 | |
571 restore_fpu(sasm, restore_fpu_registers); | |
572 | |
304 | 573 #ifdef _LP64 |
574 __ movptr(r15, Address(rsp, 0)); | |
575 __ movptr(r14, Address(rsp, wordSize)); | |
576 __ movptr(r13, Address(rsp, 2 * wordSize)); | |
577 __ movptr(r12, Address(rsp, 3 * wordSize)); | |
578 __ movptr(r11, Address(rsp, 4 * wordSize)); | |
579 __ movptr(r10, Address(rsp, 5 * wordSize)); | |
580 __ movptr(r9, Address(rsp, 6 * wordSize)); | |
581 __ movptr(r8, Address(rsp, 7 * wordSize)); | |
582 __ movptr(rdi, Address(rsp, 8 * wordSize)); | |
583 __ movptr(rsi, Address(rsp, 9 * wordSize)); | |
584 __ movptr(rbp, Address(rsp, 10 * wordSize)); | |
585 // skip rsp | |
586 __ movptr(rbx, Address(rsp, 12 * wordSize)); | |
587 __ movptr(rdx, Address(rsp, 13 * wordSize)); | |
588 __ movptr(rcx, Address(rsp, 14 * wordSize)); | |
589 | |
590 __ addptr(rsp, 16 * wordSize); | |
591 #else | |
592 | |
593 __ pop(rdi); | |
594 __ pop(rsi); | |
595 __ pop(rbp); | |
596 __ pop(rbx); // skip this value | |
597 __ pop(rbx); | |
598 __ pop(rdx); | |
599 __ pop(rcx); | |
600 __ addptr(rsp, BytesPerWord); | |
601 #endif // _LP64 | |
0 | 602 } |
603 | |
604 | |
605 void Runtime1::initialize_pd() { | |
606 // nothing to do | |
607 } | |
608 | |
609 | |
610 // target: the entry point of the method that creates and posts the exception oop | |
611 // has_argument: true if the exception needs an argument (passed on stack because registers must be preserved) | |
612 | |
613 OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address target, bool has_argument) { | |
614 // preserve all registers | |
615 int num_rt_args = has_argument ? 2 : 1; | |
616 OopMap* oop_map = save_live_registers(sasm, num_rt_args); | |
617 | |
618 // now all registers are saved and can be used freely | |
619 // verify that no old value is used accidentally | |
620 __ invalidate_registers(true, true, true, true, true, true); | |
621 | |
622 // registers used by this stub | |
623 const Register temp_reg = rbx; | |
624 | |
625 // load argument for exception that is passed as an argument into the stub | |
626 if (has_argument) { | |
304 | 627 #ifdef _LP64 |
628 __ movptr(c_rarg1, Address(rbp, 2*BytesPerWord)); | |
629 #else | |
630 __ movptr(temp_reg, Address(rbp, 2*BytesPerWord)); | |
631 __ push(temp_reg); | |
632 #endif // _LP64 | |
0 | 633 } |
634 int call_offset = __ call_RT(noreg, noreg, target, num_rt_args - 1); | |
635 | |
636 OopMapSet* oop_maps = new OopMapSet(); | |
637 oop_maps->add_gc_map(call_offset, oop_map); | |
638 | |
639 __ stop("should not reach here"); | |
640 | |
641 return oop_maps; | |
642 } | |
643 | |
644 | |
645 void Runtime1::generate_handle_exception(StubAssembler *sasm, OopMapSet* oop_maps, OopMap* oop_map, bool save_fpu_registers) { | |
646 // incoming parameters | |
647 const Register exception_oop = rax; | |
648 const Register exception_pc = rdx; | |
649 // other registers used in this stub | |
650 const Register real_return_addr = rbx; | |
304 | 651 const Register thread = NOT_LP64(rdi) LP64_ONLY(r15_thread); |
0 | 652 |
653 __ block_comment("generate_handle_exception"); | |
654 | |
655 #ifdef TIERED | |
656 // C2 can leave the fpu stack dirty | |
657 if (UseSSE < 2 ) { | |
658 __ empty_FPU_stack(); | |
659 } | |
660 #endif // TIERED | |
661 | |
662 // verify that only rax, and rdx is valid at this time | |
663 __ invalidate_registers(false, true, true, false, true, true); | |
664 // verify that rax, contains a valid exception | |
665 __ verify_not_null_oop(exception_oop); | |
666 | |
667 // load address of JavaThread object for thread-local data | |
304 | 668 NOT_LP64(__ get_thread(thread);) |
0 | 669 |
670 #ifdef ASSERT | |
671 // check that fields in JavaThread for exception oop and issuing pc are | |
672 // empty before writing to them | |
673 Label oop_empty; | |
304 | 674 __ cmpptr(Address(thread, JavaThread::exception_oop_offset()), (int32_t) NULL_WORD); |
0 | 675 __ jcc(Assembler::equal, oop_empty); |
676 __ stop("exception oop already set"); | |
677 __ bind(oop_empty); | |
678 | |
679 Label pc_empty; | |
304 | 680 __ cmpptr(Address(thread, JavaThread::exception_pc_offset()), 0); |
0 | 681 __ jcc(Assembler::equal, pc_empty); |
682 __ stop("exception pc already set"); | |
683 __ bind(pc_empty); | |
684 #endif | |
685 | |
686 // save exception oop and issuing pc into JavaThread | |
687 // (exception handler will load it from here) | |
304 | 688 __ movptr(Address(thread, JavaThread::exception_oop_offset()), exception_oop); |
689 __ movptr(Address(thread, JavaThread::exception_pc_offset()), exception_pc); | |
0 | 690 |
691 // save real return address (pc that called this stub) | |
304 | 692 __ movptr(real_return_addr, Address(rbp, 1*BytesPerWord)); |
693 __ movptr(Address(rsp, temp_1_off * VMRegImpl::stack_slot_size), real_return_addr); | |
0 | 694 |
695 // patch throwing pc into return address (has bci & oop map) | |
304 | 696 __ movptr(Address(rbp, 1*BytesPerWord), exception_pc); |
0 | 697 |
698 // compute the exception handler. | |
699 // the exception oop and the throwing pc are read from the fields in JavaThread | |
700 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, exception_handler_for_pc)); | |
701 oop_maps->add_gc_map(call_offset, oop_map); | |
702 | |
1295 | 703 // rax,: handler address |
0 | 704 // will be the deopt blob if nmethod was deoptimized while we looked up |
705 // handler regardless of whether handler existed in the nmethod. | |
706 | |
707 // only rax, is valid at this time, all other registers have been destroyed by the runtime call | |
708 __ invalidate_registers(false, true, true, true, true, true); | |
709 | |
1295 | 710 #ifdef ASSERT |
0 | 711 // Do we have an exception handler in the nmethod? |
712 Label done; | |
304 | 713 __ testptr(rax, rax); |
1295 | 714 __ jcc(Assembler::notZero, done); |
715 __ stop("no handler found"); | |
716 __ bind(done); | |
717 #endif | |
0 | 718 |
719 // exception handler found | |
720 // patch the return address -> the stub will directly return to the exception handler | |
304 | 721 __ movptr(Address(rbp, 1*BytesPerWord), rax); |
0 | 722 |
723 // restore registers | |
724 restore_live_registers(sasm, save_fpu_registers); | |
725 | |
726 // return to exception handler | |
727 __ leave(); | |
728 __ ret(0); | |
729 | |
730 } | |
731 | |
732 | |
733 void Runtime1::generate_unwind_exception(StubAssembler *sasm) { | |
734 // incoming parameters | |
735 const Register exception_oop = rax; | |
1295 | 736 // callee-saved copy of exception_oop during runtime call |
737 const Register exception_oop_callee_saved = NOT_LP64(rsi) LP64_ONLY(r14); | |
0 | 738 // other registers used in this stub |
739 const Register exception_pc = rdx; | |
740 const Register handler_addr = rbx; | |
304 | 741 const Register thread = NOT_LP64(rdi) LP64_ONLY(r15_thread); |
0 | 742 |
743 // verify that only rax, is valid at this time | |
744 __ invalidate_registers(false, true, true, true, true, true); | |
745 | |
746 #ifdef ASSERT | |
747 // check that fields in JavaThread for exception oop and issuing pc are empty | |
304 | 748 NOT_LP64(__ get_thread(thread);) |
0 | 749 Label oop_empty; |
304 | 750 __ cmpptr(Address(thread, JavaThread::exception_oop_offset()), 0); |
0 | 751 __ jcc(Assembler::equal, oop_empty); |
752 __ stop("exception oop must be empty"); | |
753 __ bind(oop_empty); | |
754 | |
755 Label pc_empty; | |
304 | 756 __ cmpptr(Address(thread, JavaThread::exception_pc_offset()), 0); |
0 | 757 __ jcc(Assembler::equal, pc_empty); |
758 __ stop("exception pc must be empty"); | |
759 __ bind(pc_empty); | |
760 #endif | |
761 | |
762 // clear the FPU stack in case any FPU results are left behind | |
763 __ empty_FPU_stack(); | |
764 | |
1295 | 765 // save exception_oop in callee-saved register to preserve it during runtime calls |
766 __ verify_not_null_oop(exception_oop); | |
767 __ movptr(exception_oop_callee_saved, exception_oop); | |
768 | |
769 NOT_LP64(__ get_thread(thread);) | |
770 // Get return address (is on top of stack after leave). | |
304 | 771 __ movptr(exception_pc, Address(rsp, 0)); |
0 | 772 |
1295 | 773 // search the exception handler address of the caller (using the return address) |
774 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), thread, exception_pc); | |
775 // rax: exception handler address of the caller | |
0 | 776 |
1295 | 777 // Only RAX and RSI are valid at this time, all other registers have been destroyed by the call. |
778 __ invalidate_registers(false, true, true, true, false, true); | |
0 | 779 |
780 // move result of call into correct register | |
304 | 781 __ movptr(handler_addr, rax); |
0 | 782 |
1295 | 783 // Restore exception oop to RAX (required convention of exception handler). |
784 __ movptr(exception_oop, exception_oop_callee_saved); | |
0 | 785 |
1295 | 786 // verify that there is really a valid exception in rax |
787 __ verify_not_null_oop(exception_oop); | |
0 | 788 |
789 // get throwing pc (= return address). | |
790 // rdx has been destroyed by the call, so it must be set again | |
791 // the pop is also necessary to simulate the effect of a ret(0) | |
304 | 792 __ pop(exception_pc); |
0 | 793 |
1295 | 794 // Restore SP from BP if the exception PC is a MethodHandle call site. |
795 NOT_LP64(__ get_thread(thread);) | |
1368
93767e6a2dfd
6941529: SharedRuntime::raw_exception_handler_for_return_address must reset thread MethodHandle flag
twisti
parents:
1295
diff
changeset
|
796 __ cmpl(Address(thread, JavaThread::is_method_handle_return_offset()), 0); |
1564 | 797 __ cmovptr(Assembler::notEqual, rsp, rbp_mh_SP_save); |
0 | 798 |
799 // continue at exception handler (return address removed) | |
800 // note: do *not* remove arguments when unwinding the | |
801 // activation since the caller assumes having | |
802 // all arguments on the stack when entering the | |
803 // runtime to determine the exception handler | |
804 // (GC happens at call site with arguments!) | |
1295 | 805 // rax: exception oop |
0 | 806 // rdx: throwing pc |
1295 | 807 // rbx: exception handler |
0 | 808 __ jmp(handler_addr); |
809 } | |
810 | |
811 | |
812 OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { | |
813 // use the maximum number of runtime-arguments here because it is difficult to | |
814 // distinguish each RT-Call. | |
815 // Note: This number affects also the RT-Call in generate_handle_exception because | |
816 // the oop-map is shared for all calls. | |
817 const int num_rt_args = 2; // thread + dummy | |
818 | |
819 DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob(); | |
820 assert(deopt_blob != NULL, "deoptimization blob must have been created"); | |
821 | |
822 OopMap* oop_map = save_live_registers(sasm, num_rt_args); | |
823 | |
304 | 824 #ifdef _LP64 |
825 const Register thread = r15_thread; | |
826 // No need to worry about dummy | |
827 __ mov(c_rarg0, thread); | |
828 #else | |
829 __ push(rax); // push dummy | |
0 | 830 |
831 const Register thread = rdi; // is callee-saved register (Visual C++ calling conventions) | |
832 // push java thread (becomes first argument of C function) | |
833 __ get_thread(thread); | |
304 | 834 __ push(thread); |
835 #endif // _LP64 | |
0 | 836 __ set_last_Java_frame(thread, noreg, rbp, NULL); |
837 // do the call | |
838 __ call(RuntimeAddress(target)); | |
839 OopMapSet* oop_maps = new OopMapSet(); | |
840 oop_maps->add_gc_map(__ offset(), oop_map); | |
841 // verify callee-saved register | |
842 #ifdef ASSERT | |
843 guarantee(thread != rax, "change this code"); | |
304 | 844 __ push(rax); |
0 | 845 { Label L; |
846 __ get_thread(rax); | |
304 | 847 __ cmpptr(thread, rax); |
0 | 848 __ jcc(Assembler::equal, L); |
304 | 849 __ stop("StubAssembler::call_RT: rdi/r15 not callee saved?"); |
0 | 850 __ bind(L); |
851 } | |
304 | 852 __ pop(rax); |
0 | 853 #endif |
854 __ reset_last_Java_frame(thread, true, false); | |
304 | 855 #ifndef _LP64 |
856 __ pop(rcx); // discard thread arg | |
857 __ pop(rcx); // discard dummy | |
858 #endif // _LP64 | |
0 | 859 |
860 // check for pending exceptions | |
861 { Label L; | |
304 | 862 __ cmpptr(Address(thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD); |
0 | 863 __ jcc(Assembler::equal, L); |
864 // exception pending => remove activation and forward to exception handler | |
865 | |
304 | 866 __ testptr(rax, rax); // have we deoptimized? |
0 | 867 __ jump_cc(Assembler::equal, |
868 RuntimeAddress(Runtime1::entry_for(Runtime1::forward_exception_id))); | |
869 | |
870 // the deopt blob expects exceptions in the special fields of | |
871 // JavaThread, so copy and clear pending exception. | |
872 | |
873 // load and clear pending exception | |
304 | 874 __ movptr(rax, Address(thread, Thread::pending_exception_offset())); |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
380
diff
changeset
|
875 __ movptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD); |
0 | 876 |
877 // check that there is really a valid exception | |
878 __ verify_not_null_oop(rax); | |
879 | |
880 // load throwing pc: this is the return address of the stub | |
304 | 881 __ movptr(rdx, Address(rsp, return_off * VMRegImpl::stack_slot_size)); |
0 | 882 |
883 #ifdef ASSERT | |
884 // check that fields in JavaThread for exception oop and issuing pc are empty | |
885 Label oop_empty; | |
304 | 886 __ cmpptr(Address(thread, JavaThread::exception_oop_offset()), (int32_t)NULL_WORD); |
0 | 887 __ jcc(Assembler::equal, oop_empty); |
888 __ stop("exception oop must be empty"); | |
889 __ bind(oop_empty); | |
890 | |
891 Label pc_empty; | |
304 | 892 __ cmpptr(Address(thread, JavaThread::exception_pc_offset()), (int32_t)NULL_WORD); |
0 | 893 __ jcc(Assembler::equal, pc_empty); |
894 __ stop("exception pc must be empty"); | |
895 __ bind(pc_empty); | |
896 #endif | |
897 | |
898 // store exception oop and throwing pc to JavaThread | |
304 | 899 __ movptr(Address(thread, JavaThread::exception_oop_offset()), rax); |
900 __ movptr(Address(thread, JavaThread::exception_pc_offset()), rdx); | |
0 | 901 |
902 restore_live_registers(sasm); | |
903 | |
904 __ leave(); | |
304 | 905 __ addptr(rsp, BytesPerWord); // remove return address from stack |
0 | 906 |
907 // Forward the exception directly to deopt blob. We can blow no | |
908 // registers and must leave throwing pc on the stack. A patch may | |
909 // have values live in registers so the entry point with the | |
910 // exception in tls. | |
911 __ jump(RuntimeAddress(deopt_blob->unpack_with_exception_in_tls())); | |
912 | |
913 __ bind(L); | |
914 } | |
915 | |
916 | |
917 // Runtime will return true if the nmethod has been deoptimized during | |
918 // the patching process. In that case we must do a deopt reexecute instead. | |
919 | |
920 Label reexecuteEntry, cont; | |
921 | |
304 | 922 __ testptr(rax, rax); // have we deoptimized? |
0 | 923 __ jcc(Assembler::equal, cont); // no |
924 | |
925 // Will reexecute. Proper return address is already on the stack we just restore | |
926 // registers, pop all of our frame but the return address and jump to the deopt blob | |
927 restore_live_registers(sasm); | |
928 __ leave(); | |
929 __ jump(RuntimeAddress(deopt_blob->unpack_with_reexecution())); | |
930 | |
931 __ bind(cont); | |
932 restore_live_registers(sasm); | |
933 __ leave(); | |
934 __ ret(0); | |
935 | |
936 return oop_maps; | |
937 | |
938 } | |
939 | |
940 | |
941 OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { | |
942 | |
943 // for better readability | |
944 const bool must_gc_arguments = true; | |
945 const bool dont_gc_arguments = false; | |
946 | |
947 // default value; overwritten for some optimized stubs that are called from methods that do not use the fpu | |
948 bool save_fpu_registers = true; | |
949 | |
950 // stub code & info for the different stubs | |
951 OopMapSet* oop_maps = NULL; | |
952 switch (id) { | |
953 case forward_exception_id: | |
954 { | |
955 // we're handling an exception in the context of a compiled | |
956 // frame. The registers have been saved in the standard | |
957 // places. Perform an exception lookup in the caller and | |
958 // dispatch to the handler if found. Otherwise unwind and | |
959 // dispatch to the callers exception handler. | |
960 | |
304 | 961 const Register thread = NOT_LP64(rdi) LP64_ONLY(r15_thread); |
0 | 962 const Register exception_oop = rax; |
963 const Register exception_pc = rdx; | |
964 | |
965 // load pending exception oop into rax, | |
304 | 966 __ movptr(exception_oop, Address(thread, Thread::pending_exception_offset())); |
0 | 967 // clear pending exception |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
380
diff
changeset
|
968 __ movptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD); |
0 | 969 |
970 // load issuing PC (the return address for this stub) into rdx | |
304 | 971 __ movptr(exception_pc, Address(rbp, 1*BytesPerWord)); |
0 | 972 |
973 // make sure that the vm_results are cleared (may be unnecessary) | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
380
diff
changeset
|
974 __ movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); |
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
380
diff
changeset
|
975 __ movptr(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD); |
0 | 976 |
977 // verify that that there is really a valid exception in rax, | |
978 __ verify_not_null_oop(exception_oop); | |
979 | |
980 | |
981 oop_maps = new OopMapSet(); | |
982 OopMap* oop_map = generate_oop_map(sasm, 1); | |
983 generate_handle_exception(sasm, oop_maps, oop_map); | |
984 __ stop("should not reach here"); | |
985 } | |
986 break; | |
987 | |
988 case new_instance_id: | |
989 case fast_new_instance_id: | |
990 case fast_new_instance_init_check_id: | |
991 { | |
992 Register klass = rdx; // Incoming | |
993 Register obj = rax; // Result | |
994 | |
995 if (id == new_instance_id) { | |
996 __ set_info("new_instance", dont_gc_arguments); | |
997 } else if (id == fast_new_instance_id) { | |
998 __ set_info("fast new_instance", dont_gc_arguments); | |
999 } else { | |
1000 assert(id == fast_new_instance_init_check_id, "bad StubID"); | |
1001 __ set_info("fast new_instance init check", dont_gc_arguments); | |
1002 } | |
1003 | |
1004 if ((id == fast_new_instance_id || id == fast_new_instance_init_check_id) && | |
1005 UseTLAB && FastTLABRefill) { | |
1006 Label slow_path; | |
1007 Register obj_size = rcx; | |
1008 Register t1 = rbx; | |
1009 Register t2 = rsi; | |
1010 assert_different_registers(klass, obj, obj_size, t1, t2); | |
1011 | |
304 | 1012 __ push(rdi); |
1013 __ push(rbx); | |
0 | 1014 |
1015 if (id == fast_new_instance_init_check_id) { | |
1016 // make sure the klass is initialized | |
1017 __ cmpl(Address(klass, instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc)), instanceKlass::fully_initialized); | |
1018 __ jcc(Assembler::notEqual, slow_path); | |
1019 } | |
1020 | |
1021 #ifdef ASSERT | |
1022 // assert object can be fast path allocated | |
1023 { | |
1024 Label ok, not_ok; | |
1025 __ movl(obj_size, Address(klass, Klass::layout_helper_offset_in_bytes() + sizeof(oopDesc))); | |
1026 __ cmpl(obj_size, 0); // make sure it's an instance (LH > 0) | |
1027 __ jcc(Assembler::lessEqual, not_ok); | |
1028 __ testl(obj_size, Klass::_lh_instance_slow_path_bit); | |
1029 __ jcc(Assembler::zero, ok); | |
1030 __ bind(not_ok); | |
1031 __ stop("assert(can be fast path allocated)"); | |
1032 __ should_not_reach_here(); | |
1033 __ bind(ok); | |
1034 } | |
1035 #endif // ASSERT | |
1036 | |
1037 // if we got here then the TLAB allocation failed, so try | |
1038 // refilling the TLAB or allocating directly from eden. | |
1039 Label retry_tlab, try_eden; | |
1040 __ tlab_refill(retry_tlab, try_eden, slow_path); // does not destroy rdx (klass) | |
1041 | |
1042 __ bind(retry_tlab); | |
1043 | |
304 | 1044 // get the instance size (size is postive so movl is fine for 64bit) |
0 | 1045 __ movl(obj_size, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes())); |
1046 __ tlab_allocate(obj, obj_size, 0, t1, t2, slow_path); | |
1047 __ initialize_object(obj, klass, obj_size, 0, t1, t2); | |
1048 __ verify_oop(obj); | |
304 | 1049 __ pop(rbx); |
1050 __ pop(rdi); | |
0 | 1051 __ ret(0); |
1052 | |
1053 __ bind(try_eden); | |
304 | 1054 // get the instance size (size is postive so movl is fine for 64bit) |
0 | 1055 __ movl(obj_size, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes())); |
1056 __ eden_allocate(obj, obj_size, 0, t1, slow_path); | |
1057 __ initialize_object(obj, klass, obj_size, 0, t1, t2); | |
1058 __ verify_oop(obj); | |
304 | 1059 __ pop(rbx); |
1060 __ pop(rdi); | |
0 | 1061 __ ret(0); |
1062 | |
1063 __ bind(slow_path); | |
304 | 1064 __ pop(rbx); |
1065 __ pop(rdi); | |
0 | 1066 } |
1067 | |
1068 __ enter(); | |
1069 OopMap* map = save_live_registers(sasm, 2); | |
1070 int call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_instance), klass); | |
1071 oop_maps = new OopMapSet(); | |
1072 oop_maps->add_gc_map(call_offset, map); | |
1073 restore_live_registers_except_rax(sasm); | |
1074 __ verify_oop(obj); | |
1075 __ leave(); | |
1076 __ ret(0); | |
1077 | |
1078 // rax,: new instance | |
1079 } | |
1080 | |
1081 break; | |
1082 | |
1083 case counter_overflow_id: | |
1084 { | |
1783 | 1085 Register bci = rax, method = rbx; |
0 | 1086 __ enter(); |
1783 | 1087 OopMap* map = save_live_registers(sasm, 3); |
0 | 1088 // Retrieve bci |
1089 __ movl(bci, Address(rbp, 2*BytesPerWord)); | |
1783 | 1090 // And a pointer to the methodOop |
1091 __ movptr(method, Address(rbp, 3*BytesPerWord)); | |
1092 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, counter_overflow), bci, method); | |
0 | 1093 oop_maps = new OopMapSet(); |
1094 oop_maps->add_gc_map(call_offset, map); | |
1095 restore_live_registers(sasm); | |
1096 __ leave(); | |
1097 __ ret(0); | |
1098 } | |
1099 break; | |
1100 | |
1101 case new_type_array_id: | |
1102 case new_object_array_id: | |
1103 { | |
1104 Register length = rbx; // Incoming | |
1105 Register klass = rdx; // Incoming | |
1106 Register obj = rax; // Result | |
1107 | |
1108 if (id == new_type_array_id) { | |
1109 __ set_info("new_type_array", dont_gc_arguments); | |
1110 } else { | |
1111 __ set_info("new_object_array", dont_gc_arguments); | |
1112 } | |
1113 | |
1114 #ifdef ASSERT | |
1115 // assert object type is really an array of the proper kind | |
1116 { | |
1117 Label ok; | |
1118 Register t0 = obj; | |
1119 __ movl(t0, Address(klass, Klass::layout_helper_offset_in_bytes() + sizeof(oopDesc))); | |
1120 __ sarl(t0, Klass::_lh_array_tag_shift); | |
1121 int tag = ((id == new_type_array_id) | |
1122 ? Klass::_lh_array_tag_type_value | |
1123 : Klass::_lh_array_tag_obj_value); | |
1124 __ cmpl(t0, tag); | |
1125 __ jcc(Assembler::equal, ok); | |
1126 __ stop("assert(is an array klass)"); | |
1127 __ should_not_reach_here(); | |
1128 __ bind(ok); | |
1129 } | |
1130 #endif // ASSERT | |
1131 | |
1132 if (UseTLAB && FastTLABRefill) { | |
1133 Register arr_size = rsi; | |
1134 Register t1 = rcx; // must be rcx for use as shift count | |
1135 Register t2 = rdi; | |
1136 Label slow_path; | |
1137 assert_different_registers(length, klass, obj, arr_size, t1, t2); | |
1138 | |
1139 // check that array length is small enough for fast path. | |
1140 __ cmpl(length, C1_MacroAssembler::max_array_allocation_length); | |
1141 __ jcc(Assembler::above, slow_path); | |
1142 | |
1143 // if we got here then the TLAB allocation failed, so try | |
1144 // refilling the TLAB or allocating directly from eden. | |
1145 Label retry_tlab, try_eden; | |
1146 __ tlab_refill(retry_tlab, try_eden, slow_path); // preserves rbx, & rdx | |
1147 | |
1148 __ bind(retry_tlab); | |
1149 | |
1150 // get the allocation size: round_up(hdr + length << (layout_helper & 0x1F)) | |
304 | 1151 // since size is postive movl does right thing on 64bit |
0 | 1152 __ movl(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes())); |
304 | 1153 // since size is postive movl does right thing on 64bit |
0 | 1154 __ movl(arr_size, length); |
1155 assert(t1 == rcx, "fixed register usage"); | |
304 | 1156 __ shlptr(arr_size /* by t1=rcx, mod 32 */); |
1157 __ shrptr(t1, Klass::_lh_header_size_shift); | |
1158 __ andptr(t1, Klass::_lh_header_size_mask); | |
1159 __ addptr(arr_size, t1); | |
1160 __ addptr(arr_size, MinObjAlignmentInBytesMask); // align up | |
1161 __ andptr(arr_size, ~MinObjAlignmentInBytesMask); | |
0 | 1162 |
1163 __ tlab_allocate(obj, arr_size, 0, t1, t2, slow_path); // preserves arr_size | |
1164 | |
1165 __ initialize_header(obj, klass, length, t1, t2); | |
1166 __ movb(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes() + (Klass::_lh_header_size_shift / BitsPerByte))); | |
1167 assert(Klass::_lh_header_size_shift % BitsPerByte == 0, "bytewise"); | |
1168 assert(Klass::_lh_header_size_mask <= 0xFF, "bytewise"); | |
304 | 1169 __ andptr(t1, Klass::_lh_header_size_mask); |
1170 __ subptr(arr_size, t1); // body length | |
1171 __ addptr(t1, obj); // body start | |
0 | 1172 __ initialize_body(t1, arr_size, 0, t2); |
1173 __ verify_oop(obj); | |
1174 __ ret(0); | |
1175 | |
1176 __ bind(try_eden); | |
1177 // get the allocation size: round_up(hdr + length << (layout_helper & 0x1F)) | |
304 | 1178 // since size is postive movl does right thing on 64bit |
0 | 1179 __ movl(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes())); |
304 | 1180 // since size is postive movl does right thing on 64bit |
0 | 1181 __ movl(arr_size, length); |
1182 assert(t1 == rcx, "fixed register usage"); | |
304 | 1183 __ shlptr(arr_size /* by t1=rcx, mod 32 */); |
1184 __ shrptr(t1, Klass::_lh_header_size_shift); | |
1185 __ andptr(t1, Klass::_lh_header_size_mask); | |
1186 __ addptr(arr_size, t1); | |
1187 __ addptr(arr_size, MinObjAlignmentInBytesMask); // align up | |
1188 __ andptr(arr_size, ~MinObjAlignmentInBytesMask); | |
0 | 1189 |
1190 __ eden_allocate(obj, arr_size, 0, t1, slow_path); // preserves arr_size | |
1191 | |
1192 __ initialize_header(obj, klass, length, t1, t2); | |
1193 __ movb(t1, Address(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes() + (Klass::_lh_header_size_shift / BitsPerByte))); | |
1194 assert(Klass::_lh_header_size_shift % BitsPerByte == 0, "bytewise"); | |
1195 assert(Klass::_lh_header_size_mask <= 0xFF, "bytewise"); | |
304 | 1196 __ andptr(t1, Klass::_lh_header_size_mask); |
1197 __ subptr(arr_size, t1); // body length | |
1198 __ addptr(t1, obj); // body start | |
0 | 1199 __ initialize_body(t1, arr_size, 0, t2); |
1200 __ verify_oop(obj); | |
1201 __ ret(0); | |
1202 | |
1203 __ bind(slow_path); | |
1204 } | |
1205 | |
1206 __ enter(); | |
1207 OopMap* map = save_live_registers(sasm, 3); | |
1208 int call_offset; | |
1209 if (id == new_type_array_id) { | |
1210 call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length); | |
1211 } else { | |
1212 call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length); | |
1213 } | |
1214 | |
1215 oop_maps = new OopMapSet(); | |
1216 oop_maps->add_gc_map(call_offset, map); | |
1217 restore_live_registers_except_rax(sasm); | |
1218 | |
1219 __ verify_oop(obj); | |
1220 __ leave(); | |
1221 __ ret(0); | |
1222 | |
1223 // rax,: new array | |
1224 } | |
1225 break; | |
1226 | |
1227 case new_multi_array_id: | |
1228 { StubFrame f(sasm, "new_multi_array", dont_gc_arguments); | |
1229 // rax,: klass | |
1230 // rbx,: rank | |
1231 // rcx: address of 1st dimension | |
1232 OopMap* map = save_live_registers(sasm, 4); | |
1233 int call_offset = __ call_RT(rax, noreg, CAST_FROM_FN_PTR(address, new_multi_array), rax, rbx, rcx); | |
1234 | |
1235 oop_maps = new OopMapSet(); | |
1236 oop_maps->add_gc_map(call_offset, map); | |
1237 restore_live_registers_except_rax(sasm); | |
1238 | |
1239 // rax,: new multi array | |
1240 __ verify_oop(rax); | |
1241 } | |
1242 break; | |
1243 | |
1244 case register_finalizer_id: | |
1245 { | |
1246 __ set_info("register_finalizer", dont_gc_arguments); | |
1247 | |
304 | 1248 // This is called via call_runtime so the arguments |
1249 // will be place in C abi locations | |
1250 | |
1251 #ifdef _LP64 | |
1252 __ verify_oop(c_rarg0); | |
1253 __ mov(rax, c_rarg0); | |
1254 #else | |
0 | 1255 // The object is passed on the stack and we haven't pushed a |
1256 // frame yet so it's one work away from top of stack. | |
304 | 1257 __ movptr(rax, Address(rsp, 1 * BytesPerWord)); |
0 | 1258 __ verify_oop(rax); |
304 | 1259 #endif // _LP64 |
0 | 1260 |
1261 // load the klass and check the has finalizer flag | |
1262 Label register_finalizer; | |
1263 Register t = rsi; | |
2002 | 1264 __ load_klass(t, rax); |
0 | 1265 __ movl(t, Address(t, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc))); |
1266 __ testl(t, JVM_ACC_HAS_FINALIZER); | |
1267 __ jcc(Assembler::notZero, register_finalizer); | |
1268 __ ret(0); | |
1269 | |
1270 __ bind(register_finalizer); | |
1271 __ enter(); | |
1272 OopMap* oop_map = save_live_registers(sasm, 2 /*num_rt_args */); | |
1273 int call_offset = __ call_RT(noreg, noreg, | |
1274 CAST_FROM_FN_PTR(address, SharedRuntime::register_finalizer), rax); | |
1275 oop_maps = new OopMapSet(); | |
1276 oop_maps->add_gc_map(call_offset, oop_map); | |
1277 | |
1278 // Now restore all the live registers | |
1279 restore_live_registers(sasm); | |
1280 | |
1281 __ leave(); | |
1282 __ ret(0); | |
1283 } | |
1284 break; | |
1285 | |
1286 case throw_range_check_failed_id: | |
1287 { StubFrame f(sasm, "range_check_failed", dont_gc_arguments); | |
1288 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_range_check_exception), true); | |
1289 } | |
1290 break; | |
1291 | |
1292 case throw_index_exception_id: | |
1293 { StubFrame f(sasm, "index_range_check_failed", dont_gc_arguments); | |
1294 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_index_exception), true); | |
1295 } | |
1296 break; | |
1297 | |
1298 case throw_div0_exception_id: | |
1299 { StubFrame f(sasm, "throw_div0_exception", dont_gc_arguments); | |
1300 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_div0_exception), false); | |
1301 } | |
1302 break; | |
1303 | |
1304 case throw_null_pointer_exception_id: | |
1305 { StubFrame f(sasm, "throw_null_pointer_exception", dont_gc_arguments); | |
1306 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_null_pointer_exception), false); | |
1307 } | |
1308 break; | |
1309 | |
1310 case handle_exception_nofpu_id: | |
1311 save_fpu_registers = false; | |
1312 // fall through | |
1313 case handle_exception_id: | |
1314 { StubFrame f(sasm, "handle_exception", dont_gc_arguments); | |
1315 oop_maps = new OopMapSet(); | |
1316 OopMap* oop_map = save_live_registers(sasm, 1, save_fpu_registers); | |
1317 generate_handle_exception(sasm, oop_maps, oop_map, save_fpu_registers); | |
1318 } | |
1319 break; | |
1320 | |
1321 case unwind_exception_id: | |
1322 { __ set_info("unwind_exception", dont_gc_arguments); | |
1323 // note: no stubframe since we are about to leave the current | |
1324 // activation and we are calling a leaf VM function only. | |
1325 generate_unwind_exception(sasm); | |
1326 } | |
1327 break; | |
1328 | |
1329 case throw_array_store_exception_id: | |
1330 { StubFrame f(sasm, "throw_array_store_exception", dont_gc_arguments); | |
1331 // tos + 0: link | |
1332 // + 1: return address | |
1333 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), false); | |
1334 } | |
1335 break; | |
1336 | |
1337 case throw_class_cast_exception_id: | |
1338 { StubFrame f(sasm, "throw_class_cast_exception", dont_gc_arguments); | |
1339 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true); | |
1340 } | |
1341 break; | |
1342 | |
1343 case throw_incompatible_class_change_error_id: | |
1344 { StubFrame f(sasm, "throw_incompatible_class_cast_exception", dont_gc_arguments); | |
1345 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false); | |
1346 } | |
1347 break; | |
1348 | |
1349 case slow_subtype_check_id: | |
1350 { | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
533
diff
changeset
|
1351 // Typical calling sequence: |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
533
diff
changeset
|
1352 // __ push(klass_RInfo); // object klass or other subclass |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
533
diff
changeset
|
1353 // __ push(sup_k_RInfo); // array element klass or other superclass |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
533
diff
changeset
|
1354 // __ call(slow_subtype_check); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
533
diff
changeset
|
1355 // Note that the subclass is pushed first, and is therefore deepest. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
533
diff
changeset
|
1356 // Previous versions of this code reversed the names 'sub' and 'super'. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
533
diff
changeset
|
1357 // This was operationally harmless but made the code unreadable. |
0 | 1358 enum layout { |
304 | 1359 rax_off, SLOT2(raxH_off) |
1360 rcx_off, SLOT2(rcxH_off) | |
1361 rsi_off, SLOT2(rsiH_off) | |
1362 rdi_off, SLOT2(rdiH_off) | |
1363 // saved_rbp_off, SLOT2(saved_rbpH_off) | |
1364 return_off, SLOT2(returnH_off) | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
533
diff
changeset
|
1365 sup_k_off, SLOT2(sup_kH_off) |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
533
diff
changeset
|
1366 klass_off, SLOT2(superH_off) |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
533
diff
changeset
|
1367 framesize, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
533
diff
changeset
|
1368 result_off = klass_off // deepest argument is also the return value |
0 | 1369 }; |
1370 | |
1371 __ set_info("slow_subtype_check", dont_gc_arguments); | |
304 | 1372 __ push(rdi); |
1373 __ push(rsi); | |
1374 __ push(rcx); | |
1375 __ push(rax); | |
0 | 1376 |
304 | 1377 // This is called by pushing args and not with C abi |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
533
diff
changeset
|
1378 __ movptr(rsi, Address(rsp, (klass_off) * VMRegImpl::stack_slot_size)); // subclass |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
533
diff
changeset
|
1379 __ movptr(rax, Address(rsp, (sup_k_off) * VMRegImpl::stack_slot_size)); // superclass |
0 | 1380 |
1381 Label miss; | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
533
diff
changeset
|
1382 __ check_klass_subtype_slow_path(rsi, rax, rcx, rdi, NULL, &miss); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
533
diff
changeset
|
1383 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
533
diff
changeset
|
1384 // fallthrough on success: |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
533
diff
changeset
|
1385 __ movptr(Address(rsp, (result_off) * VMRegImpl::stack_slot_size), 1); // result |
304 | 1386 __ pop(rax); |
1387 __ pop(rcx); | |
1388 __ pop(rsi); | |
1389 __ pop(rdi); | |
0 | 1390 __ ret(0); |
1391 | |
1392 __ bind(miss); | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
533
diff
changeset
|
1393 __ movptr(Address(rsp, (result_off) * VMRegImpl::stack_slot_size), NULL_WORD); // result |
304 | 1394 __ pop(rax); |
1395 __ pop(rcx); | |
1396 __ pop(rsi); | |
1397 __ pop(rdi); | |
0 | 1398 __ ret(0); |
1399 } | |
1400 break; | |
1401 | |
1402 case monitorenter_nofpu_id: | |
1403 save_fpu_registers = false; | |
1404 // fall through | |
1405 case monitorenter_id: | |
1406 { | |
1407 StubFrame f(sasm, "monitorenter", dont_gc_arguments); | |
1408 OopMap* map = save_live_registers(sasm, 3, save_fpu_registers); | |
1409 | |
304 | 1410 // Called with store_parameter and not C abi |
1411 | |
0 | 1412 f.load_argument(1, rax); // rax,: object |
1413 f.load_argument(0, rbx); // rbx,: lock address | |
1414 | |
1415 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorenter), rax, rbx); | |
1416 | |
1417 oop_maps = new OopMapSet(); | |
1418 oop_maps->add_gc_map(call_offset, map); | |
1419 restore_live_registers(sasm, save_fpu_registers); | |
1420 } | |
1421 break; | |
1422 | |
1423 case monitorexit_nofpu_id: | |
1424 save_fpu_registers = false; | |
1425 // fall through | |
1426 case monitorexit_id: | |
1427 { | |
1428 StubFrame f(sasm, "monitorexit", dont_gc_arguments); | |
1429 OopMap* map = save_live_registers(sasm, 2, save_fpu_registers); | |
1430 | |
304 | 1431 // Called with store_parameter and not C abi |
1432 | |
0 | 1433 f.load_argument(0, rax); // rax,: lock address |
1434 | |
1435 // note: really a leaf routine but must setup last java sp | |
1436 // => use call_RT for now (speed can be improved by | |
1437 // doing last java sp setup manually) | |
1438 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorexit), rax); | |
1439 | |
1440 oop_maps = new OopMapSet(); | |
1441 oop_maps->add_gc_map(call_offset, map); | |
1442 restore_live_registers(sasm, save_fpu_registers); | |
1443 | |
1444 } | |
1445 break; | |
1446 | |
1447 case access_field_patching_id: | |
1448 { StubFrame f(sasm, "access_field_patching", dont_gc_arguments); | |
1449 // we should set up register map | |
1450 oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, access_field_patching)); | |
1451 } | |
1452 break; | |
1453 | |
1454 case load_klass_patching_id: | |
1455 { StubFrame f(sasm, "load_klass_patching", dont_gc_arguments); | |
1456 // we should set up register map | |
1457 oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_klass_patching)); | |
1458 } | |
1459 break; | |
1460 | |
1461 case jvmti_exception_throw_id: | |
1462 { // rax,: exception oop | |
1463 StubFrame f(sasm, "jvmti_exception_throw", dont_gc_arguments); | |
1464 // Preserve all registers across this potentially blocking call | |
1465 const int num_rt_args = 2; // thread, exception oop | |
1466 OopMap* map = save_live_registers(sasm, num_rt_args); | |
1467 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, Runtime1::post_jvmti_exception_throw), rax); | |
1468 oop_maps = new OopMapSet(); | |
1469 oop_maps->add_gc_map(call_offset, map); | |
1470 restore_live_registers(sasm); | |
1471 } | |
1472 break; | |
1473 | |
1474 case dtrace_object_alloc_id: | |
1475 { // rax,: object | |
1476 StubFrame f(sasm, "dtrace_object_alloc", dont_gc_arguments); | |
1477 // we can't gc here so skip the oopmap but make sure that all | |
1478 // the live registers get saved. | |
1479 save_live_registers(sasm, 1); | |
1480 | |
304 | 1481 __ NOT_LP64(push(rax)) LP64_ONLY(mov(c_rarg0, rax)); |
0 | 1482 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc))); |
304 | 1483 NOT_LP64(__ pop(rax)); |
0 | 1484 |
1485 restore_live_registers(sasm); | |
1486 } | |
1487 break; | |
1488 | |
1489 case fpu2long_stub_id: | |
1490 { | |
1491 // rax, and rdx are destroyed, but should be free since the result is returned there | |
1492 // preserve rsi,ecx | |
304 | 1493 __ push(rsi); |
1494 __ push(rcx); | |
1495 LP64_ONLY(__ push(rdx);) | |
0 | 1496 |
1497 // check for NaN | |
1498 Label return0, do_return, return_min_jlong, do_convert; | |
1499 | |
304 | 1500 Address value_high_word(rsp, wordSize + 4); |
1501 Address value_low_word(rsp, wordSize); | |
1502 Address result_high_word(rsp, 3*wordSize + 4); | |
1503 Address result_low_word(rsp, 3*wordSize); | |
0 | 1504 |
304 | 1505 __ subptr(rsp, 32); // more than enough on 32bit |
0 | 1506 __ fst_d(value_low_word); |
1507 __ movl(rax, value_high_word); | |
1508 __ andl(rax, 0x7ff00000); | |
1509 __ cmpl(rax, 0x7ff00000); | |
1510 __ jcc(Assembler::notEqual, do_convert); | |
1511 __ movl(rax, value_high_word); | |
1512 __ andl(rax, 0xfffff); | |
1513 __ orl(rax, value_low_word); | |
1514 __ jcc(Assembler::notZero, return0); | |
1515 | |
1516 __ bind(do_convert); | |
1517 __ fnstcw(Address(rsp, 0)); | |
304 | 1518 __ movzwl(rax, Address(rsp, 0)); |
0 | 1519 __ orl(rax, 0xc00); |
1520 __ movw(Address(rsp, 2), rax); | |
1521 __ fldcw(Address(rsp, 2)); | |
1522 __ fwait(); | |
1523 __ fistp_d(result_low_word); | |
1524 __ fldcw(Address(rsp, 0)); | |
1525 __ fwait(); | |
304 | 1526 // This gets the entire long in rax on 64bit |
1527 __ movptr(rax, result_low_word); | |
1528 // testing of high bits | |
0 | 1529 __ movl(rdx, result_high_word); |
304 | 1530 __ mov(rcx, rax); |
0 | 1531 // What the heck is the point of the next instruction??? |
1532 __ xorl(rcx, 0x0); | |
1533 __ movl(rsi, 0x80000000); | |
1534 __ xorl(rsi, rdx); | |
1535 __ orl(rcx, rsi); | |
1536 __ jcc(Assembler::notEqual, do_return); | |
1537 __ fldz(); | |
1538 __ fcomp_d(value_low_word); | |
1539 __ fnstsw_ax(); | |
304 | 1540 #ifdef _LP64 |
1541 __ testl(rax, 0x4100); // ZF & CF == 0 | |
1542 __ jcc(Assembler::equal, return_min_jlong); | |
1543 #else | |
0 | 1544 __ sahf(); |
1545 __ jcc(Assembler::above, return_min_jlong); | |
304 | 1546 #endif // _LP64 |
0 | 1547 // return max_jlong |
304 | 1548 #ifndef _LP64 |
0 | 1549 __ movl(rdx, 0x7fffffff); |
1550 __ movl(rax, 0xffffffff); | |
304 | 1551 #else |
1552 __ mov64(rax, CONST64(0x7fffffffffffffff)); | |
1553 #endif // _LP64 | |
0 | 1554 __ jmp(do_return); |
1555 | |
1556 __ bind(return_min_jlong); | |
304 | 1557 #ifndef _LP64 |
0 | 1558 __ movl(rdx, 0x80000000); |
1559 __ xorl(rax, rax); | |
304 | 1560 #else |
1561 __ mov64(rax, CONST64(0x8000000000000000)); | |
1562 #endif // _LP64 | |
0 | 1563 __ jmp(do_return); |
1564 | |
1565 __ bind(return0); | |
1566 __ fpop(); | |
304 | 1567 #ifndef _LP64 |
1568 __ xorptr(rdx,rdx); | |
1569 __ xorptr(rax,rax); | |
1570 #else | |
1571 __ xorptr(rax, rax); | |
1572 #endif // _LP64 | |
0 | 1573 |
1574 __ bind(do_return); | |
304 | 1575 __ addptr(rsp, 32); |
1576 LP64_ONLY(__ pop(rdx);) | |
1577 __ pop(rcx); | |
1578 __ pop(rsi); | |
0 | 1579 __ ret(0); |
1580 } | |
1581 break; | |
1582 | |
342 | 1583 #ifndef SERIALGC |
1584 case g1_pre_barrier_slow_id: | |
1585 { | |
1586 StubFrame f(sasm, "g1_pre_barrier", dont_gc_arguments); | |
1587 // arg0 : previous value of memory | |
1588 | |
1589 BarrierSet* bs = Universe::heap()->barrier_set(); | |
1590 if (bs->kind() != BarrierSet::G1SATBCTLogging) { | |
362 | 1591 __ movptr(rax, (int)id); |
342 | 1592 __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), rax); |
1593 __ should_not_reach_here(); | |
1594 break; | |
1595 } | |
362 | 1596 __ push(rax); |
1597 __ push(rdx); | |
342 | 1598 |
1599 const Register pre_val = rax; | |
362 | 1600 const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread); |
342 | 1601 const Register tmp = rdx; |
1602 | |
362 | 1603 NOT_LP64(__ get_thread(thread);) |
342 | 1604 |
1605 Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() + | |
1606 PtrQueue::byte_offset_of_active())); | |
1607 | |
1608 Address queue_index(thread, in_bytes(JavaThread::satb_mark_queue_offset() + | |
1609 PtrQueue::byte_offset_of_index())); | |
1610 Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() + | |
1611 PtrQueue::byte_offset_of_buf())); | |
1612 | |
1613 | |
1614 Label done; | |
1615 Label runtime; | |
1616 | |
1617 // Can we store original value in the thread's buffer? | |
1618 | |
362 | 1619 #ifdef _LP64 |
1572 | 1620 __ movslq(tmp, queue_index); |
362 | 1621 __ cmpq(tmp, 0); |
1622 #else | |
342 | 1623 __ cmpl(queue_index, 0); |
362 | 1624 #endif |
342 | 1625 __ jcc(Assembler::equal, runtime); |
362 | 1626 #ifdef _LP64 |
1627 __ subq(tmp, wordSize); | |
1628 __ movl(queue_index, tmp); | |
1629 __ addq(tmp, buffer); | |
1630 #else | |
342 | 1631 __ subl(queue_index, wordSize); |
1632 __ movl(tmp, buffer); | |
1633 __ addl(tmp, queue_index); | |
362 | 1634 #endif |
1635 | |
342 | 1636 // prev_val (rax) |
1637 f.load_argument(0, pre_val); | |
362 | 1638 __ movptr(Address(tmp, 0), pre_val); |
342 | 1639 __ jmp(done); |
1640 | |
1641 __ bind(runtime); | |
1572 | 1642 __ push(rcx); |
1643 #ifdef _LP64 | |
1644 __ push(r8); | |
1645 __ push(r9); | |
1646 __ push(r10); | |
1647 __ push(r11); | |
1648 # ifndef _WIN64 | |
1649 __ push(rdi); | |
1650 __ push(rsi); | |
1651 # endif | |
1652 #endif | |
342 | 1653 // load the pre-value |
1654 f.load_argument(0, rcx); | |
1655 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), rcx, thread); | |
1572 | 1656 #ifdef _LP64 |
1657 # ifndef _WIN64 | |
1658 __ pop(rsi); | |
1659 __ pop(rdi); | |
1660 # endif | |
1661 __ pop(r11); | |
1662 __ pop(r10); | |
1663 __ pop(r9); | |
1664 __ pop(r8); | |
1665 #endif | |
362 | 1666 __ pop(rcx); |
1572 | 1667 __ bind(done); |
342 | 1668 |
362 | 1669 __ pop(rdx); |
1670 __ pop(rax); | |
342 | 1671 } |
1672 break; | |
1673 | |
1674 case g1_post_barrier_slow_id: | |
1675 { | |
1676 StubFrame f(sasm, "g1_post_barrier", dont_gc_arguments); | |
1677 | |
1678 | |
1679 // arg0: store_address | |
1680 Address store_addr(rbp, 2*BytesPerWord); | |
1681 | |
1682 BarrierSet* bs = Universe::heap()->barrier_set(); | |
1683 CardTableModRefBS* ct = (CardTableModRefBS*)bs; | |
1684 Label done; | |
1685 Label runtime; | |
1686 | |
1687 // At this point we know new_value is non-NULL and the new_value crosses regsion. | |
1688 // Must check to see if card is already dirty | |
1689 | |
362 | 1690 const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread); |
342 | 1691 |
1692 Address queue_index(thread, in_bytes(JavaThread::dirty_card_queue_offset() + | |
1693 PtrQueue::byte_offset_of_index())); | |
1694 Address buffer(thread, in_bytes(JavaThread::dirty_card_queue_offset() + | |
1695 PtrQueue::byte_offset_of_buf())); | |
1696 | |
362 | 1697 __ push(rax); |
1572 | 1698 __ push(rcx); |
342 | 1699 |
362 | 1700 NOT_LP64(__ get_thread(thread);) |
1701 ExternalAddress cardtable((address)ct->byte_map_base); | |
342 | 1702 assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); |
1703 | |
1572 | 1704 const Register card_addr = rcx; |
362 | 1705 #ifdef _LP64 |
1706 const Register tmp = rscratch1; | |
1707 f.load_argument(0, card_addr); | |
1708 __ shrq(card_addr, CardTableModRefBS::card_shift); | |
1709 __ lea(tmp, cardtable); | |
1710 // get the address of the card | |
1711 __ addq(card_addr, tmp); | |
1712 #else | |
1572 | 1713 const Register card_index = rcx; |
362 | 1714 f.load_argument(0, card_index); |
1715 __ shrl(card_index, CardTableModRefBS::card_shift); | |
1716 | |
342 | 1717 Address index(noreg, card_index, Address::times_1); |
1718 __ leal(card_addr, __ as_Address(ArrayAddress(cardtable, index))); | |
362 | 1719 #endif |
1720 | |
342 | 1721 __ cmpb(Address(card_addr, 0), 0); |
1722 __ jcc(Assembler::equal, done); | |
1723 | |
1724 // storing region crossing non-NULL, card is clean. | |
1725 // dirty card and log. | |
1726 | |
1727 __ movb(Address(card_addr, 0), 0); | |
1728 | |
1729 __ cmpl(queue_index, 0); | |
1730 __ jcc(Assembler::equal, runtime); | |
1731 __ subl(queue_index, wordSize); | |
1732 | |
1733 const Register buffer_addr = rbx; | |
362 | 1734 __ push(rbx); |
1735 | |
1736 __ movptr(buffer_addr, buffer); | |
342 | 1737 |
362 | 1738 #ifdef _LP64 |
1739 __ movslq(rscratch1, queue_index); | |
1740 __ addptr(buffer_addr, rscratch1); | |
1741 #else | |
1742 __ addptr(buffer_addr, queue_index); | |
1743 #endif | |
1744 __ movptr(Address(buffer_addr, 0), card_addr); | |
1745 | |
1746 __ pop(rbx); | |
342 | 1747 __ jmp(done); |
1748 | |
1749 __ bind(runtime); | |
1572 | 1750 __ push(rdx); |
1751 #ifdef _LP64 | |
1752 __ push(r8); | |
1753 __ push(r9); | |
1754 __ push(r10); | |
1755 __ push(r11); | |
1756 # ifndef _WIN64 | |
1757 __ push(rdi); | |
1758 __ push(rsi); | |
1759 # endif | |
1760 #endif | |
342 | 1761 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread); |
1572 | 1762 #ifdef _LP64 |
1763 # ifndef _WIN64 | |
1764 __ pop(rsi); | |
1765 __ pop(rdi); | |
1766 # endif | |
1767 __ pop(r11); | |
1768 __ pop(r10); | |
1769 __ pop(r9); | |
1770 __ pop(r8); | |
1771 #endif | |
1772 __ pop(rdx); | |
1773 __ bind(done); | |
342 | 1774 |
1572 | 1775 __ pop(rcx); |
362 | 1776 __ pop(rax); |
342 | 1777 |
1778 } | |
1779 break; | |
1780 #endif // !SERIALGC | |
1781 | |
0 | 1782 default: |
1783 { StubFrame f(sasm, "unimplemented entry", dont_gc_arguments); | |
304 | 1784 __ movptr(rax, (int)id); |
0 | 1785 __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), rax); |
1786 __ should_not_reach_here(); | |
1787 } | |
1788 break; | |
1789 } | |
1790 return oop_maps; | |
1791 } | |
1792 | |
1793 #undef __ | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1579
diff
changeset
|
1794 |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1579
diff
changeset
|
1795 const char *Runtime1::pd_name_for_address(address entry) { |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1579
diff
changeset
|
1796 return "<unknown function>"; |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1579
diff
changeset
|
1797 } |