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 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
563 info->scope()->num_stack_slots(), info->literal())), | 563 info->scope()->num_stack_slots(), info->literal())), |
564 info_(info), | 564 info_(info), |
565 scope_(info->scope()), | 565 scope_(info->scope()), |
566 globals_(0, info->zone()), | 566 globals_(0, info->zone()), |
567 execution_control_(nullptr), | 567 execution_control_(nullptr), |
568 execution_context_(nullptr), | 568 execution_context_(nullptr), |
569 execution_result_(nullptr), | 569 execution_result_(nullptr), |
570 register_allocator_(nullptr), | 570 register_allocator_(nullptr), |
571 generator_resume_points_(info->literal()->yield_count(), info->zone()), | 571 generator_resume_points_(info->literal()->yield_count(), info->zone()), |
572 generator_state_(), | 572 generator_state_(), |
573 generator_yields_seen_(0), | |
574 try_catch_nesting_level_(0), | 573 try_catch_nesting_level_(0), |
575 try_finally_nesting_level_(0) { | 574 try_finally_nesting_level_(0) { |
576 InitializeAstVisitor(isolate()); | 575 InitializeAstVisitor(isolate()); |
577 } | 576 } |
578 | 577 |
579 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode() { | 578 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode() { |
580 // Initialize the incoming context. | 579 // Initialize the incoming context. |
581 ContextScope incoming_context(this, scope(), false); | 580 ContextScope incoming_context(this, scope(), false); |
582 | 581 |
583 // Initialize control scope. | 582 // Initialize control scope. |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
660 | 659 |
661 void BytecodeGenerator::VisitIterationHeader(IterationStatement* stmt, | 660 void BytecodeGenerator::VisitIterationHeader(IterationStatement* stmt, |
662 LoopBuilder* loop_builder) { | 661 LoopBuilder* loop_builder) { |
663 // Recall that stmt->yield_count() is always zero inside ordinary | 662 // Recall that stmt->yield_count() is always zero inside ordinary |
664 // (i.e. non-generator) functions. | 663 // (i.e. non-generator) functions. |
665 | 664 |
666 // Collect all labels for generator resume points within the loop (if any) so | 665 // Collect all labels for generator resume points within the loop (if any) so |
667 // that they can be bound to the loop header below. Also create fresh labels | 666 // that they can be bound to the loop header below. Also create fresh labels |
668 // for these resume points, to be used inside the loop. | 667 // for these resume points, to be used inside the loop. |
669 ZoneVector<BytecodeLabel> resume_points_in_loop(zone()); | 668 ZoneVector<BytecodeLabel> resume_points_in_loop(zone()); |
670 for (size_t id = generator_yields_seen_; | 669 size_t first = stmt->first_yield_id(); |
Jarin
2016/04/28 16:31:18
I am mildly surprised this works is not first_yiel
neis
2016/04/29 07:52:24
signed to unsigned is always "fine" as far as I kn
| |
671 id < generator_yields_seen_ + stmt->yield_count(); id++) { | 670 for (size_t id = first; id < first + stmt->yield_count(); id++) { |
672 DCHECK(0 <= id && id < generator_resume_points_.size()); | 671 DCHECK(0 <= id && id < generator_resume_points_.size()); |
673 auto& label = generator_resume_points_[id]; | 672 auto& label = generator_resume_points_[id]; |
674 resume_points_in_loop.push_back(label); | 673 resume_points_in_loop.push_back(label); |
675 generator_resume_points_[id] = BytecodeLabel(); | 674 generator_resume_points_[id] = BytecodeLabel(); |
676 } | 675 } |
677 | 676 |
678 loop_builder->LoopHeader(&resume_points_in_loop); | 677 loop_builder->LoopHeader(&resume_points_in_loop); |
679 | 678 |
680 if (stmt->yield_count() > 0) { | 679 if (stmt->yield_count() > 0) { |
681 // If we are not resuming, fall through to loop body. | 680 // If we are not resuming, fall through to loop body. |
682 // If we are resuming, perform state dispatch. | 681 // If we are resuming, perform state dispatch. |
683 BytecodeLabel not_resuming; | 682 BytecodeLabel not_resuming; |
684 builder() | 683 builder() |
685 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) | 684 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) |
686 .CompareOperation(Token::Value::EQ, generator_state_) | 685 .CompareOperation(Token::Value::EQ, generator_state_) |
687 .JumpIfTrue(¬_resuming); | 686 .JumpIfTrue(¬_resuming); |
688 BuildIndexedJump(generator_state_, generator_yields_seen_, | 687 BuildIndexedJump( |
689 stmt->yield_count(), generator_resume_points_); | 688 generator_state_, first, stmt->yield_count(), generator_resume_points_); |
690 builder()->Bind(¬_resuming); | 689 builder()->Bind(¬_resuming); |
691 } | 690 } |
692 } | 691 } |
693 | 692 |
694 void BytecodeGenerator::VisitGeneratorPrologue() { | 693 void BytecodeGenerator::VisitGeneratorPrologue() { |
695 // The generator resume trampoline abuses the new.target register both to | 694 // The generator resume trampoline abuses the new.target register both to |
696 // indicate that this is a resume call and to pass in the generator object. | 695 // indicate that this is a resume call and to pass in the generator object. |
697 // In ordinary calls, new.target is always undefined because generator | 696 // In ordinary calls, new.target is always undefined because generator |
698 // functions are non-constructable. | 697 // functions are non-constructable. |
699 Register generator_object = Register::new_target(); | 698 Register generator_object = Register::new_target(); |
(...skipping 1559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2259 case KEYED_SUPER_PROPERTY: { | 2258 case KEYED_SUPER_PROPERTY: { |
2260 builder()->StoreAccumulatorInRegister(value); | 2259 builder()->StoreAccumulatorInRegister(value); |
2261 BuildKeyedSuperPropertyStore(object, home_object, key, value); | 2260 BuildKeyedSuperPropertyStore(object, home_object, key, value); |
2262 break; | 2261 break; |
2263 } | 2262 } |
2264 } | 2263 } |
2265 execution_result()->SetResultInAccumulator(); | 2264 execution_result()->SetResultInAccumulator(); |
2266 } | 2265 } |
2267 | 2266 |
2268 void BytecodeGenerator::VisitYield(Yield* expr) { | 2267 void BytecodeGenerator::VisitYield(Yield* expr) { |
2269 size_t id = generator_yields_seen_++; | |
2270 | |
2271 builder()->SetExpressionPosition(expr); | 2268 builder()->SetExpressionPosition(expr); |
2272 Register value = VisitForRegisterValue(expr->expression()); | 2269 Register value = VisitForRegisterValue(expr->expression()); |
2273 | 2270 |
2274 Register generator = VisitForRegisterValue(expr->generator_object()); | 2271 Register generator = VisitForRegisterValue(expr->generator_object()); |
2275 | 2272 |
2276 // Save context, registers, and state. Then return. | 2273 // Save context, registers, and state. Then return. |
2277 builder() | 2274 builder() |
2278 ->LoadLiteral(Smi::FromInt(static_cast<int>(id))) | 2275 ->LoadLiteral(Smi::FromInt(expr->id())) |
2279 .SuspendGenerator(generator) | 2276 .SuspendGenerator(generator) |
2280 .LoadAccumulatorWithRegister(value) | 2277 .LoadAccumulatorWithRegister(value) |
2281 .Return(); // Hard return (ignore any finally blocks). | 2278 .Return(); // Hard return (ignore any finally blocks). |
2282 | 2279 |
2283 builder()->Bind(&(generator_resume_points_[id])); | 2280 builder()->Bind(&(generator_resume_points_[expr->id()])); |
2284 // Upon resume, we continue here. | 2281 // Upon resume, we continue here. |
2285 | 2282 |
2286 { | 2283 { |
2287 RegisterAllocationScope register_scope(this); | 2284 RegisterAllocationScope register_scope(this); |
2288 | 2285 |
2289 // Update state to indicate that we have finished resuming. Loop headers | 2286 // Update state to indicate that we have finished resuming. Loop headers |
2290 // rely on this. | 2287 // rely on this. |
2291 builder() | 2288 builder() |
2292 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) | 2289 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) |
2293 .StoreAccumulatorInRegister(generator_state_); | 2290 .StoreAccumulatorInRegister(generator_state_); |
(...skipping 977 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3271 } | 3268 } |
3272 | 3269 |
3273 | 3270 |
3274 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3271 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
3275 return info()->shared_info()->feedback_vector()->GetIndex(slot); | 3272 return info()->shared_info()->feedback_vector()->GetIndex(slot); |
3276 } | 3273 } |
3277 | 3274 |
3278 } // namespace interpreter | 3275 } // namespace interpreter |
3279 } // namespace internal | 3276 } // namespace internal |
3280 } // namespace v8 | 3277 } // namespace v8 |
OLD | NEW |