1 /* 2 * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. 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 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "asm/macroAssembler.inline.hpp" 27 #include "c1/c1_Defs.hpp" 28 #include "c1/c1_LIRAssembler.hpp" 29 #include "c1/c1_MacroAssembler.hpp" 30 #include "c1/c1_Runtime1.hpp" 31 #include "ci/ciUtilities.hpp" 32 #include "compiler/oopMap.hpp" 33 #include "gc/shared/cardTable.hpp" 34 #include "gc/shared/cardTableBarrierSet.hpp" 35 #include "gc/shared/collectedHeap.hpp" 36 #include "gc/shared/tlab_globals.hpp" 37 #include "interpreter/interpreter.hpp" 38 #include "memory/universe.hpp" 39 #include "nativeInst_arm.hpp" 40 #include "oops/oop.inline.hpp" 41 #include "prims/jvmtiExport.hpp" 42 #include "register_arm.hpp" 43 #include "runtime/sharedRuntime.hpp" 44 #include "runtime/signature.hpp" 45 #include "runtime/vframeArray.hpp" 46 #include "utilities/align.hpp" 47 #include "vmreg_arm.inline.hpp" 48 49 // Note: Rtemp usage is this file should not impact C2 and should be 50 // correct as long as it is not implicitly used in lower layers (the 51 // arm [macro]assembler) and used with care in the other C1 specific 52 // files. 53 54 // Implementation of StubAssembler 55 56 int StubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, int args_size) { 57 mov(R0, Rthread); 58 59 int call_offset = set_last_Java_frame(SP, FP, false, Rtemp); 60 61 call(entry); 62 if (call_offset == -1) { // PC not saved 63 call_offset = offset(); 64 } 65 reset_last_Java_frame(Rtemp); 66 67 assert(frame_size() != no_frame_size, "frame must be fixed"); 68 if (_stub_id != (int)C1StubId::forward_exception_id) { 69 ldr(R3, Address(Rthread, Thread::pending_exception_offset())); 70 } 71 72 if (oop_result1->is_valid()) { 73 assert_different_registers(oop_result1, R3, Rtemp); 74 get_vm_result(oop_result1, Rtemp); 75 } 76 if (metadata_result->is_valid()) { 77 assert_different_registers(metadata_result, R3, Rtemp); 78 get_vm_result_2(metadata_result, Rtemp); 79 } 80 81 // Check for pending exception 82 // unpack_with_exception_in_tls path is taken through 83 // Runtime1::exception_handler_for_pc 84 if (_stub_id != (int)C1StubId::forward_exception_id) { 85 assert(frame_size() != no_frame_size, "cannot directly call forward_exception_id"); 86 cmp(R3, 0); 87 jump(Runtime1::entry_for(C1StubId::forward_exception_id), relocInfo::runtime_call_type, Rtemp, ne); 88 } else { 89 #ifdef ASSERT 90 // Should not have pending exception in forward_exception stub 91 ldr(R3, Address(Rthread, Thread::pending_exception_offset())); 92 cmp(R3, 0); 93 breakpoint(ne); 94 #endif // ASSERT 95 } 96 return call_offset; 97 } 98 99 100 int StubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1) { 101 if (arg1 != R1) { 102 mov(R1, arg1); 103 } 104 return call_RT(oop_result1, metadata_result, entry, 1); 105 } 106 107 108 int StubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1, Register arg2) { 109 assert(arg1 == R1 && arg2 == R2, "cannot handle otherwise"); 110 return call_RT(oop_result1, metadata_result, entry, 2); 111 } 112 113 114 int StubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1, Register arg2, Register arg3) { 115 assert(arg1 == R1 && arg2 == R2 && arg3 == R3, "cannot handle otherwise"); 116 return call_RT(oop_result1, metadata_result, entry, 3); 117 } 118 119 120 #define __ sasm-> 121 122 // TODO: ARM - does this duplicate RegisterSaver in SharedRuntime? 123 124 enum RegisterLayout { 125 fpu_save_size = pd_nof_fpu_regs_reg_alloc, 126 #ifndef __SOFTFP__ 127 D0_offset = 0, 128 #endif 129 R0_offset = fpu_save_size, 130 R1_offset, 131 R2_offset, 132 R3_offset, 133 R4_offset, 134 R5_offset, 135 R6_offset, 136 #if (FP_REG_NUM != 7) 137 R7_offset, 138 #endif 139 R8_offset, 140 R9_offset, 141 R10_offset, 142 #if (FP_REG_NUM != 11) 143 R11_offset, 144 #endif 145 R12_offset, 146 FP_offset, 147 LR_offset, 148 reg_save_size, 149 arg1_offset = reg_save_size * wordSize, 150 arg2_offset = (reg_save_size + 1) * wordSize 151 }; 152 153 154 static OopMap* generate_oop_map(StubAssembler* sasm, bool save_fpu_registers = HaveVFP) { 155 sasm->set_frame_size(reg_save_size /* in words */); 156 157 // Record saved value locations in an OopMap. 158 // Locations are offsets from sp after runtime call. 159 OopMap* map = new OopMap(VMRegImpl::slots_per_word * reg_save_size, 0); 160 161 int j=0; 162 for (int i = R0_offset; i < R10_offset; i++) { 163 if (j == FP_REG_NUM) { 164 // skip the FP register, saved below 165 j++; 166 } 167 map->set_callee_saved(VMRegImpl::stack2reg(i), as_Register(j)->as_VMReg()); 168 j++; 169 } 170 assert(j == R10->encoding(), "must be"); 171 #if (FP_REG_NUM != 11) 172 // add R11, if not saved as FP 173 map->set_callee_saved(VMRegImpl::stack2reg(R11_offset), R11->as_VMReg()); 174 #endif 175 map->set_callee_saved(VMRegImpl::stack2reg(FP_offset), FP->as_VMReg()); 176 map->set_callee_saved(VMRegImpl::stack2reg(LR_offset), LR->as_VMReg()); 177 178 if (save_fpu_registers) { 179 for (int i = 0; i < fpu_save_size; i++) { 180 map->set_callee_saved(VMRegImpl::stack2reg(i), as_FloatRegister(i)->as_VMReg()); 181 } 182 } 183 184 return map; 185 } 186 187 static OopMap* save_live_registers(StubAssembler* sasm, bool save_fpu_registers = HaveVFP) { 188 __ block_comment("save_live_registers"); 189 sasm->set_frame_size(reg_save_size /* in words */); 190 191 __ push(RegisterSet(FP) | RegisterSet(LR)); 192 __ push(RegisterSet(R0, R6) | RegisterSet(R8, R10) | R12 | altFP_7_11); 193 if (save_fpu_registers) { 194 __ fpush(FloatRegisterSet(D0, fpu_save_size / 2)); 195 } else { 196 __ sub(SP, SP, fpu_save_size * wordSize); 197 } 198 199 return generate_oop_map(sasm, save_fpu_registers); 200 } 201 202 203 static void restore_live_registers(StubAssembler* sasm, 204 bool restore_R0, 205 bool restore_FP_LR, 206 bool do_return, 207 bool restore_fpu_registers = HaveVFP) { 208 __ block_comment("restore_live_registers"); 209 210 if (restore_fpu_registers) { 211 __ fpop(FloatRegisterSet(D0, fpu_save_size / 2)); 212 if (!restore_R0) { 213 __ add(SP, SP, (R1_offset - fpu_save_size) * wordSize); 214 } 215 } else { 216 __ add(SP, SP, (restore_R0 ? fpu_save_size : R1_offset) * wordSize); 217 } 218 __ pop(RegisterSet((restore_R0 ? R0 : R1), R6) | RegisterSet(R8, R10) | R12 | altFP_7_11); 219 if (restore_FP_LR) { 220 __ pop(RegisterSet(FP) | RegisterSet(do_return ? PC : LR)); 221 } else { 222 assert (!do_return, "return without restoring FP/LR"); 223 } 224 } 225 226 227 static void restore_live_registers_except_R0(StubAssembler* sasm, bool restore_fpu_registers = HaveVFP) { 228 restore_live_registers(sasm, false, true, true, restore_fpu_registers); 229 } 230 231 static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = HaveVFP) { 232 restore_live_registers(sasm, true, true, true, restore_fpu_registers); 233 } 234 235 static void restore_live_registers_except_FP_LR(StubAssembler* sasm, bool restore_fpu_registers = HaveVFP) { 236 restore_live_registers(sasm, true, false, false, restore_fpu_registers); 237 } 238 239 static void restore_live_registers_without_return(StubAssembler* sasm, bool restore_fpu_registers = HaveVFP) { 240 restore_live_registers(sasm, true, true, false, restore_fpu_registers); 241 } 242 243 void StubAssembler::save_live_registers() { 244 ::save_live_registers(this); 245 } 246 247 void StubAssembler::restore_live_registers_without_return() { 248 ::restore_live_registers_without_return(this); 249 } 250 251 void Runtime1::initialize_pd() { 252 } 253 254 255 OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address target, bool has_argument) { 256 OopMap* oop_map = save_live_registers(sasm); 257 258 int call_offset; 259 if (has_argument) { 260 __ ldr(R1, Address(SP, arg1_offset)); 261 __ ldr(R2, Address(SP, arg2_offset)); 262 call_offset = __ call_RT(noreg, noreg, target, R1, R2); 263 } else { 264 call_offset = __ call_RT(noreg, noreg, target); 265 } 266 267 OopMapSet* oop_maps = new OopMapSet(); 268 oop_maps->add_gc_map(call_offset, oop_map); 269 270 DEBUG_ONLY(STOP("generate_exception_throw");) // Should not reach here 271 return oop_maps; 272 } 273 274 275 static void restore_sp_for_method_handle(StubAssembler* sasm) { 276 // Restore SP from its saved reg (FP) if the exception PC is a MethodHandle call site. 277 __ ldr_s32(Rtemp, Address(Rthread, JavaThread::is_method_handle_return_offset())); 278 __ cmp(Rtemp, 0); 279 __ mov(SP, Rmh_SP_save, ne); 280 } 281 282 283 OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler* sasm) { 284 __ block_comment("generate_handle_exception"); 285 286 bool save_fpu_registers = false; 287 288 // Save registers, if required. 289 OopMapSet* oop_maps = new OopMapSet(); 290 OopMap* oop_map = nullptr; 291 292 switch (id) { 293 case C1StubId::forward_exception_id: { 294 save_fpu_registers = HaveVFP; 295 oop_map = generate_oop_map(sasm); 296 __ ldr(Rexception_obj, Address(Rthread, Thread::pending_exception_offset())); 297 __ ldr(Rexception_pc, Address(SP, LR_offset * wordSize)); 298 Register zero = __ zero_register(Rtemp); 299 __ str(zero, Address(Rthread, Thread::pending_exception_offset())); 300 break; 301 } 302 case C1StubId::handle_exception_id: 303 save_fpu_registers = HaveVFP; 304 // fall-through 305 case C1StubId::handle_exception_nofpu_id: 306 // At this point all registers MAY be live. 307 oop_map = save_live_registers(sasm, save_fpu_registers); 308 break; 309 case C1StubId::handle_exception_from_callee_id: 310 // At this point all registers except exception oop (R4/R19) and 311 // exception pc (R5/R20) are dead. 312 oop_map = save_live_registers(sasm); // TODO it's not required to save all registers 313 break; 314 default: ShouldNotReachHere(); 315 } 316 317 __ str(Rexception_obj, Address(Rthread, JavaThread::exception_oop_offset())); 318 __ str(Rexception_pc, Address(Rthread, JavaThread::exception_pc_offset())); 319 320 __ str(Rexception_pc, Address(SP, LR_offset * wordSize)); // patch throwing pc into return address 321 322 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, exception_handler_for_pc)); 323 oop_maps->add_gc_map(call_offset, oop_map); 324 325 // Exception handler found 326 __ str(R0, Address(SP, LR_offset * wordSize)); // patch the return address 327 328 // Restore the registers that were saved at the beginning, remove 329 // frame and jump to the exception handler. 330 switch (id) { 331 case C1StubId::forward_exception_id: 332 case C1StubId::handle_exception_nofpu_id: 333 case C1StubId::handle_exception_id: 334 restore_live_registers(sasm, save_fpu_registers); 335 // Note: the restore live registers includes the jump to LR (patched to R0) 336 break; 337 case C1StubId::handle_exception_from_callee_id: 338 restore_live_registers_without_return(sasm); // must not jump immediately to handler 339 restore_sp_for_method_handle(sasm); 340 __ ret(); 341 break; 342 default: ShouldNotReachHere(); 343 } 344 345 DEBUG_ONLY(STOP("generate_handle_exception");) // Should not reach here 346 347 return oop_maps; 348 } 349 350 351 void Runtime1::generate_unwind_exception(StubAssembler* sasm) { 352 353 if (AbortVMOnException) { 354 save_live_registers(sasm); 355 __ call_VM_leaf(CAST_FROM_FN_PTR(address, check_abort_on_vm_exception), Rexception_obj); 356 restore_live_registers(sasm); 357 } 358 359 // FP no longer used to find the frame start 360 // on entry, remove_frame() has already been called (restoring FP and LR) 361 362 // search the exception handler address of the caller (using the return address) 363 __ mov(c_rarg0, Rthread); 364 __ mov(Rexception_pc, LR); 365 __ mov(c_rarg1, LR); 366 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), c_rarg0, c_rarg1); 367 368 // Exception oop should be still in Rexception_obj and pc in Rexception_pc 369 // Jump to handler 370 __ verify_not_null_oop(Rexception_obj); 371 372 // JSR292 extension 373 restore_sp_for_method_handle(sasm); 374 375 __ jump(R0); 376 } 377 378 379 OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { 380 OopMap* oop_map = save_live_registers(sasm); 381 382 // call the runtime patching routine, returns non-zero if nmethod got deopted. 383 int call_offset = __ call_RT(noreg, noreg, target); 384 OopMapSet* oop_maps = new OopMapSet(); 385 oop_maps->add_gc_map(call_offset, oop_map); 386 387 DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob(); 388 assert(deopt_blob != nullptr, "deoptimization blob must have been created"); 389 390 __ cmp_32(R0, 0); 391 392 restore_live_registers_except_FP_LR(sasm); 393 __ pop(RegisterSet(FP) | RegisterSet(PC), eq); 394 395 // Deoptimization needed 396 // TODO: ARM - no need to restore FP & LR because unpack_with_reexecution() stores them back 397 __ pop(RegisterSet(FP) | RegisterSet(LR)); 398 399 __ jump(deopt_blob->unpack_with_reexecution(), relocInfo::runtime_call_type, Rtemp); 400 401 DEBUG_ONLY(STOP("generate_patching");) // Should not reach here 402 return oop_maps; 403 } 404 405 406 OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) { 407 const bool must_gc_arguments = true; 408 const bool dont_gc_arguments = false; 409 410 OopMapSet* oop_maps = nullptr; 411 bool save_fpu_registers = HaveVFP; 412 413 switch (id) { 414 case C1StubId::forward_exception_id: 415 { 416 oop_maps = generate_handle_exception(id, sasm); 417 // does not return on ARM 418 } 419 break; 420 421 case C1StubId::new_instance_id: 422 case C1StubId::fast_new_instance_id: 423 case C1StubId::fast_new_instance_init_check_id: 424 { 425 const Register result = R0; 426 const Register klass = R1; 427 428 OopMap* map = save_live_registers(sasm); 429 int call_offset = __ call_RT(result, noreg, CAST_FROM_FN_PTR(address, new_instance), klass); 430 oop_maps = new OopMapSet(); 431 oop_maps->add_gc_map(call_offset, map); 432 433 // MacroAssembler::StoreStore useless (included in the runtime exit path) 434 435 restore_live_registers_except_R0(sasm); 436 } 437 break; 438 439 case C1StubId::counter_overflow_id: 440 { 441 OopMap* oop_map = save_live_registers(sasm); 442 __ ldr(R1, Address(SP, arg1_offset)); 443 __ ldr(R2, Address(SP, arg2_offset)); 444 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, counter_overflow), R1, R2); 445 oop_maps = new OopMapSet(); 446 oop_maps->add_gc_map(call_offset, oop_map); 447 restore_live_registers(sasm); 448 } 449 break; 450 451 case C1StubId::new_type_array_id: 452 case C1StubId::new_object_array_id: 453 { 454 if (id == C1StubId::new_type_array_id) { 455 __ set_info("new_type_array", dont_gc_arguments); 456 } else { 457 __ set_info("new_object_array", dont_gc_arguments); 458 } 459 460 const Register result = R0; 461 const Register klass = R1; 462 const Register length = R2; 463 464 OopMap* map = save_live_registers(sasm); 465 int call_offset; 466 if (id == C1StubId::new_type_array_id) { 467 call_offset = __ call_RT(result, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length); 468 } else { 469 call_offset = __ call_RT(result, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length); 470 } 471 oop_maps = new OopMapSet(); 472 oop_maps->add_gc_map(call_offset, map); 473 474 // MacroAssembler::StoreStore useless (included in the runtime exit path) 475 476 restore_live_registers_except_R0(sasm); 477 } 478 break; 479 480 case C1StubId::new_multi_array_id: 481 { 482 __ set_info("new_multi_array", dont_gc_arguments); 483 484 // R0: klass 485 // R2: rank 486 // SP: address of 1st dimension 487 const Register result = R0; 488 OopMap* map = save_live_registers(sasm); 489 490 __ mov(R1, R0); 491 __ add(R3, SP, arg1_offset); 492 int call_offset = __ call_RT(result, noreg, CAST_FROM_FN_PTR(address, new_multi_array), R1, R2, R3); 493 494 oop_maps = new OopMapSet(); 495 oop_maps->add_gc_map(call_offset, map); 496 497 // MacroAssembler::StoreStore useless (included in the runtime exit path) 498 499 restore_live_registers_except_R0(sasm); 500 } 501 break; 502 503 case C1StubId::register_finalizer_id: 504 { 505 __ set_info("register_finalizer", dont_gc_arguments); 506 507 // Do not call runtime if has_finalizer flag is not set 508 __ load_klass(Rtemp, R0); 509 __ ldrb(Rtemp, Address(Rtemp, Klass::misc_flags_offset())); 510 511 __ tst(Rtemp, KlassFlags::_misc_has_finalizer); 512 __ bx(LR, eq); 513 514 // Call VM 515 OopMap* map = save_live_registers(sasm); 516 oop_maps = new OopMapSet(); 517 int call_offset = __ call_RT(noreg, noreg, 518 CAST_FROM_FN_PTR(address, SharedRuntime::register_finalizer), R0); 519 oop_maps->add_gc_map(call_offset, map); 520 restore_live_registers(sasm); 521 } 522 break; 523 524 case C1StubId::throw_range_check_failed_id: 525 { 526 __ set_info("range_check_failed", dont_gc_arguments); 527 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_range_check_exception), true); 528 } 529 break; 530 531 case C1StubId::throw_index_exception_id: 532 { 533 __ set_info("index_range_check_failed", dont_gc_arguments); 534 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_index_exception), true); 535 } 536 break; 537 538 case C1StubId::throw_div0_exception_id: 539 { 540 __ set_info("throw_div0_exception", dont_gc_arguments); 541 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_div0_exception), false); 542 } 543 break; 544 545 case C1StubId::throw_null_pointer_exception_id: 546 { 547 __ set_info("throw_null_pointer_exception", dont_gc_arguments); 548 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_null_pointer_exception), false); 549 } 550 break; 551 552 case C1StubId::handle_exception_nofpu_id: 553 case C1StubId::handle_exception_id: 554 { 555 __ set_info("handle_exception", dont_gc_arguments); 556 oop_maps = generate_handle_exception(id, sasm); 557 } 558 break; 559 560 case C1StubId::handle_exception_from_callee_id: 561 { 562 __ set_info("handle_exception_from_callee", dont_gc_arguments); 563 oop_maps = generate_handle_exception(id, sasm); 564 } 565 break; 566 567 case C1StubId::unwind_exception_id: 568 { 569 __ set_info("unwind_exception", dont_gc_arguments); 570 generate_unwind_exception(sasm); 571 } 572 break; 573 574 case C1StubId::throw_array_store_exception_id: 575 { 576 __ set_info("throw_array_store_exception", dont_gc_arguments); 577 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true); 578 } 579 break; 580 581 case C1StubId::throw_class_cast_exception_id: 582 { 583 __ set_info("throw_class_cast_exception", dont_gc_arguments); 584 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true); 585 } 586 break; 587 588 case C1StubId::throw_incompatible_class_change_error_id: 589 { 590 __ set_info("throw_incompatible_class_cast_exception", dont_gc_arguments); 591 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false); 592 } 593 break; 594 595 case C1StubId::slow_subtype_check_id: 596 { 597 // (in) R0 - sub, destroyed, 598 // (in) R1 - super, not changed 599 // (out) R0 - result: 1 if check passed, 0 otherwise 600 __ raw_push(R2, R3, LR); 601 602 // Load an array of secondary_supers 603 __ ldr(R2, Address(R0, Klass::secondary_supers_offset())); 604 // Length goes to R3 605 __ ldr_s32(R3, Address(R2, Array<Klass*>::length_offset_in_bytes())); 606 __ add(R2, R2, Array<Klass*>::base_offset_in_bytes()); 607 608 Label loop, miss; 609 __ bind(loop); 610 __ cbz(R3, miss); 611 __ ldr(LR, Address(R2, wordSize, post_indexed)); 612 __ sub(R3, R3, 1); 613 __ cmp(LR, R1); 614 __ b(loop, ne); 615 616 // We get here if an equal cache entry is found 617 __ str(R1, Address(R0, Klass::secondary_super_cache_offset())); 618 __ mov(R0, 1); 619 __ raw_pop_and_ret(R2, R3); 620 621 // A cache entry not found - return false 622 __ bind(miss); 623 __ mov(R0, 0); 624 __ raw_pop_and_ret(R2, R3); 625 } 626 break; 627 628 case C1StubId::monitorenter_nofpu_id: 629 save_fpu_registers = false; 630 // fall through 631 case C1StubId::monitorenter_id: 632 { 633 __ set_info("monitorenter", dont_gc_arguments); 634 const Register obj = R1; 635 const Register lock = R2; 636 OopMap* map = save_live_registers(sasm, save_fpu_registers); 637 __ ldr(obj, Address(SP, arg1_offset)); 638 __ ldr(lock, Address(SP, arg2_offset)); 639 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorenter), obj, lock); 640 oop_maps = new OopMapSet(); 641 oop_maps->add_gc_map(call_offset, map); 642 restore_live_registers(sasm, save_fpu_registers); 643 } 644 break; 645 646 case C1StubId::monitorexit_nofpu_id: 647 save_fpu_registers = false; 648 // fall through 649 case C1StubId::monitorexit_id: 650 { 651 __ set_info("monitorexit", dont_gc_arguments); 652 const Register lock = R1; 653 OopMap* map = save_live_registers(sasm, save_fpu_registers); 654 __ ldr(lock, Address(SP, arg1_offset)); 655 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorexit), lock); 656 oop_maps = new OopMapSet(); 657 oop_maps->add_gc_map(call_offset, map); 658 restore_live_registers(sasm, save_fpu_registers); 659 } 660 break; 661 662 case C1StubId::deoptimize_id: 663 { 664 __ set_info("deoptimize", dont_gc_arguments); 665 OopMap* oop_map = save_live_registers(sasm); 666 const Register trap_request = R1; 667 __ ldr(trap_request, Address(SP, arg1_offset)); 668 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, deoptimize), trap_request); 669 oop_maps = new OopMapSet(); 670 oop_maps->add_gc_map(call_offset, oop_map); 671 restore_live_registers_without_return(sasm); 672 DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob(); 673 assert(deopt_blob != nullptr, "deoptimization blob must have been created"); 674 __ jump(deopt_blob->unpack_with_reexecution(), relocInfo::runtime_call_type, noreg); 675 } 676 break; 677 678 case C1StubId::access_field_patching_id: 679 { 680 __ set_info("access_field_patching", dont_gc_arguments); 681 oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, access_field_patching)); 682 } 683 break; 684 685 case C1StubId::load_klass_patching_id: 686 { 687 __ set_info("load_klass_patching", dont_gc_arguments); 688 oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_klass_patching)); 689 } 690 break; 691 692 case C1StubId::load_appendix_patching_id: 693 { 694 __ set_info("load_appendix_patching", dont_gc_arguments); 695 oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_appendix_patching)); 696 } 697 break; 698 699 case C1StubId::load_mirror_patching_id: 700 { 701 __ set_info("load_mirror_patching", dont_gc_arguments); 702 oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_mirror_patching)); 703 } 704 break; 705 706 case C1StubId::predicate_failed_trap_id: 707 { 708 __ set_info("predicate_failed_trap", dont_gc_arguments); 709 710 OopMap* oop_map = save_live_registers(sasm); 711 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, predicate_failed_trap)); 712 713 oop_maps = new OopMapSet(); 714 oop_maps->add_gc_map(call_offset, oop_map); 715 716 restore_live_registers_without_return(sasm); 717 718 DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob(); 719 assert(deopt_blob != nullptr, "deoptimization blob must have been created"); 720 __ jump(deopt_blob->unpack_with_reexecution(), relocInfo::runtime_call_type, Rtemp); 721 } 722 break; 723 724 default: 725 { 726 __ set_info("unimplemented entry", dont_gc_arguments); 727 STOP("unimplemented entry"); 728 } 729 break; 730 } 731 return oop_maps; 732 } 733 734 #undef __ 735 736 #ifdef __SOFTFP__ 737 const char *Runtime1::pd_name_for_address(address entry) { 738 739 #define FUNCTION_CASE(a, f) \ 740 if ((intptr_t)a == CAST_FROM_FN_PTR(intptr_t, f)) return #f 741 742 FUNCTION_CASE(entry, __aeabi_fadd_glibc); 743 FUNCTION_CASE(entry, __aeabi_fmul); 744 FUNCTION_CASE(entry, __aeabi_fsub_glibc); 745 FUNCTION_CASE(entry, __aeabi_fdiv); 746 747 // __aeabi_XXXX_glibc: Imported code from glibc soft-fp bundle for calculation accuracy improvement. See CR 6757269. 748 FUNCTION_CASE(entry, __aeabi_dadd_glibc); 749 FUNCTION_CASE(entry, __aeabi_dmul); 750 FUNCTION_CASE(entry, __aeabi_dsub_glibc); 751 FUNCTION_CASE(entry, __aeabi_ddiv); 752 753 FUNCTION_CASE(entry, __aeabi_f2d); 754 FUNCTION_CASE(entry, __aeabi_d2f); 755 FUNCTION_CASE(entry, __aeabi_i2f); 756 FUNCTION_CASE(entry, __aeabi_i2d); 757 FUNCTION_CASE(entry, __aeabi_f2iz); 758 759 FUNCTION_CASE(entry, SharedRuntime::fcmpl); 760 FUNCTION_CASE(entry, SharedRuntime::fcmpg); 761 FUNCTION_CASE(entry, SharedRuntime::dcmpl); 762 FUNCTION_CASE(entry, SharedRuntime::dcmpg); 763 764 FUNCTION_CASE(entry, SharedRuntime::unordered_fcmplt); 765 FUNCTION_CASE(entry, SharedRuntime::unordered_dcmplt); 766 FUNCTION_CASE(entry, SharedRuntime::unordered_fcmple); 767 FUNCTION_CASE(entry, SharedRuntime::unordered_dcmple); 768 FUNCTION_CASE(entry, SharedRuntime::unordered_fcmpge); 769 FUNCTION_CASE(entry, SharedRuntime::unordered_dcmpge); 770 FUNCTION_CASE(entry, SharedRuntime::unordered_fcmpgt); 771 FUNCTION_CASE(entry, SharedRuntime::unordered_dcmpgt); 772 773 FUNCTION_CASE(entry, SharedRuntime::fneg); 774 FUNCTION_CASE(entry, SharedRuntime::dneg); 775 776 FUNCTION_CASE(entry, __aeabi_fcmpeq); 777 FUNCTION_CASE(entry, __aeabi_fcmplt); 778 FUNCTION_CASE(entry, __aeabi_fcmple); 779 FUNCTION_CASE(entry, __aeabi_fcmpge); 780 FUNCTION_CASE(entry, __aeabi_fcmpgt); 781 782 FUNCTION_CASE(entry, __aeabi_dcmpeq); 783 FUNCTION_CASE(entry, __aeabi_dcmplt); 784 FUNCTION_CASE(entry, __aeabi_dcmple); 785 FUNCTION_CASE(entry, __aeabi_dcmpge); 786 FUNCTION_CASE(entry, __aeabi_dcmpgt); 787 #undef FUNCTION_CASE 788 return ""; 789 } 790 #else // __SOFTFP__ 791 const char *Runtime1::pd_name_for_address(address entry) { 792 return "<unknown function>"; 793 } 794 #endif // __SOFTFP__