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/compile-time-value.h" | 7 #include "src/ast/compile-time-value.h" |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/builtins/builtins-constructor.h" | 9 #include "src/builtins/builtins-constructor.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 192 builder()->LoadAccumulatorWithRegister(result_register_); | 192 builder()->LoadAccumulatorWithRegister(result_register_); |
| 193 execution_control()->PerformCommand(entry.command, entry.statement); | 193 execution_control()->PerformCommand(entry.command, entry.statement); |
| 194 } | 194 } |
| 195 dispatch.SetCaseTarget(static_cast<int>(deferred_.size())); | 195 dispatch.SetCaseTarget(static_cast<int>(deferred_.size())); |
| 196 } | 196 } |
| 197 | 197 |
| 198 BytecodeArrayBuilder* builder() { return generator_->builder(); } | 198 BytecodeArrayBuilder* builder() { return generator_->builder(); } |
| 199 ControlScope* execution_control() { return generator_->execution_control(); } | 199 ControlScope* execution_control() { return generator_->execution_control(); } |
| 200 | 200 |
| 201 private: | 201 private: |
| 202 BytecodeGenerator* generator_; | 202 BytecodeGenerator* generator_ = nullptr; |
|
rmcilroy
2017/02/07 17:24:41
Why was this change made? The constructor should s
| |
| 203 ZoneVector<Entry> deferred_; | 203 ZoneVector<Entry> deferred_; |
| 204 Register token_register_; | 204 Register token_register_; |
| 205 Register result_register_; | 205 Register result_register_; |
| 206 }; | 206 }; |
| 207 | 207 |
| 208 // Scoped class for dealing with control flow reaching the function level. | 208 // Scoped class for dealing with control flow reaching the function level. |
| 209 class BytecodeGenerator::ControlScopeForTopLevel final | 209 class BytecodeGenerator::ControlScopeForTopLevel final |
| 210 : public BytecodeGenerator::ControlScope { | 210 : public BytecodeGenerator::ControlScope { |
| 211 public: | 211 public: |
| 212 explicit ControlScopeForTopLevel(BytecodeGenerator* generator) | 212 explicit ControlScopeForTopLevel(BytecodeGenerator* generator) |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 573 Handle<String> name; | 573 Handle<String> name; |
| 574 FeedbackVectorSlot slot; | 574 FeedbackVectorSlot slot; |
| 575 FeedbackVectorSlot literal_slot; | 575 FeedbackVectorSlot literal_slot; |
| 576 FunctionLiteral* func; | 576 FunctionLiteral* func; |
| 577 }; | 577 }; |
| 578 ZoneVector<Declaration> declarations_; | 578 ZoneVector<Declaration> declarations_; |
| 579 size_t constant_pool_entry_; | 579 size_t constant_pool_entry_; |
| 580 bool has_constant_pool_entry_; | 580 bool has_constant_pool_entry_; |
| 581 }; | 581 }; |
| 582 | 582 |
| 583 template <class T> | |
| 584 class TryBlockBuilder; | |
| 585 class BytecodeGenerator::SimpleTryCatchBuilder : private TryCatchBuilder { | |
| 586 public: | |
| 587 typedef ControlScopeForTryCatch TryControlScope; | |
| 588 | |
| 589 explicit SimpleTryCatchBuilder(BytecodeGenerator* generator, | |
| 590 HandlerTable::CatchPrediction catch_prediction) | |
| 591 : TryCatchBuilder(generator->builder(), catch_prediction), | |
| 592 generator_(generator) {} | |
| 593 | |
| 594 Register context() const { | |
| 595 DCHECK(context_.is_valid()); | |
| 596 return context_; | |
| 597 } | |
| 598 | |
| 599 private: | |
| 600 friend class TryBlockBuilder<SimpleTryCatchBuilder>; | |
| 601 friend class CatchBlockBuilder; | |
| 602 | |
| 603 void BeginTry(ControlScopeForTryCatch* scope) { | |
| 604 DCHECK_NULL(control_scope_); | |
| 605 control_scope_ = scope; | |
| 606 | |
| 607 // Preserve the context in a dedicated register, so that it can be restored | |
| 608 // when the handler is entered by the stack-unwinding machinery. | |
| 609 // TODO(mstarzinger): Be smarter about register allocation. | |
| 610 DCHECK(!context_.is_valid()); | |
| 611 context_ = generator_->register_allocator()->NewRegister(); | |
| 612 builder()->MoveRegister(Register::current_context(), context_); | |
| 613 | |
| 614 TryCatchBuilder::BeginTry(context_); | |
| 615 last_catch_prediction_ = generator_->catch_prediction_; | |
| 616 if (catch_prediction() != HandlerTable::UNCAUGHT) { | |
| 617 generator_->catch_prediction_ = catch_prediction(); | |
| 618 } | |
|
rmcilroy
2017/02/07 17:24:41
I'm not sure why we need to update the catch predi
| |
| 619 } | |
| 620 | |
| 621 void EndTry() { | |
| 622 DCHECK_NOT_NULL(control_scope_); | |
| 623 generator_->catch_prediction_ = last_catch_prediction_; | |
| 624 last_catch_prediction_ = HandlerTable::UNCAUGHT; | |
| 625 | |
| 626 TryCatchBuilder::EndTry(); | |
| 627 control_scope_ = nullptr; | |
| 628 } | |
| 629 | |
| 630 void BeginCatch() { | |
| 631 DCHECK_NULL(control_scope_); | |
| 632 DCHECK(context_.is_valid()); | |
| 633 } | |
| 634 | |
| 635 void EndCatch() { TryCatchBuilder::EndCatch(); } | |
| 636 | |
| 637 BytecodeGenerator* generator_; | |
| 638 Register context_; | |
| 639 ControlScopeForTryCatch* control_scope_ = nullptr; | |
| 640 HandlerTable::CatchPrediction last_catch_prediction_; | |
| 641 }; | |
| 642 | |
| 643 class BytecodeGenerator::SimpleTryFinallyBuilder : public TryFinallyBuilder { | |
|
rmcilroy
2017/02/07 17:24:41
I'm not sure on the naming, why is this SimpleTryF
| |
| 644 public: | |
| 645 typedef ControlScopeForTryFinally TryControlScope; | |
| 646 | |
| 647 explicit SimpleTryFinallyBuilder(BytecodeGenerator* generator) | |
| 648 : TryFinallyBuilder(generator->builder(), generator->catch_prediction_), | |
| 649 generator_(generator), | |
| 650 token_(generator->register_allocator()->NewRegister()), | |
| 651 result_(generator->register_allocator()->NewRegister()), | |
| 652 commands_(generator, token_, result_) { | |
| 653 // We keep a record of all paths that enter the finally-block to be able to | |
| 654 // dispatch to the correct continuation point after the statements in the | |
| 655 // finally-block have been evaluated. | |
| 656 // | |
| 657 // The try-finally construct can enter the finally-block in three ways: | |
| 658 // 1. By exiting the try-block normally, falling through at the end. | |
| 659 // 2. By exiting the try-block with a function-local control flow transfer | |
| 660 // (i.e. through break/continue/return statements). | |
| 661 // 3. By exiting the try-block with a thrown exception. | |
| 662 // | |
| 663 // The result register semantics depend on how the block was entered: | |
| 664 // - ReturnStatement: It represents the return value being returned. | |
| 665 // - ThrowStatement: It represents the exception being thrown. | |
| 666 // - BreakStatement/ContinueStatement: Undefined and not used. | |
| 667 // - Falling through into finally-block: Undefined and not used. | |
| 668 } | |
| 669 | |
| 670 private: | |
| 671 friend class TryBlockBuilder<SimpleTryFinallyBuilder>; | |
| 672 friend class FinallyBlockBuilder; | |
| 673 | |
| 674 void BeginTry(ControlScopeForTryFinally* control_scope) { | |
| 675 DCHECK_NULL(control_scope_); | |
| 676 control_scope_ = control_scope; | |
| 677 | |
| 678 // Preserve the context in a dedicated register, so that it can be restored | |
| 679 // when the handler is entered by the stack-unwinding machinery. | |
| 680 // TODO(mstarzinger): Be smarter about register allocation. | |
| 681 DCHECK(!context_or_message_.is_valid()); | |
| 682 context_or_message_ = generator_->register_allocator()->NewRegister(); | |
| 683 generator_->builder()->MoveRegister(Register::current_context(), | |
| 684 context_or_message_); | |
| 685 | |
| 686 TryFinallyBuilder::BeginTry(context_or_message_); | |
| 687 } | |
| 688 | |
| 689 void EndTry() { | |
| 690 DCHECK_NOT_NULL(control_scope_); | |
| 691 TryFinallyBuilder::EndTry(); | |
| 692 control_scope_ = nullptr; | |
| 693 | |
| 694 // Record fall-through and exception cases. | |
| 695 commands_.RecordFallThroughPath(); | |
| 696 TryFinallyBuilder::LeaveTry(); | |
| 697 TryFinallyBuilder::BeginHandler(); | |
| 698 commands_.RecordHandlerReThrowPath(); | |
| 699 } | |
| 700 | |
| 701 void BeginFinally() { | |
| 702 TryFinallyBuilder::BeginFinally(); | |
| 703 generator_->builder() | |
| 704 ->LoadTheHole() | |
| 705 .SetPendingMessage() | |
| 706 .StoreAccumulatorInRegister(context_or_message_); | |
| 707 } | |
| 708 | |
| 709 void EndFinally() { | |
| 710 TryFinallyBuilder::EndFinally(); | |
| 711 | |
| 712 // Pending message object is restored on exit. | |
| 713 generator_->builder() | |
| 714 ->LoadAccumulatorWithRegister(context_or_message_) | |
| 715 .SetPendingMessage(); | |
| 716 | |
| 717 // Dynamic dispatch after the finally-block. | |
| 718 commands_.ApplyDeferredCommands(); | |
| 719 } | |
| 720 | |
| 721 ControlScopeForTryFinally* control_scope_ = nullptr; | |
| 722 BytecodeGenerator* generator_; | |
| 723 Register token_; | |
| 724 Register result_; | |
| 725 ControlScope::DeferredCommands commands_; | |
| 726 Register context_or_message_; | |
| 727 }; | |
| 728 | |
| 729 template <class T> | |
| 730 class BytecodeGenerator::TryBlockBuilder { | |
|
rmcilroy
2017/02/07 17:24:41
I don't think the scoped builders are necessary, I
| |
| 731 public: | |
| 732 typedef T SimpleControlBuilder; | |
| 733 explicit TryBlockBuilder(SimpleControlBuilder& builder); | |
| 734 ~TryBlockBuilder(); | |
| 735 | |
| 736 private: | |
| 737 SimpleControlBuilder* builder_; | |
| 738 typename SimpleControlBuilder::TryControlScope scope_; | |
| 739 }; | |
| 740 | |
| 741 template <> | |
| 742 BytecodeGenerator::TryBlockBuilder<BytecodeGenerator::SimpleTryCatchBuilder>:: | |
| 743 TryBlockBuilder(SimpleTryCatchBuilder& builder) | |
| 744 : builder_(&builder), scope_(builder_->generator_, builder_) { | |
| 745 builder_->BeginTry(&scope_); | |
| 746 } | |
| 747 | |
| 748 template <> | |
| 749 BytecodeGenerator::TryBlockBuilder< | |
| 750 BytecodeGenerator::SimpleTryCatchBuilder>::~TryBlockBuilder() { | |
| 751 builder_->EndTry(); | |
| 752 } | |
| 753 | |
| 754 template <> | |
| 755 BytecodeGenerator::TryBlockBuilder<BytecodeGenerator::SimpleTryFinallyBuilder>:: | |
| 756 TryBlockBuilder(SimpleTryFinallyBuilder& builder) | |
| 757 : builder_(&builder), | |
| 758 scope_(builder_->generator_, builder_, &builder_->commands_) { | |
| 759 builder_->BeginTry(&scope_); | |
| 760 } | |
| 761 | |
| 762 template <> | |
| 763 BytecodeGenerator::TryBlockBuilder< | |
| 764 BytecodeGenerator::SimpleTryFinallyBuilder>::~TryBlockBuilder() { | |
| 765 builder_->EndTry(); | |
| 766 } | |
| 767 | |
| 768 class BytecodeGenerator::CatchBlockBuilder { | |
| 769 public: | |
| 770 explicit CatchBlockBuilder(SimpleTryCatchBuilder& builder) | |
| 771 : builder_(&builder) { | |
| 772 builder_->BeginCatch(); | |
| 773 } | |
| 774 | |
| 775 ~CatchBlockBuilder() { builder_->EndCatch(); } | |
| 776 | |
| 777 private: | |
| 778 SimpleTryCatchBuilder* builder_; | |
| 779 }; | |
| 780 | |
| 781 class BytecodeGenerator::FinallyBlockBuilder { | |
| 782 public: | |
| 783 explicit FinallyBlockBuilder(SimpleTryFinallyBuilder& builder) | |
| 784 : builder_(&builder) { | |
| 785 builder_->BeginFinally(); | |
| 786 } | |
| 787 | |
| 788 ~FinallyBlockBuilder() { builder_->EndFinally(); } | |
| 789 | |
| 790 private: | |
| 791 SimpleTryFinallyBuilder* builder_; | |
| 792 }; | |
| 793 | |
| 583 BytecodeGenerator::BytecodeGenerator(CompilationInfo* info) | 794 BytecodeGenerator::BytecodeGenerator(CompilationInfo* info) |
| 584 : zone_(info->zone()), | 795 : zone_(info->zone()), |
| 585 builder_(new (zone()) BytecodeArrayBuilder( | 796 builder_(new (zone()) BytecodeArrayBuilder( |
| 586 info->isolate(), info->zone(), info->num_parameters_including_this(), | 797 info->isolate(), info->zone(), info->num_parameters_including_this(), |
| 587 info->scope()->MaxNestedContextChainLength(), | 798 info->scope()->MaxNestedContextChainLength(), |
| 588 info->scope()->num_stack_slots(), info->literal(), | 799 info->scope()->num_stack_slots(), info->literal(), |
| 589 info->SourcePositionRecordingMode())), | 800 info->SourcePositionRecordingMode())), |
| 590 info_(info), | 801 info_(info), |
| 591 scope_(info->scope()), | 802 scope_(info->scope()), |
| 592 globals_builder_(new (zone()) GlobalDeclarationsBuilder(info->zone())), | 803 globals_builder_(new (zone()) GlobalDeclarationsBuilder(info->zone())), |
| 593 global_declarations_(0, info->zone()), | 804 global_declarations_(0, info->zone()), |
| 594 function_literals_(0, info->zone()), | 805 function_literals_(0, info->zone()), |
| 595 native_function_literals_(0, info->zone()), | 806 native_function_literals_(0, info->zone()), |
| 596 object_literals_(0, info->zone()), | 807 object_literals_(0, info->zone()), |
| 597 array_literals_(0, info->zone()), | 808 array_literals_(0, info->zone()), |
| 598 execution_control_(nullptr), | 809 execution_control_(nullptr), |
| 599 execution_context_(nullptr), | 810 execution_context_(nullptr), |
| 600 execution_result_(nullptr), | 811 execution_result_(nullptr), |
| 601 generator_resume_points_(info->literal()->yield_count(), info->zone()), | 812 generator_resume_points_(info->literal()->yield_count(), info->zone()), |
| 602 generator_state_(), | 813 generator_state_(), |
| 603 loop_depth_(0), | 814 loop_depth_(0), |
| 815 catch_prediction_(HandlerTable::UNCAUGHT), | |
| 604 home_object_symbol_(info->isolate()->factory()->home_object_symbol()), | 816 home_object_symbol_(info->isolate()->factory()->home_object_symbol()), |
| 605 iterator_symbol_(info->isolate()->factory()->iterator_symbol()), | 817 iterator_symbol_(info->isolate()->factory()->iterator_symbol()), |
| 606 prototype_string_(info->isolate()->factory()->prototype_string()), | 818 prototype_string_(info->isolate()->factory()->prototype_string()), |
| 607 empty_fixed_array_(info->isolate()->factory()->empty_fixed_array()), | 819 empty_fixed_array_(info->isolate()->factory()->empty_fixed_array()), |
| 608 undefined_string_( | 820 undefined_string_( |
| 609 info->isolate()->ast_string_constants()->undefined_string()) {} | 821 info->isolate()->ast_string_constants()->undefined_string()) {} |
| 610 | 822 |
| 611 Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(Isolate* isolate) { | 823 Handle<BytecodeArray> BytecodeGenerator::FinalizeBytecode(Isolate* isolate) { |
| 612 AllocateDeferredConstants(isolate); | 824 AllocateDeferredConstants(isolate); |
| 613 if (HasStackOverflow()) return Handle<BytecodeArray>(); | 825 if (HasStackOverflow()) return Handle<BytecodeArray>(); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 689 if (scope()->NeedsContext()) { | 901 if (scope()->NeedsContext()) { |
| 690 // Push a new inner context scope for the function. | 902 // Push a new inner context scope for the function. |
| 691 BuildNewLocalActivationContext(); | 903 BuildNewLocalActivationContext(); |
| 692 ContextScope local_function_context(this, scope(), false); | 904 ContextScope local_function_context(this, scope(), false); |
| 693 BuildLocalActivationContextInitialization(); | 905 BuildLocalActivationContextInitialization(); |
| 694 GenerateBytecodeBody(); | 906 GenerateBytecodeBody(); |
| 695 } else { | 907 } else { |
| 696 GenerateBytecodeBody(); | 908 GenerateBytecodeBody(); |
| 697 } | 909 } |
| 698 | 910 |
| 699 // In generator functions, we may not have visited every yield in the AST | |
| 700 // since we skip some obviously dead code. Hence the generated bytecode may | |
| 701 // contain jumps to unbound labels (resume points that will never be used). | |
| 702 // We bind these now. | |
| 703 for (auto& label : generator_resume_points_) { | |
| 704 if (!label.is_bound()) builder()->Bind(&label); | |
| 705 } | |
| 706 | |
| 707 // Emit an implicit return instruction in case control flow can fall off the | 911 // Emit an implicit return instruction in case control flow can fall off the |
| 708 // end of the function without an explicit return being present on all paths. | 912 // end of the function without an explicit return being present on all paths. |
| 709 if (builder()->RequiresImplicitReturn()) { | 913 if (builder()->RequiresImplicitReturn()) { |
| 710 builder()->LoadUndefined(); | 914 builder()->LoadUndefined(); |
| 711 BuildReturn(); | 915 BuildReturn(); |
| 712 } | 916 } |
| 713 DCHECK(!builder()->RequiresImplicitReturn()); | 917 DCHECK(!builder()->RequiresImplicitReturn()); |
| 714 } | 918 } |
| 715 | 919 |
| 716 void BytecodeGenerator::GenerateBytecodeBody() { | 920 void BytecodeGenerator::GenerateBytecodeBody() { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 729 | 933 |
| 730 // Emit tracing call if requested to do so. | 934 // Emit tracing call if requested to do so. |
| 731 if (FLAG_trace) builder()->CallRuntime(Runtime::kTraceEnter); | 935 if (FLAG_trace) builder()->CallRuntime(Runtime::kTraceEnter); |
| 732 | 936 |
| 733 // Visit declarations within the function scope. | 937 // Visit declarations within the function scope. |
| 734 VisitDeclarations(scope()->declarations()); | 938 VisitDeclarations(scope()->declarations()); |
| 735 | 939 |
| 736 // Emit initializing assignments for module namespace imports (if any). | 940 // Emit initializing assignments for module namespace imports (if any). |
| 737 VisitModuleNamespaceImports(); | 941 VisitModuleNamespaceImports(); |
| 738 | 942 |
| 943 FunctionLiteral* literal = info()->literal(); | |
| 944 | |
| 739 // Perform a stack-check before the body. | 945 // Perform a stack-check before the body. |
| 740 builder()->StackCheck(info()->literal()->start_position()); | 946 builder()->StackCheck(literal->start_position()); |
| 741 | 947 |
| 948 // Build assignment to variable <function name> if function is a named | |
| 949 // expression and the variable is used. | |
| 950 if (literal->is_named_expression()) { | |
| 951 Variable* function_var = scope()->function_var(); | |
| 952 if (function_var != nullptr && !function_var->IsUnallocated()) { | |
| 953 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | |
| 954 BuildVariableAssignment(function_var, Token::INIT, | |
| 955 FeedbackVectorSlot::Invalid(), | |
| 956 HoleCheckMode::kElided); | |
| 957 } | |
| 958 } | |
| 959 | |
| 960 if (IsAsyncFunction(literal->kind())) { | |
| 961 return GenerateBytecodeBodyForAsyncFunction(literal); | |
| 962 } | |
| 963 if (IsGeneratorFunction(literal->kind())) { | |
| 964 return GenerateBytecodeBodyForGenerator(literal); | |
| 965 } | |
| 966 if (IsModule(literal->kind())) { | |
| 967 return GenerateBytecodeBodyForModule(literal); | |
| 968 } | |
| 969 | |
| 970 Block* parameter_init_block = literal->parameter_init_block(); | |
| 742 // Visit statements in the function body. | 971 // Visit statements in the function body. |
| 743 VisitStatements(info()->literal()->body()); | 972 if (parameter_init_block != nullptr) { |
| 973 VisitBlock(parameter_init_block); | |
| 974 } | |
| 975 VisitStatements(literal->body()); | |
| 976 } | |
| 977 | |
| 978 void BytecodeGenerator::BuildAllocateAndStoreJSGeneratorObject( | |
| 979 FunctionLiteral* literal, BuildJSGeneratorObject tag) { | |
| 980 RegisterAllocationScope register_scope(this); | |
| 981 RegisterList args = register_allocator()->NewRegisterList(2); | |
| 982 builder()->MoveRegister(Register::function_closure(), args[0]); | |
| 983 | |
| 984 int yield_position = literal->position(); | |
| 985 builder()->SetExpressionPosition(yield_position); | |
| 986 | |
| 987 if (IsArrowFunction(literal->kind())) { | |
| 988 // Lexical `this` | |
| 989 builder()->LoadUndefined().StoreAccumulatorInRegister(args[1]); | |
| 990 } else { | |
| 991 // Receiver parameter | |
| 992 builder()->MoveRegister(builder()->Parameter(0), args[1]); | |
| 993 } | |
| 994 builder()->CallRuntime(Runtime::kCreateJSGeneratorObject, args); | |
| 995 | |
| 996 Variable* var_generator = scope()->generator_object_var(); | |
| 997 DCHECK_NOT_NULL(var_generator); | |
| 998 | |
| 999 switch (tag) { | |
| 1000 case BuildJSGeneratorObject::kInitialYield: { | |
| 1001 Register generator = args[0]; | |
| 1002 builder()->StoreAccumulatorInRegister(generator); | |
| 1003 BuildVariableAssignment(var_generator, Token::INIT, | |
| 1004 FeedbackVectorSlot::Invalid(), | |
| 1005 HoleCheckMode::kElided); | |
| 1006 BuildYield(0, generator, generator); | |
| 1007 BuildYieldResumePoint(0, Yield::kOnExceptionThrow, generator, | |
| 1008 yield_position); | |
| 1009 break; | |
| 1010 } | |
| 1011 case BuildJSGeneratorObject::kNoInitialYield: { | |
| 1012 BuildVariableAssignment(var_generator, Token::INIT, | |
| 1013 FeedbackVectorSlot::Invalid(), | |
| 1014 HoleCheckMode::kElided); | |
| 1015 break; | |
| 1016 } | |
| 1017 } | |
| 1018 } | |
| 1019 | |
| 1020 void BytecodeGenerator::BuildAllocateAndStoreJSPromise() { | |
| 1021 Variable* var_promise = scope()->promise_var(); | |
| 1022 DCHECK_NOT_NULL(var_promise); | |
| 1023 | |
| 1024 RegisterAllocationScope register_scope(this); | |
| 1025 RegisterList args = register_allocator()->NewRegisterList(1); | |
| 1026 builder()->LoadUndefined().StoreAccumulatorInRegister(args[0]).CallJSRuntime( | |
| 1027 Context::ASYNC_FUNCTION_PROMISE_CREATE_INDEX, args); | |
| 1028 BuildVariableAssignment(var_promise, Token::INIT, | |
| 1029 FeedbackVectorSlot::Invalid(), | |
| 1030 HoleCheckMode::kElided); | |
| 1031 } | |
| 1032 | |
| 1033 void BytecodeGenerator::BindUnboundGeneratorResumePoints() { | |
| 1034 DCHECK(IsResumableFunction(info()->literal()->kind())); | |
| 1035 for (auto& label : generator_resume_points_) { | |
| 1036 if (!label.is_bound()) builder()->Bind(&label); | |
| 1037 } | |
| 1038 } | |
| 1039 | |
| 1040 void BytecodeGenerator::GenerateBytecodeBodyForGenerator( | |
| 1041 FunctionLiteral* literal) { | |
| 1042 DCHECK(IsGeneratorFunction(literal->kind())); | |
| 1043 | |
| 1044 // Desugar parameters before generator is allocated. | |
| 1045 Block* const parameter_init_block = literal->parameter_init_block(); | |
| 1046 if (parameter_init_block != nullptr) { | |
| 1047 // Initialize non-simple parameters before initial yield. | |
| 1048 VisitBlock(parameter_init_block); | |
| 1049 } | |
| 1050 | |
| 1051 { | |
| 1052 RegisterAllocationScope register_scope(this); | |
| 1053 SimpleTryFinallyBuilder try_control_builder(this); | |
| 1054 { // Try ... | |
| 1055 TryBlockBuilderForFinally try_builder(try_control_builder); | |
| 1056 BuildAllocateAndStoreJSGeneratorObject( | |
| 1057 literal, BuildJSGeneratorObject::kInitialYield); | |
| 1058 VisitStatements(literal->body()); | |
| 1059 } | |
| 1060 | |
| 1061 { // Finally ... | |
| 1062 FinallyBlockBuilder finally_builder(try_control_builder); | |
| 1063 Variable* var_generator = scope()->generator_object_var(); | |
| 1064 DCHECK_NOT_NULL(var_generator); | |
| 1065 | |
| 1066 RegisterAllocationScope register_scope(this); | |
| 1067 BuildVariableLoad(var_generator, FeedbackVectorSlot::Invalid(), | |
| 1068 HoleCheckMode::kElided); | |
| 1069 Register generator = register_allocator()->NewRegister(); | |
| 1070 builder()->StoreAccumulatorInRegister(generator).CallRuntime( | |
| 1071 Runtime::kInlineGeneratorClose, generator); | |
| 1072 } | |
| 1073 } | |
| 1074 | |
| 1075 // In generator functions, we may not have visited every yield in the AST | |
| 1076 // since we skip some obviously dead code. Hence the generated bytecode may | |
| 1077 // contain jumps to unbound labels (resume points that will never be used). | |
| 1078 // We bind these now. | |
| 1079 BindUnboundGeneratorResumePoints(); | |
| 1080 | |
| 1081 if (builder()->RequiresImplicitReturn()) { | |
| 1082 // Unreachable, but required for BytecodeArrayBuilder | |
| 1083 builder()->LoadUndefined().Return(); | |
| 1084 } | |
| 1085 DCHECK(!builder()->RequiresImplicitReturn()); | |
| 1086 } | |
| 1087 | |
| 1088 void BytecodeGenerator::GenerateBytecodeBodyForModule( | |
| 1089 FunctionLiteral* literal) { | |
| 1090 DCHECK(IsModule(literal->kind())); | |
| 1091 | |
| 1092 // Modules do not have non-simple parameters | |
| 1093 DCHECK_NULL(literal->parameter_init_block()); | |
| 1094 | |
| 1095 BuildAllocateAndStoreJSGeneratorObject(literal, | |
| 1096 BuildJSGeneratorObject::kInitialYield); | |
| 1097 VisitStatements(literal->body()); | |
| 1098 | |
| 1099 // In modules, we may not have visited every yield in the AST | |
| 1100 // since we skip some obviously dead code. Hence the generated bytecode may | |
| 1101 // contain jumps to unbound labels (resume points that will never be used). | |
| 1102 // We bind these now. | |
| 1103 BindUnboundGeneratorResumePoints(); | |
| 1104 } | |
| 1105 | |
| 1106 void BytecodeGenerator::GenerateBytecodeBodyForAsyncFunction( | |
| 1107 FunctionLiteral* literal) { | |
| 1108 DCHECK(IsAsyncFunction(literal->kind())); | |
| 1109 | |
| 1110 BuildAllocateAndStoreJSPromise(); | |
| 1111 | |
| 1112 { | |
| 1113 RegisterAllocationScope register_scope(this); | |
| 1114 SimpleTryCatchBuilder try_control_builder(this, HandlerTable::ASYNC_AWAIT); | |
| 1115 { | |
| 1116 TryBlockBuilderForCatch try_block(try_control_builder); | |
| 1117 | |
| 1118 Block* const parameter_init_block = literal->parameter_init_block(); | |
| 1119 if (parameter_init_block != nullptr) { | |
| 1120 // Initialize non-simple parameters if necessary, reject Promise in | |
| 1121 // case of exception | |
| 1122 RegisterAllocationScope register_scope(this); | |
| 1123 VisitBlock(parameter_init_block); | |
| 1124 } | |
| 1125 | |
| 1126 BuildAllocateAndStoreJSGeneratorObject( | |
| 1127 literal, BuildJSGeneratorObject::kNoInitialYield); | |
| 1128 | |
| 1129 // Finish generating function body | |
| 1130 VisitStatements(literal->body()); | |
| 1131 } | |
| 1132 | |
| 1133 { | |
| 1134 CatchBlockBuilder catch_block(try_control_builder); | |
| 1135 RegisterList args = register_allocator()->NewRegisterList(4); | |
| 1136 Register promise = args[1]; | |
| 1137 Register exception = args[2]; | |
| 1138 | |
| 1139 builder() | |
| 1140 ->StoreAccumulatorInRegister(exception) | |
| 1141 .LoadTheHole() | |
| 1142 .SetPendingMessage(); | |
| 1143 | |
| 1144 Variable* var_promise = scope()->promise_var(); | |
| 1145 DCHECK_NOT_NULL(var_promise); | |
| 1146 BuildVariableLoad(var_promise, FeedbackVectorSlot::Invalid(), | |
| 1147 HoleCheckMode::kElided); | |
| 1148 builder() | |
| 1149 ->StoreAccumulatorInRegister(promise) | |
| 1150 .LoadUndefined() | |
| 1151 .StoreAccumulatorInRegister(args[0]) | |
| 1152 .LoadFalse() | |
| 1153 .StoreAccumulatorInRegister(args[3]) | |
| 1154 .CallJSRuntime(Context::PROMISE_INTERNAL_REJECT_INDEX, args) | |
| 1155 .LoadAccumulatorWithRegister(promise) | |
| 1156 .Return(); | |
| 1157 } | |
| 1158 } | |
| 1159 | |
| 1160 // In async functions, we may not have visited every yield in the AST | |
| 1161 // since we skip some obviously dead code. Hence the generated bytecode may | |
| 1162 // contain jumps to unbound labels (resume points that will never be used). | |
| 1163 // We bind these now. | |
| 1164 BindUnboundGeneratorResumePoints(); | |
| 1165 | |
| 1166 if (builder()->RequiresImplicitReturn()) { | |
| 1167 // Unreachable, but required for BytecodeArrayBuilder | |
| 1168 builder()->LoadUndefined().Return(); | |
| 1169 } | |
| 1170 DCHECK(!builder()->RequiresImplicitReturn()); | |
| 744 } | 1171 } |
| 745 | 1172 |
| 746 void BytecodeGenerator::BuildIndexedJump(Register index, size_t start_index, | 1173 void BytecodeGenerator::BuildIndexedJump(Register index, size_t start_index, |
| 747 size_t size, | 1174 size_t size, |
| 748 ZoneVector<BytecodeLabel>& targets) { | 1175 ZoneVector<BytecodeLabel>& targets) { |
| 749 // TODO(neis): Optimize this by using a proper jump table. | 1176 // TODO(neis): Optimize this by using a proper jump table. |
| 750 DCHECK_LE(start_index + size, targets.size()); | 1177 DCHECK_LE(start_index + size, targets.size()); |
| 751 for (size_t i = start_index; i < start_index + size; i++) { | 1178 for (size_t i = start_index; i < start_index + size; i++) { |
| 752 builder() | 1179 builder() |
| 753 ->LoadLiteral(Smi::FromInt(static_cast<int>(i))) | 1180 ->LoadLiteral(Smi::FromInt(static_cast<int>(i))) |
| (...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1328 VisitForAccumulatorValue(stmt->result_done()); | 1755 VisitForAccumulatorValue(stmt->result_done()); |
| 1329 loop_builder.BreakIfTrue(); | 1756 loop_builder.BreakIfTrue(); |
| 1330 | 1757 |
| 1331 VisitForEffect(stmt->assign_each()); | 1758 VisitForEffect(stmt->assign_each()); |
| 1332 VisitIterationBody(stmt, &loop_builder); | 1759 VisitIterationBody(stmt, &loop_builder); |
| 1333 loop_builder.JumpToHeader(loop_depth_); | 1760 loop_builder.JumpToHeader(loop_depth_); |
| 1334 loop_builder.EndLoop(); | 1761 loop_builder.EndLoop(); |
| 1335 } | 1762 } |
| 1336 | 1763 |
| 1337 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 1764 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 1338 TryCatchBuilder try_control_builder(builder(), stmt->catch_prediction()); | 1765 SimpleTryCatchBuilder try_control_builder(this, stmt->catch_prediction()); |
| 1339 | |
| 1340 // Preserve the context in a dedicated register, so that it can be restored | |
| 1341 // when the handler is entered by the stack-unwinding machinery. | |
| 1342 // TODO(mstarzinger): Be smarter about register allocation. | |
| 1343 Register context = register_allocator()->NewRegister(); | |
| 1344 builder()->MoveRegister(Register::current_context(), context); | |
| 1345 | |
| 1346 // Evaluate the try-block inside a control scope. This simulates a handler | |
| 1347 // that is intercepting 'throw' control commands. | |
| 1348 try_control_builder.BeginTry(context); | |
| 1349 { | 1766 { |
| 1350 ControlScopeForTryCatch scope(this, &try_control_builder); | 1767 TryBlockBuilderForCatch try_block(try_control_builder); |
| 1351 Visit(stmt->try_block()); | 1768 Visit(stmt->try_block()); |
| 1352 } | 1769 } |
| 1353 try_control_builder.EndTry(); | |
| 1354 | 1770 |
| 1771 // Evaluate the catch-block. | |
| 1355 // Create a catch scope that binds the exception. | 1772 // Create a catch scope that binds the exception. |
| 1773 CatchBlockBuilder catch_block(try_control_builder); | |
| 1774 Register context = try_control_builder.context(); | |
| 1356 BuildNewLocalCatchContext(stmt->variable(), stmt->scope()); | 1775 BuildNewLocalCatchContext(stmt->variable(), stmt->scope()); |
| 1357 builder()->StoreAccumulatorInRegister(context); | 1776 builder()->StoreAccumulatorInRegister(context); |
| 1358 | 1777 |
| 1359 // If requested, clear message object as we enter the catch block. | 1778 // If requested, clear message object as we enter the catch block. |
| 1360 if (stmt->clear_pending_message()) { | 1779 if (stmt->clear_pending_message()) { |
| 1361 builder()->LoadTheHole().SetPendingMessage(); | 1780 builder()->LoadTheHole().SetPendingMessage(); |
| 1362 } | 1781 } |
| 1363 | 1782 |
| 1364 // Load the catch context into the accumulator. | 1783 // Load the catch context into the accumulator. |
| 1365 builder()->LoadAccumulatorWithRegister(context); | 1784 builder()->LoadAccumulatorWithRegister(context); |
| 1366 | |
| 1367 // Evaluate the catch-block. | |
| 1368 VisitInScope(stmt->catch_block(), stmt->scope()); | 1785 VisitInScope(stmt->catch_block(), stmt->scope()); |
| 1369 try_control_builder.EndCatch(); | |
| 1370 } | 1786 } |
| 1371 | 1787 |
| 1372 void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 1788 void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
| 1373 TryFinallyBuilder try_control_builder(builder(), stmt->catch_prediction()); | 1789 SimpleTryFinallyBuilder try_control_builder(this); |
| 1374 | |
| 1375 // We keep a record of all paths that enter the finally-block to be able to | |
| 1376 // dispatch to the correct continuation point after the statements in the | |
| 1377 // finally-block have been evaluated. | |
| 1378 // | |
| 1379 // The try-finally construct can enter the finally-block in three ways: | |
| 1380 // 1. By exiting the try-block normally, falling through at the end. | |
| 1381 // 2. By exiting the try-block with a function-local control flow transfer | |
| 1382 // (i.e. through break/continue/return statements). | |
| 1383 // 3. By exiting the try-block with a thrown exception. | |
| 1384 // | |
| 1385 // The result register semantics depend on how the block was entered: | |
| 1386 // - ReturnStatement: It represents the return value being returned. | |
| 1387 // - ThrowStatement: It represents the exception being thrown. | |
| 1388 // - BreakStatement/ContinueStatement: Undefined and not used. | |
| 1389 // - Falling through into finally-block: Undefined and not used. | |
| 1390 Register token = register_allocator()->NewRegister(); | |
| 1391 Register result = register_allocator()->NewRegister(); | |
| 1392 ControlScope::DeferredCommands commands(this, token, result); | |
| 1393 | |
| 1394 // Preserve the context in a dedicated register, so that it can be restored | |
| 1395 // when the handler is entered by the stack-unwinding machinery. | |
| 1396 // TODO(mstarzinger): Be smarter about register allocation. | |
| 1397 Register context = register_allocator()->NewRegister(); | |
| 1398 builder()->MoveRegister(Register::current_context(), context); | |
| 1399 | |
| 1400 // Evaluate the try-block inside a control scope. This simulates a handler | |
| 1401 // that is intercepting all control commands. | |
| 1402 try_control_builder.BeginTry(context); | |
| 1403 { | 1790 { |
| 1404 ControlScopeForTryFinally scope(this, &try_control_builder, &commands); | 1791 TryBlockBuilderForFinally try_block(try_control_builder); |
| 1405 Visit(stmt->try_block()); | 1792 Visit(stmt->try_block()); |
| 1406 } | 1793 } |
| 1407 try_control_builder.EndTry(); | |
| 1408 | 1794 |
| 1409 // Record fall-through and exception cases. | 1795 FinallyBlockBuilder finally_block(try_control_builder); |
| 1410 commands.RecordFallThroughPath(); | |
| 1411 try_control_builder.LeaveTry(); | |
| 1412 try_control_builder.BeginHandler(); | |
| 1413 commands.RecordHandlerReThrowPath(); | |
| 1414 | |
| 1415 // Pending message object is saved on entry. | |
| 1416 try_control_builder.BeginFinally(); | |
| 1417 Register message = context; // Reuse register. | |
| 1418 | |
| 1419 // Clear message object as we enter the finally block. | |
| 1420 builder()->LoadTheHole().SetPendingMessage().StoreAccumulatorInRegister( | |
| 1421 message); | |
| 1422 | |
| 1423 // Evaluate the finally-block. | |
| 1424 Visit(stmt->finally_block()); | 1796 Visit(stmt->finally_block()); |
| 1425 try_control_builder.EndFinally(); | |
| 1426 | |
| 1427 // Pending message object is restored on exit. | |
| 1428 builder()->LoadAccumulatorWithRegister(message).SetPendingMessage(); | |
| 1429 | |
| 1430 // Dynamic dispatch after the finally-block. | |
| 1431 commands.ApplyDeferredCommands(); | |
| 1432 } | 1797 } |
| 1433 | 1798 |
| 1434 void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { | 1799 void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 1435 builder()->SetStatementPosition(stmt); | 1800 builder()->SetStatementPosition(stmt); |
| 1436 builder()->Debugger(); | 1801 builder()->Debugger(); |
| 1437 } | 1802 } |
| 1438 | 1803 |
| 1439 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { | 1804 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 1440 uint8_t flags = CreateClosureFlags::Encode(expr->pretenure(), | 1805 uint8_t flags = CreateClosureFlags::Encode(expr->pretenure(), |
| 1441 scope()->is_function_scope()); | 1806 scope()->is_function_scope()); |
| (...skipping 838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2280 } | 2645 } |
| 2281 case KEYED_SUPER_PROPERTY: { | 2646 case KEYED_SUPER_PROPERTY: { |
| 2282 builder() | 2647 builder() |
| 2283 ->StoreAccumulatorInRegister(super_property_args[3]) | 2648 ->StoreAccumulatorInRegister(super_property_args[3]) |
| 2284 .CallRuntime(StoreKeyedToSuperRuntimeId(), super_property_args); | 2649 .CallRuntime(StoreKeyedToSuperRuntimeId(), super_property_args); |
| 2285 break; | 2650 break; |
| 2286 } | 2651 } |
| 2287 } | 2652 } |
| 2288 } | 2653 } |
| 2289 | 2654 |
| 2290 void BytecodeGenerator::VisitYield(Yield* expr) { | 2655 void BytecodeGenerator::BuildYield(int yield_id, Register generator, |
| 2291 builder()->SetExpressionPosition(expr); | 2656 Register value) { |
| 2292 Register value = VisitForRegisterValue(expr->expression()); | 2657 DCHECK_GE(yield_id, 0); |
| 2293 | 2658 DCHECK_LT(yield_id, generator_resume_points_.size()); |
| 2294 Register generator = VisitForRegisterValue(expr->generator_object()); | 2659 DCHECK(generator.is_valid()); |
| 2660 DCHECK(value.is_valid()); | |
| 2295 | 2661 |
| 2296 // Save context, registers, and state. Then return. | 2662 // Save context, registers, and state. Then return. |
| 2297 builder() | 2663 builder() |
| 2298 ->LoadLiteral(Smi::FromInt(expr->yield_id())) | 2664 ->LoadLiteral(Smi::FromInt(yield_id)) |
| 2299 .SuspendGenerator(generator) | 2665 .SuspendGenerator(generator) |
| 2300 .LoadAccumulatorWithRegister(value) | 2666 .LoadAccumulatorWithRegister(value) |
| 2301 .Return(); // Hard return (ignore any finally blocks). | 2667 .Return(); // Hard return (ignore any finally blocks). |
| 2668 } | |
| 2302 | 2669 |
| 2303 builder()->Bind(&(generator_resume_points_[expr->yield_id()])); | 2670 void BytecodeGenerator::BuildYieldResumePoint(int yield_id, |
| 2671 Yield::OnException on_exception, | |
| 2672 Register generator, | |
| 2673 int position) { | |
| 2674 DCHECK_GE(yield_id, 0); | |
| 2675 DCHECK_LT(yield_id, generator_resume_points_.size()); | |
| 2676 DCHECK(generator.is_valid()); | |
| 2677 | |
| 2678 DCHECK(!generator_resume_points_[yield_id].is_bound()); | |
| 2679 builder()->Bind(&(generator_resume_points_[yield_id])); | |
| 2304 // Upon resume, we continue here. | 2680 // Upon resume, we continue here. |
| 2305 | 2681 |
| 2306 { | 2682 { |
| 2307 RegisterAllocationScope register_scope(this); | 2683 RegisterAllocationScope register_scope(this); |
| 2308 | 2684 |
| 2309 // Update state to indicate that we have finished resuming. Loop headers | 2685 // Update state to indicate that we have finished resuming. Loop headers |
| 2310 // rely on this. | 2686 // rely on this. |
| 2311 builder() | 2687 builder() |
| 2312 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) | 2688 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) |
| 2313 .StoreAccumulatorInRegister(generator_state_); | 2689 .StoreAccumulatorInRegister(generator_state_); |
| 2314 | 2690 |
| 2315 Register input = register_allocator()->NewRegister(); | 2691 Register input = register_allocator()->NewRegister(); |
| 2316 builder() | 2692 builder() |
| 2317 ->CallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos, generator) | 2693 ->CallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos, generator) |
| 2318 .StoreAccumulatorInRegister(input); | 2694 .StoreAccumulatorInRegister(input); |
| 2319 | 2695 |
| 2320 Register resume_mode = register_allocator()->NewRegister(); | 2696 Register resume_mode = register_allocator()->NewRegister(); |
| 2321 builder() | 2697 builder() |
| 2322 ->CallRuntime(Runtime::kInlineGeneratorGetResumeMode, generator) | 2698 ->CallRuntime(Runtime::kInlineGeneratorGetResumeMode, generator) |
| 2323 .StoreAccumulatorInRegister(resume_mode); | 2699 .StoreAccumulatorInRegister(resume_mode); |
| 2324 | 2700 |
| 2325 // Now dispatch on resume mode. | 2701 // Now dispatch on resume mode. |
| 2326 | 2702 |
| 2327 BytecodeLabel resume_with_next; | 2703 BytecodeLabel resume_with_next; |
| 2328 BytecodeLabel resume_with_return; | 2704 BytecodeLabel resume_with_return; |
| 2329 BytecodeLabel resume_with_throw; | 2705 BytecodeLabel resume_with_throw; |
| 2330 | 2706 |
| 2707 // TODO(caitp): Don't generate `resume_with_return` block for non-generators | |
| 2331 builder() | 2708 builder() |
| 2332 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext)) | 2709 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext)) |
| 2333 .CompareOperation(Token::EQ_STRICT, resume_mode) | 2710 .CompareOperation(Token::EQ_STRICT, resume_mode) |
| 2334 .JumpIfTrue(&resume_with_next) | 2711 .JumpIfTrue(&resume_with_next) |
| 2335 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kThrow)) | 2712 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kThrow)) |
| 2336 .CompareOperation(Token::EQ_STRICT, resume_mode) | 2713 .CompareOperation(Token::EQ_STRICT, resume_mode) |
| 2337 .JumpIfTrue(&resume_with_throw) | 2714 .JumpIfTrue(&resume_with_throw) |
| 2338 .Jump(&resume_with_return); | 2715 .Jump(&resume_with_return); |
| 2339 | 2716 |
| 2340 builder()->Bind(&resume_with_return); | 2717 builder()->Bind(&resume_with_return); |
| 2341 { | 2718 { |
| 2342 RegisterList args = register_allocator()->NewRegisterList(2); | 2719 RegisterList args = register_allocator()->NewRegisterList(2); |
| 2343 builder() | 2720 builder() |
| 2344 ->MoveRegister(input, args[0]) | 2721 ->MoveRegister(input, args[0]) |
| 2345 .LoadTrue() | 2722 .LoadTrue() |
| 2346 .StoreAccumulatorInRegister(args[1]) | 2723 .StoreAccumulatorInRegister(args[1]) |
| 2347 .CallRuntime(Runtime::kInlineCreateIterResultObject, args); | 2724 .CallRuntime(Runtime::kInlineCreateIterResultObject, args); |
| 2348 execution_control()->ReturnAccumulator(); | 2725 execution_control()->ReturnAccumulator(); |
| 2349 } | 2726 } |
| 2350 | 2727 |
| 2351 builder()->Bind(&resume_with_throw); | 2728 builder()->Bind(&resume_with_throw); |
| 2352 builder()->SetExpressionPosition(expr); | 2729 builder()->SetExpressionPosition(position); |
| 2353 builder()->LoadAccumulatorWithRegister(input); | 2730 builder()->LoadAccumulatorWithRegister(input); |
| 2354 if (expr->rethrow_on_exception()) { | 2731 if (on_exception == Yield::kOnExceptionRethrow) { |
| 2355 builder()->ReThrow(); | 2732 builder()->ReThrow(); |
| 2356 } else { | 2733 } else { |
| 2357 builder()->Throw(); | 2734 builder()->Throw(); |
| 2358 } | 2735 } |
| 2359 | 2736 |
| 2360 builder()->Bind(&resume_with_next); | 2737 builder()->Bind(&resume_with_next); |
| 2361 builder()->LoadAccumulatorWithRegister(input); | 2738 builder()->LoadAccumulatorWithRegister(input); |
| 2362 } | 2739 } |
| 2363 } | 2740 } |
| 2364 | 2741 |
| 2742 void BytecodeGenerator::VisitYield(Yield* expr) { | |
| 2743 Register generator = VisitForRegisterValue(expr->generator_object()); | |
| 2744 | |
| 2745 builder()->SetExpressionPosition(expr); | |
| 2746 Register value = VisitForRegisterValue(expr->expression()); | |
| 2747 | |
| 2748 BuildYield(expr->yield_id(), generator, value); | |
| 2749 BuildYieldResumePoint(expr->yield_id(), expr->on_exception(), generator, | |
| 2750 expr->position()); | |
| 2751 } | |
| 2752 | |
| 2365 void BytecodeGenerator::VisitThrow(Throw* expr) { | 2753 void BytecodeGenerator::VisitThrow(Throw* expr) { |
| 2366 VisitForAccumulatorValue(expr->exception()); | 2754 VisitForAccumulatorValue(expr->exception()); |
| 2367 builder()->SetExpressionPosition(expr); | 2755 builder()->SetExpressionPosition(expr); |
| 2368 builder()->Throw(); | 2756 builder()->Throw(); |
| 2369 } | 2757 } |
| 2370 | 2758 |
| 2371 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { | 2759 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { |
| 2372 LhsKind property_kind = Property::GetAssignType(expr); | 2760 LhsKind property_kind = Property::GetAssignType(expr); |
| 2373 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); | 2761 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); |
| 2374 builder()->SetExpressionPosition(expr); | 2762 builder()->SetExpressionPosition(expr); |
| (...skipping 1002 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3377 } | 3765 } |
| 3378 | 3766 |
| 3379 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { | 3767 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { |
| 3380 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 3768 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict |
| 3381 : Runtime::kStoreKeyedToSuper_Sloppy; | 3769 : Runtime::kStoreKeyedToSuper_Sloppy; |
| 3382 } | 3770 } |
| 3383 | 3771 |
| 3384 } // namespace interpreter | 3772 } // namespace interpreter |
| 3385 } // namespace internal | 3773 } // namespace internal |
| 3386 } // namespace v8 | 3774 } // namespace v8 |
| OLD | NEW |