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 |