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 |