| 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 2064 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2075 builder() | 2075 builder() |
| 2076 ->JumpIfNotHole(&reference_error) | 2076 ->JumpIfNotHole(&reference_error) |
| 2077 .Jump(&no_reference_error) | 2077 .Jump(&no_reference_error) |
| 2078 .Bind(&reference_error); | 2078 .Bind(&reference_error); |
| 2079 BuildThrowReferenceError(name); | 2079 BuildThrowReferenceError(name); |
| 2080 builder()->Bind(&no_reference_error); | 2080 builder()->Bind(&no_reference_error); |
| 2081 } | 2081 } |
| 2082 | 2082 |
| 2083 void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable, | 2083 void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable, |
| 2084 Token::Value op) { | 2084 Token::Value op) { |
| 2085 DCHECK(variable->mode() != CONST_LEGACY); | |
| 2086 if (op != Token::INIT) { | 2085 if (op != Token::INIT) { |
| 2087 // Perform an initialization check for let/const declared variables. | 2086 // Perform an initialization check for let/const declared variables. |
| 2088 // E.g. let x = (x = 20); is not allowed. | 2087 // E.g. let x = (x = 20); is not allowed. |
| 2089 BuildThrowIfHole(variable->name()); | 2088 BuildThrowIfHole(variable->name()); |
| 2090 } else { | 2089 } else { |
| 2091 DCHECK(variable->is_this() && variable->mode() == CONST && | 2090 DCHECK(variable->is_this() && variable->mode() == CONST && |
| 2092 op == Token::INIT); | 2091 op == Token::INIT); |
| 2093 // Perform an initialization check for 'this'. 'this' variable is the | 2092 // Perform an initialization check for 'this'. 'this' variable is the |
| 2094 // only variable able to trigger bind operations outside the TDZ | 2093 // only variable able to trigger bind operations outside the TDZ |
| 2095 // via 'super' calls. | 2094 // via 'super' calls. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2120 // Load destination to check for hole. | 2119 // Load destination to check for hole. |
| 2121 Register value_temp = register_allocator()->NewRegister(); | 2120 Register value_temp = register_allocator()->NewRegister(); |
| 2122 builder() | 2121 builder() |
| 2123 ->StoreAccumulatorInRegister(value_temp) | 2122 ->StoreAccumulatorInRegister(value_temp) |
| 2124 .LoadAccumulatorWithRegister(destination); | 2123 .LoadAccumulatorWithRegister(destination); |
| 2125 | 2124 |
| 2126 BuildHoleCheckForVariableAssignment(variable, op); | 2125 BuildHoleCheckForVariableAssignment(variable, op); |
| 2127 builder()->LoadAccumulatorWithRegister(value_temp); | 2126 builder()->LoadAccumulatorWithRegister(value_temp); |
| 2128 } | 2127 } |
| 2129 | 2128 |
| 2130 if ((mode == CONST || mode == CONST_LEGACY) && op != Token::INIT) { | 2129 if (mode != CONST || op == Token::INIT) { |
| 2131 if (mode == CONST || is_strict(language_mode())) { | 2130 builder()->StoreAccumulatorInRegister(destination); |
| 2132 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), | 2131 } else if (variable->throw_on_const_assignment(language_mode())) { |
| 2133 0); | 2132 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); |
| 2134 } | |
| 2135 // Non-initializing assignments to legacy constants are ignored | |
| 2136 // in sloppy mode. Break here to avoid storing into variable. | |
| 2137 break; | |
| 2138 } | 2133 } |
| 2139 | |
| 2140 builder()->StoreAccumulatorInRegister(destination); | |
| 2141 break; | 2134 break; |
| 2142 } | 2135 } |
| 2143 case VariableLocation::GLOBAL: | 2136 case VariableLocation::GLOBAL: |
| 2144 case VariableLocation::UNALLOCATED: { | 2137 case VariableLocation::UNALLOCATED: { |
| 2145 builder()->StoreGlobal(variable->name(), feedback_index(slot), | 2138 builder()->StoreGlobal(variable->name(), feedback_index(slot), |
| 2146 language_mode()); | 2139 language_mode()); |
| 2147 break; | 2140 break; |
| 2148 } | 2141 } |
| 2149 case VariableLocation::CONTEXT: { | 2142 case VariableLocation::CONTEXT: { |
| 2150 int depth = execution_context()->ContextChainDepth(variable->scope()); | 2143 int depth = execution_context()->ContextChainDepth(variable->scope()); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2177 // Load destination to check for hole. | 2170 // Load destination to check for hole. |
| 2178 Register value_temp = register_allocator()->NewRegister(); | 2171 Register value_temp = register_allocator()->NewRegister(); |
| 2179 builder() | 2172 builder() |
| 2180 ->StoreAccumulatorInRegister(value_temp) | 2173 ->StoreAccumulatorInRegister(value_temp) |
| 2181 .LoadContextSlot(context_reg, variable->index()); | 2174 .LoadContextSlot(context_reg, variable->index()); |
| 2182 | 2175 |
| 2183 BuildHoleCheckForVariableAssignment(variable, op); | 2176 BuildHoleCheckForVariableAssignment(variable, op); |
| 2184 builder()->LoadAccumulatorWithRegister(value_temp); | 2177 builder()->LoadAccumulatorWithRegister(value_temp); |
| 2185 } | 2178 } |
| 2186 | 2179 |
| 2187 if ((mode == CONST || mode == CONST_LEGACY) && op != Token::INIT) { | 2180 if (mode != CONST || op == Token::INIT) { |
| 2188 if (mode == CONST || is_strict(language_mode())) { | 2181 builder()->StoreContextSlot(context_reg, variable->index()); |
| 2189 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), | 2182 } else if (variable->throw_on_const_assignment(language_mode())) { |
| 2190 0); | 2183 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); |
| 2191 } | |
| 2192 // Non-initializing assignments to legacy constants are ignored | |
| 2193 // in sloppy mode. Break here to avoid storing into variable. | |
| 2194 break; | |
| 2195 } | 2184 } |
| 2196 | |
| 2197 builder()->StoreContextSlot(context_reg, variable->index()); | |
| 2198 break; | 2185 break; |
| 2199 } | 2186 } |
| 2200 case VariableLocation::LOOKUP: { | 2187 case VariableLocation::LOOKUP: { |
| 2201 DCHECK_NE(CONST_LEGACY, variable->mode()); | |
| 2202 builder()->StoreLookupSlot(variable->name(), language_mode()); | 2188 builder()->StoreLookupSlot(variable->name(), language_mode()); |
| 2203 break; | 2189 break; |
| 2204 } | 2190 } |
| 2205 case VariableLocation::MODULE: | 2191 case VariableLocation::MODULE: |
| 2206 UNREACHABLE(); | 2192 UNREACHABLE(); |
| 2207 } | 2193 } |
| 2208 } | 2194 } |
| 2209 | 2195 |
| 2210 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 2196 void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
| 2211 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); | 2197 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); |
| (...skipping 1191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3403 return execution_context()->scope()->language_mode(); | 3389 return execution_context()->scope()->language_mode(); |
| 3404 } | 3390 } |
| 3405 | 3391 |
| 3406 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3392 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 3407 return TypeFeedbackVector::GetIndex(slot); | 3393 return TypeFeedbackVector::GetIndex(slot); |
| 3408 } | 3394 } |
| 3409 | 3395 |
| 3410 } // namespace interpreter | 3396 } // namespace interpreter |
| 3411 } // namespace internal | 3397 } // namespace internal |
| 3412 } // namespace v8 | 3398 } // namespace v8 |
| OLD | NEW |