Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(295)

Side by Side Diff: src/interpreter/bytecode-generator.cc

Issue 2411873004: [ignition] Eliminate hole checks where statically possible for loads and stores (Closed)
Patch Set: Rebased Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/parsing/parser.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/parsing/parser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698