| 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 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 612 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, | 612 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, |
| 613 HInstruction* hinstr, | 613 HInstruction* hinstr, |
| 614 CanDeoptimize can_deoptimize) { | 614 CanDeoptimize can_deoptimize) { |
| 615 info()->MarkAsNonDeferredCalling(); | 615 info()->MarkAsNonDeferredCalling(); |
| 616 #ifdef DEBUG | 616 #ifdef DEBUG |
| 617 instr->VerifyCall(); | 617 instr->VerifyCall(); |
| 618 #endif | 618 #endif |
| 619 instr->MarkAsCall(); | 619 instr->MarkAsCall(); |
| 620 instr = AssignPointerMap(instr); | 620 instr = AssignPointerMap(instr); |
| 621 | 621 |
| 622 if (hinstr->HasObservableSideEffects()) { | |
| 623 ASSERT(hinstr->next()->IsSimulate()); | |
| 624 HSimulate* sim = HSimulate::cast(hinstr->next()); | |
| 625 ASSERT(instruction_pending_deoptimization_environment_ == NULL); | |
| 626 ASSERT(pending_deoptimization_ast_id_.IsNone()); | |
| 627 instruction_pending_deoptimization_environment_ = instr; | |
| 628 pending_deoptimization_ast_id_ = sim->ast_id(); | |
| 629 } | |
| 630 | |
| 631 // If instruction does not have side-effects lazy deoptimization | 622 // If instruction does not have side-effects lazy deoptimization |
| 632 // after the call will try to deoptimize to the point before the call. | 623 // after the call will try to deoptimize to the point before the call. |
| 633 // Thus we still need to attach environment to this call even if | 624 // Thus we still need to attach environment to this call even if |
| 634 // call sequence can not deoptimize eagerly. | 625 // call sequence can not deoptimize eagerly. |
| 635 bool needs_environment = | 626 bool needs_environment = |
| 636 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || | 627 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || |
| 637 !hinstr->HasObservableSideEffects(); | 628 !hinstr->HasObservableSideEffects(); |
| 638 if (needs_environment && !instr->HasEnvironment()) { | 629 if (needs_environment && !instr->HasEnvironment()) { |
| 639 instr = AssignEnvironment(instr); | 630 instr = AssignEnvironment(instr); |
| 640 } | 631 } |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 906 } | 897 } |
| 907 #endif | 898 #endif |
| 908 | 899 |
| 909 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { | 900 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { |
| 910 instr = AssignPointerMap(instr); | 901 instr = AssignPointerMap(instr); |
| 911 } | 902 } |
| 912 if (FLAG_stress_environments && !instr->HasEnvironment()) { | 903 if (FLAG_stress_environments && !instr->HasEnvironment()) { |
| 913 instr = AssignEnvironment(instr); | 904 instr = AssignEnvironment(instr); |
| 914 } | 905 } |
| 915 chunk_->AddInstruction(instr, current_block_); | 906 chunk_->AddInstruction(instr, current_block_); |
| 907 |
| 908 if (instr->IsCall()) { |
| 909 HValue* hydrogen_value_for_lazy_bailout = current; |
| 910 LInstruction* instruction_needing_environment = NULL; |
| 911 if (current->HasObservableSideEffects()) { |
| 912 HSimulate* sim = HSimulate::cast(current->next()); |
| 913 instruction_needing_environment = instr; |
| 914 sim->ReplayEnvironment(current_block_->last_environment()); |
| 915 hydrogen_value_for_lazy_bailout = sim; |
| 916 } |
| 917 LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout()); |
| 918 bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout); |
| 919 chunk_->AddInstruction(bailout, current_block_); |
| 920 if (instruction_needing_environment != NULL) { |
| 921 // Store the lazy deopt environment with the instruction if needed. |
| 922 // Right now it is only used for LInstanceOfKnownGlobal. |
| 923 instruction_needing_environment-> |
| 924 SetDeferredLazyDeoptimizationEnvironment(bailout->environment()); |
| 925 } |
| 926 } |
| 916 } | 927 } |
| 917 current_instruction_ = old_current; | 928 current_instruction_ = old_current; |
| 918 } | 929 } |
| 919 | 930 |
| 920 | 931 |
| 921 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { | 932 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { |
| 922 return new(zone()) LGoto(instr->FirstSuccessor()); | 933 return new(zone()) LGoto(instr->FirstSuccessor()); |
| 923 } | 934 } |
| 924 | 935 |
| 925 | 936 |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1237 | 1248 |
| 1238 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1249 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1239 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1250 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
| 1240 return DefineAsRegister(new(zone()) LBitI(left, right)); | 1251 return DefineAsRegister(new(zone()) LBitI(left, right)); |
| 1241 } else { | 1252 } else { |
| 1242 return DoArithmeticT(instr->op(), instr); | 1253 return DoArithmeticT(instr->op(), instr); |
| 1243 } | 1254 } |
| 1244 } | 1255 } |
| 1245 | 1256 |
| 1246 | 1257 |
| 1258 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) { |
| 1259 ASSERT(instr->representation().IsSmiOrInteger32()); |
| 1260 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1261 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1262 LOperand* dividend = UseRegister(instr->left()); |
| 1263 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1264 LInstruction* result = DefineAsRegister(new(zone()) LDivByPowerOf2I( |
| 1265 dividend, divisor)); |
| 1266 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || |
| 1267 (instr->CheckFlag(HValue::kCanOverflow) && divisor == -1) || |
| 1268 (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
| 1269 divisor != 1 && divisor != -1)) { |
| 1270 result = AssignEnvironment(result); |
| 1271 } |
| 1272 return result; |
| 1273 } |
| 1274 |
| 1275 |
| 1276 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) { |
| 1277 ASSERT(instr->representation().IsInteger32()); |
| 1278 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1279 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1280 LOperand* dividend = UseRegister(instr->left()); |
| 1281 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1282 LInstruction* result = DefineAsRegister(new(zone()) LDivByConstI( |
| 1283 dividend, divisor)); |
| 1284 if (divisor == 0 || |
| 1285 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || |
| 1286 !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
| 1287 result = AssignEnvironment(result); |
| 1288 } |
| 1289 return result; |
| 1290 } |
| 1291 |
| 1292 |
| 1293 LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) { |
| 1294 ASSERT(instr->representation().IsSmiOrInteger32()); |
| 1295 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1296 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1297 LOperand* dividend = UseRegister(instr->left()); |
| 1298 LOperand* divisor = UseRegister(instr->right()); |
| 1299 LDivI* div = new(zone()) LDivI(dividend, divisor); |
| 1300 return AssignEnvironment(DefineAsRegister(div)); |
| 1301 } |
| 1302 |
| 1303 |
| 1247 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1304 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
| 1248 if (instr->representation().IsSmiOrInteger32()) { | 1305 if (instr->representation().IsSmiOrInteger32()) { |
| 1249 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1306 if (instr->RightIsPowerOf2()) { |
| 1250 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1307 return DoDivByPowerOf2I(instr); |
| 1251 LOperand* dividend = UseRegister(instr->left()); | 1308 } else if (instr->right()->IsConstant()) { |
| 1252 LOperand* divisor = UseRegister(instr->right()); | 1309 return DoDivByConstI(instr); |
| 1253 LDivI* div = new(zone()) LDivI(dividend, divisor); | 1310 } else { |
| 1254 return AssignEnvironment(DefineAsRegister(div)); | 1311 return DoDivI(instr); |
| 1312 } |
| 1255 } else if (instr->representation().IsDouble()) { | 1313 } else if (instr->representation().IsDouble()) { |
| 1256 return DoArithmeticD(Token::DIV, instr); | 1314 return DoArithmeticD(Token::DIV, instr); |
| 1257 } else { | 1315 } else { |
| 1258 return DoArithmeticT(Token::DIV, instr); | 1316 return DoArithmeticT(Token::DIV, instr); |
| 1259 } | 1317 } |
| 1260 } | 1318 } |
| 1261 | 1319 |
| 1262 | 1320 |
| 1263 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) { | 1321 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) { |
| 1264 uint32_t divisor_abs = abs(divisor); | 1322 LOperand* dividend = UseRegisterAtStart(instr->left()); |
| 1265 // Dividing by 0, 1, and powers of 2 is easy. | 1323 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1266 // Note that IsPowerOf2(0) returns true; | 1324 LInstruction* result = DefineAsRegister(new(zone()) LFlooringDivByPowerOf2I( |
| 1267 ASSERT(IsPowerOf2(0) == true); | 1325 dividend, divisor)); |
| 1268 if (IsPowerOf2(divisor_abs)) return true; | 1326 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || |
| 1327 (instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) { |
| 1328 result = AssignEnvironment(result); |
| 1329 } |
| 1330 return result; |
| 1331 } |
| 1269 | 1332 |
| 1270 // We have magic numbers for a few specific divisors. | |
| 1271 // Details and proofs can be found in: | |
| 1272 // - Hacker's Delight, Henry S. Warren, Jr. | |
| 1273 // - The PowerPC Compiler Writer's Guide | |
| 1274 // and probably many others. | |
| 1275 // | |
| 1276 // We handle | |
| 1277 // <divisor with magic numbers> * <power of 2> | |
| 1278 // but not | |
| 1279 // <divisor with magic numbers> * <other divisor with magic numbers> | |
| 1280 int32_t power_of_2_factor = | |
| 1281 CompilerIntrinsics::CountTrailingZeros(divisor_abs); | |
| 1282 DivMagicNumbers magic_numbers = | |
| 1283 DivMagicNumberFor(divisor_abs >> power_of_2_factor); | |
| 1284 if (magic_numbers.M != InvalidDivMagicNumber.M) return true; | |
| 1285 | 1333 |
| 1286 return false; | 1334 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) { |
| 1335 ASSERT(instr->representation().IsInteger32()); |
| 1336 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1337 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1338 LOperand* dividend = UseRegister(instr->left()); |
| 1339 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1340 LInstruction* result = |
| 1341 DefineAsRegister(new(zone()) LFlooringDivByConstI(dividend, divisor)); |
| 1342 bool can_deopt = |
| 1343 divisor == 0 || |
| 1344 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0); |
| 1345 return can_deopt ? AssignEnvironment(result) : result; |
| 1287 } | 1346 } |
| 1288 | 1347 |
| 1289 | 1348 |
| 1290 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { | 1349 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { |
| 1291 HValue* right = instr->right(); | 1350 if (instr->RightIsPowerOf2()) { |
| 1292 LOperand* dividend = UseRegister(instr->left()); | 1351 return DoFlooringDivByPowerOf2I(instr); |
| 1293 LOperand* divisor = UseRegisterOrConstant(right); | 1352 } else if (false && instr->right()->IsConstant()) { |
| 1294 LOperand* remainder = TempRegister(); | 1353 return DoFlooringDivByConstI(instr); // TODO(svenpanne) Fix and re-enable. |
| 1295 return AssignEnvironment(DefineAsRegister( | 1354 } else { |
| 1296 new(zone()) LMathFloorOfDiv(dividend, divisor, remainder))); | 1355 return DoDivI(instr); |
| 1356 } |
| 1357 } |
| 1358 |
| 1359 |
| 1360 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) { |
| 1361 ASSERT(instr->representation().IsSmiOrInteger32()); |
| 1362 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1363 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1364 LOperand* dividend = UseRegisterAtStart(instr->left()); |
| 1365 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1366 LInstruction* result = DefineSameAsFirst(new(zone()) LModByPowerOf2I( |
| 1367 dividend, divisor)); |
| 1368 if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1369 result = AssignEnvironment(result); |
| 1370 } |
| 1371 return result; |
| 1372 } |
| 1373 |
| 1374 |
| 1375 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) { |
| 1376 ASSERT(instr->representation().IsSmiOrInteger32()); |
| 1377 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1378 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1379 LOperand* dividend = UseRegister(instr->left()); |
| 1380 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1381 LInstruction* result = DefineAsRegister(new(zone()) LModByConstI( |
| 1382 dividend, divisor)); |
| 1383 if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1384 result = AssignEnvironment(result); |
| 1385 } |
| 1386 return result; |
| 1387 } |
| 1388 |
| 1389 |
| 1390 LInstruction* LChunkBuilder::DoModI(HMod* instr) { |
| 1391 ASSERT(instr->representation().IsSmiOrInteger32()); |
| 1392 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1393 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1394 LOperand* dividend = UseRegister(instr->left()); |
| 1395 LOperand* divisor = UseRegister(instr->right()); |
| 1396 LInstruction* result = DefineAsRegister(new(zone()) LModI( |
| 1397 dividend, divisor)); |
| 1398 if (instr->CheckFlag(HValue::kCanBeDivByZero) || |
| 1399 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1400 result = AssignEnvironment(result); |
| 1401 } |
| 1402 return result; |
| 1297 } | 1403 } |
| 1298 | 1404 |
| 1299 | 1405 |
| 1300 LInstruction* LChunkBuilder::DoMod(HMod* instr) { | 1406 LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
| 1301 HValue* left = instr->left(); | |
| 1302 HValue* right = instr->right(); | |
| 1303 if (instr->representation().IsSmiOrInteger32()) { | 1407 if (instr->representation().IsSmiOrInteger32()) { |
| 1304 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1408 return instr->RightIsPowerOf2() ? DoModByPowerOf2I(instr) : DoModI(instr); |
| 1305 ASSERT(instr->right()->representation().Equals(instr->representation())); | |
| 1306 if (instr->RightIsPowerOf2()) { | |
| 1307 ASSERT(!right->CanBeZero()); | |
| 1308 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left), | |
| 1309 UseConstant(right)); | |
| 1310 LInstruction* result = DefineAsRegister(mod); | |
| 1311 return (left->CanBeNegative() && | |
| 1312 instr->CheckFlag(HValue::kBailoutOnMinusZero)) | |
| 1313 ? AssignEnvironment(result) | |
| 1314 : result; | |
| 1315 } else { | |
| 1316 LModI* mod = new(zone()) LModI(UseRegister(left), | |
| 1317 UseRegister(right), | |
| 1318 TempRegister(), | |
| 1319 FixedTemp(f20), | |
| 1320 FixedTemp(f22)); | |
| 1321 LInstruction* result = DefineAsRegister(mod); | |
| 1322 return (right->CanBeZero() || | |
| 1323 (left->RangeCanInclude(kMinInt) && | |
| 1324 right->RangeCanInclude(-1)) || | |
| 1325 instr->CheckFlag(HValue::kBailoutOnMinusZero)) | |
| 1326 ? AssignEnvironment(result) | |
| 1327 : result; | |
| 1328 } | |
| 1329 } else if (instr->representation().IsDouble()) { | 1409 } else if (instr->representation().IsDouble()) { |
| 1330 return DoArithmeticD(Token::MOD, instr); | 1410 return DoArithmeticD(Token::MOD, instr); |
| 1331 } else { | 1411 } else { |
| 1332 return DoArithmeticT(Token::MOD, instr); | 1412 return DoArithmeticT(Token::MOD, instr); |
| 1333 } | 1413 } |
| 1334 } | 1414 } |
| 1335 | 1415 |
| 1336 | 1416 |
| 1337 LInstruction* LChunkBuilder::DoMul(HMul* instr) { | 1417 LInstruction* LChunkBuilder::DoMul(HMul* instr) { |
| 1338 if (instr->representation().IsSmiOrInteger32()) { | 1418 if (instr->representation().IsSmiOrInteger32()) { |
| (...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1763 ASSERT(to.IsInteger32()); | 1843 ASSERT(to.IsInteger32()); |
| 1764 LOperand* value = UseRegister(instr->value()); | 1844 LOperand* value = UseRegister(instr->value()); |
| 1765 LDoubleToI* res = new(zone()) LDoubleToI(value); | 1845 LDoubleToI* res = new(zone()) LDoubleToI(value); |
| 1766 return AssignEnvironment(DefineAsRegister(res)); | 1846 return AssignEnvironment(DefineAsRegister(res)); |
| 1767 } | 1847 } |
| 1768 } else if (from.IsInteger32()) { | 1848 } else if (from.IsInteger32()) { |
| 1769 info()->MarkAsDeferredCalling(); | 1849 info()->MarkAsDeferredCalling(); |
| 1770 if (to.IsTagged()) { | 1850 if (to.IsTagged()) { |
| 1771 HValue* val = instr->value(); | 1851 HValue* val = instr->value(); |
| 1772 LOperand* value = UseRegisterAtStart(val); | 1852 LOperand* value = UseRegisterAtStart(val); |
| 1773 if (val->CheckFlag(HInstruction::kUint32)) { | 1853 if (!instr->CheckFlag(HValue::kCanOverflow)) { |
| 1774 LNumberTagU* result = new(zone()) LNumberTagU(value); | 1854 return DefineAsRegister(new(zone()) LSmiTag(value)); |
| 1855 } else if (val->CheckFlag(HInstruction::kUint32)) { |
| 1856 LOperand* temp1 = TempRegister(); |
| 1857 LOperand* temp2 = TempRegister(); |
| 1858 LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2); |
| 1775 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); | 1859 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); |
| 1776 } else if (val->HasRange() && val->range()->IsInSmiRange()) { | |
| 1777 return DefineAsRegister(new(zone()) LSmiTag(value)); | |
| 1778 } else { | 1860 } else { |
| 1779 LNumberTagI* result = new(zone()) LNumberTagI(value); | 1861 LOperand* temp1 = TempRegister(); |
| 1862 LOperand* temp2 = TempRegister(); |
| 1863 LNumberTagI* result = new(zone()) LNumberTagI(value, temp1, temp2); |
| 1780 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); | 1864 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); |
| 1781 } | 1865 } |
| 1782 } else if (to.IsSmi()) { | 1866 } else if (to.IsSmi()) { |
| 1783 HValue* val = instr->value(); | 1867 HValue* val = instr->value(); |
| 1784 LOperand* value = UseRegister(val); | 1868 LOperand* value = UseRegister(val); |
| 1785 LInstruction* result = val->CheckFlag(HInstruction::kUint32) | 1869 LInstruction* result = DefineAsRegister(new(zone()) LSmiTag(value)); |
| 1786 ? DefineAsRegister(new(zone()) LUint32ToSmi(value)) | 1870 if (instr->CheckFlag(HValue::kCanOverflow)) { |
| 1787 : DefineAsRegister(new(zone()) LInteger32ToSmi(value)); | 1871 result = AssignEnvironment(result); |
| 1788 if (val->HasRange() && val->range()->IsInSmiRange()) { | |
| 1789 return result; | |
| 1790 } | 1872 } |
| 1791 return AssignEnvironment(result); | 1873 return result; |
| 1792 } else { | 1874 } else { |
| 1793 ASSERT(to.IsDouble()); | 1875 ASSERT(to.IsDouble()); |
| 1794 if (instr->value()->CheckFlag(HInstruction::kUint32)) { | 1876 if (instr->value()->CheckFlag(HInstruction::kUint32)) { |
| 1795 return DefineAsRegister( | 1877 return DefineAsRegister( |
| 1796 new(zone()) LUint32ToDouble(UseRegister(instr->value()))); | 1878 new(zone()) LUint32ToDouble(UseRegister(instr->value()))); |
| 1797 } else { | 1879 } else { |
| 1798 return DefineAsRegister( | 1880 return DefineAsRegister( |
| 1799 new(zone()) LInteger32ToDouble(Use(instr->value()))); | 1881 new(zone()) LInteger32ToDouble(Use(instr->value()))); |
| 1800 } | 1882 } |
| 1801 } | 1883 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1857 } else { | 1939 } else { |
| 1858 ASSERT(input_rep.IsSmiOrTagged()); | 1940 ASSERT(input_rep.IsSmiOrTagged()); |
| 1859 // Register allocator doesn't (yet) support allocation of double | 1941 // Register allocator doesn't (yet) support allocation of double |
| 1860 // temps. Reserve f22 explicitly. | 1942 // temps. Reserve f22 explicitly. |
| 1861 LClampTToUint8* result = new(zone()) LClampTToUint8(reg, FixedTemp(f22)); | 1943 LClampTToUint8* result = new(zone()) LClampTToUint8(reg, FixedTemp(f22)); |
| 1862 return AssignEnvironment(DefineAsRegister(result)); | 1944 return AssignEnvironment(DefineAsRegister(result)); |
| 1863 } | 1945 } |
| 1864 } | 1946 } |
| 1865 | 1947 |
| 1866 | 1948 |
| 1949 LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) { |
| 1950 HValue* value = instr->value(); |
| 1951 ASSERT(value->representation().IsDouble()); |
| 1952 return DefineAsRegister(new(zone()) LDoubleBits(UseRegister(value))); |
| 1953 } |
| 1954 |
| 1955 |
| 1956 LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) { |
| 1957 LOperand* lo = UseRegister(instr->lo()); |
| 1958 LOperand* hi = UseRegister(instr->hi()); |
| 1959 return DefineAsRegister(new(zone()) LConstructDouble(hi, lo)); |
| 1960 } |
| 1961 |
| 1962 |
| 1867 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { | 1963 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { |
| 1868 LOperand* context = info()->IsStub() | 1964 LOperand* context = info()->IsStub() |
| 1869 ? UseFixed(instr->context(), cp) | 1965 ? UseFixed(instr->context(), cp) |
| 1870 : NULL; | 1966 : NULL; |
| 1871 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count()); | 1967 LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count()); |
| 1872 return new(zone()) LReturn(UseFixed(instr->value(), v0), context, | 1968 return new(zone()) LReturn(UseFixed(instr->value(), v0), context, |
| 1873 parameter_count); | 1969 parameter_count); |
| 1874 } | 1970 } |
| 1875 | 1971 |
| 1876 | 1972 |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2113 obj = is_in_object | 2209 obj = is_in_object |
| 2114 ? UseRegister(instr->object()) | 2210 ? UseRegister(instr->object()) |
| 2115 : UseTempRegister(instr->object()); | 2211 : UseTempRegister(instr->object()); |
| 2116 } else { | 2212 } else { |
| 2117 obj = needs_write_barrier_for_map | 2213 obj = needs_write_barrier_for_map |
| 2118 ? UseRegister(instr->object()) | 2214 ? UseRegister(instr->object()) |
| 2119 : UseRegisterAtStart(instr->object()); | 2215 : UseRegisterAtStart(instr->object()); |
| 2120 } | 2216 } |
| 2121 | 2217 |
| 2122 LOperand* val; | 2218 LOperand* val; |
| 2123 if (needs_write_barrier || | 2219 if (needs_write_barrier || instr->field_representation().IsSmi()) { |
| 2124 (FLAG_track_fields && instr->field_representation().IsSmi())) { | |
| 2125 val = UseTempRegister(instr->value()); | 2220 val = UseTempRegister(instr->value()); |
| 2126 } else if (FLAG_track_double_fields && | 2221 } else if (instr->field_representation().IsDouble()) { |
| 2127 instr->field_representation().IsDouble()) { | |
| 2128 val = UseRegisterAtStart(instr->value()); | 2222 val = UseRegisterAtStart(instr->value()); |
| 2129 } else { | 2223 } else { |
| 2130 val = UseRegister(instr->value()); | 2224 val = UseRegister(instr->value()); |
| 2131 } | 2225 } |
| 2132 | 2226 |
| 2133 // We need a temporary register for write barrier of the map field. | 2227 // We need a temporary register for write barrier of the map field. |
| 2134 LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL; | 2228 LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL; |
| 2135 | 2229 |
| 2136 LStoreNamedField* result = new(zone()) LStoreNamedField(obj, val, temp); | 2230 LStoreNamedField* result = new(zone()) LStoreNamedField(obj, val, temp); |
| 2137 if (FLAG_track_heap_object_fields && | 2231 if (instr->field_representation().IsHeapObject()) { |
| 2138 instr->field_representation().IsHeapObject()) { | |
| 2139 if (!instr->value()->type().IsHeapObject()) { | 2232 if (!instr->value()->type().IsHeapObject()) { |
| 2140 return AssignEnvironment(result); | 2233 return AssignEnvironment(result); |
| 2141 } | 2234 } |
| 2142 } | 2235 } |
| 2143 return result; | 2236 return result; |
| 2144 } | 2237 } |
| 2145 | 2238 |
| 2146 | 2239 |
| 2147 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { | 2240 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { |
| 2148 LOperand* context = UseFixed(instr->context(), cp); | 2241 LOperand* context = UseFixed(instr->context(), cp); |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2307 | 2400 |
| 2308 | 2401 |
| 2309 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch( | 2402 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch( |
| 2310 HIsConstructCallAndBranch* instr) { | 2403 HIsConstructCallAndBranch* instr) { |
| 2311 return new(zone()) LIsConstructCallAndBranch(TempRegister()); | 2404 return new(zone()) LIsConstructCallAndBranch(TempRegister()); |
| 2312 } | 2405 } |
| 2313 | 2406 |
| 2314 | 2407 |
| 2315 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { | 2408 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { |
| 2316 instr->ReplayEnvironment(current_block_->last_environment()); | 2409 instr->ReplayEnvironment(current_block_->last_environment()); |
| 2317 | |
| 2318 // If there is an instruction pending deoptimization environment create a | |
| 2319 // lazy bailout instruction to capture the environment. | |
| 2320 if (pending_deoptimization_ast_id_ == instr->ast_id()) { | |
| 2321 LInstruction* result = new(zone()) LLazyBailout; | |
| 2322 result = AssignEnvironment(result); | |
| 2323 // Store the lazy deopt environment with the instruction if needed. Right | |
| 2324 // now it is only used for LInstanceOfKnownGlobal. | |
| 2325 instruction_pending_deoptimization_environment_-> | |
| 2326 SetDeferredLazyDeoptimizationEnvironment(result->environment()); | |
| 2327 instruction_pending_deoptimization_environment_ = NULL; | |
| 2328 pending_deoptimization_ast_id_ = BailoutId::None(); | |
| 2329 return result; | |
| 2330 } | |
| 2331 | |
| 2332 return NULL; | 2410 return NULL; |
| 2333 } | 2411 } |
| 2334 | 2412 |
| 2335 | 2413 |
| 2336 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { | 2414 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { |
| 2337 if (instr->is_function_entry()) { | 2415 if (instr->is_function_entry()) { |
| 2338 LOperand* context = UseFixed(instr->context(), cp); | 2416 LOperand* context = UseFixed(instr->context(), cp); |
| 2339 return MarkAsCall(new(zone()) LStackCheck(context), instr); | 2417 return MarkAsCall(new(zone()) LStackCheck(context), instr); |
| 2340 } else { | 2418 } else { |
| 2341 ASSERT(instr->is_backwards_branch()); | 2419 ASSERT(instr->is_backwards_branch()); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2406 | 2484 |
| 2407 | 2485 |
| 2408 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2486 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
| 2409 LOperand* object = UseRegister(instr->object()); | 2487 LOperand* object = UseRegister(instr->object()); |
| 2410 LOperand* index = UseRegister(instr->index()); | 2488 LOperand* index = UseRegister(instr->index()); |
| 2411 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); | 2489 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); |
| 2412 } | 2490 } |
| 2413 | 2491 |
| 2414 | 2492 |
| 2415 } } // namespace v8::internal | 2493 } } // namespace v8::internal |
| OLD | NEW |