312 OopMap* oop_map = save_live_registers(sasm);
313
314 int call_offset;
315 if (arg1 == noreg) {
316 call_offset = __ call_RT(result, noreg, target);
317 } else if (arg2 == noreg) {
318 call_offset = __ call_RT(result, noreg, target, arg1);
319 } else if (arg3 == noreg) {
320 call_offset = __ call_RT(result, noreg, target, arg1, arg2);
321 } else {
322 call_offset = __ call_RT(result, noreg, target, arg1, arg2, arg3);
323 }
324 OopMapSet* oop_maps = new OopMapSet();
325 oop_maps->add_gc_map(call_offset, oop_map);
326
327 restore_live_registers(sasm, result, noreg);
328 __ blr();
329 return oop_maps;
330 }
331
332 static OopMapSet* stub_call_with_stack_parms(StubAssembler* sasm, Register result, address target,
333 int stack_parms, bool do_return = true) {
334 // Make a frame and preserve the caller's caller-save registers.
335 const int parm_size_in_bytes = align_up(stack_parms << LogBytesPerWord, frame::alignment_in_bytes);
336 const int padding = parm_size_in_bytes - (stack_parms << LogBytesPerWord);
337 OopMap* oop_map = save_live_registers(sasm, true, noreg, parm_size_in_bytes);
338
339 int call_offset = 0;
340 switch (stack_parms) {
341 case 3:
342 __ ld(R6_ARG4, frame_size_in_bytes + padding + 16, R1_SP);
343 case 2:
344 __ ld(R5_ARG3, frame_size_in_bytes + padding + 8, R1_SP);
345 case 1:
346 __ ld(R4_ARG2, frame_size_in_bytes + padding + 0, R1_SP);
347 case 0:
348 call_offset = __ call_RT(result, noreg, target);
349 break;
350 default: Unimplemented(); break;
351 }
352 OopMapSet* oop_maps = new OopMapSet();
353 oop_maps->add_gc_map(call_offset, oop_map);
354
355 restore_live_registers(sasm, result, noreg);
356 if (do_return) __ blr();
357 return oop_maps;
358 }
359
360
361 OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) {
362 // Make a frame and preserve the caller's caller-save registers.
363 OopMap* oop_map = save_live_registers(sasm);
364
365 // Call the runtime patching routine, returns non-zero if nmethod got deopted.
366 int call_offset = __ call_RT(noreg, noreg, target);
367 OopMapSet* oop_maps = new OopMapSet();
368 oop_maps->add_gc_map(call_offset, oop_map);
369 __ cmpdi(CR0, R3_RET, 0);
370
371 // Re-execute the patched instruction or, if the nmethod was deoptmized,
372 // return to the deoptimization handler entry that will cause re-execution
373 // of the current bytecode.
374 DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob();
375 assert(deopt_blob != nullptr, "deoptimization blob must have been created");
415 } else if (id == StubId::c1_fast_new_instance_id) {
416 __ set_info("fast new_instance", dont_gc_arguments);
417 } else {
418 assert(id == StubId::c1_fast_new_instance_init_check_id, "bad StubId");
419 __ set_info("fast new_instance init check", dont_gc_arguments);
420 }
421
422 // We don't support eden allocation.
423
424 oop_maps = generate_stub_call(sasm, R3_RET, CAST_FROM_FN_PTR(address, new_instance), R4_ARG2);
425 }
426 break;
427
428 case StubId::c1_counter_overflow_id:
429 // Bci and method are on stack.
430 oop_maps = stub_call_with_stack_parms(sasm, noreg, CAST_FROM_FN_PTR(address, counter_overflow), 2);
431 break;
432
433 case StubId::c1_new_type_array_id:
434 case StubId::c1_new_object_array_id:
435 {
436 if (id == StubId::c1_new_type_array_id) {
437 __ set_info("new_type_array", dont_gc_arguments);
438 } else {
439 __ set_info("new_object_array", dont_gc_arguments);
440 }
441
442 #ifdef ASSERT
443 // Assert object type is really an array of the proper kind.
444 {
445 int tag = (id == StubId::c1_new_type_array_id) ? Klass::_lh_array_tag_type_value : Klass::_lh_array_tag_obj_value;
446 Label ok;
447 __ lwz(R0, in_bytes(Klass::layout_helper_offset()), R4_ARG2);
448 __ srawi(R0, R0, Klass::_lh_array_tag_shift);
449 __ cmpwi(CR0, R0, tag);
450 __ beq(CR0, ok);
451 __ stop("assert(is an array klass)");
452 __ should_not_reach_here();
453 __ bind(ok);
454 }
455 #endif // ASSERT
456
457 // We don't support eden allocation.
458
459 if (id == StubId::c1_new_type_array_id) {
460 oop_maps = generate_stub_call(sasm, R3_RET, CAST_FROM_FN_PTR(address, new_type_array), R4_ARG2, R5_ARG3);
461 } else {
462 oop_maps = generate_stub_call(sasm, R3_RET, CAST_FROM_FN_PTR(address, new_object_array), R4_ARG2, R5_ARG3);
463 }
464 }
465 break;
466
467 case StubId::c1_new_multi_array_id:
468 {
469 // R4: klass
470 // R5: rank
471 // R6: address of 1st dimension
472 __ set_info("new_multi_array", dont_gc_arguments);
473 oop_maps = generate_stub_call(sasm, R3_RET, CAST_FROM_FN_PTR(address, new_multi_array), R4_ARG2, R5_ARG3, R6_ARG4);
474 }
475 break;
476
477 case StubId::c1_register_finalizer_id:
478 {
479 __ set_info("register_finalizer", dont_gc_arguments);
480 // This code is called via rt_call. Hence, caller-save registers have been saved.
481 Register t = R11_scratch1;
482
483 // Load the klass and check the has finalizer flag.
484 __ load_klass(t, R3_ARG1);
485 __ lbz(t, in_bytes(Klass::misc_flags_offset()), t);
486 __ testbitdi(CR0, R0, t, exact_log2(KlassFlags::_misc_has_finalizer));
487 // Return if has_finalizer bit == 0 (CR0.eq).
488 __ bclr(Assembler::bcondCRbiIs1, Assembler::bi0(CR0, Assembler::equal), Assembler::bhintbhBCLRisReturn);
489
490 __ mflr(R0);
491 __ std(R0, _abi0(lr), R1_SP);
492 __ push_frame(frame::native_abi_reg_args_size, R0); // Empty dummy frame (no callee-save regs).
493 sasm->set_frame_size(frame::native_abi_reg_args_size / BytesPerWord);
494 OopMap* oop_map = new OopMap(frame::native_abi_reg_args_size / sizeof(jint), 0);
495 int call_offset = __ call_RT(noreg, noreg,
496 CAST_FROM_FN_PTR(address, SharedRuntime::register_finalizer), R3_ARG1);
574 __ bctr();
575 }
576 break;
577
578 case StubId::c1_throw_array_store_exception_id:
579 {
580 __ set_info("throw_array_store_exception", dont_gc_arguments);
581 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true);
582 }
583 break;
584
585 case StubId::c1_throw_class_cast_exception_id:
586 {
587 __ set_info("throw_class_cast_exception", dont_gc_arguments);
588 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true);
589 }
590 break;
591
592 case StubId::c1_throw_incompatible_class_change_error_id:
593 {
594 __ set_info("throw_incompatible_class_cast_exception", dont_gc_arguments);
595 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false);
596 }
597 break;
598
599 case StubId::c1_slow_subtype_check_id:
600 { // Support for uint StubRoutine::partial_subtype_check( Klass sub, Klass super );
601 const Register sub_klass = R5,
602 super_klass = R4,
603 temp1_reg = R6;
604 __ check_klass_subtype_slow_path(sub_klass, super_klass, temp1_reg, noreg);
605 // Result is in CR0.
606 __ blr();
607 }
608 break;
609
610 case StubId::c1_is_instance_of_id:
611 {
612 // Called like a C function, but without FunctionDescriptor (see LIR_Assembler::rt_call).
613
614 // Arguments and return value.
615 Register mirror = R3_ARG1;
616 Register obj = R4_ARG2;
617 Register result = R3_RET;
618
|
312 OopMap* oop_map = save_live_registers(sasm);
313
314 int call_offset;
315 if (arg1 == noreg) {
316 call_offset = __ call_RT(result, noreg, target);
317 } else if (arg2 == noreg) {
318 call_offset = __ call_RT(result, noreg, target, arg1);
319 } else if (arg3 == noreg) {
320 call_offset = __ call_RT(result, noreg, target, arg1, arg2);
321 } else {
322 call_offset = __ call_RT(result, noreg, target, arg1, arg2, arg3);
323 }
324 OopMapSet* oop_maps = new OopMapSet();
325 oop_maps->add_gc_map(call_offset, oop_map);
326
327 restore_live_registers(sasm, result, noreg);
328 __ blr();
329 return oop_maps;
330 }
331
332 static OopMapSet* stub_call_with_stack_parms(StubAssembler* sasm, Register oop_result, address target,
333 int stack_parms, bool do_return = true, Register result2 = noreg) {
334 // Make a frame and preserve the caller's caller-save registers.
335 const int parm_size_in_bytes = align_up(stack_parms << LogBytesPerWord, frame::alignment_in_bytes);
336 const int padding = parm_size_in_bytes - (stack_parms << LogBytesPerWord);
337 OopMap* oop_map = save_live_registers(sasm, true, noreg, parm_size_in_bytes);
338
339 int call_offset = 0;
340 switch (stack_parms) {
341 case 3:
342 __ ld(R6_ARG4, frame_size_in_bytes + padding + 16, R1_SP);
343 case 2:
344 __ ld(R5_ARG3, frame_size_in_bytes + padding + 8, R1_SP);
345 case 1:
346 __ ld(R4_ARG2, frame_size_in_bytes + padding + 0, R1_SP);
347 case 0:
348 call_offset = __ call_RT(oop_result, noreg, target);
349 break;
350 default: Unimplemented(); break;
351 }
352 OopMapSet* oop_maps = new OopMapSet();
353 oop_maps->add_gc_map(call_offset, oop_map);
354
355 restore_live_registers(sasm, oop_result, result2);
356 if (do_return) __ blr();
357 return oop_maps;
358 }
359
360
361 OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) {
362 // Make a frame and preserve the caller's caller-save registers.
363 OopMap* oop_map = save_live_registers(sasm);
364
365 // Call the runtime patching routine, returns non-zero if nmethod got deopted.
366 int call_offset = __ call_RT(noreg, noreg, target);
367 OopMapSet* oop_maps = new OopMapSet();
368 oop_maps->add_gc_map(call_offset, oop_map);
369 __ cmpdi(CR0, R3_RET, 0);
370
371 // Re-execute the patched instruction or, if the nmethod was deoptmized,
372 // return to the deoptimization handler entry that will cause re-execution
373 // of the current bytecode.
374 DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob();
375 assert(deopt_blob != nullptr, "deoptimization blob must have been created");
415 } else if (id == StubId::c1_fast_new_instance_id) {
416 __ set_info("fast new_instance", dont_gc_arguments);
417 } else {
418 assert(id == StubId::c1_fast_new_instance_init_check_id, "bad StubId");
419 __ set_info("fast new_instance init check", dont_gc_arguments);
420 }
421
422 // We don't support eden allocation.
423
424 oop_maps = generate_stub_call(sasm, R3_RET, CAST_FROM_FN_PTR(address, new_instance), R4_ARG2);
425 }
426 break;
427
428 case StubId::c1_counter_overflow_id:
429 // Bci and method are on stack.
430 oop_maps = stub_call_with_stack_parms(sasm, noreg, CAST_FROM_FN_PTR(address, counter_overflow), 2);
431 break;
432
433 case StubId::c1_new_type_array_id:
434 case StubId::c1_new_object_array_id:
435 case StubId::c1_new_null_free_array_id:
436 {
437 if (id == StubId::c1_new_type_array_id) {
438 __ set_info("new_type_array", dont_gc_arguments);
439 } else if (id == StubId::c1_new_object_array_id) {
440 __ set_info("new_object_array", dont_gc_arguments);
441 } else {
442 __ set_info("new_null_free_array", dont_gc_arguments);
443 }
444
445 #ifdef ASSERT
446 // Assert object type is really an array of the proper kind.
447 __ lwz(R0, in_bytes(Klass::layout_helper_offset()), R4_ARG2);
448 __ srawi(R0, R0, Klass::_lh_array_tag_shift);
449 switch (id) {
450 case StubId::c1_new_type_array_id:
451 __ cmpwi(CR0, R0, Klass::_lh_array_tag_type_value);
452 __ asm_assert_eq("assert(is a type array klass)");
453 break;
454 case StubId::c1_new_object_array_id:
455 __ cmpwi(CR0, R0, Klass::_lh_array_tag_ref_value); // new "[Ljava/lang/Object;"
456 __ cmpwi(CR1, R0, Klass::_lh_array_tag_flat_value); // new "[LVT;"
457 __ cror(CR0, Assembler::equal, CR1, Assembler::equal);
458 __ asm_assert_eq("assert(is an object or inline type array klass)");
459 break;
460 case StubId::c1_new_null_free_array_id:
461 __ cmpwi(CR0, R0, Klass::_lh_array_tag_flat_value); // the array can be a flat array.
462 __ cmpwi(CR1, R0, Klass::_lh_array_tag_ref_value); // the array cannot be a flat array (due to the InlineArrayElementMaxFlatSize, etc.)
463 __ cror(CR0, Assembler::equal, CR1, Assembler::equal);
464 __ asm_assert_eq("assert(is an object or inline type array klass)");
465 break;
466 default: ShouldNotReachHere();
467 }
468 #endif // ASSERT
469
470 // We don't support eden allocation.
471
472 if (id == StubId::c1_new_type_array_id) {
473 oop_maps = generate_stub_call(sasm, R3_RET, CAST_FROM_FN_PTR(address, new_type_array), R4_ARG2, R5_ARG3);
474 } else if (id == StubId::c1_new_object_array_id) {
475 oop_maps = generate_stub_call(sasm, R3_RET, CAST_FROM_FN_PTR(address, new_object_array), R4_ARG2, R5_ARG3);
476 } else {
477 assert(id == StubId::c1_new_null_free_array_id, "must be");
478 oop_maps = generate_stub_call(sasm, R3_RET, CAST_FROM_FN_PTR(address, new_null_free_array), R4_ARG2, R5_ARG3);
479 }
480 }
481 break;
482
483 case StubId::c1_new_multi_array_id:
484 {
485 // R4: klass
486 // R5: rank
487 // R6: address of 1st dimension
488 __ set_info("new_multi_array", dont_gc_arguments);
489 oop_maps = generate_stub_call(sasm, R3_RET, CAST_FROM_FN_PTR(address, new_multi_array), R4_ARG2, R5_ARG3, R6_ARG4);
490 }
491 break;
492
493 case StubId::c1_buffer_inline_args_id:
494 case StubId::c1_buffer_inline_args_no_receiver_id:
495 {
496 address entry = (id == StubId::c1_buffer_inline_args_id) ?
497 CAST_FROM_FN_PTR(address, buffer_inline_args) :
498 CAST_FROM_FN_PTR(address, buffer_inline_args_no_receiver);
499
500 __ unimplemented("c1_buffer_inline_args"); // TODO: handle arguments and return value
501 OopMap* oop_map = save_live_registers(sasm);
502 int call_offset = __ call_RT(noreg, noreg, entry, R3_ARG1);
503
504 oop_maps = new OopMapSet();
505 oop_maps->add_gc_map(call_offset, oop_map);
506 restore_live_registers(sasm, R3_RET, noreg);
507 __ blr();
508 }
509 break;
510
511 case StubId::c1_load_flat_array_id:
512 oop_maps = stub_call_with_stack_parms(sasm, R3_RET, CAST_FROM_FN_PTR(address, load_flat_array), 2);
513 break;
514
515 case StubId::c1_store_flat_array_id:
516 oop_maps = stub_call_with_stack_parms(sasm, noreg, CAST_FROM_FN_PTR(address, store_flat_array), 3);
517 break;
518
519 case StubId::c1_substitutability_check_id:
520 oop_maps = stub_call_with_stack_parms(sasm, noreg, CAST_FROM_FN_PTR(address, substitutability_check), 2, true, R3_RET);
521 break;
522
523 case StubId::c1_register_finalizer_id:
524 {
525 __ set_info("register_finalizer", dont_gc_arguments);
526 // This code is called via rt_call. Hence, caller-save registers have been saved.
527 Register t = R11_scratch1;
528
529 // Load the klass and check the has finalizer flag.
530 __ load_klass(t, R3_ARG1);
531 __ lbz(t, in_bytes(Klass::misc_flags_offset()), t);
532 __ testbitdi(CR0, R0, t, exact_log2(KlassFlags::_misc_has_finalizer));
533 // Return if has_finalizer bit == 0 (CR0.eq).
534 __ bclr(Assembler::bcondCRbiIs1, Assembler::bi0(CR0, Assembler::equal), Assembler::bhintbhBCLRisReturn);
535
536 __ mflr(R0);
537 __ std(R0, _abi0(lr), R1_SP);
538 __ push_frame(frame::native_abi_reg_args_size, R0); // Empty dummy frame (no callee-save regs).
539 sasm->set_frame_size(frame::native_abi_reg_args_size / BytesPerWord);
540 OopMap* oop_map = new OopMap(frame::native_abi_reg_args_size / sizeof(jint), 0);
541 int call_offset = __ call_RT(noreg, noreg,
542 CAST_FROM_FN_PTR(address, SharedRuntime::register_finalizer), R3_ARG1);
620 __ bctr();
621 }
622 break;
623
624 case StubId::c1_throw_array_store_exception_id:
625 {
626 __ set_info("throw_array_store_exception", dont_gc_arguments);
627 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true);
628 }
629 break;
630
631 case StubId::c1_throw_class_cast_exception_id:
632 {
633 __ set_info("throw_class_cast_exception", dont_gc_arguments);
634 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true);
635 }
636 break;
637
638 case StubId::c1_throw_incompatible_class_change_error_id:
639 {
640 __ set_info("throw_incompatible_class_change_error", dont_gc_arguments);
641 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false);
642 }
643 break;
644
645 case StubId::c1_throw_illegal_monitor_state_exception_id:
646 {
647 __ set_info("c1_throw_illegal_monitor_state_exception", dont_gc_arguments);
648 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_illegal_monitor_state_exception), false);
649 }
650 break;
651
652 case StubId::c1_throw_identity_exception_id:
653 {
654 __ set_info("throw_identity_exception", dont_gc_arguments);
655 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_identity_exception), true);
656 }
657 break;
658
659 case StubId::c1_slow_subtype_check_id:
660 { // Support for uint StubRoutine::partial_subtype_check( Klass sub, Klass super );
661 const Register sub_klass = R5,
662 super_klass = R4,
663 temp1_reg = R6;
664 __ check_klass_subtype_slow_path(sub_klass, super_klass, temp1_reg, noreg);
665 // Result is in CR0.
666 __ blr();
667 }
668 break;
669
670 case StubId::c1_is_instance_of_id:
671 {
672 // Called like a C function, but without FunctionDescriptor (see LIR_Assembler::rt_call).
673
674 // Arguments and return value.
675 Register mirror = R3_ARG1;
676 Register obj = R4_ARG2;
677 Register result = R3_RET;
678
|