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 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 if (scope()->NeedsContext()) { | 746 if (scope()->NeedsContext()) { |
747 // Push a new inner context scope for the function. | 747 // Push a new inner context scope for the function. |
748 VisitNewLocalFunctionContext(); | 748 BuildNewLocalActivationContext(); |
749 ContextScope local_function_context(this, scope(), false); | 749 ContextScope local_function_context(this, scope(), false); |
750 VisitBuildLocalActivationContext(); | 750 BuildLocalActivationContextInitialization(); |
751 GenerateBytecodeBody(); | 751 GenerateBytecodeBody(); |
752 } else { | 752 } else { |
753 GenerateBytecodeBody(); | 753 GenerateBytecodeBody(); |
754 } | 754 } |
755 | 755 |
756 // 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 |
757 // 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 |
758 // 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). |
759 // We bind these now. | 759 // We bind these now. |
760 for (auto& label : generator_resume_points_) { | 760 for (auto& label : generator_resume_points_) { |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
872 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) | 872 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) |
873 .StoreAccumulatorInRegister(generator_state_); | 873 .StoreAccumulatorInRegister(generator_state_); |
874 // This is a regular call. Fall through to the ordinary function prologue, | 874 // This is a regular call. Fall through to the ordinary function prologue, |
875 // after which we will run into the generator object creation and other extra | 875 // after which we will run into the generator object creation and other extra |
876 // code inserted by the parser. | 876 // code inserted by the parser. |
877 } | 877 } |
878 | 878 |
879 void BytecodeGenerator::VisitBlock(Block* stmt) { | 879 void BytecodeGenerator::VisitBlock(Block* stmt) { |
880 // Visit declarations and statements. | 880 // Visit declarations and statements. |
881 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) { | 881 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) { |
882 VisitNewLocalBlockContext(stmt->scope()); | 882 BuildNewLocalBlockContext(stmt->scope()); |
883 ContextScope scope(this, stmt->scope()); | 883 ContextScope scope(this, stmt->scope()); |
884 VisitBlockDeclarationsAndStatements(stmt); | 884 VisitBlockDeclarationsAndStatements(stmt); |
885 } else { | 885 } else { |
886 VisitBlockDeclarationsAndStatements(stmt); | 886 VisitBlockDeclarationsAndStatements(stmt); |
887 } | 887 } |
888 } | 888 } |
889 | 889 |
890 void BytecodeGenerator::VisitBlockDeclarationsAndStatements(Block* stmt) { | 890 void BytecodeGenerator::VisitBlockDeclarationsAndStatements(Block* stmt) { |
891 BlockBuilder block_builder(builder()); | 891 BlockBuilder block_builder(builder()); |
892 ControlScopeForBreakable execution_control(this, stmt, &block_builder); | 892 ControlScopeForBreakable execution_control(this, stmt, &block_builder); |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1089 | 1089 |
1090 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 1090 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
1091 builder()->SetStatementPosition(stmt); | 1091 builder()->SetStatementPosition(stmt); |
1092 VisitForAccumulatorValue(stmt->expression()); | 1092 VisitForAccumulatorValue(stmt->expression()); |
1093 execution_control()->ReturnAccumulator(); | 1093 execution_control()->ReturnAccumulator(); |
1094 } | 1094 } |
1095 | 1095 |
1096 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { | 1096 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { |
1097 builder()->SetStatementPosition(stmt); | 1097 builder()->SetStatementPosition(stmt); |
1098 VisitForAccumulatorValue(stmt->expression()); | 1098 VisitForAccumulatorValue(stmt->expression()); |
1099 VisitNewLocalWithContext(stmt->scope()); | 1099 BuildNewLocalWithContext(stmt->scope()); |
1100 VisitInScope(stmt->statement(), stmt->scope()); | 1100 VisitInScope(stmt->statement(), stmt->scope()); |
1101 } | 1101 } |
1102 | 1102 |
1103 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 1103 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
1104 // We need this scope because we visit for register values. We have to | 1104 // We need this scope because we visit for register values. We have to |
1105 // maintain a execution result scope where registers can be allocated. | 1105 // maintain a execution result scope where registers can be allocated. |
1106 ZoneList<CaseClause*>* clauses = stmt->cases(); | 1106 ZoneList<CaseClause*>* clauses = stmt->cases(); |
1107 SwitchBuilder switch_builder(builder(), clauses->length()); | 1107 SwitchBuilder switch_builder(builder(), clauses->length()); |
1108 ControlScopeForBreakable scope(this, stmt, &switch_builder); | 1108 ControlScopeForBreakable scope(this, stmt, &switch_builder); |
1109 int default_index = -1; | 1109 int default_index = -1; |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1382 // Evaluate the try-block inside a control scope. This simulates a handler | 1382 // Evaluate the try-block inside a control scope. This simulates a handler |
1383 // that is intercepting 'throw' control commands. | 1383 // that is intercepting 'throw' control commands. |
1384 try_control_builder.BeginTry(context); | 1384 try_control_builder.BeginTry(context); |
1385 { | 1385 { |
1386 ControlScopeForTryCatch scope(this, &try_control_builder); | 1386 ControlScopeForTryCatch scope(this, &try_control_builder); |
1387 Visit(stmt->try_block()); | 1387 Visit(stmt->try_block()); |
1388 } | 1388 } |
1389 try_control_builder.EndTry(); | 1389 try_control_builder.EndTry(); |
1390 | 1390 |
1391 // Create a catch scope that binds the exception. | 1391 // Create a catch scope that binds the exception. |
1392 VisitNewLocalCatchContext(stmt->variable(), stmt->scope()); | 1392 BuildNewLocalCatchContext(stmt->variable(), stmt->scope()); |
1393 builder()->StoreAccumulatorInRegister(context); | 1393 builder()->StoreAccumulatorInRegister(context); |
1394 | 1394 |
1395 // If requested, clear message object as we enter the catch block. | 1395 // If requested, clear message object as we enter the catch block. |
1396 if (stmt->clear_pending_message()) { | 1396 if (stmt->clear_pending_message()) { |
1397 builder()->CallRuntime(Runtime::kInterpreterClearPendingMessage, no_reg, 0); | 1397 builder()->CallRuntime(Runtime::kInterpreterClearPendingMessage, no_reg, 0); |
1398 } | 1398 } |
1399 | 1399 |
1400 // Load the catch context into the accumulator. | 1400 // Load the catch context into the accumulator. |
1401 builder()->LoadAccumulatorWithRegister(context); | 1401 builder()->LoadAccumulatorWithRegister(context); |
1402 | 1402 |
(...skipping 1763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3166 builder()->Bind(&end_label); | 3166 builder()->Bind(&end_label); |
3167 } | 3167 } |
3168 execution_result()->SetResultInAccumulator(); | 3168 execution_result()->SetResultInAccumulator(); |
3169 } | 3169 } |
3170 } | 3170 } |
3171 | 3171 |
3172 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { | 3172 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { |
3173 Visit(expr->expression()); | 3173 Visit(expr->expression()); |
3174 } | 3174 } |
3175 | 3175 |
3176 void BytecodeGenerator::VisitNewLocalFunctionContext() { | 3176 void BytecodeGenerator::BuildNewLocalActivationContext() { |
3177 AccumulatorResultScope accumulator_execution_result(this); | 3177 AccumulatorResultScope accumulator_execution_result(this); |
3178 Scope* scope = this->scope(); | 3178 Scope* scope = this->scope(); |
3179 | 3179 |
3180 // Create the appropriate context. | 3180 // Create the appropriate context. |
3181 if (scope->is_script_scope()) { | 3181 if (scope->is_script_scope()) { |
3182 RegisterAllocationScope register_scope(this); | 3182 RegisterAllocationScope register_scope(this); |
3183 register_allocator()->PrepareForConsecutiveAllocations(2); | 3183 register_allocator()->PrepareForConsecutiveAllocations(2); |
3184 Register closure = register_allocator()->NextConsecutiveRegister(); | 3184 Register closure = register_allocator()->NextConsecutiveRegister(); |
3185 Register scope_info = register_allocator()->NextConsecutiveRegister(); | 3185 Register scope_info = register_allocator()->NextConsecutiveRegister(); |
3186 builder() | 3186 builder() |
(...skipping 20 matching lines...) Expand all Loading... |
3207 .LoadLiteral(scope->scope_info()) | 3207 .LoadLiteral(scope->scope_info()) |
3208 .StoreAccumulatorInRegister(scope_info) | 3208 .StoreAccumulatorInRegister(scope_info) |
3209 .CallRuntime(Runtime::kPushModuleContext, module, 3); | 3209 .CallRuntime(Runtime::kPushModuleContext, module, 3); |
3210 } else { | 3210 } else { |
3211 int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 3211 int slot_count = scope->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
3212 builder()->CreateFunctionContext(slot_count); | 3212 builder()->CreateFunctionContext(slot_count); |
3213 } | 3213 } |
3214 execution_result()->SetResultInAccumulator(); | 3214 execution_result()->SetResultInAccumulator(); |
3215 } | 3215 } |
3216 | 3216 |
3217 void BytecodeGenerator::VisitBuildLocalActivationContext() { | 3217 void BytecodeGenerator::BuildLocalActivationContextInitialization() { |
3218 DeclarationScope* scope = this->scope(); | 3218 DeclarationScope* scope = this->scope(); |
3219 | 3219 |
3220 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { | 3220 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { |
3221 Variable* variable = scope->receiver(); | 3221 Variable* variable = scope->receiver(); |
3222 Register receiver(builder()->Parameter(0)); | 3222 Register receiver(builder()->Parameter(0)); |
3223 // Context variable (at bottom of the context chain). | 3223 // Context variable (at bottom of the context chain). |
3224 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); | 3224 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); |
3225 builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot( | 3225 builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot( |
3226 execution_context()->reg(), variable->index()); | 3226 execution_context()->reg(), variable->index()); |
3227 } | 3227 } |
3228 | 3228 |
3229 // Copy parameters into context if necessary. | 3229 // Copy parameters into context if necessary. |
3230 int num_parameters = scope->num_parameters(); | 3230 int num_parameters = scope->num_parameters(); |
3231 for (int i = 0; i < num_parameters; i++) { | 3231 for (int i = 0; i < num_parameters; i++) { |
3232 Variable* variable = scope->parameter(i); | 3232 Variable* variable = scope->parameter(i); |
3233 if (!variable->IsContextSlot()) continue; | 3233 if (!variable->IsContextSlot()) continue; |
3234 | 3234 |
3235 // The parameter indices are shifted by 1 (receiver is variable | 3235 // The parameter indices are shifted by 1 (receiver is variable |
3236 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 3236 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
3237 Register parameter(builder()->Parameter(i + 1)); | 3237 Register parameter(builder()->Parameter(i + 1)); |
3238 // Context variable (at bottom of the context chain). | 3238 // Context variable (at bottom of the context chain). |
3239 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); | 3239 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); |
3240 builder()->LoadAccumulatorWithRegister(parameter) | 3240 builder()->LoadAccumulatorWithRegister(parameter) |
3241 .StoreContextSlot(execution_context()->reg(), variable->index()); | 3241 .StoreContextSlot(execution_context()->reg(), variable->index()); |
3242 } | 3242 } |
3243 } | 3243 } |
3244 | 3244 |
3245 void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) { | 3245 void BytecodeGenerator::BuildNewLocalBlockContext(Scope* scope) { |
3246 AccumulatorResultScope accumulator_execution_result(this); | 3246 AccumulatorResultScope accumulator_execution_result(this); |
3247 DCHECK(scope->is_block_scope()); | 3247 DCHECK(scope->is_block_scope()); |
3248 | 3248 |
3249 VisitFunctionClosureForContext(); | 3249 VisitFunctionClosureForContext(); |
3250 builder()->CreateBlockContext(scope->scope_info()); | 3250 builder()->CreateBlockContext(scope->scope_info()); |
3251 execution_result()->SetResultInAccumulator(); | 3251 execution_result()->SetResultInAccumulator(); |
3252 } | 3252 } |
3253 | 3253 |
3254 void BytecodeGenerator::VisitNewLocalWithContext(Scope* scope) { | 3254 void BytecodeGenerator::BuildNewLocalWithContext(Scope* scope) { |
3255 AccumulatorResultScope accumulator_execution_result(this); | 3255 AccumulatorResultScope accumulator_execution_result(this); |
3256 | 3256 |
3257 Register extension_object = register_allocator()->NewRegister(); | 3257 Register extension_object = register_allocator()->NewRegister(); |
3258 | 3258 |
3259 builder()->ConvertAccumulatorToObject(extension_object); | 3259 builder()->ConvertAccumulatorToObject(extension_object); |
3260 VisitFunctionClosureForContext(); | 3260 VisitFunctionClosureForContext(); |
3261 builder()->CreateWithContext(extension_object, scope->scope_info()); | 3261 builder()->CreateWithContext(extension_object, scope->scope_info()); |
3262 execution_result()->SetResultInAccumulator(); | 3262 execution_result()->SetResultInAccumulator(); |
3263 } | 3263 } |
3264 | 3264 |
3265 void BytecodeGenerator::VisitNewLocalCatchContext(Variable* variable, | 3265 void BytecodeGenerator::BuildNewLocalCatchContext(Variable* variable, |
3266 Scope* scope) { | 3266 Scope* scope) { |
3267 AccumulatorResultScope accumulator_execution_result(this); | 3267 AccumulatorResultScope accumulator_execution_result(this); |
3268 DCHECK(variable->IsContextSlot()); | 3268 DCHECK(variable->IsContextSlot()); |
3269 | 3269 |
3270 Register exception = register_allocator()->NewRegister(); | 3270 Register exception = register_allocator()->NewRegister(); |
3271 builder()->StoreAccumulatorInRegister(exception); | 3271 builder()->StoreAccumulatorInRegister(exception); |
3272 VisitFunctionClosureForContext(); | 3272 VisitFunctionClosureForContext(); |
3273 builder()->CreateCatchContext(exception, variable->name(), | 3273 builder()->CreateCatchContext(exception, variable->name(), |
3274 scope->scope_info()); | 3274 scope->scope_info()); |
3275 execution_result()->SetResultInAccumulator(); | 3275 execution_result()->SetResultInAccumulator(); |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3453 return execution_context()->scope()->language_mode(); | 3453 return execution_context()->scope()->language_mode(); |
3454 } | 3454 } |
3455 | 3455 |
3456 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3456 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
3457 return TypeFeedbackVector::GetIndex(slot); | 3457 return TypeFeedbackVector::GetIndex(slot); |
3458 } | 3458 } |
3459 | 3459 |
3460 } // namespace interpreter | 3460 } // namespace interpreter |
3461 } // namespace internal | 3461 } // namespace internal |
3462 } // namespace v8 | 3462 } // namespace v8 |
OLD | NEW |