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 |