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 811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
822 | 822 |
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 VisitVariableAssignment(variable, Token::INIT, | 832 BuildVariableAssignment(variable, Token::INIT, |
833 FeedbackVectorSlot::Invalid()); | 833 FeedbackVectorSlot::Invalid(), false); |
834 } | 834 } |
835 // Nothing to do for imports. | 835 // Nothing to do for imports. |
836 break; | 836 break; |
837 } | 837 } |
838 } | 838 } |
839 | 839 |
840 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { | 840 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { |
841 Variable* variable = decl->proxy()->var(); | 841 Variable* variable = decl->proxy()->var(); |
842 DCHECK(variable->mode() == LET || variable->mode() == VAR); | 842 DCHECK(variable->mode() == LET || variable->mode() == VAR); |
843 switch (variable->location()) { | 843 switch (variable->location()) { |
844 case VariableLocation::UNALLOCATED: { | 844 case VariableLocation::UNALLOCATED: { |
845 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); | 845 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); |
846 globals_builder()->AddFunctionDeclaration(slot, decl->fun()); | 846 globals_builder()->AddFunctionDeclaration(slot, decl->fun()); |
847 break; | 847 break; |
848 } | 848 } |
849 case VariableLocation::PARAMETER: | 849 case VariableLocation::PARAMETER: |
850 case VariableLocation::LOCAL: { | 850 case VariableLocation::LOCAL: { |
851 VisitForAccumulatorValue(decl->fun()); | 851 VisitForAccumulatorValue(decl->fun()); |
852 VisitVariableAssignment(variable, Token::INIT, | 852 BuildVariableAssignment(variable, Token::INIT, |
853 FeedbackVectorSlot::Invalid()); | 853 FeedbackVectorSlot::Invalid(), false); |
854 break; | 854 break; |
855 } | 855 } |
856 case VariableLocation::CONTEXT: { | 856 case VariableLocation::CONTEXT: { |
857 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); | 857 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); |
858 VisitForAccumulatorValue(decl->fun()); | 858 VisitForAccumulatorValue(decl->fun()); |
859 builder()->StoreContextSlot(execution_context()->reg(), variable->index(), | 859 builder()->StoreContextSlot(execution_context()->reg(), variable->index(), |
860 0); | 860 0); |
861 break; | 861 break; |
862 } | 862 } |
863 case VariableLocation::LOOKUP: { | 863 case VariableLocation::LOOKUP: { |
864 RegisterList args = register_allocator()->NewRegisterList(2); | 864 RegisterList args = register_allocator()->NewRegisterList(2); |
865 builder() | 865 builder() |
866 ->LoadLiteral(variable->name()) | 866 ->LoadLiteral(variable->name()) |
867 .StoreAccumulatorInRegister(args[0]); | 867 .StoreAccumulatorInRegister(args[0]); |
868 VisitForAccumulatorValue(decl->fun()); | 868 VisitForAccumulatorValue(decl->fun()); |
869 builder()->StoreAccumulatorInRegister(args[1]).CallRuntime( | 869 builder()->StoreAccumulatorInRegister(args[1]).CallRuntime( |
870 Runtime::kDeclareEvalFunction, args); | 870 Runtime::kDeclareEvalFunction, args); |
871 break; | 871 break; |
872 } | 872 } |
873 case VariableLocation::MODULE: | 873 case VariableLocation::MODULE: |
874 DCHECK_EQ(variable->mode(), LET); | 874 DCHECK_EQ(variable->mode(), LET); |
875 DCHECK(variable->IsExport()); | 875 DCHECK(variable->IsExport()); |
876 VisitForAccumulatorValue(decl->fun()); | 876 VisitForAccumulatorValue(decl->fun()); |
877 VisitVariableAssignment(variable, Token::INIT, | 877 BuildVariableAssignment(variable, Token::INIT, |
878 FeedbackVectorSlot::Invalid()); | 878 FeedbackVectorSlot::Invalid(), false); |
879 break; | 879 break; |
880 } | 880 } |
881 } | 881 } |
882 | 882 |
883 void BytecodeGenerator::VisitModuleNamespaceImports() { | 883 void BytecodeGenerator::VisitModuleNamespaceImports() { |
884 if (!scope()->is_module_scope()) return; | 884 if (!scope()->is_module_scope()) return; |
885 | 885 |
886 RegisterAllocationScope register_scope(this); | 886 RegisterAllocationScope register_scope(this); |
887 Register module_request = register_allocator()->NewRegister(); | 887 Register module_request = register_allocator()->NewRegister(); |
888 | 888 |
889 ModuleDescriptor* descriptor = scope()->AsModuleScope()->module(); | 889 ModuleDescriptor* descriptor = scope()->AsModuleScope()->module(); |
890 for (auto entry : descriptor->namespace_imports()) { | 890 for (auto entry : descriptor->namespace_imports()) { |
891 builder() | 891 builder() |
892 ->LoadLiteral(Smi::FromInt(entry->module_request)) | 892 ->LoadLiteral(Smi::FromInt(entry->module_request)) |
893 .StoreAccumulatorInRegister(module_request) | 893 .StoreAccumulatorInRegister(module_request) |
894 .CallRuntime(Runtime::kGetModuleNamespace, module_request); | 894 .CallRuntime(Runtime::kGetModuleNamespace, module_request); |
895 Variable* var = scope()->LookupLocal(entry->local_name); | 895 Variable* var = scope()->LookupLocal(entry->local_name); |
896 DCHECK_NOT_NULL(var); | 896 DCHECK_NOT_NULL(var); |
897 VisitVariableAssignment(var, Token::INIT, FeedbackVectorSlot::Invalid()); | 897 BuildVariableAssignment(var, Token::INIT, FeedbackVectorSlot::Invalid(), |
| 898 false); |
898 } | 899 } |
899 } | 900 } |
900 | 901 |
901 void BytecodeGenerator::VisitDeclarations( | 902 void BytecodeGenerator::VisitDeclarations( |
902 ZoneList<Declaration*>* declarations) { | 903 ZoneList<Declaration*>* declarations) { |
903 RegisterAllocationScope register_scope(this); | 904 RegisterAllocationScope register_scope(this); |
904 DCHECK(globals_builder()->empty()); | 905 DCHECK(globals_builder()->empty()); |
905 for (int i = 0; i < declarations->length(); i++) { | 906 for (int i = 0; i < declarations->length(); i++) { |
906 RegisterAllocationScope register_scope(this); | 907 RegisterAllocationScope register_scope(this); |
907 Visit(declarations->at(i)); | 908 Visit(declarations->at(i)); |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1140 void BytecodeGenerator::VisitForInAssignment(Expression* expr, | 1141 void BytecodeGenerator::VisitForInAssignment(Expression* expr, |
1141 FeedbackVectorSlot slot) { | 1142 FeedbackVectorSlot slot) { |
1142 DCHECK(expr->IsValidReferenceExpression()); | 1143 DCHECK(expr->IsValidReferenceExpression()); |
1143 | 1144 |
1144 // Evaluate assignment starting with the value to be stored in the | 1145 // Evaluate assignment starting with the value to be stored in the |
1145 // accumulator. | 1146 // accumulator. |
1146 Property* property = expr->AsProperty(); | 1147 Property* property = expr->AsProperty(); |
1147 LhsKind assign_type = Property::GetAssignType(property); | 1148 LhsKind assign_type = Property::GetAssignType(property); |
1148 switch (assign_type) { | 1149 switch (assign_type) { |
1149 case VARIABLE: { | 1150 case VARIABLE: { |
1150 Variable* variable = expr->AsVariableProxy()->var(); | 1151 VariableProxy* proxy = expr->AsVariableProxy(); |
1151 VisitVariableAssignment(variable, Token::ASSIGN, slot); | 1152 BuildVariableAssignment(proxy->var(), Token::ASSIGN, slot, |
| 1153 proxy->needs_hole_check()); |
1152 break; | 1154 break; |
1153 } | 1155 } |
1154 case NAMED_PROPERTY: { | 1156 case NAMED_PROPERTY: { |
1155 RegisterAllocationScope register_scope(this); | 1157 RegisterAllocationScope register_scope(this); |
1156 Register value = register_allocator()->NewRegister(); | 1158 Register value = register_allocator()->NewRegister(); |
1157 builder()->StoreAccumulatorInRegister(value); | 1159 builder()->StoreAccumulatorInRegister(value); |
1158 Register object = VisitForRegisterValue(property->obj()); | 1160 Register object = VisitForRegisterValue(property->obj()); |
1159 Handle<String> name = property->key()->AsLiteral()->AsPropertyName(); | 1161 Handle<String> name = property->key()->AsLiteral()->AsPropertyName(); |
1160 builder()->LoadAccumulatorWithRegister(value); | 1162 builder()->LoadAccumulatorWithRegister(value); |
1161 builder()->StoreNamedProperty(object, name, feedback_index(slot), | 1163 builder()->StoreNamedProperty(object, name, feedback_index(slot), |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1388 FeedbackVectorSlot slot = expr->PrototypeSlot(); | 1390 FeedbackVectorSlot slot = expr->PrototypeSlot(); |
1389 builder() | 1391 builder() |
1390 ->StoreAccumulatorInRegister(literal) | 1392 ->StoreAccumulatorInRegister(literal) |
1391 .LoadNamedProperty(literal, prototype_string(), feedback_index(slot)) | 1393 .LoadNamedProperty(literal, prototype_string(), feedback_index(slot)) |
1392 .StoreAccumulatorInRegister(prototype); | 1394 .StoreAccumulatorInRegister(prototype); |
1393 | 1395 |
1394 VisitClassLiteralProperties(expr, literal, prototype); | 1396 VisitClassLiteralProperties(expr, literal, prototype); |
1395 builder()->CallRuntime(Runtime::kToFastProperties, literal); | 1397 builder()->CallRuntime(Runtime::kToFastProperties, literal); |
1396 // Assign to class variable. | 1398 // Assign to class variable. |
1397 if (expr->class_variable_proxy() != nullptr) { | 1399 if (expr->class_variable_proxy() != nullptr) { |
1398 Variable* var = expr->class_variable_proxy()->var(); | 1400 VariableProxy* proxy = expr->class_variable_proxy(); |
1399 FeedbackVectorSlot slot = expr->NeedsProxySlot() | 1401 FeedbackVectorSlot slot = expr->NeedsProxySlot() |
1400 ? expr->ProxySlot() | 1402 ? expr->ProxySlot() |
1401 : FeedbackVectorSlot::Invalid(); | 1403 : FeedbackVectorSlot::Invalid(); |
1402 VisitVariableAssignment(var, Token::INIT, slot); | 1404 BuildVariableAssignment(proxy->var(), Token::INIT, slot, false); |
1403 } | 1405 } |
1404 } | 1406 } |
1405 | 1407 |
1406 void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition( | 1408 void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition( |
1407 ClassLiteral* expr) { | 1409 ClassLiteral* expr) { |
1408 RegisterAllocationScope register_scope(this); | 1410 RegisterAllocationScope register_scope(this); |
1409 RegisterList args = register_allocator()->NewRegisterList(4); | 1411 RegisterList args = register_allocator()->NewRegisterList(4); |
1410 VisitForAccumulatorValueOrTheHole(expr->extends()); | 1412 VisitForAccumulatorValueOrTheHole(expr->extends()); |
1411 builder()->StoreAccumulatorInRegister(args[0]); | 1413 builder()->StoreAccumulatorInRegister(args[0]); |
1412 VisitForRegisterValue(expr->constructor(), args[1]); | 1414 VisitForRegisterValue(expr->constructor(), args[1]); |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1766 } | 1768 } |
1767 | 1769 |
1768 if (!literal_in_accumulator) { | 1770 if (!literal_in_accumulator) { |
1769 // Restore literal array into accumulator. | 1771 // Restore literal array into accumulator. |
1770 builder()->LoadAccumulatorWithRegister(literal); | 1772 builder()->LoadAccumulatorWithRegister(literal); |
1771 } | 1773 } |
1772 } | 1774 } |
1773 | 1775 |
1774 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { | 1776 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { |
1775 builder()->SetExpressionPosition(proxy); | 1777 builder()->SetExpressionPosition(proxy); |
1776 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 1778 BuildVariableLoad(proxy->var(), proxy->VariableFeedbackSlot(), |
| 1779 proxy->needs_hole_check()); |
1777 } | 1780 } |
1778 | 1781 |
1779 void BytecodeGenerator::BuildHoleCheckForVariableLoad(Variable* variable) { | 1782 void BytecodeGenerator::BuildVariableLoad(Variable* variable, |
1780 if (variable->binding_needs_init()) { | |
1781 BuildThrowIfHole(variable->name()); | |
1782 } | |
1783 } | |
1784 | |
1785 void BytecodeGenerator::VisitVariableLoad(Variable* variable, | |
1786 FeedbackVectorSlot slot, | 1783 FeedbackVectorSlot slot, |
| 1784 bool needs_hole_check, |
1787 TypeofMode typeof_mode) { | 1785 TypeofMode typeof_mode) { |
1788 switch (variable->location()) { | 1786 switch (variable->location()) { |
1789 case VariableLocation::LOCAL: { | 1787 case VariableLocation::LOCAL: { |
1790 Register source(Register(variable->index())); | 1788 Register source(Register(variable->index())); |
1791 // We need to load the variable into the accumulator, even when in a | 1789 // We need to load the variable into the accumulator, even when in a |
1792 // VisitForRegisterScope, in order to avoid register aliasing if | 1790 // VisitForRegisterScope, in order to avoid register aliasing if |
1793 // subsequent expressions assign to the same variable. | 1791 // subsequent expressions assign to the same variable. |
1794 builder()->LoadAccumulatorWithRegister(source); | 1792 builder()->LoadAccumulatorWithRegister(source); |
1795 BuildHoleCheckForVariableLoad(variable); | 1793 if (needs_hole_check) BuildThrowIfHole(variable->name()); |
1796 break; | 1794 break; |
1797 } | 1795 } |
1798 case VariableLocation::PARAMETER: { | 1796 case VariableLocation::PARAMETER: { |
1799 // The parameter indices are shifted by 1 (receiver is variable | 1797 // The parameter indices are shifted by 1 (receiver is variable |
1800 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 1798 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
1801 Register source = builder()->Parameter(variable->index() + 1); | 1799 Register source = builder()->Parameter(variable->index() + 1); |
1802 // We need to load the variable into the accumulator, even when in a | 1800 // We need to load the variable into the accumulator, even when in a |
1803 // VisitForRegisterScope, in order to avoid register aliasing if | 1801 // VisitForRegisterScope, in order to avoid register aliasing if |
1804 // subsequent expressions assign to the same variable. | 1802 // subsequent expressions assign to the same variable. |
1805 builder()->LoadAccumulatorWithRegister(source); | 1803 builder()->LoadAccumulatorWithRegister(source); |
1806 BuildHoleCheckForVariableLoad(variable); | 1804 if (needs_hole_check) BuildThrowIfHole(variable->name()); |
1807 break; | 1805 break; |
1808 } | 1806 } |
1809 case VariableLocation::UNALLOCATED: { | 1807 case VariableLocation::UNALLOCATED: { |
1810 builder()->LoadGlobal(feedback_index(slot), typeof_mode); | 1808 builder()->LoadGlobal(feedback_index(slot), typeof_mode); |
1811 break; | 1809 break; |
1812 } | 1810 } |
1813 case VariableLocation::CONTEXT: { | 1811 case VariableLocation::CONTEXT: { |
1814 int depth = execution_context()->ContextChainDepth(variable->scope()); | 1812 int depth = execution_context()->ContextChainDepth(variable->scope()); |
1815 ContextScope* context = execution_context()->Previous(depth); | 1813 ContextScope* context = execution_context()->Previous(depth); |
1816 Register context_reg; | 1814 Register context_reg; |
1817 if (context) { | 1815 if (context) { |
1818 context_reg = context->reg(); | 1816 context_reg = context->reg(); |
1819 depth = 0; | 1817 depth = 0; |
1820 } else { | 1818 } else { |
1821 context_reg = execution_context()->reg(); | 1819 context_reg = execution_context()->reg(); |
1822 } | 1820 } |
1823 | 1821 |
1824 builder()->LoadContextSlot(context_reg, variable->index(), depth); | 1822 builder()->LoadContextSlot(context_reg, variable->index(), depth); |
1825 BuildHoleCheckForVariableLoad(variable); | 1823 if (needs_hole_check) BuildThrowIfHole(variable->name()); |
1826 break; | 1824 break; |
1827 } | 1825 } |
1828 case VariableLocation::LOOKUP: { | 1826 case VariableLocation::LOOKUP: { |
1829 switch (variable->mode()) { | 1827 switch (variable->mode()) { |
1830 case DYNAMIC_LOCAL: { | 1828 case DYNAMIC_LOCAL: { |
1831 Variable* local_variable = variable->local_if_not_shadowed(); | 1829 Variable* local_variable = variable->local_if_not_shadowed(); |
1832 int depth = | 1830 int depth = |
1833 execution_context()->ContextChainDepth(local_variable->scope()); | 1831 execution_context()->ContextChainDepth(local_variable->scope()); |
1834 builder()->LoadLookupContextSlot(variable->name(), typeof_mode, | 1832 builder()->LoadLookupContextSlot(variable->name(), typeof_mode, |
1835 local_variable->index(), depth); | 1833 local_variable->index(), depth); |
1836 BuildHoleCheckForVariableLoad(variable); | 1834 if (needs_hole_check) BuildThrowIfHole(variable->name()); |
1837 break; | 1835 break; |
1838 } | 1836 } |
1839 case DYNAMIC_GLOBAL: { | 1837 case DYNAMIC_GLOBAL: { |
1840 int depth = scope()->ContextChainLengthUntilOutermostSloppyEval(); | 1838 int depth = scope()->ContextChainLengthUntilOutermostSloppyEval(); |
1841 builder()->LoadLookupGlobalSlot(variable->name(), typeof_mode, | 1839 builder()->LoadLookupGlobalSlot(variable->name(), typeof_mode, |
1842 feedback_index(slot), depth); | 1840 feedback_index(slot), depth); |
1843 break; | 1841 break; |
1844 } | 1842 } |
1845 default: | 1843 default: |
1846 builder()->LoadLookupSlot(variable->name(), typeof_mode); | 1844 builder()->LoadLookupSlot(variable->name(), typeof_mode); |
(...skipping 14 matching lines...) Expand all Loading... |
1861 auto it = descriptor->regular_imports().find(variable->raw_name()); | 1859 auto it = descriptor->regular_imports().find(variable->raw_name()); |
1862 DCHECK(it != descriptor->regular_imports().end()); | 1860 DCHECK(it != descriptor->regular_imports().end()); |
1863 RegisterList args = register_allocator()->NewRegisterList(2); | 1861 RegisterList args = register_allocator()->NewRegisterList(2); |
1864 builder() | 1862 builder() |
1865 ->LoadLiteral(it->second->import_name->string()) | 1863 ->LoadLiteral(it->second->import_name->string()) |
1866 .StoreAccumulatorInRegister(args[0]) | 1864 .StoreAccumulatorInRegister(args[0]) |
1867 .LoadLiteral(Smi::FromInt(it->second->module_request)) | 1865 .LoadLiteral(Smi::FromInt(it->second->module_request)) |
1868 .StoreAccumulatorInRegister(args[1]) | 1866 .StoreAccumulatorInRegister(args[1]) |
1869 .CallRuntime(Runtime::kLoadModuleImport, args); | 1867 .CallRuntime(Runtime::kLoadModuleImport, args); |
1870 } | 1868 } |
1871 BuildHoleCheckForVariableLoad(variable); | 1869 if (needs_hole_check) BuildThrowIfHole(variable->name()); |
1872 break; | 1870 break; |
1873 } | 1871 } |
1874 } | 1872 } |
1875 } | 1873 } |
1876 | 1874 |
1877 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( | 1875 void BytecodeGenerator::BuildVariableLoadForAccumulatorValue( |
1878 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { | 1876 Variable* variable, FeedbackVectorSlot slot, bool needs_hole_check, |
| 1877 TypeofMode typeof_mode) { |
1879 ValueResultScope accumulator_result(this); | 1878 ValueResultScope accumulator_result(this); |
1880 VisitVariableLoad(variable, slot, typeof_mode); | 1879 BuildVariableLoad(variable, slot, needs_hole_check, typeof_mode); |
1881 } | 1880 } |
1882 | 1881 |
1883 void BytecodeGenerator::BuildReturn() { | 1882 void BytecodeGenerator::BuildReturn() { |
1884 if (FLAG_trace) { | 1883 if (FLAG_trace) { |
1885 RegisterAllocationScope register_scope(this); | 1884 RegisterAllocationScope register_scope(this); |
1886 Register result = register_allocator()->NewRegister(); | 1885 Register result = register_allocator()->NewRegister(); |
1887 // Runtime returns {result} value, preserving accumulator. | 1886 // Runtime returns {result} value, preserving accumulator. |
1888 builder()->StoreAccumulatorInRegister(result).CallRuntime( | 1887 builder()->StoreAccumulatorInRegister(result).CallRuntime( |
1889 Runtime::kTraceExit, result); | 1888 Runtime::kTraceExit, result); |
1890 } | 1889 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1939 } else { | 1938 } else { |
1940 DCHECK(variable->is_this() && variable->mode() == CONST && | 1939 DCHECK(variable->is_this() && variable->mode() == CONST && |
1941 op == Token::INIT); | 1940 op == Token::INIT); |
1942 // Perform an initialization check for 'this'. 'this' variable is the | 1941 // Perform an initialization check for 'this'. 'this' variable is the |
1943 // only variable able to trigger bind operations outside the TDZ | 1942 // only variable able to trigger bind operations outside the TDZ |
1944 // via 'super' calls. | 1943 // via 'super' calls. |
1945 BuildThrowIfNotHole(variable->name()); | 1944 BuildThrowIfNotHole(variable->name()); |
1946 } | 1945 } |
1947 } | 1946 } |
1948 | 1947 |
1949 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, | 1948 void BytecodeGenerator::BuildVariableAssignment(Variable* variable, |
1950 Token::Value op, | 1949 Token::Value op, |
1951 FeedbackVectorSlot slot) { | 1950 FeedbackVectorSlot slot, |
| 1951 bool needs_hole_check) { |
1952 VariableMode mode = variable->mode(); | 1952 VariableMode mode = variable->mode(); |
1953 RegisterAllocationScope assignment_register_scope(this); | 1953 RegisterAllocationScope assignment_register_scope(this); |
1954 BytecodeLabel end_label; | 1954 BytecodeLabel end_label; |
1955 bool hole_check_required = | |
1956 variable->binding_needs_init() && | |
1957 (op != Token::INIT || (mode == CONST && variable->is_this())); | |
1958 switch (variable->location()) { | 1955 switch (variable->location()) { |
1959 case VariableLocation::PARAMETER: | 1956 case VariableLocation::PARAMETER: |
1960 case VariableLocation::LOCAL: { | 1957 case VariableLocation::LOCAL: { |
1961 Register destination; | 1958 Register destination; |
1962 if (VariableLocation::PARAMETER == variable->location()) { | 1959 if (VariableLocation::PARAMETER == variable->location()) { |
1963 destination = Register(builder()->Parameter(variable->index() + 1)); | 1960 destination = Register(builder()->Parameter(variable->index() + 1)); |
1964 } else { | 1961 } else { |
1965 destination = Register(variable->index()); | 1962 destination = Register(variable->index()); |
1966 } | 1963 } |
1967 | 1964 |
1968 if (hole_check_required) { | 1965 if (needs_hole_check) { |
1969 // Load destination to check for hole. | 1966 // Load destination to check for hole. |
1970 Register value_temp = register_allocator()->NewRegister(); | 1967 Register value_temp = register_allocator()->NewRegister(); |
1971 builder() | 1968 builder() |
1972 ->StoreAccumulatorInRegister(value_temp) | 1969 ->StoreAccumulatorInRegister(value_temp) |
1973 .LoadAccumulatorWithRegister(destination); | 1970 .LoadAccumulatorWithRegister(destination); |
1974 | 1971 |
1975 BuildHoleCheckForVariableAssignment(variable, op); | 1972 BuildHoleCheckForVariableAssignment(variable, op); |
1976 builder()->LoadAccumulatorWithRegister(value_temp); | 1973 builder()->LoadAccumulatorWithRegister(value_temp); |
1977 } | 1974 } |
1978 | 1975 |
(...skipping 14 matching lines...) Expand all Loading... |
1993 ContextScope* context = execution_context()->Previous(depth); | 1990 ContextScope* context = execution_context()->Previous(depth); |
1994 Register context_reg; | 1991 Register context_reg; |
1995 | 1992 |
1996 if (context) { | 1993 if (context) { |
1997 context_reg = context->reg(); | 1994 context_reg = context->reg(); |
1998 depth = 0; | 1995 depth = 0; |
1999 } else { | 1996 } else { |
2000 context_reg = execution_context()->reg(); | 1997 context_reg = execution_context()->reg(); |
2001 } | 1998 } |
2002 | 1999 |
2003 if (hole_check_required) { | 2000 if (needs_hole_check) { |
2004 // Load destination to check for hole. | 2001 // Load destination to check for hole. |
2005 Register value_temp = register_allocator()->NewRegister(); | 2002 Register value_temp = register_allocator()->NewRegister(); |
2006 builder() | 2003 builder() |
2007 ->StoreAccumulatorInRegister(value_temp) | 2004 ->StoreAccumulatorInRegister(value_temp) |
2008 .LoadContextSlot(context_reg, variable->index(), depth); | 2005 .LoadContextSlot(context_reg, variable->index(), depth); |
2009 | 2006 |
2010 BuildHoleCheckForVariableAssignment(variable, op); | 2007 BuildHoleCheckForVariableAssignment(variable, op); |
2011 builder()->LoadAccumulatorWithRegister(value_temp); | 2008 builder()->LoadAccumulatorWithRegister(value_temp); |
2012 } | 2009 } |
2013 | 2010 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2101 } | 2098 } |
2102 } | 2099 } |
2103 | 2100 |
2104 // Evaluate the value and potentially handle compound assignments by loading | 2101 // Evaluate the value and potentially handle compound assignments by loading |
2105 // the left-hand side value and performing a binary operation. | 2102 // the left-hand side value and performing a binary operation. |
2106 if (expr->is_compound()) { | 2103 if (expr->is_compound()) { |
2107 Register old_value = register_allocator()->NewRegister(); | 2104 Register old_value = register_allocator()->NewRegister(); |
2108 switch (assign_type) { | 2105 switch (assign_type) { |
2109 case VARIABLE: { | 2106 case VARIABLE: { |
2110 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 2107 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
2111 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 2108 BuildVariableLoad(proxy->var(), proxy->VariableFeedbackSlot(), |
| 2109 proxy->needs_hole_check()); |
2112 builder()->StoreAccumulatorInRegister(old_value); | 2110 builder()->StoreAccumulatorInRegister(old_value); |
2113 break; | 2111 break; |
2114 } | 2112 } |
2115 case NAMED_PROPERTY: { | 2113 case NAMED_PROPERTY: { |
2116 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); | 2114 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); |
2117 builder() | 2115 builder() |
2118 ->LoadNamedProperty(object, name, feedback_index(slot)) | 2116 ->LoadNamedProperty(object, name, feedback_index(slot)) |
2119 .StoreAccumulatorInRegister(old_value); | 2117 .StoreAccumulatorInRegister(old_value); |
2120 break; | 2118 break; |
2121 } | 2119 } |
(...skipping 28 matching lines...) Expand all Loading... |
2150 feedback_index(slot)); | 2148 feedback_index(slot)); |
2151 } else { | 2149 } else { |
2152 VisitForAccumulatorValue(expr->value()); | 2150 VisitForAccumulatorValue(expr->value()); |
2153 } | 2151 } |
2154 | 2152 |
2155 // Store the value. | 2153 // Store the value. |
2156 builder()->SetExpressionPosition(expr); | 2154 builder()->SetExpressionPosition(expr); |
2157 FeedbackVectorSlot slot = expr->AssignmentSlot(); | 2155 FeedbackVectorSlot slot = expr->AssignmentSlot(); |
2158 switch (assign_type) { | 2156 switch (assign_type) { |
2159 case VARIABLE: { | 2157 case VARIABLE: { |
2160 // TODO(oth): The VisitVariableAssignment() call is hard to reason about. | 2158 // TODO(oth): The BuildVariableAssignment() call is hard to reason about. |
2161 // Is the value in the accumulator safe? Yes, but scary. | 2159 // Is the value in the accumulator safe? Yes, but scary. |
2162 Variable* variable = expr->target()->AsVariableProxy()->var(); | 2160 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
2163 VisitVariableAssignment(variable, expr->op(), slot); | 2161 BuildVariableAssignment(proxy->var(), expr->op(), slot, |
| 2162 proxy->needs_hole_check()); |
2164 break; | 2163 break; |
2165 } | 2164 } |
2166 case NAMED_PROPERTY: | 2165 case NAMED_PROPERTY: |
2167 builder()->StoreNamedProperty(object, name, feedback_index(slot), | 2166 builder()->StoreNamedProperty(object, name, feedback_index(slot), |
2168 language_mode()); | 2167 language_mode()); |
2169 break; | 2168 break; |
2170 case KEYED_PROPERTY: | 2169 case KEYED_PROPERTY: |
2171 builder()->StoreKeyedProperty(object, key, feedback_index(slot), | 2170 builder()->StoreKeyedProperty(object, key, feedback_index(slot), |
2172 language_mode()); | 2171 language_mode()); |
2173 break; | 2172 break; |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2379 builder()->StoreAccumulatorInRegister(receiver); | 2378 builder()->StoreAccumulatorInRegister(receiver); |
2380 VisitPropertyLoadForAccumulator(receiver, property); | 2379 VisitPropertyLoadForAccumulator(receiver, property); |
2381 builder()->StoreAccumulatorInRegister(callee); | 2380 builder()->StoreAccumulatorInRegister(callee); |
2382 break; | 2381 break; |
2383 } | 2382 } |
2384 case Call::GLOBAL_CALL: { | 2383 case Call::GLOBAL_CALL: { |
2385 // Receiver is undefined for global calls. | 2384 // Receiver is undefined for global calls. |
2386 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); | 2385 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); |
2387 // Load callee as a global variable. | 2386 // Load callee as a global variable. |
2388 VariableProxy* proxy = callee_expr->AsVariableProxy(); | 2387 VariableProxy* proxy = callee_expr->AsVariableProxy(); |
2389 VisitVariableLoadForAccumulatorValue(proxy->var(), | 2388 BuildVariableLoadForAccumulatorValue(proxy->var(), |
2390 proxy->VariableFeedbackSlot()); | 2389 proxy->VariableFeedbackSlot(), |
| 2390 proxy->needs_hole_check()); |
2391 builder()->StoreAccumulatorInRegister(callee); | 2391 builder()->StoreAccumulatorInRegister(callee); |
2392 break; | 2392 break; |
2393 } | 2393 } |
2394 case Call::LOOKUP_SLOT_CALL: | 2394 case Call::LOOKUP_SLOT_CALL: |
2395 case Call::POSSIBLY_EVAL_CALL: { | 2395 case Call::POSSIBLY_EVAL_CALL: { |
2396 if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) { | 2396 if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) { |
2397 RegisterAllocationScope inner_register_scope(this); | 2397 RegisterAllocationScope inner_register_scope(this); |
2398 Register name = register_allocator()->NewRegister(); | 2398 Register name = register_allocator()->NewRegister(); |
2399 | 2399 |
2400 // Call %LoadLookupSlotForCall to get the callee and receiver. | 2400 // Call %LoadLookupSlotForCall to get the callee and receiver. |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2537 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { | 2537 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { |
2538 VisitForEffect(expr->expression()); | 2538 VisitForEffect(expr->expression()); |
2539 builder()->LoadUndefined(); | 2539 builder()->LoadUndefined(); |
2540 } | 2540 } |
2541 | 2541 |
2542 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { | 2542 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { |
2543 if (expr->expression()->IsVariableProxy()) { | 2543 if (expr->expression()->IsVariableProxy()) { |
2544 // Typeof does not throw a reference error on global variables, hence we | 2544 // Typeof does not throw a reference error on global variables, hence we |
2545 // perform a non-contextual load in case the operand is a variable proxy. | 2545 // perform a non-contextual load in case the operand is a variable proxy. |
2546 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 2546 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
2547 VisitVariableLoadForAccumulatorValue( | 2547 BuildVariableLoadForAccumulatorValue( |
2548 proxy->var(), proxy->VariableFeedbackSlot(), INSIDE_TYPEOF); | 2548 proxy->var(), proxy->VariableFeedbackSlot(), proxy->needs_hole_check(), |
| 2549 INSIDE_TYPEOF); |
2549 } else { | 2550 } else { |
2550 VisitForAccumulatorValue(expr->expression()); | 2551 VisitForAccumulatorValue(expr->expression()); |
2551 } | 2552 } |
2552 builder()->TypeOf(); | 2553 builder()->TypeOf(); |
2553 } | 2554 } |
2554 | 2555 |
2555 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { | 2556 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { |
2556 if (execution_result()->IsEffect()) { | 2557 if (execution_result()->IsEffect()) { |
2557 VisitForEffect(expr->expression()); | 2558 VisitForEffect(expr->expression()); |
2558 } else if (execution_result()->IsTest()) { | 2559 } else if (execution_result()->IsTest()) { |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2662 | 2663 |
2663 bool is_postfix = expr->is_postfix() && !execution_result()->IsEffect(); | 2664 bool is_postfix = expr->is_postfix() && !execution_result()->IsEffect(); |
2664 | 2665 |
2665 // Evaluate LHS expression and get old value. | 2666 // Evaluate LHS expression and get old value. |
2666 Register object, key, old_value; | 2667 Register object, key, old_value; |
2667 RegisterList super_property_args; | 2668 RegisterList super_property_args; |
2668 Handle<String> name; | 2669 Handle<String> name; |
2669 switch (assign_type) { | 2670 switch (assign_type) { |
2670 case VARIABLE: { | 2671 case VARIABLE: { |
2671 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 2672 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
2672 VisitVariableLoadForAccumulatorValue(proxy->var(), | 2673 BuildVariableLoadForAccumulatorValue(proxy->var(), |
2673 proxy->VariableFeedbackSlot()); | 2674 proxy->VariableFeedbackSlot(), |
| 2675 proxy->needs_hole_check()); |
2674 break; | 2676 break; |
2675 } | 2677 } |
2676 case NAMED_PROPERTY: { | 2678 case NAMED_PROPERTY: { |
2677 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); | 2679 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); |
2678 object = VisitForRegisterValue(property->obj()); | 2680 object = VisitForRegisterValue(property->obj()); |
2679 name = property->key()->AsLiteral()->AsPropertyName(); | 2681 name = property->key()->AsLiteral()->AsPropertyName(); |
2680 builder()->LoadNamedProperty(object, name, feedback_index(slot)); | 2682 builder()->LoadNamedProperty(object, name, feedback_index(slot)); |
2681 break; | 2683 break; |
2682 } | 2684 } |
2683 case KEYED_PROPERTY: { | 2685 case KEYED_PROPERTY: { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2726 | 2728 |
2727 // Perform +1/-1 operation. | 2729 // Perform +1/-1 operation. |
2728 FeedbackVectorSlot slot = expr->CountBinaryOpFeedbackSlot(); | 2730 FeedbackVectorSlot slot = expr->CountBinaryOpFeedbackSlot(); |
2729 builder()->CountOperation(expr->binary_op(), feedback_index(slot)); | 2731 builder()->CountOperation(expr->binary_op(), feedback_index(slot)); |
2730 | 2732 |
2731 // Store the value. | 2733 // Store the value. |
2732 builder()->SetExpressionPosition(expr); | 2734 builder()->SetExpressionPosition(expr); |
2733 FeedbackVectorSlot feedback_slot = expr->CountSlot(); | 2735 FeedbackVectorSlot feedback_slot = expr->CountSlot(); |
2734 switch (assign_type) { | 2736 switch (assign_type) { |
2735 case VARIABLE: { | 2737 case VARIABLE: { |
2736 Variable* variable = expr->expression()->AsVariableProxy()->var(); | 2738 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
2737 VisitVariableAssignment(variable, expr->op(), feedback_slot); | 2739 BuildVariableAssignment(proxy->var(), expr->op(), feedback_slot, |
| 2740 proxy->needs_hole_check()); |
2738 break; | 2741 break; |
2739 } | 2742 } |
2740 case NAMED_PROPERTY: { | 2743 case NAMED_PROPERTY: { |
2741 builder()->StoreNamedProperty(object, name, feedback_index(feedback_slot), | 2744 builder()->StoreNamedProperty(object, name, feedback_index(feedback_slot), |
2742 language_mode()); | 2745 language_mode()); |
2743 break; | 2746 break; |
2744 } | 2747 } |
2745 case KEYED_PROPERTY: { | 2748 case KEYED_PROPERTY: { |
2746 builder()->StoreKeyedProperty(object, key, feedback_index(feedback_slot), | 2749 builder()->StoreKeyedProperty(object, key, feedback_index(feedback_slot), |
2747 language_mode()); | 2750 language_mode()); |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3019 | 3022 |
3020 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated()); | 3023 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated()); |
3021 | 3024 |
3022 // Allocate and initialize a new arguments object and assign to the | 3025 // Allocate and initialize a new arguments object and assign to the |
3023 // {arguments} variable. | 3026 // {arguments} variable. |
3024 CreateArgumentsType type = | 3027 CreateArgumentsType type = |
3025 is_strict(language_mode()) || !info()->has_simple_parameters() | 3028 is_strict(language_mode()) || !info()->has_simple_parameters() |
3026 ? CreateArgumentsType::kUnmappedArguments | 3029 ? CreateArgumentsType::kUnmappedArguments |
3027 : CreateArgumentsType::kMappedArguments; | 3030 : CreateArgumentsType::kMappedArguments; |
3028 builder()->CreateArguments(type); | 3031 builder()->CreateArguments(type); |
3029 VisitVariableAssignment(variable, Token::ASSIGN, | 3032 BuildVariableAssignment(variable, Token::ASSIGN, |
3030 FeedbackVectorSlot::Invalid()); | 3033 FeedbackVectorSlot::Invalid(), false); |
3031 } | 3034 } |
3032 | 3035 |
3033 void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) { | 3036 void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) { |
3034 if (rest == nullptr) return; | 3037 if (rest == nullptr) return; |
3035 | 3038 |
3036 // Allocate and initialize a new rest parameter and assign to the {rest} | 3039 // Allocate and initialize a new rest parameter and assign to the {rest} |
3037 // variable. | 3040 // variable. |
3038 builder()->CreateArguments(CreateArgumentsType::kRestParameter); | 3041 builder()->CreateArguments(CreateArgumentsType::kRestParameter); |
3039 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated()); | 3042 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated()); |
3040 VisitVariableAssignment(rest, Token::ASSIGN, FeedbackVectorSlot::Invalid()); | 3043 BuildVariableAssignment(rest, Token::ASSIGN, FeedbackVectorSlot::Invalid(), |
| 3044 false); |
3041 } | 3045 } |
3042 | 3046 |
3043 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { | 3047 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { |
3044 if (variable == nullptr) return; | 3048 if (variable == nullptr) return; |
3045 | 3049 |
3046 // Store the closure we were called with in the given variable. | 3050 // Store the closure we were called with in the given variable. |
3047 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 3051 builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
3048 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); | 3052 BuildVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid(), |
| 3053 false); |
3049 } | 3054 } |
3050 | 3055 |
3051 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { | 3056 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { |
3052 if (variable == nullptr) return; | 3057 if (variable == nullptr) return; |
3053 | 3058 |
3054 // Store the new target we were called with in the given variable. | 3059 // Store the new target we were called with in the given variable. |
3055 builder()->LoadAccumulatorWithRegister(Register::new_target()); | 3060 builder()->LoadAccumulatorWithRegister(Register::new_target()); |
3056 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); | 3061 BuildVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid(), |
| 3062 false); |
3057 | 3063 |
3058 // TODO(mstarzinger): The <new.target> register is not set by the deoptimizer | 3064 // TODO(mstarzinger): The <new.target> register is not set by the deoptimizer |
3059 // and we need to make sure {BytecodeRegisterOptimizer} flushes its state | 3065 // and we need to make sure {BytecodeRegisterOptimizer} flushes its state |
3060 // before a local variable containing the <new.target> is used. Using a label | 3066 // before a local variable containing the <new.target> is used. Using a label |
3061 // as below flushes the entire pipeline, we should be more specific here. | 3067 // as below flushes the entire pipeline, we should be more specific here. |
3062 BytecodeLabel flush_state_label; | 3068 BytecodeLabel flush_state_label; |
3063 builder()->Bind(&flush_state_label); | 3069 builder()->Bind(&flush_state_label); |
3064 } | 3070 } |
3065 | 3071 |
3066 void BytecodeGenerator::VisitFunctionClosureForContext() { | 3072 void BytecodeGenerator::VisitFunctionClosureForContext() { |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3177 } | 3183 } |
3178 | 3184 |
3179 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { | 3185 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { |
3180 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 3186 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict |
3181 : Runtime::kStoreKeyedToSuper_Sloppy; | 3187 : Runtime::kStoreKeyedToSuper_Sloppy; |
3182 } | 3188 } |
3183 | 3189 |
3184 } // namespace interpreter | 3190 } // namespace interpreter |
3185 } // namespace internal | 3191 } // namespace internal |
3186 } // namespace v8 | 3192 } // namespace v8 |
OLD | NEW |