1 /*
2 * Copyright (c) 1999, 2025, 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 *
865 case StubId::c1_counter_overflow_id:
866 {
867 Register bci = rax, method = rbx;
868 __ enter();
869 OopMap* map = save_live_registers(sasm, 3);
870 // Retrieve bci
871 __ movl(bci, Address(rbp, 2*BytesPerWord));
872 // And a pointer to the Method*
873 __ movptr(method, Address(rbp, 3*BytesPerWord));
874 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, counter_overflow), bci, method);
875 oop_maps = new OopMapSet();
876 oop_maps->add_gc_map(call_offset, map);
877 restore_live_registers(sasm);
878 __ leave();
879 __ ret(0);
880 }
881 break;
882
883 case StubId::c1_new_type_array_id:
884 case StubId::c1_new_object_array_id:
885 {
886 Register length = rbx; // Incoming
887 Register klass = rdx; // Incoming
888 Register obj = rax; // Result
889
890 if (id == StubId::c1_new_type_array_id) {
891 __ set_info("new_type_array", dont_gc_arguments);
892 } else {
893 __ set_info("new_object_array", dont_gc_arguments);
894 }
895
896 #ifdef ASSERT
897 // assert object type is really an array of the proper kind
898 {
899 Label ok;
900 Register t0 = obj;
901 __ movl(t0, Address(klass, Klass::layout_helper_offset()));
902 __ sarl(t0, Klass::_lh_array_tag_shift);
903 int tag = ((id == StubId::c1_new_type_array_id)
904 ? Klass::_lh_array_tag_type_value
905 : Klass::_lh_array_tag_obj_value);
906 __ cmpl(t0, tag);
907 __ jcc(Assembler::equal, ok);
908 __ stop("assert(is an array klass)");
909 __ should_not_reach_here();
910 __ bind(ok);
911 }
912 #endif // ASSERT
913
914 __ enter();
915 OopMap* map = save_live_registers(sasm, 3);
916 int call_offset;
917 if (id == StubId::c1_new_type_array_id) {
918 call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length);
919 } else {
920 call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length);
921 }
922
923 oop_maps = new OopMapSet();
924 oop_maps->add_gc_map(call_offset, map);
925 restore_live_registers_except_rax(sasm);
926
927 __ verify_oop(obj);
928 __ leave();
929 __ ret(0);
930
931 // rax,: new array
932 }
933 break;
934
935 case StubId::c1_new_multi_array_id:
936 { StubFrame f(sasm, "new_multi_array", dont_gc_arguments);
937 // rax,: klass
938 // rbx,: rank
939 // rcx: address of 1st dimension
940 OopMap* map = save_live_registers(sasm, 4);
941 int call_offset = __ call_RT(rax, noreg, CAST_FROM_FN_PTR(address, new_multi_array), rax, rbx, rcx);
942
943 oop_maps = new OopMapSet();
944 oop_maps->add_gc_map(call_offset, map);
945 restore_live_registers_except_rax(sasm);
946
947 // rax,: new multi array
948 __ verify_oop(rax);
949 }
950 break;
951
952 case StubId::c1_register_finalizer_id:
953 {
954 __ set_info("register_finalizer", dont_gc_arguments);
955
956 // This is called via call_runtime so the arguments
957 // will be place in C abi locations
958
959 __ verify_oop(c_rarg0);
960 __ mov(rax, c_rarg0);
961
962 // load the klass and check the has finalizer flag
963 Label register_finalizer;
964 Register t = rsi;
965 __ load_klass(t, rax, rscratch1);
966 __ testb(Address(t, Klass::misc_flags_offset()), KlassFlags::_misc_has_finalizer);
967 __ jcc(Assembler::notZero, register_finalizer);
968 __ ret(0);
969
970 __ bind(register_finalizer);
971 __ enter();
1025 // activation and we are calling a leaf VM function only.
1026 generate_unwind_exception(sasm);
1027 }
1028 break;
1029
1030 case StubId::c1_throw_array_store_exception_id:
1031 { StubFrame f(sasm, "throw_array_store_exception", dont_gc_arguments);
1032 // tos + 0: link
1033 // + 1: return address
1034 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true);
1035 }
1036 break;
1037
1038 case StubId::c1_throw_class_cast_exception_id:
1039 { StubFrame f(sasm, "throw_class_cast_exception", dont_gc_arguments);
1040 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true);
1041 }
1042 break;
1043
1044 case StubId::c1_throw_incompatible_class_change_error_id:
1045 { StubFrame f(sasm, "throw_incompatible_class_cast_exception", dont_gc_arguments);
1046 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false);
1047 }
1048 break;
1049
1050 case StubId::c1_slow_subtype_check_id:
1051 {
1052 // Typical calling sequence:
1053 // __ push(klass_RInfo); // object klass or other subclass
1054 // __ push(sup_k_RInfo); // array element klass or other superclass
1055 // __ call(slow_subtype_check);
1056 // Note that the subclass is pushed first, and is therefore deepest.
1057 // Previous versions of this code reversed the names 'sub' and 'super'.
1058 // This was operationally harmless but made the code unreadable.
1059 enum layout {
1060 rax_off, SLOT2(raxH_off)
1061 rcx_off, SLOT2(rcxH_off)
1062 rsi_off, SLOT2(rsiH_off)
1063 rdi_off, SLOT2(rdiH_off)
1064 // saved_rbp_off, SLOT2(saved_rbpH_off)
1065 return_off, SLOT2(returnH_off)
1066 sup_k_off, SLOT2(sup_kH_off)
1067 klass_off, SLOT2(superH_off)
1068 framesize,
1069 result_off = klass_off // deepest argument is also the return value
|
1 /*
2 * Copyright (c) 1999, 2026, 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 *
865 case StubId::c1_counter_overflow_id:
866 {
867 Register bci = rax, method = rbx;
868 __ enter();
869 OopMap* map = save_live_registers(sasm, 3);
870 // Retrieve bci
871 __ movl(bci, Address(rbp, 2*BytesPerWord));
872 // And a pointer to the Method*
873 __ movptr(method, Address(rbp, 3*BytesPerWord));
874 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, counter_overflow), bci, method);
875 oop_maps = new OopMapSet();
876 oop_maps->add_gc_map(call_offset, map);
877 restore_live_registers(sasm);
878 __ leave();
879 __ ret(0);
880 }
881 break;
882
883 case StubId::c1_new_type_array_id:
884 case StubId::c1_new_object_array_id:
885 case StubId::c1_new_null_free_array_id:
886 {
887 Register length = rbx; // Incoming
888 Register klass = rdx; // Incoming
889 Register obj = rax; // Result
890
891 if (id == StubId::c1_new_type_array_id) {
892 __ set_info("new_type_array", dont_gc_arguments);
893 } else if (id == StubId::c1_new_object_array_id) {
894 __ set_info("new_object_array", dont_gc_arguments);
895 } else {
896 __ set_info("new_null_free_array", dont_gc_arguments);
897 }
898
899 #ifdef ASSERT
900 // assert object type is really an array of the proper kind
901 {
902 Label ok;
903 Register t0 = obj;
904 __ movl(t0, Address(klass, Klass::layout_helper_offset()));
905 __ sarl(t0, Klass::_lh_array_tag_shift);
906 switch (id) {
907 case StubId::c1_new_type_array_id:
908 __ cmpl(t0, Klass::_lh_array_tag_type_value);
909 __ jcc(Assembler::equal, ok);
910 __ stop("assert(is a type array klass)");
911 break;
912 case StubId::c1_new_object_array_id:
913 __ cmpl(t0, (Klass::_lh_array_tag_ref_value)); // new "[Ljava/lang/Object;"
914 __ jcc(Assembler::equal, ok);
915 __ cmpl(t0, Klass::_lh_array_tag_flat_value); // new "[LVT;"
916 __ jcc(Assembler::equal, ok);
917 __ stop("assert(is an object or inline type array klass)");
918 break;
919 case StubId::c1_new_null_free_array_id:
920 __ cmpl(t0, Klass::_lh_array_tag_flat_value); // the array can be a flat array.
921 __ jcc(Assembler::equal, ok);
922 __ cmpl(t0, (Klass::_lh_array_tag_ref_value)); // the array cannot be a flat array (due to InlineArrayElementMaxFlatSize, etc)
923 __ jcc(Assembler::equal, ok);
924 __ stop("assert(is an object or inline type array klass)");
925 break;
926 default: ShouldNotReachHere();
927 }
928 __ should_not_reach_here();
929 __ bind(ok);
930 }
931 #endif // ASSERT
932
933 __ enter();
934 OopMap* map = save_live_registers(sasm, 3);
935 int call_offset;
936 if (id == StubId::c1_new_type_array_id) {
937 call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length);
938 } else if (id == StubId::c1_new_object_array_id) {
939 call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length);
940 } else {
941 assert(id == StubId::c1_new_null_free_array_id, "must be");
942 call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_null_free_array), klass, length);
943 }
944
945 oop_maps = new OopMapSet();
946 oop_maps->add_gc_map(call_offset, map);
947 restore_live_registers_except_rax(sasm);
948
949 __ verify_oop(obj);
950 __ leave();
951 __ ret(0);
952
953 // rax,: new array
954 }
955 break;
956
957 case StubId::c1_new_multi_array_id:
958 { StubFrame f(sasm, "new_multi_array", dont_gc_arguments);
959 // rax,: klass
960 // rbx,: rank
961 // rcx: address of 1st dimension
962 OopMap* map = save_live_registers(sasm, 4);
963 int call_offset = __ call_RT(rax, noreg, CAST_FROM_FN_PTR(address, new_multi_array), rax, rbx, rcx);
964
965 oop_maps = new OopMapSet();
966 oop_maps->add_gc_map(call_offset, map);
967 restore_live_registers_except_rax(sasm);
968
969 // rax,: new multi array
970 __ verify_oop(rax);
971 }
972 break;
973
974 case StubId::c1_load_flat_array_id:
975 {
976 StubFrame f(sasm, "load_flat_array", dont_gc_arguments);
977 OopMap* map = save_live_registers(sasm, 3);
978
979 // Called with store_parameter and not C abi
980
981 f.load_argument(1, rax); // rax,: array
982 f.load_argument(0, rbx); // rbx,: index
983 int call_offset = __ call_RT(rax, noreg, CAST_FROM_FN_PTR(address, load_flat_array), rax, rbx);
984
985 oop_maps = new OopMapSet();
986 oop_maps->add_gc_map(call_offset, map);
987 restore_live_registers_except_rax(sasm);
988
989 // rax,: loaded element at array[index]
990 __ verify_oop(rax);
991 }
992 break;
993
994 case StubId::c1_store_flat_array_id:
995 {
996 StubFrame f(sasm, "store_flat_array", dont_gc_arguments);
997 OopMap* map = save_live_registers(sasm, 4);
998
999 // Called with store_parameter and not C abi
1000
1001 f.load_argument(2, rax); // rax,: array
1002 f.load_argument(1, rbx); // rbx,: index
1003 f.load_argument(0, rcx); // rcx,: value
1004 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, store_flat_array), rax, rbx, rcx);
1005
1006 oop_maps = new OopMapSet();
1007 oop_maps->add_gc_map(call_offset, map);
1008 restore_live_registers_except_rax(sasm);
1009 }
1010 break;
1011
1012 case StubId::c1_substitutability_check_id:
1013 {
1014 StubFrame f(sasm, "substitutability_check", dont_gc_arguments);
1015 OopMap* map = save_live_registers(sasm, 3);
1016
1017 // Called with store_parameter and not C abi
1018
1019 f.load_argument(1, rax); // rax,: left
1020 f.load_argument(0, rbx); // rbx,: right
1021 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, substitutability_check), rax, rbx);
1022
1023 oop_maps = new OopMapSet();
1024 oop_maps->add_gc_map(call_offset, map);
1025 restore_live_registers_except_rax(sasm);
1026
1027 // rax,: are the two operands substitutable
1028 }
1029 break;
1030
1031
1032 case StubId::c1_buffer_inline_args_id:
1033 case StubId::c1_buffer_inline_args_no_receiver_id:
1034 {
1035 const char* name = (id == StubId::c1_buffer_inline_args_id) ?
1036 "buffer_inline_args" : "buffer_inline_args_no_receiver";
1037 StubFrame f(sasm, name, dont_gc_arguments);
1038 OopMap* map = save_live_registers(sasm, 2);
1039 Register method = rbx;
1040 address entry = (id == StubId::c1_buffer_inline_args_id) ?
1041 CAST_FROM_FN_PTR(address, buffer_inline_args) :
1042 CAST_FROM_FN_PTR(address, buffer_inline_args_no_receiver);
1043 int call_offset = __ call_RT(rax, noreg, entry, method);
1044 oop_maps = new OopMapSet();
1045 oop_maps->add_gc_map(call_offset, map);
1046 restore_live_registers_except_rax(sasm);
1047 __ verify_oop(rax); // rax: an array of buffered value objects
1048 }
1049 break;
1050
1051 case StubId::c1_register_finalizer_id:
1052 {
1053 __ set_info("register_finalizer", dont_gc_arguments);
1054
1055 // This is called via call_runtime so the arguments
1056 // will be place in C abi locations
1057
1058 __ verify_oop(c_rarg0);
1059 __ mov(rax, c_rarg0);
1060
1061 // load the klass and check the has finalizer flag
1062 Label register_finalizer;
1063 Register t = rsi;
1064 __ load_klass(t, rax, rscratch1);
1065 __ testb(Address(t, Klass::misc_flags_offset()), KlassFlags::_misc_has_finalizer);
1066 __ jcc(Assembler::notZero, register_finalizer);
1067 __ ret(0);
1068
1069 __ bind(register_finalizer);
1070 __ enter();
1124 // activation and we are calling a leaf VM function only.
1125 generate_unwind_exception(sasm);
1126 }
1127 break;
1128
1129 case StubId::c1_throw_array_store_exception_id:
1130 { StubFrame f(sasm, "throw_array_store_exception", dont_gc_arguments);
1131 // tos + 0: link
1132 // + 1: return address
1133 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true);
1134 }
1135 break;
1136
1137 case StubId::c1_throw_class_cast_exception_id:
1138 { StubFrame f(sasm, "throw_class_cast_exception", dont_gc_arguments);
1139 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true);
1140 }
1141 break;
1142
1143 case StubId::c1_throw_incompatible_class_change_error_id:
1144 { StubFrame f(sasm, "throw_incompatible_class_change_error", dont_gc_arguments);
1145 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false);
1146 }
1147 break;
1148
1149 case StubId::c1_throw_illegal_monitor_state_exception_id:
1150 { StubFrame f(sasm, "throw_illegal_monitor_state_exception", dont_gc_arguments);
1151 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_illegal_monitor_state_exception), false);
1152 }
1153 break;
1154
1155 case StubId::c1_throw_identity_exception_id:
1156 { StubFrame f(sasm, "throw_identity_exception", dont_gc_arguments);
1157 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_identity_exception), true);
1158 }
1159 break;
1160
1161 case StubId::c1_slow_subtype_check_id:
1162 {
1163 // Typical calling sequence:
1164 // __ push(klass_RInfo); // object klass or other subclass
1165 // __ push(sup_k_RInfo); // array element klass or other superclass
1166 // __ call(slow_subtype_check);
1167 // Note that the subclass is pushed first, and is therefore deepest.
1168 // Previous versions of this code reversed the names 'sub' and 'super'.
1169 // This was operationally harmless but made the code unreadable.
1170 enum layout {
1171 rax_off, SLOT2(raxH_off)
1172 rcx_off, SLOT2(rcxH_off)
1173 rsi_off, SLOT2(rsiH_off)
1174 rdi_off, SLOT2(rdiH_off)
1175 // saved_rbp_off, SLOT2(saved_rbpH_off)
1176 return_off, SLOT2(returnH_off)
1177 sup_k_off, SLOT2(sup_kH_off)
1178 klass_off, SLOT2(superH_off)
1179 framesize,
1180 result_off = klass_off // deepest argument is also the return value
|