Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(305)

Side by Side Diff: src/compiler/ast-graph-builder.cc

Issue 1148133002: [turbofan] Fix variable liveness control structure creation. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Move the consistency check to a separate method. Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/ast-graph-builder.h ('k') | test/mjsunit/compiler/regress-variable-liveness.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 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/compiler/ast-graph-builder.h" 5 #include "src/compiler/ast-graph-builder.h"
6 6
7 #include "src/compiler.h" 7 #include "src/compiler.h"
8 #include "src/compiler/ast-loop-assignment-analyzer.h" 8 #include "src/compiler/ast-loop-assignment-analyzer.h"
9 #include "src/compiler/control-builders.h" 9 #include "src/compiler/control-builders.h"
10 #include "src/compiler/js-type-feedback.h" 10 #include "src/compiler/js-type-feedback.h"
(...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 Node* return_value = jsgraph()->UndefinedConstant(); 592 Node* return_value = jsgraph()->UndefinedConstant();
593 NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value); 593 NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value);
594 } 594 }
595 595
596 // Return 'undefined' in case we can fall off the end. 596 // Return 'undefined' in case we can fall off the end.
597 BuildReturn(jsgraph()->UndefinedConstant()); 597 BuildReturn(jsgraph()->UndefinedConstant());
598 } 598 }
599 599
600 600
601 void AstGraphBuilder::ClearNonLiveSlotsInFrameStates() { 601 void AstGraphBuilder::ClearNonLiveSlotsInFrameStates() {
602 if (!FLAG_analyze_environment_liveness) return; 602 if (!FLAG_analyze_environment_liveness ||
603 !info()->is_deoptimization_enabled()) {
604 return;
605 }
603 606
604 NonLiveFrameStateSlotReplacer replacer( 607 NonLiveFrameStateSlotReplacer replacer(
605 &state_values_cache_, jsgraph()->UndefinedConstant(), 608 &state_values_cache_, jsgraph()->UndefinedConstant(),
606 liveness_analyzer()->local_count(), local_zone()); 609 liveness_analyzer()->local_count(), local_zone());
607 Variable* arguments = info()->scope()->arguments(); 610 Variable* arguments = info()->scope()->arguments();
608 if (arguments != nullptr && arguments->IsStackAllocated()) { 611 if (arguments != nullptr && arguments->IsStackAllocated()) {
609 replacer.MarkPermanentlyLive(arguments->index()); 612 replacer.MarkPermanentlyLive(arguments->index());
610 } 613 }
611 liveness_analyzer()->Run(&replacer); 614 liveness_analyzer()->Run(&replacer);
612 if (FLAG_trace_environment_liveness) { 615 if (FLAG_trace_environment_liveness) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
653 return nullptr; 656 return nullptr;
654 } 657 }
655 658
656 659
657 AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder, 660 AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder,
658 Scope* scope, 661 Scope* scope,
659 Node* control_dependency) 662 Node* control_dependency)
660 : builder_(builder), 663 : builder_(builder),
661 parameters_count_(scope->num_parameters() + 1), 664 parameters_count_(scope->num_parameters() + 1),
662 locals_count_(scope->num_stack_slots()), 665 locals_count_(scope->num_stack_slots()),
663 liveness_block_(builder_->liveness_analyzer()->NewBlock()), 666 liveness_block_(IsLivenessAnalysisEnabled()
667 ? builder_->liveness_analyzer()->NewBlock()
668 : nullptr),
664 values_(builder_->local_zone()), 669 values_(builder_->local_zone()),
665 contexts_(builder_->local_zone()), 670 contexts_(builder_->local_zone()),
666 control_dependency_(control_dependency), 671 control_dependency_(control_dependency),
667 effect_dependency_(control_dependency), 672 effect_dependency_(control_dependency),
668 parameters_node_(nullptr), 673 parameters_node_(nullptr),
669 locals_node_(nullptr), 674 locals_node_(nullptr),
670 stack_node_(nullptr) { 675 stack_node_(nullptr) {
671 DCHECK_EQ(scope->num_parameters() + 1, parameters_count()); 676 DCHECK_EQ(scope->num_parameters() + 1, parameters_count());
672 677
673 // Bind the receiver variable. 678 // Bind the receiver variable.
(...skipping 15 matching lines...) Expand all
689 builder->graph()->start()); 694 builder->graph()->start());
690 values()->push_back(parameter); 695 values()->push_back(parameter);
691 } 696 }
692 697
693 // Bind all local variables to undefined. 698 // Bind all local variables to undefined.
694 Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); 699 Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
695 values()->insert(values()->end(), locals_count(), undefined_constant); 700 values()->insert(values()->end(), locals_count(), undefined_constant);
696 } 701 }
697 702
698 703
699 AstGraphBuilder::Environment::Environment(AstGraphBuilder::Environment* copy) 704 AstGraphBuilder::Environment::Environment(AstGraphBuilder::Environment* copy,
705 LivenessAnalyzerBlock* liveness_block)
700 : builder_(copy->builder_), 706 : builder_(copy->builder_),
701 parameters_count_(copy->parameters_count_), 707 parameters_count_(copy->parameters_count_),
702 locals_count_(copy->locals_count_), 708 locals_count_(copy->locals_count_),
709 liveness_block_(liveness_block),
703 values_(copy->zone()), 710 values_(copy->zone()),
704 contexts_(copy->zone()), 711 contexts_(copy->zone()),
705 control_dependency_(copy->control_dependency_), 712 control_dependency_(copy->control_dependency_),
706 effect_dependency_(copy->effect_dependency_), 713 effect_dependency_(copy->effect_dependency_),
707 parameters_node_(copy->parameters_node_), 714 parameters_node_(copy->parameters_node_),
708 locals_node_(copy->locals_node_), 715 locals_node_(copy->locals_node_),
709 stack_node_(copy->stack_node_) { 716 stack_node_(copy->stack_node_) {
710 const size_t kStackEstimate = 7; // optimum from experimentation! 717 const size_t kStackEstimate = 7; // optimum from experimentation!
711 values_.reserve(copy->values_.size() + kStackEstimate); 718 values_.reserve(copy->values_.size() + kStackEstimate);
712 values_.insert(values_.begin(), copy->values_.begin(), copy->values_.end()); 719 values_.insert(values_.begin(), copy->values_.begin(), copy->values_.end());
713 contexts_.reserve(copy->contexts_.size()); 720 contexts_.reserve(copy->contexts_.size());
714 contexts_.insert(contexts_.begin(), copy->contexts_.begin(), 721 contexts_.insert(contexts_.begin(), copy->contexts_.begin(),
715 copy->contexts_.end()); 722 copy->contexts_.end());
716
717 if (FLAG_analyze_environment_liveness) {
718 // Split the liveness blocks.
719 copy->liveness_block_ =
720 builder_->liveness_analyzer()->NewBlock(copy->liveness_block());
721 liveness_block_ =
722 builder_->liveness_analyzer()->NewBlock(copy->liveness_block());
723 }
724 } 723 }
725 724
726 725
727 void AstGraphBuilder::Environment::Bind(Variable* variable, Node* node) { 726 void AstGraphBuilder::Environment::Bind(Variable* variable, Node* node) {
728 DCHECK(variable->IsStackAllocated()); 727 DCHECK(variable->IsStackAllocated());
729 if (variable->IsParameter()) { 728 if (variable->IsParameter()) {
730 // The parameter indices are shifted by 1 (receiver is parameter 729 // The parameter indices are shifted by 1 (receiver is parameter
731 // index -1 but environment index 0). 730 // index -1 but environment index 0).
732 values()->at(variable->index() + 1) = node; 731 values()->at(variable->index() + 1) = node;
733 } else { 732 } else {
734 DCHECK(variable->IsStackLocal()); 733 DCHECK(variable->IsStackLocal());
735 values()->at(variable->index() + parameters_count_) = node; 734 values()->at(variable->index() + parameters_count_) = node;
736 if (FLAG_analyze_environment_liveness) { 735
736 DCHECK(IsLivenessBlockConsistent());
737 if (liveness_block() != nullptr) {
737 liveness_block()->Bind(variable->index()); 738 liveness_block()->Bind(variable->index());
738 } 739 }
739 } 740 }
740 } 741 }
741 742
742 743
743 Node* AstGraphBuilder::Environment::Lookup(Variable* variable) { 744 Node* AstGraphBuilder::Environment::Lookup(Variable* variable) {
744 DCHECK(variable->IsStackAllocated()); 745 DCHECK(variable->IsStackAllocated());
745 if (variable->IsParameter()) { 746 if (variable->IsParameter()) {
746 // The parameter indices are shifted by 1 (receiver is parameter 747 // The parameter indices are shifted by 1 (receiver is parameter
747 // index -1 but environment index 0). 748 // index -1 but environment index 0).
748 return values()->at(variable->index() + 1); 749 return values()->at(variable->index() + 1);
749 } else { 750 } else {
750 DCHECK(variable->IsStackLocal()); 751 DCHECK(variable->IsStackLocal());
751 if (FLAG_analyze_environment_liveness) { 752 DCHECK(IsLivenessBlockConsistent());
753 if (liveness_block() != nullptr) {
752 liveness_block()->Lookup(variable->index()); 754 liveness_block()->Lookup(variable->index());
753 } 755 }
754 return values()->at(variable->index() + parameters_count_); 756 return values()->at(variable->index() + parameters_count_);
755 } 757 }
756 } 758 }
757 759
758 760
759 void AstGraphBuilder::Environment::MarkAllLocalsLive() { 761 void AstGraphBuilder::Environment::MarkAllLocalsLive() {
760 if (FLAG_analyze_environment_liveness) { 762 DCHECK(IsLivenessBlockConsistent());
763 if (liveness_block() != nullptr) {
761 for (int i = 0; i < locals_count_; i++) { 764 for (int i = 0; i < locals_count_; i++) {
762 liveness_block()->Lookup(i); 765 liveness_block()->Lookup(i);
763 } 766 }
764 } 767 }
765 } 768 }
766 769
767 770
768 AstGraphBuilder::Environment* 771 AstGraphBuilder::Environment*
772 AstGraphBuilder::Environment::CopyForConditional() {
773 LivenessAnalyzerBlock* copy_liveness_block = nullptr;
774 if (liveness_block() != nullptr) {
775 copy_liveness_block =
776 builder_->liveness_analyzer()->NewBlock(liveness_block());
777 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
778 }
779 return new (zone()) Environment(this, copy_liveness_block);
780 }
781
782
783 AstGraphBuilder::Environment*
784 AstGraphBuilder::Environment::CopyAsUnreachable() {
785 Environment* env = new (zone()) Environment(this, nullptr);
786 env->MarkAsUnreachable();
787 return env;
788 }
789
790
791 AstGraphBuilder::Environment*
769 AstGraphBuilder::Environment::CopyAndShareLiveness() { 792 AstGraphBuilder::Environment::CopyAndShareLiveness() {
770 Environment* env = new (zone()) Environment(this); 793 if (liveness_block() != nullptr) {
771 if (FLAG_analyze_environment_liveness) { 794 // Finish the current liveness block before copying.
772 env->liveness_block_ = liveness_block(); 795 liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
773 } 796 }
797 Environment* env = new (zone()) Environment(this, liveness_block());
774 return env; 798 return env;
775 } 799 }
776 800
777 801
802 AstGraphBuilder::Environment* AstGraphBuilder::Environment::CopyForLoop(
803 BitVector* assigned, bool is_osr) {
804 PrepareForLoop(assigned, is_osr);
805 return CopyAndShareLiveness();
806 }
807
808
778 void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values, 809 void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values,
779 int offset, int count) { 810 int offset, int count) {
780 bool should_update = false; 811 bool should_update = false;
781 Node** env_values = (count == 0) ? nullptr : &values()->at(offset); 812 Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
782 if (*state_values == NULL || (*state_values)->InputCount() != count) { 813 if (*state_values == NULL || (*state_values)->InputCount() != count) {
783 should_update = true; 814 should_update = true;
784 } else { 815 } else {
785 DCHECK(static_cast<size_t>(offset + count) <= values()->size()); 816 DCHECK(static_cast<size_t>(offset + count) <= values()->size());
786 for (int i = 0; i < count; i++) { 817 for (int i = 0; i < count; i++) {
787 if ((*state_values)->InputAt(i) != env_values[i]) { 818 if ((*state_values)->InputAt(i) != env_values[i]) {
(...skipping 27 matching lines...) Expand all
815 UpdateStateValuesWithCache(&locals_node_, parameters_count(), locals_count()); 846 UpdateStateValuesWithCache(&locals_node_, parameters_count(), locals_count());
816 UpdateStateValues(&stack_node_, parameters_count() + locals_count(), 847 UpdateStateValues(&stack_node_, parameters_count() + locals_count(),
817 stack_height()); 848 stack_height());
818 849
819 const Operator* op = common()->FrameState(JS_FRAME, ast_id, combine); 850 const Operator* op = common()->FrameState(JS_FRAME, ast_id, combine);
820 851
821 Node* result = graph()->NewNode(op, parameters_node_, locals_node_, 852 Node* result = graph()->NewNode(op, parameters_node_, locals_node_,
822 stack_node_, builder()->current_context(), 853 stack_node_, builder()->current_context(),
823 builder()->GetFunctionClosure(), 854 builder()->GetFunctionClosure(),
824 builder()->jsgraph()->UndefinedConstant()); 855 builder()->jsgraph()->UndefinedConstant());
825 if (FLAG_analyze_environment_liveness) { 856
857 DCHECK(IsLivenessBlockConsistent());
858 if (liveness_block() != nullptr) {
826 liveness_block()->Checkpoint(result); 859 liveness_block()->Checkpoint(result);
827 } 860 }
828 return result; 861 return result;
829 } 862 }
830 863
831 864
865 bool AstGraphBuilder::Environment::IsLivenessAnalysisEnabled() {
866 return FLAG_analyze_environment_liveness &&
867 builder()->info()->is_deoptimization_enabled();
868 }
869
870
871 bool AstGraphBuilder::Environment::IsLivenessBlockConsistent() {
872 return (!IsLivenessAnalysisEnabled() || IsMarkedAsUnreachable()) ==
873 (liveness_block() == nullptr);
874 }
875
876
832 AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own, 877 AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own,
833 Expression::Context kind) 878 Expression::Context kind)
834 : kind_(kind), owner_(own), outer_(own->ast_context()) { 879 : kind_(kind), owner_(own), outer_(own->ast_context()) {
835 owner()->set_ast_context(this); // Push. 880 owner()->set_ast_context(this); // Push.
836 #ifdef DEBUG 881 #ifdef DEBUG
837 original_height_ = environment()->stack_height(); 882 original_height_ = environment()->stack_height();
838 #endif 883 #endif
839 } 884 }
840 885
841 886
(...skipping 2615 matching lines...) Expand 10 before | Expand all | Expand 10 after
3457 if (has_effect) { 3502 if (has_effect) {
3458 environment_->UpdateEffectDependency(result); 3503 environment_->UpdateEffectDependency(result);
3459 } 3504 }
3460 if (!environment()->IsMarkedAsUnreachable()) { 3505 if (!environment()->IsMarkedAsUnreachable()) {
3461 // Update the current control dependency for control-producing nodes. 3506 // Update the current control dependency for control-producing nodes.
3462 if (NodeProperties::IsControl(result)) { 3507 if (NodeProperties::IsControl(result)) {
3463 environment_->UpdateControlDependency(result); 3508 environment_->UpdateControlDependency(result);
3464 } 3509 }
3465 // Add implicit exception continuation for throwing nodes. 3510 // Add implicit exception continuation for throwing nodes.
3466 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) { 3511 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) {
3512 // Copy the environment for the success continuation.
3513 Environment* success_env = environment()->CopyForConditional();
3514
3467 Node* on_exception = graph()->NewNode(common()->IfException(), result); 3515 Node* on_exception = graph()->NewNode(common()->IfException(), result);
3468 environment_->UpdateControlDependency(on_exception); 3516 environment_->UpdateControlDependency(on_exception);
3469 execution_control()->ThrowValue(on_exception); 3517 execution_control()->ThrowValue(on_exception);
3518 set_environment(success_env);
3470 } 3519 }
3471 // Add implicit success continuation for throwing nodes. 3520 // Add implicit success continuation for throwing nodes.
3472 if (!result->op()->HasProperty(Operator::kNoThrow)) { 3521 if (!result->op()->HasProperty(Operator::kNoThrow)) {
3473 Node* on_success = graph()->NewNode(common()->IfSuccess(), result); 3522 Node* on_success = graph()->NewNode(common()->IfSuccess(), result);
3474 environment_->UpdateControlDependency(on_success); 3523 environment_->UpdateControlDependency(on_success);
3475 } 3524 }
3476 } 3525 }
3477 } 3526 }
3478 3527
3479 return result; 3528 return result;
(...skipping 15 matching lines...) Expand all
3495 DCHECK(contexts_.size() == other->contexts_.size()); 3544 DCHECK(contexts_.size() == other->contexts_.size());
3496 3545
3497 // Nothing to do if the other environment is dead. 3546 // Nothing to do if the other environment is dead.
3498 if (other->IsMarkedAsUnreachable()) return; 3547 if (other->IsMarkedAsUnreachable()) return;
3499 3548
3500 // Resurrect a dead environment by copying the contents of the other one and 3549 // Resurrect a dead environment by copying the contents of the other one and
3501 // placing a singleton merge as the new control dependency. 3550 // placing a singleton merge as the new control dependency.
3502 if (this->IsMarkedAsUnreachable()) { 3551 if (this->IsMarkedAsUnreachable()) {
3503 Node* other_control = other->control_dependency_; 3552 Node* other_control = other->control_dependency_;
3504 Node* inputs[] = {other_control}; 3553 Node* inputs[] = {other_control};
3505 liveness_block_ = other->liveness_block_;
3506 control_dependency_ = 3554 control_dependency_ =
3507 graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true); 3555 graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true);
3508 effect_dependency_ = other->effect_dependency_; 3556 effect_dependency_ = other->effect_dependency_;
3509 values_ = other->values_; 3557 values_ = other->values_;
3510 contexts_ = other->contexts_; 3558 contexts_ = other->contexts_;
3559 if (IsLivenessAnalysisEnabled()) {
3560 liveness_block_ =
3561 builder_->liveness_analyzer()->NewBlock(other->liveness_block());
3562 }
3511 return; 3563 return;
3512 } 3564 }
3513 3565
3514 // Record the merge for the local variable liveness calculation. 3566 // Record the merge for the local variable liveness calculation.
3515 // Unfortunately, we have to mirror the logic in the MergeControl method: 3567 // For loops, we are connecting a back edge into the existing block;
3516 // connect before merge or loop, or create a new merge otherwise. 3568 // for merges, we create a new merged block.
3517 if (FLAG_analyze_environment_liveness) { 3569 if (IsLivenessAnalysisEnabled()) {
3518 if (GetControlDependency()->opcode() != IrOpcode::kLoop && 3570 if (GetControlDependency()->opcode() != IrOpcode::kLoop) {
3519 GetControlDependency()->opcode() != IrOpcode::kMerge) {
3520 liveness_block_ = 3571 liveness_block_ =
3521 builder_->liveness_analyzer()->NewBlock(liveness_block()); 3572 builder_->liveness_analyzer()->NewBlock(liveness_block());
3522 } 3573 }
3523 liveness_block()->AddPredecessor(other->liveness_block()); 3574 liveness_block()->AddPredecessor(other->liveness_block());
3524 } 3575 }
3525 3576
3526 // Create a merge of the control dependencies of both environments and update 3577 // Create a merge of the control dependencies of both environments and update
3527 // the current environment's control dependency accordingly. 3578 // the current environment's control dependency accordingly.
3528 Node* control = builder_->MergeControl(this->GetControlDependency(), 3579 Node* control = builder_->MergeControl(this->GetControlDependency(),
3529 other->GetControlDependency()); 3580 other->GetControlDependency());
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
3686 // Phi does not exist yet, introduce one. 3737 // Phi does not exist yet, introduce one.
3687 value = NewPhi(inputs, value, control); 3738 value = NewPhi(inputs, value, control);
3688 value->ReplaceInput(inputs - 1, other); 3739 value->ReplaceInput(inputs - 1, other);
3689 } 3740 }
3690 return value; 3741 return value;
3691 } 3742 }
3692 3743
3693 } // namespace compiler 3744 } // namespace compiler
3694 } // namespace internal 3745 } // namespace internal
3695 } // namespace v8 3746 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/ast-graph-builder.h ('k') | test/mjsunit/compiler/regress-variable-liveness.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698