| 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(), decl->proxy()); |
| 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(), decl->proxy()); |
| 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(), decl->proxy()); |
| 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 } | 898 } |
| 899 } | 899 } |
| 900 | 900 |
| 901 void BytecodeGenerator::VisitDeclarations( | 901 void BytecodeGenerator::VisitDeclarations( |
| 902 ZoneList<Declaration*>* declarations) { | 902 ZoneList<Declaration*>* declarations) { |
| 903 RegisterAllocationScope register_scope(this); | 903 RegisterAllocationScope register_scope(this); |
| 904 DCHECK(globals_builder()->empty()); | 904 DCHECK(globals_builder()->empty()); |
| 905 for (int i = 0; i < declarations->length(); i++) { | 905 for (int i = 0; i < declarations->length(); i++) { |
| 906 RegisterAllocationScope register_scope(this); | 906 RegisterAllocationScope register_scope(this); |
| 907 Visit(declarations->at(i)); | 907 Visit(declarations->at(i)); |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1140 void BytecodeGenerator::VisitForInAssignment(Expression* expr, | 1140 void BytecodeGenerator::VisitForInAssignment(Expression* expr, |
| 1141 FeedbackVectorSlot slot) { | 1141 FeedbackVectorSlot slot) { |
| 1142 DCHECK(expr->IsValidReferenceExpression()); | 1142 DCHECK(expr->IsValidReferenceExpression()); |
| 1143 | 1143 |
| 1144 // Evaluate assignment starting with the value to be stored in the | 1144 // Evaluate assignment starting with the value to be stored in the |
| 1145 // accumulator. | 1145 // accumulator. |
| 1146 Property* property = expr->AsProperty(); | 1146 Property* property = expr->AsProperty(); |
| 1147 LhsKind assign_type = Property::GetAssignType(property); | 1147 LhsKind assign_type = Property::GetAssignType(property); |
| 1148 switch (assign_type) { | 1148 switch (assign_type) { |
| 1149 case VARIABLE: { | 1149 case VARIABLE: { |
| 1150 Variable* variable = expr->AsVariableProxy()->var(); | 1150 VariableProxy* proxy = expr->AsVariableProxy(); |
| 1151 VisitVariableAssignment(variable, Token::ASSIGN, slot); | 1151 BuildVariableAssignment(proxy->var(), Token::ASSIGN, slot, proxy); |
| 1152 break; | 1152 break; |
| 1153 } | 1153 } |
| 1154 case NAMED_PROPERTY: { | 1154 case NAMED_PROPERTY: { |
| 1155 RegisterAllocationScope register_scope(this); | 1155 RegisterAllocationScope register_scope(this); |
| 1156 Register value = register_allocator()->NewRegister(); | 1156 Register value = register_allocator()->NewRegister(); |
| 1157 builder()->StoreAccumulatorInRegister(value); | 1157 builder()->StoreAccumulatorInRegister(value); |
| 1158 Register object = VisitForRegisterValue(property->obj()); | 1158 Register object = VisitForRegisterValue(property->obj()); |
| 1159 Handle<String> name = property->key()->AsLiteral()->AsPropertyName(); | 1159 Handle<String> name = property->key()->AsLiteral()->AsPropertyName(); |
| 1160 builder()->LoadAccumulatorWithRegister(value); | 1160 builder()->LoadAccumulatorWithRegister(value); |
| 1161 builder()->StoreNamedProperty(object, name, feedback_index(slot), | 1161 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(); | 1388 FeedbackVectorSlot slot = expr->PrototypeSlot(); |
| 1389 builder() | 1389 builder() |
| 1390 ->StoreAccumulatorInRegister(literal) | 1390 ->StoreAccumulatorInRegister(literal) |
| 1391 .LoadNamedProperty(literal, prototype_string(), feedback_index(slot)) | 1391 .LoadNamedProperty(literal, prototype_string(), feedback_index(slot)) |
| 1392 .StoreAccumulatorInRegister(prototype); | 1392 .StoreAccumulatorInRegister(prototype); |
| 1393 | 1393 |
| 1394 VisitClassLiteralProperties(expr, literal, prototype); | 1394 VisitClassLiteralProperties(expr, literal, prototype); |
| 1395 builder()->CallRuntime(Runtime::kToFastProperties, literal); | 1395 builder()->CallRuntime(Runtime::kToFastProperties, literal); |
| 1396 // Assign to class variable. | 1396 // Assign to class variable. |
| 1397 if (expr->class_variable_proxy() != nullptr) { | 1397 if (expr->class_variable_proxy() != nullptr) { |
| 1398 Variable* var = expr->class_variable_proxy()->var(); | 1398 VariableProxy* proxy = expr->class_variable_proxy(); |
| 1399 FeedbackVectorSlot slot = expr->NeedsProxySlot() | 1399 FeedbackVectorSlot slot = expr->NeedsProxySlot() |
| 1400 ? expr->ProxySlot() | 1400 ? expr->ProxySlot() |
| 1401 : FeedbackVectorSlot::Invalid(); | 1401 : FeedbackVectorSlot::Invalid(); |
| 1402 VisitVariableAssignment(var, Token::INIT, slot); | 1402 BuildVariableAssignment(proxy->var(), Token::INIT, slot, proxy); |
| 1403 } | 1403 } |
| 1404 } | 1404 } |
| 1405 | 1405 |
| 1406 void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition( | 1406 void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition( |
| 1407 ClassLiteral* expr) { | 1407 ClassLiteral* expr) { |
| 1408 RegisterAllocationScope register_scope(this); | 1408 RegisterAllocationScope register_scope(this); |
| 1409 RegisterList args = register_allocator()->NewRegisterList(4); | 1409 RegisterList args = register_allocator()->NewRegisterList(4); |
| 1410 VisitForAccumulatorValueOrTheHole(expr->extends()); | 1410 VisitForAccumulatorValueOrTheHole(expr->extends()); |
| 1411 builder()->StoreAccumulatorInRegister(args[0]); | 1411 builder()->StoreAccumulatorInRegister(args[0]); |
| 1412 VisitForRegisterValue(expr->constructor(), args[1]); | 1412 VisitForRegisterValue(expr->constructor(), args[1]); |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1766 } | 1766 } |
| 1767 | 1767 |
| 1768 if (!literal_in_accumulator) { | 1768 if (!literal_in_accumulator) { |
| 1769 // Restore literal array into accumulator. | 1769 // Restore literal array into accumulator. |
| 1770 builder()->LoadAccumulatorWithRegister(literal); | 1770 builder()->LoadAccumulatorWithRegister(literal); |
| 1771 } | 1771 } |
| 1772 } | 1772 } |
| 1773 | 1773 |
| 1774 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { | 1774 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { |
| 1775 builder()->SetExpressionPosition(proxy); | 1775 builder()->SetExpressionPosition(proxy); |
| 1776 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 1776 BuildVariableLoad(proxy); |
| 1777 } | 1777 } |
| 1778 | 1778 |
| 1779 void BytecodeGenerator::BuildHoleCheckForVariableLoad(Variable* variable) { | 1779 void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableProxy* proxy) { |
| 1780 if (variable->binding_needs_init()) { | 1780 if (proxy->needs_hole_check()) { |
| 1781 BuildThrowIfHole(variable->name()); | 1781 BuildThrowIfHole(proxy->name()); |
| 1782 } | 1782 } |
| 1783 } | 1783 } |
| 1784 | 1784 |
| 1785 void BytecodeGenerator::VisitVariableLoad(Variable* variable, | 1785 void BytecodeGenerator::BuildVariableLoad(VariableProxy* proxy, |
| 1786 FeedbackVectorSlot slot, | |
| 1787 TypeofMode typeof_mode) { | 1786 TypeofMode typeof_mode) { |
| 1787 Variable* variable = proxy->var(); |
| 1788 FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); |
| 1788 switch (variable->location()) { | 1789 switch (variable->location()) { |
| 1789 case VariableLocation::LOCAL: { | 1790 case VariableLocation::LOCAL: { |
| 1790 Register source(Register(variable->index())); | 1791 Register source(Register(variable->index())); |
| 1791 // We need to load the variable into the accumulator, even when in a | 1792 // We need to load the variable into the accumulator, even when in a |
| 1792 // VisitForRegisterScope, in order to avoid register aliasing if | 1793 // VisitForRegisterScope, in order to avoid register aliasing if |
| 1793 // subsequent expressions assign to the same variable. | 1794 // subsequent expressions assign to the same variable. |
| 1794 builder()->LoadAccumulatorWithRegister(source); | 1795 builder()->LoadAccumulatorWithRegister(source); |
| 1795 BuildHoleCheckForVariableLoad(variable); | 1796 BuildHoleCheckForVariableLoad(proxy); |
| 1796 break; | 1797 break; |
| 1797 } | 1798 } |
| 1798 case VariableLocation::PARAMETER: { | 1799 case VariableLocation::PARAMETER: { |
| 1799 // The parameter indices are shifted by 1 (receiver is variable | 1800 // The parameter indices are shifted by 1 (receiver is variable |
| 1800 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 1801 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
| 1801 Register source = builder()->Parameter(variable->index() + 1); | 1802 Register source = builder()->Parameter(variable->index() + 1); |
| 1802 // We need to load the variable into the accumulator, even when in a | 1803 // We need to load the variable into the accumulator, even when in a |
| 1803 // VisitForRegisterScope, in order to avoid register aliasing if | 1804 // VisitForRegisterScope, in order to avoid register aliasing if |
| 1804 // subsequent expressions assign to the same variable. | 1805 // subsequent expressions assign to the same variable. |
| 1805 builder()->LoadAccumulatorWithRegister(source); | 1806 builder()->LoadAccumulatorWithRegister(source); |
| 1806 BuildHoleCheckForVariableLoad(variable); | 1807 BuildHoleCheckForVariableLoad(proxy); |
| 1807 break; | 1808 break; |
| 1808 } | 1809 } |
| 1809 case VariableLocation::UNALLOCATED: { | 1810 case VariableLocation::UNALLOCATED: { |
| 1810 builder()->LoadGlobal(feedback_index(slot), typeof_mode); | 1811 builder()->LoadGlobal(feedback_index(slot), typeof_mode); |
| 1811 break; | 1812 break; |
| 1812 } | 1813 } |
| 1813 case VariableLocation::CONTEXT: { | 1814 case VariableLocation::CONTEXT: { |
| 1814 int depth = execution_context()->ContextChainDepth(variable->scope()); | 1815 int depth = execution_context()->ContextChainDepth(variable->scope()); |
| 1815 ContextScope* context = execution_context()->Previous(depth); | 1816 ContextScope* context = execution_context()->Previous(depth); |
| 1816 Register context_reg; | 1817 Register context_reg; |
| 1817 if (context) { | 1818 if (context) { |
| 1818 context_reg = context->reg(); | 1819 context_reg = context->reg(); |
| 1819 depth = 0; | 1820 depth = 0; |
| 1820 } else { | 1821 } else { |
| 1821 context_reg = execution_context()->reg(); | 1822 context_reg = execution_context()->reg(); |
| 1822 } | 1823 } |
| 1823 | 1824 |
| 1824 builder()->LoadContextSlot(context_reg, variable->index(), depth); | 1825 builder()->LoadContextSlot(context_reg, variable->index(), depth); |
| 1825 BuildHoleCheckForVariableLoad(variable); | 1826 BuildHoleCheckForVariableLoad(proxy); |
| 1826 break; | 1827 break; |
| 1827 } | 1828 } |
| 1828 case VariableLocation::LOOKUP: { | 1829 case VariableLocation::LOOKUP: { |
| 1829 switch (variable->mode()) { | 1830 switch (variable->mode()) { |
| 1830 case DYNAMIC_LOCAL: { | 1831 case DYNAMIC_LOCAL: { |
| 1831 Variable* local_variable = variable->local_if_not_shadowed(); | 1832 Variable* local_variable = variable->local_if_not_shadowed(); |
| 1832 int depth = | 1833 int depth = |
| 1833 execution_context()->ContextChainDepth(local_variable->scope()); | 1834 execution_context()->ContextChainDepth(local_variable->scope()); |
| 1834 builder()->LoadLookupContextSlot(variable->name(), typeof_mode, | 1835 builder()->LoadLookupContextSlot(variable->name(), typeof_mode, |
| 1835 local_variable->index(), depth); | 1836 local_variable->index(), depth); |
| 1836 BuildHoleCheckForVariableLoad(variable); | 1837 BuildHoleCheckForVariableLoad(proxy); |
| 1837 break; | 1838 break; |
| 1838 } | 1839 } |
| 1839 case DYNAMIC_GLOBAL: { | 1840 case DYNAMIC_GLOBAL: { |
| 1840 int depth = scope()->ContextChainLengthUntilOutermostSloppyEval(); | 1841 int depth = scope()->ContextChainLengthUntilOutermostSloppyEval(); |
| 1841 builder()->LoadLookupGlobalSlot(variable->name(), typeof_mode, | 1842 builder()->LoadLookupGlobalSlot(variable->name(), typeof_mode, |
| 1842 feedback_index(slot), depth); | 1843 feedback_index(slot), depth); |
| 1843 break; | 1844 break; |
| 1844 } | 1845 } |
| 1845 default: | 1846 default: |
| 1846 builder()->LoadLookupSlot(variable->name(), typeof_mode); | 1847 builder()->LoadLookupSlot(variable->name(), typeof_mode); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1861 auto it = descriptor->regular_imports().find(variable->raw_name()); | 1862 auto it = descriptor->regular_imports().find(variable->raw_name()); |
| 1862 DCHECK(it != descriptor->regular_imports().end()); | 1863 DCHECK(it != descriptor->regular_imports().end()); |
| 1863 RegisterList args = register_allocator()->NewRegisterList(2); | 1864 RegisterList args = register_allocator()->NewRegisterList(2); |
| 1864 builder() | 1865 builder() |
| 1865 ->LoadLiteral(it->second->import_name->string()) | 1866 ->LoadLiteral(it->second->import_name->string()) |
| 1866 .StoreAccumulatorInRegister(args[0]) | 1867 .StoreAccumulatorInRegister(args[0]) |
| 1867 .LoadLiteral(Smi::FromInt(it->second->module_request)) | 1868 .LoadLiteral(Smi::FromInt(it->second->module_request)) |
| 1868 .StoreAccumulatorInRegister(args[1]) | 1869 .StoreAccumulatorInRegister(args[1]) |
| 1869 .CallRuntime(Runtime::kLoadModuleImport, args); | 1870 .CallRuntime(Runtime::kLoadModuleImport, args); |
| 1870 } | 1871 } |
| 1871 BuildHoleCheckForVariableLoad(variable); | 1872 BuildHoleCheckForVariableLoad(proxy); |
| 1872 break; | 1873 break; |
| 1873 } | 1874 } |
| 1874 } | 1875 } |
| 1875 } | 1876 } |
| 1876 | 1877 |
| 1877 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( | 1878 void BytecodeGenerator::BuildVariableLoadForAccumulatorValue( |
| 1878 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { | 1879 VariableProxy* proxy, TypeofMode typeof_mode) { |
| 1879 ValueResultScope accumulator_result(this); | 1880 ValueResultScope accumulator_result(this); |
| 1880 VisitVariableLoad(variable, slot, typeof_mode); | 1881 BuildVariableLoad(proxy, typeof_mode); |
| 1881 } | 1882 } |
| 1882 | 1883 |
| 1883 void BytecodeGenerator::BuildReturn() { | 1884 void BytecodeGenerator::BuildReturn() { |
| 1884 if (FLAG_trace) { | 1885 if (FLAG_trace) { |
| 1885 RegisterAllocationScope register_scope(this); | 1886 RegisterAllocationScope register_scope(this); |
| 1886 Register result = register_allocator()->NewRegister(); | 1887 Register result = register_allocator()->NewRegister(); |
| 1887 // Runtime returns {result} value, preserving accumulator. | 1888 // Runtime returns {result} value, preserving accumulator. |
| 1888 builder()->StoreAccumulatorInRegister(result).CallRuntime( | 1889 builder()->StoreAccumulatorInRegister(result).CallRuntime( |
| 1889 Runtime::kTraceExit, result); | 1890 Runtime::kTraceExit, result); |
| 1890 } | 1891 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1939 } else { | 1940 } else { |
| 1940 DCHECK(variable->is_this() && variable->mode() == CONST && | 1941 DCHECK(variable->is_this() && variable->mode() == CONST && |
| 1941 op == Token::INIT); | 1942 op == Token::INIT); |
| 1942 // Perform an initialization check for 'this'. 'this' variable is the | 1943 // Perform an initialization check for 'this'. 'this' variable is the |
| 1943 // only variable able to trigger bind operations outside the TDZ | 1944 // only variable able to trigger bind operations outside the TDZ |
| 1944 // via 'super' calls. | 1945 // via 'super' calls. |
| 1945 BuildThrowIfNotHole(variable->name()); | 1946 BuildThrowIfNotHole(variable->name()); |
| 1946 } | 1947 } |
| 1947 } | 1948 } |
| 1948 | 1949 |
| 1949 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, | 1950 void BytecodeGenerator::BuildVariableAssignment(Variable* variable, |
| 1950 Token::Value op, | 1951 Token::Value op, |
| 1951 FeedbackVectorSlot slot) { | 1952 FeedbackVectorSlot slot, |
| 1953 VariableProxy* proxy) { |
| 1954 DCHECK_IMPLIES(proxy != nullptr, variable == proxy->var()); |
| 1955 DCHECK_IMPLIES(proxy == nullptr, !variable->binding_needs_init()); |
| 1956 bool hole_check_required = proxy != nullptr && proxy->needs_hole_check(); |
| 1952 VariableMode mode = variable->mode(); | 1957 VariableMode mode = variable->mode(); |
| 1953 RegisterAllocationScope assignment_register_scope(this); | 1958 RegisterAllocationScope assignment_register_scope(this); |
| 1954 BytecodeLabel end_label; | 1959 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()) { | 1960 switch (variable->location()) { |
| 1959 case VariableLocation::PARAMETER: | 1961 case VariableLocation::PARAMETER: |
| 1960 case VariableLocation::LOCAL: { | 1962 case VariableLocation::LOCAL: { |
| 1961 Register destination; | 1963 Register destination; |
| 1962 if (VariableLocation::PARAMETER == variable->location()) { | 1964 if (VariableLocation::PARAMETER == variable->location()) { |
| 1963 destination = Register(builder()->Parameter(variable->index() + 1)); | 1965 destination = Register(builder()->Parameter(variable->index() + 1)); |
| 1964 } else { | 1966 } else { |
| 1965 destination = Register(variable->index()); | 1967 destination = Register(variable->index()); |
| 1966 } | 1968 } |
| 1967 | 1969 |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2101 } | 2103 } |
| 2102 } | 2104 } |
| 2103 | 2105 |
| 2104 // Evaluate the value and potentially handle compound assignments by loading | 2106 // Evaluate the value and potentially handle compound assignments by loading |
| 2105 // the left-hand side value and performing a binary operation. | 2107 // the left-hand side value and performing a binary operation. |
| 2106 if (expr->is_compound()) { | 2108 if (expr->is_compound()) { |
| 2107 Register old_value = register_allocator()->NewRegister(); | 2109 Register old_value = register_allocator()->NewRegister(); |
| 2108 switch (assign_type) { | 2110 switch (assign_type) { |
| 2109 case VARIABLE: { | 2111 case VARIABLE: { |
| 2110 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 2112 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
| 2111 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 2113 BuildVariableLoad(proxy); |
| 2112 builder()->StoreAccumulatorInRegister(old_value); | 2114 builder()->StoreAccumulatorInRegister(old_value); |
| 2113 break; | 2115 break; |
| 2114 } | 2116 } |
| 2115 case NAMED_PROPERTY: { | 2117 case NAMED_PROPERTY: { |
| 2116 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); | 2118 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); |
| 2117 builder() | 2119 builder() |
| 2118 ->LoadNamedProperty(object, name, feedback_index(slot)) | 2120 ->LoadNamedProperty(object, name, feedback_index(slot)) |
| 2119 .StoreAccumulatorInRegister(old_value); | 2121 .StoreAccumulatorInRegister(old_value); |
| 2120 break; | 2122 break; |
| 2121 } | 2123 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2150 feedback_index(slot)); | 2152 feedback_index(slot)); |
| 2151 } else { | 2153 } else { |
| 2152 VisitForAccumulatorValue(expr->value()); | 2154 VisitForAccumulatorValue(expr->value()); |
| 2153 } | 2155 } |
| 2154 | 2156 |
| 2155 // Store the value. | 2157 // Store the value. |
| 2156 builder()->SetExpressionPosition(expr); | 2158 builder()->SetExpressionPosition(expr); |
| 2157 FeedbackVectorSlot slot = expr->AssignmentSlot(); | 2159 FeedbackVectorSlot slot = expr->AssignmentSlot(); |
| 2158 switch (assign_type) { | 2160 switch (assign_type) { |
| 2159 case VARIABLE: { | 2161 case VARIABLE: { |
| 2160 // TODO(oth): The VisitVariableAssignment() call is hard to reason about. | 2162 // TODO(oth): The BuildVariableAssignment() call is hard to reason about. |
| 2161 // Is the value in the accumulator safe? Yes, but scary. | 2163 // Is the value in the accumulator safe? Yes, but scary. |
| 2162 Variable* variable = expr->target()->AsVariableProxy()->var(); | 2164 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
| 2163 VisitVariableAssignment(variable, expr->op(), slot); | 2165 BuildVariableAssignment(proxy->var(), expr->op(), slot, proxy); |
| 2164 break; | 2166 break; |
| 2165 } | 2167 } |
| 2166 case NAMED_PROPERTY: | 2168 case NAMED_PROPERTY: |
| 2167 builder()->StoreNamedProperty(object, name, feedback_index(slot), | 2169 builder()->StoreNamedProperty(object, name, feedback_index(slot), |
| 2168 language_mode()); | 2170 language_mode()); |
| 2169 break; | 2171 break; |
| 2170 case KEYED_PROPERTY: | 2172 case KEYED_PROPERTY: |
| 2171 builder()->StoreKeyedProperty(object, key, feedback_index(slot), | 2173 builder()->StoreKeyedProperty(object, key, feedback_index(slot), |
| 2172 language_mode()); | 2174 language_mode()); |
| 2173 break; | 2175 break; |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2379 builder()->StoreAccumulatorInRegister(receiver); | 2381 builder()->StoreAccumulatorInRegister(receiver); |
| 2380 VisitPropertyLoadForAccumulator(receiver, property); | 2382 VisitPropertyLoadForAccumulator(receiver, property); |
| 2381 builder()->StoreAccumulatorInRegister(callee); | 2383 builder()->StoreAccumulatorInRegister(callee); |
| 2382 break; | 2384 break; |
| 2383 } | 2385 } |
| 2384 case Call::GLOBAL_CALL: { | 2386 case Call::GLOBAL_CALL: { |
| 2385 // Receiver is undefined for global calls. | 2387 // Receiver is undefined for global calls. |
| 2386 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); | 2388 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); |
| 2387 // Load callee as a global variable. | 2389 // Load callee as a global variable. |
| 2388 VariableProxy* proxy = callee_expr->AsVariableProxy(); | 2390 VariableProxy* proxy = callee_expr->AsVariableProxy(); |
| 2389 VisitVariableLoadForAccumulatorValue(proxy->var(), | 2391 BuildVariableLoadForAccumulatorValue(proxy); |
| 2390 proxy->VariableFeedbackSlot()); | |
| 2391 builder()->StoreAccumulatorInRegister(callee); | 2392 builder()->StoreAccumulatorInRegister(callee); |
| 2392 break; | 2393 break; |
| 2393 } | 2394 } |
| 2394 case Call::LOOKUP_SLOT_CALL: | 2395 case Call::LOOKUP_SLOT_CALL: |
| 2395 case Call::POSSIBLY_EVAL_CALL: { | 2396 case Call::POSSIBLY_EVAL_CALL: { |
| 2396 if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) { | 2397 if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) { |
| 2397 RegisterAllocationScope inner_register_scope(this); | 2398 RegisterAllocationScope inner_register_scope(this); |
| 2398 Register name = register_allocator()->NewRegister(); | 2399 Register name = register_allocator()->NewRegister(); |
| 2399 | 2400 |
| 2400 // Call %LoadLookupSlotForCall to get the callee and receiver. | 2401 // Call %LoadLookupSlotForCall to get the callee and receiver. |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2546 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { | 2547 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { |
| 2547 VisitForEffect(expr->expression()); | 2548 VisitForEffect(expr->expression()); |
| 2548 builder()->LoadUndefined(); | 2549 builder()->LoadUndefined(); |
| 2549 } | 2550 } |
| 2550 | 2551 |
| 2551 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { | 2552 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { |
| 2552 if (expr->expression()->IsVariableProxy()) { | 2553 if (expr->expression()->IsVariableProxy()) { |
| 2553 // Typeof does not throw a reference error on global variables, hence we | 2554 // Typeof does not throw a reference error on global variables, hence we |
| 2554 // perform a non-contextual load in case the operand is a variable proxy. | 2555 // perform a non-contextual load in case the operand is a variable proxy. |
| 2555 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 2556 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 2556 VisitVariableLoadForAccumulatorValue( | 2557 BuildVariableLoadForAccumulatorValue(proxy, INSIDE_TYPEOF); |
| 2557 proxy->var(), proxy->VariableFeedbackSlot(), INSIDE_TYPEOF); | |
| 2558 } else { | 2558 } else { |
| 2559 VisitForAccumulatorValue(expr->expression()); | 2559 VisitForAccumulatorValue(expr->expression()); |
| 2560 } | 2560 } |
| 2561 builder()->TypeOf(); | 2561 builder()->TypeOf(); |
| 2562 } | 2562 } |
| 2563 | 2563 |
| 2564 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { | 2564 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { |
| 2565 if (execution_result()->IsEffect()) { | 2565 if (execution_result()->IsEffect()) { |
| 2566 VisitForEffect(expr->expression()); | 2566 VisitForEffect(expr->expression()); |
| 2567 } else if (execution_result()->IsTest()) { | 2567 } else if (execution_result()->IsTest()) { |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2671 | 2671 |
| 2672 bool is_postfix = expr->is_postfix() && !execution_result()->IsEffect(); | 2672 bool is_postfix = expr->is_postfix() && !execution_result()->IsEffect(); |
| 2673 | 2673 |
| 2674 // Evaluate LHS expression and get old value. | 2674 // Evaluate LHS expression and get old value. |
| 2675 Register object, key, old_value; | 2675 Register object, key, old_value; |
| 2676 RegisterList super_property_args; | 2676 RegisterList super_property_args; |
| 2677 Handle<String> name; | 2677 Handle<String> name; |
| 2678 switch (assign_type) { | 2678 switch (assign_type) { |
| 2679 case VARIABLE: { | 2679 case VARIABLE: { |
| 2680 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 2680 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 2681 VisitVariableLoadForAccumulatorValue(proxy->var(), | 2681 BuildVariableLoadForAccumulatorValue(proxy); |
| 2682 proxy->VariableFeedbackSlot()); | |
| 2683 break; | 2682 break; |
| 2684 } | 2683 } |
| 2685 case NAMED_PROPERTY: { | 2684 case NAMED_PROPERTY: { |
| 2686 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); | 2685 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); |
| 2687 object = VisitForRegisterValue(property->obj()); | 2686 object = VisitForRegisterValue(property->obj()); |
| 2688 name = property->key()->AsLiteral()->AsPropertyName(); | 2687 name = property->key()->AsLiteral()->AsPropertyName(); |
| 2689 builder()->LoadNamedProperty(object, name, feedback_index(slot)); | 2688 builder()->LoadNamedProperty(object, name, feedback_index(slot)); |
| 2690 break; | 2689 break; |
| 2691 } | 2690 } |
| 2692 case KEYED_PROPERTY: { | 2691 case KEYED_PROPERTY: { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2735 | 2734 |
| 2736 // Perform +1/-1 operation. | 2735 // Perform +1/-1 operation. |
| 2737 FeedbackVectorSlot slot = expr->CountBinaryOpFeedbackSlot(); | 2736 FeedbackVectorSlot slot = expr->CountBinaryOpFeedbackSlot(); |
| 2738 builder()->CountOperation(expr->binary_op(), feedback_index(slot)); | 2737 builder()->CountOperation(expr->binary_op(), feedback_index(slot)); |
| 2739 | 2738 |
| 2740 // Store the value. | 2739 // Store the value. |
| 2741 builder()->SetExpressionPosition(expr); | 2740 builder()->SetExpressionPosition(expr); |
| 2742 FeedbackVectorSlot feedback_slot = expr->CountSlot(); | 2741 FeedbackVectorSlot feedback_slot = expr->CountSlot(); |
| 2743 switch (assign_type) { | 2742 switch (assign_type) { |
| 2744 case VARIABLE: { | 2743 case VARIABLE: { |
| 2745 Variable* variable = expr->expression()->AsVariableProxy()->var(); | 2744 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 2746 VisitVariableAssignment(variable, expr->op(), feedback_slot); | 2745 BuildVariableAssignment(proxy->var(), expr->op(), feedback_slot, proxy); |
| 2747 break; | 2746 break; |
| 2748 } | 2747 } |
| 2749 case NAMED_PROPERTY: { | 2748 case NAMED_PROPERTY: { |
| 2750 builder()->StoreNamedProperty(object, name, feedback_index(feedback_slot), | 2749 builder()->StoreNamedProperty(object, name, feedback_index(feedback_slot), |
| 2751 language_mode()); | 2750 language_mode()); |
| 2752 break; | 2751 break; |
| 2753 } | 2752 } |
| 2754 case KEYED_PROPERTY: { | 2753 case KEYED_PROPERTY: { |
| 2755 builder()->StoreKeyedProperty(object, key, feedback_index(feedback_slot), | 2754 builder()->StoreKeyedProperty(object, key, feedback_index(feedback_slot), |
| 2756 language_mode()); | 2755 language_mode()); |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3028 | 3027 |
| 3029 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated()); | 3028 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated()); |
| 3030 | 3029 |
| 3031 // Allocate and initialize a new arguments object and assign to the | 3030 // Allocate and initialize a new arguments object and assign to the |
| 3032 // {arguments} variable. | 3031 // {arguments} variable. |
| 3033 CreateArgumentsType type = | 3032 CreateArgumentsType type = |
| 3034 is_strict(language_mode()) || !info()->has_simple_parameters() | 3033 is_strict(language_mode()) || !info()->has_simple_parameters() |
| 3035 ? CreateArgumentsType::kUnmappedArguments | 3034 ? CreateArgumentsType::kUnmappedArguments |
| 3036 : CreateArgumentsType::kMappedArguments; | 3035 : CreateArgumentsType::kMappedArguments; |
| 3037 builder()->CreateArguments(type); | 3036 builder()->CreateArguments(type); |
| 3038 VisitVariableAssignment(variable, Token::ASSIGN, | 3037 BuildVariableAssignment(variable, Token::ASSIGN, |
| 3039 FeedbackVectorSlot::Invalid()); | 3038 FeedbackVectorSlot::Invalid()); |
| 3040 } | 3039 } |
| 3041 | 3040 |
| 3042 void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) { | 3041 void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) { |
| 3043 if (rest == nullptr) return; | 3042 if (rest == nullptr) return; |
| 3044 | 3043 |
| 3045 // Allocate and initialize a new rest parameter and assign to the {rest} | 3044 // Allocate and initialize a new rest parameter and assign to the {rest} |
| 3046 // variable. | 3045 // variable. |
| 3047 builder()->CreateArguments(CreateArgumentsType::kRestParameter); | 3046 builder()->CreateArguments(CreateArgumentsType::kRestParameter); |
| 3048 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated()); | 3047 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated()); |
| 3049 VisitVariableAssignment(rest, Token::ASSIGN, FeedbackVectorSlot::Invalid()); | 3048 BuildVariableAssignment(rest, Token::ASSIGN, FeedbackVectorSlot::Invalid()); |
| 3050 } | 3049 } |
| 3051 | 3050 |
| 3052 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { | 3051 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { |
| 3053 if (variable == nullptr) return; | 3052 if (variable == nullptr) return; |
| 3054 | 3053 |
| 3055 // Store the closure we were called with in the given variable. | 3054 // Store the closure we were called with in the given variable. |
| 3056 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 3055 builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
| 3057 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); | 3056 BuildVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); |
| 3058 } | 3057 } |
| 3059 | 3058 |
| 3060 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { | 3059 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { |
| 3061 if (variable == nullptr) return; | 3060 if (variable == nullptr) return; |
| 3062 | 3061 |
| 3063 // Store the new target we were called with in the given variable. | 3062 // Store the new target we were called with in the given variable. |
| 3064 builder()->LoadAccumulatorWithRegister(Register::new_target()); | 3063 builder()->LoadAccumulatorWithRegister(Register::new_target()); |
| 3065 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); | 3064 BuildVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); |
| 3066 | 3065 |
| 3067 // TODO(mstarzinger): The <new.target> register is not set by the deoptimizer | 3066 // TODO(mstarzinger): The <new.target> register is not set by the deoptimizer |
| 3068 // and we need to make sure {BytecodeRegisterOptimizer} flushes its state | 3067 // and we need to make sure {BytecodeRegisterOptimizer} flushes its state |
| 3069 // before a local variable containing the <new.target> is used. Using a label | 3068 // before a local variable containing the <new.target> is used. Using a label |
| 3070 // as below flushes the entire pipeline, we should be more specific here. | 3069 // as below flushes the entire pipeline, we should be more specific here. |
| 3071 BytecodeLabel flush_state_label; | 3070 BytecodeLabel flush_state_label; |
| 3072 builder()->Bind(&flush_state_label); | 3071 builder()->Bind(&flush_state_label); |
| 3073 } | 3072 } |
| 3074 | 3073 |
| 3075 void BytecodeGenerator::VisitFunctionClosureForContext() { | 3074 void BytecodeGenerator::VisitFunctionClosureForContext() { |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3186 } | 3185 } |
| 3187 | 3186 |
| 3188 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { | 3187 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { |
| 3189 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 3188 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict |
| 3190 : Runtime::kStoreKeyedToSuper_Sloppy; | 3189 : Runtime::kStoreKeyedToSuper_Sloppy; |
| 3191 } | 3190 } |
| 3192 | 3191 |
| 3193 } // namespace interpreter | 3192 } // namespace interpreter |
| 3194 } // namespace internal | 3193 } // namespace internal |
| 3195 } // namespace v8 | 3194 } // namespace v8 |
| OLD | NEW |