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/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/compiler.h" | 9 #include "src/compiler.h" |
10 #include "src/interpreter/bytecode-register-allocator.h" | 10 #include "src/interpreter/bytecode-register-allocator.h" |
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
564 info->scope()->num_stack_slots(), info->literal())), | 564 info->scope()->num_stack_slots(), info->literal())), |
565 info_(info), | 565 info_(info), |
566 scope_(info->scope()), | 566 scope_(info->scope()), |
567 globals_(0, info->zone()), | 567 globals_(0, info->zone()), |
568 execution_control_(nullptr), | 568 execution_control_(nullptr), |
569 execution_context_(nullptr), | 569 execution_context_(nullptr), |
570 execution_result_(nullptr), | 570 execution_result_(nullptr), |
571 register_allocator_(nullptr), | 571 register_allocator_(nullptr), |
572 generator_resume_points_(info->literal()->yield_count(), info->zone()), | 572 generator_resume_points_(info->literal()->yield_count(), info->zone()), |
573 generator_state_(), | 573 generator_state_(), |
574 generator_yields_seen_(0), | |
575 try_catch_nesting_level_(0), | 574 try_catch_nesting_level_(0), |
576 try_finally_nesting_level_(0) { | 575 try_finally_nesting_level_(0) { |
577 InitializeAstVisitor(isolate()); | 576 InitializeAstVisitor(isolate()); |
578 } | 577 } |
579 | 578 |
580 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode() { | 579 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode() { |
581 // Initialize the incoming context. | 580 // Initialize the incoming context. |
582 ContextScope incoming_context(this, scope(), false); | 581 ContextScope incoming_context(this, scope(), false); |
583 | 582 |
584 // Initialize control scope. | 583 // Initialize control scope. |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
661 | 660 |
662 void BytecodeGenerator::VisitIterationHeader(IterationStatement* stmt, | 661 void BytecodeGenerator::VisitIterationHeader(IterationStatement* stmt, |
663 LoopBuilder* loop_builder) { | 662 LoopBuilder* loop_builder) { |
664 // Recall that stmt->yield_count() is always zero inside ordinary | 663 // Recall that stmt->yield_count() is always zero inside ordinary |
665 // (i.e. non-generator) functions. | 664 // (i.e. non-generator) functions. |
666 | 665 |
667 // Collect all labels for generator resume points within the loop (if any) so | 666 // Collect all labels for generator resume points within the loop (if any) so |
668 // that they can be bound to the loop header below. Also create fresh labels | 667 // that they can be bound to the loop header below. Also create fresh labels |
669 // for these resume points, to be used inside the loop. | 668 // for these resume points, to be used inside the loop. |
670 ZoneVector<BytecodeLabel> resume_points_in_loop(zone()); | 669 ZoneVector<BytecodeLabel> resume_points_in_loop(zone()); |
671 for (size_t id = generator_yields_seen_; | 670 size_t first_yield = stmt->first_yield_id(); |
672 id < generator_yields_seen_ + stmt->yield_count(); id++) { | 671 for (size_t id = first_yield; id < first_yield + stmt->yield_count(); id++) { |
673 DCHECK(0 <= id && id < generator_resume_points_.size()); | 672 DCHECK(0 <= id && id < generator_resume_points_.size()); |
674 auto& label = generator_resume_points_[id]; | 673 auto& label = generator_resume_points_[id]; |
675 resume_points_in_loop.push_back(label); | 674 resume_points_in_loop.push_back(label); |
676 generator_resume_points_[id] = BytecodeLabel(); | 675 generator_resume_points_[id] = BytecodeLabel(); |
677 } | 676 } |
678 | 677 |
679 loop_builder->LoopHeader(&resume_points_in_loop); | 678 loop_builder->LoopHeader(&resume_points_in_loop); |
680 | 679 |
681 if (stmt->yield_count() > 0) { | 680 if (stmt->yield_count() > 0) { |
682 // If we are not resuming, fall through to loop body. | 681 // If we are not resuming, fall through to loop body. |
683 // If we are resuming, perform state dispatch. | 682 // If we are resuming, perform state dispatch. |
684 BytecodeLabel not_resuming; | 683 BytecodeLabel not_resuming; |
685 builder() | 684 builder() |
686 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) | 685 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) |
687 .CompareOperation(Token::Value::EQ, generator_state_) | 686 .CompareOperation(Token::Value::EQ, generator_state_) |
688 .JumpIfTrue(¬_resuming); | 687 .JumpIfTrue(¬_resuming); |
689 BuildIndexedJump(generator_state_, generator_yields_seen_, | 688 BuildIndexedJump(generator_state_, first_yield, |
690 stmt->yield_count(), generator_resume_points_); | 689 stmt->yield_count(), generator_resume_points_); |
691 builder()->Bind(¬_resuming); | 690 builder()->Bind(¬_resuming); |
692 } | 691 } |
693 } | 692 } |
694 | 693 |
695 void BytecodeGenerator::VisitGeneratorPrologue() { | 694 void BytecodeGenerator::VisitGeneratorPrologue() { |
696 // The generator resume trampoline abuses the new.target register both to | 695 // The generator resume trampoline abuses the new.target register both to |
697 // indicate that this is a resume call and to pass in the generator object. | 696 // indicate that this is a resume call and to pass in the generator object. |
698 // In ordinary calls, new.target is always undefined because generator | 697 // In ordinary calls, new.target is always undefined because generator |
699 // functions are non-constructable. | 698 // functions are non-constructable. |
700 Register generator_object = Register::new_target(); | 699 Register generator_object = Register::new_target(); |
(...skipping 1570 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2271 case KEYED_SUPER_PROPERTY: { | 2270 case KEYED_SUPER_PROPERTY: { |
2272 builder()->StoreAccumulatorInRegister(value); | 2271 builder()->StoreAccumulatorInRegister(value); |
2273 BuildKeyedSuperPropertyStore(object, home_object, key, value); | 2272 BuildKeyedSuperPropertyStore(object, home_object, key, value); |
2274 break; | 2273 break; |
2275 } | 2274 } |
2276 } | 2275 } |
2277 execution_result()->SetResultInAccumulator(); | 2276 execution_result()->SetResultInAccumulator(); |
2278 } | 2277 } |
2279 | 2278 |
2280 void BytecodeGenerator::VisitYield(Yield* expr) { | 2279 void BytecodeGenerator::VisitYield(Yield* expr) { |
2281 size_t id = generator_yields_seen_++; | |
2282 | |
2283 builder()->SetExpressionPosition(expr); | 2280 builder()->SetExpressionPosition(expr); |
2284 Register value = VisitForRegisterValue(expr->expression()); | 2281 Register value = VisitForRegisterValue(expr->expression()); |
2285 | 2282 |
2286 Register generator = VisitForRegisterValue(expr->generator_object()); | 2283 Register generator = VisitForRegisterValue(expr->generator_object()); |
2287 | 2284 |
2288 // Save context, registers, and state. Then return. | 2285 // Save context, registers, and state. Then return. |
2289 builder() | 2286 builder() |
2290 ->LoadLiteral(Smi::FromInt(static_cast<int>(id))) | 2287 ->LoadLiteral(Smi::FromInt(expr->yield_id())) |
2291 .SuspendGenerator(generator) | 2288 .SuspendGenerator(generator) |
2292 .LoadAccumulatorWithRegister(value) | 2289 .LoadAccumulatorWithRegister(value) |
2293 .Return(); // Hard return (ignore any finally blocks). | 2290 .Return(); // Hard return (ignore any finally blocks). |
2294 | 2291 |
2295 builder()->Bind(&(generator_resume_points_[id])); | 2292 builder()->Bind(&(generator_resume_points_[expr->yield_id()])); |
2296 // Upon resume, we continue here. | 2293 // Upon resume, we continue here. |
2297 | 2294 |
2298 { | 2295 { |
2299 RegisterAllocationScope register_scope(this); | 2296 RegisterAllocationScope register_scope(this); |
2300 | 2297 |
2301 // Update state to indicate that we have finished resuming. Loop headers | 2298 // Update state to indicate that we have finished resuming. Loop headers |
2302 // rely on this. | 2299 // rely on this. |
2303 builder() | 2300 builder() |
2304 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) | 2301 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) |
2305 .StoreAccumulatorInRegister(generator_state_); | 2302 .StoreAccumulatorInRegister(generator_state_); |
(...skipping 977 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3283 } | 3280 } |
3284 | 3281 |
3285 | 3282 |
3286 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3283 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
3287 return info()->shared_info()->feedback_vector()->GetIndex(slot); | 3284 return info()->shared_info()->feedback_vector()->GetIndex(slot); |
3288 } | 3285 } |
3289 | 3286 |
3290 } // namespace interpreter | 3287 } // namespace interpreter |
3291 } // namespace internal | 3288 } // namespace internal |
3292 } // namespace v8 | 3289 } // namespace v8 |
OLD | NEW |