< prev index next >

src/hotspot/cpu/x86/c1_Runtime1_x86.cpp

Print this page

   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
< prev index next >