Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(234)

Side by Side Diff: src/a64/code-stubs-a64.cc

Issue 145773008: A64: Synchronize with r17104. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « include/v8config.h ('k') | src/a64/ic-a64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 static Register registers[] = { x0 }; 182 static Register registers[] = { x0 };
183 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); 183 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]);
184 descriptor->register_params_ = registers; 184 descriptor->register_params_ = registers;
185 descriptor->deoptimization_handler_ = 185 descriptor->deoptimization_handler_ =
186 FUNCTION_ADDR(CompareNilIC_Miss); 186 FUNCTION_ADDR(CompareNilIC_Miss);
187 descriptor->SetMissHandler( 187 descriptor->SetMissHandler(
188 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate)); 188 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate));
189 } 189 }
190 190
191 191
192 void BinaryOpStub::InitializeInterfaceDescriptor(
193 Isolate* isolate,
194 CodeStubInterfaceDescriptor* descriptor) {
195 // x1: left operand
196 // x0: right operand
197 static Register registers[] = { x1, x0 };
198 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]);
199 descriptor->register_params_ = registers;
200 descriptor->deoptimization_handler_ = FUNCTION_ADDR(BinaryOpIC_Miss);
201 descriptor->SetMissHandler(
202 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate));
203 }
204
205
192 static void InitializeArrayConstructorDescriptor( 206 static void InitializeArrayConstructorDescriptor(
193 Isolate* isolate, 207 Isolate* isolate,
194 CodeStubInterfaceDescriptor* descriptor, 208 CodeStubInterfaceDescriptor* descriptor,
195 int constant_stack_parameter_count) { 209 int constant_stack_parameter_count) {
196 // x1: function 210 // x1: function
197 // x2: type info cell with elements kind 211 // x2: type info cell with elements kind
198 static Register registers[] = { x1, x2 }; 212 static Register registers[] = { x1, x2 };
199 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); 213 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]);
200 if (constant_stack_parameter_count != 0) { 214 if (constant_stack_parameter_count != 0) {
201 // stack param count needs (constructor pointer, and single argument) 215 // stack param count needs (constructor pointer, and single argument)
(...skipping 750 matching lines...) Expand 10 before | Expand all | Expand 10 after
952 966
953 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( 967 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(
954 Isolate* isolate) { 968 Isolate* isolate) {
955 StoreBufferOverflowStub stub1(kDontSaveFPRegs); 969 StoreBufferOverflowStub stub1(kDontSaveFPRegs);
956 stub1.GetCode(isolate)->set_is_pregenerated(true); 970 stub1.GetCode(isolate)->set_is_pregenerated(true);
957 StoreBufferOverflowStub stub2(kSaveFPRegs); 971 StoreBufferOverflowStub stub2(kSaveFPRegs);
958 stub2.GetCode(isolate)->set_is_pregenerated(true); 972 stub2.GetCode(isolate)->set_is_pregenerated(true);
959 } 973 }
960 974
961 975
962 void BinaryOpStub::Initialize() {
963 // Nothing to do here.
964 }
965
966
967 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
968 ASM_LOCATION("BinaryOpStub::GenerateTypeTransition");
969 Label get_result;
970
971 __ Mov(x12, Operand(Smi::FromInt(MinorKey())));
972 __ Push(x1, x0, x12);
973
974 __ TailCallExternalReference(
975 ExternalReference(IC_Utility(IC::kBinaryOp_Patch), masm->isolate()),
976 3,
977 1);
978 }
979
980
981 void BinaryOpStub::GenerateTypeTransitionWithSavedArgs(
982 MacroAssembler* masm) {
983 UNIMPLEMENTED();
984 }
985
986
987 void BinaryOpStub_GenerateSmiSmiOperation(MacroAssembler* masm,
988 Token::Value op) {
989 ASM_LOCATION("BinaryOpStub_GenerateSmiSmiOperation");
990 Register left = x1;
991 Register right = x0;
992 Register scratch1 = x10;
993 Register scratch2 = x11;
994 // Note that 'result' aliases 'right'. The code below must care not to
995 // overwrite 'right' before it is certain it won't be needed.
996 Register result = x0;
997
998 // Adapt the code below if that does not hold.
999 STATIC_ASSERT(kSmiTag == 0);
1000 STATIC_ASSERT(kSmiShift == 32);
1001
1002 // TODO(alexandre): The code below mostly uses 64-bits operations, knowing
1003 // that the input are Smis.
1004 // Use of 32-bits instructions should be investigated. For example maybe speed
1005 // or power consumption could be improved.
1006
1007 Label overflow, not_smi_result;
1008 switch (op) {
1009 case Token::ADD:
1010 __ Adds(result, left, right); // Add optimistically.
1011 __ B(vs, &overflow);
1012 __ Ret();
1013 __ Bind(&overflow);
1014 // Revert optimistic add.
1015 __ Sub(right, result, left);
1016 break;
1017
1018 case Token::SUB:
1019 // Subtract optimistically.
1020 __ Subs(result, left, right);
1021 __ B(vs, &overflow);
1022 __ Ret();
1023 __ Bind(&overflow);
1024 // Revert optimistic subtract.
1025 __ Sub(right, left, result);
1026 break;
1027
1028 case Token::MUL: {
1029 Label not_minus_zero;
1030
1031 // Use smulh to avoid shifting right the inputs.
1032 // scratch1 = bits<127:64> of left * right.
1033 __ Smulh(scratch1, left, right);
1034
1035 // Check if the result is a Smi.
1036 __ Cbnz(scratch1, &not_minus_zero);
1037
1038 // Check for minus zero.
1039 // Exclusive or the arguments and check the sign bit of the result.
1040 __ Eor(scratch2, left, right);
1041 __ Tbnz(scratch2, kXSignBit, &not_smi_result);
1042
1043 // At this point, the result is zero, which needs no smi conversion.
1044 STATIC_ASSERT(kSmiTag == 0);
1045 __ Mov(result, scratch1);
1046 __ Ret();
1047
1048 __ Bind(&not_minus_zero);
1049 // Check if the result is a signed 32 bits.
1050 // It is if bits 63-31 are sign bits.
1051 __ Cls(scratch2, scratch1);
1052 __ Cmp(scratch2, kXRegSize - kSmiShift);
1053 __ B(lt, &not_smi_result);
1054
1055 // Tag the result.
1056 __ SmiTag(result, scratch1);
1057 __ Ret();
1058 break;
1059 }
1060
1061 case Token::DIV: {
1062 // Check for division by zero.
1063 __ Cbz(right, &not_smi_result);
1064 // Try integer division.
1065 // If the remainder is not zero jump the result is not a Smi.
1066 __ Sdiv(scratch1, left, right);
1067 // scratch2 = quotient * right.
1068 __ Mul(scratch2, scratch1, right);
1069 __ Cmp(scratch2, left);
1070 __ B(ne, &not_smi_result);
1071 // Check for -0 (result is zero and right is negative).
1072 Label not_minus_zero;
1073 __ Cbnz(scratch1, &not_minus_zero);
1074 __ Tbnz(right, kXSignBit, &not_smi_result);
1075 __ Bind(&not_minus_zero);
1076 // Check for minus_int / -1.
1077 __ Eor(scratch2, scratch1, 1L << 31);
1078 __ Cbz(scratch2, &not_smi_result);
1079 // Tag the result and return.
1080 __ SmiTag(result, scratch1);
1081 __ Ret();
1082 break;
1083 }
1084
1085 case Token::MOD: {
1086 Label not_minus_zero;
1087 // Check for division by zero.
1088 __ Cbz(right, &not_smi_result);
1089 // Compute:
1090 // modulo = left - quotient * right
1091 __ Sdiv(scratch1, left, right);
1092 __ Msub(scratch1, scratch1, right, left);
1093 __ Cbnz(scratch1, &not_minus_zero);
1094 // Check if the result should be minus zero.
1095 __ Tbnz(left, kXSignBit, &not_smi_result);
1096 __ Bind(&not_minus_zero);
1097 __ Mov(result, scratch1);
1098 __ Ret();
1099 break;
1100 }
1101
1102 case Token::BIT_OR:
1103 __ Orr(result, left, right);
1104 __ Ret();
1105 break;
1106
1107 case Token::BIT_AND:
1108 __ And(result, left, right);
1109 __ Ret();
1110 break;
1111
1112 case Token::BIT_XOR:
1113 __ Eor(result, left, right);
1114 __ Ret();
1115 break;
1116
1117 // For shift operations, only the 5 least significant bits of the rhs
1118 // are used (see ECMA-262 11.7.1 and following).
1119 // We would like to use the implicit masking operation performed by the
1120 // shift instructions, but that would require using W registers and thus
1121 // untagging.
1122 case Token::SAR:
1123 __ Ubfx(right, right, kSmiShift, 5);
1124 __ Asr(result, left, right);
1125 __ Bic(result, result, kSmiShiftMask);
1126 __ Ret();
1127 break;
1128
1129 case Token::SHR: {
1130 __ Ubfx(scratch1, right, kSmiShift, 5);
1131 // SHR must not yield a negative value. This can only happen if left is
1132 // negative and we shift right by zero.
1133 Label right_not_zero;
1134 __ Cbnz(scratch1, &right_not_zero);
1135 __ Tbnz(left, kXSignBit, &not_smi_result);
1136 __ Bind(&right_not_zero);
1137 __ Lsr(result, left, scratch1);
1138 __ Bic(result, result, kSmiShiftMask);
1139 __ Ret();
1140 break;
1141 }
1142
1143 case Token::SHL:
1144 __ Ubfx(scratch1, right, kSmiShift, 5);
1145 __ Lsl(result, left, scratch1);
1146 __ Ret();
1147 break;
1148
1149 default:
1150 UNREACHABLE();
1151 }
1152
1153 __ Bind(&not_smi_result);
1154 }
1155
1156
1157 void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm,
1158 Register result,
1159 Register heap_number_map,
1160 Register scratch1,
1161 Register scratch2,
1162 Label* gc_required,
1163 OverwriteMode mode);
1164
1165
1166 void BinaryOpStub_GenerateFPOperation(MacroAssembler* masm,
1167 BinaryOpIC::TypeInfo left_type,
1168 BinaryOpIC::TypeInfo right_type,
1169 bool smi_operands,
1170 Label* not_numbers,
1171 Label* gc_required,
1172 Label* miss,
1173 Token::Value op,
1174 OverwriteMode mode) {
1175 ASM_LOCATION("BinaryOpStub_GenerateFPOperation");
1176
1177 Register result = x0;
1178 FPRegister result_d = d0;
1179 Register right = x0;
1180 Register left = x1;
1181 Register heap_result = x21;
1182
1183 ASSERT(smi_operands || (not_numbers != NULL));
1184 if (smi_operands) {
1185 __ AssertSmi(left);
1186 __ AssertSmi(right);
1187 }
1188 if (left_type == BinaryOpIC::SMI) {
1189 __ JumpIfNotSmi(left, miss);
1190 }
1191 if (right_type == BinaryOpIC::SMI) {
1192 __ JumpIfNotSmi(right, miss);
1193 }
1194
1195 Register heap_number_map = x2;
1196 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
1197
1198 switch (op) {
1199 case Token::ADD:
1200 case Token::SUB:
1201 case Token::MUL:
1202 case Token::DIV:
1203 case Token::MOD: {
1204 FPRegister left_d = d0;
1205 FPRegister right_d = d1;
1206 Label do_operation;
1207
1208 __ SmiUntagToDouble(left_d, left, kSpeculativeUntag);
1209 __ SmiUntagToDouble(right_d, right, kSpeculativeUntag);
1210
1211 if (!smi_operands) {
1212 if (left_type != BinaryOpIC::SMI) {
1213 Label left_done;
1214 Label* left_not_heap =
1215 (left_type == BinaryOpIC::NUMBER) ? miss : not_numbers;
1216 __ JumpIfSmi(left, &left_done);
1217
1218 // Left not smi: load if heap number.
1219 __ JumpIfNotHeapNumber(left, left_not_heap, heap_number_map);
1220 __ Ldr(left_d, FieldMemOperand(left, HeapNumber::kValueOffset));
1221 __ Bind(&left_done);
1222 }
1223
1224 if (right_type != BinaryOpIC::SMI) {
1225 Label* right_not_heap =
1226 (right_type == BinaryOpIC::NUMBER) ? miss : not_numbers;
1227 __ JumpIfSmi(right, &do_operation);
1228
1229 // Right not smi: load if heap number.
1230 __ JumpIfNotHeapNumber(right, right_not_heap, heap_number_map);
1231 __ Ldr(right_d, FieldMemOperand(right, HeapNumber::kValueOffset));
1232 }
1233 }
1234
1235 // Left and right are doubles in left_d and right_d. Calculate the result.
1236 __ Bind(&do_operation);
1237
1238 BinaryOpStub_GenerateHeapResultAllocation(
1239 masm, heap_result, heap_number_map, x10, x11, gc_required, mode);
1240
1241 switch (op) {
1242 case Token::ADD: __ Fadd(result_d, left_d, right_d); break;
1243 case Token::SUB: __ Fsub(result_d, left_d, right_d); break;
1244 case Token::MUL: __ Fmul(result_d, left_d, right_d); break;
1245 case Token::DIV: __ Fdiv(result_d, left_d, right_d); break;
1246 case Token::MOD: {
1247 Register saved_lr = x20;
1248 __ Mov(saved_lr, lr);
1249 AllowExternalCallThatCantCauseGC scope(masm);
1250 __ CallCFunction(
1251 ExternalReference::double_fp_operation(op, masm->isolate()),
1252 0, 2);
1253 __ Mov(lr, saved_lr);
1254 break;
1255 }
1256 default: UNREACHABLE();
1257 }
1258
1259 __ Str(result_d, FieldMemOperand(heap_result, HeapNumber::kValueOffset));
1260 __ Mov(result, heap_result);
1261 __ Ret();
1262 break;
1263 }
1264
1265 case Token::BIT_OR:
1266 case Token::BIT_XOR:
1267 case Token::BIT_AND:
1268 case Token::SAR:
1269 case Token::SHR:
1270 case Token::SHL: {
1271 Label do_operation, result_not_smi;
1272
1273 if (!smi_operands) {
1274 Label left_is_smi;
1275 // Convert heap number operands to smis.
1276 if (left_type != BinaryOpIC::SMI) {
1277 __ JumpIfSmi(left, &left_is_smi);
1278 __ JumpIfNotHeapNumber(left, not_numbers, heap_number_map);
1279 __ HeapNumberECMA262ToInt32(left, left, x10, x11, d0,
1280 MacroAssembler::SMI);
1281 }
1282 __ Bind(&left_is_smi);
1283 if (right_type != BinaryOpIC::SMI) {
1284 __ JumpIfSmi(right, &do_operation);
1285 __ JumpIfNotHeapNumber(right, not_numbers, heap_number_map);
1286 __ HeapNumberECMA262ToInt32(right, right, x10, x11, d0,
1287 MacroAssembler::SMI);
1288 }
1289 }
1290
1291 // Left and right are smis. Calculate the result.
1292 __ Bind(&do_operation);
1293 switch (op) {
1294 case Token::BIT_OR: __ Orr(result, left, right); break;
1295 case Token::BIT_XOR: __ Eor(result, left, right); break;
1296 case Token::BIT_AND: __ And(result, left, right); break;
1297
1298 // For shift operations, only the 5 least significant bits of the rhs
1299 // are used (see ECMA-262 11.7.1 and following).
1300 // We would like to use the implicit masking operation performed by the
1301 // shift instructions, but that would require using W registers and thus
1302 // untagging.
1303 case Token::SAR:
1304 __ Ubfx(right, right, kSmiShift, 5);
1305 __ Asr(result, left, right);
1306 // Clear bits shifted right.
1307 __ Bic(result, result, kSmiShiftMask);
1308 break;
1309 case Token::SHL:
1310 __ Ubfx(right, right, kSmiShift, 5);
1311 __ Lsl(result, left, right);
1312 break;
1313 case Token::SHR: {
1314 Label ok;
1315 // SHR must always yield a positive result.
1316 // This is a problem if right is zero and left is negative.
1317 __ Ubfx(right, right, kSmiShift, 5);
1318 __ Cbnz(right, &ok);
1319 __ Cmp(left, 0);
1320 __ B(mi, &result_not_smi);
1321 __ Bind(&ok);
1322 __ Lsr(result, left, right);
1323 // Clear bits shifted right.
1324 __ Bic(result, result, kSmiShiftMask);
1325 break;
1326 }
1327 default: UNREACHABLE();
1328 }
1329 __ Ret();
1330
1331 __ Bind(&result_not_smi);
1332 // We know the operation was shift right, the left operand is negative,
1333 // and the right is zero. The result will be the left operand cast to a
1334 // positive value, as a heap number.
1335 __ Ucvtf(result_d, left, kSmiShift);
1336 if (smi_operands) {
1337 __ AllocateHeapNumber(heap_result, gc_required, x10, x11,
1338 heap_number_map);
1339 } else {
1340 BinaryOpStub_GenerateHeapResultAllocation(masm, heap_result,
1341 heap_number_map, x10, x11,
1342 gc_required, mode);
1343 }
1344
1345 // Nothing can go wrong now, so move the heap number to the result
1346 // register.
1347 __ Mov(result, heap_result);
1348
1349 // Now store the double result into the allocated heap number, and return.
1350 __ Str(result_d, FieldMemOperand(result, HeapNumber::kValueOffset));
1351 __ Ret();
1352 break;
1353 }
1354 default:
1355 UNREACHABLE();
1356 }
1357 }
1358
1359
1360 // Generate the smi code. If the operation on smis are successful this return is
1361 // generated. If the result is not a smi and heap number allocation is not
1362 // requested the code falls through. If number allocation is requested but a
1363 // heap number cannot be allocated the code jumps to the label gc_required.
1364 void BinaryOpStub_GenerateSmiCode(
1365 MacroAssembler* masm,
1366 Label* use_runtime,
1367 Label* gc_required,
1368 Token::Value op,
1369 BinaryOpStub::SmiCodeGenerateHeapNumberResults allow_heapnumber_results,
1370 OverwriteMode mode) {
1371 ASM_LOCATION("BinaryOpStub_GenerateSmiCode");
1372 Label not_smis;
1373
1374 Register left = x1;
1375 Register right = x0;
1376
1377 // Perform combined smi check on both operands.
1378 __ JumpIfEitherNotSmi(left, right, &not_smis);
1379
1380 // If the smi-smi operation results in a smi, the result is returned from the
1381 // code generated for the operation. Otherwise, execution falls through to
1382 // the following code.
1383 BinaryOpStub_GenerateSmiSmiOperation(masm, op);
1384
1385 // If heap number results are allowed, generate the result in an allocated
1386 // heap number.
1387 if (allow_heapnumber_results == BinaryOpStub::ALLOW_HEAPNUMBER_RESULTS) {
1388 BinaryOpStub_GenerateFPOperation(masm, BinaryOpIC::UNINITIALIZED,
1389 BinaryOpIC::UNINITIALIZED, true,
1390 use_runtime, gc_required, &not_smis, op,
1391 mode);
1392 }
1393
1394 __ Bind(&not_smis);
1395 }
1396
1397
1398 void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
1399 ASM_LOCATION("BinaryOpStub::GenerateSmiStub");
1400 Label right_arg_changed, call_runtime;
1401
1402 if ((op_ == Token::MOD) && encoded_right_arg_.has_value) {
1403 // It is guaranteed that the value will fit into a Smi, because if it
1404 // didn't, we wouldn't be here, see BinaryOp_Patch.
1405 __ CompareAndBranch(x0, Operand(Smi::FromInt(fixed_right_arg_value())), ne,
1406 &right_arg_changed);
1407 }
1408
1409 #ifdef DEBUG
1410 Register saved_left = x18;
1411 Register saved_right = x19;
1412 if (masm->emit_debug_code()) {
1413 __ Mov(saved_left, x1);
1414 __ Mov(saved_right, x0);
1415 }
1416 #endif
1417
1418 if (result_type_ == BinaryOpIC::UNINITIALIZED ||
1419 result_type_ == BinaryOpIC::SMI) {
1420 // Only allow smi results. No allocation should take place, so we don't need
1421 // a label for gc.
1422 BinaryOpStub_GenerateSmiCode(masm, &call_runtime, NULL, op_,
1423 NO_HEAPNUMBER_RESULTS, mode_);
1424 } else {
1425 // Allow heap number result and don't make a transition if a heap number
1426 // cannot be allocated.
1427 BinaryOpStub_GenerateSmiCode(masm, &call_runtime, &call_runtime, op_,
1428 ALLOW_HEAPNUMBER_RESULTS, mode_);
1429 }
1430
1431 // Code falls through if the result is not returned as either a smi or heap
1432 // number.
1433 __ Bind(&right_arg_changed);
1434 GenerateTypeTransition(masm);
1435
1436 __ Bind(&call_runtime);
1437 #ifdef DEBUG
1438 if (masm->emit_debug_code()) {
1439 __ Cmp(saved_left, x1);
1440 __ Assert(eq, kLhsHasBeenClobbered);
1441 __ Cmp(saved_right, x0);
1442 __ Assert(eq, kRhsHasBeenClobbered);
1443 }
1444 #endif
1445 {
1446 FrameScope scope(masm, StackFrame::INTERNAL);
1447 GenerateRegisterArgsPush(masm);
1448 GenerateCallRuntime(masm);
1449 }
1450 __ Ret();
1451 }
1452
1453
1454 void BinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
1455 ASM_LOCATION("BinaryOpStub::GenerateBothStringStub");
1456 ASSERT((left_type_ == BinaryOpIC::STRING) &&
1457 (right_type_ == BinaryOpIC::STRING));
1458 ASSERT(op_ == Token::ADD);
1459 Label call_transition;
1460
1461 // If both arguments are strings, call the string add stub. Otherwise, do a
1462 // transition.
1463
1464 Register left = x1;
1465 Register right = x0;
1466
1467 // Test if left operand is a smi or string.
1468 __ JumpIfSmi(left, &call_transition);
1469 __ JumpIfObjectType(left, x2, x2, FIRST_NONSTRING_TYPE, &call_transition, ge);
1470
1471 // Test if right operand is a smi or string.
1472 __ JumpIfSmi(right, &call_transition);
1473 __ JumpIfObjectType(right, x2, x2, FIRST_NONSTRING_TYPE, &call_transition,
1474 ge);
1475
1476 StringAddStub string_add_stub(
1477 static_cast<StringAddFlags>(STRING_ADD_CHECK_NONE |
1478 STRING_ADD_ERECT_FRAME));
1479 GenerateRegisterArgsPush(masm);
1480 __ TailCallStub(&string_add_stub);
1481
1482 __ Bind(&call_transition);
1483 GenerateTypeTransition(masm);
1484 }
1485
1486
1487 void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
1488 // On a64 the smis are 32 bits, so we should never see the INT32 type.
1489 UNREACHABLE();
1490 }
1491
1492
1493 void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
1494 ASM_LOCATION("BinaryOpStub::GenerateOddballStub");
1495 Register right = x0;
1496 Register left = x1;
1497
1498 if (op_ == Token::ADD) {
1499 // Handle string addition here, because it is the only operation that does
1500 // not do a ToNumber conversion on the operands.
1501 GenerateAddStrings(masm);
1502 }
1503
1504 // Convert oddball arguments to numbers.
1505 Label check, done;
1506 __ JumpIfNotRoot(left, Heap::kUndefinedValueRootIndex, &check);
1507 if (Token::IsBitOp(op_)) {
1508 __ Mov(left, 0);
1509 } else {
1510 __ LoadRoot(left, Heap::kNanValueRootIndex);
1511 }
1512 __ B(&done);
1513
1514 __ Bind(&check);
1515 __ JumpIfNotRoot(right, Heap::kUndefinedValueRootIndex, &done);
1516 if (Token::IsBitOp(op_)) {
1517 __ Mov(right, 0);
1518 } else {
1519 __ LoadRoot(right, Heap::kNanValueRootIndex);
1520 }
1521
1522 __ Bind(&done);
1523
1524 GenerateNumberStub(masm);
1525 }
1526
1527
1528 void BinaryOpStub::GenerateNumberStub(MacroAssembler* masm) {
1529 ASM_LOCATION("BinaryOpStub::GenerateNumberStub");
1530 Label call_runtime, transition;
1531
1532 BinaryOpStub_GenerateFPOperation(masm, left_type_, right_type_, false,
1533 &transition, &call_runtime, &transition,
1534 op_, mode_);
1535
1536 __ Bind(&transition);
1537 GenerateTypeTransition(masm);
1538
1539 __ Bind(&call_runtime);
1540 {
1541 FrameScope scope(masm, StackFrame::INTERNAL);
1542 GenerateRegisterArgsPush(masm);
1543 GenerateCallRuntime(masm);
1544 }
1545 __ Ret();
1546 }
1547
1548
1549 void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
1550 ASM_LOCATION("BinaryOpStub::GenerateGeneric");
1551 Label call_runtime, call_string_add_or_runtime, transition;
1552
1553 BinaryOpStub_GenerateSmiCode(masm, &call_runtime, &call_runtime, op_,
1554 ALLOW_HEAPNUMBER_RESULTS, mode_);
1555
1556 BinaryOpStub_GenerateFPOperation(masm, left_type_, right_type_, false,
1557 &call_string_add_or_runtime, &call_runtime,
1558 &transition, op_, mode_);
1559
1560 __ Bind(&transition);
1561 GenerateTypeTransition(masm);
1562
1563 __ Bind(&call_string_add_or_runtime);
1564 if (op_ == Token::ADD) {
1565 GenerateAddStrings(masm);
1566 }
1567
1568 __ Bind(&call_runtime);
1569 {
1570 FrameScope scope(masm, StackFrame::INTERNAL);
1571 GenerateRegisterArgsPush(masm);
1572 GenerateCallRuntime(masm);
1573 }
1574 __ Ret();
1575 }
1576
1577
1578 void BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
1579 ASM_LOCATION("BinaryOpStub::GenerateAddStrings");
1580 ASSERT(op_ == Token::ADD);
1581 Label left_not_string, call_runtime;
1582
1583 Register left = x1;
1584 Register right = x0;
1585
1586 // Check if left argument is a string.
1587 __ JumpIfSmi(left, &left_not_string);
1588 __ JumpIfObjectType(left, x2, x2, FIRST_NONSTRING_TYPE, &left_not_string, ge);
1589
1590 StringAddStub string_add_left_stub(
1591 static_cast<StringAddFlags>(STRING_ADD_CHECK_RIGHT |
1592 STRING_ADD_ERECT_FRAME));
1593 GenerateRegisterArgsPush(masm);
1594 __ TailCallStub(&string_add_left_stub);
1595
1596 // Left operand is not a string, test right.
1597 __ Bind(&left_not_string);
1598 __ JumpIfSmi(right, &call_runtime);
1599 __ JumpIfObjectType(right, x2, x2, FIRST_NONSTRING_TYPE, &call_runtime, ge);
1600
1601 StringAddStub string_add_right_stub(
1602 static_cast<StringAddFlags>(STRING_ADD_CHECK_LEFT |
1603 STRING_ADD_ERECT_FRAME));
1604 GenerateRegisterArgsPush(masm);
1605 __ TailCallStub(&string_add_right_stub);
1606
1607 // Neither argument is a string.
1608 __ Bind(&call_runtime);
1609 }
1610
1611
1612 void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm,
1613 Register result,
1614 Register heap_number_map,
1615 Register scratch1,
1616 Register scratch2,
1617 Label* gc_required,
1618 OverwriteMode mode) {
1619 ASM_LOCATION("BinaryOpStub::GenerateHeapResultAllocation");
1620 ASSERT(!AreAliased(result, heap_number_map, scratch1, scratch2));
1621
1622 if ((mode == OVERWRITE_LEFT) || (mode == OVERWRITE_RIGHT)) {
1623 Label skip_allocation, allocated;
1624 Register overwritable_operand = (mode == OVERWRITE_LEFT) ? x1 : x0;
1625 if (masm->emit_debug_code()) {
1626 // Check that the overwritable operand is a Smi or a HeapNumber.
1627 Label ok;
1628 __ JumpIfSmi(overwritable_operand, &ok);
1629 __ JumpIfHeapNumber(overwritable_operand, &ok);
1630 __ Abort(kExpectedSmiOrHeapNumber);
1631 __ Bind(&ok);
1632 }
1633 // If the overwritable operand is already a HeapNumber, we can skip
1634 // allocation of a heap number.
1635 __ JumpIfNotSmi(overwritable_operand, &skip_allocation);
1636 // Allocate a heap number for the result.
1637 __ AllocateHeapNumber(result, gc_required, scratch1, scratch2,
1638 heap_number_map);
1639 __ B(&allocated);
1640 __ Bind(&skip_allocation);
1641 // Use object holding the overwritable operand for result.
1642 __ Mov(result, overwritable_operand);
1643 __ Bind(&allocated);
1644 } else {
1645 ASSERT(mode == NO_OVERWRITE);
1646 __ AllocateHeapNumber(result, gc_required, scratch1, scratch2,
1647 heap_number_map);
1648 }
1649 }
1650
1651
1652 void BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
1653 __ Push(x1, x0);
1654 }
1655
1656
1657 void TranscendentalCacheStub::Generate(MacroAssembler* masm) { 976 void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
1658 // Untagged case: 977 // Untagged case:
1659 // Input: double in d0 978 // Input: double in d0
1660 // Result: double in d0 979 // Result: double in d0
1661 // 980 //
1662 // Tagged case: 981 // Tagged case:
1663 // Input: tagged value in jssp[0] 982 // Input: tagged value in jssp[0]
1664 // Result: tagged value in x0 983 // Result: tagged value in x0
1665 984
1666 const bool tagged = (argument_type_ == TAGGED); 985 const bool tagged = (argument_type_ == TAGGED);
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after
2134 // It is important that the following stubs are generated in this order 1453 // It is important that the following stubs are generated in this order
2135 // because pregenerated stubs can only call other pregenerated stubs. 1454 // because pregenerated stubs can only call other pregenerated stubs.
2136 // RecordWriteStub uses StoreBufferOverflowStub, which in turn uses 1455 // RecordWriteStub uses StoreBufferOverflowStub, which in turn uses
2137 // CEntryStub. 1456 // CEntryStub.
2138 CEntryStub::GenerateAheadOfTime(isolate); 1457 CEntryStub::GenerateAheadOfTime(isolate);
2139 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 1458 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
2140 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 1459 StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
2141 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); 1460 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate);
2142 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); 1461 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
2143 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); 1462 CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
1463 BinaryOpStub::GenerateAheadOfTime(isolate);
2144 } 1464 }
2145 1465
2146 1466
2147 void CodeStub::GenerateFPStubs(Isolate* isolate) { 1467 void CodeStub::GenerateFPStubs(Isolate* isolate) {
2148 // Floating-point code doesn't get special handling in A64, so there's 1468 // Floating-point code doesn't get special handling in A64, so there's
2149 // nothing to do here. 1469 // nothing to do here.
2150 USE(isolate); 1470 USE(isolate);
2151 } 1471 }
2152 1472
2153 1473
(...skipping 4695 matching lines...) Expand 10 before | Expand all | Expand 10 after
6849 __ Bind(&fast_elements_case); 6169 __ Bind(&fast_elements_case);
6850 GenerateCase(masm, FAST_ELEMENTS); 6170 GenerateCase(masm, FAST_ELEMENTS);
6851 } 6171 }
6852 6172
6853 6173
6854 #undef __ 6174 #undef __
6855 6175
6856 } } // namespace v8::internal 6176 } } // namespace v8::internal
6857 6177
6858 #endif // V8_TARGET_ARCH_A64 6178 #endif // V8_TARGET_ARCH_A64
OLDNEW
« no previous file with comments | « include/v8config.h ('k') | src/a64/ic-a64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698