| 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 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 694 return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value()))); | 694 return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value()))); |
| 695 } | 695 } |
| 696 | 696 |
| 697 | 697 |
| 698 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) { | 698 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) { |
| 699 UNREACHABLE(); | 699 UNREACHABLE(); |
| 700 return NULL; | 700 return NULL; |
| 701 } | 701 } |
| 702 | 702 |
| 703 | 703 |
| 704 LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) { | |
| 705 return AssignEnvironment(new(zone()) LDeoptimize); | |
| 706 } | |
| 707 | |
| 708 | |
| 709 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { | 704 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { |
| 710 return AssignEnvironment(new(zone()) LDeoptimize); | 705 return AssignEnvironment(new(zone()) LDeoptimize); |
| 711 } | 706 } |
| 712 | 707 |
| 713 | 708 |
| 714 LInstruction* LChunkBuilder::DoShift(Token::Value op, | 709 LInstruction* LChunkBuilder::DoShift(Token::Value op, |
| 715 HBitwiseBinaryOperation* instr) { | 710 HBitwiseBinaryOperation* instr) { |
| 716 if (instr->representation().IsSmiOrTagged()) { | 711 if (instr->representation().IsTagged()) { |
| 717 ASSERT(instr->left()->representation().IsSmiOrTagged()); | 712 ASSERT(instr->left()->representation().IsTagged()); |
| 718 ASSERT(instr->right()->representation().IsSmiOrTagged()); | 713 ASSERT(instr->right()->representation().IsTagged()); |
| 719 | 714 |
| 720 LOperand* left = UseFixed(instr->left(), r1); | 715 LOperand* left = UseFixed(instr->left(), r1); |
| 721 LOperand* right = UseFixed(instr->right(), r0); | 716 LOperand* right = UseFixed(instr->right(), r0); |
| 722 LArithmeticT* result = new(zone()) LArithmeticT(op, left, right); | 717 LArithmeticT* result = new(zone()) LArithmeticT(op, left, right); |
| 723 return MarkAsCall(DefineFixed(result, r0), instr); | 718 return MarkAsCall(DefineFixed(result, r0), instr); |
| 724 } | 719 } |
| 725 | 720 |
| 726 ASSERT(instr->representation().IsInteger32()); | 721 ASSERT(instr->representation().IsSmiOrInteger32()); |
| 727 ASSERT(instr->left()->representation().IsInteger32()); | 722 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 728 ASSERT(instr->right()->representation().IsInteger32()); | 723 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 729 LOperand* left = UseRegisterAtStart(instr->left()); | 724 LOperand* left = UseRegisterAtStart(instr->left()); |
| 730 | 725 |
| 731 HValue* right_value = instr->right(); | 726 HValue* right_value = instr->right(); |
| 732 LOperand* right = NULL; | 727 LOperand* right = NULL; |
| 733 int constant_value = 0; | 728 int constant_value = 0; |
| 729 bool does_deopt = false; |
| 734 if (right_value->IsConstant()) { | 730 if (right_value->IsConstant()) { |
| 735 HConstant* constant = HConstant::cast(right_value); | 731 HConstant* constant = HConstant::cast(right_value); |
| 736 right = chunk_->DefineConstantOperand(constant); | 732 right = chunk_->DefineConstantOperand(constant); |
| 737 constant_value = constant->Integer32Value() & 0x1f; | 733 constant_value = constant->Integer32Value() & 0x1f; |
| 734 // Left shifts can deoptimize if we shift by > 0 and the result cannot be |
| 735 // truncated to smi. |
| 736 if (instr->representation().IsSmi() && constant_value > 0) { |
| 737 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) { |
| 738 if (!it.value()->CheckFlag(HValue::kTruncatingToSmi)) { |
| 739 does_deopt = true; |
| 740 break; |
| 741 } |
| 742 } |
| 743 } |
| 738 } else { | 744 } else { |
| 739 right = UseRegisterAtStart(right_value); | 745 right = UseRegisterAtStart(right_value); |
| 740 } | 746 } |
| 741 | 747 |
| 742 // Shift operations can only deoptimize if we do a logical shift | 748 // Shift operations can only deoptimize if we do a logical shift |
| 743 // by 0 and the result cannot be truncated to int32. | 749 // by 0 and the result cannot be truncated to int32. |
| 744 bool does_deopt = false; | |
| 745 if (op == Token::SHR && constant_value == 0) { | 750 if (op == Token::SHR && constant_value == 0) { |
| 746 if (FLAG_opt_safe_uint32_operations) { | 751 if (FLAG_opt_safe_uint32_operations) { |
| 747 does_deopt = !instr->CheckFlag(HInstruction::kUint32); | 752 does_deopt = !instr->CheckFlag(HInstruction::kUint32); |
| 748 } else { | 753 } else { |
| 749 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) { | 754 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) { |
| 750 if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) { | 755 if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) { |
| 751 does_deopt = true; | 756 does_deopt = true; |
| 752 break; | 757 break; |
| 753 } | 758 } |
| 754 } | 759 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 776 | 781 |
| 777 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, | 782 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, |
| 778 HArithmeticBinaryOperation* instr) { | 783 HArithmeticBinaryOperation* instr) { |
| 779 ASSERT(op == Token::ADD || | 784 ASSERT(op == Token::ADD || |
| 780 op == Token::DIV || | 785 op == Token::DIV || |
| 781 op == Token::MOD || | 786 op == Token::MOD || |
| 782 op == Token::MUL || | 787 op == Token::MUL || |
| 783 op == Token::SUB); | 788 op == Token::SUB); |
| 784 HValue* left = instr->left(); | 789 HValue* left = instr->left(); |
| 785 HValue* right = instr->right(); | 790 HValue* right = instr->right(); |
| 786 ASSERT(left->representation().IsSmiOrTagged()); | 791 ASSERT(left->representation().IsTagged()); |
| 787 ASSERT(right->representation().IsSmiOrTagged()); | 792 ASSERT(right->representation().IsTagged()); |
| 788 LOperand* left_operand = UseFixed(left, r1); | 793 LOperand* left_operand = UseFixed(left, r1); |
| 789 LOperand* right_operand = UseFixed(right, r0); | 794 LOperand* right_operand = UseFixed(right, r0); |
| 790 LArithmeticT* result = | 795 LArithmeticT* result = |
| 791 new(zone()) LArithmeticT(op, left_operand, right_operand); | 796 new(zone()) LArithmeticT(op, left_operand, right_operand); |
| 792 return MarkAsCall(DefineFixed(result, r0), instr); | 797 return MarkAsCall(DefineFixed(result, r0), instr); |
| 793 } | 798 } |
| 794 | 799 |
| 795 | 800 |
| 796 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) { | 801 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) { |
| 797 ASSERT(is_building()); | 802 ASSERT(is_building()); |
| (...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1311 return DoShift(Token::SAR, instr); | 1316 return DoShift(Token::SAR, instr); |
| 1312 } | 1317 } |
| 1313 | 1318 |
| 1314 | 1319 |
| 1315 LInstruction* LChunkBuilder::DoShl(HShl* instr) { | 1320 LInstruction* LChunkBuilder::DoShl(HShl* instr) { |
| 1316 return DoShift(Token::SHL, instr); | 1321 return DoShift(Token::SHL, instr); |
| 1317 } | 1322 } |
| 1318 | 1323 |
| 1319 | 1324 |
| 1320 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { | 1325 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { |
| 1321 if (instr->representation().IsInteger32()) { | 1326 if (instr->representation().IsSmiOrInteger32()) { |
| 1322 ASSERT(instr->left()->representation().IsInteger32()); | 1327 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1323 ASSERT(instr->right()->representation().IsInteger32()); | 1328 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1324 | 1329 |
| 1325 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1330 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1326 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1331 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
| 1327 return DefineAsRegister(new(zone()) LBitI(left, right)); | 1332 return DefineAsRegister(new(zone()) LBitI(left, right)); |
| 1328 } else { | 1333 } else { |
| 1329 ASSERT(instr->representation().IsSmiOrTagged()); | 1334 ASSERT(instr->representation().IsTagged()); |
| 1330 ASSERT(instr->left()->representation().IsSmiOrTagged()); | 1335 ASSERT(instr->left()->representation().IsTagged()); |
| 1331 ASSERT(instr->right()->representation().IsSmiOrTagged()); | 1336 ASSERT(instr->right()->representation().IsTagged()); |
| 1332 | 1337 |
| 1333 LOperand* left = UseFixed(instr->left(), r1); | 1338 LOperand* left = UseFixed(instr->left(), r1); |
| 1334 LOperand* right = UseFixed(instr->right(), r0); | 1339 LOperand* right = UseFixed(instr->right(), r0); |
| 1335 LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right); | 1340 LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right); |
| 1336 return MarkAsCall(DefineFixed(result, r0), instr); | 1341 return MarkAsCall(DefineFixed(result, r0), instr); |
| 1337 } | 1342 } |
| 1338 } | 1343 } |
| 1339 | 1344 |
| 1340 | 1345 |
| 1341 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) { | 1346 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) { |
| 1342 ASSERT(instr->value()->representation().IsInteger32()); | 1347 ASSERT(instr->value()->representation().IsInteger32()); |
| 1343 ASSERT(instr->representation().IsInteger32()); | 1348 ASSERT(instr->representation().IsInteger32()); |
| 1344 if (instr->HasNoUses()) return NULL; | 1349 if (instr->HasNoUses()) return NULL; |
| 1345 LOperand* value = UseRegisterAtStart(instr->value()); | 1350 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1346 return DefineAsRegister(new(zone()) LBitNotI(value)); | 1351 return DefineAsRegister(new(zone()) LBitNotI(value)); |
| 1347 } | 1352 } |
| 1348 | 1353 |
| 1349 | 1354 |
| 1350 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1355 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
| 1351 if (instr->representation().IsDouble()) { | 1356 if (instr->representation().IsDouble()) { |
| 1352 return DoArithmeticD(Token::DIV, instr); | 1357 return DoArithmeticD(Token::DIV, instr); |
| 1353 } else if (instr->representation().IsInteger32()) { | 1358 } else if (instr->representation().IsSmiOrInteger32()) { |
| 1359 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1360 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1354 if (instr->HasPowerOf2Divisor()) { | 1361 if (instr->HasPowerOf2Divisor()) { |
| 1355 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); | 1362 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); |
| 1356 LOperand* value = UseRegisterAtStart(instr->left()); | 1363 LOperand* value = UseRegisterAtStart(instr->left()); |
| 1357 LDivI* div = | 1364 LDivI* div = |
| 1358 new(zone()) LDivI(value, UseOrConstant(instr->right()), NULL); | 1365 new(zone()) LDivI(value, UseOrConstant(instr->right()), NULL); |
| 1359 return AssignEnvironment(DefineSameAsFirst(div)); | 1366 return AssignEnvironment(DefineSameAsFirst(div)); |
| 1360 } | 1367 } |
| 1361 LOperand* dividend = UseRegister(instr->left()); | 1368 LOperand* dividend = UseRegister(instr->left()); |
| 1362 LOperand* divisor = UseRegister(instr->right()); | 1369 LOperand* divisor = UseRegister(instr->right()); |
| 1363 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4); | 1370 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1434 HConstant::cast(right)->HasInteger32Value() && | 1441 HConstant::cast(right)->HasInteger32Value() && |
| 1435 HasMagicNumberForDivisor(HConstant::cast(right)->Integer32Value()))); | 1442 HasMagicNumberForDivisor(HConstant::cast(right)->Integer32Value()))); |
| 1436 return AssignEnvironment(DefineAsRegister( | 1443 return AssignEnvironment(DefineAsRegister( |
| 1437 new(zone()) LMathFloorOfDiv(dividend, divisor, remainder))); | 1444 new(zone()) LMathFloorOfDiv(dividend, divisor, remainder))); |
| 1438 } | 1445 } |
| 1439 | 1446 |
| 1440 | 1447 |
| 1441 LInstruction* LChunkBuilder::DoMod(HMod* instr) { | 1448 LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
| 1442 HValue* left = instr->left(); | 1449 HValue* left = instr->left(); |
| 1443 HValue* right = instr->right(); | 1450 HValue* right = instr->right(); |
| 1444 if (instr->representation().IsInteger32()) { | 1451 if (instr->representation().IsSmiOrInteger32()) { |
| 1445 ASSERT(left->representation().IsInteger32()); | 1452 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1446 ASSERT(right->representation().IsInteger32()); | 1453 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1447 if (instr->HasPowerOf2Divisor()) { | 1454 if (instr->HasPowerOf2Divisor()) { |
| 1448 ASSERT(!right->CanBeZero()); | 1455 ASSERT(!right->CanBeZero()); |
| 1449 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left), | 1456 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left), |
| 1450 UseOrConstant(right)); | 1457 UseOrConstant(right)); |
| 1451 LInstruction* result = DefineAsRegister(mod); | 1458 LInstruction* result = DefineAsRegister(mod); |
| 1452 return (left->CanBeNegative() && | 1459 return (left->CanBeNegative() && |
| 1453 instr->CheckFlag(HValue::kBailoutOnMinusZero)) | 1460 instr->CheckFlag(HValue::kBailoutOnMinusZero)) |
| 1454 ? AssignEnvironment(result) | 1461 ? AssignEnvironment(result) |
| 1455 : result; | 1462 : result; |
| 1456 } else if (instr->fixed_right_arg().has_value) { | 1463 } else if (instr->fixed_right_arg().has_value) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1476 FixedTemp(d10), | 1483 FixedTemp(d10), |
| 1477 FixedTemp(d11)); | 1484 FixedTemp(d11)); |
| 1478 LInstruction* result = DefineAsRegister(mod); | 1485 LInstruction* result = DefineAsRegister(mod); |
| 1479 return (right->CanBeZero() || | 1486 return (right->CanBeZero() || |
| 1480 (left->CanBeNegative() && | 1487 (left->CanBeNegative() && |
| 1481 instr->CanBeZero() && | 1488 instr->CanBeZero() && |
| 1482 instr->CheckFlag(HValue::kBailoutOnMinusZero))) | 1489 instr->CheckFlag(HValue::kBailoutOnMinusZero))) |
| 1483 ? AssignEnvironment(result) | 1490 ? AssignEnvironment(result) |
| 1484 : result; | 1491 : result; |
| 1485 } | 1492 } |
| 1486 } else if (instr->representation().IsSmiOrTagged()) { | 1493 } else if (instr->representation().IsTagged()) { |
| 1487 return DoArithmeticT(Token::MOD, instr); | 1494 return DoArithmeticT(Token::MOD, instr); |
| 1488 } else { | 1495 } else { |
| 1489 ASSERT(instr->representation().IsDouble()); | 1496 ASSERT(instr->representation().IsDouble()); |
| 1490 // We call a C function for double modulo. It can't trigger a GC. We need | 1497 // We call a C function for double modulo. It can't trigger a GC. We need |
| 1491 // to use fixed result register for the call. | 1498 // to use fixed result register for the call. |
| 1492 // TODO(fschneider): Allow any register as input registers. | 1499 // TODO(fschneider): Allow any register as input registers. |
| 1493 LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD, | 1500 LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD, |
| 1494 UseFixedDouble(left, d1), | 1501 UseFixedDouble(left, d1), |
| 1495 UseFixedDouble(right, d2)); | 1502 UseFixedDouble(right, d2)); |
| 1496 return MarkAsCall(DefineFixedDouble(mod, d1), instr); | 1503 return MarkAsCall(DefineFixedDouble(mod, d1), instr); |
| 1497 } | 1504 } |
| 1498 } | 1505 } |
| 1499 | 1506 |
| 1500 | 1507 |
| 1501 LInstruction* LChunkBuilder::DoMul(HMul* instr) { | 1508 LInstruction* LChunkBuilder::DoMul(HMul* instr) { |
| 1502 if (instr->representation().IsInteger32()) { | 1509 if (instr->representation().IsSmiOrInteger32()) { |
| 1503 ASSERT(instr->left()->representation().IsInteger32()); | 1510 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1504 ASSERT(instr->right()->representation().IsInteger32()); | 1511 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1505 LOperand* left; | 1512 LOperand* left; |
| 1506 LOperand* right = UseOrConstant(instr->BetterRightOperand()); | 1513 LOperand* right = UseOrConstant(instr->BetterRightOperand()); |
| 1507 LOperand* temp = NULL; | 1514 LOperand* temp = NULL; |
| 1508 if (instr->CheckFlag(HValue::kBailoutOnMinusZero) && | 1515 if (instr->CheckFlag(HValue::kBailoutOnMinusZero) && |
| 1509 (instr->CheckFlag(HValue::kCanOverflow) || | 1516 (instr->CheckFlag(HValue::kCanOverflow) || |
| 1510 !right->IsConstantOperand())) { | 1517 !right->IsConstantOperand())) { |
| 1511 left = UseRegister(instr->BetterLeftOperand()); | 1518 left = UseRegister(instr->BetterLeftOperand()); |
| 1512 temp = TempRegister(); | 1519 temp = TempRegister(); |
| 1513 } else { | 1520 } else { |
| 1514 left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1521 left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1543 } | 1550 } |
| 1544 | 1551 |
| 1545 return DoArithmeticD(Token::MUL, instr); | 1552 return DoArithmeticD(Token::MUL, instr); |
| 1546 } else { | 1553 } else { |
| 1547 return DoArithmeticT(Token::MUL, instr); | 1554 return DoArithmeticT(Token::MUL, instr); |
| 1548 } | 1555 } |
| 1549 } | 1556 } |
| 1550 | 1557 |
| 1551 | 1558 |
| 1552 LInstruction* LChunkBuilder::DoSub(HSub* instr) { | 1559 LInstruction* LChunkBuilder::DoSub(HSub* instr) { |
| 1553 if (instr->representation().IsInteger32()) { | 1560 if (instr->representation().IsSmiOrInteger32()) { |
| 1554 ASSERT(instr->left()->representation().IsInteger32()); | 1561 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1555 ASSERT(instr->right()->representation().IsInteger32()); | 1562 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1556 | 1563 |
| 1557 if (instr->left()->IsConstant()) { | 1564 if (instr->left()->IsConstant()) { |
| 1558 // If lhs is constant, do reverse subtraction instead. | 1565 // If lhs is constant, do reverse subtraction instead. |
| 1559 return DoRSub(instr); | 1566 return DoRSub(instr); |
| 1560 } | 1567 } |
| 1561 | 1568 |
| 1562 LOperand* left = UseRegisterAtStart(instr->left()); | 1569 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1563 LOperand* right = UseOrConstantAtStart(instr->right()); | 1570 LOperand* right = UseOrConstantAtStart(instr->right()); |
| 1564 LSubI* sub = new(zone()) LSubI(left, right); | 1571 LSubI* sub = new(zone()) LSubI(left, right); |
| 1565 LInstruction* result = DefineAsRegister(sub); | 1572 LInstruction* result = DefineAsRegister(sub); |
| 1566 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1573 if (instr->CheckFlag(HValue::kCanOverflow)) { |
| 1567 result = AssignEnvironment(result); | 1574 result = AssignEnvironment(result); |
| 1568 } | 1575 } |
| 1569 return result; | 1576 return result; |
| 1570 } else if (instr->representation().IsDouble()) { | 1577 } else if (instr->representation().IsDouble()) { |
| 1571 if (instr->right()->IsMul()) { | 1578 if (instr->right()->IsMul()) { |
| 1572 return DoMultiplySub(instr->left(), HMul::cast(instr->right())); | 1579 return DoMultiplySub(instr->left(), HMul::cast(instr->right())); |
| 1573 } | 1580 } |
| 1574 | 1581 |
| 1575 return DoArithmeticD(Token::SUB, instr); | 1582 return DoArithmeticD(Token::SUB, instr); |
| 1576 } else { | 1583 } else { |
| 1577 return DoArithmeticT(Token::SUB, instr); | 1584 return DoArithmeticT(Token::SUB, instr); |
| 1578 } | 1585 } |
| 1579 } | 1586 } |
| 1580 | 1587 |
| 1581 | 1588 |
| 1582 LInstruction* LChunkBuilder::DoRSub(HSub* instr) { | 1589 LInstruction* LChunkBuilder::DoRSub(HSub* instr) { |
| 1583 ASSERT(instr->representation().IsInteger32()); | 1590 ASSERT(instr->representation().IsSmiOrInteger32()); |
| 1584 ASSERT(instr->left()->representation().IsInteger32()); | 1591 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1585 ASSERT(instr->right()->representation().IsInteger32()); | 1592 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1586 | 1593 |
| 1587 // Note: The lhs of the subtraction becomes the rhs of the | 1594 // Note: The lhs of the subtraction becomes the rhs of the |
| 1588 // reverse-subtraction. | 1595 // reverse-subtraction. |
| 1589 LOperand* left = UseRegisterAtStart(instr->right()); | 1596 LOperand* left = UseRegisterAtStart(instr->right()); |
| 1590 LOperand* right = UseOrConstantAtStart(instr->left()); | 1597 LOperand* right = UseOrConstantAtStart(instr->left()); |
| 1591 LRSubI* rsb = new(zone()) LRSubI(left, right); | 1598 LRSubI* rsb = new(zone()) LRSubI(left, right); |
| 1592 LInstruction* result = DefineAsRegister(rsb); | 1599 LInstruction* result = DefineAsRegister(rsb); |
| 1593 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1600 if (instr->CheckFlag(HValue::kCanOverflow)) { |
| 1594 result = AssignEnvironment(result); | 1601 result = AssignEnvironment(result); |
| 1595 } | 1602 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1611 LOperand* multiplier_op = UseRegisterAtStart(mul->left()); | 1618 LOperand* multiplier_op = UseRegisterAtStart(mul->left()); |
| 1612 LOperand* multiplicand_op = UseRegisterAtStart(mul->right()); | 1619 LOperand* multiplicand_op = UseRegisterAtStart(mul->right()); |
| 1613 | 1620 |
| 1614 return DefineSameAsFirst(new(zone()) LMultiplySubD(minuend_op, | 1621 return DefineSameAsFirst(new(zone()) LMultiplySubD(minuend_op, |
| 1615 multiplier_op, | 1622 multiplier_op, |
| 1616 multiplicand_op)); | 1623 multiplicand_op)); |
| 1617 } | 1624 } |
| 1618 | 1625 |
| 1619 | 1626 |
| 1620 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { | 1627 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { |
| 1621 if (instr->representation().IsInteger32()) { | 1628 if (instr->representation().IsSmiOrInteger32()) { |
| 1622 ASSERT(instr->left()->representation().IsInteger32()); | 1629 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1623 ASSERT(instr->right()->representation().IsInteger32()); | 1630 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1624 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1631 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1625 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1632 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
| 1626 LAddI* add = new(zone()) LAddI(left, right); | 1633 LAddI* add = new(zone()) LAddI(left, right); |
| 1627 LInstruction* result = DefineAsRegister(add); | 1634 LInstruction* result = DefineAsRegister(add); |
| 1628 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1635 if (instr->CheckFlag(HValue::kCanOverflow)) { |
| 1629 result = AssignEnvironment(result); | 1636 result = AssignEnvironment(result); |
| 1630 } | 1637 } |
| 1631 return result; | 1638 return result; |
| 1632 } else if (instr->representation().IsDouble()) { | 1639 } else if (instr->representation().IsDouble()) { |
| 1633 if (instr->left()->IsMul()) { | 1640 if (instr->left()->IsMul()) { |
| 1634 return DoMultiplyAdd(HMul::cast(instr->left()), instr->right()); | 1641 return DoMultiplyAdd(HMul::cast(instr->left()), instr->right()); |
| 1635 } | 1642 } |
| 1636 | 1643 |
| 1637 if (instr->right()->IsMul()) { | 1644 if (instr->right()->IsMul()) { |
| 1638 ASSERT(!instr->left()->IsMul()); | 1645 ASSERT(!instr->left()->IsMul()); |
| 1639 return DoMultiplyAdd(HMul::cast(instr->right()), instr->left()); | 1646 return DoMultiplyAdd(HMul::cast(instr->right()), instr->left()); |
| 1640 } | 1647 } |
| 1641 | 1648 |
| 1642 return DoArithmeticD(Token::ADD, instr); | 1649 return DoArithmeticD(Token::ADD, instr); |
| 1643 } else { | 1650 } else { |
| 1644 ASSERT(instr->representation().IsSmiOrTagged()); | 1651 ASSERT(instr->representation().IsTagged()); |
| 1645 return DoArithmeticT(Token::ADD, instr); | 1652 return DoArithmeticT(Token::ADD, instr); |
| 1646 } | 1653 } |
| 1647 } | 1654 } |
| 1648 | 1655 |
| 1649 | 1656 |
| 1650 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { | 1657 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { |
| 1651 LOperand* left = NULL; | 1658 LOperand* left = NULL; |
| 1652 LOperand* right = NULL; | 1659 LOperand* right = NULL; |
| 1653 if (instr->representation().IsInteger32()) { | 1660 if (instr->representation().IsSmiOrInteger32()) { |
| 1654 ASSERT(instr->left()->representation().IsInteger32()); | 1661 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1655 ASSERT(instr->right()->representation().IsInteger32()); | 1662 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1656 left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1663 left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1657 right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1664 right = UseOrConstantAtStart(instr->BetterRightOperand()); |
| 1658 } else { | 1665 } else { |
| 1659 ASSERT(instr->representation().IsDouble()); | 1666 ASSERT(instr->representation().IsDouble()); |
| 1660 ASSERT(instr->left()->representation().IsDouble()); | 1667 ASSERT(instr->left()->representation().IsDouble()); |
| 1661 ASSERT(instr->right()->representation().IsDouble()); | 1668 ASSERT(instr->right()->representation().IsDouble()); |
| 1662 left = UseRegisterAtStart(instr->left()); | 1669 left = UseRegisterAtStart(instr->left()); |
| 1663 right = UseRegisterAtStart(instr->right()); | 1670 right = UseRegisterAtStart(instr->right()); |
| 1664 } | 1671 } |
| 1665 return DefineAsRegister(new(zone()) LMathMinMax(left, right)); | 1672 return DefineAsRegister(new(zone()) LMathMinMax(left, right)); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1724 | 1731 |
| 1725 | 1732 |
| 1726 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( | 1733 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( |
| 1727 HCompareObjectEqAndBranch* instr) { | 1734 HCompareObjectEqAndBranch* instr) { |
| 1728 LOperand* left = UseRegisterAtStart(instr->left()); | 1735 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1729 LOperand* right = UseRegisterAtStart(instr->right()); | 1736 LOperand* right = UseRegisterAtStart(instr->right()); |
| 1730 return new(zone()) LCmpObjectEqAndBranch(left, right); | 1737 return new(zone()) LCmpObjectEqAndBranch(left, right); |
| 1731 } | 1738 } |
| 1732 | 1739 |
| 1733 | 1740 |
| 1734 LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch( | |
| 1735 HCompareConstantEqAndBranch* instr) { | |
| 1736 LOperand* value = UseRegisterAtStart(instr->value()); | |
| 1737 return new(zone()) LCmpConstantEqAndBranch(value); | |
| 1738 } | |
| 1739 | |
| 1740 | |
| 1741 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) { | 1741 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) { |
| 1742 ASSERT(instr->value()->representation().IsTagged()); | 1742 ASSERT(instr->value()->representation().IsTagged()); |
| 1743 LOperand* value = UseRegisterAtStart(instr->value()); | 1743 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1744 LOperand* temp = TempRegister(); | 1744 LOperand* temp = TempRegister(); |
| 1745 return new(zone()) LIsObjectAndBranch(value, temp); | 1745 return new(zone()) LIsObjectAndBranch(value, temp); |
| 1746 } | 1746 } |
| 1747 | 1747 |
| 1748 | 1748 |
| 1749 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) { | 1749 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) { |
| 1750 ASSERT(instr->value()->representation().IsTagged()); | 1750 ASSERT(instr->value()->representation().IsTagged()); |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2028 | 2028 |
| 2029 | 2029 |
| 2030 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { | 2030 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { |
| 2031 LOperand* value = UseRegisterAtStart(instr->value()); | 2031 LOperand* value = UseRegisterAtStart(instr->value()); |
| 2032 LInstruction* result = new(zone()) LCheckInstanceType(value); | 2032 LInstruction* result = new(zone()) LCheckInstanceType(value); |
| 2033 return AssignEnvironment(result); | 2033 return AssignEnvironment(result); |
| 2034 } | 2034 } |
| 2035 | 2035 |
| 2036 | 2036 |
| 2037 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) { | 2037 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) { |
| 2038 LUnallocated* temp1 = TempRegister(); | 2038 LUnallocated* temp1 = NULL; |
| 2039 LOperand* temp2 = TempRegister(); | 2039 LOperand* temp2 = NULL; |
| 2040 if (!instr->CanOmitPrototypeChecks()) { |
| 2041 temp1 = TempRegister(); |
| 2042 temp2 = TempRegister(); |
| 2043 } |
| 2040 LCheckPrototypeMaps* result = new(zone()) LCheckPrototypeMaps(temp1, temp2); | 2044 LCheckPrototypeMaps* result = new(zone()) LCheckPrototypeMaps(temp1, temp2); |
| 2045 if (instr->CanOmitPrototypeChecks()) return result; |
| 2041 return AssignEnvironment(result); | 2046 return AssignEnvironment(result); |
| 2042 } | 2047 } |
| 2043 | 2048 |
| 2044 | 2049 |
| 2045 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) { | 2050 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) { |
| 2046 LOperand* value = UseRegisterAtStart(instr->value()); | 2051 LOperand* value = UseRegisterAtStart(instr->value()); |
| 2047 return AssignEnvironment(new(zone()) LCheckFunction(value)); | 2052 return AssignEnvironment(new(zone()) LCheckFunction(value)); |
| 2048 } | 2053 } |
| 2049 | 2054 |
| 2050 | 2055 |
| 2051 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { | 2056 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { |
| 2052 LOperand* value = UseRegisterAtStart(instr->value()); | 2057 LOperand* value = NULL; |
| 2058 if (!instr->CanOmitMapChecks()) value = UseRegisterAtStart(instr->value()); |
| 2053 LInstruction* result = new(zone()) LCheckMaps(value); | 2059 LInstruction* result = new(zone()) LCheckMaps(value); |
| 2060 if (instr->CanOmitMapChecks()) return result; |
| 2054 return AssignEnvironment(result); | 2061 return AssignEnvironment(result); |
| 2055 } | 2062 } |
| 2056 | 2063 |
| 2057 | 2064 |
| 2058 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { | 2065 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { |
| 2059 HValue* value = instr->value(); | 2066 HValue* value = instr->value(); |
| 2060 Representation input_rep = value->representation(); | 2067 Representation input_rep = value->representation(); |
| 2061 LOperand* reg = UseRegister(value); | 2068 LOperand* reg = UseRegister(value); |
| 2062 if (input_rep.IsDouble()) { | 2069 if (input_rep.IsDouble()) { |
| 2063 return DefineAsRegister(new(zone()) LClampDToUint8(reg, FixedTemp(d11))); | 2070 return DefineAsRegister(new(zone()) LClampDToUint8(reg)); |
| 2064 } else if (input_rep.IsInteger32()) { | 2071 } else if (input_rep.IsInteger32()) { |
| 2065 return DefineAsRegister(new(zone()) LClampIToUint8(reg)); | 2072 return DefineAsRegister(new(zone()) LClampIToUint8(reg)); |
| 2066 } else { | 2073 } else { |
| 2067 ASSERT(input_rep.IsSmiOrTagged()); | 2074 ASSERT(input_rep.IsSmiOrTagged()); |
| 2068 // Register allocator doesn't (yet) support allocation of double | 2075 // Register allocator doesn't (yet) support allocation of double |
| 2069 // temps. Reserve d1 explicitly. | 2076 // temps. Reserve d1 explicitly. |
| 2070 LClampTToUint8* result = new(zone()) LClampTToUint8(reg, FixedTemp(d11)); | 2077 LClampTToUint8* result = new(zone()) LClampTToUint8(reg, FixedTemp(d11)); |
| 2071 return AssignEnvironment(DefineAsRegister(result)); | 2078 return AssignEnvironment(DefineAsRegister(result)); |
| 2072 } | 2079 } |
| 2073 } | 2080 } |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2199 | 2206 |
| 2200 | 2207 |
| 2201 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( | 2208 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( |
| 2202 HLoadExternalArrayPointer* instr) { | 2209 HLoadExternalArrayPointer* instr) { |
| 2203 LOperand* input = UseRegisterAtStart(instr->value()); | 2210 LOperand* input = UseRegisterAtStart(instr->value()); |
| 2204 return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input)); | 2211 return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input)); |
| 2205 } | 2212 } |
| 2206 | 2213 |
| 2207 | 2214 |
| 2208 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { | 2215 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { |
| 2209 ASSERT(instr->key()->representation().IsInteger32() || | 2216 ASSERT(instr->key()->representation().IsSmiOrInteger32()); |
| 2210 instr->key()->representation().IsSmi()); | |
| 2211 ElementsKind elements_kind = instr->elements_kind(); | 2217 ElementsKind elements_kind = instr->elements_kind(); |
| 2212 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); | 2218 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); |
| 2213 LLoadKeyed* result = NULL; | 2219 LLoadKeyed* result = NULL; |
| 2214 | 2220 |
| 2215 if (!instr->is_external()) { | 2221 if (!instr->is_external()) { |
| 2216 LOperand* obj = NULL; | 2222 LOperand* obj = NULL; |
| 2217 if (instr->representation().IsDouble()) { | 2223 if (instr->representation().IsDouble()) { |
| 2218 obj = UseTempRegister(instr->elements()); | 2224 obj = UseTempRegister(instr->elements()); |
| 2219 } else { | 2225 } else { |
| 2220 ASSERT(instr->representation().IsSmiOrTagged()); | 2226 ASSERT(instr->representation().IsSmiOrTagged()); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2309 return MarkAsCall(new(zone()) LStoreKeyedGeneric(obj, key, val), instr); | 2315 return MarkAsCall(new(zone()) LStoreKeyedGeneric(obj, key, val), instr); |
| 2310 } | 2316 } |
| 2311 | 2317 |
| 2312 | 2318 |
| 2313 LInstruction* LChunkBuilder::DoTransitionElementsKind( | 2319 LInstruction* LChunkBuilder::DoTransitionElementsKind( |
| 2314 HTransitionElementsKind* instr) { | 2320 HTransitionElementsKind* instr) { |
| 2315 LOperand* object = UseRegister(instr->object()); | 2321 LOperand* object = UseRegister(instr->object()); |
| 2316 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) { | 2322 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) { |
| 2317 LOperand* new_map_reg = TempRegister(); | 2323 LOperand* new_map_reg = TempRegister(); |
| 2318 LTransitionElementsKind* result = | 2324 LTransitionElementsKind* result = |
| 2319 new(zone()) LTransitionElementsKind(object, new_map_reg, NULL); | 2325 new(zone()) LTransitionElementsKind(object, new_map_reg); |
| 2320 return result; | 2326 return result; |
| 2321 } else if (FLAG_compiled_transitions) { | 2327 } else { |
| 2322 LTransitionElementsKind* result = | 2328 LTransitionElementsKind* result = |
| 2323 new(zone()) LTransitionElementsKind(object, NULL, NULL); | 2329 new(zone()) LTransitionElementsKind(object, NULL); |
| 2324 return AssignPointerMap(result); | 2330 return AssignPointerMap(result); |
| 2325 } else { | |
| 2326 LOperand* object = UseFixed(instr->object(), r0); | |
| 2327 LOperand* fixed_object_reg = FixedTemp(r2); | |
| 2328 LOperand* new_map_reg = FixedTemp(r3); | |
| 2329 LTransitionElementsKind* result = | |
| 2330 new(zone()) LTransitionElementsKind(object, | |
| 2331 new_map_reg, | |
| 2332 fixed_object_reg); | |
| 2333 return MarkAsCall(result, instr); | |
| 2334 } | 2331 } |
| 2335 } | 2332 } |
| 2336 | 2333 |
| 2337 | 2334 |
| 2338 LInstruction* LChunkBuilder::DoTrapAllocationMemento( | 2335 LInstruction* LChunkBuilder::DoTrapAllocationMemento( |
| 2339 HTrapAllocationMemento* instr) { | 2336 HTrapAllocationMemento* instr) { |
| 2340 LOperand* object = UseRegister(instr->object()); | 2337 LOperand* object = UseRegister(instr->object()); |
| 2341 LOperand* temp = TempRegister(); | 2338 LOperand* temp = TempRegister(); |
| 2342 LTrapAllocationMemento* result = | 2339 LTrapAllocationMemento* result = |
| 2343 new(zone()) LTrapAllocationMemento(object, temp); | 2340 new(zone()) LTrapAllocationMemento(object, temp); |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2640 | 2637 |
| 2641 | 2638 |
| 2642 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2639 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
| 2643 LOperand* object = UseRegister(instr->object()); | 2640 LOperand* object = UseRegister(instr->object()); |
| 2644 LOperand* index = UseRegister(instr->index()); | 2641 LOperand* index = UseRegister(instr->index()); |
| 2645 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); | 2642 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); |
| 2646 } | 2643 } |
| 2647 | 2644 |
| 2648 | 2645 |
| 2649 } } // namespace v8::internal | 2646 } } // namespace v8::internal |
| OLD | NEW |