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