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);
|