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 736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
747 return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value()))); | 747 return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value()))); |
748 } | 748 } |
749 | 749 |
750 | 750 |
751 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) { | 751 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) { |
752 UNREACHABLE(); | 752 UNREACHABLE(); |
753 return NULL; | 753 return NULL; |
754 } | 754 } |
755 | 755 |
756 | 756 |
757 LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) { | |
758 return AssignEnvironment(new(zone()) LDeoptimize); | |
759 } | |
760 | |
761 | |
762 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { | 757 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { |
763 return AssignEnvironment(new(zone()) LDeoptimize); | 758 return AssignEnvironment(new(zone()) LDeoptimize); |
764 } | 759 } |
765 | 760 |
766 | 761 |
767 LInstruction* LChunkBuilder::DoShift(Token::Value op, | 762 LInstruction* LChunkBuilder::DoShift(Token::Value op, |
768 HBitwiseBinaryOperation* instr) { | 763 HBitwiseBinaryOperation* instr) { |
769 if (instr->representation().IsSmiOrTagged()) { | 764 if (instr->representation().IsTagged()) { |
770 ASSERT(instr->left()->representation().IsSmiOrTagged()); | 765 ASSERT(instr->left()->representation().IsSmiOrTagged()); |
771 ASSERT(instr->right()->representation().IsSmiOrTagged()); | 766 ASSERT(instr->right()->representation().IsSmiOrTagged()); |
772 | 767 |
773 LOperand* context = UseFixed(instr->context(), esi); | 768 LOperand* context = UseFixed(instr->context(), esi); |
774 LOperand* left = UseFixed(instr->left(), edx); | 769 LOperand* left = UseFixed(instr->left(), edx); |
775 LOperand* right = UseFixed(instr->right(), eax); | 770 LOperand* right = UseFixed(instr->right(), eax); |
776 LArithmeticT* result = new(zone()) LArithmeticT(op, context, left, right); | 771 LArithmeticT* result = new(zone()) LArithmeticT(op, context, left, right); |
777 return MarkAsCall(DefineFixed(result, eax), instr); | 772 return MarkAsCall(DefineFixed(result, eax), instr); |
778 } | 773 } |
779 | 774 |
780 ASSERT(instr->representation().IsInteger32()); | 775 ASSERT(instr->representation().IsSmiOrInteger32()); |
781 ASSERT(instr->left()->representation().IsInteger32()); | 776 ASSERT(instr->left()->representation().Equals(instr->representation())); |
782 ASSERT(instr->right()->representation().IsInteger32()); | 777 ASSERT(instr->right()->representation().Equals(instr->representation())); |
783 LOperand* left = UseRegisterAtStart(instr->left()); | 778 LOperand* left = UseRegisterAtStart(instr->left()); |
784 | 779 |
785 HValue* right_value = instr->right(); | 780 HValue* right_value = instr->right(); |
786 LOperand* right = NULL; | 781 LOperand* right = NULL; |
787 int constant_value = 0; | 782 int constant_value = 0; |
| 783 bool does_deopt = false; |
788 if (right_value->IsConstant()) { | 784 if (right_value->IsConstant()) { |
789 HConstant* constant = HConstant::cast(right_value); | 785 HConstant* constant = HConstant::cast(right_value); |
790 right = chunk_->DefineConstantOperand(constant); | 786 right = chunk_->DefineConstantOperand(constant); |
791 constant_value = constant->Integer32Value() & 0x1f; | 787 constant_value = constant->Integer32Value() & 0x1f; |
| 788 // Left shifts can deoptimize if we shift by > 0 and the result cannot be |
| 789 // truncated to smi. |
| 790 if (instr->representation().IsSmi() && constant_value > 0) { |
| 791 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) { |
| 792 if (!it.value()->CheckFlag(HValue::kTruncatingToSmi)) { |
| 793 does_deopt = true; |
| 794 break; |
| 795 } |
| 796 } |
| 797 } |
792 } else { | 798 } else { |
793 right = UseFixed(right_value, ecx); | 799 right = UseFixed(right_value, ecx); |
794 } | 800 } |
795 | 801 |
796 // Shift operations can only deoptimize if we do a logical shift by 0 and | 802 // Shift operations can only deoptimize if we do a logical shift by 0 and |
797 // the result cannot be truncated to int32. | 803 // the result cannot be truncated to int32. |
798 bool does_deopt = false; | |
799 if (op == Token::SHR && constant_value == 0) { | 804 if (op == Token::SHR && constant_value == 0) { |
800 if (FLAG_opt_safe_uint32_operations) { | 805 if (FLAG_opt_safe_uint32_operations) { |
801 does_deopt = !instr->CheckFlag(HInstruction::kUint32); | 806 does_deopt = !instr->CheckFlag(HInstruction::kUint32); |
802 } else { | 807 } else { |
803 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) { | 808 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) { |
804 if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) { | 809 if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) { |
805 does_deopt = true; | 810 does_deopt = true; |
806 break; | 811 break; |
807 } | 812 } |
808 } | 813 } |
(...skipping 21 matching lines...) Expand all Loading... |
830 | 835 |
831 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, | 836 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, |
832 HArithmeticBinaryOperation* instr) { | 837 HArithmeticBinaryOperation* instr) { |
833 ASSERT(op == Token::ADD || | 838 ASSERT(op == Token::ADD || |
834 op == Token::DIV || | 839 op == Token::DIV || |
835 op == Token::MOD || | 840 op == Token::MOD || |
836 op == Token::MUL || | 841 op == Token::MUL || |
837 op == Token::SUB); | 842 op == Token::SUB); |
838 HValue* left = instr->left(); | 843 HValue* left = instr->left(); |
839 HValue* right = instr->right(); | 844 HValue* right = instr->right(); |
840 ASSERT(left->representation().IsSmiOrTagged()); | 845 ASSERT(left->representation().IsTagged()); |
841 ASSERT(right->representation().IsSmiOrTagged()); | 846 ASSERT(right->representation().IsTagged()); |
842 LOperand* context = UseFixed(instr->context(), esi); | 847 LOperand* context = UseFixed(instr->context(), esi); |
843 LOperand* left_operand = UseFixed(left, edx); | 848 LOperand* left_operand = UseFixed(left, edx); |
844 LOperand* right_operand = UseFixed(right, eax); | 849 LOperand* right_operand = UseFixed(right, eax); |
845 LArithmeticT* result = | 850 LArithmeticT* result = |
846 new(zone()) LArithmeticT(op, context, left_operand, right_operand); | 851 new(zone()) LArithmeticT(op, context, left_operand, right_operand); |
847 return MarkAsCall(DefineFixed(result, eax), instr); | 852 return MarkAsCall(DefineFixed(result, eax), instr); |
848 } | 853 } |
849 | 854 |
850 | 855 |
851 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) { | 856 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) { |
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1397 return DoShift(Token::SAR, instr); | 1402 return DoShift(Token::SAR, instr); |
1398 } | 1403 } |
1399 | 1404 |
1400 | 1405 |
1401 LInstruction* LChunkBuilder::DoShl(HShl* instr) { | 1406 LInstruction* LChunkBuilder::DoShl(HShl* instr) { |
1402 return DoShift(Token::SHL, instr); | 1407 return DoShift(Token::SHL, instr); |
1403 } | 1408 } |
1404 | 1409 |
1405 | 1410 |
1406 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { | 1411 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { |
1407 if (instr->representation().IsInteger32()) { | 1412 if (instr->representation().IsSmiOrInteger32()) { |
1408 ASSERT(instr->left()->representation().IsInteger32()); | 1413 ASSERT(instr->left()->representation().IsSmiOrInteger32()); |
1409 ASSERT(instr->right()->representation().IsInteger32()); | 1414 ASSERT(instr->right()->representation().Equals( |
| 1415 instr->left()->representation())); |
1410 | 1416 |
1411 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1417 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
1412 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1418 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
1413 return DefineSameAsFirst(new(zone()) LBitI(left, right)); | 1419 return DefineSameAsFirst(new(zone()) LBitI(left, right)); |
1414 } else { | 1420 } else { |
1415 ASSERT(instr->representation().IsSmiOrTagged()); | 1421 ASSERT(instr->representation().IsSmiOrTagged()); |
1416 ASSERT(instr->left()->representation().IsSmiOrTagged()); | 1422 ASSERT(instr->left()->representation().IsSmiOrTagged()); |
1417 ASSERT(instr->right()->representation().IsSmiOrTagged()); | 1423 ASSERT(instr->right()->representation().IsSmiOrTagged()); |
1418 | 1424 |
1419 LOperand* context = UseFixed(instr->context(), esi); | 1425 LOperand* context = UseFixed(instr->context(), esi); |
(...skipping 12 matching lines...) Expand all Loading... |
1432 if (instr->HasNoUses()) return NULL; | 1438 if (instr->HasNoUses()) return NULL; |
1433 LOperand* input = UseRegisterAtStart(instr->value()); | 1439 LOperand* input = UseRegisterAtStart(instr->value()); |
1434 LBitNotI* result = new(zone()) LBitNotI(input); | 1440 LBitNotI* result = new(zone()) LBitNotI(input); |
1435 return DefineSameAsFirst(result); | 1441 return DefineSameAsFirst(result); |
1436 } | 1442 } |
1437 | 1443 |
1438 | 1444 |
1439 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1445 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
1440 if (instr->representation().IsDouble()) { | 1446 if (instr->representation().IsDouble()) { |
1441 return DoArithmeticD(Token::DIV, instr); | 1447 return DoArithmeticD(Token::DIV, instr); |
1442 } else if (instr->representation().IsInteger32()) { | 1448 } else if (instr->representation().IsSmiOrInteger32()) { |
| 1449 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1450 ASSERT(instr->right()->representation().Equals(instr->representation())); |
1443 if (instr->HasPowerOf2Divisor()) { | 1451 if (instr->HasPowerOf2Divisor()) { |
1444 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); | 1452 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); |
1445 LOperand* value = UseRegisterAtStart(instr->left()); | 1453 LOperand* value = UseRegisterAtStart(instr->left()); |
1446 LDivI* div = | 1454 LDivI* div = |
1447 new(zone()) LDivI(value, UseOrConstant(instr->right()), NULL); | 1455 new(zone()) LDivI(value, UseOrConstant(instr->right()), NULL); |
1448 return AssignEnvironment(DefineSameAsFirst(div)); | 1456 return AssignEnvironment(DefineSameAsFirst(div)); |
1449 } | 1457 } |
1450 // The temporary operand is necessary to ensure that right is not allocated | 1458 // The temporary operand is necessary to ensure that right is not allocated |
1451 // into edx. | 1459 // into edx. |
1452 LOperand* temp = FixedTemp(edx); | 1460 LOperand* temp = FixedTemp(edx); |
1453 LOperand* dividend = UseFixed(instr->left(), eax); | 1461 LOperand* dividend = UseFixed(instr->left(), eax); |
1454 LOperand* divisor = UseRegister(instr->right()); | 1462 LOperand* divisor = UseRegister(instr->right()); |
1455 LDivI* result = new(zone()) LDivI(dividend, divisor, temp); | 1463 LDivI* result = new(zone()) LDivI(dividend, divisor, temp); |
1456 return AssignEnvironment(DefineFixed(result, eax)); | 1464 return AssignEnvironment(DefineFixed(result, eax)); |
1457 } else { | 1465 } else { |
1458 ASSERT(instr->representation().IsSmiOrTagged()); | 1466 ASSERT(instr->representation().IsTagged()); |
1459 return DoArithmeticT(Token::DIV, instr); | 1467 return DoArithmeticT(Token::DIV, instr); |
1460 } | 1468 } |
1461 } | 1469 } |
1462 | 1470 |
1463 | 1471 |
1464 HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) { | 1472 HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) { |
1465 if (divisor->IsConstant() && | 1473 if (divisor->IsConstant() && |
1466 HConstant::cast(divisor)->HasInteger32Value()) { | 1474 HConstant::cast(divisor)->HasInteger32Value()) { |
1467 HConstant* constant_val = HConstant::cast(divisor); | 1475 HConstant* constant_val = HConstant::cast(divisor); |
1468 return constant_val->CopyToRepresentation(Representation::Integer32(), | 1476 return constant_val->CopyToRepresentation(Representation::Integer32(), |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1514 LInstruction* result = DefineFixed( | 1522 LInstruction* result = DefineFixed( |
1515 new(zone()) LMathFloorOfDiv(dividend, divisor, temp), edx); | 1523 new(zone()) LMathFloorOfDiv(dividend, divisor, temp), edx); |
1516 return divisor_si < 0 ? AssignEnvironment(result) : result; | 1524 return divisor_si < 0 ? AssignEnvironment(result) : result; |
1517 } | 1525 } |
1518 } | 1526 } |
1519 | 1527 |
1520 | 1528 |
1521 LInstruction* LChunkBuilder::DoMod(HMod* instr) { | 1529 LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
1522 HValue* left = instr->left(); | 1530 HValue* left = instr->left(); |
1523 HValue* right = instr->right(); | 1531 HValue* right = instr->right(); |
1524 if (instr->representation().IsInteger32()) { | 1532 if (instr->representation().IsSmiOrInteger32()) { |
1525 ASSERT(left->representation().IsInteger32()); | 1533 ASSERT(left->representation().IsSmiOrInteger32()); |
1526 ASSERT(right->representation().IsInteger32()); | 1534 ASSERT(right->representation().Equals(left->representation())); |
| 1535 |
1527 if (instr->HasPowerOf2Divisor()) { | 1536 if (instr->HasPowerOf2Divisor()) { |
1528 ASSERT(!right->CanBeZero()); | 1537 ASSERT(!right->CanBeZero()); |
1529 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left), | 1538 LModI* mod = new(zone()) LModI(UseRegisterAtStart(left), |
1530 UseOrConstant(right), | 1539 UseOrConstant(right), |
1531 NULL); | 1540 NULL); |
1532 LInstruction* result = DefineSameAsFirst(mod); | 1541 LInstruction* result = DefineSameAsFirst(mod); |
1533 return (left->CanBeNegative() && | 1542 return (left->CanBeNegative() && |
1534 instr->CheckFlag(HValue::kBailoutOnMinusZero)) | 1543 instr->CheckFlag(HValue::kBailoutOnMinusZero)) |
1535 ? AssignEnvironment(result) | 1544 ? AssignEnvironment(result) |
1536 : result; | 1545 : result; |
(...skipping 28 matching lines...) Expand all Loading... |
1565 // TODO(fschneider): Allow any register as input registers. | 1574 // TODO(fschneider): Allow any register as input registers. |
1566 LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD, | 1575 LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD, |
1567 UseFixedDouble(left, xmm2), | 1576 UseFixedDouble(left, xmm2), |
1568 UseFixedDouble(right, xmm1)); | 1577 UseFixedDouble(right, xmm1)); |
1569 return MarkAsCall(DefineFixedDouble(mod, xmm1), instr); | 1578 return MarkAsCall(DefineFixedDouble(mod, xmm1), instr); |
1570 } | 1579 } |
1571 } | 1580 } |
1572 | 1581 |
1573 | 1582 |
1574 LInstruction* LChunkBuilder::DoMul(HMul* instr) { | 1583 LInstruction* LChunkBuilder::DoMul(HMul* instr) { |
1575 if (instr->representation().IsInteger32()) { | 1584 if (instr->representation().IsSmiOrInteger32()) { |
1576 ASSERT(instr->left()->representation().IsInteger32()); | 1585 ASSERT(instr->left()->representation().Equals(instr->representation())); |
1577 ASSERT(instr->right()->representation().IsInteger32()); | 1586 ASSERT(instr->right()->representation().Equals(instr->representation())); |
1578 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1587 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
1579 LOperand* right = UseOrConstant(instr->BetterRightOperand()); | 1588 LOperand* right = UseOrConstant(instr->BetterRightOperand()); |
1580 LOperand* temp = NULL; | 1589 LOperand* temp = NULL; |
1581 if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1590 if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1582 temp = TempRegister(); | 1591 temp = TempRegister(); |
1583 } | 1592 } |
1584 LMulI* mul = new(zone()) LMulI(left, right, temp); | 1593 LMulI* mul = new(zone()) LMulI(left, right, temp); |
1585 if (instr->CheckFlag(HValue::kCanOverflow) || | 1594 if (instr->CheckFlag(HValue::kCanOverflow) || |
1586 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1595 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1587 AssignEnvironment(mul); | 1596 AssignEnvironment(mul); |
1588 } | 1597 } |
1589 return DefineSameAsFirst(mul); | 1598 return DefineSameAsFirst(mul); |
1590 } else if (instr->representation().IsDouble()) { | 1599 } else if (instr->representation().IsDouble()) { |
1591 return DoArithmeticD(Token::MUL, instr); | 1600 return DoArithmeticD(Token::MUL, instr); |
1592 } else { | 1601 } else { |
1593 ASSERT(instr->representation().IsSmiOrTagged()); | 1602 ASSERT(instr->representation().IsTagged()); |
1594 return DoArithmeticT(Token::MUL, instr); | 1603 return DoArithmeticT(Token::MUL, instr); |
1595 } | 1604 } |
1596 } | 1605 } |
1597 | 1606 |
1598 | 1607 |
1599 LInstruction* LChunkBuilder::DoSub(HSub* instr) { | 1608 LInstruction* LChunkBuilder::DoSub(HSub* instr) { |
1600 if (instr->representation().IsInteger32()) { | 1609 if (instr->representation().IsSmiOrInteger32()) { |
1601 ASSERT(instr->left()->representation().IsInteger32()); | 1610 ASSERT(instr->left()->representation().IsSmiOrInteger32()); |
1602 ASSERT(instr->right()->representation().IsInteger32()); | 1611 ASSERT(instr->right()->representation().Equals( |
| 1612 instr->left()->representation())); |
1603 LOperand* left = UseRegisterAtStart(instr->left()); | 1613 LOperand* left = UseRegisterAtStart(instr->left()); |
1604 LOperand* right = UseOrConstantAtStart(instr->right()); | 1614 LOperand* right = UseOrConstantAtStart(instr->right()); |
1605 LSubI* sub = new(zone()) LSubI(left, right); | 1615 LSubI* sub = new(zone()) LSubI(left, right); |
1606 LInstruction* result = DefineSameAsFirst(sub); | 1616 LInstruction* result = DefineSameAsFirst(sub); |
1607 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1617 if (instr->CheckFlag(HValue::kCanOverflow)) { |
1608 result = AssignEnvironment(result); | 1618 result = AssignEnvironment(result); |
1609 } | 1619 } |
1610 return result; | 1620 return result; |
1611 } else if (instr->representation().IsDouble()) { | 1621 } else if (instr->representation().IsDouble()) { |
1612 return DoArithmeticD(Token::SUB, instr); | 1622 return DoArithmeticD(Token::SUB, instr); |
1613 } else { | 1623 } else { |
1614 ASSERT(instr->representation().IsSmiOrTagged()); | 1624 ASSERT(instr->representation().IsSmiOrTagged()); |
1615 return DoArithmeticT(Token::SUB, instr); | 1625 return DoArithmeticT(Token::SUB, instr); |
1616 } | 1626 } |
1617 } | 1627 } |
1618 | 1628 |
1619 | 1629 |
1620 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { | 1630 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { |
1621 if (instr->representation().IsInteger32()) { | 1631 if (instr->representation().IsSmiOrInteger32()) { |
| 1632 ASSERT(instr->left()->representation().IsSmiOrInteger32()); |
| 1633 ASSERT(instr->right()->representation().Equals( |
| 1634 instr->left()->representation())); |
1622 // Check to see if it would be advantageous to use an lea instruction rather | 1635 // Check to see if it would be advantageous to use an lea instruction rather |
1623 // than an add. This is the case when no overflow check is needed and there | 1636 // than an add. This is the case when no overflow check is needed and there |
1624 // are multiple uses of the add's inputs, so using a 3-register add will | 1637 // are multiple uses of the add's inputs, so using a 3-register add will |
1625 // preserve all input values for later uses. | 1638 // preserve all input values for later uses. |
1626 bool use_lea = LAddI::UseLea(instr); | 1639 bool use_lea = LAddI::UseLea(instr); |
1627 ASSERT(instr->left()->representation().IsInteger32()); | |
1628 ASSERT(instr->right()->representation().IsInteger32()); | |
1629 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1640 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
1630 HValue* right_candidate = instr->BetterRightOperand(); | 1641 HValue* right_candidate = instr->BetterRightOperand(); |
1631 LOperand* right = use_lea | 1642 LOperand* right = use_lea |
1632 ? UseRegisterOrConstantAtStart(right_candidate) | 1643 ? UseRegisterOrConstantAtStart(right_candidate) |
1633 : UseOrConstantAtStart(right_candidate); | 1644 : UseOrConstantAtStart(right_candidate); |
1634 LAddI* add = new(zone()) LAddI(left, right); | 1645 LAddI* add = new(zone()) LAddI(left, right); |
1635 bool can_overflow = instr->CheckFlag(HValue::kCanOverflow); | 1646 bool can_overflow = instr->CheckFlag(HValue::kCanOverflow); |
1636 LInstruction* result = use_lea | 1647 LInstruction* result = use_lea |
1637 ? DefineAsRegister(add) | 1648 ? DefineAsRegister(add) |
1638 : DefineSameAsFirst(add); | 1649 : DefineSameAsFirst(add); |
1639 if (can_overflow) { | 1650 if (can_overflow) { |
1640 result = AssignEnvironment(result); | 1651 result = AssignEnvironment(result); |
1641 } | 1652 } |
1642 return result; | 1653 return result; |
1643 } else if (instr->representation().IsDouble()) { | 1654 } else if (instr->representation().IsDouble()) { |
1644 return DoArithmeticD(Token::ADD, instr); | 1655 return DoArithmeticD(Token::ADD, instr); |
1645 } else { | 1656 } else { |
1646 ASSERT(instr->representation().IsSmiOrTagged()); | 1657 ASSERT(instr->representation().IsSmiOrTagged()); |
1647 return DoArithmeticT(Token::ADD, instr); | 1658 return DoArithmeticT(Token::ADD, instr); |
1648 } | 1659 } |
1649 } | 1660 } |
1650 | 1661 |
1651 | 1662 |
1652 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { | 1663 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { |
1653 LOperand* left = NULL; | 1664 LOperand* left = NULL; |
1654 LOperand* right = NULL; | 1665 LOperand* right = NULL; |
1655 if (instr->representation().IsInteger32()) { | 1666 if (instr->representation().IsSmiOrInteger32()) { |
1656 ASSERT(instr->left()->representation().IsInteger32()); | 1667 ASSERT(instr->left()->representation().IsSmiOrInteger32()); |
1657 ASSERT(instr->right()->representation().IsInteger32()); | 1668 ASSERT(instr->right()->representation().Equals( |
| 1669 instr->left()->representation())); |
1658 left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1670 left = UseRegisterAtStart(instr->BetterLeftOperand()); |
1659 right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1671 right = UseOrConstantAtStart(instr->BetterRightOperand()); |
1660 } else { | 1672 } else { |
1661 ASSERT(instr->representation().IsDouble()); | 1673 ASSERT(instr->representation().IsDouble()); |
1662 ASSERT(instr->left()->representation().IsDouble()); | 1674 ASSERT(instr->left()->representation().IsDouble()); |
1663 ASSERT(instr->right()->representation().IsDouble()); | 1675 ASSERT(instr->right()->representation().IsDouble()); |
1664 left = UseRegisterAtStart(instr->left()); | 1676 left = UseRegisterAtStart(instr->left()); |
1665 right = UseRegisterAtStart(instr->right()); | 1677 right = UseRegisterAtStart(instr->right()); |
1666 } | 1678 } |
1667 LMathMinMax* minmax = new(zone()) LMathMinMax(left, right); | 1679 LMathMinMax* minmax = new(zone()) LMathMinMax(left, right); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1734 | 1746 |
1735 | 1747 |
1736 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( | 1748 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( |
1737 HCompareObjectEqAndBranch* instr) { | 1749 HCompareObjectEqAndBranch* instr) { |
1738 LOperand* left = UseRegisterAtStart(instr->left()); | 1750 LOperand* left = UseRegisterAtStart(instr->left()); |
1739 LOperand* right = UseOrConstantAtStart(instr->right()); | 1751 LOperand* right = UseOrConstantAtStart(instr->right()); |
1740 return new(zone()) LCmpObjectEqAndBranch(left, right); | 1752 return new(zone()) LCmpObjectEqAndBranch(left, right); |
1741 } | 1753 } |
1742 | 1754 |
1743 | 1755 |
1744 LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch( | |
1745 HCompareConstantEqAndBranch* instr) { | |
1746 return new(zone()) LCmpConstantEqAndBranch( | |
1747 UseRegisterAtStart(instr->value())); | |
1748 } | |
1749 | |
1750 | |
1751 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) { | 1756 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) { |
1752 ASSERT(instr->value()->representation().IsSmiOrTagged()); | 1757 ASSERT(instr->value()->representation().IsSmiOrTagged()); |
1753 LOperand* temp = TempRegister(); | 1758 LOperand* temp = TempRegister(); |
1754 return new(zone()) LIsObjectAndBranch(UseRegister(instr->value()), temp); | 1759 return new(zone()) LIsObjectAndBranch(UseRegister(instr->value()), temp); |
1755 } | 1760 } |
1756 | 1761 |
1757 | 1762 |
1758 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) { | 1763 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) { |
1759 ASSERT(instr->value()->representation().IsTagged()); | 1764 ASSERT(instr->value()->representation().IsTagged()); |
1760 LOperand* temp = TempRegister(); | 1765 LOperand* temp = TempRegister(); |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2056 | 2061 |
2057 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { | 2062 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { |
2058 LOperand* value = UseRegisterAtStart(instr->value()); | 2063 LOperand* value = UseRegisterAtStart(instr->value()); |
2059 LOperand* temp = TempRegister(); | 2064 LOperand* temp = TempRegister(); |
2060 LCheckInstanceType* result = new(zone()) LCheckInstanceType(value, temp); | 2065 LCheckInstanceType* result = new(zone()) LCheckInstanceType(value, temp); |
2061 return AssignEnvironment(result); | 2066 return AssignEnvironment(result); |
2062 } | 2067 } |
2063 | 2068 |
2064 | 2069 |
2065 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) { | 2070 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) { |
2066 LUnallocated* temp = TempRegister(); | 2071 LUnallocated* temp = NULL; |
| 2072 if (!instr->CanOmitPrototypeChecks()) temp = TempRegister(); |
2067 LCheckPrototypeMaps* result = new(zone()) LCheckPrototypeMaps(temp); | 2073 LCheckPrototypeMaps* result = new(zone()) LCheckPrototypeMaps(temp); |
| 2074 if (instr->CanOmitPrototypeChecks()) return result; |
2068 return AssignEnvironment(result); | 2075 return AssignEnvironment(result); |
2069 } | 2076 } |
2070 | 2077 |
2071 | 2078 |
2072 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) { | 2079 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) { |
2073 // If the target is in new space, we'll emit a global cell compare and so | 2080 // If the target is in new space, we'll emit a global cell compare and so |
2074 // want the value in a register. If the target gets promoted before we | 2081 // want the value in a register. If the target gets promoted before we |
2075 // emit code, we will still get the register but will do an immediate | 2082 // emit code, we will still get the register but will do an immediate |
2076 // compare instead of the cell compare. This is safe. | 2083 // compare instead of the cell compare. This is safe. |
2077 LOperand* value = instr->target_in_new_space() | 2084 LOperand* value = instr->target_in_new_space() |
2078 ? UseRegisterAtStart(instr->value()) : UseAtStart(instr->value()); | 2085 ? UseRegisterAtStart(instr->value()) : UseAtStart(instr->value()); |
2079 return AssignEnvironment(new(zone()) LCheckFunction(value)); | 2086 return AssignEnvironment(new(zone()) LCheckFunction(value)); |
2080 } | 2087 } |
2081 | 2088 |
2082 | 2089 |
2083 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { | 2090 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { |
2084 LOperand* value = UseRegisterAtStart(instr->value()); | 2091 LOperand* value = NULL; |
| 2092 if (!instr->CanOmitMapChecks()) value = UseRegisterAtStart(instr->value()); |
2085 LCheckMaps* result = new(zone()) LCheckMaps(value); | 2093 LCheckMaps* result = new(zone()) LCheckMaps(value); |
| 2094 if (instr->CanOmitMapChecks()) return result; |
2086 return AssignEnvironment(result); | 2095 return AssignEnvironment(result); |
2087 } | 2096 } |
2088 | 2097 |
2089 | 2098 |
2090 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { | 2099 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { |
2091 HValue* value = instr->value(); | 2100 HValue* value = instr->value(); |
2092 Representation input_rep = value->representation(); | 2101 Representation input_rep = value->representation(); |
2093 if (input_rep.IsDouble()) { | 2102 if (input_rep.IsDouble()) { |
2094 LOperand* reg = UseRegister(value); | 2103 LOperand* reg = UseRegister(value); |
2095 return DefineFixed(new(zone()) LClampDToUint8(reg), eax); | 2104 return DefineFixed(new(zone()) LClampDToUint8(reg), eax); |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2254 | 2263 |
2255 | 2264 |
2256 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( | 2265 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer( |
2257 HLoadExternalArrayPointer* instr) { | 2266 HLoadExternalArrayPointer* instr) { |
2258 LOperand* input = UseRegisterAtStart(instr->value()); | 2267 LOperand* input = UseRegisterAtStart(instr->value()); |
2259 return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input)); | 2268 return DefineAsRegister(new(zone()) LLoadExternalArrayPointer(input)); |
2260 } | 2269 } |
2261 | 2270 |
2262 | 2271 |
2263 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { | 2272 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { |
2264 ASSERT(instr->key()->representation().IsInteger32() || | 2273 ASSERT(instr->key()->representation().IsSmiOrInteger32()); |
2265 instr->key()->representation().IsSmi()); | |
2266 ElementsKind elements_kind = instr->elements_kind(); | 2274 ElementsKind elements_kind = instr->elements_kind(); |
2267 bool clobbers_key = ExternalArrayOpRequiresTemp( | 2275 bool clobbers_key = ExternalArrayOpRequiresTemp( |
2268 instr->key()->representation(), elements_kind); | 2276 instr->key()->representation(), elements_kind); |
2269 LOperand* key = clobbers_key | 2277 LOperand* key = clobbers_key |
2270 ? UseTempRegister(instr->key()) | 2278 ? UseTempRegister(instr->key()) |
2271 : UseRegisterOrConstantAtStart(instr->key()); | 2279 : UseRegisterOrConstantAtStart(instr->key()); |
2272 LLoadKeyed* result = NULL; | 2280 LLoadKeyed* result = NULL; |
2273 | 2281 |
2274 if (!instr->is_external()) { | 2282 if (!instr->is_external()) { |
2275 LOperand* obj = UseRegisterAtStart(instr->elements()); | 2283 LOperand* obj = UseRegisterAtStart(instr->elements()); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2400 HTransitionElementsKind* instr) { | 2408 HTransitionElementsKind* instr) { |
2401 LOperand* object = UseRegister(instr->object()); | 2409 LOperand* object = UseRegister(instr->object()); |
2402 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) { | 2410 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) { |
2403 LOperand* object = UseRegister(instr->object()); | 2411 LOperand* object = UseRegister(instr->object()); |
2404 LOperand* new_map_reg = TempRegister(); | 2412 LOperand* new_map_reg = TempRegister(); |
2405 LOperand* temp_reg = TempRegister(); | 2413 LOperand* temp_reg = TempRegister(); |
2406 LTransitionElementsKind* result = | 2414 LTransitionElementsKind* result = |
2407 new(zone()) LTransitionElementsKind(object, NULL, | 2415 new(zone()) LTransitionElementsKind(object, NULL, |
2408 new_map_reg, temp_reg); | 2416 new_map_reg, temp_reg); |
2409 return result; | 2417 return result; |
2410 } else if (FLAG_compiled_transitions) { | 2418 } else { |
2411 LOperand* context = UseRegister(instr->context()); | 2419 LOperand* context = UseRegister(instr->context()); |
2412 LTransitionElementsKind* result = | 2420 LTransitionElementsKind* result = |
2413 new(zone()) LTransitionElementsKind(object, context, NULL, NULL); | 2421 new(zone()) LTransitionElementsKind(object, context, NULL, NULL); |
2414 return AssignPointerMap(result); | 2422 return AssignPointerMap(result); |
2415 } else { | |
2416 LOperand* object = UseFixed(instr->object(), eax); | |
2417 LOperand* fixed_object_reg = FixedTemp(edx); | |
2418 LOperand* new_map_reg = FixedTemp(ebx); | |
2419 LTransitionElementsKind* result = | |
2420 new(zone()) LTransitionElementsKind(object, | |
2421 NULL, | |
2422 new_map_reg, | |
2423 fixed_object_reg); | |
2424 return MarkAsCall(result, instr); | |
2425 } | 2423 } |
2426 } | 2424 } |
2427 | 2425 |
2428 | 2426 |
2429 LInstruction* LChunkBuilder::DoTrapAllocationMemento( | 2427 LInstruction* LChunkBuilder::DoTrapAllocationMemento( |
2430 HTrapAllocationMemento* instr) { | 2428 HTrapAllocationMemento* instr) { |
2431 LOperand* object = UseRegister(instr->object()); | 2429 LOperand* object = UseRegister(instr->object()); |
2432 LOperand* temp = TempRegister(); | 2430 LOperand* temp = TempRegister(); |
2433 LTrapAllocationMemento* result = | 2431 LTrapAllocationMemento* result = |
2434 new(zone()) LTrapAllocationMemento(object, temp); | 2432 new(zone()) LTrapAllocationMemento(object, temp); |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2767 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2765 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
2768 LOperand* object = UseRegister(instr->object()); | 2766 LOperand* object = UseRegister(instr->object()); |
2769 LOperand* index = UseTempRegister(instr->index()); | 2767 LOperand* index = UseTempRegister(instr->index()); |
2770 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index)); | 2768 return DefineSameAsFirst(new(zone()) LLoadFieldByIndex(object, index)); |
2771 } | 2769 } |
2772 | 2770 |
2773 | 2771 |
2774 } } // namespace v8::internal | 2772 } } // namespace v8::internal |
2775 | 2773 |
2776 #endif // V8_TARGET_ARCH_IA32 | 2774 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |