| 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 725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 736 // Initialize control scope. | 736 // Initialize control scope. |
| 737 ControlScopeForTopLevel control(this); | 737 ControlScopeForTopLevel control(this); |
| 738 | 738 |
| 739 RegisterAllocationScope register_scope(this); | 739 RegisterAllocationScope register_scope(this); |
| 740 | 740 |
| 741 if (IsResumableFunction(info()->literal()->kind())) { | 741 if (IsResumableFunction(info()->literal()->kind())) { |
| 742 generator_state_ = register_allocator()->NewRegister(); | 742 generator_state_ = register_allocator()->NewRegister(); |
| 743 VisitGeneratorPrologue(); | 743 VisitGeneratorPrologue(); |
| 744 } | 744 } |
| 745 | 745 |
| 746 // Build function context only if there are context allocated variables. |
| 746 if (scope()->NeedsContext()) { | 747 if (scope()->NeedsContext()) { |
| 747 // Push a new inner context scope for the function. | 748 // Push a new inner context scope for the function. |
| 748 VisitNewLocalFunctionContext(); | 749 VisitNewLocalFunctionContext(); |
| 749 ContextScope local_function_context(this, scope(), false); | 750 ContextScope local_function_context(this, scope(), false); |
| 750 VisitBuildLocalActivationContext(); | 751 VisitBuildLocalActivationContext(); |
| 751 GenerateBytecodeBody(); | 752 GenerateBytecodeBody(); |
| 752 } else { | 753 } else { |
| 753 GenerateBytecodeBody(); | 754 GenerateBytecodeBody(); |
| 754 } | 755 } |
| 755 | 756 |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 932 | 933 |
| 933 Register name = register_allocator()->NewRegister(); | 934 Register name = register_allocator()->NewRegister(); |
| 934 | 935 |
| 935 builder() | 936 builder() |
| 936 ->LoadLiteral(variable->name()) | 937 ->LoadLiteral(variable->name()) |
| 937 .StoreAccumulatorInRegister(name) | 938 .StoreAccumulatorInRegister(name) |
| 938 .CallRuntime(Runtime::kDeclareEvalVar, name, 1); | 939 .CallRuntime(Runtime::kDeclareEvalVar, name, 1); |
| 939 break; | 940 break; |
| 940 } | 941 } |
| 941 case VariableLocation::MODULE: | 942 case VariableLocation::MODULE: |
| 942 // Nothing to do here. | 943 UNREACHABLE(); |
| 943 break; | |
| 944 } | 944 } |
| 945 } | 945 } |
| 946 | 946 |
| 947 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { | 947 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { |
| 948 Variable* variable = decl->proxy()->var(); | 948 Variable* variable = decl->proxy()->var(); |
| 949 DCHECK(variable->mode() == LET || variable->mode() == VAR); | 949 DCHECK(variable->mode() == LET || variable->mode() == VAR); |
| 950 switch (variable->location()) { | 950 switch (variable->location()) { |
| 951 case VariableLocation::UNALLOCATED: { | 951 case VariableLocation::UNALLOCATED: { |
| 952 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); | 952 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); |
| 953 globals_builder()->AddFunctionDeclaration(slot, decl->fun()); | 953 globals_builder()->AddFunctionDeclaration(slot, decl->fun()); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 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( |
| 978 Runtime::kDeclareEvalFunction, name, 2); | 978 Runtime::kDeclareEvalFunction, name, 2); |
| 979 break; | 979 break; |
| 980 } | 980 } |
| 981 case VariableLocation::MODULE: | 981 case VariableLocation::MODULE: |
| 982 DCHECK(variable->mode() == LET); | 982 UNREACHABLE(); |
| 983 VisitForAccumulatorValue(decl->fun()); | |
| 984 VisitVariableAssignment(variable, Token::INIT, | |
| 985 FeedbackVectorSlot::Invalid()); | |
| 986 break; | |
| 987 } | 983 } |
| 988 } | 984 } |
| 989 | 985 |
| 990 void BytecodeGenerator::VisitDeclarations( | 986 void BytecodeGenerator::VisitDeclarations( |
| 991 ZoneList<Declaration*>* declarations) { | 987 ZoneList<Declaration*>* declarations) { |
| 992 RegisterAllocationScope register_scope(this); | 988 RegisterAllocationScope register_scope(this); |
| 993 DCHECK(globals_builder()->empty()); | 989 DCHECK(globals_builder()->empty()); |
| 994 for (int i = 0; i < declarations->length(); i++) { | 990 for (int i = 0; i < declarations->length(); i++) { |
| 995 RegisterAllocationScope register_scope(this); | 991 RegisterAllocationScope register_scope(this); |
| 996 Visit(declarations->at(i)); | 992 Visit(declarations->at(i)); |
| (...skipping 978 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1975 } | 1971 } |
| 1976 | 1972 |
| 1977 builder()->LoadContextSlot(context_reg, variable->index()); | 1973 builder()->LoadContextSlot(context_reg, variable->index()); |
| 1978 BuildHoleCheckForVariableLoad(variable); | 1974 BuildHoleCheckForVariableLoad(variable); |
| 1979 break; | 1975 break; |
| 1980 } | 1976 } |
| 1981 case VariableLocation::LOOKUP: { | 1977 case VariableLocation::LOOKUP: { |
| 1982 builder()->LoadLookupSlot(variable->name(), typeof_mode); | 1978 builder()->LoadLookupSlot(variable->name(), typeof_mode); |
| 1983 break; | 1979 break; |
| 1984 } | 1980 } |
| 1985 case VariableLocation::MODULE: { | 1981 case VariableLocation::MODULE: |
| 1986 ModuleDescriptor* descriptor = scope()->GetModuleScope()->module(); | 1982 UNREACHABLE(); |
| 1987 if (variable->IsExport()) { | |
| 1988 auto it = descriptor->regular_exports().find(variable->raw_name()); | |
| 1989 DCHECK(it != descriptor->regular_exports().end()); | |
| 1990 Register export_name = register_allocator()->NewRegister(); | |
| 1991 builder() | |
| 1992 ->LoadLiteral(it->second->export_name->string()) | |
| 1993 .StoreAccumulatorInRegister(export_name) | |
| 1994 .CallRuntime(Runtime::kLoadModuleExport, export_name, 1); | |
| 1995 } else { | |
| 1996 UNIMPLEMENTED(); | |
| 1997 } | |
| 1998 break; | |
| 1999 } | |
| 2000 } | 1983 } |
| 2001 execution_result()->SetResultInAccumulator(); | 1984 execution_result()->SetResultInAccumulator(); |
| 2002 } | 1985 } |
| 2003 | 1986 |
| 2004 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( | 1987 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( |
| 2005 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { | 1988 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { |
| 2006 AccumulatorResultScope accumulator_result(this); | 1989 AccumulatorResultScope accumulator_result(this); |
| 2007 VisitVariableLoad(variable, slot, typeof_mode); | 1990 VisitVariableLoad(variable, slot, typeof_mode); |
| 2008 } | 1991 } |
| 2009 | 1992 |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2187 builder()->StoreContextSlot(context_reg, variable->index()); | 2170 builder()->StoreContextSlot(context_reg, variable->index()); |
| 2188 } else if (variable->throw_on_const_assignment(language_mode())) { | 2171 } else if (variable->throw_on_const_assignment(language_mode())) { |
| 2189 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); | 2172 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); |
| 2190 } | 2173 } |
| 2191 break; | 2174 break; |
| 2192 } | 2175 } |
| 2193 case VariableLocation::LOOKUP: { | 2176 case VariableLocation::LOOKUP: { |
| 2194 builder()->StoreLookupSlot(variable->name(), language_mode()); | 2177 builder()->StoreLookupSlot(variable->name(), language_mode()); |
| 2195 break; | 2178 break; |
| 2196 } | 2179 } |
| 2197 case VariableLocation::MODULE: { | 2180 case VariableLocation::MODULE: |
| 2198 DCHECK(IsDeclaredVariableMode(mode)); | 2181 UNREACHABLE(); |
| 2199 | |
| 2200 if (mode == CONST && op != Token::INIT) { | |
| 2201 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); | |
| 2202 break; | |
| 2203 } | |
| 2204 | |
| 2205 // If we don't throw above, we know that we're dealing with an | |
| 2206 // export because imports are const and we do not generate initializing | |
| 2207 // assignments for them. | |
| 2208 DCHECK(variable->IsExport()); | |
| 2209 | |
| 2210 ModuleDescriptor* mod = scope()->GetModuleScope()->module(); | |
| 2211 auto it = mod->regular_exports().find(variable->raw_name()); | |
| 2212 DCHECK(it != mod->regular_exports().end()); | |
| 2213 | |
| 2214 register_allocator()->PrepareForConsecutiveAllocations(2); | |
| 2215 Register export_name = register_allocator()->NextConsecutiveRegister(); | |
| 2216 Register value = register_allocator()->NextConsecutiveRegister(); | |
| 2217 builder() | |
| 2218 ->StoreAccumulatorInRegister(value) | |
| 2219 .LoadLiteral(it->second->export_name->string()) | |
| 2220 .StoreAccumulatorInRegister(export_name) | |
| 2221 .CallRuntime(Runtime::kStoreModuleExport, export_name, 2); | |
| 2222 break; | |
| 2223 } | |
| 2224 } | 2182 } |
| 2225 } | 2183 } |
| 2226 | 2184 |
| 2227 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 2185 void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
| 2228 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); | 2186 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); |
| 2229 Register object, key, home_object, value; | 2187 Register object, key, home_object, value; |
| 2230 Handle<String> name; | 2188 Handle<String> name; |
| 2231 | 2189 |
| 2232 // Left-hand side can only be a property, a global or a variable slot. | 2190 // Left-hand side can only be a property, a global or a variable slot. |
| 2233 Property* property = expr->target()->AsProperty(); | 2191 Property* property = expr->target()->AsProperty(); |
| (...skipping 936 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3170 } | 3128 } |
| 3171 | 3129 |
| 3172 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { | 3130 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { |
| 3173 Visit(expr->expression()); | 3131 Visit(expr->expression()); |
| 3174 } | 3132 } |
| 3175 | 3133 |
| 3176 void BytecodeGenerator::VisitNewLocalFunctionContext() { | 3134 void BytecodeGenerator::VisitNewLocalFunctionContext() { |
| 3177 AccumulatorResultScope accumulator_execution_result(this); | 3135 AccumulatorResultScope accumulator_execution_result(this); |
| 3178 Scope* scope = this->scope(); | 3136 Scope* scope = this->scope(); |
| 3179 | 3137 |
| 3180 // Create the appropriate context. | 3138 // Allocate a new local context. |
| 3181 if (scope->is_script_scope()) { | 3139 if (scope->is_script_scope()) { |
| 3182 RegisterAllocationScope register_scope(this); | 3140 RegisterAllocationScope register_scope(this); |
| 3183 register_allocator()->PrepareForConsecutiveAllocations(2); | 3141 Register closure = register_allocator()->NewRegister(); |
| 3184 Register closure = register_allocator()->NextConsecutiveRegister(); | 3142 Register scope_info = register_allocator()->NewRegister(); |
| 3185 Register scope_info = register_allocator()->NextConsecutiveRegister(); | 3143 DCHECK(Register::AreContiguous(closure, scope_info)); |
| 3186 builder() | 3144 builder() |
| 3187 ->LoadAccumulatorWithRegister(Register::function_closure()) | 3145 ->LoadAccumulatorWithRegister(Register::function_closure()) |
| 3188 .StoreAccumulatorInRegister(closure) | 3146 .StoreAccumulatorInRegister(closure) |
| 3189 .LoadLiteral(scope->scope_info()) | 3147 .LoadLiteral(scope->scope_info()) |
| 3190 .StoreAccumulatorInRegister(scope_info) | 3148 .StoreAccumulatorInRegister(scope_info) |
| 3191 .CallRuntime(Runtime::kNewScriptContext, closure, 2); | 3149 .CallRuntime(Runtime::kNewScriptContext, closure, 2); |
| 3192 } else if (scope->is_module_scope()) { | |
| 3193 // We don't need to do anything for the outer script scope. | |
| 3194 DCHECK(scope->outer_scope()->is_script_scope()); | |
| 3195 | |
| 3196 RegisterAllocationScope register_scope(this); | |
| 3197 register_allocator()->PrepareForConsecutiveAllocations(3); | |
| 3198 Register module = register_allocator()->NextConsecutiveRegister(); | |
| 3199 Register closure = register_allocator()->NextConsecutiveRegister(); | |
| 3200 Register scope_info = register_allocator()->NextConsecutiveRegister(); | |
| 3201 // A JSFunction representing a module is called with the module object as | |
| 3202 // its sole argument, which we pass on to PushModuleContext. | |
| 3203 builder() | |
| 3204 ->MoveRegister(builder()->Parameter(1), module) | |
| 3205 .LoadAccumulatorWithRegister(Register::function_closure()) | |
| 3206 .StoreAccumulatorInRegister(closure) | |
| 3207 .LoadLiteral(scope->scope_info()) | |
| 3208 .StoreAccumulatorInRegister(scope_info) | |
| 3209 .CallRuntime(Runtime::kPushModuleContext, module, 3); | |
| 3210 } else { | 3150 } else { |
| 3211 int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 3151 int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 3212 builder()->CreateFunctionContext(slot_count); | 3152 builder()->CreateFunctionContext(slot_count); |
| 3213 } | 3153 } |
| 3214 execution_result()->SetResultInAccumulator(); | 3154 execution_result()->SetResultInAccumulator(); |
| 3215 } | 3155 } |
| 3216 | 3156 |
| 3217 void BytecodeGenerator::VisitBuildLocalActivationContext() { | 3157 void BytecodeGenerator::VisitBuildLocalActivationContext() { |
| 3218 DeclarationScope* scope = this->scope(); | 3158 DeclarationScope* scope = this->scope(); |
| 3219 | 3159 |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3346 // before a local variable containing the <new.target> is used. Using a label | 3286 // before a local variable containing the <new.target> is used. Using a label |
| 3347 // as below flushes the entire pipeline, we should be more specific here. | 3287 // as below flushes the entire pipeline, we should be more specific here. |
| 3348 BytecodeLabel flush_state_label; | 3288 BytecodeLabel flush_state_label; |
| 3349 builder()->Bind(&flush_state_label); | 3289 builder()->Bind(&flush_state_label); |
| 3350 } | 3290 } |
| 3351 | 3291 |
| 3352 void BytecodeGenerator::VisitFunctionClosureForContext() { | 3292 void BytecodeGenerator::VisitFunctionClosureForContext() { |
| 3353 AccumulatorResultScope accumulator_execution_result(this); | 3293 AccumulatorResultScope accumulator_execution_result(this); |
| 3354 DeclarationScope* closure_scope = | 3294 DeclarationScope* closure_scope = |
| 3355 execution_context()->scope()->GetClosureScope(); | 3295 execution_context()->scope()->GetClosureScope(); |
| 3356 if (closure_scope->is_script_scope()) { | 3296 if (closure_scope->is_script_scope() || |
| 3297 closure_scope->is_module_scope()) { |
| 3357 // Contexts nested in the native context have a canonical empty function as | 3298 // Contexts nested in the native context have a canonical empty function as |
| 3358 // their closure, not the anonymous closure containing the global code. | 3299 // their closure, not the anonymous closure containing the global code. |
| 3359 Register native_context = register_allocator()->NewRegister(); | 3300 Register native_context = register_allocator()->NewRegister(); |
| 3360 builder() | 3301 builder() |
| 3361 ->LoadContextSlot(execution_context()->reg(), | 3302 ->LoadContextSlot(execution_context()->reg(), |
| 3362 Context::NATIVE_CONTEXT_INDEX) | 3303 Context::NATIVE_CONTEXT_INDEX) |
| 3363 .StoreAccumulatorInRegister(native_context) | 3304 .StoreAccumulatorInRegister(native_context) |
| 3364 .LoadContextSlot(native_context, Context::CLOSURE_INDEX); | 3305 .LoadContextSlot(native_context, Context::CLOSURE_INDEX); |
| 3365 } else if (closure_scope->is_eval_scope()) { | 3306 } else if (closure_scope->is_eval_scope()) { |
| 3366 // Contexts created by a call to eval have the same closure as the | 3307 // Contexts created by a call to eval have the same closure as the |
| 3367 // context calling eval, not the anonymous closure containing the eval | 3308 // context calling eval, not the anonymous closure containing the eval |
| 3368 // code. Fetch it from the context. | 3309 // code. Fetch it from the context. |
| 3369 builder()->LoadContextSlot(execution_context()->reg(), | 3310 builder()->LoadContextSlot(execution_context()->reg(), |
| 3370 Context::CLOSURE_INDEX); | 3311 Context::CLOSURE_INDEX); |
| 3371 } else { | 3312 } else { |
| 3372 DCHECK(closure_scope->is_function_scope() || | 3313 DCHECK(closure_scope->is_function_scope()); |
| 3373 closure_scope->is_module_scope()); | |
| 3374 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 3314 builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
| 3375 } | 3315 } |
| 3376 execution_result()->SetResultInAccumulator(); | 3316 execution_result()->SetResultInAccumulator(); |
| 3377 } | 3317 } |
| 3378 | 3318 |
| 3379 // Visits the expression |expr| and places the result in the accumulator. | 3319 // Visits the expression |expr| and places the result in the accumulator. |
| 3380 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { | 3320 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { |
| 3381 AccumulatorResultScope accumulator_scope(this); | 3321 AccumulatorResultScope accumulator_scope(this); |
| 3382 Visit(expr); | 3322 Visit(expr); |
| 3383 } | 3323 } |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3453 return execution_context()->scope()->language_mode(); | 3393 return execution_context()->scope()->language_mode(); |
| 3454 } | 3394 } |
| 3455 | 3395 |
| 3456 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3396 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 3457 return TypeFeedbackVector::GetIndex(slot); | 3397 return TypeFeedbackVector::GetIndex(slot); |
| 3458 } | 3398 } |
| 3459 | 3399 |
| 3460 } // namespace interpreter | 3400 } // namespace interpreter |
| 3461 } // namespace internal | 3401 } // namespace internal |
| 3462 } // namespace v8 | 3402 } // namespace v8 |
| OLD | NEW |