1042 break;
1043
1044 case C1StubId::new_instance_id:
1045 case C1StubId::fast_new_instance_id:
1046 case C1StubId::fast_new_instance_init_check_id:
1047 {
1048 Register klass = rdx; // Incoming
1049 Register obj = rax; // Result
1050
1051 if (id == C1StubId::new_instance_id) {
1052 __ set_info("new_instance", dont_gc_arguments);
1053 } else if (id == C1StubId::fast_new_instance_id) {
1054 __ set_info("fast new_instance", dont_gc_arguments);
1055 } else {
1056 assert(id == C1StubId::fast_new_instance_init_check_id, "bad C1StubId");
1057 __ set_info("fast new_instance init check", dont_gc_arguments);
1058 }
1059
1060 __ enter();
1061 OopMap* map = save_live_registers(sasm, 2);
1062 int call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_instance), klass);
1063 oop_maps = new OopMapSet();
1064 oop_maps->add_gc_map(call_offset, map);
1065 restore_live_registers_except_rax(sasm);
1066 __ verify_oop(obj);
1067 __ leave();
1068 __ ret(0);
1069
1070 // rax,: new instance
1071 }
1072
1073 break;
1074
1075 case C1StubId::counter_overflow_id:
1076 {
1077 Register bci = rax, method = rbx;
1078 __ enter();
1079 OopMap* map = save_live_registers(sasm, 3);
1080 // Retrieve bci
1081 __ movl(bci, Address(rbp, 2*BytesPerWord));
1082 // And a pointer to the Method*
1083 __ movptr(method, Address(rbp, 3*BytesPerWord));
1084 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, counter_overflow), bci, method);
1085 oop_maps = new OopMapSet();
1086 oop_maps->add_gc_map(call_offset, map);
1087 restore_live_registers(sasm);
1088 __ leave();
1089 __ ret(0);
1090 }
1091 break;
1092
1093 case C1StubId::new_type_array_id:
1094 case C1StubId::new_object_array_id:
1095 {
1096 Register length = rbx; // Incoming
1097 Register klass = rdx; // Incoming
1098 Register obj = rax; // Result
1099
1100 if (id == C1StubId::new_type_array_id) {
1101 __ set_info("new_type_array", dont_gc_arguments);
1102 } else {
1103 __ set_info("new_object_array", dont_gc_arguments);
1104 }
1105
1106 #ifdef ASSERT
1107 // assert object type is really an array of the proper kind
1108 {
1109 Label ok;
1110 Register t0 = obj;
1111 __ movl(t0, Address(klass, Klass::layout_helper_offset()));
1112 __ sarl(t0, Klass::_lh_array_tag_shift);
1113 int tag = ((id == C1StubId::new_type_array_id)
1114 ? Klass::_lh_array_tag_type_value
1115 : Klass::_lh_array_tag_obj_value);
1116 __ cmpl(t0, tag);
1117 __ jcc(Assembler::equal, ok);
1118 __ stop("assert(is an array klass)");
1119 __ should_not_reach_here();
1120 __ bind(ok);
1121 }
1122 #endif // ASSERT
1123
1124 __ enter();
1125 OopMap* map = save_live_registers(sasm, 3);
1126 int call_offset;
1127 if (id == C1StubId::new_type_array_id) {
1128 call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length);
1129 } else {
1130 call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length);
1131 }
1132
1133 oop_maps = new OopMapSet();
1134 oop_maps->add_gc_map(call_offset, map);
1135 restore_live_registers_except_rax(sasm);
1136
1137 __ verify_oop(obj);
1138 __ leave();
1139 __ ret(0);
1140
1141 // rax,: new array
1142 }
1143 break;
1144
1145 case C1StubId::new_multi_array_id:
1146 { StubFrame f(sasm, "new_multi_array", dont_gc_arguments);
1147 // rax,: klass
1148 // rbx,: rank
1149 // rcx: address of 1st dimension
1150 OopMap* map = save_live_registers(sasm, 4);
1151 int call_offset = __ call_RT(rax, noreg, CAST_FROM_FN_PTR(address, new_multi_array), rax, rbx, rcx);
1152
1153 oop_maps = new OopMapSet();
1154 oop_maps->add_gc_map(call_offset, map);
1155 restore_live_registers_except_rax(sasm);
1156
1157 // rax,: new multi array
1158 __ verify_oop(rax);
1159 }
1160 break;
1161
1162 case C1StubId::register_finalizer_id:
1163 {
1164 __ set_info("register_finalizer", dont_gc_arguments);
1165
1166 // This is called via call_runtime so the arguments
1167 // will be place in C abi locations
1168
1169 #ifdef _LP64
1170 __ verify_oop(c_rarg0);
1171 __ mov(rax, c_rarg0);
1172 #else
1173 // The object is passed on the stack and we haven't pushed a
1174 // frame yet so it's one work away from top of stack.
1175 __ movptr(rax, Address(rsp, 1 * BytesPerWord));
1176 __ verify_oop(rax);
1177 #endif // _LP64
1178
1179 // load the klass and check the has finalizer flag
1180 Label register_finalizer;
1181 Register t = rsi;
1242 // activation and we are calling a leaf VM function only.
1243 generate_unwind_exception(sasm);
1244 }
1245 break;
1246
1247 case C1StubId::throw_array_store_exception_id:
1248 { StubFrame f(sasm, "throw_array_store_exception", dont_gc_arguments);
1249 // tos + 0: link
1250 // + 1: return address
1251 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true);
1252 }
1253 break;
1254
1255 case C1StubId::throw_class_cast_exception_id:
1256 { StubFrame f(sasm, "throw_class_cast_exception", dont_gc_arguments);
1257 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true);
1258 }
1259 break;
1260
1261 case C1StubId::throw_incompatible_class_change_error_id:
1262 { StubFrame f(sasm, "throw_incompatible_class_cast_exception", dont_gc_arguments);
1263 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false);
1264 }
1265 break;
1266
1267 case C1StubId::slow_subtype_check_id:
1268 {
1269 // Typical calling sequence:
1270 // __ push(klass_RInfo); // object klass or other subclass
1271 // __ push(sup_k_RInfo); // array element klass or other superclass
1272 // __ call(slow_subtype_check);
1273 // Note that the subclass is pushed first, and is therefore deepest.
1274 // Previous versions of this code reversed the names 'sub' and 'super'.
1275 // This was operationally harmless but made the code unreadable.
1276 enum layout {
1277 rax_off, SLOT2(raxH_off)
1278 rcx_off, SLOT2(rcxH_off)
1279 rsi_off, SLOT2(rsiH_off)
1280 rdi_off, SLOT2(rdiH_off)
1281 // saved_rbp_off, SLOT2(saved_rbpH_off)
1282 return_off, SLOT2(returnH_off)
1283 sup_k_off, SLOT2(sup_kH_off)
1284 klass_off, SLOT2(superH_off)
1285 framesize,
1286 result_off = klass_off // deepest argument is also the return value
|
1042 break;
1043
1044 case C1StubId::new_instance_id:
1045 case C1StubId::fast_new_instance_id:
1046 case C1StubId::fast_new_instance_init_check_id:
1047 {
1048 Register klass = rdx; // Incoming
1049 Register obj = rax; // Result
1050
1051 if (id == C1StubId::new_instance_id) {
1052 __ set_info("new_instance", dont_gc_arguments);
1053 } else if (id == C1StubId::fast_new_instance_id) {
1054 __ set_info("fast new_instance", dont_gc_arguments);
1055 } else {
1056 assert(id == C1StubId::fast_new_instance_init_check_id, "bad C1StubId");
1057 __ set_info("fast new_instance init check", dont_gc_arguments);
1058 }
1059
1060 __ enter();
1061 OopMap* map = save_live_registers(sasm, 2);
1062 int call_offset;
1063 call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_instance), klass);
1064 oop_maps = new OopMapSet();
1065 oop_maps->add_gc_map(call_offset, map);
1066 restore_live_registers_except_rax(sasm);
1067 __ verify_oop(obj);
1068 __ leave();
1069 __ ret(0);
1070
1071 // rax,: new instance
1072 }
1073
1074 break;
1075
1076 case C1StubId::counter_overflow_id:
1077 {
1078 Register bci = rax, method = rbx;
1079 __ enter();
1080 OopMap* map = save_live_registers(sasm, 3);
1081 // Retrieve bci
1082 __ movl(bci, Address(rbp, 2*BytesPerWord));
1083 // And a pointer to the Method*
1084 __ movptr(method, Address(rbp, 3*BytesPerWord));
1085 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, counter_overflow), bci, method);
1086 oop_maps = new OopMapSet();
1087 oop_maps->add_gc_map(call_offset, map);
1088 restore_live_registers(sasm);
1089 __ leave();
1090 __ ret(0);
1091 }
1092 break;
1093
1094 case C1StubId::new_type_array_id:
1095 case C1StubId::new_object_array_id:
1096 case C1StubId::new_null_free_array_id:
1097 {
1098 Register length = rbx; // Incoming
1099 Register klass = rdx; // Incoming
1100 Register obj = rax; // Result
1101
1102 if (id == C1StubId::new_type_array_id) {
1103 __ set_info("new_type_array", dont_gc_arguments);
1104 } else if (id == C1StubId::new_object_array_id) {
1105 __ set_info("new_object_array", dont_gc_arguments);
1106 } else {
1107 __ set_info("new_null_free_array", dont_gc_arguments);
1108 }
1109
1110 #ifdef ASSERT
1111 // assert object type is really an array of the proper kind
1112 {
1113 Label ok;
1114 Register t0 = obj;
1115 __ movl(t0, Address(klass, Klass::layout_helper_offset()));
1116 __ sarl(t0, Klass::_lh_array_tag_shift);
1117 switch (id) {
1118 case C1StubId::new_type_array_id:
1119 __ cmpl(t0, Klass::_lh_array_tag_type_value);
1120 __ jcc(Assembler::equal, ok);
1121 __ stop("assert(is a type array klass)");
1122 break;
1123 case C1StubId::new_object_array_id:
1124 __ cmpl(t0, Klass::_lh_array_tag_obj_value); // new "[Ljava/lang/Object;"
1125 __ jcc(Assembler::equal, ok);
1126 __ cmpl(t0, Klass::_lh_array_tag_vt_value); // new "[LVT;"
1127 __ jcc(Assembler::equal, ok);
1128 __ stop("assert(is an object or inline type array klass)");
1129 break;
1130 case C1StubId::new_null_free_array_id:
1131 __ cmpl(t0, Klass::_lh_array_tag_vt_value); // the array can be a flat array.
1132 __ jcc(Assembler::equal, ok);
1133 __ cmpl(t0, Klass::_lh_array_tag_obj_value); // the array cannot be a flat array (due to InlineArrayElementMaxFlatSize, etc)
1134 __ jcc(Assembler::equal, ok);
1135 __ stop("assert(is an object or inline type array klass)");
1136 break;
1137 default: ShouldNotReachHere();
1138 }
1139 __ should_not_reach_here();
1140 __ bind(ok);
1141 }
1142 #endif // ASSERT
1143
1144 __ enter();
1145 OopMap* map = save_live_registers(sasm, 3);
1146 int call_offset;
1147 if (id == C1StubId::new_type_array_id) {
1148 call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length);
1149 } else if (id == C1StubId::new_object_array_id) {
1150 call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length);
1151 } else {
1152 assert(id == C1StubId::new_null_free_array_id, "must be");
1153 call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_null_free_array), klass, length);
1154 }
1155
1156 oop_maps = new OopMapSet();
1157 oop_maps->add_gc_map(call_offset, map);
1158 restore_live_registers_except_rax(sasm);
1159
1160 __ verify_oop(obj);
1161 __ leave();
1162 __ ret(0);
1163
1164 // rax,: new array
1165 }
1166 break;
1167
1168 case C1StubId::new_multi_array_id:
1169 { StubFrame f(sasm, "new_multi_array", dont_gc_arguments);
1170 // rax,: klass
1171 // rbx,: rank
1172 // rcx: address of 1st dimension
1173 OopMap* map = save_live_registers(sasm, 4);
1174 int call_offset = __ call_RT(rax, noreg, CAST_FROM_FN_PTR(address, new_multi_array), rax, rbx, rcx);
1175
1176 oop_maps = new OopMapSet();
1177 oop_maps->add_gc_map(call_offset, map);
1178 restore_live_registers_except_rax(sasm);
1179
1180 // rax,: new multi array
1181 __ verify_oop(rax);
1182 }
1183 break;
1184
1185 case C1StubId::load_flat_array_id:
1186 {
1187 StubFrame f(sasm, "load_flat_array", dont_gc_arguments);
1188 OopMap* map = save_live_registers(sasm, 3);
1189
1190 // Called with store_parameter and not C abi
1191
1192 f.load_argument(1, rax); // rax,: array
1193 f.load_argument(0, rbx); // rbx,: index
1194 int call_offset = __ call_RT(rax, noreg, CAST_FROM_FN_PTR(address, load_flat_array), rax, rbx);
1195
1196 oop_maps = new OopMapSet();
1197 oop_maps->add_gc_map(call_offset, map);
1198 restore_live_registers_except_rax(sasm);
1199
1200 // rax,: loaded element at array[index]
1201 __ verify_oop(rax);
1202 }
1203 break;
1204
1205 case C1StubId::store_flat_array_id:
1206 {
1207 StubFrame f(sasm, "store_flat_array", dont_gc_arguments);
1208 OopMap* map = save_live_registers(sasm, 4);
1209
1210 // Called with store_parameter and not C abi
1211
1212 f.load_argument(2, rax); // rax,: array
1213 f.load_argument(1, rbx); // rbx,: index
1214 f.load_argument(0, rcx); // rcx,: value
1215 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, store_flat_array), rax, rbx, rcx);
1216
1217 oop_maps = new OopMapSet();
1218 oop_maps->add_gc_map(call_offset, map);
1219 restore_live_registers_except_rax(sasm);
1220 }
1221 break;
1222
1223 case C1StubId::substitutability_check_id:
1224 {
1225 StubFrame f(sasm, "substitutability_check", dont_gc_arguments);
1226 OopMap* map = save_live_registers(sasm, 3);
1227
1228 // Called with store_parameter and not C abi
1229
1230 f.load_argument(1, rax); // rax,: left
1231 f.load_argument(0, rbx); // rbx,: right
1232 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, substitutability_check), rax, rbx);
1233
1234 oop_maps = new OopMapSet();
1235 oop_maps->add_gc_map(call_offset, map);
1236 restore_live_registers_except_rax(sasm);
1237
1238 // rax,: are the two operands substitutable
1239 }
1240 break;
1241
1242
1243 case C1StubId::buffer_inline_args_id:
1244 case C1StubId::buffer_inline_args_no_receiver_id:
1245 {
1246 const char* name = (id == C1StubId::buffer_inline_args_id) ?
1247 "buffer_inline_args" : "buffer_inline_args_no_receiver";
1248 StubFrame f(sasm, name, dont_gc_arguments);
1249 OopMap* map = save_live_registers(sasm, 2);
1250 Register method = rbx;
1251 address entry = (id == C1StubId::buffer_inline_args_id) ?
1252 CAST_FROM_FN_PTR(address, buffer_inline_args) :
1253 CAST_FROM_FN_PTR(address, buffer_inline_args_no_receiver);
1254 int call_offset = __ call_RT(rax, noreg, entry, method);
1255 oop_maps = new OopMapSet();
1256 oop_maps->add_gc_map(call_offset, map);
1257 restore_live_registers_except_rax(sasm);
1258 __ verify_oop(rax); // rax: an array of buffered value objects
1259 }
1260 break;
1261
1262 case C1StubId::register_finalizer_id:
1263 {
1264 __ set_info("register_finalizer", dont_gc_arguments);
1265
1266 // This is called via call_runtime so the arguments
1267 // will be place in C abi locations
1268
1269 #ifdef _LP64
1270 __ verify_oop(c_rarg0);
1271 __ mov(rax, c_rarg0);
1272 #else
1273 // The object is passed on the stack and we haven't pushed a
1274 // frame yet so it's one work away from top of stack.
1275 __ movptr(rax, Address(rsp, 1 * BytesPerWord));
1276 __ verify_oop(rax);
1277 #endif // _LP64
1278
1279 // load the klass and check the has finalizer flag
1280 Label register_finalizer;
1281 Register t = rsi;
1342 // activation and we are calling a leaf VM function only.
1343 generate_unwind_exception(sasm);
1344 }
1345 break;
1346
1347 case C1StubId::throw_array_store_exception_id:
1348 { StubFrame f(sasm, "throw_array_store_exception", dont_gc_arguments);
1349 // tos + 0: link
1350 // + 1: return address
1351 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true);
1352 }
1353 break;
1354
1355 case C1StubId::throw_class_cast_exception_id:
1356 { StubFrame f(sasm, "throw_class_cast_exception", dont_gc_arguments);
1357 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true);
1358 }
1359 break;
1360
1361 case C1StubId::throw_incompatible_class_change_error_id:
1362 { StubFrame f(sasm, "throw_incompatible_class_change_error", dont_gc_arguments);
1363 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false);
1364 }
1365 break;
1366
1367 case C1StubId::throw_illegal_monitor_state_exception_id:
1368 { StubFrame f(sasm, "throw_illegal_monitor_state_exception", dont_gc_arguments);
1369 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_illegal_monitor_state_exception), false);
1370 }
1371 break;
1372
1373 case C1StubId::throw_identity_exception_id:
1374 { StubFrame f(sasm, "throw_identity_exception", dont_gc_arguments);
1375 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_identity_exception), true);
1376 }
1377 break;
1378
1379 case C1StubId::slow_subtype_check_id:
1380 {
1381 // Typical calling sequence:
1382 // __ push(klass_RInfo); // object klass or other subclass
1383 // __ push(sup_k_RInfo); // array element klass or other superclass
1384 // __ call(slow_subtype_check);
1385 // Note that the subclass is pushed first, and is therefore deepest.
1386 // Previous versions of this code reversed the names 'sub' and 'super'.
1387 // This was operationally harmless but made the code unreadable.
1388 enum layout {
1389 rax_off, SLOT2(raxH_off)
1390 rcx_off, SLOT2(rcxH_off)
1391 rsi_off, SLOT2(rsiH_off)
1392 rdi_off, SLOT2(rdiH_off)
1393 // saved_rbp_off, SLOT2(saved_rbpH_off)
1394 return_off, SLOT2(returnH_off)
1395 sup_k_off, SLOT2(sup_kH_off)
1396 klass_off, SLOT2(superH_off)
1397 framesize,
1398 result_off = klass_off // deepest argument is also the return value
|