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 692 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
703 } | 703 } |
704 | 704 |
705 | 705 |
706 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { | 706 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { |
707 return AssignEnvironment(new(zone()) LDeoptimize); | 707 return AssignEnvironment(new(zone()) LDeoptimize); |
708 } | 708 } |
709 | 709 |
710 | 710 |
711 LInstruction* LChunkBuilder::DoShift(Token::Value op, | 711 LInstruction* LChunkBuilder::DoShift(Token::Value op, |
712 HBitwiseBinaryOperation* instr) { | 712 HBitwiseBinaryOperation* instr) { |
713 if (instr->representation().IsSmiOrInteger32()) { | 713 if (instr->representation().IsTagged()) { |
714 ASSERT(instr->left()->representation().Equals(instr->representation())); | 714 ASSERT(instr->left()->representation().IsTagged()); |
715 ASSERT(instr->right()->representation().Equals(instr->representation())); | 715 ASSERT(instr->right()->representation().IsTagged()); |
716 LOperand* left = UseRegisterAtStart(instr->left()); | |
717 | 716 |
718 HValue* right_value = instr->right(); | 717 LOperand* left = UseFixed(instr->left(), r1); |
719 LOperand* right = NULL; | 718 LOperand* right = UseFixed(instr->right(), r0); |
720 int constant_value = 0; | 719 LArithmeticT* result = new(zone()) LArithmeticT(op, left, right); |
721 bool does_deopt = false; | 720 return MarkAsCall(DefineFixed(result, r0), instr); |
722 if (right_value->IsConstant()) { | 721 } |
723 HConstant* constant = HConstant::cast(right_value); | 722 |
724 right = chunk_->DefineConstantOperand(constant); | 723 ASSERT(instr->representation().IsSmiOrInteger32()); |
725 constant_value = constant->Integer32Value() & 0x1f; | 724 ASSERT(instr->left()->representation().Equals(instr->representation())); |
726 // Left shifts can deoptimize if we shift by > 0 and the result cannot be | 725 ASSERT(instr->right()->representation().Equals(instr->representation())); |
727 // truncated to smi. | 726 LOperand* left = UseRegisterAtStart(instr->left()); |
728 if (instr->representation().IsSmi() && constant_value > 0) { | 727 |
729 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi); | 728 HValue* right_value = instr->right(); |
730 } | 729 LOperand* right = NULL; |
| 730 int constant_value = 0; |
| 731 bool does_deopt = false; |
| 732 if (right_value->IsConstant()) { |
| 733 HConstant* constant = HConstant::cast(right_value); |
| 734 right = chunk_->DefineConstantOperand(constant); |
| 735 constant_value = constant->Integer32Value() & 0x1f; |
| 736 // Left shifts can deoptimize if we shift by > 0 and the result cannot be |
| 737 // truncated to smi. |
| 738 if (instr->representation().IsSmi() && constant_value > 0) { |
| 739 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToSmi); |
| 740 } |
| 741 } else { |
| 742 right = UseRegisterAtStart(right_value); |
| 743 } |
| 744 |
| 745 // Shift operations can only deoptimize if we do a logical shift |
| 746 // by 0 and the result cannot be truncated to int32. |
| 747 if (op == Token::SHR && constant_value == 0) { |
| 748 if (FLAG_opt_safe_uint32_operations) { |
| 749 does_deopt = !instr->CheckFlag(HInstruction::kUint32); |
731 } else { | 750 } else { |
732 right = UseRegisterAtStart(right_value); | 751 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32); |
733 } | 752 } |
| 753 } |
734 | 754 |
735 // Shift operations can only deoptimize if we do a logical shift | 755 LInstruction* result = |
736 // by 0 and the result cannot be truncated to int32. | 756 DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt)); |
737 if (op == Token::SHR && constant_value == 0) { | 757 return does_deopt ? AssignEnvironment(result) : result; |
738 if (FLAG_opt_safe_uint32_operations) { | |
739 does_deopt = !instr->CheckFlag(HInstruction::kUint32); | |
740 } else { | |
741 does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32); | |
742 } | |
743 } | |
744 | |
745 LInstruction* result = | |
746 DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt)); | |
747 return does_deopt ? AssignEnvironment(result) : result; | |
748 } else { | |
749 return DoArithmeticT(op, instr); | |
750 } | |
751 } | 758 } |
752 | 759 |
753 | 760 |
754 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, | 761 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, |
755 HArithmeticBinaryOperation* instr) { | 762 HArithmeticBinaryOperation* instr) { |
756 ASSERT(instr->representation().IsDouble()); | 763 ASSERT(instr->representation().IsDouble()); |
757 ASSERT(instr->left()->representation().IsDouble()); | 764 ASSERT(instr->left()->representation().IsDouble()); |
758 ASSERT(instr->right()->representation().IsDouble()); | 765 ASSERT(instr->right()->representation().IsDouble()); |
759 if (op == Token::MOD) { | 766 ASSERT(op != Token::MOD); |
760 LOperand* left = UseFixedDouble(instr->left(), d1); | 767 LOperand* left = UseRegisterAtStart(instr->left()); |
761 LOperand* right = UseFixedDouble(instr->right(), d2); | 768 LOperand* right = UseRegisterAtStart(instr->right()); |
762 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); | 769 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); |
763 // We call a C function for double modulo. It can't trigger a GC. We need | 770 return DefineAsRegister(result); |
764 // to use fixed result register for the call. | |
765 // TODO(fschneider): Allow any register as input registers. | |
766 return MarkAsCall(DefineFixedDouble(result, d1), instr); | |
767 } else { | |
768 LOperand* left = UseRegisterAtStart(instr->left()); | |
769 LOperand* right = UseRegisterAtStart(instr->right()); | |
770 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); | |
771 return DefineAsRegister(result); | |
772 } | |
773 } | 771 } |
774 | 772 |
775 | 773 |
776 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, | 774 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, |
777 HBinaryOperation* instr) { | 775 HArithmeticBinaryOperation* instr) { |
| 776 ASSERT(op == Token::ADD || |
| 777 op == Token::DIV || |
| 778 op == Token::MOD || |
| 779 op == Token::MUL || |
| 780 op == Token::SUB); |
778 HValue* left = instr->left(); | 781 HValue* left = instr->left(); |
779 HValue* right = instr->right(); | 782 HValue* right = instr->right(); |
780 ASSERT(left->representation().IsTagged()); | 783 ASSERT(left->representation().IsTagged()); |
781 ASSERT(right->representation().IsTagged()); | 784 ASSERT(right->representation().IsTagged()); |
782 LOperand* left_operand = UseFixed(left, r1); | 785 LOperand* left_operand = UseFixed(left, r1); |
783 LOperand* right_operand = UseFixed(right, r0); | 786 LOperand* right_operand = UseFixed(right, r0); |
784 LArithmeticT* result = | 787 LArithmeticT* result = |
785 new(zone()) LArithmeticT(op, left_operand, right_operand); | 788 new(zone()) LArithmeticT(op, left_operand, right_operand); |
786 return MarkAsCall(DefineFixed(result, r0), instr); | 789 return MarkAsCall(DefineFixed(result, r0), instr); |
787 } | 790 } |
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1337 | 1340 |
1338 LInstruction* LChunkBuilder::DoShl(HShl* instr) { | 1341 LInstruction* LChunkBuilder::DoShl(HShl* instr) { |
1339 return DoShift(Token::SHL, instr); | 1342 return DoShift(Token::SHL, instr); |
1340 } | 1343 } |
1341 | 1344 |
1342 | 1345 |
1343 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { | 1346 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { |
1344 if (instr->representation().IsSmiOrInteger32()) { | 1347 if (instr->representation().IsSmiOrInteger32()) { |
1345 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1348 ASSERT(instr->left()->representation().Equals(instr->representation())); |
1346 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1349 ASSERT(instr->right()->representation().Equals(instr->representation())); |
1347 ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32)); | |
1348 | 1350 |
1349 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1351 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
1350 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1352 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
1351 return DefineAsRegister(new(zone()) LBitI(left, right)); | 1353 return DefineAsRegister(new(zone()) LBitI(left, right)); |
1352 } else { | 1354 } else { |
1353 return DoArithmeticT(instr->op(), instr); | 1355 ASSERT(instr->representation().IsTagged()); |
| 1356 ASSERT(instr->left()->representation().IsTagged()); |
| 1357 ASSERT(instr->right()->representation().IsTagged()); |
| 1358 |
| 1359 LOperand* left = UseFixed(instr->left(), r1); |
| 1360 LOperand* right = UseFixed(instr->right(), r0); |
| 1361 LArithmeticT* result = new(zone()) LArithmeticT(instr->op(), left, right); |
| 1362 return MarkAsCall(DefineFixed(result, r0), instr); |
1354 } | 1363 } |
1355 } | 1364 } |
1356 | 1365 |
1357 | 1366 |
1358 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1367 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
1359 if (instr->representation().IsSmiOrInteger32()) { | 1368 if (instr->representation().IsDouble()) { |
| 1369 return DoArithmeticD(Token::DIV, instr); |
| 1370 } else if (instr->representation().IsSmiOrInteger32()) { |
1360 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1371 ASSERT(instr->left()->representation().Equals(instr->representation())); |
1361 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1372 ASSERT(instr->right()->representation().Equals(instr->representation())); |
1362 if (instr->HasPowerOf2Divisor()) { | 1373 if (instr->HasPowerOf2Divisor()) { |
1363 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); | 1374 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); |
1364 LOperand* value = UseRegisterAtStart(instr->left()); | 1375 LOperand* value = UseRegisterAtStart(instr->left()); |
1365 LDivI* div = new(zone()) LDivI(value, UseConstant(instr->right()), NULL); | 1376 LDivI* div = |
1366 return AssignEnvironment(DefineAsRegister(div)); | 1377 new(zone()) LDivI(value, UseOrConstant(instr->right()), NULL); |
| 1378 return AssignEnvironment(DefineSameAsFirst(div)); |
1367 } | 1379 } |
1368 LOperand* dividend = UseRegister(instr->left()); | 1380 LOperand* dividend = UseRegister(instr->left()); |
1369 LOperand* divisor = UseRegister(instr->right()); | 1381 LOperand* divisor = UseRegister(instr->right()); |
1370 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4); | 1382 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4); |
1371 LDivI* div = new(zone()) LDivI(dividend, divisor, temp); | 1383 LDivI* div = new(zone()) LDivI(dividend, divisor, temp); |
1372 return AssignEnvironment(DefineAsRegister(div)); | 1384 return AssignEnvironment(DefineAsRegister(div)); |
1373 } else if (instr->representation().IsDouble()) { | |
1374 return DoArithmeticD(Token::DIV, instr); | |
1375 } else { | 1385 } else { |
1376 return DoArithmeticT(Token::DIV, instr); | 1386 return DoArithmeticT(Token::DIV, instr); |
1377 } | 1387 } |
1378 } | 1388 } |
1379 | 1389 |
1380 | 1390 |
1381 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) { | 1391 bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) { |
1382 uint32_t divisor_abs = abs(divisor); | 1392 uint32_t divisor_abs = abs(divisor); |
1383 // Dividing by 0, 1, and powers of 2 is easy. | 1393 // Dividing by 0, 1, and powers of 2 is easy. |
1384 // Note that IsPowerOf2(0) returns true; | 1394 // Note that IsPowerOf2(0) returns true; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1485 FixedTemp(d10), | 1495 FixedTemp(d10), |
1486 FixedTemp(d11)); | 1496 FixedTemp(d11)); |
1487 LInstruction* result = DefineAsRegister(mod); | 1497 LInstruction* result = DefineAsRegister(mod); |
1488 return (right->CanBeZero() || | 1498 return (right->CanBeZero() || |
1489 (left->CanBeNegative() && | 1499 (left->CanBeNegative() && |
1490 instr->CanBeZero() && | 1500 instr->CanBeZero() && |
1491 instr->CheckFlag(HValue::kBailoutOnMinusZero))) | 1501 instr->CheckFlag(HValue::kBailoutOnMinusZero))) |
1492 ? AssignEnvironment(result) | 1502 ? AssignEnvironment(result) |
1493 : result; | 1503 : result; |
1494 } | 1504 } |
1495 } else if (instr->representation().IsDouble()) { | 1505 } else if (instr->representation().IsTagged()) { |
1496 return DoArithmeticD(Token::MOD, instr); | 1506 return DoArithmeticT(Token::MOD, instr); |
1497 } else { | 1507 } else { |
1498 return DoArithmeticT(Token::MOD, instr); | 1508 ASSERT(instr->representation().IsDouble()); |
| 1509 // We call a C function for double modulo. It can't trigger a GC. We need |
| 1510 // to use fixed result register for the call. |
| 1511 // TODO(fschneider): Allow any register as input registers. |
| 1512 LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD, |
| 1513 UseFixedDouble(left, d1), |
| 1514 UseFixedDouble(right, d2)); |
| 1515 return MarkAsCall(DefineFixedDouble(mod, d1), instr); |
1499 } | 1516 } |
1500 } | 1517 } |
1501 | 1518 |
1502 | 1519 |
1503 LInstruction* LChunkBuilder::DoMul(HMul* instr) { | 1520 LInstruction* LChunkBuilder::DoMul(HMul* instr) { |
1504 if (instr->representation().IsSmiOrInteger32()) { | 1521 if (instr->representation().IsSmiOrInteger32()) { |
1505 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1522 ASSERT(instr->left()->representation().Equals(instr->representation())); |
1506 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1523 ASSERT(instr->right()->representation().Equals(instr->representation())); |
1507 HValue* left = instr->BetterLeftOperand(); | 1524 HValue* left = instr->BetterLeftOperand(); |
1508 HValue* right = instr->BetterRightOperand(); | 1525 HValue* right = instr->BetterRightOperand(); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1655 return DoMultiplyAdd(HMul::cast(instr->left()), instr->right()); | 1672 return DoMultiplyAdd(HMul::cast(instr->left()), instr->right()); |
1656 } | 1673 } |
1657 | 1674 |
1658 if (instr->right()->IsMul()) { | 1675 if (instr->right()->IsMul()) { |
1659 ASSERT(!instr->left()->IsMul()); | 1676 ASSERT(!instr->left()->IsMul()); |
1660 return DoMultiplyAdd(HMul::cast(instr->right()), instr->left()); | 1677 return DoMultiplyAdd(HMul::cast(instr->right()), instr->left()); |
1661 } | 1678 } |
1662 | 1679 |
1663 return DoArithmeticD(Token::ADD, instr); | 1680 return DoArithmeticD(Token::ADD, instr); |
1664 } else { | 1681 } else { |
| 1682 ASSERT(instr->representation().IsTagged()); |
1665 return DoArithmeticT(Token::ADD, instr); | 1683 return DoArithmeticT(Token::ADD, instr); |
1666 } | 1684 } |
1667 } | 1685 } |
1668 | 1686 |
1669 | 1687 |
1670 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { | 1688 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { |
1671 LOperand* left = NULL; | 1689 LOperand* left = NULL; |
1672 LOperand* right = NULL; | 1690 LOperand* right = NULL; |
1673 if (instr->representation().IsSmiOrInteger32()) { | 1691 if (instr->representation().IsSmiOrInteger32()) { |
1674 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1692 ASSERT(instr->left()->representation().Equals(instr->representation())); |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1858 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) { | 1876 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) { |
1859 LOperand* object = UseFixed(instr->value(), r0); | 1877 LOperand* object = UseFixed(instr->value(), r0); |
1860 LDateField* result = | 1878 LDateField* result = |
1861 new(zone()) LDateField(object, FixedTemp(r1), instr->index()); | 1879 new(zone()) LDateField(object, FixedTemp(r1), instr->index()); |
1862 return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY); | 1880 return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY); |
1863 } | 1881 } |
1864 | 1882 |
1865 | 1883 |
1866 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) { | 1884 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) { |
1867 LOperand* string = UseRegister(instr->string()); | 1885 LOperand* string = UseRegister(instr->string()); |
1868 LOperand* index = UseRegisterOrConstant(instr->index()); | 1886 LOperand* index = UseRegister(instr->index()); |
1869 LOperand* value = UseRegister(instr->value()); | 1887 LOperand* value = UseTempRegister(instr->value()); |
1870 return new(zone()) LSeqStringSetChar(instr->encoding(), string, index, value); | 1888 LSeqStringSetChar* result = |
| 1889 new(zone()) LSeqStringSetChar(instr->encoding(), string, index, value); |
| 1890 return DefineAsRegister(result); |
1871 } | 1891 } |
1872 | 1892 |
1873 | 1893 |
1874 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { | 1894 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { |
1875 LOperand* value = UseRegisterOrConstantAtStart(instr->index()); | 1895 LOperand* value = UseRegisterOrConstantAtStart(instr->index()); |
1876 LOperand* length = UseRegister(instr->length()); | 1896 LOperand* length = UseRegister(instr->length()); |
1877 return AssignEnvironment(new(zone()) LBoundsCheck(value, length)); | 1897 return AssignEnvironment(new(zone()) LBoundsCheck(value, length)); |
1878 } | 1898 } |
1879 | 1899 |
1880 | 1900 |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2013 return AssignEnvironment(new(zone()) LCheckNonSmi(value)); | 2033 return AssignEnvironment(new(zone()) LCheckNonSmi(value)); |
2014 } | 2034 } |
2015 | 2035 |
2016 | 2036 |
2017 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) { | 2037 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) { |
2018 LOperand* value = UseRegisterAtStart(instr->value()); | 2038 LOperand* value = UseRegisterAtStart(instr->value()); |
2019 return AssignEnvironment(new(zone()) LCheckSmi(value)); | 2039 return AssignEnvironment(new(zone()) LCheckSmi(value)); |
2020 } | 2040 } |
2021 | 2041 |
2022 | 2042 |
| 2043 LInstruction* LChunkBuilder::DoIsNumberAndBranch(HIsNumberAndBranch* instr) { |
| 2044 return new(zone()) |
| 2045 LIsNumberAndBranch(UseRegisterOrConstantAtStart(instr->value())); |
| 2046 } |
| 2047 |
| 2048 |
2023 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { | 2049 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { |
2024 LOperand* value = UseRegisterAtStart(instr->value()); | 2050 LOperand* value = UseRegisterAtStart(instr->value()); |
2025 LInstruction* result = new(zone()) LCheckInstanceType(value); | 2051 LInstruction* result = new(zone()) LCheckInstanceType(value); |
2026 return AssignEnvironment(result); | 2052 return AssignEnvironment(result); |
2027 } | 2053 } |
2028 | 2054 |
2029 | 2055 |
2030 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) { | 2056 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) { |
2031 LOperand* value = UseRegisterAtStart(instr->value()); | 2057 LOperand* value = UseRegisterAtStart(instr->value()); |
2032 return AssignEnvironment(new(zone()) LCheckValue(value)); | 2058 return AssignEnvironment(new(zone()) LCheckValue(value)); |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2216 LOperand* object = UseFixed(instr->object(), r1); | 2242 LOperand* object = UseFixed(instr->object(), r1); |
2217 LOperand* key = UseFixed(instr->key(), r0); | 2243 LOperand* key = UseFixed(instr->key(), r0); |
2218 | 2244 |
2219 LInstruction* result = | 2245 LInstruction* result = |
2220 DefineFixed(new(zone()) LLoadKeyedGeneric(object, key), r0); | 2246 DefineFixed(new(zone()) LLoadKeyedGeneric(object, key), r0); |
2221 return MarkAsCall(result, instr); | 2247 return MarkAsCall(result, instr); |
2222 } | 2248 } |
2223 | 2249 |
2224 | 2250 |
2225 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { | 2251 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { |
| 2252 ElementsKind elements_kind = instr->elements_kind(); |
| 2253 |
2226 if (!instr->is_external()) { | 2254 if (!instr->is_external()) { |
2227 ASSERT(instr->elements()->representation().IsTagged()); | 2255 ASSERT(instr->elements()->representation().IsTagged()); |
2228 bool needs_write_barrier = instr->NeedsWriteBarrier(); | 2256 bool needs_write_barrier = instr->NeedsWriteBarrier(); |
2229 LOperand* object = NULL; | 2257 LOperand* object = NULL; |
2230 LOperand* key = NULL; | 2258 LOperand* key = NULL; |
2231 LOperand* val = NULL; | 2259 LOperand* val = NULL; |
2232 | 2260 |
2233 if (instr->value()->representation().IsDouble()) { | 2261 if (instr->value()->representation().IsDouble()) { |
2234 object = UseRegisterAtStart(instr->elements()); | 2262 object = UseRegisterAtStart(instr->elements()); |
2235 val = UseRegister(instr->value()); | 2263 val = UseTempRegister(instr->value()); |
2236 key = UseRegisterOrConstantAtStart(instr->key()); | 2264 key = UseRegisterOrConstantAtStart(instr->key()); |
2237 } else { | 2265 } else { |
2238 ASSERT(instr->value()->representation().IsSmiOrTagged()); | 2266 ASSERT(instr->value()->representation().IsSmiOrTagged()); |
2239 if (needs_write_barrier) { | 2267 object = UseTempRegister(instr->elements()); |
2240 object = UseTempRegister(instr->elements()); | 2268 val = needs_write_barrier ? UseTempRegister(instr->value()) |
2241 val = UseTempRegister(instr->value()); | 2269 : UseRegisterAtStart(instr->value()); |
2242 key = UseTempRegister(instr->key()); | 2270 key = needs_write_barrier ? UseTempRegister(instr->key()) |
2243 } else { | 2271 : UseRegisterOrConstantAtStart(instr->key()); |
2244 object = UseRegisterAtStart(instr->elements()); | |
2245 val = UseRegisterAtStart(instr->value()); | |
2246 key = UseRegisterOrConstantAtStart(instr->key()); | |
2247 } | |
2248 } | 2272 } |
2249 | 2273 |
2250 return new(zone()) LStoreKeyed(object, key, val); | 2274 return new(zone()) LStoreKeyed(object, key, val); |
2251 } | 2275 } |
2252 | 2276 |
2253 ASSERT( | 2277 ASSERT( |
2254 (instr->value()->representation().IsInteger32() && | 2278 (instr->value()->representation().IsInteger32() && |
2255 (instr->elements_kind() != EXTERNAL_FLOAT_ELEMENTS) && | 2279 (elements_kind != EXTERNAL_FLOAT_ELEMENTS) && |
2256 (instr->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS)) || | 2280 (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) || |
2257 (instr->value()->representation().IsDouble() && | 2281 (instr->value()->representation().IsDouble() && |
2258 ((instr->elements_kind() == EXTERNAL_FLOAT_ELEMENTS) || | 2282 ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || |
2259 (instr->elements_kind() == EXTERNAL_DOUBLE_ELEMENTS)))); | 2283 (elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); |
2260 ASSERT(instr->elements()->representation().IsExternal()); | 2284 ASSERT(instr->elements()->representation().IsExternal()); |
2261 LOperand* val = UseRegister(instr->value()); | 2285 bool val_is_temp_register = |
| 2286 elements_kind == EXTERNAL_PIXEL_ELEMENTS || |
| 2287 elements_kind == EXTERNAL_FLOAT_ELEMENTS; |
| 2288 LOperand* val = val_is_temp_register ? UseTempRegister(instr->value()) |
| 2289 : UseRegister(instr->value()); |
2262 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); | 2290 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); |
2263 LOperand* external_pointer = UseRegister(instr->elements()); | 2291 LOperand* external_pointer = UseRegister(instr->elements()); |
2264 return new(zone()) LStoreKeyed(external_pointer, key, val); | 2292 return new(zone()) LStoreKeyed(external_pointer, key, val); |
2265 } | 2293 } |
2266 | 2294 |
2267 | 2295 |
2268 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { | 2296 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { |
2269 LOperand* obj = UseFixed(instr->object(), r2); | 2297 LOperand* obj = UseFixed(instr->object(), r2); |
2270 LOperand* key = UseFixed(instr->key(), r1); | 2298 LOperand* key = UseFixed(instr->key(), r1); |
2271 LOperand* val = UseFixed(instr->value(), r0); | 2299 LOperand* val = UseFixed(instr->value(), r0); |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2596 | 2624 |
2597 | 2625 |
2598 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2626 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
2599 LOperand* object = UseRegister(instr->object()); | 2627 LOperand* object = UseRegister(instr->object()); |
2600 LOperand* index = UseRegister(instr->index()); | 2628 LOperand* index = UseRegister(instr->index()); |
2601 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); | 2629 return DefineAsRegister(new(zone()) LLoadFieldByIndex(object, index)); |
2602 } | 2630 } |
2603 | 2631 |
2604 | 2632 |
2605 } } // namespace v8::internal | 2633 } } // namespace v8::internal |
OLD | NEW |