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/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/compiler.h" | 9 #include "src/compiler.h" |
10 #include "src/interpreter/bytecode-flags.h" | 10 #include "src/interpreter/bytecode-flags.h" |
(...skipping 814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
825 ControlScopeForBreakable execution_control(this, stmt, &block_builder); | 825 ControlScopeForBreakable execution_control(this, stmt, &block_builder); |
826 if (stmt->scope() != nullptr) { | 826 if (stmt->scope() != nullptr) { |
827 VisitDeclarations(stmt->scope()->declarations()); | 827 VisitDeclarations(stmt->scope()->declarations()); |
828 } | 828 } |
829 VisitStatements(stmt->statements()); | 829 VisitStatements(stmt->statements()); |
830 if (stmt->labels() != nullptr) block_builder.EndBlock(); | 830 if (stmt->labels() != nullptr) block_builder.EndBlock(); |
831 } | 831 } |
832 | 832 |
833 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { | 833 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { |
834 Variable* variable = decl->proxy()->var(); | 834 Variable* variable = decl->proxy()->var(); |
835 VariableMode mode = decl->mode(); | |
836 // Const and let variables are initialized with the hole so that we can | |
837 // check that they are only assigned once. | |
838 bool hole_init = mode == CONST || mode == LET; | |
839 switch (variable->location()) { | 835 switch (variable->location()) { |
840 case VariableLocation::GLOBAL: | 836 case VariableLocation::GLOBAL: |
841 case VariableLocation::UNALLOCATED: { | 837 case VariableLocation::UNALLOCATED: { |
842 DCHECK(!variable->binding_needs_init()); | 838 DCHECK(!variable->binding_needs_init()); |
843 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); | 839 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); |
844 globals_builder()->AddUndefinedDeclaration(slot); | 840 globals_builder()->AddUndefinedDeclaration(slot); |
845 break; | 841 break; |
846 } | 842 } |
847 case VariableLocation::LOCAL: | 843 case VariableLocation::LOCAL: |
848 if (hole_init) { | 844 if (variable->binding_needs_init()) { |
849 Register destination(variable->index()); | 845 Register destination(variable->index()); |
850 builder()->LoadTheHole().StoreAccumulatorInRegister(destination); | 846 builder()->LoadTheHole().StoreAccumulatorInRegister(destination); |
851 } | 847 } |
852 break; | 848 break; |
853 case VariableLocation::PARAMETER: | 849 case VariableLocation::PARAMETER: |
854 if (hole_init) { | 850 if (variable->binding_needs_init()) { |
855 // The parameter indices are shifted by 1 (receiver is variable | 851 // The parameter indices are shifted by 1 (receiver is variable |
856 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 852 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
857 Register destination(builder()->Parameter(variable->index() + 1)); | 853 Register destination(builder()->Parameter(variable->index() + 1)); |
858 builder()->LoadTheHole().StoreAccumulatorInRegister(destination); | 854 builder()->LoadTheHole().StoreAccumulatorInRegister(destination); |
859 } | 855 } |
860 break; | 856 break; |
861 case VariableLocation::CONTEXT: | 857 case VariableLocation::CONTEXT: |
862 if (hole_init) { | 858 if (variable->binding_needs_init()) { |
863 builder()->LoadTheHole().StoreContextSlot(execution_context()->reg(), | 859 builder()->LoadTheHole().StoreContextSlot(execution_context()->reg(), |
864 variable->index()); | 860 variable->index()); |
865 } | 861 } |
866 break; | 862 break; |
867 case VariableLocation::LOOKUP: { | 863 case VariableLocation::LOOKUP: { |
868 DCHECK_EQ(VAR, mode); | 864 DCHECK_EQ(VAR, variable->mode()); |
869 DCHECK(!hole_init); | 865 DCHECK(!variable->binding_needs_init()); |
870 | 866 |
871 Register name = register_allocator()->NewRegister(); | 867 Register name = register_allocator()->NewRegister(); |
872 | 868 |
873 builder() | 869 builder() |
874 ->LoadLiteral(variable->name()) | 870 ->LoadLiteral(variable->name()) |
875 .StoreAccumulatorInRegister(name) | 871 .StoreAccumulatorInRegister(name) |
876 .CallRuntime(Runtime::kDeclareEvalVar, name, 1); | 872 .CallRuntime(Runtime::kDeclareEvalVar, name, 1); |
877 break; | 873 break; |
878 } | 874 } |
879 } | 875 } |
(...skipping 956 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1836 builder()->LoadAccumulatorWithRegister(literal); | 1832 builder()->LoadAccumulatorWithRegister(literal); |
1837 } | 1833 } |
1838 execution_result()->SetResultInAccumulator(); | 1834 execution_result()->SetResultInAccumulator(); |
1839 } | 1835 } |
1840 | 1836 |
1841 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { | 1837 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { |
1842 builder()->SetExpressionPosition(proxy); | 1838 builder()->SetExpressionPosition(proxy); |
1843 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 1839 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
1844 } | 1840 } |
1845 | 1841 |
1846 void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode, | 1842 void BytecodeGenerator::BuildHoleCheckForVariableLoad(Variable* variable) { |
1847 Handle<String> name) { | 1843 if (variable->binding_needs_init()) { |
1848 if (mode == LET || mode == CONST) { | 1844 BuildThrowIfHole(variable->name()); |
1849 BuildThrowIfHole(name); | |
1850 } | 1845 } |
1851 } | 1846 } |
1852 | 1847 |
1853 void BytecodeGenerator::VisitVariableLoad(Variable* variable, | 1848 void BytecodeGenerator::VisitVariableLoad(Variable* variable, |
1854 FeedbackVectorSlot slot, | 1849 FeedbackVectorSlot slot, |
1855 TypeofMode typeof_mode) { | 1850 TypeofMode typeof_mode) { |
1856 VariableMode mode = variable->mode(); | |
1857 switch (variable->location()) { | 1851 switch (variable->location()) { |
1858 case VariableLocation::LOCAL: { | 1852 case VariableLocation::LOCAL: { |
1859 Register source(Register(variable->index())); | 1853 Register source(Register(variable->index())); |
1860 builder()->LoadAccumulatorWithRegister(source); | 1854 builder()->LoadAccumulatorWithRegister(source); |
1861 BuildHoleCheckForVariableLoad(mode, variable->name()); | 1855 BuildHoleCheckForVariableLoad(variable); |
1862 execution_result()->SetResultInAccumulator(); | 1856 execution_result()->SetResultInAccumulator(); |
1863 break; | 1857 break; |
1864 } | 1858 } |
1865 case VariableLocation::PARAMETER: { | 1859 case VariableLocation::PARAMETER: { |
1866 // The parameter indices are shifted by 1 (receiver is variable | 1860 // The parameter indices are shifted by 1 (receiver is variable |
1867 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 1861 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
1868 Register source = builder()->Parameter(variable->index() + 1); | 1862 Register source = builder()->Parameter(variable->index() + 1); |
1869 builder()->LoadAccumulatorWithRegister(source); | 1863 builder()->LoadAccumulatorWithRegister(source); |
1870 BuildHoleCheckForVariableLoad(mode, variable->name()); | 1864 BuildHoleCheckForVariableLoad(variable); |
1871 execution_result()->SetResultInAccumulator(); | 1865 execution_result()->SetResultInAccumulator(); |
1872 break; | 1866 break; |
1873 } | 1867 } |
1874 case VariableLocation::GLOBAL: | 1868 case VariableLocation::GLOBAL: |
1875 case VariableLocation::UNALLOCATED: { | 1869 case VariableLocation::UNALLOCATED: { |
1876 builder()->LoadGlobal(feedback_index(slot), typeof_mode); | 1870 builder()->LoadGlobal(feedback_index(slot), typeof_mode); |
1877 execution_result()->SetResultInAccumulator(); | 1871 execution_result()->SetResultInAccumulator(); |
1878 break; | 1872 break; |
1879 } | 1873 } |
1880 case VariableLocation::CONTEXT: { | 1874 case VariableLocation::CONTEXT: { |
(...skipping 13 matching lines...) Expand all Loading... |
1894 ->LoadAccumulatorWithRegister(execution_context()->reg()) | 1888 ->LoadAccumulatorWithRegister(execution_context()->reg()) |
1895 .StoreAccumulatorInRegister(context_reg); | 1889 .StoreAccumulatorInRegister(context_reg); |
1896 for (int i = 0; i < depth; ++i) { | 1890 for (int i = 0; i < depth; ++i) { |
1897 builder() | 1891 builder() |
1898 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) | 1892 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) |
1899 .StoreAccumulatorInRegister(context_reg); | 1893 .StoreAccumulatorInRegister(context_reg); |
1900 } | 1894 } |
1901 } | 1895 } |
1902 | 1896 |
1903 builder()->LoadContextSlot(context_reg, variable->index()); | 1897 builder()->LoadContextSlot(context_reg, variable->index()); |
1904 BuildHoleCheckForVariableLoad(mode, variable->name()); | 1898 BuildHoleCheckForVariableLoad(variable); |
1905 execution_result()->SetResultInAccumulator(); | 1899 execution_result()->SetResultInAccumulator(); |
1906 break; | 1900 break; |
1907 } | 1901 } |
1908 case VariableLocation::LOOKUP: { | 1902 case VariableLocation::LOOKUP: { |
1909 builder()->LoadLookupSlot(variable->name(), typeof_mode); | 1903 builder()->LoadLookupSlot(variable->name(), typeof_mode); |
1910 execution_result()->SetResultInAccumulator(); | 1904 execution_result()->SetResultInAccumulator(); |
1911 break; | 1905 break; |
1912 } | 1906 } |
1913 } | 1907 } |
1914 } | 1908 } |
(...skipping 1356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3271 return execution_context()->scope()->language_mode(); | 3265 return execution_context()->scope()->language_mode(); |
3272 } | 3266 } |
3273 | 3267 |
3274 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3268 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
3275 return TypeFeedbackVector::GetIndex(slot); | 3269 return TypeFeedbackVector::GetIndex(slot); |
3276 } | 3270 } |
3277 | 3271 |
3278 } // namespace interpreter | 3272 } // namespace interpreter |
3279 } // namespace internal | 3273 } // namespace internal |
3280 } // namespace v8 | 3274 } // namespace v8 |
OLD | NEW |