| 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/compile-time-value.h" | 7 #include "src/ast/compile-time-value.h" |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/compilation-info.h" | 10 #include "src/compilation-info.h" |
| (...skipping 905 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 916 case VariableLocation::PARAMETER: | 916 case VariableLocation::PARAMETER: |
| 917 if (variable->binding_needs_init()) { | 917 if (variable->binding_needs_init()) { |
| 918 // The parameter indices are shifted by 1 (receiver is variable | 918 // The parameter indices are shifted by 1 (receiver is variable |
| 919 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 919 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
| 920 Register destination(builder()->Parameter(variable->index() + 1)); | 920 Register destination(builder()->Parameter(variable->index() + 1)); |
| 921 builder()->LoadTheHole().StoreAccumulatorInRegister(destination); | 921 builder()->LoadTheHole().StoreAccumulatorInRegister(destination); |
| 922 } | 922 } |
| 923 break; | 923 break; |
| 924 case VariableLocation::CONTEXT: | 924 case VariableLocation::CONTEXT: |
| 925 if (variable->binding_needs_init()) { | 925 if (variable->binding_needs_init()) { |
| 926 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); |
| 926 builder()->LoadTheHole().StoreContextSlot(execution_context()->reg(), | 927 builder()->LoadTheHole().StoreContextSlot(execution_context()->reg(), |
| 927 variable->index()); | 928 variable->index(), 0); |
| 928 } | 929 } |
| 929 break; | 930 break; |
| 930 case VariableLocation::LOOKUP: { | 931 case VariableLocation::LOOKUP: { |
| 931 DCHECK_EQ(VAR, variable->mode()); | 932 DCHECK_EQ(VAR, variable->mode()); |
| 932 DCHECK(!variable->binding_needs_init()); | 933 DCHECK(!variable->binding_needs_init()); |
| 933 | 934 |
| 934 Register name = register_allocator()->NewRegister(); | 935 Register name = register_allocator()->NewRegister(); |
| 935 | 936 |
| 936 builder() | 937 builder() |
| 937 ->LoadLiteral(variable->name()) | 938 ->LoadLiteral(variable->name()) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 956 case VariableLocation::PARAMETER: | 957 case VariableLocation::PARAMETER: |
| 957 case VariableLocation::LOCAL: { | 958 case VariableLocation::LOCAL: { |
| 958 VisitForAccumulatorValue(decl->fun()); | 959 VisitForAccumulatorValue(decl->fun()); |
| 959 VisitVariableAssignment(variable, Token::INIT, | 960 VisitVariableAssignment(variable, Token::INIT, |
| 960 FeedbackVectorSlot::Invalid()); | 961 FeedbackVectorSlot::Invalid()); |
| 961 break; | 962 break; |
| 962 } | 963 } |
| 963 case VariableLocation::CONTEXT: { | 964 case VariableLocation::CONTEXT: { |
| 964 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); | 965 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); |
| 965 VisitForAccumulatorValue(decl->fun()); | 966 VisitForAccumulatorValue(decl->fun()); |
| 966 builder()->StoreContextSlot(execution_context()->reg(), | 967 builder()->StoreContextSlot(execution_context()->reg(), variable->index(), |
| 967 variable->index()); | 968 0); |
| 968 break; | 969 break; |
| 969 } | 970 } |
| 970 case VariableLocation::LOOKUP: { | 971 case VariableLocation::LOOKUP: { |
| 971 register_allocator()->PrepareForConsecutiveAllocations(2); | 972 register_allocator()->PrepareForConsecutiveAllocations(2); |
| 972 Register name = register_allocator()->NextConsecutiveRegister(); | 973 Register name = register_allocator()->NextConsecutiveRegister(); |
| 973 Register literal = register_allocator()->NextConsecutiveRegister(); | 974 Register literal = register_allocator()->NextConsecutiveRegister(); |
| 974 builder()->LoadLiteral(variable->name()).StoreAccumulatorInRegister(name); | 975 builder()->LoadLiteral(variable->name()).StoreAccumulatorInRegister(name); |
| 975 | 976 |
| 976 VisitForAccumulatorValue(decl->fun()); | 977 VisitForAccumulatorValue(decl->fun()); |
| 977 builder()->StoreAccumulatorInRegister(literal).CallRuntime( | 978 builder()->StoreAccumulatorInRegister(literal).CallRuntime( |
| (...skipping 968 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1946 case VariableLocation::UNALLOCATED: { | 1947 case VariableLocation::UNALLOCATED: { |
| 1947 builder()->LoadGlobal(feedback_index(slot), typeof_mode); | 1948 builder()->LoadGlobal(feedback_index(slot), typeof_mode); |
| 1948 break; | 1949 break; |
| 1949 } | 1950 } |
| 1950 case VariableLocation::CONTEXT: { | 1951 case VariableLocation::CONTEXT: { |
| 1951 int depth = execution_context()->ContextChainDepth(variable->scope()); | 1952 int depth = execution_context()->ContextChainDepth(variable->scope()); |
| 1952 ContextScope* context = execution_context()->Previous(depth); | 1953 ContextScope* context = execution_context()->Previous(depth); |
| 1953 Register context_reg; | 1954 Register context_reg; |
| 1954 if (context) { | 1955 if (context) { |
| 1955 context_reg = context->reg(); | 1956 context_reg = context->reg(); |
| 1957 depth = 0; |
| 1956 } else { | 1958 } else { |
| 1957 context_reg = register_allocator()->NewRegister(); | 1959 context_reg = execution_context()->reg(); |
| 1958 // Walk the context chain to find the context at the given depth. | |
| 1959 // TODO(rmcilroy): Perform this work in a bytecode handler once we have | |
| 1960 // a generic mechanism for performing jumps in interpreter.cc. | |
| 1961 // TODO(mythria): Also update bytecode graph builder with correct depth | |
| 1962 // when this changes. | |
| 1963 builder() | |
| 1964 ->LoadAccumulatorWithRegister(execution_context()->reg()) | |
| 1965 .StoreAccumulatorInRegister(context_reg); | |
| 1966 for (int i = 0; i < depth; ++i) { | |
| 1967 builder() | |
| 1968 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) | |
| 1969 .StoreAccumulatorInRegister(context_reg); | |
| 1970 } | |
| 1971 } | 1960 } |
| 1972 | 1961 |
| 1973 builder()->LoadContextSlot(context_reg, variable->index()); | 1962 builder()->LoadContextSlot(context_reg, variable->index(), depth); |
| 1974 BuildHoleCheckForVariableLoad(variable); | 1963 BuildHoleCheckForVariableLoad(variable); |
| 1975 break; | 1964 break; |
| 1976 } | 1965 } |
| 1977 case VariableLocation::LOOKUP: { | 1966 case VariableLocation::LOOKUP: { |
| 1978 builder()->LoadLookupSlot(variable->name(), typeof_mode); | 1967 builder()->LoadLookupSlot(variable->name(), typeof_mode); |
| 1979 break; | 1968 break; |
| 1980 } | 1969 } |
| 1981 case VariableLocation::MODULE: | 1970 case VariableLocation::MODULE: |
| 1982 UNREACHABLE(); | 1971 UNREACHABLE(); |
| 1983 } | 1972 } |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2128 language_mode()); | 2117 language_mode()); |
| 2129 break; | 2118 break; |
| 2130 } | 2119 } |
| 2131 case VariableLocation::CONTEXT: { | 2120 case VariableLocation::CONTEXT: { |
| 2132 int depth = execution_context()->ContextChainDepth(variable->scope()); | 2121 int depth = execution_context()->ContextChainDepth(variable->scope()); |
| 2133 ContextScope* context = execution_context()->Previous(depth); | 2122 ContextScope* context = execution_context()->Previous(depth); |
| 2134 Register context_reg; | 2123 Register context_reg; |
| 2135 | 2124 |
| 2136 if (context) { | 2125 if (context) { |
| 2137 context_reg = context->reg(); | 2126 context_reg = context->reg(); |
| 2127 depth = 0; |
| 2138 } else { | 2128 } else { |
| 2139 Register value_temp = register_allocator()->NewRegister(); | 2129 context_reg = execution_context()->reg(); |
| 2140 context_reg = register_allocator()->NewRegister(); | |
| 2141 // Walk the context chain to find the context at the given depth. | |
| 2142 // TODO(rmcilroy): Perform this work in a bytecode handler once we have | |
| 2143 // a generic mechanism for performing jumps in interpreter.cc. | |
| 2144 // TODO(mythria): Also update bytecode graph builder with correct depth | |
| 2145 // when this changes. | |
| 2146 builder() | |
| 2147 ->StoreAccumulatorInRegister(value_temp) | |
| 2148 .LoadAccumulatorWithRegister(execution_context()->reg()) | |
| 2149 .StoreAccumulatorInRegister(context_reg); | |
| 2150 for (int i = 0; i < depth; ++i) { | |
| 2151 builder() | |
| 2152 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX) | |
| 2153 .StoreAccumulatorInRegister(context_reg); | |
| 2154 } | |
| 2155 builder()->LoadAccumulatorWithRegister(value_temp); | |
| 2156 } | 2130 } |
| 2157 | 2131 |
| 2158 if (hole_check_required) { | 2132 if (hole_check_required) { |
| 2159 // Load destination to check for hole. | 2133 // Load destination to check for hole. |
| 2160 Register value_temp = register_allocator()->NewRegister(); | 2134 Register value_temp = register_allocator()->NewRegister(); |
| 2161 builder() | 2135 builder() |
| 2162 ->StoreAccumulatorInRegister(value_temp) | 2136 ->StoreAccumulatorInRegister(value_temp) |
| 2163 .LoadContextSlot(context_reg, variable->index()); | 2137 .LoadContextSlot(context_reg, variable->index(), depth); |
| 2164 | 2138 |
| 2165 BuildHoleCheckForVariableAssignment(variable, op); | 2139 BuildHoleCheckForVariableAssignment(variable, op); |
| 2166 builder()->LoadAccumulatorWithRegister(value_temp); | 2140 builder()->LoadAccumulatorWithRegister(value_temp); |
| 2167 } | 2141 } |
| 2168 | 2142 |
| 2169 if (mode != CONST || op == Token::INIT) { | 2143 if (mode != CONST || op == Token::INIT) { |
| 2170 builder()->StoreContextSlot(context_reg, variable->index()); | 2144 builder()->StoreContextSlot(context_reg, variable->index(), depth); |
| 2171 } else if (variable->throw_on_const_assignment(language_mode())) { | 2145 } else if (variable->throw_on_const_assignment(language_mode())) { |
| 2172 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); | 2146 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); |
| 2173 } | 2147 } |
| 2174 break; | 2148 break; |
| 2175 } | 2149 } |
| 2176 case VariableLocation::LOOKUP: { | 2150 case VariableLocation::LOOKUP: { |
| 2177 builder()->StoreLookupSlot(variable->name(), language_mode()); | 2151 builder()->StoreLookupSlot(variable->name(), language_mode()); |
| 2178 break; | 2152 break; |
| 2179 } | 2153 } |
| 2180 case VariableLocation::MODULE: | 2154 case VariableLocation::MODULE: |
| (...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2826 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 2800 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 2827 Variable* variable = proxy->var(); | 2801 Variable* variable = proxy->var(); |
| 2828 DCHECK(is_sloppy(language_mode()) || variable->is_this()); | 2802 DCHECK(is_sloppy(language_mode()) || variable->is_this()); |
| 2829 switch (variable->location()) { | 2803 switch (variable->location()) { |
| 2830 case VariableLocation::UNALLOCATED: { | 2804 case VariableLocation::UNALLOCATED: { |
| 2831 // Global var, let, const or variables not explicitly declared. | 2805 // Global var, let, const or variables not explicitly declared. |
| 2832 Register native_context = register_allocator()->NewRegister(); | 2806 Register native_context = register_allocator()->NewRegister(); |
| 2833 Register global_object = register_allocator()->NewRegister(); | 2807 Register global_object = register_allocator()->NewRegister(); |
| 2834 builder() | 2808 builder() |
| 2835 ->LoadContextSlot(execution_context()->reg(), | 2809 ->LoadContextSlot(execution_context()->reg(), |
| 2836 Context::NATIVE_CONTEXT_INDEX) | 2810 Context::NATIVE_CONTEXT_INDEX, 0) |
| 2837 .StoreAccumulatorInRegister(native_context) | 2811 .StoreAccumulatorInRegister(native_context) |
| 2838 .LoadContextSlot(native_context, Context::EXTENSION_INDEX) | 2812 .LoadContextSlot(native_context, Context::EXTENSION_INDEX, 0) |
| 2839 .StoreAccumulatorInRegister(global_object) | 2813 .StoreAccumulatorInRegister(global_object) |
| 2840 .LoadLiteral(variable->name()) | 2814 .LoadLiteral(variable->name()) |
| 2841 .Delete(global_object, language_mode()); | 2815 .Delete(global_object, language_mode()); |
| 2842 break; | 2816 break; |
| 2843 } | 2817 } |
| 2844 case VariableLocation::PARAMETER: | 2818 case VariableLocation::PARAMETER: |
| 2845 case VariableLocation::LOCAL: | 2819 case VariableLocation::LOCAL: |
| 2846 case VariableLocation::CONTEXT: { | 2820 case VariableLocation::CONTEXT: { |
| 2847 // Deleting local var/let/const, context variables, and arguments | 2821 // Deleting local var/let/const, context variables, and arguments |
| 2848 // does not have any effect. | 2822 // does not have any effect. |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3156 | 3130 |
| 3157 void BytecodeGenerator::BuildLocalActivationContextInitialization() { | 3131 void BytecodeGenerator::BuildLocalActivationContextInitialization() { |
| 3158 DeclarationScope* scope = this->scope(); | 3132 DeclarationScope* scope = this->scope(); |
| 3159 | 3133 |
| 3160 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { | 3134 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { |
| 3161 Variable* variable = scope->receiver(); | 3135 Variable* variable = scope->receiver(); |
| 3162 Register receiver(builder()->Parameter(0)); | 3136 Register receiver(builder()->Parameter(0)); |
| 3163 // Context variable (at bottom of the context chain). | 3137 // Context variable (at bottom of the context chain). |
| 3164 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); | 3138 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); |
| 3165 builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot( | 3139 builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot( |
| 3166 execution_context()->reg(), variable->index()); | 3140 execution_context()->reg(), variable->index(), 0); |
| 3167 } | 3141 } |
| 3168 | 3142 |
| 3169 // Copy parameters into context if necessary. | 3143 // Copy parameters into context if necessary. |
| 3170 int num_parameters = scope->num_parameters(); | 3144 int num_parameters = scope->num_parameters(); |
| 3171 for (int i = 0; i < num_parameters; i++) { | 3145 for (int i = 0; i < num_parameters; i++) { |
| 3172 Variable* variable = scope->parameter(i); | 3146 Variable* variable = scope->parameter(i); |
| 3173 if (!variable->IsContextSlot()) continue; | 3147 if (!variable->IsContextSlot()) continue; |
| 3174 | 3148 |
| 3175 // The parameter indices are shifted by 1 (receiver is variable | 3149 // The parameter indices are shifted by 1 (receiver is variable |
| 3176 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 3150 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
| 3177 Register parameter(builder()->Parameter(i + 1)); | 3151 Register parameter(builder()->Parameter(i + 1)); |
| 3178 // Context variable (at bottom of the context chain). | 3152 // Context variable (at bottom of the context chain). |
| 3179 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); | 3153 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); |
| 3180 builder()->LoadAccumulatorWithRegister(parameter) | 3154 builder()->LoadAccumulatorWithRegister(parameter).StoreContextSlot( |
| 3181 .StoreContextSlot(execution_context()->reg(), variable->index()); | 3155 execution_context()->reg(), variable->index(), 0); |
| 3182 } | 3156 } |
| 3183 } | 3157 } |
| 3184 | 3158 |
| 3185 void BytecodeGenerator::BuildNewLocalBlockContext(Scope* scope) { | 3159 void BytecodeGenerator::BuildNewLocalBlockContext(Scope* scope) { |
| 3186 AccumulatorResultScope accumulator_execution_result(this); | 3160 AccumulatorResultScope accumulator_execution_result(this); |
| 3187 DCHECK(scope->is_block_scope()); | 3161 DCHECK(scope->is_block_scope()); |
| 3188 | 3162 |
| 3189 VisitFunctionClosureForContext(); | 3163 VisitFunctionClosureForContext(); |
| 3190 builder()->CreateBlockContext(scope->scope_info()); | 3164 builder()->CreateBlockContext(scope->scope_info()); |
| 3191 execution_result()->SetResultInAccumulator(); | 3165 execution_result()->SetResultInAccumulator(); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3293 AccumulatorResultScope accumulator_execution_result(this); | 3267 AccumulatorResultScope accumulator_execution_result(this); |
| 3294 DeclarationScope* closure_scope = | 3268 DeclarationScope* closure_scope = |
| 3295 execution_context()->scope()->GetClosureScope(); | 3269 execution_context()->scope()->GetClosureScope(); |
| 3296 if (closure_scope->is_script_scope() || | 3270 if (closure_scope->is_script_scope() || |
| 3297 closure_scope->is_module_scope()) { | 3271 closure_scope->is_module_scope()) { |
| 3298 // Contexts nested in the native context have a canonical empty function as | 3272 // Contexts nested in the native context have a canonical empty function as |
| 3299 // their closure, not the anonymous closure containing the global code. | 3273 // their closure, not the anonymous closure containing the global code. |
| 3300 Register native_context = register_allocator()->NewRegister(); | 3274 Register native_context = register_allocator()->NewRegister(); |
| 3301 builder() | 3275 builder() |
| 3302 ->LoadContextSlot(execution_context()->reg(), | 3276 ->LoadContextSlot(execution_context()->reg(), |
| 3303 Context::NATIVE_CONTEXT_INDEX) | 3277 Context::NATIVE_CONTEXT_INDEX, 0) |
| 3304 .StoreAccumulatorInRegister(native_context) | 3278 .StoreAccumulatorInRegister(native_context) |
| 3305 .LoadContextSlot(native_context, Context::CLOSURE_INDEX); | 3279 .LoadContextSlot(native_context, Context::CLOSURE_INDEX, 0); |
| 3306 } else if (closure_scope->is_eval_scope()) { | 3280 } else if (closure_scope->is_eval_scope()) { |
| 3307 // Contexts created by a call to eval have the same closure as the | 3281 // Contexts created by a call to eval have the same closure as the |
| 3308 // context calling eval, not the anonymous closure containing the eval | 3282 // context calling eval, not the anonymous closure containing the eval |
| 3309 // code. Fetch it from the context. | 3283 // code. Fetch it from the context. |
| 3310 builder()->LoadContextSlot(execution_context()->reg(), | 3284 builder()->LoadContextSlot(execution_context()->reg(), |
| 3311 Context::CLOSURE_INDEX); | 3285 Context::CLOSURE_INDEX, 0); |
| 3312 } else { | 3286 } else { |
| 3313 DCHECK(closure_scope->is_function_scope()); | 3287 DCHECK(closure_scope->is_function_scope()); |
| 3314 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 3288 builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
| 3315 } | 3289 } |
| 3316 execution_result()->SetResultInAccumulator(); | 3290 execution_result()->SetResultInAccumulator(); |
| 3317 } | 3291 } |
| 3318 | 3292 |
| 3319 // Visits the expression |expr| and places the result in the accumulator. | 3293 // Visits the expression |expr| and places the result in the accumulator. |
| 3320 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { | 3294 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { |
| 3321 AccumulatorResultScope accumulator_scope(this); | 3295 AccumulatorResultScope accumulator_scope(this); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3393 return execution_context()->scope()->language_mode(); | 3367 return execution_context()->scope()->language_mode(); |
| 3394 } | 3368 } |
| 3395 | 3369 |
| 3396 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3370 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 3397 return TypeFeedbackVector::GetIndex(slot); | 3371 return TypeFeedbackVector::GetIndex(slot); |
| 3398 } | 3372 } |
| 3399 | 3373 |
| 3400 } // namespace interpreter | 3374 } // namespace interpreter |
| 3401 } // namespace internal | 3375 } // namespace internal |
| 3402 } // namespace v8 | 3376 } // namespace v8 |
| OLD | NEW |