Chromium Code Reviews| 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. | |
| 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(); |
| 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 |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 934 | 933 |
| 935 Register name = register_allocator()->NewRegister(); | 934 Register name = register_allocator()->NewRegister(); |
| 936 | 935 |
| 937 builder() | 936 builder() |
| 938 ->LoadLiteral(variable->name()) | 937 ->LoadLiteral(variable->name()) |
| 939 .StoreAccumulatorInRegister(name) | 938 .StoreAccumulatorInRegister(name) |
| 940 .CallRuntime(Runtime::kDeclareEvalVar, name, 1); | 939 .CallRuntime(Runtime::kDeclareEvalVar, name, 1); |
| 941 break; | 940 break; |
| 942 } | 941 } |
| 943 case VariableLocation::MODULE: | 942 case VariableLocation::MODULE: |
| 944 UNREACHABLE(); | 943 // Nothing to do here. |
| 944 break; | |
| 945 } | 945 } |
| 946 } | 946 } |
| 947 | 947 |
| 948 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { | 948 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { |
| 949 Variable* variable = decl->proxy()->var(); | 949 Variable* variable = decl->proxy()->var(); |
| 950 switch (variable->location()) { | 950 switch (variable->location()) { |
| 951 case VariableLocation::GLOBAL: | 951 case VariableLocation::GLOBAL: |
| 952 case VariableLocation::UNALLOCATED: { | 952 case VariableLocation::UNALLOCATED: { |
| 953 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); | 953 FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); |
| 954 globals_builder()->AddFunctionDeclaration(slot, decl->fun()); | 954 globals_builder()->AddFunctionDeclaration(slot, decl->fun()); |
| 955 break; | 955 break; |
| 956 } | 956 } |
| 957 case VariableLocation::PARAMETER: | 957 case VariableLocation::PARAMETER: |
| 958 case VariableLocation::LOCAL: { | 958 case VariableLocation::LOCAL: { |
| 959 VisitForAccumulatorValue(decl->fun()); | 959 VisitForAccumulatorValue(decl->fun()); |
| 960 DCHECK(variable->mode() == LET || variable->mode() == VAR || | 960 DCHECK(variable->mode() == LET || variable->mode() == VAR || |
| 961 variable->mode() == CONST); | 961 variable->mode() == CONST); |
|
adamk
2016/09/01 23:13:34
I think you already touched this DCHECK in a diffe
neis
2016/09/02 11:32:58
Done in the other CL.
| |
| 962 VisitVariableAssignment(variable, Token::INIT, | 962 VisitVariableAssignment(variable, Token::INIT, |
| 963 FeedbackVectorSlot::Invalid()); | 963 FeedbackVectorSlot::Invalid()); |
| 964 break; | 964 break; |
| 965 } | 965 } |
| 966 case VariableLocation::CONTEXT: { | 966 case VariableLocation::CONTEXT: { |
| 967 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); | 967 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope())); |
| 968 VisitForAccumulatorValue(decl->fun()); | 968 VisitForAccumulatorValue(decl->fun()); |
| 969 builder()->StoreContextSlot(execution_context()->reg(), | 969 builder()->StoreContextSlot(execution_context()->reg(), |
| 970 variable->index()); | 970 variable->index()); |
| 971 break; | 971 break; |
| 972 } | 972 } |
| 973 case VariableLocation::LOOKUP: { | 973 case VariableLocation::LOOKUP: { |
| 974 register_allocator()->PrepareForConsecutiveAllocations(2); | 974 register_allocator()->PrepareForConsecutiveAllocations(2); |
| 975 Register name = register_allocator()->NextConsecutiveRegister(); | 975 Register name = register_allocator()->NextConsecutiveRegister(); |
| 976 Register literal = register_allocator()->NextConsecutiveRegister(); | 976 Register literal = register_allocator()->NextConsecutiveRegister(); |
| 977 builder()->LoadLiteral(variable->name()).StoreAccumulatorInRegister(name); | 977 builder()->LoadLiteral(variable->name()).StoreAccumulatorInRegister(name); |
| 978 | 978 |
| 979 VisitForAccumulatorValue(decl->fun()); | 979 VisitForAccumulatorValue(decl->fun()); |
| 980 builder()->StoreAccumulatorInRegister(literal).CallRuntime( | 980 builder()->StoreAccumulatorInRegister(literal).CallRuntime( |
| 981 Runtime::kDeclareEvalFunction, name, 2); | 981 Runtime::kDeclareEvalFunction, name, 2); |
| 982 break; | 982 break; |
| 983 } | 983 } |
| 984 case VariableLocation::MODULE: | 984 case VariableLocation::MODULE: |
| 985 UNREACHABLE(); | 985 VisitForAccumulatorValue(decl->fun()); |
|
adamk
2016/09/01 23:13:34
Add a DCHECK above here that the mode is LET?
neis
2016/09/02 11:32:58
Done.
| |
| 986 VisitVariableAssignment(variable, Token::INIT, | |
| 987 FeedbackVectorSlot::Invalid()); | |
| 988 break; | |
| 986 } | 989 } |
| 987 } | 990 } |
| 988 | 991 |
| 989 void BytecodeGenerator::VisitDeclarations( | 992 void BytecodeGenerator::VisitDeclarations( |
| 990 ZoneList<Declaration*>* declarations) { | 993 ZoneList<Declaration*>* declarations) { |
| 991 RegisterAllocationScope register_scope(this); | 994 RegisterAllocationScope register_scope(this); |
| 992 DCHECK(globals_builder()->empty()); | 995 DCHECK(globals_builder()->empty()); |
| 993 for (int i = 0; i < declarations->length(); i++) { | 996 for (int i = 0; i < declarations->length(); i++) { |
| 994 RegisterAllocationScope register_scope(this); | 997 RegisterAllocationScope register_scope(this); |
| 995 Visit(declarations->at(i)); | 998 Visit(declarations->at(i)); |
| (...skipping 986 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1982 } | 1985 } |
| 1983 | 1986 |
| 1984 builder()->LoadContextSlot(context_reg, variable->index()); | 1987 builder()->LoadContextSlot(context_reg, variable->index()); |
| 1985 BuildHoleCheckForVariableLoad(variable); | 1988 BuildHoleCheckForVariableLoad(variable); |
| 1986 break; | 1989 break; |
| 1987 } | 1990 } |
| 1988 case VariableLocation::LOOKUP: { | 1991 case VariableLocation::LOOKUP: { |
| 1989 builder()->LoadLookupSlot(variable->name(), typeof_mode); | 1992 builder()->LoadLookupSlot(variable->name(), typeof_mode); |
| 1990 break; | 1993 break; |
| 1991 } | 1994 } |
| 1992 case VariableLocation::MODULE: | 1995 case VariableLocation::MODULE: { |
| 1993 UNREACHABLE(); | 1996 ModuleDescriptor* descriptor = scope()->GetModuleScope()->module(); |
| 1997 if (variable->IsExport()) { | |
| 1998 auto it = descriptor->regular_exports().find(variable->raw_name()); | |
| 1999 DCHECK(it != descriptor->regular_exports().end()); | |
| 2000 Register export_name = register_allocator()->NewRegister(); | |
| 2001 builder() | |
| 2002 ->LoadLiteral(it->second->export_name->string()) | |
| 2003 .StoreAccumulatorInRegister(export_name) | |
| 2004 .CallRuntime(Runtime::kLoadModuleExport, export_name, 1); | |
| 2005 } else { | |
| 2006 UNIMPLEMENTED(); | |
| 2007 } | |
| 2008 break; | |
| 2009 } | |
| 1994 } | 2010 } |
| 1995 execution_result()->SetResultInAccumulator(); | 2011 execution_result()->SetResultInAccumulator(); |
| 1996 } | 2012 } |
| 1997 | 2013 |
| 1998 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( | 2014 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue( |
| 1999 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { | 2015 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) { |
| 2000 AccumulatorResultScope accumulator_result(this); | 2016 AccumulatorResultScope accumulator_result(this); |
| 2001 VisitVariableLoad(variable, slot, typeof_mode); | 2017 VisitVariableLoad(variable, slot, typeof_mode); |
| 2002 } | 2018 } |
| 2003 | 2019 |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2182 builder()->StoreContextSlot(context_reg, variable->index()); | 2198 builder()->StoreContextSlot(context_reg, variable->index()); |
| 2183 } else if (variable->throw_on_const_assignment(language_mode())) { | 2199 } else if (variable->throw_on_const_assignment(language_mode())) { |
| 2184 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); | 2200 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); |
| 2185 } | 2201 } |
| 2186 break; | 2202 break; |
| 2187 } | 2203 } |
| 2188 case VariableLocation::LOOKUP: { | 2204 case VariableLocation::LOOKUP: { |
| 2189 builder()->StoreLookupSlot(variable->name(), language_mode()); | 2205 builder()->StoreLookupSlot(variable->name(), language_mode()); |
| 2190 break; | 2206 break; |
| 2191 } | 2207 } |
| 2192 case VariableLocation::MODULE: | 2208 case VariableLocation::MODULE: { |
| 2193 UNREACHABLE(); | 2209 DCHECK(IsDeclaredVariableMode(mode)); |
| 2210 | |
| 2211 if (mode == CONST && op != Token::INIT) { | |
| 2212 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); | |
| 2213 break; | |
| 2214 } | |
| 2215 | |
| 2216 // If we don't throw above, we know that we're dealing with an | |
| 2217 // export because imports are const and we do not generate initializing | |
| 2218 // assignments for them. | |
| 2219 DCHECK(variable->IsExport()); | |
| 2220 | |
| 2221 ModuleDescriptor* mod = scope()->GetModuleScope()->module(); | |
| 2222 auto it = mod->regular_exports().find(variable->raw_name()); | |
| 2223 DCHECK(it != mod->regular_exports().end()); | |
| 2224 | |
| 2225 register_allocator()->PrepareForConsecutiveAllocations(2); | |
| 2226 Register export_name = register_allocator()->NextConsecutiveRegister(); | |
| 2227 Register value = register_allocator()->NextConsecutiveRegister(); | |
| 2228 builder() | |
| 2229 ->StoreAccumulatorInRegister(value) | |
| 2230 .LoadLiteral(it->second->export_name->string()) | |
| 2231 .StoreAccumulatorInRegister(export_name) | |
| 2232 .CallRuntime(Runtime::kStoreModuleExport, export_name, 2); | |
| 2233 break; | |
| 2234 } | |
| 2194 } | 2235 } |
| 2195 } | 2236 } |
| 2196 | 2237 |
| 2197 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 2238 void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
| 2198 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); | 2239 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); |
| 2199 Register object, key, home_object, value; | 2240 Register object, key, home_object, value; |
| 2200 Handle<String> name; | 2241 Handle<String> name; |
| 2201 | 2242 |
| 2202 // Left-hand side can only be a property, a global or a variable slot. | 2243 // Left-hand side can only be a property, a global or a variable slot. |
| 2203 Property* property = expr->target()->AsProperty(); | 2244 Property* property = expr->target()->AsProperty(); |
| (...skipping 930 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3134 } | 3175 } |
| 3135 | 3176 |
| 3136 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { | 3177 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { |
| 3137 Visit(expr->expression()); | 3178 Visit(expr->expression()); |
| 3138 } | 3179 } |
| 3139 | 3180 |
| 3140 void BytecodeGenerator::VisitNewLocalFunctionContext() { | 3181 void BytecodeGenerator::VisitNewLocalFunctionContext() { |
| 3141 AccumulatorResultScope accumulator_execution_result(this); | 3182 AccumulatorResultScope accumulator_execution_result(this); |
| 3142 Scope* scope = this->scope(); | 3183 Scope* scope = this->scope(); |
| 3143 | 3184 |
| 3144 // Allocate a new local context. | 3185 // Allocate a new local context. XXX |
| 3145 if (scope->is_script_scope()) { | 3186 if (scope->is_module_scope()) { |
| 3187 // We don't need to do anything for the outer script scope. | |
| 3188 DCHECK(scope->outer_scope()->is_script_scope()); | |
| 3189 | |
| 3190 RegisterAllocationScope register_scope(this); | |
| 3191 Register module = register_allocator()->NewRegister(); | |
| 3192 Register closure = register_allocator()->NewRegister(); | |
| 3193 Register scope_info = register_allocator()->NewRegister(); | |
| 3194 DCHECK(Register::AreContiguous(module, closure, scope_info)); | |
| 3195 // A JSFunction representing a module is called with the module object as | |
| 3196 // its sole argument, which we pass on to PushModuleContext. | |
| 3197 builder() | |
| 3198 ->MoveRegister(builder()->Parameter(1), module) | |
| 3199 .LoadAccumulatorWithRegister(Register::function_closure()) | |
| 3200 .StoreAccumulatorInRegister(closure) | |
| 3201 .LoadLiteral(scope->scope_info()) | |
| 3202 .StoreAccumulatorInRegister(scope_info) | |
| 3203 .CallRuntime(Runtime::kPushModuleContext, module, 3); | |
| 3204 } else if (scope->is_script_scope()) { | |
| 3146 RegisterAllocationScope register_scope(this); | 3205 RegisterAllocationScope register_scope(this); |
| 3147 Register closure = register_allocator()->NewRegister(); | 3206 Register closure = register_allocator()->NewRegister(); |
| 3148 Register scope_info = register_allocator()->NewRegister(); | 3207 Register scope_info = register_allocator()->NewRegister(); |
| 3149 DCHECK(Register::AreContiguous(closure, scope_info)); | 3208 DCHECK(Register::AreContiguous(closure, scope_info)); |
| 3150 builder() | 3209 builder() |
| 3151 ->LoadAccumulatorWithRegister(Register::function_closure()) | 3210 ->LoadAccumulatorWithRegister(Register::function_closure()) |
| 3152 .StoreAccumulatorInRegister(closure) | 3211 .StoreAccumulatorInRegister(closure) |
| 3153 .LoadLiteral(scope->scope_info()) | 3212 .LoadLiteral(scope->scope_info()) |
| 3154 .StoreAccumulatorInRegister(scope_info) | 3213 .StoreAccumulatorInRegister(scope_info) |
| 3155 .CallRuntime(Runtime::kNewScriptContext, closure, 2); | 3214 .CallRuntime(Runtime::kNewScriptContext, closure, 2); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3283 | 3342 |
| 3284 // Store the new target we were called with in the given variable. | 3343 // Store the new target we were called with in the given variable. |
| 3285 builder()->LoadAccumulatorWithRegister(Register::new_target()); | 3344 builder()->LoadAccumulatorWithRegister(Register::new_target()); |
| 3286 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); | 3345 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); |
| 3287 } | 3346 } |
| 3288 | 3347 |
| 3289 void BytecodeGenerator::VisitFunctionClosureForContext() { | 3348 void BytecodeGenerator::VisitFunctionClosureForContext() { |
| 3290 AccumulatorResultScope accumulator_execution_result(this); | 3349 AccumulatorResultScope accumulator_execution_result(this); |
| 3291 DeclarationScope* closure_scope = | 3350 DeclarationScope* closure_scope = |
| 3292 execution_context()->scope()->GetClosureScope(); | 3351 execution_context()->scope()->GetClosureScope(); |
| 3293 if (closure_scope->is_script_scope() || | 3352 if (closure_scope->is_script_scope()) { |
| 3294 closure_scope->is_module_scope()) { | |
| 3295 // Contexts nested in the native context have a canonical empty function as | 3353 // Contexts nested in the native context have a canonical empty function as |
| 3296 // their closure, not the anonymous closure containing the global code. | 3354 // their closure, not the anonymous closure containing the global code. |
| 3297 Register native_context = register_allocator()->NewRegister(); | 3355 Register native_context = register_allocator()->NewRegister(); |
| 3298 builder() | 3356 builder() |
| 3299 ->LoadContextSlot(execution_context()->reg(), | 3357 ->LoadContextSlot(execution_context()->reg(), |
| 3300 Context::NATIVE_CONTEXT_INDEX) | 3358 Context::NATIVE_CONTEXT_INDEX) |
| 3301 .StoreAccumulatorInRegister(native_context) | 3359 .StoreAccumulatorInRegister(native_context) |
| 3302 .LoadContextSlot(native_context, Context::CLOSURE_INDEX); | 3360 .LoadContextSlot(native_context, Context::CLOSURE_INDEX); |
| 3303 } else if (closure_scope->is_eval_scope()) { | 3361 } else if (closure_scope->is_eval_scope()) { |
| 3304 // Contexts created by a call to eval have the same closure as the | 3362 // Contexts created by a call to eval have the same closure as the |
| 3305 // context calling eval, not the anonymous closure containing the eval | 3363 // context calling eval, not the anonymous closure containing the eval |
| 3306 // code. Fetch it from the context. | 3364 // code. Fetch it from the context. |
| 3307 builder()->LoadContextSlot(execution_context()->reg(), | 3365 builder()->LoadContextSlot(execution_context()->reg(), |
| 3308 Context::CLOSURE_INDEX); | 3366 Context::CLOSURE_INDEX); |
| 3309 } else { | 3367 } else { |
| 3310 DCHECK(closure_scope->is_function_scope()); | 3368 DCHECK(closure_scope->is_function_scope() || |
| 3369 closure_scope->is_module_scope()); | |
| 3311 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 3370 builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
| 3312 } | 3371 } |
| 3313 execution_result()->SetResultInAccumulator(); | 3372 execution_result()->SetResultInAccumulator(); |
| 3314 } | 3373 } |
| 3315 | 3374 |
| 3316 // Visits the expression |expr| and places the result in the accumulator. | 3375 // Visits the expression |expr| and places the result in the accumulator. |
| 3317 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { | 3376 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { |
| 3318 AccumulatorResultScope accumulator_scope(this); | 3377 AccumulatorResultScope accumulator_scope(this); |
| 3319 Visit(expr); | 3378 Visit(expr); |
| 3320 } | 3379 } |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3390 return execution_context()->scope()->language_mode(); | 3449 return execution_context()->scope()->language_mode(); |
| 3391 } | 3450 } |
| 3392 | 3451 |
| 3393 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3452 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 3394 return TypeFeedbackVector::GetIndex(slot); | 3453 return TypeFeedbackVector::GetIndex(slot); |
| 3395 } | 3454 } |
| 3396 | 3455 |
| 3397 } // namespace interpreter | 3456 } // namespace interpreter |
| 3398 } // namespace internal | 3457 } // namespace internal |
| 3399 } // namespace v8 | 3458 } // namespace v8 |
| OLD | NEW |