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 913 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
924 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { | 924 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { |
925 return new(zone()) LGoto(instr->FirstSuccessor()); | 925 return new(zone()) LGoto(instr->FirstSuccessor()); |
926 } | 926 } |
927 | 927 |
928 | 928 |
929 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { | 929 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { |
930 LInstruction* goto_instr = CheckElideControlInstruction(instr); | 930 LInstruction* goto_instr = CheckElideControlInstruction(instr); |
931 if (goto_instr != NULL) return goto_instr; | 931 if (goto_instr != NULL) return goto_instr; |
932 | 932 |
933 HValue* value = instr->value(); | 933 HValue* value = instr->value(); |
934 LBranch* result = new(zone()) LBranch(UseRegister(value)); | 934 Representation r = value->representation(); |
935 // Tagged values that are not known smis or booleans require a | |
936 // deoptimization environment. If the instruction is generic no | |
937 // environment is needed since all cases are handled. | |
938 Representation rep = value->representation(); | |
939 HType type = value->type(); | 935 HType type = value->type(); |
940 ToBooleanStub::Types expected = instr->expected_input_types(); | 936 ToBooleanStub::Types expected = instr->expected_input_types(); |
941 if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean() && | 937 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); |
942 !expected.IsGeneric()) { | 938 |
943 return AssignEnvironment(result); | 939 bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() || |
| 940 type.IsJSArray() || type.IsHeapNumber() || type.IsString(); |
| 941 LInstruction* branch = new(zone()) LBranch(UseRegister(value)); |
| 942 if (!easy_case && |
| 943 ((!expected.Contains(ToBooleanStub::SMI) && expected.NeedsMap()) || |
| 944 !expected.IsGeneric())) { |
| 945 branch = AssignEnvironment(branch); |
944 } | 946 } |
945 return result; | 947 return branch; |
946 } | 948 } |
947 | 949 |
948 | 950 |
949 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) { | 951 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) { |
950 return new(zone()) LDebugBreak(); | 952 return new(zone()) LDebugBreak(); |
951 } | 953 } |
952 | 954 |
953 | 955 |
954 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { | 956 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { |
955 LInstruction* goto_instr = CheckElideControlInstruction(instr); | 957 LInstruction* goto_instr = CheckElideControlInstruction(instr); |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1131 return AssignEnvironment(DefineAsRegister(result)); | 1133 return AssignEnvironment(DefineAsRegister(result)); |
1132 } | 1134 } |
1133 | 1135 |
1134 | 1136 |
1135 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) { | 1137 LInstruction* LChunkBuilder::DoMathAbs(HUnaryMathOperation* instr) { |
1136 Representation r = instr->value()->representation(); | 1138 Representation r = instr->value()->representation(); |
1137 LOperand* context = (r.IsDouble() || r.IsSmiOrInteger32()) | 1139 LOperand* context = (r.IsDouble() || r.IsSmiOrInteger32()) |
1138 ? NULL | 1140 ? NULL |
1139 : UseFixed(instr->context(), cp); | 1141 : UseFixed(instr->context(), cp); |
1140 LOperand* input = UseRegister(instr->value()); | 1142 LOperand* input = UseRegister(instr->value()); |
1141 LMathAbs* result = new(zone()) LMathAbs(context, input); | 1143 LInstruction* result = |
1142 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); | 1144 DefineAsRegister(new(zone()) LMathAbs(context, input)); |
| 1145 if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result); |
| 1146 if (!r.IsDouble()) result = AssignEnvironment(result); |
| 1147 return result; |
1143 } | 1148 } |
1144 | 1149 |
1145 | 1150 |
1146 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) { | 1151 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) { |
1147 ASSERT(instr->representation().IsDouble()); | 1152 ASSERT(instr->representation().IsDouble()); |
1148 ASSERT(instr->value()->representation().IsDouble()); | 1153 ASSERT(instr->value()->representation().IsDouble()); |
1149 LOperand* input = UseFixedDouble(instr->value(), d0); | 1154 LOperand* input = UseFixedDouble(instr->value(), d0); |
1150 return MarkAsCall(DefineFixedDouble(new(zone()) LMathLog(input), d0), instr); | 1155 return MarkAsCall(DefineFixedDouble(new(zone()) LMathLog(input), d0), instr); |
1151 } | 1156 } |
1152 | 1157 |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1284 } | 1289 } |
1285 | 1290 |
1286 | 1291 |
1287 LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) { | 1292 LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) { |
1288 ASSERT(instr->representation().IsSmiOrInteger32()); | 1293 ASSERT(instr->representation().IsSmiOrInteger32()); |
1289 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1294 ASSERT(instr->left()->representation().Equals(instr->representation())); |
1290 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1295 ASSERT(instr->right()->representation().Equals(instr->representation())); |
1291 LOperand* dividend = UseRegister(instr->left()); | 1296 LOperand* dividend = UseRegister(instr->left()); |
1292 LOperand* divisor = UseRegister(instr->right()); | 1297 LOperand* divisor = UseRegister(instr->right()); |
1293 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4); | 1298 LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4); |
1294 LDivI* div = new(zone()) LDivI(dividend, divisor, temp); | 1299 LInstruction* result = |
1295 return AssignEnvironment(DefineAsRegister(div)); | 1300 DefineAsRegister(new(zone()) LDivI(dividend, divisor, temp)); |
| 1301 if (instr->CheckFlag(HValue::kCanBeDivByZero) || |
| 1302 instr->CheckFlag(HValue::kBailoutOnMinusZero) || |
| 1303 (instr->CheckFlag(HValue::kCanOverflow) && |
| 1304 (!CpuFeatures::IsSupported(SUDIV) || |
| 1305 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) || |
| 1306 (!instr->IsMathFloorOfDiv() && |
| 1307 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { |
| 1308 result = AssignEnvironment(result); |
| 1309 } |
| 1310 return result; |
1296 } | 1311 } |
1297 | 1312 |
1298 | 1313 |
1299 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1314 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
1300 if (instr->representation().IsSmiOrInteger32()) { | 1315 if (instr->representation().IsSmiOrInteger32()) { |
1301 if (instr->RightIsPowerOf2()) { | 1316 if (instr->RightIsPowerOf2()) { |
1302 return DoDivByPowerOf2I(instr); | 1317 return DoDivByPowerOf2I(instr); |
1303 } else if (instr->right()->IsConstant()) { | 1318 } else if (instr->right()->IsConstant()) { |
1304 return DoDivByConstI(instr); | 1319 return DoDivByConstI(instr); |
1305 } else { | 1320 } else { |
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1830 // All HForceRepresentation instructions should be eliminated in the | 1845 // All HForceRepresentation instructions should be eliminated in the |
1831 // representation change phase of Hydrogen. | 1846 // representation change phase of Hydrogen. |
1832 UNREACHABLE(); | 1847 UNREACHABLE(); |
1833 return NULL; | 1848 return NULL; |
1834 } | 1849 } |
1835 | 1850 |
1836 | 1851 |
1837 LInstruction* LChunkBuilder::DoChange(HChange* instr) { | 1852 LInstruction* LChunkBuilder::DoChange(HChange* instr) { |
1838 Representation from = instr->from(); | 1853 Representation from = instr->from(); |
1839 Representation to = instr->to(); | 1854 Representation to = instr->to(); |
| 1855 HValue* val = instr->value(); |
1840 if (from.IsSmi()) { | 1856 if (from.IsSmi()) { |
1841 if (to.IsTagged()) { | 1857 if (to.IsTagged()) { |
1842 LOperand* value = UseRegister(instr->value()); | 1858 LOperand* value = UseRegister(val); |
1843 return DefineSameAsFirst(new(zone()) LDummyUse(value)); | 1859 return DefineSameAsFirst(new(zone()) LDummyUse(value)); |
1844 } | 1860 } |
1845 from = Representation::Tagged(); | 1861 from = Representation::Tagged(); |
1846 } | 1862 } |
1847 if (from.IsTagged()) { | 1863 if (from.IsTagged()) { |
1848 if (to.IsDouble()) { | 1864 if (to.IsDouble()) { |
1849 LOperand* value = UseRegister(instr->value()); | 1865 LOperand* value = UseRegister(val); |
1850 LNumberUntagD* res = new(zone()) LNumberUntagD(value); | 1866 LInstruction* result = DefineAsRegister(new(zone()) LNumberUntagD(value)); |
1851 return AssignEnvironment(DefineAsRegister(res)); | 1867 if (!val->representation().IsSmi()) result = AssignEnvironment(result); |
| 1868 return result; |
1852 } else if (to.IsSmi()) { | 1869 } else if (to.IsSmi()) { |
1853 HValue* val = instr->value(); | |
1854 LOperand* value = UseRegister(val); | 1870 LOperand* value = UseRegister(val); |
1855 if (val->type().IsSmi()) { | 1871 if (val->type().IsSmi()) { |
1856 return DefineSameAsFirst(new(zone()) LDummyUse(value)); | 1872 return DefineSameAsFirst(new(zone()) LDummyUse(value)); |
1857 } | 1873 } |
1858 return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value))); | 1874 return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value))); |
1859 } else { | 1875 } else { |
1860 ASSERT(to.IsInteger32()); | 1876 ASSERT(to.IsInteger32()); |
1861 LOperand* value = NULL; | |
1862 LInstruction* res = NULL; | |
1863 HValue* val = instr->value(); | |
1864 if (val->type().IsSmi() || val->representation().IsSmi()) { | 1877 if (val->type().IsSmi() || val->representation().IsSmi()) { |
1865 value = UseRegisterAtStart(val); | 1878 LOperand* value = UseRegisterAtStart(val); |
1866 res = DefineAsRegister(new(zone()) LSmiUntag(value, false)); | 1879 return DefineAsRegister(new(zone()) LSmiUntag(value, false)); |
1867 } else { | 1880 } else { |
1868 value = UseRegister(val); | 1881 LOperand* value = UseRegister(val); |
1869 LOperand* temp1 = TempRegister(); | 1882 LOperand* temp1 = TempRegister(); |
1870 LOperand* temp2 = FixedTemp(d11); | 1883 LOperand* temp2 = FixedTemp(d11); |
1871 res = DefineSameAsFirst(new(zone()) LTaggedToI(value, | 1884 LInstruction* result = |
1872 temp1, | 1885 DefineSameAsFirst(new(zone()) LTaggedToI(value, temp1, temp2)); |
1873 temp2)); | 1886 if (!val->representation().IsSmi()) { |
1874 res = AssignEnvironment(res); | 1887 // Note: Only deopts in deferred code. |
| 1888 result = AssignEnvironment(result); |
| 1889 } |
| 1890 return result; |
1875 } | 1891 } |
1876 return res; | |
1877 } | 1892 } |
1878 } else if (from.IsDouble()) { | 1893 } else if (from.IsDouble()) { |
1879 if (to.IsTagged()) { | 1894 if (to.IsTagged()) { |
1880 info()->MarkAsDeferredCalling(); | 1895 info()->MarkAsDeferredCalling(); |
1881 LOperand* value = UseRegister(instr->value()); | 1896 LOperand* value = UseRegister(val); |
1882 LOperand* temp1 = TempRegister(); | 1897 LOperand* temp1 = TempRegister(); |
1883 LOperand* temp2 = TempRegister(); | 1898 LOperand* temp2 = TempRegister(); |
1884 | |
1885 // Make sure that the temp and result_temp registers are | |
1886 // different. | |
1887 LUnallocated* result_temp = TempRegister(); | 1899 LUnallocated* result_temp = TempRegister(); |
1888 LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2); | 1900 LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2); |
1889 Define(result, result_temp); | 1901 return AssignPointerMap(Define(result, result_temp)); |
1890 return AssignPointerMap(result); | |
1891 } else if (to.IsSmi()) { | 1902 } else if (to.IsSmi()) { |
1892 LOperand* value = UseRegister(instr->value()); | 1903 LOperand* value = UseRegister(val); |
1893 return AssignEnvironment( | 1904 return AssignEnvironment( |
1894 DefineAsRegister(new(zone()) LDoubleToSmi(value))); | 1905 DefineAsRegister(new(zone()) LDoubleToSmi(value))); |
1895 } else { | 1906 } else { |
1896 ASSERT(to.IsInteger32()); | 1907 ASSERT(to.IsInteger32()); |
1897 LOperand* value = UseRegister(instr->value()); | 1908 LOperand* value = UseRegister(val); |
1898 LDoubleToI* res = new(zone()) LDoubleToI(value); | 1909 LInstruction* result = DefineAsRegister(new(zone()) LDoubleToI(value)); |
1899 return AssignEnvironment(DefineAsRegister(res)); | 1910 if (!instr->CanTruncateToInt32()) result = AssignEnvironment(result); |
| 1911 return result; |
1900 } | 1912 } |
1901 } else if (from.IsInteger32()) { | 1913 } else if (from.IsInteger32()) { |
1902 info()->MarkAsDeferredCalling(); | 1914 info()->MarkAsDeferredCalling(); |
1903 if (to.IsTagged()) { | 1915 if (to.IsTagged()) { |
1904 HValue* val = instr->value(); | |
1905 LOperand* value = UseRegisterAtStart(val); | |
1906 if (!instr->CheckFlag(HValue::kCanOverflow)) { | 1916 if (!instr->CheckFlag(HValue::kCanOverflow)) { |
| 1917 LOperand* value = UseRegisterAtStart(val); |
1907 return DefineAsRegister(new(zone()) LSmiTag(value)); | 1918 return DefineAsRegister(new(zone()) LSmiTag(value)); |
1908 } else if (val->CheckFlag(HInstruction::kUint32)) { | 1919 } else if (val->CheckFlag(HInstruction::kUint32)) { |
| 1920 LOperand* value = UseRegisterAtStart(val); |
1909 LOperand* temp1 = TempRegister(); | 1921 LOperand* temp1 = TempRegister(); |
1910 LOperand* temp2 = TempRegister(); | 1922 LOperand* temp2 = TempRegister(); |
1911 LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2); | 1923 LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2); |
1912 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); | 1924 return AssignPointerMap(DefineAsRegister(result)); |
1913 } else { | 1925 } else { |
| 1926 LOperand* value = UseRegisterAtStart(val); |
1914 LOperand* temp1 = TempRegister(); | 1927 LOperand* temp1 = TempRegister(); |
1915 LOperand* temp2 = TempRegister(); | 1928 LOperand* temp2 = TempRegister(); |
1916 LNumberTagI* result = new(zone()) LNumberTagI(value, temp1, temp2); | 1929 LNumberTagI* result = new(zone()) LNumberTagI(value, temp1, temp2); |
1917 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); | 1930 return AssignPointerMap(DefineAsRegister(result)); |
1918 } | 1931 } |
1919 } else if (to.IsSmi()) { | 1932 } else if (to.IsSmi()) { |
1920 HValue* val = instr->value(); | |
1921 LOperand* value = UseRegister(val); | 1933 LOperand* value = UseRegister(val); |
1922 LInstruction* result = DefineAsRegister(new(zone()) LSmiTag(value)); | 1934 LInstruction* result = DefineAsRegister(new(zone()) LSmiTag(value)); |
1923 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1935 if (instr->CheckFlag(HValue::kCanOverflow)) { |
1924 result = AssignEnvironment(result); | 1936 result = AssignEnvironment(result); |
1925 } | 1937 } |
1926 return result; | 1938 return result; |
1927 } else { | 1939 } else { |
1928 ASSERT(to.IsDouble()); | 1940 ASSERT(to.IsDouble()); |
1929 if (instr->value()->CheckFlag(HInstruction::kUint32)) { | 1941 if (val->CheckFlag(HInstruction::kUint32)) { |
1930 return DefineAsRegister( | 1942 return DefineAsRegister(new(zone()) LUint32ToDouble(UseRegister(val))); |
1931 new(zone()) LUint32ToDouble(UseRegister(instr->value()))); | |
1932 } else { | 1943 } else { |
1933 return DefineAsRegister( | 1944 return DefineAsRegister(new(zone()) LInteger32ToDouble(Use(val))); |
1934 new(zone()) LInteger32ToDouble(Use(instr->value()))); | |
1935 } | 1945 } |
1936 } | 1946 } |
1937 } | 1947 } |
1938 UNREACHABLE(); | 1948 UNREACHABLE(); |
1939 return NULL; | 1949 return NULL; |
1940 } | 1950 } |
1941 | 1951 |
1942 | 1952 |
1943 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) { | 1953 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) { |
1944 LOperand* value = UseRegisterAtStart(instr->value()); | 1954 LOperand* value = UseRegisterAtStart(instr->value()); |
(...skipping 21 matching lines...) Expand all Loading... |
1966 | 1976 |
1967 | 1977 |
1968 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { | 1978 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) { |
1969 LOperand* value = NULL; | 1979 LOperand* value = NULL; |
1970 if (!instr->CanOmitMapChecks()) { | 1980 if (!instr->CanOmitMapChecks()) { |
1971 value = UseRegisterAtStart(instr->value()); | 1981 value = UseRegisterAtStart(instr->value()); |
1972 if (instr->has_migration_target()) info()->MarkAsDeferredCalling(); | 1982 if (instr->has_migration_target()) info()->MarkAsDeferredCalling(); |
1973 } | 1983 } |
1974 LCheckMaps* result = new(zone()) LCheckMaps(value); | 1984 LCheckMaps* result = new(zone()) LCheckMaps(value); |
1975 if (!instr->CanOmitMapChecks()) { | 1985 if (!instr->CanOmitMapChecks()) { |
| 1986 // Note: Only deopts in deferred code. |
1976 AssignEnvironment(result); | 1987 AssignEnvironment(result); |
1977 if (instr->has_migration_target()) return AssignPointerMap(result); | 1988 if (instr->has_migration_target()) return AssignPointerMap(result); |
1978 } | 1989 } |
1979 return result; | 1990 return result; |
1980 } | 1991 } |
1981 | 1992 |
1982 | 1993 |
1983 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { | 1994 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { |
1984 HValue* value = instr->value(); | 1995 HValue* value = instr->value(); |
1985 Representation input_rep = value->representation(); | 1996 Representation input_rep = value->representation(); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2065 return instr->RequiresHoleCheck() | 2076 return instr->RequiresHoleCheck() |
2066 ? AssignEnvironment(new(zone()) LStoreGlobalCell(value, TempRegister())) | 2077 ? AssignEnvironment(new(zone()) LStoreGlobalCell(value, TempRegister())) |
2067 : new(zone()) LStoreGlobalCell(value, NULL); | 2078 : new(zone()) LStoreGlobalCell(value, NULL); |
2068 } | 2079 } |
2069 | 2080 |
2070 | 2081 |
2071 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { | 2082 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { |
2072 LOperand* context = UseRegisterAtStart(instr->value()); | 2083 LOperand* context = UseRegisterAtStart(instr->value()); |
2073 LInstruction* result = | 2084 LInstruction* result = |
2074 DefineAsRegister(new(zone()) LLoadContextSlot(context)); | 2085 DefineAsRegister(new(zone()) LLoadContextSlot(context)); |
2075 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; | 2086 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { |
| 2087 result = AssignEnvironment(result); |
| 2088 } |
| 2089 return result; |
2076 } | 2090 } |
2077 | 2091 |
2078 | 2092 |
2079 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { | 2093 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { |
2080 LOperand* context; | 2094 LOperand* context; |
2081 LOperand* value; | 2095 LOperand* value; |
2082 if (instr->NeedsWriteBarrier()) { | 2096 if (instr->NeedsWriteBarrier()) { |
2083 context = UseTempRegister(instr->context()); | 2097 context = UseTempRegister(instr->context()); |
2084 value = UseTempRegister(instr->value()); | 2098 value = UseTempRegister(instr->value()); |
2085 } else { | 2099 } else { |
2086 context = UseRegister(instr->context()); | 2100 context = UseRegister(instr->context()); |
2087 value = UseRegister(instr->value()); | 2101 value = UseRegister(instr->value()); |
2088 } | 2102 } |
2089 LInstruction* result = new(zone()) LStoreContextSlot(context, value); | 2103 LInstruction* result = new(zone()) LStoreContextSlot(context, value); |
2090 return instr->RequiresHoleCheck() ? AssignEnvironment(result) : result; | 2104 if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) { |
| 2105 result = AssignEnvironment(result); |
| 2106 } |
| 2107 return result; |
2091 } | 2108 } |
2092 | 2109 |
2093 | 2110 |
2094 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { | 2111 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { |
2095 LOperand* obj = UseRegisterAtStart(instr->object()); | 2112 LOperand* obj = UseRegisterAtStart(instr->object()); |
2096 return DefineAsRegister(new(zone()) LLoadNamedField(obj)); | 2113 return DefineAsRegister(new(zone()) LLoadNamedField(obj)); |
2097 } | 2114 } |
2098 | 2115 |
2099 | 2116 |
2100 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { | 2117 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { |
(...skipping 14 matching lines...) Expand all Loading... |
2115 | 2132 |
2116 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) { | 2133 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) { |
2117 return DefineAsRegister(new(zone()) LLoadRoot); | 2134 return DefineAsRegister(new(zone()) LLoadRoot); |
2118 } | 2135 } |
2119 | 2136 |
2120 | 2137 |
2121 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { | 2138 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { |
2122 ASSERT(instr->key()->representation().IsSmiOrInteger32()); | 2139 ASSERT(instr->key()->representation().IsSmiOrInteger32()); |
2123 ElementsKind elements_kind = instr->elements_kind(); | 2140 ElementsKind elements_kind = instr->elements_kind(); |
2124 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); | 2141 LOperand* key = UseRegisterOrConstantAtStart(instr->key()); |
2125 LLoadKeyed* result = NULL; | 2142 LInstruction* result = NULL; |
2126 | 2143 |
2127 if (!instr->is_typed_elements()) { | 2144 if (!instr->is_typed_elements()) { |
2128 LOperand* obj = NULL; | 2145 LOperand* obj = NULL; |
2129 if (instr->representation().IsDouble()) { | 2146 if (instr->representation().IsDouble()) { |
2130 obj = UseRegister(instr->elements()); | 2147 obj = UseRegister(instr->elements()); |
2131 } else { | 2148 } else { |
2132 ASSERT(instr->representation().IsSmiOrTagged()); | 2149 ASSERT(instr->representation().IsSmiOrTagged()); |
2133 obj = UseRegisterAtStart(instr->elements()); | 2150 obj = UseRegisterAtStart(instr->elements()); |
2134 } | 2151 } |
2135 result = new(zone()) LLoadKeyed(obj, key); | 2152 result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key)); |
2136 } else { | 2153 } else { |
2137 ASSERT( | 2154 ASSERT( |
2138 (instr->representation().IsInteger32() && | 2155 (instr->representation().IsInteger32() && |
2139 !IsDoubleOrFloatElementsKind(instr->elements_kind())) || | 2156 !IsDoubleOrFloatElementsKind(elements_kind)) || |
2140 (instr->representation().IsDouble() && | 2157 (instr->representation().IsDouble() && |
2141 IsDoubleOrFloatElementsKind(instr->elements_kind()))); | 2158 IsDoubleOrFloatElementsKind(elements_kind))); |
2142 LOperand* backing_store = UseRegister(instr->elements()); | 2159 LOperand* backing_store = UseRegister(instr->elements()); |
2143 result = new(zone()) LLoadKeyed(backing_store, key); | 2160 result = DefineAsRegister(new(zone()) LLoadKeyed(backing_store, key)); |
2144 } | 2161 } |
2145 | 2162 |
2146 DefineAsRegister(result); | 2163 if ((instr->is_external() || instr->is_fixed_typed_array()) ? |
2147 // An unsigned int array load might overflow and cause a deopt, make sure it | 2164 // see LCodeGen::DoLoadKeyedExternalArray |
2148 // has an environment. | 2165 ((elements_kind == EXTERNAL_UINT32_ELEMENTS || |
2149 bool can_deoptimize = instr->RequiresHoleCheck() || | 2166 elements_kind == UINT32_ELEMENTS) && |
2150 elements_kind == EXTERNAL_UINT32_ELEMENTS || | 2167 !instr->CheckFlag(HInstruction::kUint32)) : |
2151 elements_kind == UINT32_ELEMENTS; | 2168 // see LCodeGen::DoLoadKeyedFixedDoubleArray and |
2152 return can_deoptimize ? AssignEnvironment(result) : result; | 2169 // LCodeGen::DoLoadKeyedFixedArray |
| 2170 instr->RequiresHoleCheck()) { |
| 2171 result = AssignEnvironment(result); |
| 2172 } |
| 2173 return result; |
2153 } | 2174 } |
2154 | 2175 |
2155 | 2176 |
2156 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { | 2177 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { |
2157 LOperand* context = UseFixed(instr->context(), cp); | 2178 LOperand* context = UseFixed(instr->context(), cp); |
2158 LOperand* object = UseFixed(instr->object(), r1); | 2179 LOperand* object = UseFixed(instr->object(), r1); |
2159 LOperand* key = UseFixed(instr->key(), r0); | 2180 LOperand* key = UseFixed(instr->key(), r0); |
2160 | 2181 |
2161 LInstruction* result = | 2182 LInstruction* result = |
2162 DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key), r0); | 2183 DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key), r0); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2273 val = UseTempRegister(instr->value()); | 2294 val = UseTempRegister(instr->value()); |
2274 } else if (instr->field_representation().IsDouble()) { | 2295 } else if (instr->field_representation().IsDouble()) { |
2275 val = UseRegisterAtStart(instr->value()); | 2296 val = UseRegisterAtStart(instr->value()); |
2276 } else { | 2297 } else { |
2277 val = UseRegister(instr->value()); | 2298 val = UseRegister(instr->value()); |
2278 } | 2299 } |
2279 | 2300 |
2280 // We need a temporary register for write barrier of the map field. | 2301 // We need a temporary register for write barrier of the map field. |
2281 LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL; | 2302 LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL; |
2282 | 2303 |
2283 LStoreNamedField* result = new(zone()) LStoreNamedField(obj, val, temp); | 2304 LInstruction* result = new(zone()) LStoreNamedField(obj, val, temp); |
2284 if (instr->field_representation().IsHeapObject()) { | 2305 if (!instr->access().IsExternalMemory() && |
2285 if (!instr->value()->type().IsHeapObject()) { | 2306 instr->field_representation().IsHeapObject() && |
2286 return AssignEnvironment(result); | 2307 !instr->value()->type().IsHeapObject()) { |
2287 } | 2308 result = AssignEnvironment(result); |
2288 } | 2309 } |
2289 return result; | 2310 return result; |
2290 } | 2311 } |
2291 | 2312 |
2292 | 2313 |
2293 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { | 2314 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { |
2294 LOperand* context = UseFixed(instr->context(), cp); | 2315 LOperand* context = UseFixed(instr->context(), cp); |
2295 LOperand* obj = UseFixed(instr->object(), r1); | 2316 LOperand* obj = UseFixed(instr->object(), r1); |
2296 LOperand* val = UseFixed(instr->value(), r0); | 2317 LOperand* val = UseFixed(instr->value(), r0); |
2297 | 2318 |
(...skipping 11 matching lines...) Expand all Loading... |
2309 instr); | 2330 instr); |
2310 } | 2331 } |
2311 | 2332 |
2312 | 2333 |
2313 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { | 2334 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { |
2314 LOperand* string = UseTempRegister(instr->string()); | 2335 LOperand* string = UseTempRegister(instr->string()); |
2315 LOperand* index = UseTempRegister(instr->index()); | 2336 LOperand* index = UseTempRegister(instr->index()); |
2316 LOperand* context = UseAny(instr->context()); | 2337 LOperand* context = UseAny(instr->context()); |
2317 LStringCharCodeAt* result = | 2338 LStringCharCodeAt* result = |
2318 new(zone()) LStringCharCodeAt(context, string, index); | 2339 new(zone()) LStringCharCodeAt(context, string, index); |
2319 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); | 2340 return AssignPointerMap(DefineAsRegister(result)); |
2320 } | 2341 } |
2321 | 2342 |
2322 | 2343 |
2323 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) { | 2344 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) { |
2324 LOperand* char_code = UseRegister(instr->value()); | 2345 LOperand* char_code = UseRegister(instr->value()); |
2325 LOperand* context = UseAny(instr->context()); | 2346 LOperand* context = UseAny(instr->context()); |
2326 LStringCharFromCode* result = | 2347 LStringCharFromCode* result = |
2327 new(zone()) LStringCharFromCode(context, char_code); | 2348 new(zone()) LStringCharFromCode(context, char_code); |
2328 return AssignPointerMap(DefineAsRegister(result)); | 2349 return AssignPointerMap(DefineAsRegister(result)); |
2329 } | 2350 } |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2538 | 2559 |
2539 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { | 2560 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) { |
2540 LOperand* object = UseRegister(instr->object()); | 2561 LOperand* object = UseRegister(instr->object()); |
2541 LOperand* index = UseRegister(instr->index()); | 2562 LOperand* index = UseRegister(instr->index()); |
2542 LLoadFieldByIndex* load = new(zone()) LLoadFieldByIndex(object, index); | 2563 LLoadFieldByIndex* load = new(zone()) LLoadFieldByIndex(object, index); |
2543 LInstruction* result = DefineSameAsFirst(load); | 2564 LInstruction* result = DefineSameAsFirst(load); |
2544 return AssignPointerMap(result); | 2565 return AssignPointerMap(result); |
2545 } | 2566 } |
2546 | 2567 |
2547 } } // namespace v8::internal | 2568 } } // namespace v8::internal |
OLD | NEW |