| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 623 HInstruction* hinstr, | 623 HInstruction* hinstr, |
| 624 CanDeoptimize can_deoptimize) { | 624 CanDeoptimize can_deoptimize) { |
| 625 info()->MarkAsNonDeferredCalling(); | 625 info()->MarkAsNonDeferredCalling(); |
| 626 | 626 |
| 627 #ifdef DEBUG | 627 #ifdef DEBUG |
| 628 instr->VerifyCall(); | 628 instr->VerifyCall(); |
| 629 #endif | 629 #endif |
| 630 instr->MarkAsCall(); | 630 instr->MarkAsCall(); |
| 631 instr = AssignPointerMap(instr); | 631 instr = AssignPointerMap(instr); |
| 632 | 632 |
| 633 if (hinstr->HasObservableSideEffects()) { | |
| 634 ASSERT(hinstr->next()->IsSimulate()); | |
| 635 HSimulate* sim = HSimulate::cast(hinstr->next()); | |
| 636 ASSERT(instruction_pending_deoptimization_environment_ == NULL); | |
| 637 ASSERT(pending_deoptimization_ast_id_.IsNone()); | |
| 638 instruction_pending_deoptimization_environment_ = instr; | |
| 639 pending_deoptimization_ast_id_ = sim->ast_id(); | |
| 640 } | |
| 641 | |
| 642 // If instruction does not have side-effects lazy deoptimization | 633 // If instruction does not have side-effects lazy deoptimization |
| 643 // after the call will try to deoptimize to the point before the call. | 634 // after the call will try to deoptimize to the point before the call. |
| 644 // Thus we still need to attach environment to this call even if | 635 // Thus we still need to attach environment to this call even if |
| 645 // call sequence can not deoptimize eagerly. | 636 // call sequence can not deoptimize eagerly. |
| 646 bool needs_environment = | 637 bool needs_environment = |
| 647 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || | 638 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || |
| 648 !hinstr->HasObservableSideEffects(); | 639 !hinstr->HasObservableSideEffects(); |
| 649 if (needs_environment && !instr->HasEnvironment()) { | 640 if (needs_environment && !instr->HasEnvironment()) { |
| 650 instr = AssignEnvironment(instr); | 641 instr = AssignEnvironment(instr); |
| 651 } | 642 } |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 909 } | 900 } |
| 910 #endif | 901 #endif |
| 911 | 902 |
| 912 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { | 903 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { |
| 913 instr = AssignPointerMap(instr); | 904 instr = AssignPointerMap(instr); |
| 914 } | 905 } |
| 915 if (FLAG_stress_environments && !instr->HasEnvironment()) { | 906 if (FLAG_stress_environments && !instr->HasEnvironment()) { |
| 916 instr = AssignEnvironment(instr); | 907 instr = AssignEnvironment(instr); |
| 917 } | 908 } |
| 918 chunk_->AddInstruction(instr, current_block_); | 909 chunk_->AddInstruction(instr, current_block_); |
| 910 |
| 911 if (instr->IsCall()) { |
| 912 HValue* hydrogen_value_for_lazy_bailout = current; |
| 913 LInstruction* instruction_needing_environment = NULL; |
| 914 if (current->HasObservableSideEffects()) { |
| 915 HSimulate* sim = HSimulate::cast(current->next()); |
| 916 instruction_needing_environment = instr; |
| 917 sim->ReplayEnvironment(current_block_->last_environment()); |
| 918 hydrogen_value_for_lazy_bailout = sim; |
| 919 } |
| 920 LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout()); |
| 921 bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout); |
| 922 chunk_->AddInstruction(bailout, current_block_); |
| 923 if (instruction_needing_environment != NULL) { |
| 924 // Store the lazy deopt environment with the instruction if needed. |
| 925 // Right now it is only used for LInstanceOfKnownGlobal. |
| 926 instruction_needing_environment-> |
| 927 SetDeferredLazyDeoptimizationEnvironment(bailout->environment()); |
| 928 } |
| 929 } |
| 919 } | 930 } |
| 920 current_instruction_ = old_current; | 931 current_instruction_ = old_current; |
| 921 } | 932 } |
| 922 | 933 |
| 923 | 934 |
| 924 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { | 935 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { |
| 925 return new(zone()) LGoto(instr->FirstSuccessor()); | 936 return new(zone()) LGoto(instr->FirstSuccessor()); |
| 926 } | 937 } |
| 927 | 938 |
| 928 | 939 |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1115 | 1126 |
| 1116 | 1127 |
| 1117 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) { | 1128 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) { |
| 1118 LOperand* input = UseRegisterAtStart(instr->value()); | 1129 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1119 LMathFloor* result = new(zone()) LMathFloor(input); | 1130 LMathFloor* result = new(zone()) LMathFloor(input); |
| 1120 return AssignEnvironment(DefineAsRegister(result)); | 1131 return AssignEnvironment(DefineAsRegister(result)); |
| 1121 } | 1132 } |
| 1122 | 1133 |
| 1123 | 1134 |
| 1124 LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) { | 1135 LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) { |
| 1125 LOperand* input = UseRegisterAtStart(instr->value()); | 1136 LOperand* input = UseRegister(instr->value()); |
| 1126 LMathRound* result = new(zone()) LMathRound(input); | 1137 LOperand* temp = FixedTemp(xmm4); |
| 1138 LMathRound* result = new(zone()) LMathRound(input, temp); |
| 1127 return AssignEnvironment(DefineAsRegister(result)); | 1139 return AssignEnvironment(DefineAsRegister(result)); |
| 1128 } | 1140 } |
| 1129 | 1141 |
| 1130 | 1142 |
| 1131 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) { | 1143 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) { |
| 1132 LOperand* context = UseAny(instr->context()); | 1144 LOperand* context = UseAny(instr->context()); |
| 1133 LOperand* input = UseRegisterAtStart(instr->value()); | 1145 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1134 LMathAbs* result = new(zone()) LMathAbs(context, input); | 1146 LMathAbs* result = new(zone()) LMathAbs(context, input); |
| 1135 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); | 1147 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); |
| 1136 } | 1148 } |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1235 | 1247 |
| 1236 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1248 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1237 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1249 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
| 1238 return DefineSameAsFirst(new(zone()) LBitI(left, right)); | 1250 return DefineSameAsFirst(new(zone()) LBitI(left, right)); |
| 1239 } else { | 1251 } else { |
| 1240 return DoArithmeticT(instr->op(), instr); | 1252 return DoArithmeticT(instr->op(), instr); |
| 1241 } | 1253 } |
| 1242 } | 1254 } |
| 1243 | 1255 |
| 1244 | 1256 |
| 1257 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) { |
| 1258 ASSERT(instr->representation().IsSmiOrInteger32()); |
| 1259 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1260 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1261 LOperand* dividend = UseRegister(instr->left()); |
| 1262 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1263 LInstruction* result = DefineAsRegister(new(zone()) LDivByPowerOf2I( |
| 1264 dividend, divisor)); |
| 1265 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || |
| 1266 (instr->CheckFlag(HValue::kCanOverflow) && divisor == -1) || |
| 1267 (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
| 1268 divisor != 1 && divisor != -1)) { |
| 1269 result = AssignEnvironment(result); |
| 1270 } |
| 1271 return result; |
| 1272 } |
| 1273 |
| 1274 |
| 1275 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) { |
| 1276 ASSERT(instr->representation().IsInteger32()); |
| 1277 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1278 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1279 LOperand* dividend = UseRegister(instr->left()); |
| 1280 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1281 LOperand* temp1 = FixedTemp(rax); |
| 1282 LOperand* temp2 = FixedTemp(rdx); |
| 1283 LInstruction* result = DefineFixed(new(zone()) LDivByConstI( |
| 1284 dividend, divisor, temp1, temp2), rdx); |
| 1285 if (divisor == 0 || |
| 1286 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || |
| 1287 !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
| 1288 result = AssignEnvironment(result); |
| 1289 } |
| 1290 return result; |
| 1291 } |
| 1292 |
| 1293 |
| 1294 LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) { |
| 1295 ASSERT(instr->representation().IsSmiOrInteger32()); |
| 1296 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1297 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1298 LOperand* dividend = UseFixed(instr->left(), rax); |
| 1299 LOperand* divisor = UseRegister(instr->right()); |
| 1300 LOperand* temp = FixedTemp(rdx); |
| 1301 LInstruction* result = DefineFixed(new(zone()) LDivI( |
| 1302 dividend, divisor, temp), rax); |
| 1303 if (instr->CheckFlag(HValue::kCanBeDivByZero) || |
| 1304 instr->CheckFlag(HValue::kBailoutOnMinusZero) || |
| 1305 instr->CheckFlag(HValue::kCanOverflow) || |
| 1306 (!instr->IsMathFloorOfDiv() && |
| 1307 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { |
| 1308 result = AssignEnvironment(result); |
| 1309 } |
| 1310 return result; |
| 1311 } |
| 1312 |
| 1313 |
| 1245 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1314 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
| 1246 if (instr->representation().IsSmiOrInteger32()) { | 1315 if (instr->representation().IsSmiOrInteger32()) { |
| 1247 ASSERT(instr->left()->representation().Equals(instr->representation())); | |
| 1248 ASSERT(instr->right()->representation().Equals(instr->representation())); | |
| 1249 if (instr->RightIsPowerOf2()) { | 1316 if (instr->RightIsPowerOf2()) { |
| 1250 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); | 1317 return DoDivByPowerOf2I(instr); |
| 1251 LOperand* value = UseRegister(instr->left()); | 1318 } else if (instr->right()->IsConstant()) { |
| 1252 LDivI* div = | 1319 return DoDivByConstI(instr); |
| 1253 new(zone()) LDivI(value, UseOrConstant(instr->right()), NULL); | 1320 } else { |
| 1254 return AssignEnvironment(DefineAsRegister(div)); | 1321 return DoDivI(instr); |
| 1255 } | 1322 } |
| 1256 // The temporary operand is necessary to ensure that right is not allocated | |
| 1257 // into rdx. | |
| 1258 LOperand* temp = FixedTemp(rdx); | |
| 1259 LOperand* dividend = UseFixed(instr->left(), rax); | |
| 1260 LOperand* divisor = UseRegister(instr->right()); | |
| 1261 LDivI* result = new(zone()) LDivI(dividend, divisor, temp); | |
| 1262 return AssignEnvironment(DefineFixed(result, rax)); | |
| 1263 } else if (instr->representation().IsDouble()) { | 1323 } else if (instr->representation().IsDouble()) { |
| 1264 return DoArithmeticD(Token::DIV, instr); | 1324 return DoArithmeticD(Token::DIV, instr); |
| 1265 } else { | 1325 } else { |
| 1266 return DoArithmeticT(Token::DIV, instr); | 1326 return DoArithmeticT(Token::DIV, instr); |
| 1267 } | 1327 } |
| 1268 } | 1328 } |
| 1269 | 1329 |
| 1270 | 1330 |
| 1331 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) { |
| 1332 LOperand* dividend = UseRegisterAtStart(instr->left()); |
| 1333 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1334 LInstruction* result = DefineSameAsFirst(new(zone()) LFlooringDivByPowerOf2I( |
| 1335 dividend, divisor)); |
| 1336 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || |
| 1337 (instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) { |
| 1338 result = AssignEnvironment(result); |
| 1339 } |
| 1340 return result; |
| 1341 } |
| 1342 |
| 1343 |
| 1344 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) { |
| 1345 ASSERT(instr->representation().IsInteger32()); |
| 1346 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1347 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1348 LOperand* dividend = UseRegister(instr->left()); |
| 1349 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1350 LOperand* temp1 = FixedTemp(rax); |
| 1351 LOperand* temp2 = FixedTemp(rdx); |
| 1352 LInstruction* result = |
| 1353 DefineFixed(new(zone()) LFlooringDivByConstI(dividend, |
| 1354 divisor, |
| 1355 temp1, |
| 1356 temp2), |
| 1357 rdx); |
| 1358 bool can_deopt = |
| 1359 divisor == 0 || |
| 1360 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0); |
| 1361 return can_deopt ? AssignEnvironment(result) : result; |
| 1362 } |
| 1363 |
| 1364 |
| 1271 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { | 1365 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { |
| 1272 HValue* right = instr->right(); | 1366 if (instr->RightIsPowerOf2()) { |
| 1273 if (!right->IsConstant()) { | 1367 return DoFlooringDivByPowerOf2I(instr); |
| 1274 ASSERT(right->representation().IsInteger32()); | 1368 } else if (false && instr->right()->IsConstant()) { |
| 1275 // The temporary operand is necessary to ensure that right is not allocated | 1369 return DoFlooringDivByConstI(instr); // TODO(svenpanne) Fix and re-enable. |
| 1276 // into rdx. | |
| 1277 LOperand* temp = FixedTemp(rdx); | |
| 1278 LOperand* dividend = UseFixed(instr->left(), rax); | |
| 1279 LOperand* divisor = UseRegister(instr->right()); | |
| 1280 LDivI* flooring_div = new(zone()) LDivI(dividend, divisor, temp); | |
| 1281 return AssignEnvironment(DefineFixed(flooring_div, rax)); | |
| 1282 } | |
| 1283 | |
| 1284 ASSERT(right->IsConstant() && HConstant::cast(right)->HasInteger32Value()); | |
| 1285 LOperand* divisor = chunk_->DefineConstantOperand(HConstant::cast(right)); | |
| 1286 int32_t divisor_si = HConstant::cast(right)->Integer32Value(); | |
| 1287 if (divisor_si == 0) { | |
| 1288 LOperand* dividend = UseRegister(instr->left()); | |
| 1289 return AssignEnvironment(DefineAsRegister( | |
| 1290 new(zone()) LMathFloorOfDiv(dividend, divisor, NULL))); | |
| 1291 } else if (IsPowerOf2(abs(divisor_si))) { | |
| 1292 LOperand* dividend = UseRegisterAtStart(instr->left()); | |
| 1293 LInstruction* result = DefineAsRegister( | |
| 1294 new(zone()) LMathFloorOfDiv(dividend, divisor, NULL)); | |
| 1295 return divisor_si < 0 ? AssignEnvironment(result) : result; | |
| 1296 } else { | 1370 } else { |
| 1297 // use two r64 | 1371 return DoDivI(instr); |
| 1298 LOperand* dividend = UseRegisterAtStart(instr->left()); | |
| 1299 LOperand* temp = TempRegister(); | |
| 1300 LInstruction* result = DefineAsRegister( | |
| 1301 new(zone()) LMathFloorOfDiv(dividend, divisor, temp)); | |
| 1302 return divisor_si < 0 ? AssignEnvironment(result) : result; | |
| 1303 } | 1372 } |
| 1304 } | 1373 } |
| 1305 | 1374 |
| 1306 | 1375 |
| 1376 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) { |
| 1377 ASSERT(instr->representation().IsSmiOrInteger32()); |
| 1378 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1379 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1380 LOperand* dividend = UseRegisterAtStart(instr->left()); |
| 1381 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1382 LInstruction* result = DefineSameAsFirst(new(zone()) LModByPowerOf2I( |
| 1383 dividend, divisor)); |
| 1384 if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1385 result = AssignEnvironment(result); |
| 1386 } |
| 1387 return result; |
| 1388 } |
| 1389 |
| 1390 |
| 1391 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) { |
| 1392 ASSERT(instr->representation().IsSmiOrInteger32()); |
| 1393 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1394 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1395 LOperand* dividend = UseRegister(instr->left()); |
| 1396 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1397 LOperand* temp1 = FixedTemp(rax); |
| 1398 LOperand* temp2 = FixedTemp(rdx); |
| 1399 LInstruction* result = DefineFixed(new(zone()) LModByConstI( |
| 1400 dividend, divisor, temp1, temp2), rax); |
| 1401 if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1402 result = AssignEnvironment(result); |
| 1403 } |
| 1404 return result; |
| 1405 } |
| 1406 |
| 1407 |
| 1408 LInstruction* LChunkBuilder::DoModI(HMod* instr) { |
| 1409 ASSERT(instr->representation().IsSmiOrInteger32()); |
| 1410 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1411 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1412 LOperand* dividend = UseFixed(instr->left(), rax); |
| 1413 LOperand* divisor = UseRegister(instr->right()); |
| 1414 LOperand* temp = FixedTemp(rdx); |
| 1415 LInstruction* result = DefineFixed(new(zone()) LModI( |
| 1416 dividend, divisor, temp), rdx); |
| 1417 if (instr->CheckFlag(HValue::kCanBeDivByZero) || |
| 1418 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1419 result = AssignEnvironment(result); |
| 1420 } |
| 1421 return result; |
| 1422 } |
| 1423 |
| 1424 |
| 1307 LInstruction* LChunkBuilder::DoMod(HMod* instr) { | 1425 LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
| 1308 HValue* left = instr->left(); | |
| 1309 HValue* right = instr->right(); | |
| 1310 if (instr->representation().IsSmiOrInteger32()) { | 1426 if (instr->representation().IsSmiOrInteger32()) { |
| 1311 ASSERT(left->representation().Equals(instr->representation())); | |
| 1312 ASSERT(right->representation().Equals(instr->representation())); | |
| 1313 if (instr->RightIsPowerOf2()) { | 1427 if (instr->RightIsPowerOf2()) { |
| 1314 ASSERT(!right->CanBeZero()); | 1428 return DoModByPowerOf2I(instr); |
| 1315 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left), | 1429 } else if (instr->right()->IsConstant()) { |
| 1316 UseOrConstant(right), | 1430 return DoModByConstI(instr); |
| 1317 NULL); | |
| 1318 LInstruction* result = DefineSameAsFirst(mod); | |
| 1319 return (left->CanBeNegative() && | |
| 1320 instr->CheckFlag(HValue::kBailoutOnMinusZero)) | |
| 1321 ? AssignEnvironment(result) | |
| 1322 : result; | |
| 1323 } else { | 1431 } else { |
| 1324 // The temporary operand is necessary to ensure that right is not | 1432 return DoModI(instr); |
| 1325 // allocated into edx. | |
| 1326 LModI* mod = new(zone()) LModI(UseFixed(left, rax), | |
| 1327 UseRegister(right), | |
| 1328 FixedTemp(rdx)); | |
| 1329 LInstruction* result = DefineFixed(mod, rdx); | |
| 1330 return (right->CanBeZero() || | |
| 1331 (left->RangeCanInclude(kMinInt) && | |
| 1332 right->RangeCanInclude(-1) && | |
| 1333 instr->CheckFlag(HValue::kBailoutOnMinusZero)) || | |
| 1334 (left->CanBeNegative() && | |
| 1335 instr->CanBeZero() && | |
| 1336 instr->CheckFlag(HValue::kBailoutOnMinusZero))) | |
| 1337 ? AssignEnvironment(result) | |
| 1338 : result; | |
| 1339 } | 1433 } |
| 1340 } else if (instr->representation().IsDouble()) { | 1434 } else if (instr->representation().IsDouble()) { |
| 1341 return DoArithmeticD(Token::MOD, instr); | 1435 return DoArithmeticD(Token::MOD, instr); |
| 1342 } else { | 1436 } else { |
| 1343 return DoArithmeticT(Token::MOD, instr); | 1437 return DoArithmeticT(Token::MOD, instr); |
| 1344 } | 1438 } |
| 1345 } | 1439 } |
| 1346 | 1440 |
| 1347 | 1441 |
| 1348 LInstruction* LChunkBuilder::DoMul(HMul* instr) { | 1442 LInstruction* LChunkBuilder::DoMul(HMul* instr) { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1428 } else { | 1522 } else { |
| 1429 return DoArithmeticT(Token::ADD, instr); | 1523 return DoArithmeticT(Token::ADD, instr); |
| 1430 } | 1524 } |
| 1431 return NULL; | 1525 return NULL; |
| 1432 } | 1526 } |
| 1433 | 1527 |
| 1434 | 1528 |
| 1435 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { | 1529 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { |
| 1436 LOperand* left = NULL; | 1530 LOperand* left = NULL; |
| 1437 LOperand* right = NULL; | 1531 LOperand* right = NULL; |
| 1438 if (instr->representation().IsSmiOrInteger32()) { | 1532 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1439 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1533 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1440 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1534 if (instr->representation().IsSmi()) { |
| 1535 left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1536 right = UseAtStart(instr->BetterRightOperand()); |
| 1537 } else if (instr->representation().IsInteger32()) { |
| 1441 left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1538 left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1442 right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1539 right = UseOrConstantAtStart(instr->BetterRightOperand()); |
| 1443 } else { | 1540 } else { |
| 1444 ASSERT(instr->representation().IsDouble()); | 1541 ASSERT(instr->representation().IsDouble()); |
| 1445 ASSERT(instr->left()->representation().IsDouble()); | |
| 1446 ASSERT(instr->right()->representation().IsDouble()); | |
| 1447 left = UseRegisterAtStart(instr->left()); | 1542 left = UseRegisterAtStart(instr->left()); |
| 1448 right = UseRegisterAtStart(instr->right()); | 1543 right = UseRegisterAtStart(instr->right()); |
| 1449 } | 1544 } |
| 1450 LMathMinMax* minmax = new(zone()) LMathMinMax(left, right); | 1545 LMathMinMax* minmax = new(zone()) LMathMinMax(left, right); |
| 1451 return DefineSameAsFirst(minmax); | 1546 return DefineSameAsFirst(minmax); |
| 1452 } | 1547 } |
| 1453 | 1548 |
| 1454 | 1549 |
| 1455 LInstruction* LChunkBuilder::DoPower(HPower* instr) { | 1550 LInstruction* LChunkBuilder::DoPower(HPower* instr) { |
| 1456 ASSERT(instr->representation().IsDouble()); | 1551 ASSERT(instr->representation().IsDouble()); |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1737 ASSERT(to.IsInteger32()); | 1832 ASSERT(to.IsInteger32()); |
| 1738 LOperand* value = UseRegister(instr->value()); | 1833 LOperand* value = UseRegister(instr->value()); |
| 1739 return AssignEnvironment( | 1834 return AssignEnvironment( |
| 1740 DefineAsRegister(new(zone()) LDoubleToI(value))); | 1835 DefineAsRegister(new(zone()) LDoubleToI(value))); |
| 1741 } | 1836 } |
| 1742 } else if (from.IsInteger32()) { | 1837 } else if (from.IsInteger32()) { |
| 1743 info()->MarkAsDeferredCalling(); | 1838 info()->MarkAsDeferredCalling(); |
| 1744 if (to.IsTagged()) { | 1839 if (to.IsTagged()) { |
| 1745 HValue* val = instr->value(); | 1840 HValue* val = instr->value(); |
| 1746 LOperand* value = UseRegister(val); | 1841 LOperand* value = UseRegister(val); |
| 1747 if (val->CheckFlag(HInstruction::kUint32)) { | 1842 if (!instr->CheckFlag(HValue::kCanOverflow)) { |
| 1748 LOperand* temp = FixedTemp(xmm1); | 1843 return DefineAsRegister(new(zone()) LSmiTag(value)); |
| 1749 LNumberTagU* result = new(zone()) LNumberTagU(value, temp); | 1844 } else if (val->CheckFlag(HInstruction::kUint32)) { |
| 1845 LOperand* temp1 = TempRegister(); |
| 1846 LOperand* temp2 = FixedTemp(xmm1); |
| 1847 LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2); |
| 1750 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); | 1848 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); |
| 1751 } else if (val->HasRange() && val->range()->IsInSmiRange()) { | |
| 1752 return DefineSameAsFirst(new(zone()) LSmiTag(value)); | |
| 1753 } else { | 1849 } else { |
| 1754 LNumberTagI* result = new(zone()) LNumberTagI(value); | 1850 LNumberTagI* result = new(zone()) LNumberTagI(value); |
| 1755 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); | 1851 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); |
| 1756 } | 1852 } |
| 1757 } else if (to.IsSmi()) { | 1853 } else if (to.IsSmi()) { |
| 1758 HValue* val = instr->value(); | 1854 HValue* val = instr->value(); |
| 1759 LOperand* value = UseRegister(val); | 1855 LOperand* value = UseRegister(val); |
| 1760 LInstruction* result = NULL; | 1856 LInstruction* result = DefineAsRegister(new(zone()) LSmiTag(value)); |
| 1761 if (val->CheckFlag(HInstruction::kUint32)) { | 1857 if (instr->CheckFlag(HValue::kCanOverflow)) { |
| 1762 result = DefineAsRegister(new(zone()) LUint32ToSmi(value)); | 1858 ASSERT(val->CheckFlag(HValue::kUint32)); |
| 1763 if (val->HasRange() && val->range()->IsInSmiRange() && | 1859 result = AssignEnvironment(result); |
| 1764 val->range()->upper() != kMaxInt) { | |
| 1765 return result; | |
| 1766 } | |
| 1767 } else { | |
| 1768 result = DefineAsRegister(new(zone()) LInteger32ToSmi(value)); | |
| 1769 if (val->HasRange() && val->range()->IsInSmiRange()) { | |
| 1770 return result; | |
| 1771 } | |
| 1772 } | 1860 } |
| 1773 return AssignEnvironment(result); | 1861 return result; |
| 1774 } else { | 1862 } else { |
| 1775 if (instr->value()->CheckFlag(HInstruction::kUint32)) { | 1863 if (instr->value()->CheckFlag(HInstruction::kUint32)) { |
| 1776 LOperand* temp = FixedTemp(xmm1); | 1864 LOperand* temp = FixedTemp(xmm1); |
| 1777 return DefineAsRegister( | 1865 return DefineAsRegister( |
| 1778 new(zone()) LUint32ToDouble(UseRegister(instr->value()), temp)); | 1866 new(zone()) LUint32ToDouble(UseRegister(instr->value()), temp)); |
| 1779 } else { | 1867 } else { |
| 1780 ASSERT(to.IsDouble()); | 1868 ASSERT(to.IsDouble()); |
| 1781 LOperand* value = Use(instr->value()); | 1869 LOperand* value = Use(instr->value()); |
| 1782 return DefineAsRegister(new(zone()) LInteger32ToDouble(value)); | 1870 return DefineAsRegister(new(zone()) LInteger32ToDouble(value)); |
| 1783 } | 1871 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1840 ASSERT(input_rep.IsSmiOrTagged()); | 1928 ASSERT(input_rep.IsSmiOrTagged()); |
| 1841 // Register allocator doesn't (yet) support allocation of double | 1929 // Register allocator doesn't (yet) support allocation of double |
| 1842 // temps. Reserve xmm1 explicitly. | 1930 // temps. Reserve xmm1 explicitly. |
| 1843 LClampTToUint8* result = new(zone()) LClampTToUint8(reg, | 1931 LClampTToUint8* result = new(zone()) LClampTToUint8(reg, |
| 1844 FixedTemp(xmm1)); | 1932 FixedTemp(xmm1)); |
| 1845 return AssignEnvironment(DefineSameAsFirst(result)); | 1933 return AssignEnvironment(DefineSameAsFirst(result)); |
| 1846 } | 1934 } |
| 1847 } | 1935 } |
| 1848 | 1936 |
| 1849 | 1937 |
| 1938 LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) { |
| 1939 HValue* value = instr->value(); |
| 1940 ASSERT(value->representation().IsDouble()); |
| 1941 return DefineAsRegister(new(zone()) LDoubleBits(UseRegister(value))); |
| 1942 } |
| 1943 |
| 1944 |
| 1945 LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) { |
| 1946 LOperand* lo = UseRegister(instr->lo()); |
| 1947 LOperand* hi = UseRegister(instr->hi()); |
| 1948 return DefineAsRegister(new(zone()) LConstructDouble(hi, lo)); |
| 1949 } |
| 1950 |
| 1951 |
| 1850 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { | 1952 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { |
| 1851 LOperand* context = info()->IsStub() ? UseFixed(instr->context(), rsi) : NULL; | 1953 LOperand* context = info()->IsStub() ? UseFixed(instr->context(), rsi) : NULL; |
| 1852 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count()); | 1954 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count()); |
| 1853 return new(zone()) LReturn( | 1955 return new(zone()) LReturn( |
| 1854 UseFixed(instr->value(), rax), context, parameter_count); | 1956 UseFixed(instr->value(), rax), context, parameter_count); |
| 1855 } | 1957 } |
| 1856 | 1958 |
| 1857 | 1959 |
| 1858 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { | 1960 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { |
| 1859 Representation r = instr->representation(); | 1961 Representation r = instr->representation(); |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2121 ASSERT(!needs_write_barrier_for_map); | 2223 ASSERT(!needs_write_barrier_for_map); |
| 2122 obj = UseRegisterOrConstant(instr->object()); | 2224 obj = UseRegisterOrConstant(instr->object()); |
| 2123 } else { | 2225 } else { |
| 2124 obj = needs_write_barrier_for_map | 2226 obj = needs_write_barrier_for_map |
| 2125 ? UseRegister(instr->object()) | 2227 ? UseRegister(instr->object()) |
| 2126 : UseRegisterAtStart(instr->object()); | 2228 : UseRegisterAtStart(instr->object()); |
| 2127 } | 2229 } |
| 2128 | 2230 |
| 2129 bool can_be_constant = instr->value()->IsConstant() && | 2231 bool can_be_constant = instr->value()->IsConstant() && |
| 2130 HConstant::cast(instr->value())->NotInNewSpace() && | 2232 HConstant::cast(instr->value())->NotInNewSpace() && |
| 2131 !(FLAG_track_double_fields && instr->field_representation().IsDouble()); | 2233 !instr->field_representation().IsDouble(); |
| 2132 | 2234 |
| 2133 LOperand* val; | 2235 LOperand* val; |
| 2134 if (needs_write_barrier) { | 2236 if (needs_write_barrier) { |
| 2135 val = UseTempRegister(instr->value()); | 2237 val = UseTempRegister(instr->value()); |
| 2136 } else if (is_external_location) { | 2238 } else if (is_external_location) { |
| 2137 val = UseFixed(instr->value(), rax); | 2239 val = UseFixed(instr->value(), rax); |
| 2138 } else if (can_be_constant) { | 2240 } else if (can_be_constant) { |
| 2139 val = UseRegisterOrConstant(instr->value()); | 2241 val = UseRegisterOrConstant(instr->value()); |
| 2140 } else if (FLAG_track_fields && instr->field_representation().IsSmi()) { | 2242 } else if (instr->field_representation().IsSmi()) { |
| 2141 val = UseRegister(instr->value()); | 2243 val = UseRegister(instr->value()); |
| 2142 } else if (FLAG_track_double_fields && | 2244 } else if (instr->field_representation().IsDouble()) { |
| 2143 instr->field_representation().IsDouble()) { | |
| 2144 val = UseRegisterAtStart(instr->value()); | 2245 val = UseRegisterAtStart(instr->value()); |
| 2145 } else { | 2246 } else { |
| 2146 val = UseRegister(instr->value()); | 2247 val = UseRegister(instr->value()); |
| 2147 } | 2248 } |
| 2148 | 2249 |
| 2149 // We only need a scratch register if we have a write barrier or we | 2250 // We only need a scratch register if we have a write barrier or we |
| 2150 // have a store into the properties array (not in-object-property). | 2251 // have a store into the properties array (not in-object-property). |
| 2151 LOperand* temp = (!is_in_object || needs_write_barrier || | 2252 LOperand* temp = (!is_in_object || needs_write_barrier || |
| 2152 needs_write_barrier_for_map) ? TempRegister() : NULL; | 2253 needs_write_barrier_for_map) ? TempRegister() : NULL; |
| 2153 | 2254 |
| 2154 LStoreNamedField* result = new(zone()) LStoreNamedField(obj, val, temp); | 2255 LStoreNamedField* result = new(zone()) LStoreNamedField(obj, val, temp); |
| 2155 if (FLAG_track_heap_object_fields && | 2256 if (instr->field_representation().IsHeapObject()) { |
| 2156 instr->field_representation().IsHeapObject()) { | |
| 2157 if (!instr->value()->type().IsHeapObject()) { | 2257 if (!instr->value()->type().IsHeapObject()) { |
| 2158 return AssignEnvironment(result); | 2258 return AssignEnvironment(result); |
| 2159 } | 2259 } |
| 2160 } | 2260 } |
| 2161 return result; | 2261 return result; |
| 2162 } | 2262 } |
| 2163 | 2263 |
| 2164 | 2264 |
| 2165 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { | 2265 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { |
| 2166 LOperand* context = UseFixed(instr->context(), rsi); | 2266 LOperand* context = UseFixed(instr->context(), rsi); |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2333 | 2433 |
| 2334 | 2434 |
| 2335 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch( | 2435 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch( |
| 2336 HIsConstructCallAndBranch* instr) { | 2436 HIsConstructCallAndBranch* instr) { |
| 2337 return new(zone()) LIsConstructCallAndBranch(TempRegister()); | 2437 return new(zone()) LIsConstructCallAndBranch(TempRegister()); |
| 2338 } | 2438 } |
| 2339 | 2439 |
| 2340 | 2440 |
| 2341 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { | 2441 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { |
| 2342 instr->ReplayEnvironment(current_block_->last_environment()); | 2442 instr->ReplayEnvironment(current_block_->last_environment()); |
| 2343 | |
| 2344 // If there is an instruction pending deoptimization environment create a | |
| 2345 // lazy bailout instruction to capture the environment. | |
| 2346 if (pending_deoptimization_ast_id_ == instr->ast_id()) { | |
| 2347 LLazyBailout* lazy_bailout = new(zone()) LLazyBailout; | |
| 2348 LInstruction* result = AssignEnvironment(lazy_bailout); | |
| 2349 // Store the lazy deopt environment with the instruction if needed. Right | |
| 2350 // now it is only used for LInstanceOfKnownGlobal. | |
| 2351 instruction_pending_deoptimization_environment_-> | |
| 2352 SetDeferredLazyDeoptimizationEnvironment(result->environment()); | |
| 2353 instruction_pending_deoptimization_environment_ = NULL; | |
| 2354 pending_deoptimization_ast_id_ = BailoutId::None(); | |
| 2355 return result; | |
| 2356 } | |
| 2357 | |
| 2358 return NULL; | 2443 return NULL; |
| 2359 } | 2444 } |
| 2360 | 2445 |
| 2361 | 2446 |
| 2362 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { | 2447 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { |
| 2363 info()->MarkAsDeferredCalling(); | 2448 info()->MarkAsDeferredCalling(); |
| 2364 if (instr->is_function_entry()) { | 2449 if (instr->is_function_entry()) { |
| 2365 LOperand* context = UseFixed(instr->context(), rsi); | 2450 LOperand* context = UseFixed(instr->context(), rsi); |
| 2366 return MarkAsCall(new(zone()) LStackCheck(context), instr); | 2451 return MarkAsCall(new(zone()) LStackCheck(context), instr); |
| 2367 } else { | 2452 } else { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2436 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2521 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
| 2437 LOperand* object = UseRegister(instr->object()); | 2522 LOperand* object = UseRegister(instr->object()); |
| 2438 LOperand* index = UseTempRegister(instr->index()); | 2523 LOperand* index = UseTempRegister(instr->index()); |
| 2439 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index)); | 2524 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index)); |
| 2440 } | 2525 } |
| 2441 | 2526 |
| 2442 | 2527 |
| 2443 } } // namespace v8::internal | 2528 } } // namespace v8::internal |
| 2444 | 2529 |
| 2445 #endif // V8_TARGET_ARCH_X64 | 2530 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |