Mercurial > hg > graal-jvmci-8
annotate src/cpu/sparc/vm/c1_Runtime1_sparc.cpp @ 2368:dde920245681
6896099: Integrate CMS heap ergo with default heap sizing ergo
6627787: CMS: JVM refuses to start up with -Xms16m -Xmx16m
7000125: CMS: Anti-monotone young gen sizing with respect to maximum whole heap size specification
7027529: CMS: retire CMSUseOldDefaults flag
Summary: Simplify CMS heap sizing code, relying on ergonomic initial sizing consistent with other collectors for the most part, controlling only young gen sizing to rein in pause times. Make CMS young gen sizing default statically cpu-dependant. Remove inconsistencies wrt generation sizing and policy code, allowing for the fixing for 6627787 and 7000125. For 7027529, retire the flag CMSUseOldDefaults which had been introduced as a bridge from JDK 5 to JDK 6 a number of years ago.
Reviewed-by: brutisso, poonam
author | ysr |
---|---|
date | Wed, 16 Mar 2011 10:37:08 -0700 |
parents | 635b068a7224 |
children | 1b4e6a5d98e0 |
rev | line source |
---|---|
0 | 1 /* |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2002
diff
changeset
|
2 * Copyright (c) 1999, 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:
1295
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1295
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:
1295
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_sparc.hpp" | |
31 #include "oops/compiledICHolderOop.hpp" | |
32 #include "oops/oop.inline.hpp" | |
33 #include "prims/jvmtiExport.hpp" | |
34 #include "register_sparc.hpp" | |
35 #include "runtime/sharedRuntime.hpp" | |
36 #include "runtime/signature.hpp" | |
37 #include "runtime/vframeArray.hpp" | |
38 #include "vmreg_sparc.inline.hpp" | |
0 | 39 |
40 // Implementation of StubAssembler | |
41 | |
42 int StubAssembler::call_RT(Register oop_result1, Register oop_result2, address entry_point, int number_of_arguments) { | |
43 // for sparc changing the number of arguments doesn't change | |
44 // anything about the frame size so we'll always lie and claim that | |
45 // we are only passing 1 argument. | |
46 set_num_rt_args(1); | |
47 | |
48 assert_not_delayed(); | |
49 // bang stack before going to runtime | |
50 set(-os::vm_page_size() + STACK_BIAS, G3_scratch); | |
51 st(G0, SP, G3_scratch); | |
52 | |
53 // debugging support | |
54 assert(number_of_arguments >= 0 , "cannot have negative number of arguments"); | |
55 | |
56 set_last_Java_frame(SP, noreg); | |
57 if (VerifyThread) mov(G2_thread, O0); // about to be smashed; pass early | |
58 save_thread(L7_thread_cache); | |
59 // do the call | |
60 call(entry_point, relocInfo::runtime_call_type); | |
61 if (!VerifyThread) { | |
62 delayed()->mov(G2_thread, O0); // pass thread as first argument | |
63 } else { | |
64 delayed()->nop(); // (thread already passed) | |
65 } | |
66 int call_offset = offset(); // offset of return address | |
67 restore_thread(L7_thread_cache); | |
68 reset_last_Java_frame(); | |
69 | |
70 // check for pending exceptions | |
71 { Label L; | |
727 | 72 Address exception_addr(G2_thread, Thread::pending_exception_offset()); |
0 | 73 ld_ptr(exception_addr, Gtemp); |
74 br_null(Gtemp, false, pt, L); | |
75 delayed()->nop(); | |
727 | 76 Address vm_result_addr(G2_thread, JavaThread::vm_result_offset()); |
0 | 77 st_ptr(G0, vm_result_addr); |
727 | 78 Address vm_result_addr_2(G2_thread, JavaThread::vm_result_2_offset()); |
0 | 79 st_ptr(G0, vm_result_addr_2); |
80 | |
81 if (frame_size() == no_frame_size) { | |
82 // we use O7 linkage so that forward_exception_entry has the issuing PC | |
83 call(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); | |
84 delayed()->restore(); | |
85 } else if (_stub_id == Runtime1::forward_exception_id) { | |
86 should_not_reach_here(); | |
87 } else { | |
727 | 88 AddressLiteral exc(Runtime1::entry_for(Runtime1::forward_exception_id)); |
89 jump_to(exc, G4); | |
0 | 90 delayed()->nop(); |
91 } | |
92 bind(L); | |
93 } | |
94 | |
95 // get oop result if there is one and reset the value in the thread | |
96 if (oop_result1->is_valid()) { // get oop result if there is one and reset it in the thread | |
97 get_vm_result (oop_result1); | |
98 } else { | |
99 // be a little paranoid and clear the result | |
727 | 100 Address vm_result_addr(G2_thread, JavaThread::vm_result_offset()); |
0 | 101 st_ptr(G0, vm_result_addr); |
102 } | |
103 | |
104 if (oop_result2->is_valid()) { | |
105 get_vm_result_2(oop_result2); | |
106 } else { | |
107 // be a little paranoid and clear the result | |
727 | 108 Address vm_result_addr_2(G2_thread, JavaThread::vm_result_2_offset()); |
0 | 109 st_ptr(G0, vm_result_addr_2); |
110 } | |
111 | |
112 return call_offset; | |
113 } | |
114 | |
115 | |
116 int StubAssembler::call_RT(Register oop_result1, Register oop_result2, address entry, Register arg1) { | |
117 // O0 is reserved for the thread | |
118 mov(arg1, O1); | |
119 return call_RT(oop_result1, oop_result2, entry, 1); | |
120 } | |
121 | |
122 | |
123 int StubAssembler::call_RT(Register oop_result1, Register oop_result2, address entry, Register arg1, Register arg2) { | |
124 // O0 is reserved for the thread | |
125 mov(arg1, O1); | |
126 mov(arg2, O2); assert(arg2 != O1, "smashed argument"); | |
127 return call_RT(oop_result1, oop_result2, entry, 2); | |
128 } | |
129 | |
130 | |
131 int StubAssembler::call_RT(Register oop_result1, Register oop_result2, address entry, Register arg1, Register arg2, Register arg3) { | |
132 // O0 is reserved for the thread | |
133 mov(arg1, O1); | |
134 mov(arg2, O2); assert(arg2 != O1, "smashed argument"); | |
135 mov(arg3, O3); assert(arg3 != O1 && arg3 != O2, "smashed argument"); | |
136 return call_RT(oop_result1, oop_result2, entry, 3); | |
137 } | |
138 | |
139 | |
140 // Implementation of Runtime1 | |
141 | |
142 #define __ sasm-> | |
143 | |
144 static int cpu_reg_save_offsets[FrameMap::nof_cpu_regs]; | |
145 static int fpu_reg_save_offsets[FrameMap::nof_fpu_regs]; | |
146 static int reg_save_size_in_words; | |
147 static int frame_size_in_bytes = -1; | |
148 | |
149 static OopMap* generate_oop_map(StubAssembler* sasm, bool save_fpu_registers) { | |
150 assert(frame_size_in_bytes == __ total_frame_size_in_bytes(reg_save_size_in_words), | |
151 " mismatch in calculation"); | |
152 sasm->set_frame_size(frame_size_in_bytes / BytesPerWord); | |
153 int frame_size_in_slots = frame_size_in_bytes / sizeof(jint); | |
154 OopMap* oop_map = new OopMap(frame_size_in_slots, 0); | |
155 | |
156 int i; | |
157 for (i = 0; i < FrameMap::nof_cpu_regs; i++) { | |
158 Register r = as_Register(i); | |
159 if (r == G1 || r == G3 || r == G4 || r == G5) { | |
160 int sp_offset = cpu_reg_save_offsets[i]; | |
161 oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset), | |
162 r->as_VMReg()); | |
163 } | |
164 } | |
165 | |
166 if (save_fpu_registers) { | |
167 for (i = 0; i < FrameMap::nof_fpu_regs; i++) { | |
168 FloatRegister r = as_FloatRegister(i); | |
169 int sp_offset = fpu_reg_save_offsets[i]; | |
170 oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset), | |
171 r->as_VMReg()); | |
172 } | |
173 } | |
174 return oop_map; | |
175 } | |
176 | |
177 static OopMap* save_live_registers(StubAssembler* sasm, bool save_fpu_registers = true) { | |
178 assert(frame_size_in_bytes == __ total_frame_size_in_bytes(reg_save_size_in_words), | |
179 " mismatch in calculation"); | |
180 __ save_frame_c1(frame_size_in_bytes); | |
181 sasm->set_frame_size(frame_size_in_bytes / BytesPerWord); | |
182 | |
183 // Record volatile registers as callee-save values in an OopMap so their save locations will be | |
184 // propagated to the caller frame's RegisterMap during StackFrameStream construction (needed for | |
185 // deoptimization; see compiledVFrame::create_stack_value). The caller's I, L and O registers | |
186 // are saved in register windows - I's and L's in the caller's frame and O's in the stub frame | |
187 // (as the stub's I's) when the runtime routine called by the stub creates its frame. | |
188 // OopMap frame sizes are in c2 stack slot sizes (sizeof(jint)) | |
189 | |
190 int i; | |
191 for (i = 0; i < FrameMap::nof_cpu_regs; i++) { | |
192 Register r = as_Register(i); | |
193 if (r == G1 || r == G3 || r == G4 || r == G5) { | |
194 int sp_offset = cpu_reg_save_offsets[i]; | |
195 __ st_ptr(r, SP, (sp_offset * BytesPerWord) + STACK_BIAS); | |
196 } | |
197 } | |
198 | |
199 if (save_fpu_registers) { | |
200 for (i = 0; i < FrameMap::nof_fpu_regs; i++) { | |
201 FloatRegister r = as_FloatRegister(i); | |
202 int sp_offset = fpu_reg_save_offsets[i]; | |
203 __ stf(FloatRegisterImpl::S, r, SP, (sp_offset * BytesPerWord) + STACK_BIAS); | |
204 } | |
205 } | |
206 | |
207 return generate_oop_map(sasm, save_fpu_registers); | |
208 } | |
209 | |
210 static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = true) { | |
211 for (int i = 0; i < FrameMap::nof_cpu_regs; i++) { | |
212 Register r = as_Register(i); | |
213 if (r == G1 || r == G3 || r == G4 || r == G5) { | |
214 __ ld_ptr(SP, (cpu_reg_save_offsets[i] * BytesPerWord) + STACK_BIAS, r); | |
215 } | |
216 } | |
217 | |
218 if (restore_fpu_registers) { | |
219 for (int i = 0; i < FrameMap::nof_fpu_regs; i++) { | |
220 FloatRegister r = as_FloatRegister(i); | |
221 __ ldf(FloatRegisterImpl::S, SP, (fpu_reg_save_offsets[i] * BytesPerWord) + STACK_BIAS, r); | |
222 } | |
223 } | |
224 } | |
225 | |
226 | |
227 void Runtime1::initialize_pd() { | |
228 // compute word offsets from SP at which live (non-windowed) registers are captured by stub routines | |
229 // | |
230 // A stub routine will have a frame that is at least large enough to hold | |
231 // a register window save area (obviously) and the volatile g registers | |
232 // and floating registers. A user of save_live_registers can have a frame | |
233 // that has more scratch area in it (although typically they will use L-regs). | |
234 // in that case the frame will look like this (stack growing down) | |
235 // | |
236 // FP -> | | | |
237 // | scratch mem | | |
238 // | " " | | |
239 // -------------- | |
240 // | float regs | | |
241 // | " " | | |
242 // --------------- | |
243 // | G regs | | |
244 // | " " | | |
245 // --------------- | |
246 // | abi reg. | | |
247 // | window save | | |
248 // | area | | |
249 // SP -> --------------- | |
250 // | |
251 int i; | |
252 int sp_offset = round_to(frame::register_save_words, 2); // start doubleword aligned | |
253 | |
254 // only G int registers are saved explicitly; others are found in register windows | |
255 for (i = 0; i < FrameMap::nof_cpu_regs; i++) { | |
256 Register r = as_Register(i); | |
257 if (r == G1 || r == G3 || r == G4 || r == G5) { | |
258 cpu_reg_save_offsets[i] = sp_offset; | |
259 sp_offset++; | |
260 } | |
261 } | |
262 | |
263 // all float registers are saved explicitly | |
264 assert(FrameMap::nof_fpu_regs == 32, "double registers not handled here"); | |
265 for (i = 0; i < FrameMap::nof_fpu_regs; i++) { | |
266 fpu_reg_save_offsets[i] = sp_offset; | |
267 sp_offset++; | |
268 } | |
269 reg_save_size_in_words = sp_offset - frame::memory_parameter_word_sp_offset; | |
270 // this should match assembler::total_frame_size_in_bytes, which | |
271 // isn't callable from this context. It's checked by an assert when | |
272 // it's used though. | |
273 frame_size_in_bytes = align_size_up(sp_offset * wordSize, 8); | |
274 } | |
275 | |
276 | |
277 OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address target, bool has_argument) { | |
278 // make a frame and preserve the caller's caller-save registers | |
279 OopMap* oop_map = save_live_registers(sasm); | |
280 int call_offset; | |
281 if (!has_argument) { | |
282 call_offset = __ call_RT(noreg, noreg, target); | |
283 } else { | |
284 call_offset = __ call_RT(noreg, noreg, target, G4); | |
285 } | |
286 OopMapSet* oop_maps = new OopMapSet(); | |
287 oop_maps->add_gc_map(call_offset, oop_map); | |
288 | |
289 __ should_not_reach_here(); | |
290 return oop_maps; | |
291 } | |
292 | |
293 | |
294 OopMapSet* Runtime1::generate_stub_call(StubAssembler* sasm, Register result, address target, | |
295 Register arg1, Register arg2, Register arg3) { | |
296 // make a frame and preserve the caller's caller-save registers | |
297 OopMap* oop_map = save_live_registers(sasm); | |
298 | |
299 int call_offset; | |
300 if (arg1 == noreg) { | |
301 call_offset = __ call_RT(result, noreg, target); | |
302 } else if (arg2 == noreg) { | |
303 call_offset = __ call_RT(result, noreg, target, arg1); | |
304 } else if (arg3 == noreg) { | |
305 call_offset = __ call_RT(result, noreg, target, arg1, arg2); | |
306 } else { | |
307 call_offset = __ call_RT(result, noreg, target, arg1, arg2, arg3); | |
308 } | |
309 OopMapSet* oop_maps = NULL; | |
310 | |
311 oop_maps = new OopMapSet(); | |
312 oop_maps->add_gc_map(call_offset, oop_map); | |
313 restore_live_registers(sasm); | |
314 | |
315 __ ret(); | |
316 __ delayed()->restore(); | |
317 | |
318 return oop_maps; | |
319 } | |
320 | |
321 | |
322 OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { | |
323 // make a frame and preserve the caller's caller-save registers | |
324 OopMap* oop_map = save_live_registers(sasm); | |
325 | |
326 // call the runtime patching routine, returns non-zero if nmethod got deopted. | |
327 int call_offset = __ call_RT(noreg, noreg, target); | |
328 OopMapSet* oop_maps = new OopMapSet(); | |
329 oop_maps->add_gc_map(call_offset, oop_map); | |
330 | |
331 // re-execute the patched instruction or, if the nmethod was deoptmized, return to the | |
332 // deoptimization handler entry that will cause re-execution of the current bytecode | |
333 DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob(); | |
334 assert(deopt_blob != NULL, "deoptimization blob must have been created"); | |
335 | |
336 Label no_deopt; | |
337 __ tst(O0); | |
338 __ brx(Assembler::equal, false, Assembler::pt, no_deopt); | |
339 __ delayed()->nop(); | |
340 | |
341 // return to the deoptimization handler entry for unpacking and rexecute | |
342 // if we simply returned the we'd deopt as if any call we patched had just | |
343 // returned. | |
344 | |
345 restore_live_registers(sasm); | |
2156
85330eaa15ee
7013812: C1: deopt blob too far from patching stub
iveresov
parents:
2127
diff
changeset
|
346 |
85330eaa15ee
7013812: C1: deopt blob too far from patching stub
iveresov
parents:
2127
diff
changeset
|
347 AddressLiteral dest(deopt_blob->unpack_with_reexecution()); |
85330eaa15ee
7013812: C1: deopt blob too far from patching stub
iveresov
parents:
2127
diff
changeset
|
348 __ jump_to(dest, O0); |
85330eaa15ee
7013812: C1: deopt blob too far from patching stub
iveresov
parents:
2127
diff
changeset
|
349 __ delayed()->restore(); |
0 | 350 |
351 __ bind(no_deopt); | |
352 restore_live_registers(sasm); | |
353 __ ret(); | |
354 __ delayed()->restore(); | |
355 | |
356 return oop_maps; | |
357 } | |
358 | |
359 OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { | |
360 | |
361 OopMapSet* oop_maps = NULL; | |
362 // for better readability | |
363 const bool must_gc_arguments = true; | |
364 const bool dont_gc_arguments = false; | |
365 | |
366 // stub code & info for the different stubs | |
367 switch (id) { | |
368 case forward_exception_id: | |
369 { | |
370 // we're handling an exception in the context of a compiled | |
371 // frame. The registers have been saved in the standard | |
372 // places. Perform an exception lookup in the caller and | |
373 // dispatch to the handler if found. Otherwise unwind and | |
374 // dispatch to the callers exception handler. | |
375 | |
376 oop_maps = new OopMapSet(); | |
377 OopMap* oop_map = generate_oop_map(sasm, true); | |
378 | |
379 // transfer the pending exception to the exception_oop | |
380 __ ld_ptr(G2_thread, in_bytes(JavaThread::pending_exception_offset()), Oexception); | |
381 __ ld_ptr(Oexception, 0, G0); | |
382 __ st_ptr(G0, G2_thread, in_bytes(JavaThread::pending_exception_offset())); | |
383 __ add(I7, frame::pc_return_offset, Oissuing_pc); | |
384 | |
385 generate_handle_exception(sasm, oop_maps, oop_map); | |
386 __ should_not_reach_here(); | |
387 } | |
388 break; | |
389 | |
390 case new_instance_id: | |
391 case fast_new_instance_id: | |
392 case fast_new_instance_init_check_id: | |
393 { | |
394 Register G5_klass = G5; // Incoming | |
395 Register O0_obj = O0; // Outgoing | |
396 | |
397 if (id == new_instance_id) { | |
398 __ set_info("new_instance", dont_gc_arguments); | |
399 } else if (id == fast_new_instance_id) { | |
400 __ set_info("fast new_instance", dont_gc_arguments); | |
401 } else { | |
402 assert(id == fast_new_instance_init_check_id, "bad StubID"); | |
403 __ set_info("fast new_instance init check", dont_gc_arguments); | |
404 } | |
405 | |
406 if ((id == fast_new_instance_id || id == fast_new_instance_init_check_id) && | |
407 UseTLAB && FastTLABRefill) { | |
408 Label slow_path; | |
409 Register G1_obj_size = G1; | |
410 Register G3_t1 = G3; | |
411 Register G4_t2 = G4; | |
412 assert_different_registers(G5_klass, G1_obj_size, G3_t1, G4_t2); | |
413 | |
414 // Push a frame since we may do dtrace notification for the | |
415 // allocation which requires calling out and we don't want | |
416 // to stomp the real return address. | |
417 __ save_frame(0); | |
418 | |
419 if (id == fast_new_instance_init_check_id) { | |
420 // make sure the klass is initialized | |
421 __ ld(G5_klass, instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc), G3_t1); | |
422 __ cmp(G3_t1, instanceKlass::fully_initialized); | |
423 __ br(Assembler::notEqual, false, Assembler::pn, slow_path); | |
424 __ delayed()->nop(); | |
425 } | |
426 #ifdef ASSERT | |
427 // assert object can be fast path allocated | |
428 { | |
429 Label ok, not_ok; | |
430 __ ld(G5_klass, Klass::layout_helper_offset_in_bytes() + sizeof(oopDesc), G1_obj_size); | |
431 __ cmp(G1_obj_size, 0); // make sure it's an instance (LH > 0) | |
432 __ br(Assembler::lessEqual, false, Assembler::pn, not_ok); | |
433 __ delayed()->nop(); | |
434 __ btst(Klass::_lh_instance_slow_path_bit, G1_obj_size); | |
435 __ br(Assembler::zero, false, Assembler::pn, ok); | |
436 __ delayed()->nop(); | |
437 __ bind(not_ok); | |
438 __ stop("assert(can be fast path allocated)"); | |
439 __ should_not_reach_here(); | |
440 __ bind(ok); | |
441 } | |
442 #endif // ASSERT | |
443 // if we got here then the TLAB allocation failed, so try | |
444 // refilling the TLAB or allocating directly from eden. | |
445 Label retry_tlab, try_eden; | |
446 __ tlab_refill(retry_tlab, try_eden, slow_path); // preserves G5_klass | |
447 | |
448 __ bind(retry_tlab); | |
449 | |
450 // get the instance size | |
451 __ ld(G5_klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes(), G1_obj_size); | |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2002
diff
changeset
|
452 |
0 | 453 __ tlab_allocate(O0_obj, G1_obj_size, 0, G3_t1, slow_path); |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2002
diff
changeset
|
454 |
0 | 455 __ initialize_object(O0_obj, G5_klass, G1_obj_size, 0, G3_t1, G4_t2); |
456 __ verify_oop(O0_obj); | |
457 __ mov(O0, I0); | |
458 __ ret(); | |
459 __ delayed()->restore(); | |
460 | |
461 __ bind(try_eden); | |
462 // get the instance size | |
463 __ ld(G5_klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes(), G1_obj_size); | |
464 __ eden_allocate(O0_obj, G1_obj_size, 0, G3_t1, G4_t2, slow_path); | |
2127
5577848f5923
7011463: Sparc MacroAssembler::incr_allocated_bytes() needs a RegisterOrConstant argument
phh
parents:
2100
diff
changeset
|
465 __ incr_allocated_bytes(G1_obj_size, G3_t1, G4_t2); |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2002
diff
changeset
|
466 |
0 | 467 __ initialize_object(O0_obj, G5_klass, G1_obj_size, 0, G3_t1, G4_t2); |
468 __ verify_oop(O0_obj); | |
469 __ mov(O0, I0); | |
470 __ ret(); | |
471 __ delayed()->restore(); | |
472 | |
473 __ bind(slow_path); | |
474 | |
475 // pop this frame so generate_stub_call can push it's own | |
476 __ restore(); | |
477 } | |
478 | |
479 oop_maps = generate_stub_call(sasm, I0, CAST_FROM_FN_PTR(address, new_instance), G5_klass); | |
480 // I0->O0: new instance | |
481 } | |
482 | |
483 break; | |
484 | |
485 case counter_overflow_id: | |
1783 | 486 // G4 contains bci, G5 contains method |
487 oop_maps = generate_stub_call(sasm, noreg, CAST_FROM_FN_PTR(address, counter_overflow), G4, G5); | |
0 | 488 break; |
489 | |
490 case new_type_array_id: | |
491 case new_object_array_id: | |
492 { | |
493 Register G5_klass = G5; // Incoming | |
494 Register G4_length = G4; // Incoming | |
495 Register O0_obj = O0; // Outgoing | |
496 | |
727 | 497 Address klass_lh(G5_klass, ((klassOopDesc::header_size() * HeapWordSize) |
498 + Klass::layout_helper_offset_in_bytes())); | |
0 | 499 assert(Klass::_lh_header_size_shift % BitsPerByte == 0, "bytewise"); |
500 assert(Klass::_lh_header_size_mask == 0xFF, "bytewise"); | |
501 // Use this offset to pick out an individual byte of the layout_helper: | |
502 const int klass_lh_header_size_offset = ((BytesPerInt - 1) // 3 - 2 selects byte {0,1,0,0} | |
503 - Klass::_lh_header_size_shift / BitsPerByte); | |
504 | |
505 if (id == new_type_array_id) { | |
506 __ set_info("new_type_array", dont_gc_arguments); | |
507 } else { | |
508 __ set_info("new_object_array", dont_gc_arguments); | |
509 } | |
510 | |
511 #ifdef ASSERT | |
512 // assert object type is really an array of the proper kind | |
513 { | |
514 Label ok; | |
515 Register G3_t1 = G3; | |
516 __ ld(klass_lh, G3_t1); | |
517 __ sra(G3_t1, Klass::_lh_array_tag_shift, G3_t1); | |
518 int tag = ((id == new_type_array_id) | |
519 ? Klass::_lh_array_tag_type_value | |
520 : Klass::_lh_array_tag_obj_value); | |
521 __ cmp(G3_t1, tag); | |
522 __ brx(Assembler::equal, false, Assembler::pt, ok); | |
523 __ delayed()->nop(); | |
524 __ stop("assert(is an array klass)"); | |
525 __ should_not_reach_here(); | |
526 __ bind(ok); | |
527 } | |
528 #endif // ASSERT | |
529 | |
530 if (UseTLAB && FastTLABRefill) { | |
531 Label slow_path; | |
532 Register G1_arr_size = G1; | |
533 Register G3_t1 = G3; | |
534 Register O1_t2 = O1; | |
535 assert_different_registers(G5_klass, G4_length, G1_arr_size, G3_t1, O1_t2); | |
536 | |
537 // check that array length is small enough for fast path | |
538 __ set(C1_MacroAssembler::max_array_allocation_length, G3_t1); | |
539 __ cmp(G4_length, G3_t1); | |
540 __ br(Assembler::greaterUnsigned, false, Assembler::pn, slow_path); | |
541 __ delayed()->nop(); | |
542 | |
543 // if we got here then the TLAB allocation failed, so try | |
544 // refilling the TLAB or allocating directly from eden. | |
545 Label retry_tlab, try_eden; | |
546 __ tlab_refill(retry_tlab, try_eden, slow_path); // preserves G4_length and G5_klass | |
547 | |
548 __ bind(retry_tlab); | |
549 | |
550 // get the allocation size: (length << (layout_helper & 0x1F)) + header_size | |
551 __ ld(klass_lh, G3_t1); | |
552 __ sll(G4_length, G3_t1, G1_arr_size); | |
553 __ srl(G3_t1, Klass::_lh_header_size_shift, G3_t1); | |
554 __ and3(G3_t1, Klass::_lh_header_size_mask, G3_t1); | |
555 __ add(G1_arr_size, G3_t1, G1_arr_size); | |
556 __ add(G1_arr_size, MinObjAlignmentInBytesMask, G1_arr_size); // align up | |
557 __ and3(G1_arr_size, ~MinObjAlignmentInBytesMask, G1_arr_size); | |
558 | |
559 __ tlab_allocate(O0_obj, G1_arr_size, 0, G3_t1, slow_path); // preserves G1_arr_size | |
560 | |
561 __ initialize_header(O0_obj, G5_klass, G4_length, G3_t1, O1_t2); | |
562 __ ldub(klass_lh, G3_t1, klass_lh_header_size_offset); | |
563 __ sub(G1_arr_size, G3_t1, O1_t2); // body length | |
564 __ add(O0_obj, G3_t1, G3_t1); // body start | |
565 __ initialize_body(G3_t1, O1_t2); | |
566 __ verify_oop(O0_obj); | |
567 __ retl(); | |
568 __ delayed()->nop(); | |
569 | |
570 __ bind(try_eden); | |
571 // get the allocation size: (length << (layout_helper & 0x1F)) + header_size | |
572 __ ld(klass_lh, G3_t1); | |
573 __ sll(G4_length, G3_t1, G1_arr_size); | |
574 __ srl(G3_t1, Klass::_lh_header_size_shift, G3_t1); | |
575 __ and3(G3_t1, Klass::_lh_header_size_mask, G3_t1); | |
576 __ add(G1_arr_size, G3_t1, G1_arr_size); | |
577 __ add(G1_arr_size, MinObjAlignmentInBytesMask, G1_arr_size); | |
578 __ and3(G1_arr_size, ~MinObjAlignmentInBytesMask, G1_arr_size); | |
579 | |
580 __ eden_allocate(O0_obj, G1_arr_size, 0, G3_t1, O1_t2, slow_path); // preserves G1_arr_size | |
2127
5577848f5923
7011463: Sparc MacroAssembler::incr_allocated_bytes() needs a RegisterOrConstant argument
phh
parents:
2100
diff
changeset
|
581 __ incr_allocated_bytes(G1_arr_size, G3_t1, O1_t2); |
0 | 582 |
583 __ initialize_header(O0_obj, G5_klass, G4_length, G3_t1, O1_t2); | |
584 __ ldub(klass_lh, G3_t1, klass_lh_header_size_offset); | |
585 __ sub(G1_arr_size, G3_t1, O1_t2); // body length | |
586 __ add(O0_obj, G3_t1, G3_t1); // body start | |
587 __ initialize_body(G3_t1, O1_t2); | |
588 __ verify_oop(O0_obj); | |
589 __ retl(); | |
590 __ delayed()->nop(); | |
591 | |
592 __ bind(slow_path); | |
593 } | |
594 | |
595 if (id == new_type_array_id) { | |
596 oop_maps = generate_stub_call(sasm, I0, CAST_FROM_FN_PTR(address, new_type_array), G5_klass, G4_length); | |
597 } else { | |
598 oop_maps = generate_stub_call(sasm, I0, CAST_FROM_FN_PTR(address, new_object_array), G5_klass, G4_length); | |
599 } | |
600 // I0 -> O0: new array | |
601 } | |
602 break; | |
603 | |
604 case new_multi_array_id: | |
605 { // O0: klass | |
606 // O1: rank | |
607 // O2: address of 1st dimension | |
608 __ set_info("new_multi_array", dont_gc_arguments); | |
609 oop_maps = generate_stub_call(sasm, I0, CAST_FROM_FN_PTR(address, new_multi_array), I0, I1, I2); | |
610 // I0 -> O0: new multi array | |
611 } | |
612 break; | |
613 | |
614 case register_finalizer_id: | |
615 { | |
616 __ set_info("register_finalizer", dont_gc_arguments); | |
617 | |
618 // load the klass and check the has finalizer flag | |
619 Label register_finalizer; | |
620 Register t = O1; | |
2002 | 621 __ load_klass(O0, t); |
0 | 622 __ ld(t, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc), t); |
623 __ set(JVM_ACC_HAS_FINALIZER, G3); | |
624 __ andcc(G3, t, G0); | |
625 __ br(Assembler::notZero, false, Assembler::pt, register_finalizer); | |
626 __ delayed()->nop(); | |
627 | |
628 // do a leaf return | |
629 __ retl(); | |
630 __ delayed()->nop(); | |
631 | |
632 __ bind(register_finalizer); | |
633 OopMap* oop_map = save_live_registers(sasm); | |
634 int call_offset = __ call_RT(noreg, noreg, | |
635 CAST_FROM_FN_PTR(address, SharedRuntime::register_finalizer), I0); | |
636 oop_maps = new OopMapSet(); | |
637 oop_maps->add_gc_map(call_offset, oop_map); | |
638 | |
639 // Now restore all the live registers | |
640 restore_live_registers(sasm); | |
641 | |
642 __ ret(); | |
643 __ delayed()->restore(); | |
644 } | |
645 break; | |
646 | |
647 case throw_range_check_failed_id: | |
648 { __ set_info("range_check_failed", dont_gc_arguments); // arguments will be discarded | |
649 // G4: index | |
650 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_range_check_exception), true); | |
651 } | |
652 break; | |
653 | |
654 case throw_index_exception_id: | |
655 { __ set_info("index_range_check_failed", dont_gc_arguments); // arguments will be discarded | |
656 // G4: index | |
657 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_index_exception), true); | |
658 } | |
659 break; | |
660 | |
661 case throw_div0_exception_id: | |
662 { __ set_info("throw_div0_exception", dont_gc_arguments); | |
663 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_div0_exception), false); | |
664 } | |
665 break; | |
666 | |
667 case throw_null_pointer_exception_id: | |
668 { __ set_info("throw_null_pointer_exception", dont_gc_arguments); | |
669 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_null_pointer_exception), false); | |
670 } | |
671 break; | |
672 | |
673 case handle_exception_id: | |
674 { | |
675 __ set_info("handle_exception", dont_gc_arguments); | |
676 // make a frame and preserve the caller's caller-save registers | |
677 | |
678 oop_maps = new OopMapSet(); | |
679 OopMap* oop_map = save_live_registers(sasm); | |
680 __ mov(Oexception->after_save(), Oexception); | |
681 __ mov(Oissuing_pc->after_save(), Oissuing_pc); | |
682 generate_handle_exception(sasm, oop_maps, oop_map); | |
683 } | |
684 break; | |
685 | |
686 case unwind_exception_id: | |
687 { | |
688 // O0: exception | |
689 // I7: address of call to this method | |
690 | |
691 __ set_info("unwind_exception", dont_gc_arguments); | |
692 __ mov(Oexception, Oexception->after_save()); | |
693 __ add(I7, frame::pc_return_offset, Oissuing_pc->after_save()); | |
694 | |
695 __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), | |
1295 | 696 G2_thread, Oissuing_pc->after_save()); |
0 | 697 __ verify_not_null_oop(Oexception->after_save()); |
1564 | 698 |
699 // Restore SP from L7 if the exception PC is a MethodHandle call site. | |
700 __ mov(O0, G5); // Save the target address. | |
701 __ lduw(Address(G2_thread, JavaThread::is_method_handle_return_offset()), L0); | |
702 __ tst(L0); // Condition codes are preserved over the restore. | |
703 __ restore(); | |
704 | |
705 __ jmp(G5, 0); | |
706 __ delayed()->movcc(Assembler::notZero, false, Assembler::icc, L7_mh_SP_save, SP); // Restore SP if required. | |
0 | 707 } |
708 break; | |
709 | |
710 case throw_array_store_exception_id: | |
711 { | |
712 __ set_info("throw_array_store_exception", dont_gc_arguments); | |
2168
e4fee0bdaa85
7008809: should report the class in ArrayStoreExceptions from compiled code
never
parents:
2127
diff
changeset
|
713 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true); |
0 | 714 } |
715 break; | |
716 | |
717 case throw_class_cast_exception_id: | |
718 { | |
719 // G4: object | |
720 __ set_info("throw_class_cast_exception", dont_gc_arguments); | |
721 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true); | |
722 } | |
723 break; | |
724 | |
725 case throw_incompatible_class_change_error_id: | |
726 { | |
727 __ set_info("throw_incompatible_class_cast_exception", dont_gc_arguments); | |
728 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false); | |
729 } | |
730 break; | |
731 | |
732 case slow_subtype_check_id: | |
733 { // Support for uint StubRoutine::partial_subtype_check( Klass sub, Klass super ); | |
734 // Arguments : | |
735 // | |
736 // ret : G3 | |
737 // sub : G3, argument, destroyed | |
738 // super: G1, argument, not changed | |
739 // raddr: O7, blown by call | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
342
diff
changeset
|
740 Label miss; |
0 | 741 |
742 __ save_frame(0); // Blow no registers! | |
743 | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
342
diff
changeset
|
744 __ check_klass_subtype_slow_path(G3, G1, L0, L1, L2, L4, NULL, &miss); |
0 | 745 |
746 __ mov(1, G3); | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
342
diff
changeset
|
747 __ ret(); // Result in G5 is 'true' |
0 | 748 __ delayed()->restore(); // free copy or add can go here |
749 | |
750 __ bind(miss); | |
751 __ mov(0, G3); | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
342
diff
changeset
|
752 __ ret(); // Result in G5 is 'false' |
0 | 753 __ delayed()->restore(); // free copy or add can go here |
754 } | |
755 | |
756 case monitorenter_nofpu_id: | |
757 case monitorenter_id: | |
758 { // G4: object | |
759 // G5: lock address | |
760 __ set_info("monitorenter", dont_gc_arguments); | |
761 | |
762 int save_fpu_registers = (id == monitorenter_id); | |
763 // make a frame and preserve the caller's caller-save registers | |
764 OopMap* oop_map = save_live_registers(sasm, save_fpu_registers); | |
765 | |
766 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorenter), G4, G5); | |
767 | |
768 oop_maps = new OopMapSet(); | |
769 oop_maps->add_gc_map(call_offset, oop_map); | |
770 restore_live_registers(sasm, save_fpu_registers); | |
771 | |
772 __ ret(); | |
773 __ delayed()->restore(); | |
774 } | |
775 break; | |
776 | |
777 case monitorexit_nofpu_id: | |
778 case monitorexit_id: | |
779 { // G4: lock address | |
780 // note: really a leaf routine but must setup last java sp | |
781 // => use call_RT for now (speed can be improved by | |
782 // doing last java sp setup manually) | |
783 __ set_info("monitorexit", dont_gc_arguments); | |
784 | |
785 int save_fpu_registers = (id == monitorexit_id); | |
786 // make a frame and preserve the caller's caller-save registers | |
787 OopMap* oop_map = save_live_registers(sasm, save_fpu_registers); | |
788 | |
789 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorexit), G4); | |
790 | |
791 oop_maps = new OopMapSet(); | |
792 oop_maps->add_gc_map(call_offset, oop_map); | |
793 restore_live_registers(sasm, save_fpu_registers); | |
794 | |
795 __ ret(); | |
796 __ delayed()->restore(); | |
797 | |
798 } | |
799 break; | |
800 | |
801 case access_field_patching_id: | |
802 { __ set_info("access_field_patching", dont_gc_arguments); | |
803 oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, access_field_patching)); | |
804 } | |
805 break; | |
806 | |
807 case load_klass_patching_id: | |
808 { __ set_info("load_klass_patching", dont_gc_arguments); | |
809 oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_klass_patching)); | |
810 } | |
811 break; | |
812 | |
813 case jvmti_exception_throw_id: | |
814 { // Oexception : exception | |
815 __ set_info("jvmti_exception_throw", dont_gc_arguments); | |
816 oop_maps = generate_stub_call(sasm, noreg, CAST_FROM_FN_PTR(address, Runtime1::post_jvmti_exception_throw), I0); | |
817 } | |
818 break; | |
819 | |
820 case dtrace_object_alloc_id: | |
821 { // O0: object | |
822 __ set_info("dtrace_object_alloc", dont_gc_arguments); | |
823 // we can't gc here so skip the oopmap but make sure that all | |
824 // the live registers get saved. | |
825 save_live_registers(sasm); | |
826 | |
827 __ save_thread(L7_thread_cache); | |
828 __ call(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), | |
829 relocInfo::runtime_call_type); | |
830 __ delayed()->mov(I0, O0); | |
831 __ restore_thread(L7_thread_cache); | |
832 | |
833 restore_live_registers(sasm); | |
834 __ ret(); | |
835 __ delayed()->restore(); | |
836 } | |
837 break; | |
838 | |
342 | 839 #ifndef SERIALGC |
840 case g1_pre_barrier_slow_id: | |
841 { // G4: previous value of memory | |
842 BarrierSet* bs = Universe::heap()->barrier_set(); | |
843 if (bs->kind() != BarrierSet::G1SATBCTLogging) { | |
844 __ save_frame(0); | |
845 __ set((int)id, O1); | |
846 __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), I0); | |
847 __ should_not_reach_here(); | |
848 break; | |
849 } | |
850 | |
851 __ set_info("g1_pre_barrier_slow_id", dont_gc_arguments); | |
852 | |
853 Register pre_val = G4; | |
854 Register tmp = G1_scratch; | |
855 Register tmp2 = G3_scratch; | |
856 | |
857 Label refill, restart; | |
858 bool with_frame = false; // I don't know if we can do with-frame. | |
859 int satb_q_index_byte_offset = | |
860 in_bytes(JavaThread::satb_mark_queue_offset() + | |
861 PtrQueue::byte_offset_of_index()); | |
862 int satb_q_buf_byte_offset = | |
863 in_bytes(JavaThread::satb_mark_queue_offset() + | |
864 PtrQueue::byte_offset_of_buf()); | |
865 __ bind(restart); | |
866 __ ld_ptr(G2_thread, satb_q_index_byte_offset, tmp); | |
867 | |
868 __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, | |
869 Assembler::pn, tmp, refill); | |
870 | |
871 // If the branch is taken, no harm in executing this in the delay slot. | |
872 __ delayed()->ld_ptr(G2_thread, satb_q_buf_byte_offset, tmp2); | |
873 __ sub(tmp, oopSize, tmp); | |
874 | |
875 __ st_ptr(pre_val, tmp2, tmp); // [_buf + index] := <address_of_card> | |
876 // Use return-from-leaf | |
877 __ retl(); | |
878 __ delayed()->st_ptr(tmp, G2_thread, satb_q_index_byte_offset); | |
879 | |
880 __ bind(refill); | |
881 __ save_frame(0); | |
882 | |
883 __ mov(pre_val, L0); | |
884 __ mov(tmp, L1); | |
885 __ mov(tmp2, L2); | |
886 | |
887 __ call_VM_leaf(L7_thread_cache, | |
888 CAST_FROM_FN_PTR(address, | |
889 SATBMarkQueueSet::handle_zero_index_for_thread), | |
890 G2_thread); | |
891 | |
892 __ mov(L0, pre_val); | |
893 __ mov(L1, tmp); | |
894 __ mov(L2, tmp2); | |
895 | |
896 __ br(Assembler::always, /*annul*/false, Assembler::pt, restart); | |
897 __ delayed()->restore(); | |
898 } | |
899 break; | |
900 | |
901 case g1_post_barrier_slow_id: | |
902 { | |
903 BarrierSet* bs = Universe::heap()->barrier_set(); | |
904 if (bs->kind() != BarrierSet::G1SATBCTLogging) { | |
905 __ save_frame(0); | |
906 __ set((int)id, O1); | |
907 __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), I0); | |
908 __ should_not_reach_here(); | |
909 break; | |
910 } | |
911 | |
912 __ set_info("g1_post_barrier_slow_id", dont_gc_arguments); | |
913 | |
914 Register addr = G4; | |
915 Register cardtable = G5; | |
916 Register tmp = G1_scratch; | |
917 Register tmp2 = G3_scratch; | |
918 jbyte* byte_map_base = ((CardTableModRefBS*)bs)->byte_map_base; | |
919 | |
920 Label not_already_dirty, restart, refill; | |
921 | |
922 #ifdef _LP64 | |
923 __ srlx(addr, CardTableModRefBS::card_shift, addr); | |
924 #else | |
925 __ srl(addr, CardTableModRefBS::card_shift, addr); | |
926 #endif | |
927 | |
727 | 928 AddressLiteral rs(byte_map_base); |
929 __ set(rs, cardtable); // cardtable := <card table base> | |
342 | 930 __ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable] |
931 | |
932 __ br_on_reg_cond(Assembler::rc_nz, /*annul*/false, Assembler::pt, | |
933 tmp, not_already_dirty); | |
934 // Get cardtable + tmp into a reg by itself -- useful in the take-the-branch | |
935 // case, harmless if not. | |
936 __ delayed()->add(addr, cardtable, tmp2); | |
937 | |
938 // We didn't take the branch, so we're already dirty: return. | |
939 // Use return-from-leaf | |
940 __ retl(); | |
941 __ delayed()->nop(); | |
942 | |
943 // Not dirty. | |
944 __ bind(not_already_dirty); | |
945 // First, dirty it. | |
946 __ stb(G0, tmp2, 0); // [cardPtr] := 0 (i.e., dirty). | |
947 | |
948 Register tmp3 = cardtable; | |
949 Register tmp4 = tmp; | |
950 | |
951 // these registers are now dead | |
952 addr = cardtable = tmp = noreg; | |
953 | |
954 int dirty_card_q_index_byte_offset = | |
955 in_bytes(JavaThread::dirty_card_queue_offset() + | |
956 PtrQueue::byte_offset_of_index()); | |
957 int dirty_card_q_buf_byte_offset = | |
958 in_bytes(JavaThread::dirty_card_queue_offset() + | |
959 PtrQueue::byte_offset_of_buf()); | |
960 __ bind(restart); | |
961 __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, tmp3); | |
962 | |
963 __ br_on_reg_cond(Assembler::rc_z, /*annul*/false, Assembler::pn, | |
964 tmp3, refill); | |
965 // If the branch is taken, no harm in executing this in the delay slot. | |
966 __ delayed()->ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, tmp4); | |
967 __ sub(tmp3, oopSize, tmp3); | |
968 | |
969 __ st_ptr(tmp2, tmp4, tmp3); // [_buf + index] := <address_of_card> | |
970 // Use return-from-leaf | |
971 __ retl(); | |
972 __ delayed()->st_ptr(tmp3, G2_thread, dirty_card_q_index_byte_offset); | |
973 | |
974 __ bind(refill); | |
975 __ save_frame(0); | |
976 | |
977 __ mov(tmp2, L0); | |
978 __ mov(tmp3, L1); | |
979 __ mov(tmp4, L2); | |
980 | |
981 __ call_VM_leaf(L7_thread_cache, | |
982 CAST_FROM_FN_PTR(address, | |
983 DirtyCardQueueSet::handle_zero_index_for_thread), | |
984 G2_thread); | |
985 | |
986 __ mov(L0, tmp2); | |
987 __ mov(L1, tmp3); | |
988 __ mov(L2, tmp4); | |
989 | |
990 __ br(Assembler::always, /*annul*/false, Assembler::pt, restart); | |
991 __ delayed()->restore(); | |
992 } | |
993 break; | |
994 #endif // !SERIALGC | |
995 | |
0 | 996 default: |
997 { __ set_info("unimplemented entry", dont_gc_arguments); | |
998 __ save_frame(0); | |
999 __ set((int)id, O1); | |
1000 __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), O1); | |
1001 __ should_not_reach_here(); | |
1002 } | |
1003 break; | |
1004 } | |
1005 return oop_maps; | |
1006 } | |
1007 | |
1008 | |
1009 void Runtime1::generate_handle_exception(StubAssembler* sasm, OopMapSet* oop_maps, OopMap* oop_map, bool) { | |
1010 Label no_deopt; | |
1011 | |
1012 __ verify_not_null_oop(Oexception); | |
1013 | |
1014 // save the exception and issuing pc in the thread | |
1015 __ st_ptr(Oexception, G2_thread, in_bytes(JavaThread::exception_oop_offset())); | |
1016 __ st_ptr(Oissuing_pc, G2_thread, in_bytes(JavaThread::exception_pc_offset())); | |
1017 | |
1018 // save the real return address and use the throwing pc as the return address to lookup (has bci & oop map) | |
1019 __ mov(I7, L0); | |
1020 __ mov(Oissuing_pc, I7); | |
1021 __ sub(I7, frame::pc_return_offset, I7); | |
1022 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, exception_handler_for_pc)); | |
1023 | |
1024 // Note: if nmethod has been deoptimized then regardless of | |
1025 // whether it had a handler or not we will deoptimize | |
1026 // by entering the deopt blob with a pending exception. | |
1027 | |
1295 | 1028 #ifdef ASSERT |
1029 Label done; | |
0 | 1030 __ tst(O0); |
1295 | 1031 __ br(Assembler::notZero, false, Assembler::pn, done); |
0 | 1032 __ delayed()->nop(); |
1295 | 1033 __ stop("should have found address"); |
1034 __ bind(done); | |
1035 #endif | |
0 | 1036 |
1037 // restore the registers that were saved at the beginning and jump to the exception handler. | |
1038 restore_live_registers(sasm); | |
1039 | |
1040 __ jmp(O0, 0); | |
1041 __ delayed()->restore(); | |
1042 | |
1043 oop_maps->add_gc_map(call_offset, oop_map); | |
1044 } | |
1045 | |
1046 | |
1047 #undef __ | |
1048 | |
1049 #define __ masm-> | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1579
diff
changeset
|
1050 |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1579
diff
changeset
|
1051 const char *Runtime1::pd_name_for_address(address entry) { |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1579
diff
changeset
|
1052 return "<unknown function>"; |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1579
diff
changeset
|
1053 } |