Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: src/interpreter/bytecode-generator.cc

Issue 1901713003: [generators] Perform state dispatch in loop header. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/compiler.h" 8 #include "src/compiler.h"
9 #include "src/interpreter/bytecode-register-allocator.h" 9 #include "src/interpreter/bytecode-register-allocator.h"
10 #include "src/interpreter/control-flow-builders.h" 10 #include "src/interpreter/control-flow-builders.h"
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 : isolate_(isolate), 558 : isolate_(isolate),
559 zone_(zone), 559 zone_(zone),
560 builder_(nullptr), 560 builder_(nullptr),
561 info_(nullptr), 561 info_(nullptr),
562 scope_(nullptr), 562 scope_(nullptr),
563 globals_(0, zone), 563 globals_(0, zone),
564 execution_control_(nullptr), 564 execution_control_(nullptr),
565 execution_context_(nullptr), 565 execution_context_(nullptr),
566 execution_result_(nullptr), 566 execution_result_(nullptr),
567 register_allocator_(nullptr), 567 register_allocator_(nullptr),
568 generator_resume_points_(0, zone),
569 try_catch_nesting_level_(0), 568 try_catch_nesting_level_(0),
570 try_finally_nesting_level_(0), 569 try_finally_nesting_level_(0) {
571 generator_yields_seen_(0) {
572 InitializeAstVisitor(isolate); 570 InitializeAstVisitor(isolate);
573 } 571 }
574 572
575 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { 573 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
576 set_info(info); 574 set_info(info);
577 set_scope(info->scope()); 575 set_scope(info->scope());
578 576
579 // Initialize bytecode array builder. 577 // Initialize bytecode array builder.
580 set_builder(new (zone()) BytecodeArrayBuilder( 578 set_builder(new (zone()) BytecodeArrayBuilder(
581 isolate(), zone(), info->num_parameters_including_this(), 579 isolate(), zone(), info->num_parameters_including_this(),
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 VisitDeclarations(scope()->declarations()); 632 VisitDeclarations(scope()->declarations());
635 633
636 // Perform a stack-check before the body. 634 // Perform a stack-check before the body.
637 builder()->StackCheck(); 635 builder()->StackCheck();
638 636
639 // Visit statements in the function body. 637 // Visit statements in the function body.
640 VisitStatements(info()->literal()->body()); 638 VisitStatements(info()->literal()->body());
641 } 639 }
642 640
643 void BytecodeGenerator::VisitGeneratorPrologue() { 641 void BytecodeGenerator::VisitGeneratorPrologue() {
644 generator_resume_points_.clear(); 642 auto& resume_points = builder()->generator_resume_points;
645 generator_resume_points_.resize(info()->literal()->yield_count()); 643 resume_points.clear();
644 resume_points.resize(info()->literal()->yield_count());
646 645
647 BytecodeLabel regular_call; 646 BytecodeLabel regular_call;
648 builder() 647 builder()
649 ->LoadAccumulatorWithRegister(Register::new_target()) 648 ->LoadAccumulatorWithRegister(Register::new_target())
650 .JumpIfUndefined(&regular_call); 649 .JumpIfUndefined(&regular_call);
651 650
652 // This is a resume call. Restore registers and perform state dispatch. 651 // This is a resume call. Restore registers and perform state dispatch.
653 // (The current context has already been restored by the trampoline.) 652 // (The current context has already been restored by the trampoline.)
654 { 653 Register state = Register::new_target(); // HACK
rmcilroy 2016/04/19 09:30:03 Could you allocate an additional local for this pu
neis 2016/04/19 11:02:15 I think I prefer having a dedicated register rathe
655 RegisterAllocationScope register_scope(this); 654 builder()
656 Register state = register_allocator()->NewRegister(); 655 ->CallRuntime(Runtime::kResumeIgnitionGenerator, Register::new_target(),
657 builder() 656 1)
658 ->CallRuntime(Runtime::kResumeIgnitionGenerator, Register::new_target(), 657 .StoreAccumulatorInRegister(state)
659 1) 658 .IndexedJump(state, 0, resume_points.size(), resume_points);
660 .StoreAccumulatorInRegister(state);
661
662 // TODO(neis): Optimize this by using a proper jump table.
663 for (size_t i = 0; i < generator_resume_points_.size(); ++i) {
664 builder()
665 ->LoadLiteral(Smi::FromInt(static_cast<int>(i)))
666 .CompareOperation(Token::Value::EQ_STRICT, state)
667 .JumpIfTrue(&(generator_resume_points_[i]));
668 }
669 builder()->Illegal(); // Should never get here.
670 }
671 659
672 builder()->Bind(&regular_call); 660 builder()->Bind(&regular_call);
673 // This is a regular call. Fall through to the ordinary function prologue, 661 // This is a regular call. Fall through to the ordinary function prologue,
674 // after which we will run into the generator object creation and the initial 662 // after which we will run into the generator object creation and the initial
675 // yield (both inserted by the parser). 663 // yield (both inserted by the parser).
676 } 664 }
677 665
678 void BytecodeGenerator::VisitBlock(Block* stmt) { 666 void BytecodeGenerator::VisitBlock(Block* stmt) {
679 // Visit declarations and statements. 667 // Visit declarations and statements.
680 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) { 668 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) {
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
993 } 981 }
994 982
995 void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt, 983 void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt,
996 LoopBuilder* loop_builder) { 984 LoopBuilder* loop_builder) {
997 ControlScopeForIteration execution_control(this, stmt, loop_builder); 985 ControlScopeForIteration execution_control(this, stmt, loop_builder);
998 builder()->StackCheck(); 986 builder()->StackCheck();
999 Visit(stmt->body()); 987 Visit(stmt->body());
1000 } 988 }
1001 989
1002 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { 990 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
1003 LoopBuilder loop_builder(builder()); 991 LoopBuilder loop_builder(builder(), stmt->yield_count());
1004 loop_builder.LoopHeader(); 992 loop_builder.LoopHeader();
1005 if (stmt->cond()->ToBooleanIsFalse()) { 993 if (stmt->cond()->ToBooleanIsFalse()) {
1006 VisitIterationBody(stmt, &loop_builder); 994 VisitIterationBody(stmt, &loop_builder);
1007 loop_builder.Condition(); 995 loop_builder.Condition();
1008 } else if (stmt->cond()->ToBooleanIsTrue()) { 996 } else if (stmt->cond()->ToBooleanIsTrue()) {
1009 loop_builder.Condition(); 997 loop_builder.Condition();
1010 VisitIterationBody(stmt, &loop_builder); 998 VisitIterationBody(stmt, &loop_builder);
1011 loop_builder.JumpToHeader(); 999 loop_builder.JumpToHeader();
1012 } else { 1000 } else {
1013 VisitIterationBody(stmt, &loop_builder); 1001 VisitIterationBody(stmt, &loop_builder);
1014 loop_builder.Condition(); 1002 loop_builder.Condition();
1015 builder()->SetExpressionAsStatementPosition(stmt->cond()); 1003 builder()->SetExpressionAsStatementPosition(stmt->cond());
1016 VisitForAccumulatorValue(stmt->cond()); 1004 VisitForAccumulatorValue(stmt->cond());
1017 loop_builder.JumpToHeaderIfTrue(); 1005 loop_builder.JumpToHeaderIfTrue();
1018 } 1006 }
1019 loop_builder.EndLoop(); 1007 loop_builder.EndLoop();
1020 } 1008 }
1021 1009
1022 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { 1010 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
1023 if (stmt->cond()->ToBooleanIsFalse()) { 1011 if (stmt->cond()->ToBooleanIsFalse()) {
1024 // If the condition is false there is no need to generate the loop. 1012 // If the condition is false there is no need to generate the loop.
1025 return; 1013 return;
1026 } 1014 }
1027 1015
1028 LoopBuilder loop_builder(builder()); 1016 LoopBuilder loop_builder(builder(), stmt->yield_count());
1029 loop_builder.LoopHeader(); 1017 loop_builder.LoopHeader();
1030 loop_builder.Condition(); 1018 loop_builder.Condition();
1031 if (!stmt->cond()->ToBooleanIsTrue()) { 1019 if (!stmt->cond()->ToBooleanIsTrue()) {
1032 builder()->SetExpressionAsStatementPosition(stmt->cond()); 1020 builder()->SetExpressionAsStatementPosition(stmt->cond());
1033 VisitForAccumulatorValue(stmt->cond()); 1021 VisitForAccumulatorValue(stmt->cond());
1034 loop_builder.BreakIfFalse(); 1022 loop_builder.BreakIfFalse();
1035 } 1023 }
1036 VisitIterationBody(stmt, &loop_builder); 1024 VisitIterationBody(stmt, &loop_builder);
1037 loop_builder.JumpToHeader(); 1025 loop_builder.JumpToHeader();
1038 loop_builder.EndLoop(); 1026 loop_builder.EndLoop();
1039 } 1027 }
1040 1028
1041 1029
1042 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { 1030 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
1043 if (stmt->init() != nullptr) { 1031 if (stmt->init() != nullptr) {
1044 Visit(stmt->init()); 1032 Visit(stmt->init());
1045 } 1033 }
1046 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { 1034 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) {
1047 // If the condition is known to be false there is no need to generate 1035 // If the condition is known to be false there is no need to generate
1048 // body, next or condition blocks. Init block should be generated. 1036 // body, next or condition blocks. Init block should be generated.
1049 return; 1037 return;
1050 } 1038 }
1051 1039
1052 LoopBuilder loop_builder(builder()); 1040 LoopBuilder loop_builder(builder(), stmt->yield_count());
1053 loop_builder.LoopHeader(); 1041 loop_builder.LoopHeader();
1054 loop_builder.Condition(); 1042 loop_builder.Condition();
1055 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { 1043 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) {
1056 builder()->SetExpressionAsStatementPosition(stmt->cond()); 1044 builder()->SetExpressionAsStatementPosition(stmt->cond());
1057 VisitForAccumulatorValue(stmt->cond()); 1045 VisitForAccumulatorValue(stmt->cond());
1058 loop_builder.BreakIfFalse(); 1046 loop_builder.BreakIfFalse();
1059 } 1047 }
1060 VisitIterationBody(stmt, &loop_builder); 1048 VisitIterationBody(stmt, &loop_builder);
1061 if (stmt->next() != nullptr) { 1049 if (stmt->next() != nullptr) {
1062 loop_builder.Next(); 1050 loop_builder.Next();
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1142 } 1130 }
1143 1131
1144 1132
1145 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { 1133 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
1146 if (stmt->subject()->IsNullLiteral() || 1134 if (stmt->subject()->IsNullLiteral() ||
1147 stmt->subject()->IsUndefinedLiteral()) { 1135 stmt->subject()->IsUndefinedLiteral()) {
1148 // ForIn generates lots of code, skip if it wouldn't produce any effects. 1136 // ForIn generates lots of code, skip if it wouldn't produce any effects.
1149 return; 1137 return;
1150 } 1138 }
1151 1139
1152 LoopBuilder loop_builder(builder()); 1140 LoopBuilder loop_builder(builder(), stmt->yield_count());
1153 BytecodeLabel subject_null_label, subject_undefined_label; 1141 BytecodeLabel subject_null_label, subject_undefined_label;
1154 1142
1155 // Prepare the state for executing ForIn. 1143 // Prepare the state for executing ForIn.
1156 builder()->SetExpressionAsStatementPosition(stmt->subject()); 1144 builder()->SetExpressionAsStatementPosition(stmt->subject());
1157 VisitForAccumulatorValue(stmt->subject()); 1145 VisitForAccumulatorValue(stmt->subject());
1158 builder()->JumpIfUndefined(&subject_undefined_label); 1146 builder()->JumpIfUndefined(&subject_undefined_label);
1159 builder()->JumpIfNull(&subject_null_label); 1147 builder()->JumpIfNull(&subject_null_label);
1160 Register receiver = register_allocator()->NewRegister(); 1148 Register receiver = register_allocator()->NewRegister();
1161 builder()->CastAccumulatorToJSObject(); 1149 builder()->CastAccumulatorToJSObject();
1162 builder()->StoreAccumulatorInRegister(receiver); 1150 builder()->StoreAccumulatorInRegister(receiver);
(...skipping 27 matching lines...) Expand all
1190 builder()->ForInStep(index); 1178 builder()->ForInStep(index);
1191 builder()->StoreAccumulatorInRegister(index); 1179 builder()->StoreAccumulatorInRegister(index);
1192 loop_builder.JumpToHeader(); 1180 loop_builder.JumpToHeader();
1193 loop_builder.EndLoop(); 1181 loop_builder.EndLoop();
1194 builder()->Bind(&subject_null_label); 1182 builder()->Bind(&subject_null_label);
1195 builder()->Bind(&subject_undefined_label); 1183 builder()->Bind(&subject_undefined_label);
1196 } 1184 }
1197 1185
1198 1186
1199 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { 1187 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
1200 LoopBuilder loop_builder(builder()); 1188 LoopBuilder loop_builder(builder(), stmt->yield_count());
1201 ControlScopeForIteration control_scope(this, stmt, &loop_builder); 1189 ControlScopeForIteration control_scope(this, stmt, &loop_builder);
1202 1190
1203 VisitForEffect(stmt->assign_iterator()); 1191 VisitForEffect(stmt->assign_iterator());
1204 1192
1205 loop_builder.LoopHeader(); 1193 loop_builder.LoopHeader();
1206 loop_builder.Next(); 1194 loop_builder.Next();
1207 builder()->SetExpressionAsStatementPosition(stmt->next_result()); 1195 builder()->SetExpressionAsStatementPosition(stmt->next_result());
1208 VisitForEffect(stmt->next_result()); 1196 VisitForEffect(stmt->next_result());
1209 VisitForAccumulatorValue(stmt->result_done()); 1197 VisitForAccumulatorValue(stmt->result_done());
1210 loop_builder.BreakIfTrue(); 1198 loop_builder.BreakIfTrue();
(...skipping 1052 matching lines...) Expand 10 before | Expand all | Expand 10 after
2263 case KEYED_SUPER_PROPERTY: { 2251 case KEYED_SUPER_PROPERTY: {
2264 builder()->StoreAccumulatorInRegister(value); 2252 builder()->StoreAccumulatorInRegister(value);
2265 BuildKeyedSuperPropertyStore(object, home_object, key, value); 2253 BuildKeyedSuperPropertyStore(object, home_object, key, value);
2266 break; 2254 break;
2267 } 2255 }
2268 } 2256 }
2269 execution_result()->SetResultInAccumulator(); 2257 execution_result()->SetResultInAccumulator();
2270 } 2258 }
2271 2259
2272 void BytecodeGenerator::VisitYield(Yield* expr) { 2260 void BytecodeGenerator::VisitYield(Yield* expr) {
2273 int id = generator_yields_seen_++; 2261 int id = builder()->incr_generator_yields_seen();
2274 2262
2275 builder()->SetExpressionPosition(expr); 2263 builder()->SetExpressionPosition(expr);
2276 Register value = VisitForRegisterValue(expr->expression()); 2264 Register value = VisitForRegisterValue(expr->expression());
2277 2265
2278 register_allocator()->PrepareForConsecutiveAllocations(2); 2266 register_allocator()->PrepareForConsecutiveAllocations(2);
2279 Register generator = register_allocator()->NextConsecutiveRegister(); 2267 Register generator = register_allocator()->NextConsecutiveRegister();
2280 Register state = register_allocator()->NextConsecutiveRegister(); 2268 Register state = register_allocator()->NextConsecutiveRegister();
2281 2269
2282 // Save context, registers, and state. Then return. 2270 // Save context, registers, and state. Then return.
2283 VisitForRegisterValue(expr->generator_object(), generator); 2271 VisitForRegisterValue(expr->generator_object(), generator);
2284 builder() 2272 builder()
2285 ->LoadLiteral(Smi::FromInt(id)) 2273 ->LoadLiteral(Smi::FromInt(id))
2286 .StoreAccumulatorInRegister(state) 2274 .StoreAccumulatorInRegister(state)
2287 .CallRuntime(Runtime::kSuspendIgnitionGenerator, generator, 2) 2275 .CallRuntime(Runtime::kSuspendIgnitionGenerator, generator, 2)
2288 .LoadAccumulatorWithRegister(value) 2276 .LoadAccumulatorWithRegister(value)
2289 .Return(); // Hard return (ignore any finally blocks). 2277 .Return(); // Hard return (ignore any finally blocks).
2290 2278
2291 builder()->Bind(&(generator_resume_points_[id])); 2279 builder()->Bind(&(builder()->generator_resume_points[id]));
2292 // Upon resume, we continue here. 2280 // Upon resume, we continue here.
2293 2281
2294 { 2282 {
2295 RegisterAllocationScope register_scope(this); 2283 RegisterAllocationScope register_scope(this);
2296 2284
2297 Register input = register_allocator()->NewRegister(); 2285 Register input = register_allocator()->NewRegister();
2298 builder() 2286 builder()
2299 ->CallRuntime(Runtime::kGeneratorGetInput, generator, 1) 2287 ->CallRuntime(Runtime::kGeneratorGetInput, generator, 1)
2300 .StoreAccumulatorInRegister(input); 2288 .StoreAccumulatorInRegister(input);
2301 2289
(...skipping 972 matching lines...) Expand 10 before | Expand all | Expand 10 after
3274 } 3262 }
3275 3263
3276 3264
3277 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 3265 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
3278 return info()->shared_info()->feedback_vector()->GetIndex(slot); 3266 return info()->shared_info()->feedback_vector()->GetIndex(slot);
3279 } 3267 }
3280 3268
3281 } // namespace interpreter 3269 } // namespace interpreter
3282 } // namespace internal 3270 } // namespace internal
3283 } // namespace v8 3271 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698