| 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 697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 708 } | 708 } |
| 709 | 709 |
| 710 | 710 |
| 711 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { | 711 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { |
| 712 return AssignEnvironment(new(zone()) LDeoptimize); | 712 return AssignEnvironment(new(zone()) LDeoptimize); |
| 713 } | 713 } |
| 714 | 714 |
| 715 | 715 |
| 716 LInstruction* LChunkBuilder::DoShift(Token::Value op, | 716 LInstruction* LChunkBuilder::DoShift(Token::Value op, |
| 717 HBitwiseBinaryOperation* instr) { | 717 HBitwiseBinaryOperation* instr) { |
| 718 if (instr->representation().IsSmiOrInteger32()) { | 718 if (instr->representation().IsTagged()) { |
| 719 ASSERT(instr->left()->representation().Equals(instr->representation())); | 719 ASSERT(instr->left()->representation().IsTagged()); |
| 720 ASSERT(instr->right()->representation().Equals(instr->representation())); | 720 ASSERT(instr->right()->representation().IsTagged()); |
| 721 LOperand* left = UseRegisterAtStart(instr->left()); | |
| 722 | 721 |
| 723 HValue* right_value = instr->right(); | 722 LOperand* left = UseFixed(instr->left(), a1); |
| 724 LOperand* right = NULL; | 723 LOperand* right = UseFixed(instr->right(), a0); |
| 725 int constant_value = 0; | 724 LArithmeticT* result = new(zone()) LArithmeticT(op, left, right); |
| 726 bool does_deopt = false; | 725 return MarkAsCall(DefineFixed(result, v0), instr); |
| 727 if (right_value->IsConstant()) { | 726 } |
| 728 HConstant* constant = HConstant::cast(right_value); | 727 |
| 729 right = chunk_->DefineConstantOperand(constant); | 728 ASSERT(instr->representation().IsSmiOrInteger32()); |
| 730 constant_value = constant->Integer32Value() & 0x1f; | 729 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 731 // Left shifts can deoptimize if we shift by > 0 and the result cannot be | 730 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 732 // truncated to smi. | 731 LOperand* left = UseRegisterAtStart(instr->left()); |
| 733 if (instr->representation().IsSmi() && constant_value > 0) { | 732 |
| 734 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi); | 733 HValue* right_value = instr->right(); |
| 735 } | 734 LOperand* right = NULL; |
| 735 int constant_value = 0; |
| 736 bool does_deopt = false; |
| 737 if (right_value->IsConstant()) { |
| 738 HConstant* constant = HConstant::cast(right_value); |
| 739 right = chunk_->DefineConstantOperand(constant); |
| 740 constant_value = constant->Integer32Value() & 0x1f; |
| 741 // Left shifts can deoptimize if we shift by > 0 and the result cannot be |
| 742 // truncated to smi. |
| 743 if (instr->representation().IsSmi() && constant_value > 0) { |
| 744 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi); |
| 745 } |
| 746 } else { |
| 747 right = UseRegisterAtStart(right_value); |
| 748 } |
| 749 |
| 750 // Shift operations can deoptimize if we do a logical shift |
| 751 // by 0 and the result cannot be truncated to int32. |
| 752 if (op == Token::SHR && constant_value == 0) { |
| 753 if (FLAG_opt_safe_uint32_operations) { |
| 754 does_deopt = !instr->CheckFlag(HInstruction::kUint32); |
| 736 } else { | 755 } else { |
| 737 right = UseRegisterAtStart(right_value); | 756 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32); |
| 738 } | 757 } |
| 758 } |
| 739 | 759 |
| 740 // Shift operations can only deoptimize if we do a logical shift | 760 LInstruction* result = |
| 741 // by 0 and the result cannot be truncated to int32. | 761 DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt)); |
| 742 if (op == Token::SHR && constant_value == 0) { | 762 return does_deopt ? AssignEnvironment(result) : result; |
| 743 if (FLAG_opt_safe_uint32_operations) { | |
| 744 does_deopt = !instr->CheckFlag(HInstruction::kUint32); | |
| 745 } else { | |
| 746 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32); | |
| 747 } | |
| 748 } | |
| 749 | |
| 750 LInstruction* result = | |
| 751 DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt)); | |
| 752 return does_deopt ? AssignEnvironment(result) : result; | |
| 753 } else { | |
| 754 return DoArithmeticT(op, instr); | |
| 755 } | |
| 756 } | 763 } |
| 757 | 764 |
| 758 | 765 |
| 759 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, | 766 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, |
| 760 HArithmeticBinaryOperation* instr) { | 767 HArithmeticBinaryOperation* instr) { |
| 761 ASSERT(instr->representation().IsDouble()); | 768 ASSERT(instr->representation().IsDouble()); |
| 762 ASSERT(instr->left()->representation().IsDouble()); | 769 ASSERT(instr->left()->representation().IsDouble()); |
| 763 ASSERT(instr->right()->representation().IsDouble()); | 770 ASSERT(instr->right()->representation().IsDouble()); |
| 764 if (op == Token::MOD) { | 771 ASSERT(op != Token::MOD); |
| 765 LOperand* left = UseFixedDouble(instr->left(), f2); | 772 LOperand* left = UseRegisterAtStart(instr->left()); |
| 766 LOperand* right = UseFixedDouble(instr->right(), f4); | 773 LOperand* right = UseRegisterAtStart(instr->right()); |
| 767 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); | 774 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); |
| 768 // We call a C function for double modulo. It can't trigger a GC. We need | 775 return DefineAsRegister(result); |
| 769 // to use fixed result register for the call. | |
| 770 // TODO(fschneider): Allow any register as input registers. | |
| 771 return MarkAsCall(DefineFixedDouble(result, f2), instr); | |
| 772 } else { | |
| 773 LOperand* left = UseRegisterAtStart(instr->left()); | |
| 774 LOperand* right = UseRegisterAtStart(instr->right()); | |
| 775 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); | |
| 776 return DefineAsRegister(result); | |
| 777 } | |
| 778 } | 776 } |
| 779 | 777 |
| 780 | 778 |
| 781 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, | 779 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, |
| 782 HBinaryOperation* instr) { | 780 HArithmeticBinaryOperation* instr) { |
| 781 ASSERT(op == Token::ADD || |
| 782 op == Token::DIV || |
| 783 op == Token::MOD || |
| 784 op == Token::MUL || |
| 785 op == Token::SUB); |
| 783 HValue* left = instr->left(); | 786 HValue* left = instr->left(); |
| 784 HValue* right = instr->right(); | 787 HValue* right = instr->right(); |
| 785 ASSERT(left->representation().IsTagged()); | 788 ASSERT(left->representation().IsTagged()); |
| 786 ASSERT(right->representation().IsTagged()); | 789 ASSERT(right->representation().IsTagged()); |
| 787 LOperand* left_operand = UseFixed(left, a1); | 790 LOperand* left_operand = UseFixed(left, a1); |
| 788 LOperand* right_operand = UseFixed(right, a0); | 791 LOperand* right_operand = UseFixed(right, a0); |
| 789 LArithmeticT* result = | 792 LArithmeticT* result = |
| 790 new(zone()) LArithmeticT(op, left_operand, right_operand); | 793 new(zone()) LArithmeticT(op, left_operand, right_operand); |
| 791 return MarkAsCall(DefineFixed(result, v0), instr); | 794 return MarkAsCall(DefineFixed(result, v0), instr); |
| 792 } | 795 } |
| (...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1339 | 1342 |
| 1340 LInstruction* LChunkBuilder::DoShl(HShl* instr) { | 1343 LInstruction* LChunkBuilder::DoShl(HShl* instr) { |
| 1341 return DoShift(Token::SHL, instr); | 1344 return DoShift(Token::SHL, instr); |
| 1342 } | 1345 } |
| 1343 | 1346 |
| 1344 | 1347 |
| 1345 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { | 1348 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { |
| 1346 if (instr->representation().IsSmiOrInteger32()) { | 1349 if (instr->representation().IsSmiOrInteger32()) { |
| 1347 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1350 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1348 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1351 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1349 ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32)); | |
| 1350 | 1352 |
| 1351 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1353 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1352 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1354 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
| 1353 return DefineAsRegister(new(zone()) LBitI(left, right)); | 1355 return DefineAsRegister(new(zone()) LBitI(left, right)); |
| 1354 } else { | 1356 } else { |
| 1355 return DoArithmeticT(instr->op(), instr); | 1357 ASSERT(instr->representation().IsTagged()); |
| 1358 ASSERT(instr->left()->representation().IsTagged()); |
| 1359 ASSERT(instr->right()->representation().IsTagged()); |
| 1360 |
| 1361 LOperand* left = UseFixed(instr->left(), a1); |
| 1362 LOperand* right = UseFixed(instr->right(), a0); |
| 1363 LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right); |
| 1364 return MarkAsCall(DefineFixed(result, v0), instr); |
| 1356 } | 1365 } |
| 1357 } | 1366 } |
| 1358 | 1367 |
| 1359 | 1368 |
| 1360 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1369 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
| 1361 if (instr->representation().IsSmiOrInteger32()) { | 1370 if (instr->representation().IsDouble()) { |
| 1371 return DoArithmeticD(Token::DIV, instr); |
| 1372 } else if (instr->representation().IsSmiOrInteger32()) { |
| 1362 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1373 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1363 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1374 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1364 LOperand* dividend = UseRegister(instr->left()); | 1375 LOperand* dividend = UseRegister(instr->left()); |
| 1365 LOperand* divisor = UseRegister(instr->right()); | 1376 LOperand* divisor = UseRegister(instr->right()); |
| 1366 LDivI* div = new(zone()) LDivI(dividend, divisor); | 1377 LDivI* div = new(zone()) LDivI(dividend, divisor); |
| 1367 return AssignEnvironment(DefineAsRegister(div)); | 1378 return AssignEnvironment(DefineAsRegister(div)); |
| 1368 } else if (instr->representation().IsDouble()) { | |
| 1369 return DoArithmeticD(Token::DIV, instr); | |
| 1370 } else { | 1379 } else { |
| 1371 return DoArithmeticT(Token::DIV, instr); | 1380 return DoArithmeticT(Token::DIV, instr); |
| 1372 } | 1381 } |
| 1373 } | 1382 } |
| 1374 | 1383 |
| 1375 | 1384 |
| 1376 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) { | 1385 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) { |
| 1377 uint32_t divisor_abs = abs(divisor); | 1386 uint32_t divisor_abs = abs(divisor); |
| 1378 // Dividing by 0, 1, and powers of 2 is easy. | 1387 // Dividing by 0, 1, and powers of 2 is easy. |
| 1379 // Note that IsPowerOf2(0) returns true; | 1388 // Note that IsPowerOf2(0) returns true; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1450 FixedTemp(f20), | 1459 FixedTemp(f20), |
| 1451 FixedTemp(f22)); | 1460 FixedTemp(f22)); |
| 1452 LInstruction* result = DefineAsRegister(mod); | 1461 LInstruction* result = DefineAsRegister(mod); |
| 1453 return (right->CanBeZero() || | 1462 return (right->CanBeZero() || |
| 1454 (left->RangeCanInclude(kMinInt) && | 1463 (left->RangeCanInclude(kMinInt) && |
| 1455 right->RangeCanInclude(-1)) || | 1464 right->RangeCanInclude(-1)) || |
| 1456 instr->CheckFlag(HValue::kBailoutOnMinusZero)) | 1465 instr->CheckFlag(HValue::kBailoutOnMinusZero)) |
| 1457 ? AssignEnvironment(result) | 1466 ? AssignEnvironment(result) |
| 1458 : result; | 1467 : result; |
| 1459 } | 1468 } |
| 1460 } else if (instr->representation().IsDouble()) { | 1469 } else if (instr->representation().IsTagged()) { |
| 1461 return DoArithmeticD(Token::MOD, instr); | 1470 return DoArithmeticT(Token::MOD, instr); |
| 1462 } else { | 1471 } else { |
| 1463 return DoArithmeticT(Token::MOD, instr); | 1472 ASSERT(instr->representation().IsDouble()); |
| 1473 // We call a C function for double modulo. It can't trigger a GC. We need |
| 1474 // to use fixed result register for the call. |
| 1475 // TODO(fschneider): Allow any register as input registers. |
| 1476 LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD, |
| 1477 UseFixedDouble(left, f2), |
| 1478 UseFixedDouble(right, f4)); |
| 1479 return MarkAsCall(DefineFixedDouble(mod, f2), instr); |
| 1464 } | 1480 } |
| 1465 } | 1481 } |
| 1466 | 1482 |
| 1467 | 1483 |
| 1468 LInstruction* LChunkBuilder::DoMul(HMul* instr) { | 1484 LInstruction* LChunkBuilder::DoMul(HMul* instr) { |
| 1469 if (instr->representation().IsSmiOrInteger32()) { | 1485 if (instr->representation().IsSmiOrInteger32()) { |
| 1470 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1486 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1471 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1487 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1472 LOperand* left; | 1488 LOperand* left; |
| 1473 LOperand* right = UseOrConstant(instr->BetterRightOperand()); | 1489 LOperand* right = UseOrConstant(instr->BetterRightOperand()); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1556 if (instr->left()->IsMul()) | 1572 if (instr->left()->IsMul()) |
| 1557 return DoMultiplyAdd(HMul::cast(instr->left()), instr->right()); | 1573 return DoMultiplyAdd(HMul::cast(instr->left()), instr->right()); |
| 1558 | 1574 |
| 1559 if (instr->right()->IsMul()) { | 1575 if (instr->right()->IsMul()) { |
| 1560 ASSERT(!instr->left()->IsMul()); | 1576 ASSERT(!instr->left()->IsMul()); |
| 1561 return DoMultiplyAdd(HMul::cast(instr->right()), instr->left()); | 1577 return DoMultiplyAdd(HMul::cast(instr->right()), instr->left()); |
| 1562 } | 1578 } |
| 1563 } | 1579 } |
| 1564 return DoArithmeticD(Token::ADD, instr); | 1580 return DoArithmeticD(Token::ADD, instr); |
| 1565 } else { | 1581 } else { |
| 1582 ASSERT(instr->representation().IsTagged()); |
| 1566 return DoArithmeticT(Token::ADD, instr); | 1583 return DoArithmeticT(Token::ADD, instr); |
| 1567 } | 1584 } |
| 1568 } | 1585 } |
| 1569 | 1586 |
| 1570 | 1587 |
| 1571 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { | 1588 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { |
| 1572 LOperand* left = NULL; | 1589 LOperand* left = NULL; |
| 1573 LOperand* right = NULL; | 1590 LOperand* right = NULL; |
| 1574 if (instr->representation().IsSmiOrInteger32()) { | 1591 if (instr->representation().IsSmiOrInteger32()) { |
| 1575 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1592 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1759 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) { | 1776 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) { |
| 1760 LOperand* object = UseFixed(instr->value(), a0); | 1777 LOperand* object = UseFixed(instr->value(), a0); |
| 1761 LDateField* result = | 1778 LDateField* result = |
| 1762 new(zone()) LDateField(object, FixedTemp(a1), instr->index()); | 1779 new(zone()) LDateField(object, FixedTemp(a1), instr->index()); |
| 1763 return MarkAsCall(DefineFixed(result, v0), instr, CAN_DEOPTIMIZE_EAGERLY); | 1780 return MarkAsCall(DefineFixed(result, v0), instr, CAN_DEOPTIMIZE_EAGERLY); |
| 1764 } | 1781 } |
| 1765 | 1782 |
| 1766 | 1783 |
| 1767 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) { | 1784 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) { |
| 1768 LOperand* string = UseRegister(instr->string()); | 1785 LOperand* string = UseRegister(instr->string()); |
| 1769 LOperand* index = UseRegisterOrConstant(instr->index()); | 1786 LOperand* index = UseRegister(instr->index()); |
| 1770 LOperand* value = UseRegister(instr->value()); | 1787 LOperand* value = UseTempRegister(instr->value()); |
| 1771 return new(zone()) LSeqStringSetChar(instr->encoding(), string, index, value); | 1788 LSeqStringSetChar* result = |
| 1789 new(zone()) LSeqStringSetChar(instr->encoding(), string, index, value); |
| 1790 return DefineAsRegister(result); |
| 1772 } | 1791 } |
| 1773 | 1792 |
| 1774 | 1793 |
| 1775 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { | 1794 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { |
| 1776 LOperand* value = UseRegisterOrConstantAtStart(instr->index()); | 1795 LOperand* value = UseRegisterOrConstantAtStart(instr->index()); |
| 1777 LOperand* length = UseRegister(instr->length()); | 1796 LOperand* length = UseRegister(instr->length()); |
| 1778 return AssignEnvironment(new(zone()) LBoundsCheck(value, length)); | 1797 return AssignEnvironment(new(zone()) LBoundsCheck(value, length)); |
| 1779 } | 1798 } |
| 1780 | 1799 |
| 1781 | 1800 |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1914 return AssignEnvironment(new(zone()) LCheckNonSmi(value)); | 1933 return AssignEnvironment(new(zone()) LCheckNonSmi(value)); |
| 1915 } | 1934 } |
| 1916 | 1935 |
| 1917 | 1936 |
| 1918 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) { | 1937 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) { |
| 1919 LOperand* value = UseRegisterAtStart(instr->value()); | 1938 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1920 return AssignEnvironment(new(zone()) LCheckSmi(value)); | 1939 return AssignEnvironment(new(zone()) LCheckSmi(value)); |
| 1921 } | 1940 } |
| 1922 | 1941 |
| 1923 | 1942 |
| 1943 LInstruction* LChunkBuilder::DoIsNumberAndBranch(HIsNumberAndBranch* instr) { |
| 1944 return new(zone()) |
| 1945 LIsNumberAndBranch(UseRegisterOrConstantAtStart(instr->value())); |
| 1946 } |
| 1947 |
| 1948 |
| 1924 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { | 1949 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { |
| 1925 LOperand* value = UseRegisterAtStart(instr->value()); | 1950 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1926 LInstruction* result = new(zone()) LCheckInstanceType(value); | 1951 LInstruction* result = new(zone()) LCheckInstanceType(value); |
| 1927 return AssignEnvironment(result); | 1952 return AssignEnvironment(result); |
| 1928 } | 1953 } |
| 1929 | 1954 |
| 1930 | 1955 |
| 1931 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) { | 1956 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) { |
| 1932 LOperand* value = UseRegisterAtStart(instr->value()); | 1957 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1933 return AssignEnvironment(new(zone()) LCheckValue(value)); | 1958 return AssignEnvironment(new(zone()) LCheckValue(value)); |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2118 LOperand* object = UseFixed(instr->object(), a1); | 2143 LOperand* object = UseFixed(instr->object(), a1); |
| 2119 LOperand* key = UseFixed(instr->key(), a0); | 2144 LOperand* key = UseFixed(instr->key(), a0); |
| 2120 | 2145 |
| 2121 LInstruction* result = | 2146 LInstruction* result = |
| 2122 DefineFixed(new(zone()) LLoadKeyedGeneric(object, key), v0); | 2147 DefineFixed(new(zone()) LLoadKeyedGeneric(object, key), v0); |
| 2123 return MarkAsCall(result, instr); | 2148 return MarkAsCall(result, instr); |
| 2124 } | 2149 } |
| 2125 | 2150 |
| 2126 | 2151 |
| 2127 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { | 2152 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { |
| 2153 ElementsKind elements_kind = instr->elements_kind(); |
| 2154 |
| 2128 if (!instr->is_external()) { | 2155 if (!instr->is_external()) { |
| 2129 ASSERT(instr->elements()->representation().IsTagged()); | 2156 ASSERT(instr->elements()->representation().IsTagged()); |
| 2130 bool needs_write_barrier = instr->NeedsWriteBarrier(); | 2157 bool needs_write_barrier = instr->NeedsWriteBarrier(); |
| 2131 LOperand* object = NULL; | 2158 LOperand* object = NULL; |
| 2132 LOperand* val = NULL; | 2159 LOperand* val = NULL; |
| 2133 LOperand* key = NULL; | 2160 LOperand* key = NULL; |
| 2134 | 2161 |
| 2135 if (instr->value()->representation().IsDouble()) { | 2162 if (instr->value()->representation().IsDouble()) { |
| 2136 object = UseRegisterAtStart(instr->elements()); | 2163 object = UseRegisterAtStart(instr->elements()); |
| 2137 key = UseRegisterOrConstantAtStart(instr->key()); | 2164 key = UseRegisterOrConstantAtStart(instr->key()); |
| 2138 val = UseRegister(instr->value()); | 2165 val = UseTempRegister(instr->value()); |
| 2139 } else { | 2166 } else { |
| 2140 ASSERT(instr->value()->representation().IsSmiOrTagged()); | 2167 ASSERT(instr->value()->representation().IsSmiOrTagged()); |
| 2141 if (needs_write_barrier) { | 2168 object = UseTempRegister(instr->elements()); |
| 2142 object = UseTempRegister(instr->elements()); | 2169 val = needs_write_barrier ? UseTempRegister(instr->value()) |
| 2143 val = UseTempRegister(instr->value()); | 2170 : UseRegisterAtStart(instr->value()); |
| 2144 key = UseTempRegister(instr->key()); | 2171 key = needs_write_barrier ? UseTempRegister(instr->key()) |
| 2145 } else { | 2172 : UseRegisterOrConstantAtStart(instr->key()); |
| 2146 object = UseRegisterAtStart(instr->elements()); | |
| 2147 val = UseRegisterAtStart(instr->value()); | |
| 2148 key = UseRegisterOrConstantAtStart(instr->key()); | |
| 2149 } | |
| 2150 } | 2173 } |
| 2151 | 2174 |
| 2152 return new(zone()) LStoreKeyed(object, key, val); | 2175 return new(zone()) LStoreKeyed(object, key, val); |
| 2153 } | 2176 } |
| 2154 | 2177 |
| 2155 ASSERT( | 2178 ASSERT( |
| 2156 (instr->value()->representation().IsInteger32() && | 2179 (instr->value()->representation().IsInteger32() && |
| 2157 (instr->elements_kind() != EXTERNAL_FLOAT_ELEMENTS) && | 2180 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) && |
| 2158 (instr->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS)) || | 2181 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) || |
| 2159 (instr->value()->representation().IsDouble() && | 2182 (instr->value()->representation().IsDouble() && |
| 2160 ((instr->elements_kind() == EXTERNAL_FLOAT_ELEMENTS) || | 2183 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || |
| 2161 (instr->elements_kind() == EXTERNAL_DOUBLE_ELEMENTS)))); | 2184 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); |
| 2162 ASSERT(instr->elements()->representation().IsExternal()); | 2185 ASSERT(instr->elements()->representation().IsExternal()); |
| 2163 LOperand* val = UseRegister(instr->value()); | 2186 bool val_is_temp_register = |
| 2187 elements_kind == EXTERNAL_PIXEL_ELEMENTS || |
| 2188 elements_kind == EXTERNAL_FLOAT_ELEMENTS; |
| 2189 LOperand* val = val_is_temp_register ? UseTempRegister(instr->value()) |
| 2190 : UseRegister(instr->value()); |
| 2164 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); | 2191 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); |
| 2165 LOperand* external_pointer = UseRegister(instr->elements()); | 2192 LOperand* external_pointer = UseRegister(instr->elements()); |
| 2166 | 2193 |
| 2167 return new(zone()) LStoreKeyed(external_pointer, key, val); | 2194 return new(zone()) LStoreKeyed(external_pointer, key, val); |
| 2168 } | 2195 } |
| 2169 | 2196 |
| 2170 | 2197 |
| 2171 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { | 2198 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { |
| 2172 LOperand* obj = UseFixed(instr->object(), a2); | 2199 LOperand* obj = UseFixed(instr->object(), a2); |
| 2173 LOperand* key = UseFixed(instr->key(), a1); | 2200 LOperand* key = UseFixed(instr->key(), a1); |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2499 | 2526 |
| 2500 | 2527 |
| 2501 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2528 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
| 2502 LOperand* object = UseRegister(instr->object()); | 2529 LOperand* object = UseRegister(instr->object()); |
| 2503 LOperand* index = UseRegister(instr->index()); | 2530 LOperand* index = UseRegister(instr->index()); |
| 2504 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); | 2531 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); |
| 2505 } | 2532 } |
| 2506 | 2533 |
| 2507 | 2534 |
| 2508 } } // namespace v8::internal | 2535 } } // namespace v8::internal |
| OLD | NEW |