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/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 Loading... | |
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 Loading... | |
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(®ular_call); | 649 .JumpIfUndefined(®ular_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(®ular_call); | 660 builder()->Bind(®ular_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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |