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