< prev index next >

src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp

Print this page

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

 724     case StubId::c1_counter_overflow_id:
 725       {
 726         Register bci = r0, method = r1;
 727         __ enter();
 728         OopMap* map = save_live_registers(sasm);
 729         // Retrieve bci
 730         __ ldrw(bci, Address(rfp, 2*BytesPerWord));
 731         // And a pointer to the Method*
 732         __ ldr(method, Address(rfp, 3*BytesPerWord));
 733         int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, counter_overflow), bci, method);
 734         oop_maps = new OopMapSet();
 735         oop_maps->add_gc_map(call_offset, map);
 736         restore_live_registers(sasm);
 737         __ leave();
 738         __ ret(lr);
 739       }
 740       break;
 741 
 742     case StubId::c1_new_type_array_id:
 743     case StubId::c1_new_object_array_id:

 744       {
 745         Register length   = r19; // Incoming
 746         Register klass    = r3; // Incoming
 747         Register obj      = r0; // Result
 748 
 749         if (id == StubId::c1_new_type_array_id) {
 750           __ set_info("new_type_array", dont_gc_arguments);
 751         } else {
 752           __ set_info("new_object_array", dont_gc_arguments);


 753         }
 754 
 755 #ifdef ASSERT
 756         // assert object type is really an array of the proper kind
 757         {
 758           Label ok;
 759           Register t0 = obj;
 760           __ ldrw(t0, Address(klass, Klass::layout_helper_offset()));
 761           __ asrw(t0, t0, Klass::_lh_array_tag_shift);
 762           int tag = ((id == StubId::c1_new_type_array_id)
 763                      ? Klass::_lh_array_tag_type_value
 764                      : Klass::_lh_array_tag_obj_value);
 765           __ mov(rscratch1, tag);
 766           __ cmpw(t0, rscratch1);
 767           __ br(Assembler::EQ, ok);
 768           __ stop("assert(is an array klass)");















 769           __ should_not_reach_here();
 770           __ bind(ok);
 771         }
 772 #endif // ASSERT
 773 
 774         __ enter();
 775         OopMap* map = save_live_registers(sasm);
 776         int call_offset;
 777         if (id == StubId::c1_new_type_array_id) {
 778           call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length);
 779         } else {
 780           call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length);



 781         }
 782 
 783         oop_maps = new OopMapSet();
 784         oop_maps->add_gc_map(call_offset, map);
 785         restore_live_registers_except_r0(sasm);
 786 
 787         __ verify_oop(obj);
 788         __ leave();
 789         __ ret(lr);
 790 
 791         // r0: new array
 792       }
 793       break;
 794 
 795     case StubId::c1_new_multi_array_id:
 796       { StubFrame f(sasm, "new_multi_array", dont_gc_arguments);
 797         // r0,: klass
 798         // r19,: rank
 799         // r2: address of 1st dimension
 800         OopMap* map = save_live_registers(sasm);
 801         __ mov(c_rarg1, r0);
 802         __ mov(c_rarg3, r2);
 803         __ mov(c_rarg2, r19);
 804         int call_offset = __ call_RT(r0, noreg, CAST_FROM_FN_PTR(address, new_multi_array), r1, r2, r3);
 805 
 806         oop_maps = new OopMapSet();
 807         oop_maps->add_gc_map(call_offset, map);
 808         restore_live_registers_except_r0(sasm);
 809 
 810         // r0,: new multi array
 811         __ verify_oop(r0);
 812       }
 813       break;
 814 























































































 815     case StubId::c1_register_finalizer_id:
 816       {
 817         __ set_info("register_finalizer", dont_gc_arguments);
 818 
 819         // This is called via call_runtime so the arguments
 820         // will be place in C abi locations
 821 
 822         __ verify_oop(c_rarg0);
 823 
 824         // load the klass and check the has finalizer flag
 825         Label register_finalizer;
 826         Register t = r5;
 827         __ load_klass(t, r0);
 828         __ ldrb(t, Address(t, Klass::misc_flags_offset()));
 829         __ tbnz(t, exact_log2(KlassFlags::_misc_has_finalizer), register_finalizer);
 830         __ ret(lr);
 831 
 832         __ bind(register_finalizer);
 833         __ enter();
 834         OopMap* oop_map = save_live_registers(sasm);
 835         int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, SharedRuntime::register_finalizer), r0);
 836         oop_maps = new OopMapSet();
 837         oop_maps->add_gc_map(call_offset, oop_map);
 838 
 839         // Now restore all the live registers
 840         restore_live_registers(sasm);
 841 
 842         __ leave();
 843         __ ret(lr);
 844       }
 845       break;
 846 
 847     case StubId::c1_throw_class_cast_exception_id:
 848       { StubFrame f(sasm, "throw_class_cast_exception", dont_gc_arguments, does_not_return);
 849         oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true);
 850       }
 851       break;
 852 
 853     case StubId::c1_throw_incompatible_class_change_error_id:
 854       { StubFrame f(sasm, "throw_incompatible_class_cast_exception", dont_gc_arguments, does_not_return);
 855         oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false);
 856       }
 857       break;
 858 












 859     case StubId::c1_slow_subtype_check_id:
 860       {
 861         // Typical calling sequence:
 862         // __ push(klass_RInfo);  // object klass or other subclass
 863         // __ push(sup_k_RInfo);  // array element klass or other superclass
 864         // __ bl(slow_subtype_check);
 865         // Note that the subclass is pushed first, and is therefore deepest.
 866         enum layout {
 867           r0_off, r0_off_hi,
 868           r2_off, r2_off_hi,
 869           r4_off, r4_off_hi,
 870           r5_off, r5_off_hi,
 871           sup_k_off, sup_k_off_hi,
 872           klass_off, klass_off_hi,
 873           framesize,
 874           result_off = sup_k_off
 875         };
 876 
 877         __ set_info("slow_subtype_check", dont_gc_arguments);
 878         __ push(RegSet::of(r0, r2, r4, r5), sp);

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

 724     case StubId::c1_counter_overflow_id:
 725       {
 726         Register bci = r0, method = r1;
 727         __ enter();
 728         OopMap* map = save_live_registers(sasm);
 729         // Retrieve bci
 730         __ ldrw(bci, Address(rfp, 2*BytesPerWord));
 731         // And a pointer to the Method*
 732         __ ldr(method, Address(rfp, 3*BytesPerWord));
 733         int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, counter_overflow), bci, method);
 734         oop_maps = new OopMapSet();
 735         oop_maps->add_gc_map(call_offset, map);
 736         restore_live_registers(sasm);
 737         __ leave();
 738         __ ret(lr);
 739       }
 740       break;
 741 
 742     case StubId::c1_new_type_array_id:
 743     case StubId::c1_new_object_array_id:
 744     case StubId::c1_new_null_free_array_id:
 745       {
 746         Register length   = r19; // Incoming
 747         Register klass    = r3; // Incoming
 748         Register obj      = r0; // Result
 749 
 750         if (id == StubId::c1_new_type_array_id) {
 751           __ set_info("new_type_array", dont_gc_arguments);
 752         } else if (id == StubId::c1_new_object_array_id) {
 753           __ set_info("new_object_array", dont_gc_arguments);
 754         } else {
 755           __ set_info("new_null_free_array", dont_gc_arguments);
 756         }
 757 
 758 #ifdef ASSERT
 759         // assert object type is really an array of the proper kind
 760         {
 761           Label ok;
 762           Register t0 = obj;
 763           __ ldrw(t0, Address(klass, Klass::layout_helper_offset()));
 764           __ asrw(t0, t0, Klass::_lh_array_tag_shift);
 765           switch (id) {
 766           case StubId::c1_new_type_array_id:
 767             __ cmpw(t0, Klass::_lh_array_tag_type_value);
 768             __ br(Assembler::EQ, ok);
 769             __ stop("assert(is a type array klass)");
 770             break;
 771           case StubId::c1_new_object_array_id:
 772             __ cmpw(t0, Klass::_lh_array_tag_ref_value); // new "[Ljava/lang/Object;"
 773             __ br(Assembler::EQ, ok);
 774             __ cmpw(t0, Klass::_lh_array_tag_flat_value);  // new "[LVT;"
 775             __ br(Assembler::EQ, ok);
 776             __ stop("assert(is an object or inline type array klass)");
 777             break;
 778           case StubId::c1_new_null_free_array_id:
 779             __ cmpw(t0, Klass::_lh_array_tag_flat_value);  // the array can be a flat array.
 780             __ br(Assembler::EQ, ok);
 781             __ cmpw(t0, Klass::_lh_array_tag_ref_value); // the array cannot be a flat array (due to the InlineArrayElementMaxFlatSize, etc.)
 782             __ br(Assembler::EQ, ok);
 783             __ stop("assert(is an object or inline type array klass)");
 784             break;
 785           default:  ShouldNotReachHere();
 786           }
 787           __ should_not_reach_here();
 788           __ bind(ok);
 789         }
 790 #endif // ASSERT
 791 
 792         __ enter();
 793         OopMap* map = save_live_registers(sasm);
 794         int call_offset;
 795         if (id == StubId::c1_new_type_array_id) {
 796           call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length);
 797         } else if (id == StubId::c1_new_object_array_id) {
 798           call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length);
 799         } else {
 800           assert(id == StubId::c1_new_null_free_array_id, "must be");
 801           call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_null_free_array), klass, length);
 802         }
 803 
 804         oop_maps = new OopMapSet();
 805         oop_maps->add_gc_map(call_offset, map);
 806         restore_live_registers_except_r0(sasm);
 807 
 808         __ verify_oop(obj);
 809         __ leave();
 810         __ ret(lr);
 811 
 812         // r0: new array
 813       }
 814       break;
 815 
 816     case StubId::c1_new_multi_array_id:
 817       { StubFrame f(sasm, "new_multi_array", dont_gc_arguments);
 818         // r0,: klass
 819         // r19,: rank
 820         // r2: address of 1st dimension
 821         OopMap* map = save_live_registers(sasm);
 822         __ mov(c_rarg1, r0);
 823         __ mov(c_rarg3, r2);
 824         __ mov(c_rarg2, r19);
 825         int call_offset = __ call_RT(r0, noreg, CAST_FROM_FN_PTR(address, new_multi_array), r1, r2, r3);
 826 
 827         oop_maps = new OopMapSet();
 828         oop_maps->add_gc_map(call_offset, map);
 829         restore_live_registers_except_r0(sasm);
 830 
 831         // r0,: new multi array
 832         __ verify_oop(r0);
 833       }
 834       break;
 835 
 836     case StubId::c1_buffer_inline_args_id:
 837     case StubId::c1_buffer_inline_args_no_receiver_id:
 838       {
 839         const char* name = (id == StubId::c1_buffer_inline_args_id) ?
 840           "buffer_inline_args" : "buffer_inline_args_no_receiver";
 841         StubFrame f(sasm, name, dont_gc_arguments);
 842         OopMap* map = save_live_registers(sasm);
 843         Register method = r19;   // Incoming
 844         address entry = (id == StubId::c1_buffer_inline_args_id) ?
 845           CAST_FROM_FN_PTR(address, buffer_inline_args) :
 846           CAST_FROM_FN_PTR(address, buffer_inline_args_no_receiver);
 847         // This is called from a C1 method's scalarized entry point
 848         // where r0-r7 may be holding live argument values so we can't
 849         // return the result in r0 as the other stubs do. LR is used as
 850         // a temporary below to avoid the result being clobbered by
 851         // restore_live_registers. It's saved and restored by
 852         // StubAssembler::prologue and epilogue anyway.
 853         int call_offset = __ call_RT(lr, noreg, entry, method);
 854         oop_maps = new OopMapSet();
 855         oop_maps->add_gc_map(call_offset, map);
 856         restore_live_registers(sasm);
 857         __ mov(r20, lr);
 858         __ verify_oop(r20);  // r20: an array of buffered value objects
 859      }
 860      break;
 861 
 862     case StubId::c1_load_flat_array_id:
 863       {
 864         StubFrame f(sasm, "load_flat_array", dont_gc_arguments);
 865         OopMap* map = save_live_registers(sasm);
 866 
 867         // Called with store_parameter and not C abi
 868 
 869         f.load_argument(1, r0); // r0,: array
 870         f.load_argument(0, r1); // r1,: index
 871         int call_offset = __ call_RT(r0, noreg, CAST_FROM_FN_PTR(address, load_flat_array), r0, r1);
 872 
 873         // Ensure the stores that initialize the buffer are visible
 874         // before any subsequent store that publishes this reference.
 875         __ membar(Assembler::StoreStore);
 876 
 877         oop_maps = new OopMapSet();
 878         oop_maps->add_gc_map(call_offset, map);
 879         restore_live_registers_except_r0(sasm);
 880 
 881         // r0: loaded element at array[index]
 882         __ verify_oop(r0);
 883       }
 884       break;
 885 
 886     case StubId::c1_store_flat_array_id:
 887       {
 888         StubFrame f(sasm, "store_flat_array", dont_gc_arguments);
 889         OopMap* map = save_live_registers(sasm);
 890 
 891         // Called with store_parameter and not C abi
 892 
 893         f.load_argument(2, r0); // r0: array
 894         f.load_argument(1, r1); // r1: index
 895         f.load_argument(0, r2); // r2: value
 896         int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, store_flat_array), r0, r1, r2);
 897 
 898         oop_maps = new OopMapSet();
 899         oop_maps->add_gc_map(call_offset, map);
 900         restore_live_registers_except_r0(sasm);
 901       }
 902       break;
 903 
 904     case StubId::c1_substitutability_check_id:
 905       {
 906         StubFrame f(sasm, "substitutability_check", dont_gc_arguments);
 907         OopMap* map = save_live_registers(sasm);
 908 
 909         // Called with store_parameter and not C abi
 910 
 911         f.load_argument(1, r1); // r1,: left
 912         f.load_argument(0, r2); // r2,: right
 913         int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, substitutability_check), r1, r2);
 914 
 915         oop_maps = new OopMapSet();
 916         oop_maps->add_gc_map(call_offset, map);
 917         restore_live_registers_except_r0(sasm);
 918 
 919         // r0,: are the two operands substitutable
 920       }
 921       break;
 922 
 923     case StubId::c1_register_finalizer_id:
 924       {
 925         __ set_info("register_finalizer", dont_gc_arguments);
 926 
 927         // This is called via call_runtime so the arguments
 928         // will be place in C abi locations
 929 
 930         __ verify_oop(c_rarg0);
 931 
 932         // load the klass and check the has finalizer flag
 933         Label register_finalizer;
 934         Register t = r5;
 935         __ load_klass(t, r0);
 936         __ ldrb(t, Address(t, Klass::misc_flags_offset()));
 937         __ tbnz(t, exact_log2(KlassFlags::_misc_has_finalizer), register_finalizer);
 938         __ ret(lr);
 939 
 940         __ bind(register_finalizer);
 941         __ enter();
 942         OopMap* oop_map = save_live_registers(sasm);
 943         int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, SharedRuntime::register_finalizer), r0);
 944         oop_maps = new OopMapSet();
 945         oop_maps->add_gc_map(call_offset, oop_map);
 946 
 947         // Now restore all the live registers
 948         restore_live_registers(sasm);
 949 
 950         __ leave();
 951         __ ret(lr);
 952       }
 953       break;
 954 
 955     case StubId::c1_throw_class_cast_exception_id:
 956       { StubFrame f(sasm, "throw_class_cast_exception", dont_gc_arguments, does_not_return);
 957         oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true);
 958       }
 959       break;
 960 
 961     case StubId::c1_throw_incompatible_class_change_error_id:
 962       { StubFrame f(sasm, "throw_incompatible_class_change_error", dont_gc_arguments, does_not_return);
 963         oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false);
 964       }
 965       break;
 966 
 967     case StubId::c1_throw_illegal_monitor_state_exception_id:
 968       { StubFrame f(sasm, "throw_illegal_monitor_state_exception", dont_gc_arguments);
 969         oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_illegal_monitor_state_exception), false);
 970       }
 971       break;
 972 
 973     case StubId::c1_throw_identity_exception_id:
 974       { StubFrame f(sasm, "throw_identity_exception", dont_gc_arguments);
 975         oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_identity_exception), true);
 976       }
 977       break;
 978 
 979     case StubId::c1_slow_subtype_check_id:
 980       {
 981         // Typical calling sequence:
 982         // __ push(klass_RInfo);  // object klass or other subclass
 983         // __ push(sup_k_RInfo);  // array element klass or other superclass
 984         // __ bl(slow_subtype_check);
 985         // Note that the subclass is pushed first, and is therefore deepest.
 986         enum layout {
 987           r0_off, r0_off_hi,
 988           r2_off, r2_off_hi,
 989           r4_off, r4_off_hi,
 990           r5_off, r5_off_hi,
 991           sup_k_off, sup_k_off_hi,
 992           klass_off, klass_off_hi,
 993           framesize,
 994           result_off = sup_k_off
 995         };
 996 
 997         __ set_info("slow_subtype_check", dont_gc_arguments);
 998         __ push(RegSet::of(r0, r2, r4, r5), sp);
< prev index next >