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/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 |