OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/interpreter/bytecode-generator.h" | 5 #include "src/interpreter/bytecode-generator.h" |
6 | 6 |
7 #include "src/ast/compile-time-value.h" | 7 #include "src/ast/compile-time-value.h" |
8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/compilation-info.h" | 10 #include "src/compilation-info.h" |
(...skipping 812 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
823 builder() | 823 builder() |
824 ->LoadLiteral(variable->name()) | 824 ->LoadLiteral(variable->name()) |
825 .StoreAccumulatorInRegister(name) | 825 .StoreAccumulatorInRegister(name) |
826 .CallRuntime(Runtime::kDeclareEvalVar, name); | 826 .CallRuntime(Runtime::kDeclareEvalVar, name); |
827 break; | 827 break; |
828 } | 828 } |
829 case VariableLocation::MODULE: | 829 case VariableLocation::MODULE: |
830 if (variable->IsExport() && variable->binding_needs_init()) { | 830 if (variable->IsExport() && variable->binding_needs_init()) { |
831 builder()->LoadTheHole(); | 831 builder()->LoadTheHole(); |
832 BuildVariableAssignment(variable, Token::INIT, | 832 BuildVariableAssignment(variable, Token::INIT, |
833 FeedbackVectorSlot::Invalid(), false); | 833 FeedbackVectorSlot::Invalid(), |
| 834 HoleCheckMode::kElided); |
834 } | 835 } |
835 // Nothing to do for imports. | 836 // Nothing to do for imports. |
836 break; | 837 break; |
837 } | 838 } |
838 } | 839 } |
839 | 840 |
840 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { | 841 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { |
841 Variable* variable = decl->proxy()->var(); | 842 Variable* variable = decl->proxy()->var(); |
842 DCHECK(variable->mode() == LET || variable->mode() == VAR); | 843 DCHECK(variable->mode() == LET || variable->mode() == VAR); |
843 switch (variable->location()) { | 844 switch (variable->location()) { |
844 case VariableLocation::UNALLOCATED: { | 845 case VariableLocation::UNALLOCATED: { |
845 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); | 846 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); |
846 globals_builder()->AddFunctionDeclaration(slot, decl->fun()); | 847 globals_builder()->AddFunctionDeclaration(slot, decl->fun()); |
847 break; | 848 break; |
848 } | 849 } |
849 case VariableLocation::PARAMETER: | 850 case VariableLocation::PARAMETER: |
850 case VariableLocation::LOCAL: { | 851 case VariableLocation::LOCAL: { |
851 VisitForAccumulatorValue(decl->fun()); | 852 VisitForAccumulatorValue(decl->fun()); |
852 BuildVariableAssignment(variable, Token::INIT, | 853 BuildVariableAssignment(variable, Token::INIT, |
853 FeedbackVectorSlot::Invalid(), false); | 854 FeedbackVectorSlot::Invalid(), |
| 855 HoleCheckMode::kElided); |
854 break; | 856 break; |
855 } | 857 } |
856 case VariableLocation::CONTEXT: { | 858 case VariableLocation::CONTEXT: { |
857 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); | 859 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); |
858 VisitForAccumulatorValue(decl->fun()); | 860 VisitForAccumulatorValue(decl->fun()); |
859 builder()->StoreContextSlot(execution_context()->reg(), variable->index(), | 861 builder()->StoreContextSlot(execution_context()->reg(), variable->index(), |
860 0); | 862 0); |
861 break; | 863 break; |
862 } | 864 } |
863 case VariableLocation::LOOKUP: { | 865 case VariableLocation::LOOKUP: { |
864 RegisterList args = register_allocator()->NewRegisterList(2); | 866 RegisterList args = register_allocator()->NewRegisterList(2); |
865 builder() | 867 builder() |
866 ->LoadLiteral(variable->name()) | 868 ->LoadLiteral(variable->name()) |
867 .StoreAccumulatorInRegister(args[0]); | 869 .StoreAccumulatorInRegister(args[0]); |
868 VisitForAccumulatorValue(decl->fun()); | 870 VisitForAccumulatorValue(decl->fun()); |
869 builder()->StoreAccumulatorInRegister(args[1]).CallRuntime( | 871 builder()->StoreAccumulatorInRegister(args[1]).CallRuntime( |
870 Runtime::kDeclareEvalFunction, args); | 872 Runtime::kDeclareEvalFunction, args); |
871 break; | 873 break; |
872 } | 874 } |
873 case VariableLocation::MODULE: | 875 case VariableLocation::MODULE: |
874 DCHECK_EQ(variable->mode(), LET); | 876 DCHECK_EQ(variable->mode(), LET); |
875 DCHECK(variable->IsExport()); | 877 DCHECK(variable->IsExport()); |
876 VisitForAccumulatorValue(decl->fun()); | 878 VisitForAccumulatorValue(decl->fun()); |
877 BuildVariableAssignment(variable, Token::INIT, | 879 BuildVariableAssignment(variable, Token::INIT, |
878 FeedbackVectorSlot::Invalid(), false); | 880 FeedbackVectorSlot::Invalid(), |
| 881 HoleCheckMode::kElided); |
879 break; | 882 break; |
880 } | 883 } |
881 } | 884 } |
882 | 885 |
883 void BytecodeGenerator::VisitModuleNamespaceImports() { | 886 void BytecodeGenerator::VisitModuleNamespaceImports() { |
884 if (!scope()->is_module_scope()) return; | 887 if (!scope()->is_module_scope()) return; |
885 | 888 |
886 RegisterAllocationScope register_scope(this); | 889 RegisterAllocationScope register_scope(this); |
887 Register module_request = register_allocator()->NewRegister(); | 890 Register module_request = register_allocator()->NewRegister(); |
888 | 891 |
889 ModuleDescriptor* descriptor = scope()->AsModuleScope()->module(); | 892 ModuleDescriptor* descriptor = scope()->AsModuleScope()->module(); |
890 for (auto entry : descriptor->namespace_imports()) { | 893 for (auto entry : descriptor->namespace_imports()) { |
891 builder() | 894 builder() |
892 ->LoadLiteral(Smi::FromInt(entry->module_request)) | 895 ->LoadLiteral(Smi::FromInt(entry->module_request)) |
893 .StoreAccumulatorInRegister(module_request) | 896 .StoreAccumulatorInRegister(module_request) |
894 .CallRuntime(Runtime::kGetModuleNamespace, module_request); | 897 .CallRuntime(Runtime::kGetModuleNamespace, module_request); |
895 Variable* var = scope()->LookupLocal(entry->local_name); | 898 Variable* var = scope()->LookupLocal(entry->local_name); |
896 DCHECK_NOT_NULL(var); | 899 DCHECK_NOT_NULL(var); |
897 BuildVariableAssignment(var, Token::INIT, FeedbackVectorSlot::Invalid(), | 900 BuildVariableAssignment(var, Token::INIT, FeedbackVectorSlot::Invalid(), |
898 false); | 901 HoleCheckMode::kElided); |
899 } | 902 } |
900 } | 903 } |
901 | 904 |
902 void BytecodeGenerator::VisitDeclarations( | 905 void BytecodeGenerator::VisitDeclarations( |
903 ZoneList<Declaration*>* declarations) { | 906 ZoneList<Declaration*>* declarations) { |
904 RegisterAllocationScope register_scope(this); | 907 RegisterAllocationScope register_scope(this); |
905 DCHECK(globals_builder()->empty()); | 908 DCHECK(globals_builder()->empty()); |
906 for (int i = 0; i < declarations->length(); i++) { | 909 for (int i = 0; i < declarations->length(); i++) { |
907 RegisterAllocationScope register_scope(this); | 910 RegisterAllocationScope register_scope(this); |
908 Visit(declarations->at(i)); | 911 Visit(declarations->at(i)); |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1143 DCHECK(expr->IsValidReferenceExpression()); | 1146 DCHECK(expr->IsValidReferenceExpression()); |
1144 | 1147 |
1145 // Evaluate assignment starting with the value to be stored in the | 1148 // Evaluate assignment starting with the value to be stored in the |
1146 // accumulator. | 1149 // accumulator. |
1147 Property* property = expr->AsProperty(); | 1150 Property* property = expr->AsProperty(); |
1148 LhsKind assign_type = Property::GetAssignType(property); | 1151 LhsKind assign_type = Property::GetAssignType(property); |
1149 switch (assign_type) { | 1152 switch (assign_type) { |
1150 case VARIABLE: { | 1153 case VARIABLE: { |
1151 VariableProxy* proxy = expr->AsVariableProxy(); | 1154 VariableProxy* proxy = expr->AsVariableProxy(); |
1152 BuildVariableAssignment(proxy->var(), Token::ASSIGN, slot, | 1155 BuildVariableAssignment(proxy->var(), Token::ASSIGN, slot, |
1153 proxy->needs_hole_check()); | 1156 proxy->hole_check_mode()); |
1154 break; | 1157 break; |
1155 } | 1158 } |
1156 case NAMED_PROPERTY: { | 1159 case NAMED_PROPERTY: { |
1157 RegisterAllocationScope register_scope(this); | 1160 RegisterAllocationScope register_scope(this); |
1158 Register value = register_allocator()->NewRegister(); | 1161 Register value = register_allocator()->NewRegister(); |
1159 builder()->StoreAccumulatorInRegister(value); | 1162 builder()->StoreAccumulatorInRegister(value); |
1160 Register object = VisitForRegisterValue(property->obj()); | 1163 Register object = VisitForRegisterValue(property->obj()); |
1161 Handle<String> name = property->key()->AsLiteral()->AsPropertyName(); | 1164 Handle<String> name = property->key()->AsLiteral()->AsPropertyName(); |
1162 builder()->LoadAccumulatorWithRegister(value); | 1165 builder()->LoadAccumulatorWithRegister(value); |
1163 builder()->StoreNamedProperty(object, name, feedback_index(slot), | 1166 builder()->StoreNamedProperty(object, name, feedback_index(slot), |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1394 .StoreAccumulatorInRegister(prototype); | 1397 .StoreAccumulatorInRegister(prototype); |
1395 | 1398 |
1396 VisitClassLiteralProperties(expr, literal, prototype); | 1399 VisitClassLiteralProperties(expr, literal, prototype); |
1397 builder()->CallRuntime(Runtime::kToFastProperties, literal); | 1400 builder()->CallRuntime(Runtime::kToFastProperties, literal); |
1398 // Assign to class variable. | 1401 // Assign to class variable. |
1399 if (expr->class_variable_proxy() != nullptr) { | 1402 if (expr->class_variable_proxy() != nullptr) { |
1400 VariableProxy* proxy = expr->class_variable_proxy(); | 1403 VariableProxy* proxy = expr->class_variable_proxy(); |
1401 FeedbackVectorSlot slot = expr->NeedsProxySlot() | 1404 FeedbackVectorSlot slot = expr->NeedsProxySlot() |
1402 ? expr->ProxySlot() | 1405 ? expr->ProxySlot() |
1403 : FeedbackVectorSlot::Invalid(); | 1406 : FeedbackVectorSlot::Invalid(); |
1404 BuildVariableAssignment(proxy->var(), Token::INIT, slot, false); | 1407 BuildVariableAssignment(proxy->var(), Token::INIT, slot, |
| 1408 HoleCheckMode::kElided); |
1405 } | 1409 } |
1406 } | 1410 } |
1407 | 1411 |
1408 void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition( | 1412 void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition( |
1409 ClassLiteral* expr) { | 1413 ClassLiteral* expr) { |
1410 RegisterAllocationScope register_scope(this); | 1414 RegisterAllocationScope register_scope(this); |
1411 RegisterList args = register_allocator()->NewRegisterList(4); | 1415 RegisterList args = register_allocator()->NewRegisterList(4); |
1412 VisitForAccumulatorValueOrTheHole(expr->extends()); | 1416 VisitForAccumulatorValueOrTheHole(expr->extends()); |
1413 builder()->StoreAccumulatorInRegister(args[0]); | 1417 builder()->StoreAccumulatorInRegister(args[0]); |
1414 VisitForRegisterValue(expr->constructor(), args[1]); | 1418 VisitForRegisterValue(expr->constructor(), args[1]); |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1769 | 1773 |
1770 if (!literal_in_accumulator) { | 1774 if (!literal_in_accumulator) { |
1771 // Restore literal array into accumulator. | 1775 // Restore literal array into accumulator. |
1772 builder()->LoadAccumulatorWithRegister(literal); | 1776 builder()->LoadAccumulatorWithRegister(literal); |
1773 } | 1777 } |
1774 } | 1778 } |
1775 | 1779 |
1776 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { | 1780 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { |
1777 builder()->SetExpressionPosition(proxy); | 1781 builder()->SetExpressionPosition(proxy); |
1778 BuildVariableLoad(proxy->var(), proxy->VariableFeedbackSlot(), | 1782 BuildVariableLoad(proxy->var(), proxy->VariableFeedbackSlot(), |
1779 proxy->needs_hole_check()); | 1783 proxy->hole_check_mode()); |
1780 } | 1784 } |
1781 | 1785 |
1782 void BytecodeGenerator::BuildVariableLoad(Variable* variable, | 1786 void BytecodeGenerator::BuildVariableLoad(Variable* variable, |
1783 FeedbackVectorSlot slot, | 1787 FeedbackVectorSlot slot, |
1784 bool needs_hole_check, | 1788 HoleCheckMode hole_check_mode, |
1785 TypeofMode typeof_mode) { | 1789 TypeofMode typeof_mode) { |
1786 switch (variable->location()) { | 1790 switch (variable->location()) { |
1787 case VariableLocation::LOCAL: { | 1791 case VariableLocation::LOCAL: { |
1788 Register source(Register(variable->index())); | 1792 Register source(Register(variable->index())); |
1789 // We need to load the variable into the accumulator, even when in a | 1793 // We need to load the variable into the accumulator, even when in a |
1790 // VisitForRegisterScope, in order to avoid register aliasing if | 1794 // VisitForRegisterScope, in order to avoid register aliasing if |
1791 // subsequent expressions assign to the same variable. | 1795 // subsequent expressions assign to the same variable. |
1792 builder()->LoadAccumulatorWithRegister(source); | 1796 builder()->LoadAccumulatorWithRegister(source); |
1793 if (needs_hole_check) BuildThrowIfHole(variable->name()); | 1797 if (hole_check_mode == HoleCheckMode::kRequired) { |
| 1798 BuildThrowIfHole(variable->name()); |
| 1799 } |
1794 break; | 1800 break; |
1795 } | 1801 } |
1796 case VariableLocation::PARAMETER: { | 1802 case VariableLocation::PARAMETER: { |
1797 // The parameter indices are shifted by 1 (receiver is variable | 1803 // The parameter indices are shifted by 1 (receiver is variable |
1798 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 1804 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
1799 Register source = builder()->Parameter(variable->index() + 1); | 1805 Register source = builder()->Parameter(variable->index() + 1); |
1800 // We need to load the variable into the accumulator, even when in a | 1806 // We need to load the variable into the accumulator, even when in a |
1801 // VisitForRegisterScope, in order to avoid register aliasing if | 1807 // VisitForRegisterScope, in order to avoid register aliasing if |
1802 // subsequent expressions assign to the same variable. | 1808 // subsequent expressions assign to the same variable. |
1803 builder()->LoadAccumulatorWithRegister(source); | 1809 builder()->LoadAccumulatorWithRegister(source); |
1804 if (needs_hole_check) BuildThrowIfHole(variable->name()); | 1810 if (hole_check_mode == HoleCheckMode::kRequired) { |
| 1811 BuildThrowIfHole(variable->name()); |
| 1812 } |
1805 break; | 1813 break; |
1806 } | 1814 } |
1807 case VariableLocation::UNALLOCATED: { | 1815 case VariableLocation::UNALLOCATED: { |
1808 builder()->LoadGlobal(feedback_index(slot), typeof_mode); | 1816 builder()->LoadGlobal(feedback_index(slot), typeof_mode); |
1809 break; | 1817 break; |
1810 } | 1818 } |
1811 case VariableLocation::CONTEXT: { | 1819 case VariableLocation::CONTEXT: { |
1812 int depth = execution_context()->ContextChainDepth(variable->scope()); | 1820 int depth = execution_context()->ContextChainDepth(variable->scope()); |
1813 ContextScope* context = execution_context()->Previous(depth); | 1821 ContextScope* context = execution_context()->Previous(depth); |
1814 Register context_reg; | 1822 Register context_reg; |
1815 if (context) { | 1823 if (context) { |
1816 context_reg = context->reg(); | 1824 context_reg = context->reg(); |
1817 depth = 0; | 1825 depth = 0; |
1818 } else { | 1826 } else { |
1819 context_reg = execution_context()->reg(); | 1827 context_reg = execution_context()->reg(); |
1820 } | 1828 } |
1821 | 1829 |
1822 builder()->LoadContextSlot(context_reg, variable->index(), depth); | 1830 builder()->LoadContextSlot(context_reg, variable->index(), depth); |
1823 if (needs_hole_check) BuildThrowIfHole(variable->name()); | 1831 if (hole_check_mode == HoleCheckMode::kRequired) { |
| 1832 BuildThrowIfHole(variable->name()); |
| 1833 } |
1824 break; | 1834 break; |
1825 } | 1835 } |
1826 case VariableLocation::LOOKUP: { | 1836 case VariableLocation::LOOKUP: { |
1827 switch (variable->mode()) { | 1837 switch (variable->mode()) { |
1828 case DYNAMIC_LOCAL: { | 1838 case DYNAMIC_LOCAL: { |
1829 Variable* local_variable = variable->local_if_not_shadowed(); | 1839 Variable* local_variable = variable->local_if_not_shadowed(); |
1830 int depth = | 1840 int depth = |
1831 execution_context()->ContextChainDepth(local_variable->scope()); | 1841 execution_context()->ContextChainDepth(local_variable->scope()); |
1832 builder()->LoadLookupContextSlot(variable->name(), typeof_mode, | 1842 builder()->LoadLookupContextSlot(variable->name(), typeof_mode, |
1833 local_variable->index(), depth); | 1843 local_variable->index(), depth); |
1834 if (needs_hole_check) BuildThrowIfHole(variable->name()); | 1844 if (hole_check_mode == HoleCheckMode::kRequired) { |
| 1845 BuildThrowIfHole(variable->name()); |
| 1846 } |
1835 break; | 1847 break; |
1836 } | 1848 } |
1837 case DYNAMIC_GLOBAL: { | 1849 case DYNAMIC_GLOBAL: { |
1838 int depth = scope()->ContextChainLengthUntilOutermostSloppyEval(); | 1850 int depth = scope()->ContextChainLengthUntilOutermostSloppyEval(); |
1839 builder()->LoadLookupGlobalSlot(variable->name(), typeof_mode, | 1851 builder()->LoadLookupGlobalSlot(variable->name(), typeof_mode, |
1840 feedback_index(slot), depth); | 1852 feedback_index(slot), depth); |
1841 break; | 1853 break; |
1842 } | 1854 } |
1843 default: | 1855 default: |
1844 builder()->LoadLookupSlot(variable->name(), typeof_mode); | 1856 builder()->LoadLookupSlot(variable->name(), typeof_mode); |
(...skipping 14 matching lines...) Expand all Loading... |
1859 auto it = descriptor->regular_imports().find(variable->raw_name()); | 1871 auto it = descriptor->regular_imports().find(variable->raw_name()); |
1860 DCHECK(it != descriptor->regular_imports().end()); | 1872 DCHECK(it != descriptor->regular_imports().end()); |
1861 RegisterList args = register_allocator()->NewRegisterList(2); | 1873 RegisterList args = register_allocator()->NewRegisterList(2); |
1862 builder() | 1874 builder() |
1863 ->LoadLiteral(it->second->import_name->string()) | 1875 ->LoadLiteral(it->second->import_name->string()) |
1864 .StoreAccumulatorInRegister(args[0]) | 1876 .StoreAccumulatorInRegister(args[0]) |
1865 .LoadLiteral(Smi::FromInt(it->second->module_request)) | 1877 .LoadLiteral(Smi::FromInt(it->second->module_request)) |
1866 .StoreAccumulatorInRegister(args[1]) | 1878 .StoreAccumulatorInRegister(args[1]) |
1867 .CallRuntime(Runtime::kLoadModuleImport, args); | 1879 .CallRuntime(Runtime::kLoadModuleImport, args); |
1868 } | 1880 } |
1869 if (needs_hole_check) BuildThrowIfHole(variable->name()); | 1881 if (hole_check_mode == HoleCheckMode::kRequired) { |
| 1882 BuildThrowIfHole(variable->name()); |
| 1883 } |
1870 break; | 1884 break; |
1871 } | 1885 } |
1872 } | 1886 } |
1873 } | 1887 } |
1874 | 1888 |
1875 void BytecodeGenerator::BuildVariableLoadForAccumulatorValue( | 1889 void BytecodeGenerator::BuildVariableLoadForAccumulatorValue( |
1876 Variable* variable, FeedbackVectorSlot slot, bool needs_hole_check, | 1890 Variable* variable, FeedbackVectorSlot slot, HoleCheckMode hole_check_mode, |
1877 TypeofMode typeof_mode) { | 1891 TypeofMode typeof_mode) { |
1878 ValueResultScope accumulator_result(this); | 1892 ValueResultScope accumulator_result(this); |
1879 BuildVariableLoad(variable, slot, needs_hole_check, typeof_mode); | 1893 BuildVariableLoad(variable, slot, hole_check_mode, typeof_mode); |
1880 } | 1894 } |
1881 | 1895 |
1882 void BytecodeGenerator::BuildReturn() { | 1896 void BytecodeGenerator::BuildReturn() { |
1883 if (FLAG_trace) { | 1897 if (FLAG_trace) { |
1884 RegisterAllocationScope register_scope(this); | 1898 RegisterAllocationScope register_scope(this); |
1885 Register result = register_allocator()->NewRegister(); | 1899 Register result = register_allocator()->NewRegister(); |
1886 // Runtime returns {result} value, preserving accumulator. | 1900 // Runtime returns {result} value, preserving accumulator. |
1887 builder()->StoreAccumulatorInRegister(result).CallRuntime( | 1901 builder()->StoreAccumulatorInRegister(result).CallRuntime( |
1888 Runtime::kTraceExit, result); | 1902 Runtime::kTraceExit, result); |
1889 } | 1903 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1941 // Perform an initialization check for 'this'. 'this' variable is the | 1955 // Perform an initialization check for 'this'. 'this' variable is the |
1942 // only variable able to trigger bind operations outside the TDZ | 1956 // only variable able to trigger bind operations outside the TDZ |
1943 // via 'super' calls. | 1957 // via 'super' calls. |
1944 BuildThrowIfNotHole(variable->name()); | 1958 BuildThrowIfNotHole(variable->name()); |
1945 } | 1959 } |
1946 } | 1960 } |
1947 | 1961 |
1948 void BytecodeGenerator::BuildVariableAssignment(Variable* variable, | 1962 void BytecodeGenerator::BuildVariableAssignment(Variable* variable, |
1949 Token::Value op, | 1963 Token::Value op, |
1950 FeedbackVectorSlot slot, | 1964 FeedbackVectorSlot slot, |
1951 bool needs_hole_check) { | 1965 HoleCheckMode hole_check_mode) { |
1952 VariableMode mode = variable->mode(); | 1966 VariableMode mode = variable->mode(); |
1953 RegisterAllocationScope assignment_register_scope(this); | 1967 RegisterAllocationScope assignment_register_scope(this); |
1954 BytecodeLabel end_label; | 1968 BytecodeLabel end_label; |
1955 switch (variable->location()) { | 1969 switch (variable->location()) { |
1956 case VariableLocation::PARAMETER: | 1970 case VariableLocation::PARAMETER: |
1957 case VariableLocation::LOCAL: { | 1971 case VariableLocation::LOCAL: { |
1958 Register destination; | 1972 Register destination; |
1959 if (VariableLocation::PARAMETER == variable->location()) { | 1973 if (VariableLocation::PARAMETER == variable->location()) { |
1960 destination = Register(builder()->Parameter(variable->index() + 1)); | 1974 destination = Register(builder()->Parameter(variable->index() + 1)); |
1961 } else { | 1975 } else { |
1962 destination = Register(variable->index()); | 1976 destination = Register(variable->index()); |
1963 } | 1977 } |
1964 | 1978 |
1965 if (needs_hole_check) { | 1979 if (hole_check_mode == HoleCheckMode::kRequired) { |
1966 // Load destination to check for hole. | 1980 // Load destination to check for hole. |
1967 Register value_temp = register_allocator()->NewRegister(); | 1981 Register value_temp = register_allocator()->NewRegister(); |
1968 builder() | 1982 builder() |
1969 ->StoreAccumulatorInRegister(value_temp) | 1983 ->StoreAccumulatorInRegister(value_temp) |
1970 .LoadAccumulatorWithRegister(destination); | 1984 .LoadAccumulatorWithRegister(destination); |
1971 | 1985 |
1972 BuildHoleCheckForVariableAssignment(variable, op); | 1986 BuildHoleCheckForVariableAssignment(variable, op); |
1973 builder()->LoadAccumulatorWithRegister(value_temp); | 1987 builder()->LoadAccumulatorWithRegister(value_temp); |
1974 } | 1988 } |
1975 | 1989 |
(...skipping 14 matching lines...) Expand all Loading... |
1990 ContextScope* context = execution_context()->Previous(depth); | 2004 ContextScope* context = execution_context()->Previous(depth); |
1991 Register context_reg; | 2005 Register context_reg; |
1992 | 2006 |
1993 if (context) { | 2007 if (context) { |
1994 context_reg = context->reg(); | 2008 context_reg = context->reg(); |
1995 depth = 0; | 2009 depth = 0; |
1996 } else { | 2010 } else { |
1997 context_reg = execution_context()->reg(); | 2011 context_reg = execution_context()->reg(); |
1998 } | 2012 } |
1999 | 2013 |
2000 if (needs_hole_check) { | 2014 if (hole_check_mode == HoleCheckMode::kRequired) { |
2001 // Load destination to check for hole. | 2015 // Load destination to check for hole. |
2002 Register value_temp = register_allocator()->NewRegister(); | 2016 Register value_temp = register_allocator()->NewRegister(); |
2003 builder() | 2017 builder() |
2004 ->StoreAccumulatorInRegister(value_temp) | 2018 ->StoreAccumulatorInRegister(value_temp) |
2005 .LoadContextSlot(context_reg, variable->index(), depth); | 2019 .LoadContextSlot(context_reg, variable->index(), depth); |
2006 | 2020 |
2007 BuildHoleCheckForVariableAssignment(variable, op); | 2021 BuildHoleCheckForVariableAssignment(variable, op); |
2008 builder()->LoadAccumulatorWithRegister(value_temp); | 2022 builder()->LoadAccumulatorWithRegister(value_temp); |
2009 } | 2023 } |
2010 | 2024 |
(...skipping 25 matching lines...) Expand all Loading... |
2036 // There may be several export names for this local name, but it doesn't | 2050 // There may be several export names for this local name, but it doesn't |
2037 // matter which one we pick, as they all map to the same cell. | 2051 // matter which one we pick, as they all map to the same cell. |
2038 auto it = mod->regular_exports().find(variable->raw_name()); | 2052 auto it = mod->regular_exports().find(variable->raw_name()); |
2039 DCHECK(it != mod->regular_exports().end()); | 2053 DCHECK(it != mod->regular_exports().end()); |
2040 | 2054 |
2041 RegisterList args = register_allocator()->NewRegisterList(2); | 2055 RegisterList args = register_allocator()->NewRegisterList(2); |
2042 builder() | 2056 builder() |
2043 ->StoreAccumulatorInRegister(args[1]) | 2057 ->StoreAccumulatorInRegister(args[1]) |
2044 .LoadLiteral(it->second->export_name->string()) | 2058 .LoadLiteral(it->second->export_name->string()) |
2045 .StoreAccumulatorInRegister(args[0]); | 2059 .StoreAccumulatorInRegister(args[0]); |
2046 if (needs_hole_check) { | 2060 if (hole_check_mode == HoleCheckMode::kRequired) { |
2047 builder()->CallRuntime(Runtime::kLoadModuleExport, args[0]); | 2061 builder()->CallRuntime(Runtime::kLoadModuleExport, args[0]); |
2048 BuildHoleCheckForVariableAssignment(variable, op); | 2062 BuildHoleCheckForVariableAssignment(variable, op); |
2049 } | 2063 } |
2050 builder() | 2064 builder() |
2051 ->CallRuntime(Runtime::kStoreModuleExport, args) | 2065 ->CallRuntime(Runtime::kStoreModuleExport, args) |
2052 .LoadAccumulatorWithRegister(args[1]); | 2066 .LoadAccumulatorWithRegister(args[1]); |
2053 break; | 2067 break; |
2054 } | 2068 } |
2055 } | 2069 } |
2056 } | 2070 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2105 } | 2119 } |
2106 | 2120 |
2107 // Evaluate the value and potentially handle compound assignments by loading | 2121 // Evaluate the value and potentially handle compound assignments by loading |
2108 // the left-hand side value and performing a binary operation. | 2122 // the left-hand side value and performing a binary operation. |
2109 if (expr->is_compound()) { | 2123 if (expr->is_compound()) { |
2110 Register old_value = register_allocator()->NewRegister(); | 2124 Register old_value = register_allocator()->NewRegister(); |
2111 switch (assign_type) { | 2125 switch (assign_type) { |
2112 case VARIABLE: { | 2126 case VARIABLE: { |
2113 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 2127 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
2114 BuildVariableLoad(proxy->var(), proxy->VariableFeedbackSlot(), | 2128 BuildVariableLoad(proxy->var(), proxy->VariableFeedbackSlot(), |
2115 proxy->needs_hole_check()); | 2129 proxy->hole_check_mode()); |
2116 builder()->StoreAccumulatorInRegister(old_value); | 2130 builder()->StoreAccumulatorInRegister(old_value); |
2117 break; | 2131 break; |
2118 } | 2132 } |
2119 case NAMED_PROPERTY: { | 2133 case NAMED_PROPERTY: { |
2120 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); | 2134 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); |
2121 builder() | 2135 builder() |
2122 ->LoadNamedProperty(object, name, feedback_index(slot)) | 2136 ->LoadNamedProperty(object, name, feedback_index(slot)) |
2123 .StoreAccumulatorInRegister(old_value); | 2137 .StoreAccumulatorInRegister(old_value); |
2124 break; | 2138 break; |
2125 } | 2139 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2158 | 2172 |
2159 // Store the value. | 2173 // Store the value. |
2160 builder()->SetExpressionPosition(expr); | 2174 builder()->SetExpressionPosition(expr); |
2161 FeedbackVectorSlot slot = expr->AssignmentSlot(); | 2175 FeedbackVectorSlot slot = expr->AssignmentSlot(); |
2162 switch (assign_type) { | 2176 switch (assign_type) { |
2163 case VARIABLE: { | 2177 case VARIABLE: { |
2164 // TODO(oth): The BuildVariableAssignment() call is hard to reason about. | 2178 // TODO(oth): The BuildVariableAssignment() call is hard to reason about. |
2165 // Is the value in the accumulator safe? Yes, but scary. | 2179 // Is the value in the accumulator safe? Yes, but scary. |
2166 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 2180 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
2167 BuildVariableAssignment(proxy->var(), expr->op(), slot, | 2181 BuildVariableAssignment(proxy->var(), expr->op(), slot, |
2168 proxy->needs_hole_check()); | 2182 proxy->hole_check_mode()); |
2169 break; | 2183 break; |
2170 } | 2184 } |
2171 case NAMED_PROPERTY: | 2185 case NAMED_PROPERTY: |
2172 builder()->StoreNamedProperty(object, name, feedback_index(slot), | 2186 builder()->StoreNamedProperty(object, name, feedback_index(slot), |
2173 language_mode()); | 2187 language_mode()); |
2174 break; | 2188 break; |
2175 case KEYED_PROPERTY: | 2189 case KEYED_PROPERTY: |
2176 builder()->StoreKeyedProperty(object, key, feedback_index(slot), | 2190 builder()->StoreKeyedProperty(object, key, feedback_index(slot), |
2177 language_mode()); | 2191 language_mode()); |
2178 break; | 2192 break; |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2386 builder()->StoreAccumulatorInRegister(callee); | 2400 builder()->StoreAccumulatorInRegister(callee); |
2387 break; | 2401 break; |
2388 } | 2402 } |
2389 case Call::GLOBAL_CALL: { | 2403 case Call::GLOBAL_CALL: { |
2390 // Receiver is undefined for global calls. | 2404 // Receiver is undefined for global calls. |
2391 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); | 2405 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); |
2392 // Load callee as a global variable. | 2406 // Load callee as a global variable. |
2393 VariableProxy* proxy = callee_expr->AsVariableProxy(); | 2407 VariableProxy* proxy = callee_expr->AsVariableProxy(); |
2394 BuildVariableLoadForAccumulatorValue(proxy->var(), | 2408 BuildVariableLoadForAccumulatorValue(proxy->var(), |
2395 proxy->VariableFeedbackSlot(), | 2409 proxy->VariableFeedbackSlot(), |
2396 proxy->needs_hole_check()); | 2410 proxy->hole_check_mode()); |
2397 builder()->StoreAccumulatorInRegister(callee); | 2411 builder()->StoreAccumulatorInRegister(callee); |
2398 break; | 2412 break; |
2399 } | 2413 } |
2400 case Call::LOOKUP_SLOT_CALL: | 2414 case Call::LOOKUP_SLOT_CALL: |
2401 case Call::POSSIBLY_EVAL_CALL: { | 2415 case Call::POSSIBLY_EVAL_CALL: { |
2402 if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) { | 2416 if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) { |
2403 RegisterAllocationScope inner_register_scope(this); | 2417 RegisterAllocationScope inner_register_scope(this); |
2404 Register name = register_allocator()->NewRegister(); | 2418 Register name = register_allocator()->NewRegister(); |
2405 | 2419 |
2406 // Call %LoadLookupSlotForCall to get the callee and receiver. | 2420 // Call %LoadLookupSlotForCall to get the callee and receiver. |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2544 VisitForEffect(expr->expression()); | 2558 VisitForEffect(expr->expression()); |
2545 builder()->LoadUndefined(); | 2559 builder()->LoadUndefined(); |
2546 } | 2560 } |
2547 | 2561 |
2548 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { | 2562 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { |
2549 if (expr->expression()->IsVariableProxy()) { | 2563 if (expr->expression()->IsVariableProxy()) { |
2550 // Typeof does not throw a reference error on global variables, hence we | 2564 // Typeof does not throw a reference error on global variables, hence we |
2551 // perform a non-contextual load in case the operand is a variable proxy. | 2565 // perform a non-contextual load in case the operand is a variable proxy. |
2552 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 2566 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
2553 BuildVariableLoadForAccumulatorValue( | 2567 BuildVariableLoadForAccumulatorValue( |
2554 proxy->var(), proxy->VariableFeedbackSlot(), proxy->needs_hole_check(), | 2568 proxy->var(), proxy->VariableFeedbackSlot(), proxy->hole_check_mode(), |
2555 INSIDE_TYPEOF); | 2569 INSIDE_TYPEOF); |
2556 } else { | 2570 } else { |
2557 VisitForAccumulatorValue(expr->expression()); | 2571 VisitForAccumulatorValue(expr->expression()); |
2558 } | 2572 } |
2559 builder()->TypeOf(); | 2573 builder()->TypeOf(); |
2560 } | 2574 } |
2561 | 2575 |
2562 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { | 2576 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { |
2563 if (execution_result()->IsEffect()) { | 2577 if (execution_result()->IsEffect()) { |
2564 VisitForEffect(expr->expression()); | 2578 VisitForEffect(expr->expression()); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2671 | 2685 |
2672 // Evaluate LHS expression and get old value. | 2686 // Evaluate LHS expression and get old value. |
2673 Register object, key, old_value; | 2687 Register object, key, old_value; |
2674 RegisterList super_property_args; | 2688 RegisterList super_property_args; |
2675 Handle<String> name; | 2689 Handle<String> name; |
2676 switch (assign_type) { | 2690 switch (assign_type) { |
2677 case VARIABLE: { | 2691 case VARIABLE: { |
2678 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 2692 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
2679 BuildVariableLoadForAccumulatorValue(proxy->var(), | 2693 BuildVariableLoadForAccumulatorValue(proxy->var(), |
2680 proxy->VariableFeedbackSlot(), | 2694 proxy->VariableFeedbackSlot(), |
2681 proxy->needs_hole_check()); | 2695 proxy->hole_check_mode()); |
2682 break; | 2696 break; |
2683 } | 2697 } |
2684 case NAMED_PROPERTY: { | 2698 case NAMED_PROPERTY: { |
2685 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); | 2699 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); |
2686 object = VisitForRegisterValue(property->obj()); | 2700 object = VisitForRegisterValue(property->obj()); |
2687 name = property->key()->AsLiteral()->AsPropertyName(); | 2701 name = property->key()->AsLiteral()->AsPropertyName(); |
2688 builder()->LoadNamedProperty(object, name, feedback_index(slot)); | 2702 builder()->LoadNamedProperty(object, name, feedback_index(slot)); |
2689 break; | 2703 break; |
2690 } | 2704 } |
2691 case KEYED_PROPERTY: { | 2705 case KEYED_PROPERTY: { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2736 FeedbackVectorSlot slot = expr->CountBinaryOpFeedbackSlot(); | 2750 FeedbackVectorSlot slot = expr->CountBinaryOpFeedbackSlot(); |
2737 builder()->CountOperation(expr->binary_op(), feedback_index(slot)); | 2751 builder()->CountOperation(expr->binary_op(), feedback_index(slot)); |
2738 | 2752 |
2739 // Store the value. | 2753 // Store the value. |
2740 builder()->SetExpressionPosition(expr); | 2754 builder()->SetExpressionPosition(expr); |
2741 FeedbackVectorSlot feedback_slot = expr->CountSlot(); | 2755 FeedbackVectorSlot feedback_slot = expr->CountSlot(); |
2742 switch (assign_type) { | 2756 switch (assign_type) { |
2743 case VARIABLE: { | 2757 case VARIABLE: { |
2744 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 2758 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
2745 BuildVariableAssignment(proxy->var(), expr->op(), feedback_slot, | 2759 BuildVariableAssignment(proxy->var(), expr->op(), feedback_slot, |
2746 proxy->needs_hole_check()); | 2760 proxy->hole_check_mode()); |
2747 break; | 2761 break; |
2748 } | 2762 } |
2749 case NAMED_PROPERTY: { | 2763 case NAMED_PROPERTY: { |
2750 builder()->StoreNamedProperty(object, name, feedback_index(feedback_slot), | 2764 builder()->StoreNamedProperty(object, name, feedback_index(feedback_slot), |
2751 language_mode()); | 2765 language_mode()); |
2752 break; | 2766 break; |
2753 } | 2767 } |
2754 case KEYED_PROPERTY: { | 2768 case KEYED_PROPERTY: { |
2755 builder()->StoreKeyedProperty(object, key, feedback_index(feedback_slot), | 2769 builder()->StoreKeyedProperty(object, key, feedback_index(feedback_slot), |
2756 language_mode()); | 2770 language_mode()); |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3029 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated()); | 3043 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated()); |
3030 | 3044 |
3031 // Allocate and initialize a new arguments object and assign to the | 3045 // Allocate and initialize a new arguments object and assign to the |
3032 // {arguments} variable. | 3046 // {arguments} variable. |
3033 CreateArgumentsType type = | 3047 CreateArgumentsType type = |
3034 is_strict(language_mode()) || !info()->has_simple_parameters() | 3048 is_strict(language_mode()) || !info()->has_simple_parameters() |
3035 ? CreateArgumentsType::kUnmappedArguments | 3049 ? CreateArgumentsType::kUnmappedArguments |
3036 : CreateArgumentsType::kMappedArguments; | 3050 : CreateArgumentsType::kMappedArguments; |
3037 builder()->CreateArguments(type); | 3051 builder()->CreateArguments(type); |
3038 BuildVariableAssignment(variable, Token::ASSIGN, | 3052 BuildVariableAssignment(variable, Token::ASSIGN, |
3039 FeedbackVectorSlot::Invalid(), false); | 3053 FeedbackVectorSlot::Invalid(), |
| 3054 HoleCheckMode::kElided); |
3040 } | 3055 } |
3041 | 3056 |
3042 void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) { | 3057 void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) { |
3043 if (rest == nullptr) return; | 3058 if (rest == nullptr) return; |
3044 | 3059 |
3045 // Allocate and initialize a new rest parameter and assign to the {rest} | 3060 // Allocate and initialize a new rest parameter and assign to the {rest} |
3046 // variable. | 3061 // variable. |
3047 builder()->CreateArguments(CreateArgumentsType::kRestParameter); | 3062 builder()->CreateArguments(CreateArgumentsType::kRestParameter); |
3048 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated()); | 3063 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated()); |
3049 BuildVariableAssignment(rest, Token::ASSIGN, FeedbackVectorSlot::Invalid(), | 3064 BuildVariableAssignment(rest, Token::ASSIGN, FeedbackVectorSlot::Invalid(), |
3050 false); | 3065 HoleCheckMode::kElided); |
3051 } | 3066 } |
3052 | 3067 |
3053 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { | 3068 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { |
3054 if (variable == nullptr) return; | 3069 if (variable == nullptr) return; |
3055 | 3070 |
3056 // Store the closure we were called with in the given variable. | 3071 // Store the closure we were called with in the given variable. |
3057 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 3072 builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
3058 BuildVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid(), | 3073 BuildVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid(), |
3059 false); | 3074 HoleCheckMode::kElided); |
3060 } | 3075 } |
3061 | 3076 |
3062 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { | 3077 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { |
3063 if (variable == nullptr) return; | 3078 if (variable == nullptr) return; |
3064 | 3079 |
3065 // Store the new target we were called with in the given variable. | 3080 // Store the new target we were called with in the given variable. |
3066 builder()->LoadAccumulatorWithRegister(Register::new_target()); | 3081 builder()->LoadAccumulatorWithRegister(Register::new_target()); |
3067 BuildVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid(), | 3082 BuildVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid(), |
3068 false); | 3083 HoleCheckMode::kElided); |
3069 | 3084 |
3070 // TODO(mstarzinger): The <new.target> register is not set by the deoptimizer | 3085 // TODO(mstarzinger): The <new.target> register is not set by the deoptimizer |
3071 // and we need to make sure {BytecodeRegisterOptimizer} flushes its state | 3086 // and we need to make sure {BytecodeRegisterOptimizer} flushes its state |
3072 // before a local variable containing the <new.target> is used. Using a label | 3087 // before a local variable containing the <new.target> is used. Using a label |
3073 // as below flushes the entire pipeline, we should be more specific here. | 3088 // as below flushes the entire pipeline, we should be more specific here. |
3074 BytecodeLabel flush_state_label; | 3089 BytecodeLabel flush_state_label; |
3075 builder()->Bind(&flush_state_label); | 3090 builder()->Bind(&flush_state_label); |
3076 } | 3091 } |
3077 | 3092 |
3078 void BytecodeGenerator::VisitFunctionClosureForContext() { | 3093 void BytecodeGenerator::VisitFunctionClosureForContext() { |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3189 } | 3204 } |
3190 | 3205 |
3191 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { | 3206 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { |
3192 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 3207 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict |
3193 : Runtime::kStoreKeyedToSuper_Sloppy; | 3208 : Runtime::kStoreKeyedToSuper_Sloppy; |
3194 } | 3209 } |
3195 | 3210 |
3196 } // namespace interpreter | 3211 } // namespace interpreter |
3197 } // namespace internal | 3212 } // namespace internal |
3198 } // namespace v8 | 3213 } // namespace v8 |
OLD | NEW |