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 |