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 |