< prev index next >

src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp

Print this page

   1 /*
   2  * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2014, Red Hat Inc. All rights reserved.
   4  * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved.
   5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   6  *
   7  * This code is free software; you can redistribute it and/or modify it
   8  * under the terms of the GNU General Public License version 2 only, as
   9  * published by the Free Software Foundation.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any

 718         assert_cond(map != nullptr);
 719 
 720         const int bci_off = 0;
 721         const int method_off = 1;
 722         // Retrieve bci
 723         __ lw(bci, Address(fp, bci_off * BytesPerWord));
 724         // And a pointer to the Method*
 725         __ ld(method, Address(fp, method_off * BytesPerWord));
 726         int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, counter_overflow), bci, method);
 727         oop_maps = new OopMapSet();
 728         assert_cond(oop_maps != nullptr);
 729         oop_maps->add_gc_map(call_offset, map);
 730         restore_live_registers(sasm);
 731         __ leave();
 732         __ ret();
 733       }
 734       break;
 735 
 736     case StubId::c1_new_type_array_id:
 737     case StubId::c1_new_object_array_id:

 738       {
 739         Register length   = x9;  // Incoming
 740         Register klass    = x13; // Incoming
 741         Register obj      = x10; // Result
 742 
 743         if (id == StubId::c1_new_type_array_id) {
 744           __ set_info("new_type_array", dont_gc_arguments);
 745         } else {
 746           __ set_info("new_object_array", dont_gc_arguments);



 747         }
 748 
 749 #ifdef ASSERT
 750         // assert object type is really an array of the proper kind
 751         {
 752           Label ok;
 753           Register tmp = obj;
 754           __ lwu(tmp, Address(klass, Klass::layout_helper_offset()));
 755           __ sraiw(tmp, tmp, Klass::_lh_array_tag_shift);
 756           int tag = ((id == StubId::c1_new_type_array_id) ? Klass::_lh_array_tag_type_value : Klass::_lh_array_tag_obj_value);
 757           __ mv(t0, tag);
 758           __ beq(t0, tmp, ok);
 759           __ stop("assert(is an array klass)");




















 760           __ should_not_reach_here();
 761           __ bind(ok);
 762         }
 763 #endif // ASSERT
 764 
 765         __ enter();
 766         OopMap* map = save_live_registers(sasm);
 767         assert_cond(map != nullptr);
 768         int call_offset = 0;
 769         if (id == StubId::c1_new_type_array_id) {
 770           call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length);
 771         } else {
 772           call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length);


 773         }
 774 
 775         oop_maps = new OopMapSet();
 776         assert_cond(oop_maps != nullptr);
 777         oop_maps->add_gc_map(call_offset, map);
 778         restore_live_registers_except_r10(sasm);
 779 
 780         __ verify_oop(obj);
 781         __ leave();
 782         __ ret();
 783 
 784         // x10: new array
 785       }
 786       break;
 787 
 788     case StubId::c1_new_multi_array_id:
 789       {
 790         StubFrame f(sasm, "new_multi_array", dont_gc_arguments);
 791         // x10: klass
 792         // x9: rank
 793         // x12: address of 1st dimension
 794         OopMap* map = save_live_registers(sasm);
 795         assert_cond(map != nullptr);
 796         __ mv(c_rarg1, x10);
 797         __ mv(c_rarg3, x12);
 798         __ mv(c_rarg2, x9);
 799         int call_offset = __ call_RT(x10, noreg, CAST_FROM_FN_PTR(address, new_multi_array), x11, x12, x13);
 800 
 801         oop_maps = new OopMapSet();
 802         assert_cond(oop_maps != nullptr);
 803         oop_maps->add_gc_map(call_offset, map);
 804         restore_live_registers_except_r10(sasm);
 805 
 806         // x10: new multi array
 807         __ verify_oop(x10);
 808       }
 809       break;
 810 























































































 811     case StubId::c1_register_finalizer_id:
 812       {
 813         __ set_info("register_finalizer", dont_gc_arguments);
 814 
 815         // This is called via call_runtime so the arguments
 816         // will be place in C abi locations
 817         __ verify_oop(c_rarg0);
 818 
 819         // load the klass and check the has finalizer flag
 820         Label register_finalizer;
 821         Register t = x15;
 822         __ load_klass(t, x10);
 823         __ lbu(t, Address(t, Klass::misc_flags_offset()));
 824         __ test_bit(t0, t, exact_log2(KlassFlags::_misc_has_finalizer));
 825         __ bnez(t0, register_finalizer);
 826         __ ret();
 827 
 828         __ bind(register_finalizer);
 829         __ enter();
 830         OopMap* oop_map = save_live_registers(sasm);

 834         assert_cond(oop_maps != nullptr);
 835         oop_maps->add_gc_map(call_offset, oop_map);
 836 
 837         // Now restore all the live registers
 838         restore_live_registers(sasm);
 839 
 840         __ leave();
 841         __ ret();
 842       }
 843       break;
 844 
 845     case StubId::c1_throw_class_cast_exception_id:
 846       {
 847         StubFrame f(sasm, "throw_class_cast_exception", dont_gc_arguments, does_not_return);
 848         oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true);
 849       }
 850       break;
 851 
 852     case StubId::c1_throw_incompatible_class_change_error_id:
 853       {
 854         StubFrame f(sasm, "throw_incompatible_class_cast_exception", dont_gc_arguments, does_not_return);
 855         oop_maps = generate_exception_throw(sasm,
 856                                             CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false);
 857       }
 858       break;
 859 












 860     case StubId::c1_slow_subtype_check_id:
 861       {
 862         // Typical calling sequence:
 863         // push klass_RInfo (object klass or other subclass)
 864         // push sup_k_RInfo (array element klass or other superclass)
 865         // jump to slow_subtype_check
 866         // Note that the subclass is pushed first, and is therefore deepest.
 867         enum layout {
 868           x10_off, x10_off_hi,
 869           x12_off, x12_off_hi,
 870           x14_off, x14_off_hi,
 871           x15_off, x15_off_hi,
 872           sup_k_off, sup_k_off_hi,
 873           klass_off, klass_off_hi,
 874           framesize,
 875           result_off = sup_k_off
 876         };
 877 
 878         __ set_info("slow_subtype_check", dont_gc_arguments);
 879         __ push_reg(RegSet::of(x10, x12, x14, x15), sp);

   1 /*
   2  * Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2014, Red Hat Inc. All rights reserved.
   4  * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved.
   5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   6  *
   7  * This code is free software; you can redistribute it and/or modify it
   8  * under the terms of the GNU General Public License version 2 only, as
   9  * published by the Free Software Foundation.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any

 718         assert_cond(map != nullptr);
 719 
 720         const int bci_off = 0;
 721         const int method_off = 1;
 722         // Retrieve bci
 723         __ lw(bci, Address(fp, bci_off * BytesPerWord));
 724         // And a pointer to the Method*
 725         __ ld(method, Address(fp, method_off * BytesPerWord));
 726         int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, counter_overflow), bci, method);
 727         oop_maps = new OopMapSet();
 728         assert_cond(oop_maps != nullptr);
 729         oop_maps->add_gc_map(call_offset, map);
 730         restore_live_registers(sasm);
 731         __ leave();
 732         __ ret();
 733       }
 734       break;
 735 
 736     case StubId::c1_new_type_array_id:
 737     case StubId::c1_new_object_array_id:
 738     case StubId::c1_new_null_free_array_id:
 739       {
 740         Register length   = x9;  // Incoming
 741         Register klass    = x13; // Incoming
 742         Register obj      = x10; // Result
 743 
 744         if (id == StubId::c1_new_type_array_id) {
 745           __ set_info("new_type_array", dont_gc_arguments);
 746         } else if (id == StubId::c1_new_object_array_id) {
 747           __ set_info("new_object_array", dont_gc_arguments);
 748         } else {
 749           assert(id == StubId::c1_new_null_free_array_id, "must be");
 750           __ set_info("new_null_free_array", dont_gc_arguments);
 751         }
 752 
 753 #ifdef ASSERT
 754         // assert object type is really an array of the proper kind
 755         {
 756           Label ok;
 757           Register tmp = obj;
 758           __ lwu(tmp, Address(klass, Klass::layout_helper_offset()));
 759           __ sraiw(tmp, tmp, Klass::_lh_array_tag_shift);
 760 
 761           switch (id) {
 762             case StubId::c1_new_type_array_id:
 763               __ mv(t0, (int)Klass::_lh_array_tag_type_value);
 764               __ beq(t0, tmp, ok);
 765               __ stop("assert(is a type array klass)");
 766               break;
 767             case StubId::c1_new_object_array_id:
 768               __ mv(t0, (int)Klass::_lh_array_tag_ref_value);  // new "[Ljava/lang/Object;"
 769               __ beq(t0, tmp, ok);
 770               __ mv(t0, (int)Klass::_lh_array_tag_flat_value); // new "[LVT;"
 771               __ beq(t0, tmp, ok);
 772               __ stop("assert(is an object or inline type array klass)");
 773               break;
 774             case StubId::c1_new_null_free_array_id:
 775               __ mv(t0, (int)Klass::_lh_array_tag_flat_value); // the array can be a flat array.
 776               __ beq(t0, tmp, ok);
 777               __ mv(t0, (int)Klass::_lh_array_tag_ref_value);  // the array cannot be a flat array (due to the InlineArrayElementMaxFlatSize, etc.)
 778               __ beq(t0, tmp, ok);
 779               __ stop("assert(is an object or inline type array klass)");
 780               break;
 781             default: ShouldNotReachHere();
 782          }
 783 
 784           __ should_not_reach_here();
 785           __ bind(ok);
 786         }
 787 #endif // ASSERT
 788 
 789         __ enter();
 790         OopMap* map = save_live_registers(sasm);
 791         assert_cond(map != nullptr);
 792         int call_offset = 0;
 793         if (id == StubId::c1_new_type_array_id) {
 794           call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length);
 795         } else if (id == StubId::c1_new_object_array_id) {
 796           call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length);
 797         } else {
 798           call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_null_free_array), klass, length);
 799         }
 800 
 801         oop_maps = new OopMapSet();
 802         assert_cond(oop_maps != nullptr);
 803         oop_maps->add_gc_map(call_offset, map);
 804         restore_live_registers_except_r10(sasm);
 805 
 806         __ verify_oop(obj);
 807         __ leave();
 808         __ ret();
 809 
 810         // x10: new array
 811       }
 812       break;
 813 
 814     case StubId::c1_new_multi_array_id:
 815       {
 816         StubFrame f(sasm, "new_multi_array", dont_gc_arguments);
 817         // x10: klass
 818         // x9: rank
 819         // x12: address of 1st dimension
 820         OopMap* map = save_live_registers(sasm);
 821         assert_cond(map != nullptr);
 822         __ mv(c_rarg1, x10);
 823         __ mv(c_rarg3, x12);
 824         __ mv(c_rarg2, x9);
 825         int call_offset = __ call_RT(x10, noreg, CAST_FROM_FN_PTR(address, new_multi_array), x11, x12, x13);
 826 
 827         oop_maps = new OopMapSet();
 828         assert_cond(oop_maps != nullptr);
 829         oop_maps->add_gc_map(call_offset, map);
 830         restore_live_registers_except_r10(sasm);
 831 
 832         // x10: new multi array
 833         __ verify_oop(x10);
 834       }
 835       break;
 836 
 837     case StubId::c1_buffer_inline_args_id:
 838     case StubId::c1_buffer_inline_args_no_receiver_id:
 839       {
 840         const char* name = (id == StubId::c1_buffer_inline_args_id) ?
 841           "buffer_inline_args" : "buffer_inline_args_no_receiver";
 842         StubFrame f(sasm, name, dont_gc_arguments);
 843         OopMap* map = save_live_registers(sasm);
 844         Register method = x9;   // Incoming
 845         address entry = (id == StubId::c1_buffer_inline_args_id) ?
 846           CAST_FROM_FN_PTR(address, buffer_inline_args) :
 847           CAST_FROM_FN_PTR(address, buffer_inline_args_no_receiver);
 848         // This is called from a C1 method's scalarized entry point
 849         // where x10-x17 may be holding live argument values so we can't
 850         // return the result in x10 as the other stubs do. RA is used as
 851         // a temporary below to avoid the result being clobbered by
 852         // restore_live_registers. It's saved and restored by
 853         // StubAssembler::prologue and epilogue anyway.
 854         int call_offset = __ call_RT(ra, noreg, entry, method);
 855         oop_maps = new OopMapSet();
 856         oop_maps->add_gc_map(call_offset, map);
 857         restore_live_registers(sasm);
 858         __ mv(x18, ra);
 859         __ verify_oop(x18);  // x18: an array of buffered value objects
 860       }
 861       break;
 862 
 863     case StubId::c1_load_flat_array_id:
 864       {
 865         StubFrame f(sasm, "load_flat_array", dont_gc_arguments);
 866         OopMap* map = save_live_registers(sasm);
 867 
 868         // Called with store_parameter and not C abi
 869 
 870         f.load_argument(1, x10); // x10,: array
 871         f.load_argument(0, x11); // x11,: index
 872         int call_offset = __ call_RT(x10, noreg, CAST_FROM_FN_PTR(address, load_flat_array), x10, x11);
 873 
 874         // Ensure the stores that initialize the buffer are visible
 875         // before many subsequent store that publishes this reference.
 876         __ membar(MacroAssembler::StoreStore);
 877 
 878         oop_maps = new OopMapSet();
 879         oop_maps->add_gc_map(call_offset, map);
 880         restore_live_registers_except_r10(sasm);
 881 
 882         // x10: loaded element at array[index]
 883         __ verify_oop(x10);
 884       }
 885       break;
 886 
 887     case StubId::c1_store_flat_array_id:
 888       {
 889         StubFrame f(sasm, "store_flat_array", dont_gc_arguments);
 890         OopMap* map = save_live_registers(sasm);
 891 
 892         // Called with store_parameter and not C abi
 893 
 894         f.load_argument(2, x10); // x10: array
 895         f.load_argument(1, x11); // x11: index
 896         f.load_argument(0, x12); // x12: value
 897         int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, store_flat_array), x10, x11, x12);
 898 
 899         oop_maps = new OopMapSet();
 900         oop_maps->add_gc_map(call_offset, map);
 901         restore_live_registers_except_r10(sasm);
 902       }
 903       break;
 904 
 905     case StubId::c1_substitutability_check_id:
 906       {
 907         StubFrame f(sasm, "substitutability_check", dont_gc_arguments);
 908         OopMap* map = save_live_registers(sasm);
 909 
 910         // Called with store_parameter and not C abi
 911 
 912         f.load_argument(1, x11); // x11,: left
 913         f.load_argument(0, x12); // x12,: right
 914         int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, substitutability_check), x11, x12);
 915 
 916         oop_maps = new OopMapSet();
 917         oop_maps->add_gc_map(call_offset, map);
 918         restore_live_registers_except_r10(sasm);
 919 
 920         // x10,: are the two operands substitutable
 921       }
 922       break;
 923 
 924     case StubId::c1_register_finalizer_id:
 925       {
 926         __ set_info("register_finalizer", dont_gc_arguments);
 927 
 928         // This is called via call_runtime so the arguments
 929         // will be place in C abi locations
 930         __ verify_oop(c_rarg0);
 931 
 932         // load the klass and check the has finalizer flag
 933         Label register_finalizer;
 934         Register t = x15;
 935         __ load_klass(t, x10);
 936         __ lbu(t, Address(t, Klass::misc_flags_offset()));
 937         __ test_bit(t0, t, exact_log2(KlassFlags::_misc_has_finalizer));
 938         __ bnez(t0, register_finalizer);
 939         __ ret();
 940 
 941         __ bind(register_finalizer);
 942         __ enter();
 943         OopMap* oop_map = save_live_registers(sasm);

 947         assert_cond(oop_maps != nullptr);
 948         oop_maps->add_gc_map(call_offset, oop_map);
 949 
 950         // Now restore all the live registers
 951         restore_live_registers(sasm);
 952 
 953         __ leave();
 954         __ ret();
 955       }
 956       break;
 957 
 958     case StubId::c1_throw_class_cast_exception_id:
 959       {
 960         StubFrame f(sasm, "throw_class_cast_exception", dont_gc_arguments, does_not_return);
 961         oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true);
 962       }
 963       break;
 964 
 965     case StubId::c1_throw_incompatible_class_change_error_id:
 966       {
 967         StubFrame f(sasm, "throw_incompatible_class_change_error", dont_gc_arguments, does_not_return);
 968         oop_maps = generate_exception_throw(sasm,
 969                                             CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false);
 970       }
 971       break;
 972 
 973     case StubId::c1_throw_illegal_monitor_state_exception_id:
 974       { StubFrame f(sasm, "throw_illegal_monitor_state_exception", dont_gc_arguments);
 975         oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_illegal_monitor_state_exception), false);
 976       }
 977       break;
 978 
 979     case StubId::c1_throw_identity_exception_id:
 980       { StubFrame f(sasm, "throw_identity_exception", dont_gc_arguments);
 981         oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_identity_exception), true);
 982       }
 983       break;
 984 
 985     case StubId::c1_slow_subtype_check_id:
 986       {
 987         // Typical calling sequence:
 988         // push klass_RInfo (object klass or other subclass)
 989         // push sup_k_RInfo (array element klass or other superclass)
 990         // jump to slow_subtype_check
 991         // Note that the subclass is pushed first, and is therefore deepest.
 992         enum layout {
 993           x10_off, x10_off_hi,
 994           x12_off, x12_off_hi,
 995           x14_off, x14_off_hi,
 996           x15_off, x15_off_hi,
 997           sup_k_off, sup_k_off_hi,
 998           klass_off, klass_off_hi,
 999           framesize,
1000           result_off = sup_k_off
1001         };
1002 
1003         __ set_info("slow_subtype_check", dont_gc_arguments);
1004         __ push_reg(RegSet::of(x10, x12, x14, x15), sp);
< prev index next >