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/compilation-info.h" | 9 #include "src/compilation-info.h" |
10 #include "src/compiler.h" | 10 #include "src/compiler.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. | |
neis
2016/09/02 12:06:07
This comment was not quite right: a scope may not
| |
747 if (scope()->NeedsContext()) { | 746 if (scope()->NeedsContext()) { |
748 // Push a new inner context scope for the function. | 747 // Push a new inner context scope for the function. |
749 VisitNewLocalFunctionContext(); | 748 VisitNewLocalFunctionContext(); |
neis
2016/09/02 12:06:07
I'm not happy with this name, as it can also creat
adamk
2016/09/02 17:51:51
BuildNewContext?
rmcilroy
2016/09/05 11:36:07
Could we do a rename pass on all the context creat
| |
750 ContextScope local_function_context(this, scope(), false); | 749 ContextScope local_function_context(this, scope(), false); |
751 VisitBuildLocalActivationContext(); | 750 VisitBuildLocalActivationContext(); |
752 GenerateBytecodeBody(); | 751 GenerateBytecodeBody(); |
753 } else { | 752 } else { |
754 GenerateBytecodeBody(); | 753 GenerateBytecodeBody(); |
755 } | 754 } |
756 | 755 |
757 // In generator functions, we may not have visited every yield in the AST | 756 // In generator functions, we may not have visited every yield in the AST |
758 // since we skip some obviously dead code. Hence the generated bytecode may | 757 // since we skip some obviously dead code. Hence the generated bytecode may |
759 // contain jumps to unbound labels (resume points that will never be used). | 758 // contain jumps to unbound labels (resume points that will never be used). |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
933 | 932 |
934 Register name = register_allocator()->NewRegister(); | 933 Register name = register_allocator()->NewRegister(); |
935 | 934 |
936 builder() | 935 builder() |
937 ->LoadLiteral(variable->name()) | 936 ->LoadLiteral(variable->name()) |
938 .StoreAccumulatorInRegister(name) | 937 .StoreAccumulatorInRegister(name) |
939 .CallRuntime(Runtime::kDeclareEvalVar, name, 1); | 938 .CallRuntime(Runtime::kDeclareEvalVar, name, 1); |
940 break; | 939 break; |
941 } | 940 } |
942 case VariableLocation::MODULE: | 941 case VariableLocation::MODULE: |
943 UNREACHABLE(); | 942 // Nothing to do here. |
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 switch (variable->location()) { | 949 switch (variable->location()) { |
950 case VariableLocation::UNALLOCATED: { | 950 case VariableLocation::UNALLOCATED: { |
951 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); | 951 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); |
952 globals_builder()->AddFunctionDeclaration(slot, decl->fun()); | 952 globals_builder()->AddFunctionDeclaration(slot, decl->fun()); |
953 break; | 953 break; |
(...skipping 19 matching lines...) Expand all Loading... | |
973 Register name = register_allocator()->NextConsecutiveRegister(); | 973 Register name = register_allocator()->NextConsecutiveRegister(); |
974 Register literal = register_allocator()->NextConsecutiveRegister(); | 974 Register literal = register_allocator()->NextConsecutiveRegister(); |
975 builder()->LoadLiteral(variable->name()).StoreAccumulatorInRegister(name); | 975 builder()->LoadLiteral(variable->name()).StoreAccumulatorInRegister(name); |
976 | 976 |
977 VisitForAccumulatorValue(decl->fun()); | 977 VisitForAccumulatorValue(decl->fun()); |
978 builder()->StoreAccumulatorInRegister(literal).CallRuntime( | 978 builder()->StoreAccumulatorInRegister(literal).CallRuntime( |
979 Runtime::kDeclareEvalFunction, name, 2); | 979 Runtime::kDeclareEvalFunction, name, 2); |
980 break; | 980 break; |
981 } | 981 } |
982 case VariableLocation::MODULE: | 982 case VariableLocation::MODULE: |
983 UNREACHABLE(); | 983 DCHECK(variable->mode() == LET); |
984 VisitForAccumulatorValue(decl->fun()); | |
985 VisitVariableAssignment(variable, Token::INIT, | |
986 FeedbackVectorSlot::Invalid()); | |
987 break; | |
984 } | 988 } |
985 } | 989 } |
986 | 990 |
987 void BytecodeGenerator::VisitDeclarations( | 991 void BytecodeGenerator::VisitDeclarations( |
988 ZoneList<Declaration*>* declarations) { | 992 ZoneList<Declaration*>* declarations) { |
989 RegisterAllocationScope register_scope(this); | 993 RegisterAllocationScope register_scope(this); |
990 DCHECK(globals_builder()->empty()); | 994 DCHECK(globals_builder()->empty()); |
991 for (int i = 0; i < declarations->length(); i++) { | 995 for (int i = 0; i < declarations->length(); i++) { |
992 RegisterAllocationScope register_scope(this); | 996 RegisterAllocationScope register_scope(this); |
993 Visit(declarations->at(i)); | 997 Visit(declarations->at(i)); |
(...skipping 985 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1979 } | 1983 } |
1980 | 1984 |
1981 builder()->LoadContextSlot(context_reg, variable->index()); | 1985 builder()->LoadContextSlot(context_reg, variable->index()); |
1982 BuildHoleCheckForVariableLoad(variable); | 1986 BuildHoleCheckForVariableLoad(variable); |
1983 break; | 1987 break; |
1984 } | 1988 } |
1985 case VariableLocation::LOOKUP: { | 1989 case VariableLocation::LOOKUP: { |
1986 builder()->LoadLookupSlot(variable->name(), typeof_mode); | 1990 builder()->LoadLookupSlot(variable->name(), typeof_mode); |
1987 break; | 1991 break; |
1988 } | 1992 } |
1989 case VariableLocation::MODULE: | 1993 case VariableLocation::MODULE: { |
1990 UNREACHABLE(); | 1994 ModuleDescriptor* descriptor = scope()->GetModuleScope()->module(); |
1995 if (variable->IsExport()) { | |
1996 auto it = descriptor->regular_exports().find(variable->raw_name()); | |
1997 DCHECK(it != descriptor->regular_exports().end()); | |
1998 Register export_name = register_allocator()->NewRegister(); | |
1999 builder() | |
2000 ->LoadLiteral(it->second->export_name->string()) | |
2001 .StoreAccumulatorInRegister(export_name) | |
2002 .CallRuntime(Runtime::kLoadModuleExport, export_name, 1); | |
2003 } else { | |
2004 UNIMPLEMENTED(); | |
2005 } | |
2006 break; | |
2007 } | |
1991 } | 2008 } |
1992 execution_result()->SetResultInAccumulator(); | 2009 execution_result()->SetResultInAccumulator(); |
1993 } | 2010 } |
1994 | 2011 |
1995 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( | 2012 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( |
1996 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { | 2013 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { |
1997 AccumulatorResultScope accumulator_result(this); | 2014 AccumulatorResultScope accumulator_result(this); |
1998 VisitVariableLoad(variable, slot, typeof_mode); | 2015 VisitVariableLoad(variable, slot, typeof_mode); |
1999 } | 2016 } |
2000 | 2017 |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2178 builder()->StoreContextSlot(context_reg, variable->index()); | 2195 builder()->StoreContextSlot(context_reg, variable->index()); |
2179 } else if (variable->throw_on_const_assignment(language_mode())) { | 2196 } else if (variable->throw_on_const_assignment(language_mode())) { |
2180 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); | 2197 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); |
2181 } | 2198 } |
2182 break; | 2199 break; |
2183 } | 2200 } |
2184 case VariableLocation::LOOKUP: { | 2201 case VariableLocation::LOOKUP: { |
2185 builder()->StoreLookupSlot(variable->name(), language_mode()); | 2202 builder()->StoreLookupSlot(variable->name(), language_mode()); |
2186 break; | 2203 break; |
2187 } | 2204 } |
2188 case VariableLocation::MODULE: | 2205 case VariableLocation::MODULE: { |
2189 UNREACHABLE(); | 2206 DCHECK(IsDeclaredVariableMode(mode)); |
2207 | |
2208 if (mode == CONST && op != Token::INIT) { | |
2209 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); | |
2210 break; | |
2211 } | |
2212 | |
2213 // If we don't throw above, we know that we're dealing with an | |
2214 // export because imports are const and we do not generate initializing | |
2215 // assignments for them. | |
2216 DCHECK(variable->IsExport()); | |
2217 | |
2218 ModuleDescriptor* mod = scope()->GetModuleScope()->module(); | |
2219 auto it = mod->regular_exports().find(variable->raw_name()); | |
2220 DCHECK(it != mod->regular_exports().end()); | |
2221 | |
2222 register_allocator()->PrepareForConsecutiveAllocations(2); | |
2223 Register export_name = register_allocator()->NextConsecutiveRegister(); | |
2224 Register value = register_allocator()->NextConsecutiveRegister(); | |
2225 builder() | |
2226 ->StoreAccumulatorInRegister(value) | |
2227 .LoadLiteral(it->second->export_name->string()) | |
2228 .StoreAccumulatorInRegister(export_name) | |
2229 .CallRuntime(Runtime::kStoreModuleExport, export_name, 2); | |
2230 break; | |
2231 } | |
2190 } | 2232 } |
2191 } | 2233 } |
2192 | 2234 |
2193 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 2235 void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
2194 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); | 2236 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); |
2195 Register object, key, home_object, value; | 2237 Register object, key, home_object, value; |
2196 Handle<String> name; | 2238 Handle<String> name; |
2197 | 2239 |
2198 // Left-hand side can only be a property, a global or a variable slot. | 2240 // Left-hand side can only be a property, a global or a variable slot. |
2199 Property* property = expr->target()->AsProperty(); | 2241 Property* property = expr->target()->AsProperty(); |
(...skipping 936 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3136 } | 3178 } |
3137 | 3179 |
3138 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { | 3180 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { |
3139 Visit(expr->expression()); | 3181 Visit(expr->expression()); |
3140 } | 3182 } |
3141 | 3183 |
3142 void BytecodeGenerator::VisitNewLocalFunctionContext() { | 3184 void BytecodeGenerator::VisitNewLocalFunctionContext() { |
3143 AccumulatorResultScope accumulator_execution_result(this); | 3185 AccumulatorResultScope accumulator_execution_result(this); |
3144 Scope* scope = this->scope(); | 3186 Scope* scope = this->scope(); |
3145 | 3187 |
3146 // Allocate a new local context. | 3188 // Create the appropriate context. |
3147 if (scope->is_script_scope()) { | 3189 if (scope->is_module_scope()) { |
3190 // We don't need to do anything for the outer script scope. | |
3191 DCHECK(scope->outer_scope()->is_script_scope()); | |
3192 | |
3193 RegisterAllocationScope register_scope(this); | |
3194 Register module = register_allocator()->NewRegister(); | |
3195 Register closure = register_allocator()->NewRegister(); | |
3196 Register scope_info = register_allocator()->NewRegister(); | |
3197 DCHECK(Register::AreContiguous(module, closure, scope_info)); | |
rmcilroy
2016/09/05 11:36:07
Please use PrepareForConsecutiveAllocations / Next
| |
3198 // A JSFunction representing a module is called with the module object as | |
3199 // its sole argument, which we pass on to PushModuleContext. | |
3200 builder() | |
3201 ->MoveRegister(builder()->Parameter(1), module) | |
3202 .LoadAccumulatorWithRegister(Register::function_closure()) | |
3203 .StoreAccumulatorInRegister(closure) | |
rmcilroy
2016/09/05 11:36:07
.MoveRegister(Register::function_closure(), closur
| |
3204 .LoadLiteral(scope->scope_info()) | |
3205 .StoreAccumulatorInRegister(scope_info) | |
3206 .CallRuntime(Runtime::kPushModuleContext, module, 3); | |
3207 } else if (scope->is_script_scope()) { | |
rmcilroy
2016/09/05 11:36:07
nit - could we do script scope first.
| |
3148 RegisterAllocationScope register_scope(this); | 3208 RegisterAllocationScope register_scope(this); |
3149 Register closure = register_allocator()->NewRegister(); | 3209 Register closure = register_allocator()->NewRegister(); |
3150 Register scope_info = register_allocator()->NewRegister(); | 3210 Register scope_info = register_allocator()->NewRegister(); |
3151 DCHECK(Register::AreContiguous(closure, scope_info)); | 3211 DCHECK(Register::AreContiguous(closure, scope_info)); |
3152 builder() | 3212 builder() |
3153 ->LoadAccumulatorWithRegister(Register::function_closure()) | 3213 ->LoadAccumulatorWithRegister(Register::function_closure()) |
3154 .StoreAccumulatorInRegister(closure) | 3214 .StoreAccumulatorInRegister(closure) |
3155 .LoadLiteral(scope->scope_info()) | 3215 .LoadLiteral(scope->scope_info()) |
3156 .StoreAccumulatorInRegister(scope_info) | 3216 .StoreAccumulatorInRegister(scope_info) |
3157 .CallRuntime(Runtime::kNewScriptContext, closure, 2); | 3217 .CallRuntime(Runtime::kNewScriptContext, closure, 2); |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3285 | 3345 |
3286 // Store the new target we were called with in the given variable. | 3346 // Store the new target we were called with in the given variable. |
3287 builder()->LoadAccumulatorWithRegister(Register::new_target()); | 3347 builder()->LoadAccumulatorWithRegister(Register::new_target()); |
3288 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); | 3348 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); |
3289 } | 3349 } |
3290 | 3350 |
3291 void BytecodeGenerator::VisitFunctionClosureForContext() { | 3351 void BytecodeGenerator::VisitFunctionClosureForContext() { |
3292 AccumulatorResultScope accumulator_execution_result(this); | 3352 AccumulatorResultScope accumulator_execution_result(this); |
3293 DeclarationScope* closure_scope = | 3353 DeclarationScope* closure_scope = |
3294 execution_context()->scope()->GetClosureScope(); | 3354 execution_context()->scope()->GetClosureScope(); |
3295 if (closure_scope->is_script_scope() || | 3355 if (closure_scope->is_script_scope()) { |
3296 closure_scope->is_module_scope()) { | |
3297 // Contexts nested in the native context have a canonical empty function as | 3356 // Contexts nested in the native context have a canonical empty function as |
3298 // their closure, not the anonymous closure containing the global code. | 3357 // their closure, not the anonymous closure containing the global code. |
3299 Register native_context = register_allocator()->NewRegister(); | 3358 Register native_context = register_allocator()->NewRegister(); |
3300 builder() | 3359 builder() |
3301 ->LoadContextSlot(execution_context()->reg(), | 3360 ->LoadContextSlot(execution_context()->reg(), |
3302 Context::NATIVE_CONTEXT_INDEX) | 3361 Context::NATIVE_CONTEXT_INDEX) |
3303 .StoreAccumulatorInRegister(native_context) | 3362 .StoreAccumulatorInRegister(native_context) |
3304 .LoadContextSlot(native_context, Context::CLOSURE_INDEX); | 3363 .LoadContextSlot(native_context, Context::CLOSURE_INDEX); |
3305 } else if (closure_scope->is_eval_scope()) { | 3364 } else if (closure_scope->is_eval_scope()) { |
3306 // Contexts created by a call to eval have the same closure as the | 3365 // Contexts created by a call to eval have the same closure as the |
3307 // context calling eval, not the anonymous closure containing the eval | 3366 // context calling eval, not the anonymous closure containing the eval |
3308 // code. Fetch it from the context. | 3367 // code. Fetch it from the context. |
3309 builder()->LoadContextSlot(execution_context()->reg(), | 3368 builder()->LoadContextSlot(execution_context()->reg(), |
3310 Context::CLOSURE_INDEX); | 3369 Context::CLOSURE_INDEX); |
3311 } else { | 3370 } else { |
3312 DCHECK(closure_scope->is_function_scope()); | 3371 DCHECK(closure_scope->is_function_scope() || |
3372 closure_scope->is_module_scope()); | |
3313 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 3373 builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
3314 } | 3374 } |
3315 execution_result()->SetResultInAccumulator(); | 3375 execution_result()->SetResultInAccumulator(); |
3316 } | 3376 } |
3317 | 3377 |
3318 // Visits the expression |expr| and places the result in the accumulator. | 3378 // Visits the expression |expr| and places the result in the accumulator. |
3319 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { | 3379 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { |
3320 AccumulatorResultScope accumulator_scope(this); | 3380 AccumulatorResultScope accumulator_scope(this); |
3321 Visit(expr); | 3381 Visit(expr); |
3322 } | 3382 } |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3392 return execution_context()->scope()->language_mode(); | 3452 return execution_context()->scope()->language_mode(); |
3393 } | 3453 } |
3394 | 3454 |
3395 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3455 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
3396 return TypeFeedbackVector::GetIndex(slot); | 3456 return TypeFeedbackVector::GetIndex(slot); |
3397 } | 3457 } |
3398 | 3458 |
3399 } // namespace interpreter | 3459 } // namespace interpreter |
3400 } // namespace internal | 3460 } // namespace internal |
3401 } // namespace v8 | 3461 } // namespace v8 |
OLD | NEW |