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

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: Move logic to scope analysis time 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
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(), 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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698