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/compiler.h" | 8 #include "src/compiler.h" |
9 #include "src/interpreter/bytecode-register-allocator.h" | 9 #include "src/interpreter/bytecode-register-allocator.h" |
10 #include "src/interpreter/control-flow-builders.h" | 10 #include "src/interpreter/control-flow-builders.h" |
(...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
696 VisitStatements(stmt->statements()); | 696 VisitStatements(stmt->statements()); |
697 if (stmt->labels() != nullptr) block_builder.EndBlock(); | 697 if (stmt->labels() != nullptr) block_builder.EndBlock(); |
698 } | 698 } |
699 | 699 |
700 | 700 |
701 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { | 701 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { |
702 Variable* variable = decl->proxy()->var(); | 702 Variable* variable = decl->proxy()->var(); |
703 VariableMode mode = decl->mode(); | 703 VariableMode mode = decl->mode(); |
704 // Const and let variables are initialized with the hole so that we can | 704 // Const and let variables are initialized with the hole so that we can |
705 // check that they are only assigned once. | 705 // check that they are only assigned once. |
706 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET; | 706 bool hole_init = mode == CONST || mode == LET; |
707 switch (variable->location()) { | 707 switch (variable->location()) { |
708 case VariableLocation::GLOBAL: | 708 case VariableLocation::GLOBAL: |
709 case VariableLocation::UNALLOCATED: { | 709 case VariableLocation::UNALLOCATED: { |
710 Handle<Oddball> value = variable->binding_needs_init() | 710 Handle<Oddball> value = variable->binding_needs_init() |
711 ? isolate()->factory()->the_hole_value() | 711 ? isolate()->factory()->the_hole_value() |
712 : isolate()->factory()->undefined_value(); | 712 : isolate()->factory()->undefined_value(); |
713 globals()->push_back(variable->name()); | 713 globals()->push_back(variable->name()); |
714 globals()->push_back(value); | 714 globals()->push_back(value); |
715 break; | 715 break; |
716 } | 716 } |
(...skipping 1069 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1786 } | 1786 } |
1787 | 1787 |
1788 | 1788 |
1789 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { | 1789 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { |
1790 builder()->SetExpressionPosition(proxy); | 1790 builder()->SetExpressionPosition(proxy); |
1791 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 1791 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
1792 } | 1792 } |
1793 | 1793 |
1794 void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode, | 1794 void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode, |
1795 Handle<String> name) { | 1795 Handle<String> name) { |
1796 if (mode == CONST_LEGACY) { | 1796 if (mode == LET || mode == CONST) { |
1797 BytecodeLabel end_label; | |
1798 builder()->JumpIfNotHole(&end_label).LoadUndefined().Bind(&end_label); | |
1799 } else if (mode == LET || mode == CONST) { | |
1800 BuildThrowIfHole(name); | 1797 BuildThrowIfHole(name); |
1801 } | 1798 } |
1802 } | 1799 } |
1803 | 1800 |
1804 void BytecodeGenerator::VisitVariableLoad(Variable* variable, | 1801 void BytecodeGenerator::VisitVariableLoad(Variable* variable, |
1805 FeedbackVectorSlot slot, | 1802 FeedbackVectorSlot slot, |
1806 TypeofMode typeof_mode) { | 1803 TypeofMode typeof_mode) { |
1807 VariableMode mode = variable->mode(); | 1804 VariableMode mode = variable->mode(); |
1808 switch (variable->location()) { | 1805 switch (variable->location()) { |
1809 case VariableLocation::LOCAL: { | 1806 case VariableLocation::LOCAL: { |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1973 } | 1970 } |
1974 } | 1971 } |
1975 | 1972 |
1976 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, | 1973 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, |
1977 Token::Value op, | 1974 Token::Value op, |
1978 FeedbackVectorSlot slot) { | 1975 FeedbackVectorSlot slot) { |
1979 VariableMode mode = variable->mode(); | 1976 VariableMode mode = variable->mode(); |
1980 RegisterAllocationScope assignment_register_scope(this); | 1977 RegisterAllocationScope assignment_register_scope(this); |
1981 BytecodeLabel end_label; | 1978 BytecodeLabel end_label; |
1982 bool hole_check_required = | 1979 bool hole_check_required = |
1983 (mode == CONST_LEGACY) || (mode == LET && op != Token::INIT) || | 1980 (mode == LET && op != Token::INIT) || |
1984 (mode == CONST && op != Token::INIT) || | 1981 (mode == CONST && op != Token::INIT) || |
1985 (mode == CONST && op == Token::INIT && variable->is_this()); | 1982 (mode == CONST && op == Token::INIT && variable->is_this()); |
1986 switch (variable->location()) { | 1983 switch (variable->location()) { |
1987 case VariableLocation::PARAMETER: | 1984 case VariableLocation::PARAMETER: |
1988 case VariableLocation::LOCAL: { | 1985 case VariableLocation::LOCAL: { |
1989 Register destination; | 1986 Register destination; |
1990 if (VariableLocation::PARAMETER == variable->location()) { | 1987 if (VariableLocation::PARAMETER == variable->location()) { |
1991 destination = Register(builder()->Parameter(variable->index() + 1)); | 1988 destination = Register(builder()->Parameter(variable->index() + 1)); |
1992 } else { | 1989 } else { |
1993 destination = Register(variable->index()); | 1990 destination = Register(variable->index()); |
1994 } | 1991 } |
1995 | 1992 |
| 1993 if (mode == CONST_LEGACY && op != Token::INIT) { |
| 1994 if (is_strict(language_mode())) { |
| 1995 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), |
| 1996 0); |
| 1997 } |
| 1998 // Non-initializing assignments to legacy constants are ignored |
| 1999 // in sloppy mode. Break here to avoid storing into variable. |
| 2000 break; |
| 2001 } |
| 2002 |
1996 if (hole_check_required) { | 2003 if (hole_check_required) { |
1997 // Load destination to check for hole. | 2004 // Load destination to check for hole. |
1998 Register value_temp = register_allocator()->NewRegister(); | 2005 Register value_temp = register_allocator()->NewRegister(); |
1999 builder() | 2006 builder() |
2000 ->StoreAccumulatorInRegister(value_temp) | 2007 ->StoreAccumulatorInRegister(value_temp) |
2001 .LoadAccumulatorWithRegister(destination); | 2008 .LoadAccumulatorWithRegister(destination); |
2002 | 2009 |
2003 if (mode == CONST_LEGACY && op == Token::INIT) { | 2010 BuildHoleCheckForVariableAssignment(variable, op); |
2004 // Perform an intialization check for legacy constants. | 2011 builder()->LoadAccumulatorWithRegister(value_temp); |
2005 builder() | |
2006 ->JumpIfNotHole(&end_label) | |
2007 .MoveRegister(value_temp, destination) | |
2008 .Bind(&end_label) | |
2009 .LoadAccumulatorWithRegister(value_temp); | |
2010 // Break here because the value should not be stored unconditionally. | |
2011 break; | |
2012 } else if (mode == CONST_LEGACY && op != Token::INIT) { | |
2013 if (is_strict(language_mode())) { | |
2014 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), | |
2015 0); | |
2016 } else { | |
2017 // Ensure accumulator is in the correct state. | |
2018 builder()->LoadAccumulatorWithRegister(value_temp); | |
2019 } | |
2020 // Non-initializing assignments to legacy constants are ignored | |
2021 // in sloppy mode. Break here to avoid storing into variable. | |
2022 break; | |
2023 } else { | |
2024 BuildHoleCheckForVariableAssignment(variable, op); | |
2025 builder()->LoadAccumulatorWithRegister(value_temp); | |
2026 } | |
2027 } | 2012 } |
2028 | |
2029 builder()->StoreAccumulatorInRegister(destination); | 2013 builder()->StoreAccumulatorInRegister(destination); |
2030 break; | 2014 break; |
2031 } | 2015 } |
2032 case VariableLocation::GLOBAL: | 2016 case VariableLocation::GLOBAL: |
2033 case VariableLocation::UNALLOCATED: { | 2017 case VariableLocation::UNALLOCATED: { |
2034 builder()->StoreGlobal(variable->name(), feedback_index(slot), | 2018 builder()->StoreGlobal(variable->name(), feedback_index(slot), |
2035 language_mode()); | 2019 language_mode()); |
2036 break; | 2020 break; |
2037 } | 2021 } |
2038 case VariableLocation::CONTEXT: { | 2022 case VariableLocation::CONTEXT: { |
(...skipping 16 matching lines...) Expand all Loading... |
2055 .LoadAccumulatorWithRegister(execution_context()->reg()) | 2039 .LoadAccumulatorWithRegister(execution_context()->reg()) |
2056 .StoreAccumulatorInRegister(context_reg); | 2040 .StoreAccumulatorInRegister(context_reg); |
2057 for (int i = 0; i < depth; ++i) { | 2041 for (int i = 0; i < depth; ++i) { |
2058 builder() | 2042 builder() |
2059 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) | 2043 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) |
2060 .StoreAccumulatorInRegister(context_reg); | 2044 .StoreAccumulatorInRegister(context_reg); |
2061 } | 2045 } |
2062 builder()->LoadAccumulatorWithRegister(value_temp); | 2046 builder()->LoadAccumulatorWithRegister(value_temp); |
2063 } | 2047 } |
2064 | 2048 |
| 2049 if (mode == CONST_LEGACY && op != Token::INIT) { |
| 2050 if (is_strict(language_mode())) { |
| 2051 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), |
| 2052 0); |
| 2053 } |
| 2054 // Non-initializing assignments to legacy constants are ignored |
| 2055 // in sloppy mode. Break here to avoid storing into variable. |
| 2056 break; |
| 2057 } |
| 2058 |
2065 if (hole_check_required) { | 2059 if (hole_check_required) { |
2066 // Load destination to check for hole. | 2060 // Load destination to check for hole. |
2067 Register value_temp = register_allocator()->NewRegister(); | 2061 Register value_temp = register_allocator()->NewRegister(); |
2068 builder() | 2062 builder() |
2069 ->StoreAccumulatorInRegister(value_temp) | 2063 ->StoreAccumulatorInRegister(value_temp) |
2070 .LoadContextSlot(context_reg, variable->index()); | 2064 .LoadContextSlot(context_reg, variable->index()); |
2071 | 2065 |
2072 if (mode == CONST_LEGACY && op == Token::INIT) { | 2066 BuildHoleCheckForVariableAssignment(variable, op); |
2073 // Perform an intialization check for legacy constants. | 2067 builder()->LoadAccumulatorWithRegister(value_temp); |
2074 builder() | |
2075 ->JumpIfNotHole(&end_label) | |
2076 .LoadAccumulatorWithRegister(value_temp) | |
2077 .StoreContextSlot(context_reg, variable->index()) | |
2078 .Bind(&end_label); | |
2079 builder()->LoadAccumulatorWithRegister(value_temp); | |
2080 // Break here because the value should not be stored unconditionally. | |
2081 // The above code performs the store conditionally. | |
2082 break; | |
2083 } else if (mode == CONST_LEGACY && op != Token::INIT) { | |
2084 if (is_strict(language_mode())) { | |
2085 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), | |
2086 0); | |
2087 } else { | |
2088 // Ensure accumulator is in the correct state. | |
2089 builder()->LoadAccumulatorWithRegister(value_temp); | |
2090 } | |
2091 // Non-initializing assignments to legacy constants are ignored | |
2092 // in sloppy mode. Break here to avoid storing into variable. | |
2093 break; | |
2094 } else { | |
2095 BuildHoleCheckForVariableAssignment(variable, op); | |
2096 builder()->LoadAccumulatorWithRegister(value_temp); | |
2097 } | |
2098 } | 2068 } |
2099 | 2069 |
2100 builder()->StoreContextSlot(context_reg, variable->index()); | 2070 builder()->StoreContextSlot(context_reg, variable->index()); |
2101 break; | 2071 break; |
2102 } | 2072 } |
2103 case VariableLocation::LOOKUP: { | 2073 case VariableLocation::LOOKUP: { |
2104 if (mode == CONST_LEGACY && op == Token::INIT) { | 2074 DCHECK_NE(CONST_LEGACY, variable->mode()); |
2105 register_allocator()->PrepareForConsecutiveAllocations(3); | 2075 builder()->StoreLookupSlot(variable->name(), language_mode()); |
2106 Register value = register_allocator()->NextConsecutiveRegister(); | |
2107 Register context = register_allocator()->NextConsecutiveRegister(); | |
2108 Register name = register_allocator()->NextConsecutiveRegister(); | |
2109 | |
2110 // InitializeLegacyConstLookupSlot runtime call returns the 'value' | |
2111 // passed to it. So, accumulator will have its original contents when | |
2112 // runtime call returns. | |
2113 builder() | |
2114 ->StoreAccumulatorInRegister(value) | |
2115 .MoveRegister(execution_context()->reg(), context) | |
2116 .LoadLiteral(variable->name()) | |
2117 .StoreAccumulatorInRegister(name) | |
2118 .CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, value, 3); | |
2119 } else { | |
2120 builder()->StoreLookupSlot(variable->name(), language_mode()); | |
2121 } | |
2122 break; | 2076 break; |
2123 } | 2077 } |
2124 } | 2078 } |
2125 } | 2079 } |
2126 | 2080 |
2127 | 2081 |
2128 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 2082 void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
2129 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); | 2083 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); |
2130 Register object, key, home_object, value; | 2084 Register object, key, home_object, value; |
2131 Handle<String> name; | 2085 Handle<String> name; |
(...skipping 1142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3274 } | 3228 } |
3275 | 3229 |
3276 | 3230 |
3277 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3231 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
3278 return info()->shared_info()->feedback_vector()->GetIndex(slot); | 3232 return info()->shared_info()->feedback_vector()->GetIndex(slot); |
3279 } | 3233 } |
3280 | 3234 |
3281 } // namespace interpreter | 3235 } // namespace interpreter |
3282 } // namespace internal | 3236 } // namespace internal |
3283 } // namespace v8 | 3237 } // namespace v8 |
OLD | NEW |