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 |