| 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 1994 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2005 builder() | 2005 builder() |
| 2006 ->JumpIfNotHole(&reference_error) | 2006 ->JumpIfNotHole(&reference_error) |
| 2007 .Jump(&no_reference_error) | 2007 .Jump(&no_reference_error) |
| 2008 .Bind(&reference_error); | 2008 .Bind(&reference_error); |
| 2009 BuildThrowReferenceError(name); | 2009 BuildThrowReferenceError(name); |
| 2010 builder()->Bind(&no_reference_error); | 2010 builder()->Bind(&no_reference_error); |
| 2011 } | 2011 } |
| 2012 | 2012 |
| 2013 void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable, | 2013 void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable, |
| 2014 Token::Value op) { | 2014 Token::Value op) { |
| 2015 DCHECK(variable->mode() != CONST_LEGACY); | |
| 2016 if (op != Token::INIT) { | 2015 if (op != Token::INIT) { |
| 2017 // Perform an initialization check for let/const declared variables. | 2016 // Perform an initialization check for let/const declared variables. |
| 2018 // E.g. let x = (x = 20); is not allowed. | 2017 // E.g. let x = (x = 20); is not allowed. |
| 2019 BuildThrowIfHole(variable->name()); | 2018 BuildThrowIfHole(variable->name()); |
| 2020 } else { | 2019 } else { |
| 2021 DCHECK(variable->is_this() && variable->mode() == CONST && | 2020 DCHECK(variable->is_this() && variable->mode() == CONST && |
| 2022 op == Token::INIT); | 2021 op == Token::INIT); |
| 2023 // Perform an initialization check for 'this'. 'this' variable is the | 2022 // Perform an initialization check for 'this'. 'this' variable is the |
| 2024 // only variable able to trigger bind operations outside the TDZ | 2023 // only variable able to trigger bind operations outside the TDZ |
| 2025 // via 'super' calls. | 2024 // via 'super' calls. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2051 // Load destination to check for hole. | 2050 // Load destination to check for hole. |
| 2052 Register value_temp = register_allocator()->NewRegister(); | 2051 Register value_temp = register_allocator()->NewRegister(); |
| 2053 builder() | 2052 builder() |
| 2054 ->StoreAccumulatorInRegister(value_temp) | 2053 ->StoreAccumulatorInRegister(value_temp) |
| 2055 .LoadAccumulatorWithRegister(destination); | 2054 .LoadAccumulatorWithRegister(destination); |
| 2056 | 2055 |
| 2057 BuildHoleCheckForVariableAssignment(variable, op); | 2056 BuildHoleCheckForVariableAssignment(variable, op); |
| 2058 builder()->LoadAccumulatorWithRegister(value_temp); | 2057 builder()->LoadAccumulatorWithRegister(value_temp); |
| 2059 } | 2058 } |
| 2060 | 2059 |
| 2061 if ((mode == CONST || mode == CONST_LEGACY) && op != Token::INIT) { | 2060 if (mode != CONST || op == Token::INIT) { |
| 2062 if (mode == CONST || is_strict(language_mode())) { | 2061 builder()->StoreAccumulatorInRegister(destination); |
| 2063 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), | 2062 } else if (variable->throw_on_const_assignment(language_mode())) { |
| 2064 0); | 2063 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); |
| 2065 } | |
| 2066 // Non-initializing assignments to legacy constants are ignored | |
| 2067 // in sloppy mode. Break here to avoid storing into variable. | |
| 2068 break; | |
| 2069 } | 2064 } |
| 2070 | |
| 2071 builder()->StoreAccumulatorInRegister(destination); | |
| 2072 break; | 2065 break; |
| 2073 } | 2066 } |
| 2074 case VariableLocation::GLOBAL: | 2067 case VariableLocation::GLOBAL: |
| 2075 case VariableLocation::UNALLOCATED: { | 2068 case VariableLocation::UNALLOCATED: { |
| 2076 builder()->StoreGlobal(variable->name(), feedback_index(slot), | 2069 builder()->StoreGlobal(variable->name(), feedback_index(slot), |
| 2077 language_mode()); | 2070 language_mode()); |
| 2078 break; | 2071 break; |
| 2079 } | 2072 } |
| 2080 case VariableLocation::CONTEXT: { | 2073 case VariableLocation::CONTEXT: { |
| 2081 int depth = execution_context()->ContextChainDepth(variable->scope()); | 2074 int depth = execution_context()->ContextChainDepth(variable->scope()); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2108 // Load destination to check for hole. | 2101 // Load destination to check for hole. |
| 2109 Register value_temp = register_allocator()->NewRegister(); | 2102 Register value_temp = register_allocator()->NewRegister(); |
| 2110 builder() | 2103 builder() |
| 2111 ->StoreAccumulatorInRegister(value_temp) | 2104 ->StoreAccumulatorInRegister(value_temp) |
| 2112 .LoadContextSlot(context_reg, variable->index()); | 2105 .LoadContextSlot(context_reg, variable->index()); |
| 2113 | 2106 |
| 2114 BuildHoleCheckForVariableAssignment(variable, op); | 2107 BuildHoleCheckForVariableAssignment(variable, op); |
| 2115 builder()->LoadAccumulatorWithRegister(value_temp); | 2108 builder()->LoadAccumulatorWithRegister(value_temp); |
| 2116 } | 2109 } |
| 2117 | 2110 |
| 2118 if ((mode == CONST || mode == CONST_LEGACY) && op != Token::INIT) { | 2111 if (mode != CONST || op == Token::INIT) { |
| 2119 if (mode == CONST || is_strict(language_mode())) { | 2112 builder()->StoreContextSlot(context_reg, variable->index()); |
| 2120 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), | 2113 } else if (variable->throw_on_const_assignment(language_mode())) { |
| 2121 0); | 2114 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); |
| 2122 } | |
| 2123 // Non-initializing assignments to legacy constants are ignored | |
| 2124 // in sloppy mode. Break here to avoid storing into variable. | |
| 2125 break; | |
| 2126 } | 2115 } |
| 2127 | |
| 2128 builder()->StoreContextSlot(context_reg, variable->index()); | |
| 2129 break; | 2116 break; |
| 2130 } | 2117 } |
| 2131 case VariableLocation::LOOKUP: { | 2118 case VariableLocation::LOOKUP: { |
| 2132 DCHECK_NE(CONST_LEGACY, variable->mode()); | |
| 2133 builder()->StoreLookupSlot(variable->name(), language_mode()); | 2119 builder()->StoreLookupSlot(variable->name(), language_mode()); |
| 2134 break; | 2120 break; |
| 2135 } | 2121 } |
| 2136 case VariableLocation::MODULE: | 2122 case VariableLocation::MODULE: |
| 2137 UNREACHABLE(); | 2123 UNREACHABLE(); |
| 2138 } | 2124 } |
| 2139 } | 2125 } |
| 2140 | 2126 |
| 2141 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 2127 void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
| 2142 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); | 2128 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); |
| (...skipping 1142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3285 return execution_context()->scope()->language_mode(); | 3271 return execution_context()->scope()->language_mode(); |
| 3286 } | 3272 } |
| 3287 | 3273 |
| 3288 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3274 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 3289 return TypeFeedbackVector::GetIndex(slot); | 3275 return TypeFeedbackVector::GetIndex(slot); |
| 3290 } | 3276 } |
| 3291 | 3277 |
| 3292 } // namespace interpreter | 3278 } // namespace interpreter |
| 3293 } // namespace internal | 3279 } // namespace internal |
| 3294 } // namespace v8 | 3280 } // namespace v8 |
| OLD | NEW |