| 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 921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 932 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { | 932 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { |
| 933 return new(zone()) LGoto(instr->FirstSuccessor()); | 933 return new(zone()) LGoto(instr->FirstSuccessor()); |
| 934 } | 934 } |
| 935 | 935 |
| 936 | 936 |
| 937 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { | 937 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { |
| 938 LInstruction* goto_instr = CheckElideControlInstruction(instr); | 938 LInstruction* goto_instr = CheckElideControlInstruction(instr); |
| 939 if (goto_instr != NULL) return goto_instr; | 939 if (goto_instr != NULL) return goto_instr; |
| 940 | 940 |
| 941 HValue* value = instr->value(); | 941 HValue* value = instr->value(); |
| 942 LBranch* result = new(zone()) LBranch(UseRegister(value)); | 942 Representation r = value->representation(); |
| 943 // Tagged values that are not known smis or booleans require a | |
| 944 // deoptimization environment. If the instruction is generic no | |
| 945 // environment is needed since all cases are handled. | |
| 946 Representation rep = value->representation(); | |
| 947 HType type = value->type(); | 943 HType type = value->type(); |
| 948 ToBooleanStub::Types expected = instr->expected_input_types(); | 944 ToBooleanStub::Types expected = instr->expected_input_types(); |
| 949 if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean() && | 945 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); |
| 950 !expected.IsGeneric()) { | 946 |
| 951 return AssignEnvironment(result); | 947 bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() || |
| 948 type.IsJSArray() || type.IsHeapNumber() || type.IsString(); |
| 949 LInstruction* branch = new(zone()) LBranch(UseRegister(value)); |
| 950 if (!easy_case && |
| 951 ((!expected.Contains(ToBooleanStub::SMI) && expected.NeedsMap()) || |
| 952 !expected.IsGeneric())) { |
| 953 branch = AssignEnvironment(branch); |
| 952 } | 954 } |
| 953 return result; | 955 return branch; |
| 954 } | 956 } |
| 955 | 957 |
| 956 | 958 |
| 957 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { | 959 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { |
| 958 LInstruction* goto_instr = CheckElideControlInstruction(instr); | 960 LInstruction* goto_instr = CheckElideControlInstruction(instr); |
| 959 if (goto_instr != NULL) return goto_instr; | 961 if (goto_instr != NULL) return goto_instr; |
| 960 | 962 |
| 961 ASSERT(instr->value()->representation().IsTagged()); | 963 ASSERT(instr->value()->representation().IsTagged()); |
| 962 LOperand* value = UseRegisterAtStart(instr->value()); | 964 LOperand* value = UseRegisterAtStart(instr->value()); |
| 963 LOperand* temp = TempRegister(); | 965 LOperand* temp = TempRegister(); |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 return DefineFixedDouble(result, f4); | 1157 return DefineFixedDouble(result, f4); |
| 1156 } | 1158 } |
| 1157 | 1159 |
| 1158 | 1160 |
| 1159 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) { | 1161 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) { |
| 1160 Representation r = instr->value()->representation(); | 1162 Representation r = instr->value()->representation(); |
| 1161 LOperand* context = (r.IsDouble() || r.IsSmiOrInteger32()) | 1163 LOperand* context = (r.IsDouble() || r.IsSmiOrInteger32()) |
| 1162 ? NULL | 1164 ? NULL |
| 1163 : UseFixed(instr->context(), cp); | 1165 : UseFixed(instr->context(), cp); |
| 1164 LOperand* input = UseRegister(instr->value()); | 1166 LOperand* input = UseRegister(instr->value()); |
| 1165 LMathAbs* result = new(zone()) LMathAbs(context, input); | 1167 LInstruction* result = |
| 1166 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); | 1168 DefineAsRegister(new(zone()) LMathAbs(context, input)); |
| 1169 if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result); |
| 1170 if (!r.IsDouble()) result = AssignEnvironment(result); |
| 1171 return result; |
| 1167 } | 1172 } |
| 1168 | 1173 |
| 1169 | 1174 |
| 1170 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) { | 1175 LInstruction* LChunkBuilder::DoMathFloor(HUnaryMathOperation* instr) { |
| 1171 LOperand* input = UseRegister(instr->value()); | 1176 LOperand* input = UseRegister(instr->value()); |
| 1172 LOperand* temp = TempRegister(); | 1177 LOperand* temp = TempRegister(); |
| 1173 LMathFloor* result = new(zone()) LMathFloor(input, temp); | 1178 LMathFloor* result = new(zone()) LMathFloor(input, temp); |
| 1174 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); | 1179 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); |
| 1175 } | 1180 } |
| 1176 | 1181 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1289 return result; | 1294 return result; |
| 1290 } | 1295 } |
| 1291 | 1296 |
| 1292 | 1297 |
| 1293 LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) { | 1298 LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) { |
| 1294 ASSERT(instr->representation().IsSmiOrInteger32()); | 1299 ASSERT(instr->representation().IsSmiOrInteger32()); |
| 1295 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1300 ASSERT(instr->left()->representation().Equals(instr->representation())); |
| 1296 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1301 ASSERT(instr->right()->representation().Equals(instr->representation())); |
| 1297 LOperand* dividend = UseRegister(instr->left()); | 1302 LOperand* dividend = UseRegister(instr->left()); |
| 1298 LOperand* divisor = UseRegister(instr->right()); | 1303 LOperand* divisor = UseRegister(instr->right()); |
| 1299 LDivI* div = new(zone()) LDivI(dividend, divisor); | 1304 LInstruction* result = |
| 1300 return AssignEnvironment(DefineAsRegister(div)); | 1305 DefineAsRegister(new(zone()) LDivI(dividend, divisor)); |
| 1306 if (instr->CheckFlag(HValue::kCanBeDivByZero) || |
| 1307 instr->CheckFlag(HValue::kBailoutOnMinusZero) || |
| 1308 (instr->CheckFlag(HValue::kCanOverflow) && |
| 1309 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32)) || |
| 1310 (!instr->IsMathFloorOfDiv() && |
| 1311 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { |
| 1312 result = AssignEnvironment(result); |
| 1313 } |
| 1314 return result; |
| 1301 } | 1315 } |
| 1302 | 1316 |
| 1303 | 1317 |
| 1304 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1318 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
| 1305 if (instr->representation().IsSmiOrInteger32()) { | 1319 if (instr->representation().IsSmiOrInteger32()) { |
| 1306 if (instr->RightIsPowerOf2()) { | 1320 if (instr->RightIsPowerOf2()) { |
| 1307 return DoDivByPowerOf2I(instr); | 1321 return DoDivByPowerOf2I(instr); |
| 1308 } else if (instr->right()->IsConstant()) { | 1322 } else if (instr->right()->IsConstant()) { |
| 1309 return DoDivByConstI(instr); | 1323 return DoDivByConstI(instr); |
| 1310 } else { | 1324 } else { |
| (...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1782 // All HForceRepresentation instructions should be eliminated in the | 1796 // All HForceRepresentation instructions should be eliminated in the |
| 1783 // representation change phase of Hydrogen. | 1797 // representation change phase of Hydrogen. |
| 1784 UNREACHABLE(); | 1798 UNREACHABLE(); |
| 1785 return NULL; | 1799 return NULL; |
| 1786 } | 1800 } |
| 1787 | 1801 |
| 1788 | 1802 |
| 1789 LInstruction* LChunkBuilder::DoChange(HChange* instr) { | 1803 LInstruction* LChunkBuilder::DoChange(HChange* instr) { |
| 1790 Representation from = instr->from(); | 1804 Representation from = instr->from(); |
| 1791 Representation to = instr->to(); | 1805 Representation to = instr->to(); |
| 1806 HValue* val = instr->value(); |
| 1792 if (from.IsSmi()) { | 1807 if (from.IsSmi()) { |
| 1793 if (to.IsTagged()) { | 1808 if (to.IsTagged()) { |
| 1794 LOperand* value = UseRegister(instr->value()); | 1809 LOperand* value = UseRegister(val); |
| 1795 return DefineSameAsFirst(new(zone()) LDummyUse(value)); | 1810 return DefineSameAsFirst(new(zone()) LDummyUse(value)); |
| 1796 } | 1811 } |
| 1797 from = Representation::Tagged(); | 1812 from = Representation::Tagged(); |
| 1798 } | 1813 } |
| 1799 if (from.IsTagged()) { | 1814 if (from.IsTagged()) { |
| 1800 if (to.IsDouble()) { | 1815 if (to.IsDouble()) { |
| 1801 LOperand* value = UseRegister(instr->value()); | 1816 LOperand* value = UseRegister(val); |
| 1802 LNumberUntagD* res = new(zone()) LNumberUntagD(value); | 1817 LInstruction* result = DefineAsRegister(new(zone()) LNumberUntagD(value)); |
| 1803 return AssignEnvironment(DefineAsRegister(res)); | 1818 if (!val->representation().IsSmi()) result = AssignEnvironment(result); |
| 1819 return result; |
| 1804 } else if (to.IsSmi()) { | 1820 } else if (to.IsSmi()) { |
| 1805 HValue* val = instr->value(); | |
| 1806 LOperand* value = UseRegister(val); | 1821 LOperand* value = UseRegister(val); |
| 1807 if (val->type().IsSmi()) { | 1822 if (val->type().IsSmi()) { |
| 1808 return DefineSameAsFirst(new(zone()) LDummyUse(value)); | 1823 return DefineSameAsFirst(new(zone()) LDummyUse(value)); |
| 1809 } | 1824 } |
| 1810 return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value))); | 1825 return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value))); |
| 1811 } else { | 1826 } else { |
| 1812 ASSERT(to.IsInteger32()); | 1827 ASSERT(to.IsInteger32()); |
| 1813 LOperand* value = NULL; | |
| 1814 LInstruction* res = NULL; | |
| 1815 HValue* val = instr->value(); | |
| 1816 if (val->type().IsSmi() || val->representation().IsSmi()) { | 1828 if (val->type().IsSmi() || val->representation().IsSmi()) { |
| 1817 value = UseRegisterAtStart(val); | 1829 LOperand* value = UseRegisterAtStart(val); |
| 1818 res = DefineAsRegister(new(zone()) LSmiUntag(value, false)); | 1830 return DefineAsRegister(new(zone()) LSmiUntag(value, false)); |
| 1819 } else { | 1831 } else { |
| 1820 value = UseRegister(val); | 1832 LOperand* value = UseRegister(val); |
| 1821 LOperand* temp1 = TempRegister(); | 1833 LOperand* temp1 = TempRegister(); |
| 1822 LOperand* temp2 = FixedTemp(f22); | 1834 LOperand* temp2 = FixedTemp(f22); |
| 1823 res = DefineSameAsFirst(new(zone()) LTaggedToI(value, | 1835 LInstruction* result = |
| 1824 temp1, | 1836 DefineSameAsFirst(new(zone()) LTaggedToI(value, temp1, temp2)); |
| 1825 temp2)); | 1837 if (!val->representation().IsSmi()) { |
| 1826 res = AssignEnvironment(res); | 1838 // Note: Only deopts in deferred code. |
| 1839 result = AssignEnvironment(result); |
| 1840 } |
| 1841 return result; |
| 1827 } | 1842 } |
| 1828 return res; | |
| 1829 } | 1843 } |
| 1830 } else if (from.IsDouble()) { | 1844 } else if (from.IsDouble()) { |
| 1831 if (to.IsTagged()) { | 1845 if (to.IsTagged()) { |
| 1832 info()->MarkAsDeferredCalling(); | 1846 info()->MarkAsDeferredCalling(); |
| 1833 LOperand* value = UseRegister(instr->value()); | 1847 LOperand* value = UseRegister(val); |
| 1834 LOperand* temp1 = TempRegister(); | 1848 LOperand* temp1 = TempRegister(); |
| 1835 LOperand* temp2 = TempRegister(); | 1849 LOperand* temp2 = TempRegister(); |
| 1836 | |
| 1837 // Make sure that the temp and result_temp registers are | |
| 1838 // different. | |
| 1839 LUnallocated* result_temp = TempRegister(); | 1850 LUnallocated* result_temp = TempRegister(); |
| 1840 LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2); | 1851 LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2); |
| 1841 Define(result, result_temp); | 1852 return AssignPointerMap(Define(result, result_temp)); |
| 1842 return AssignPointerMap(result); | |
| 1843 } else if (to.IsSmi()) { | 1853 } else if (to.IsSmi()) { |
| 1844 LOperand* value = UseRegister(instr->value()); | 1854 LOperand* value = UseRegister(val); |
| 1845 return AssignEnvironment( | 1855 return AssignEnvironment( |
| 1846 DefineAsRegister(new(zone()) LDoubleToSmi(value))); | 1856 DefineAsRegister(new(zone()) LDoubleToSmi(value))); |
| 1847 } else { | 1857 } else { |
| 1848 ASSERT(to.IsInteger32()); | 1858 ASSERT(to.IsInteger32()); |
| 1849 LOperand* value = UseRegister(instr->value()); | 1859 LOperand* value = UseRegister(val); |
| 1850 LDoubleToI* res = new(zone()) LDoubleToI(value); | 1860 LInstruction* result = DefineAsRegister(new(zone()) LDoubleToI(value)); |
| 1851 return AssignEnvironment(DefineAsRegister(res)); | 1861 if (!instr->CanTruncateToInt32()) result = AssignEnvironment(result); |
| 1862 return result; |
| 1852 } | 1863 } |
| 1853 } else if (from.IsInteger32()) { | 1864 } else if (from.IsInteger32()) { |
| 1854 info()->MarkAsDeferredCalling(); | 1865 info()->MarkAsDeferredCalling(); |
| 1855 if (to.IsTagged()) { | 1866 if (to.IsTagged()) { |
| 1856 HValue* val = instr->value(); | |
| 1857 LOperand* value = UseRegisterAtStart(val); | |
| 1858 if (!instr->CheckFlag(HValue::kCanOverflow)) { | 1867 if (!instr->CheckFlag(HValue::kCanOverflow)) { |
| 1868 LOperand* value = UseRegisterAtStart(val); |
| 1859 return DefineAsRegister(new(zone()) LSmiTag(value)); | 1869 return DefineAsRegister(new(zone()) LSmiTag(value)); |
| 1860 } else if (val->CheckFlag(HInstruction::kUint32)) { | 1870 } else if (val->CheckFlag(HInstruction::kUint32)) { |
| 1871 LOperand* value = UseRegisterAtStart(val); |
| 1861 LOperand* temp1 = TempRegister(); | 1872 LOperand* temp1 = TempRegister(); |
| 1862 LOperand* temp2 = TempRegister(); | 1873 LOperand* temp2 = TempRegister(); |
| 1863 LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2); | 1874 LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2); |
| 1864 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); | 1875 return AssignPointerMap(DefineAsRegister(result)); |
| 1865 } else { | 1876 } else { |
| 1877 LOperand* value = UseRegisterAtStart(val); |
| 1866 LOperand* temp1 = TempRegister(); | 1878 LOperand* temp1 = TempRegister(); |
| 1867 LOperand* temp2 = TempRegister(); | 1879 LOperand* temp2 = TempRegister(); |
| 1868 LNumberTagI* result = new(zone()) LNumberTagI(value, temp1, temp2); | 1880 LNumberTagI* result = new(zone()) LNumberTagI(value, temp1, temp2); |
| 1869 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); | 1881 return AssignPointerMap(DefineAsRegister(result)); |
| 1870 } | 1882 } |
| 1871 } else if (to.IsSmi()) { | 1883 } else if (to.IsSmi()) { |
| 1872 HValue* val = instr->value(); | |
| 1873 LOperand* value = UseRegister(val); | 1884 LOperand* value = UseRegister(val); |
| 1874 LInstruction* result = DefineAsRegister(new(zone()) LSmiTag(value)); | 1885 LInstruction* result = DefineAsRegister(new(zone()) LSmiTag(value)); |
| 1875 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1886 if (instr->CheckFlag(HValue::kCanOverflow)) { |
| 1876 result = AssignEnvironment(result); | 1887 result = AssignEnvironment(result); |
| 1877 } | 1888 } |
| 1878 return result; | 1889 return result; |
| 1879 } else { | 1890 } else { |
| 1880 ASSERT(to.IsDouble()); | 1891 ASSERT(to.IsDouble()); |
| 1881 if (instr->value()->CheckFlag(HInstruction::kUint32)) { | 1892 if (val->CheckFlag(HInstruction::kUint32)) { |
| 1882 return DefineAsRegister( | 1893 return DefineAsRegister(new(zone()) LUint32ToDouble(UseRegister(val))); |
| 1883 new(zone()) LUint32ToDouble(UseRegister(instr->value()))); | |
| 1884 } else { | 1894 } else { |
| 1885 return DefineAsRegister( | 1895 return DefineAsRegister(new(zone()) LInteger32ToDouble(Use(val))); |
| 1886 new(zone()) LInteger32ToDouble(Use(instr->value()))); | |
| 1887 } | 1896 } |
| 1888 } | 1897 } |
| 1889 } | 1898 } |
| 1890 UNREACHABLE(); | 1899 UNREACHABLE(); |
| 1891 return NULL; | 1900 return NULL; |
| 1892 } | 1901 } |
| 1893 | 1902 |
| 1894 | 1903 |
| 1895 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) { | 1904 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) { |
| 1896 LOperand* value = UseRegisterAtStart(instr->value()); | 1905 LOperand* value = UseRegisterAtStart(instr->value()); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1918 | 1927 |
| 1919 | 1928 |
| 1920 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { | 1929 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { |
| 1921 LOperand* value = NULL; | 1930 LOperand* value = NULL; |
| 1922 if (!instr->CanOmitMapChecks()) { | 1931 if (!instr->CanOmitMapChecks()) { |
| 1923 value = UseRegisterAtStart(instr->value()); | 1932 value = UseRegisterAtStart(instr->value()); |
| 1924 if (instr->has_migration_target()) info()->MarkAsDeferredCalling(); | 1933 if (instr->has_migration_target()) info()->MarkAsDeferredCalling(); |
| 1925 } | 1934 } |
| 1926 LCheckMaps* result = new(zone()) LCheckMaps(value); | 1935 LCheckMaps* result = new(zone()) LCheckMaps(value); |
| 1927 if (!instr->CanOmitMapChecks()) { | 1936 if (!instr->CanOmitMapChecks()) { |
| 1937 // Note: Only deopts in deferred code. |
| 1928 AssignEnvironment(result); | 1938 AssignEnvironment(result); |
| 1929 if (instr->has_migration_target()) return AssignPointerMap(result); | 1939 if (instr->has_migration_target()) return AssignPointerMap(result); |
| 1930 } | 1940 } |
| 1931 return result; | 1941 return result; |
| 1932 } | 1942 } |
| 1933 | 1943 |
| 1934 | 1944 |
| 1935 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { | 1945 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { |
| 1936 HValue* value = instr->value(); | 1946 HValue* value = instr->value(); |
| 1937 Representation input_rep = value->representation(); | 1947 Representation input_rep = value->representation(); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2018 return instr->RequiresHoleCheck() | 2028 return instr->RequiresHoleCheck() |
| 2019 ? AssignEnvironment(new(zone()) LStoreGlobalCell(value, TempRegister())) | 2029 ? AssignEnvironment(new(zone()) LStoreGlobalCell(value, TempRegister())) |
| 2020 : new(zone()) LStoreGlobalCell(value, NULL); | 2030 : new(zone()) LStoreGlobalCell(value, NULL); |
| 2021 } | 2031 } |
| 2022 | 2032 |
| 2023 | 2033 |
| 2024 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { | 2034 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { |
| 2025 LOperand* context = UseRegisterAtStart(instr->value()); | 2035 LOperand* context = UseRegisterAtStart(instr->value()); |
| 2026 LInstruction* result = | 2036 LInstruction* result = |
| 2027 DefineAsRegister(new(zone()) LLoadContextSlot(context)); | 2037 DefineAsRegister(new(zone()) LLoadContextSlot(context)); |
| 2028 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; | 2038 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { |
| 2039 result = AssignEnvironment(result); |
| 2040 } |
| 2041 return result; |
| 2029 } | 2042 } |
| 2030 | 2043 |
| 2031 | 2044 |
| 2032 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { | 2045 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { |
| 2033 LOperand* context; | 2046 LOperand* context; |
| 2034 LOperand* value; | 2047 LOperand* value; |
| 2035 if (instr->NeedsWriteBarrier()) { | 2048 if (instr->NeedsWriteBarrier()) { |
| 2036 context = UseTempRegister(instr->context()); | 2049 context = UseTempRegister(instr->context()); |
| 2037 value = UseTempRegister(instr->value()); | 2050 value = UseTempRegister(instr->value()); |
| 2038 } else { | 2051 } else { |
| 2039 context = UseRegister(instr->context()); | 2052 context = UseRegister(instr->context()); |
| 2040 value = UseRegister(instr->value()); | 2053 value = UseRegister(instr->value()); |
| 2041 } | 2054 } |
| 2042 LInstruction* result = new(zone()) LStoreContextSlot(context, value); | 2055 LInstruction* result = new(zone()) LStoreContextSlot(context, value); |
| 2043 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; | 2056 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { |
| 2057 result = AssignEnvironment(result); |
| 2058 } |
| 2059 return result; |
| 2044 } | 2060 } |
| 2045 | 2061 |
| 2046 | 2062 |
| 2047 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { | 2063 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { |
| 2048 LOperand* obj = UseRegisterAtStart(instr->object()); | 2064 LOperand* obj = UseRegisterAtStart(instr->object()); |
| 2049 return DefineAsRegister(new(zone()) LLoadNamedField(obj)); | 2065 return DefineAsRegister(new(zone()) LLoadNamedField(obj)); |
| 2050 } | 2066 } |
| 2051 | 2067 |
| 2052 | 2068 |
| 2053 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { | 2069 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2068 | 2084 |
| 2069 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) { | 2085 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) { |
| 2070 return DefineAsRegister(new(zone()) LLoadRoot); | 2086 return DefineAsRegister(new(zone()) LLoadRoot); |
| 2071 } | 2087 } |
| 2072 | 2088 |
| 2073 | 2089 |
| 2074 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { | 2090 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { |
| 2075 ASSERT(instr->key()->representation().IsSmiOrInteger32()); | 2091 ASSERT(instr->key()->representation().IsSmiOrInteger32()); |
| 2076 ElementsKind elements_kind = instr->elements_kind(); | 2092 ElementsKind elements_kind = instr->elements_kind(); |
| 2077 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); | 2093 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); |
| 2078 LLoadKeyed* result = NULL; | 2094 LInstruction* result = NULL; |
| 2079 | 2095 |
| 2080 if (!instr->is_typed_elements()) { | 2096 if (!instr->is_typed_elements()) { |
| 2081 LOperand* obj = NULL; | 2097 LOperand* obj = NULL; |
| 2082 if (instr->representation().IsDouble()) { | 2098 if (instr->representation().IsDouble()) { |
| 2083 obj = UseRegister(instr->elements()); | 2099 obj = UseRegister(instr->elements()); |
| 2084 } else { | 2100 } else { |
| 2085 ASSERT(instr->representation().IsSmiOrTagged()); | 2101 ASSERT(instr->representation().IsSmiOrTagged()); |
| 2086 obj = UseRegisterAtStart(instr->elements()); | 2102 obj = UseRegisterAtStart(instr->elements()); |
| 2087 } | 2103 } |
| 2088 result = new(zone()) LLoadKeyed(obj, key); | 2104 result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key)); |
| 2089 } else { | 2105 } else { |
| 2090 ASSERT( | 2106 ASSERT( |
| 2091 (instr->representation().IsInteger32() && | 2107 (instr->representation().IsInteger32() && |
| 2092 !IsDoubleOrFloatElementsKind(instr->elements_kind())) || | 2108 !IsDoubleOrFloatElementsKind(elements_kind)) || |
| 2093 (instr->representation().IsDouble() && | 2109 (instr->representation().IsDouble() && |
| 2094 IsDoubleOrFloatElementsKind(instr->elements_kind()))); | 2110 IsDoubleOrFloatElementsKind(elements_kind))); |
| 2095 LOperand* backing_store = UseRegister(instr->elements()); | 2111 LOperand* backing_store = UseRegister(instr->elements()); |
| 2096 result = new(zone()) LLoadKeyed(backing_store, key); | 2112 result = DefineAsRegister(new(zone()) LLoadKeyed(backing_store, key)); |
| 2097 } | 2113 } |
| 2098 | 2114 |
| 2099 DefineAsRegister(result); | 2115 if ((instr->is_external() || instr->is_fixed_typed_array()) ? |
| 2100 // An unsigned int array load might overflow and cause a deopt, make sure it | 2116 // see LCodeGen::DoLoadKeyedExternalArray |
| 2101 // has an environment. | 2117 ((elements_kind == EXTERNAL_UINT32_ELEMENTS || |
| 2102 bool can_deoptimize = instr->RequiresHoleCheck() || | 2118 elements_kind == UINT32_ELEMENTS) && |
| 2103 elements_kind == EXTERNAL_UINT32_ELEMENTS || | 2119 !instr->CheckFlag(HInstruction::kUint32)) : |
| 2104 elements_kind == UINT32_ELEMENTS; | 2120 // see LCodeGen::DoLoadKeyedFixedDoubleArray and |
| 2105 return can_deoptimize ? AssignEnvironment(result) : result; | 2121 // LCodeGen::DoLoadKeyedFixedArray |
| 2122 instr->RequiresHoleCheck()) { |
| 2123 result = AssignEnvironment(result); |
| 2124 } |
| 2125 return result; |
| 2106 } | 2126 } |
| 2107 | 2127 |
| 2108 | 2128 |
| 2109 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { | 2129 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { |
| 2110 LOperand* context = UseFixed(instr->context(), cp); | 2130 LOperand* context = UseFixed(instr->context(), cp); |
| 2111 LOperand* object = UseFixed(instr->object(), a1); | 2131 LOperand* object = UseFixed(instr->object(), a1); |
| 2112 LOperand* key = UseFixed(instr->key(), a0); | 2132 LOperand* key = UseFixed(instr->key(), a0); |
| 2113 | 2133 |
| 2114 LInstruction* result = | 2134 LInstruction* result = |
| 2115 DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key), v0); | 2135 DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key), v0); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2226 val = UseTempRegister(instr->value()); | 2246 val = UseTempRegister(instr->value()); |
| 2227 } else if (instr->field_representation().IsDouble()) { | 2247 } else if (instr->field_representation().IsDouble()) { |
| 2228 val = UseRegisterAtStart(instr->value()); | 2248 val = UseRegisterAtStart(instr->value()); |
| 2229 } else { | 2249 } else { |
| 2230 val = UseRegister(instr->value()); | 2250 val = UseRegister(instr->value()); |
| 2231 } | 2251 } |
| 2232 | 2252 |
| 2233 // We need a temporary register for write barrier of the map field. | 2253 // We need a temporary register for write barrier of the map field. |
| 2234 LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL; | 2254 LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL; |
| 2235 | 2255 |
| 2236 LStoreNamedField* result = new(zone()) LStoreNamedField(obj, val, temp); | 2256 LInstruction* result = new(zone()) LStoreNamedField(obj, val, temp); |
| 2237 if (instr->field_representation().IsHeapObject()) { | 2257 if (!instr->access().IsExternalMemory() && |
| 2238 if (!instr->value()->type().IsHeapObject()) { | 2258 instr->field_representation().IsHeapObject() && |
| 2239 return AssignEnvironment(result); | 2259 !instr->value()->type().IsHeapObject()) { |
| 2240 } | 2260 result = AssignEnvironment(result); |
| 2241 } | 2261 } |
| 2242 return result; | 2262 return result; |
| 2243 } | 2263 } |
| 2244 | 2264 |
| 2245 | 2265 |
| 2246 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { | 2266 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { |
| 2247 LOperand* context = UseFixed(instr->context(), cp); | 2267 LOperand* context = UseFixed(instr->context(), cp); |
| 2248 LOperand* obj = UseFixed(instr->object(), a1); | 2268 LOperand* obj = UseFixed(instr->object(), a1); |
| 2249 LOperand* val = UseFixed(instr->value(), a0); | 2269 LOperand* val = UseFixed(instr->value(), a0); |
| 2250 | 2270 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2262 instr); | 2282 instr); |
| 2263 } | 2283 } |
| 2264 | 2284 |
| 2265 | 2285 |
| 2266 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { | 2286 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { |
| 2267 LOperand* string = UseTempRegister(instr->string()); | 2287 LOperand* string = UseTempRegister(instr->string()); |
| 2268 LOperand* index = UseTempRegister(instr->index()); | 2288 LOperand* index = UseTempRegister(instr->index()); |
| 2269 LOperand* context = UseAny(instr->context()); | 2289 LOperand* context = UseAny(instr->context()); |
| 2270 LStringCharCodeAt* result = | 2290 LStringCharCodeAt* result = |
| 2271 new(zone()) LStringCharCodeAt(context, string, index); | 2291 new(zone()) LStringCharCodeAt(context, string, index); |
| 2272 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); | 2292 return AssignPointerMap(DefineAsRegister(result)); |
| 2273 } | 2293 } |
| 2274 | 2294 |
| 2275 | 2295 |
| 2276 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) { | 2296 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) { |
| 2277 LOperand* char_code = UseRegister(instr->value()); | 2297 LOperand* char_code = UseRegister(instr->value()); |
| 2278 LOperand* context = UseAny(instr->context()); | 2298 LOperand* context = UseAny(instr->context()); |
| 2279 LStringCharFromCode* result = | 2299 LStringCharFromCode* result = |
| 2280 new(zone()) LStringCharFromCode(context, char_code); | 2300 new(zone()) LStringCharFromCode(context, char_code); |
| 2281 return AssignPointerMap(DefineAsRegister(result)); | 2301 return AssignPointerMap(DefineAsRegister(result)); |
| 2282 } | 2302 } |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2492 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2512 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
| 2493 LOperand* object = UseRegister(instr->object()); | 2513 LOperand* object = UseRegister(instr->object()); |
| 2494 LOperand* index = UseRegister(instr->index()); | 2514 LOperand* index = UseRegister(instr->index()); |
| 2495 LLoadFieldByIndex* load = new(zone()) LLoadFieldByIndex(object, index); | 2515 LLoadFieldByIndex* load = new(zone()) LLoadFieldByIndex(object, index); |
| 2496 LInstruction* result = DefineSameAsFirst(load); | 2516 LInstruction* result = DefineSameAsFirst(load); |
| 2497 return AssignPointerMap(result); | 2517 return AssignPointerMap(result); |
| 2498 } | 2518 } |
| 2499 | 2519 |
| 2500 | 2520 |
| 2501 } } // namespace v8::internal | 2521 } } // namespace v8::internal |
| OLD | NEW |