OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 void HBasicBlock::Finish(HControlInstruction* end) { | 176 void HBasicBlock::Finish(HControlInstruction* end) { |
177 ASSERT(!IsFinished()); | 177 ASSERT(!IsFinished()); |
178 AddInstruction(end); | 178 AddInstruction(end); |
179 end_ = end; | 179 end_ = end; |
180 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { | 180 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { |
181 it.Current()->RegisterPredecessor(this); | 181 it.Current()->RegisterPredecessor(this); |
182 } | 182 } |
183 } | 183 } |
184 | 184 |
185 | 185 |
186 void HBasicBlock::Goto(HBasicBlock* block, FunctionState* state) { | 186 void HBasicBlock::Goto(HBasicBlock* block, |
| 187 FunctionState* state, |
| 188 bool add_simulate) { |
187 bool drop_extra = state != NULL && | 189 bool drop_extra = state != NULL && |
188 state->inlining_kind() == DROP_EXTRA_ON_RETURN; | 190 state->inlining_kind() == DROP_EXTRA_ON_RETURN; |
189 | 191 |
190 if (block->IsInlineReturnTarget()) { | 192 if (block->IsInlineReturnTarget()) { |
191 AddInstruction(new(zone()) HLeaveInlined()); | 193 AddInstruction(new(zone()) HLeaveInlined()); |
192 last_environment_ = last_environment()->DiscardInlined(drop_extra); | 194 last_environment_ = last_environment()->DiscardInlined(drop_extra); |
193 } | 195 } |
194 | 196 |
195 AddSimulate(BailoutId::None()); | 197 if (add_simulate) AddSimulate(BailoutId::None()); |
196 HGoto* instr = new(zone()) HGoto(block); | 198 HGoto* instr = new(zone()) HGoto(block); |
197 Finish(instr); | 199 Finish(instr); |
198 } | 200 } |
199 | 201 |
200 | 202 |
201 void HBasicBlock::AddLeaveInlined(HValue* return_value, | 203 void HBasicBlock::AddLeaveInlined(HValue* return_value, |
202 FunctionState* state) { | 204 FunctionState* state) { |
203 HBasicBlock* target = state->function_return(); | 205 HBasicBlock* target = state->function_return(); |
204 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN; | 206 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN; |
205 | 207 |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
633 } | 635 } |
634 | 636 |
635 | 637 |
636 DEFINE_GET_CONSTANT(True, true, HType::Boolean(), true) | 638 DEFINE_GET_CONSTANT(True, true, HType::Boolean(), true) |
637 DEFINE_GET_CONSTANT(False, false, HType::Boolean(), false) | 639 DEFINE_GET_CONSTANT(False, false, HType::Boolean(), false) |
638 DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false) | 640 DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false) |
639 | 641 |
640 #undef DEFINE_GET_CONSTANT | 642 #undef DEFINE_GET_CONSTANT |
641 | 643 |
642 | 644 |
643 HGraphBuilder::CheckBuilder::CheckBuilder(HGraphBuilder* builder, BailoutId id) | 645 HGraphBuilder::CheckBuilder::CheckBuilder(HGraphBuilder* builder) |
644 : builder_(builder), | 646 : builder_(builder), |
645 finished_(false), | 647 finished_(false) { |
646 id_(id) { | |
647 HEnvironment* env = builder->environment(); | 648 HEnvironment* env = builder->environment(); |
648 failure_block_ = builder->CreateBasicBlock(env->CopyWithoutHistory()); | 649 failure_block_ = builder->CreateBasicBlock(env->Copy()); |
649 merge_block_ = builder->CreateBasicBlock(env->CopyWithoutHistory()); | 650 merge_block_ = builder->CreateBasicBlock(env->Copy()); |
650 } | 651 } |
651 | 652 |
652 | 653 |
653 HValue* HGraphBuilder::CheckBuilder::CheckNotUndefined(HValue* value) { | 654 HValue* HGraphBuilder::CheckBuilder::CheckNotUndefined(HValue* value) { |
654 HEnvironment* env = builder_->environment(); | 655 HEnvironment* env = builder_->environment(); |
655 HIsNilAndBranch* compare = | 656 HCompareObjectEqAndBranch* compare = |
656 new(zone()) HIsNilAndBranch(value, kStrictEquality, kUndefinedValue); | 657 new(zone()) HCompareObjectEqAndBranch( |
657 HBasicBlock* success_block = | 658 value, |
658 builder_->CreateBasicBlock(env->CopyWithoutHistory()); | 659 builder_->graph()->GetConstantUndefined()); |
659 HBasicBlock* failure_block = | 660 HBasicBlock* success_block = builder_->CreateBasicBlock(env->Copy()); |
660 builder_->CreateBasicBlock(env->CopyWithoutHistory()); | 661 HBasicBlock* failure_block = builder_->CreateBasicBlock(env->Copy()); |
661 compare->SetSuccessorAt(0, failure_block); | 662 compare->SetSuccessorAt(0, failure_block); |
662 compare->SetSuccessorAt(1, success_block); | 663 compare->SetSuccessorAt(1, success_block); |
663 failure_block->Goto(failure_block_); | 664 failure_block->GotoNoSimulate(failure_block_); |
664 builder_->current_block()->Finish(compare); | 665 builder_->current_block()->Finish(compare); |
665 builder_->set_current_block(success_block); | 666 builder_->set_current_block(success_block); |
666 return compare; | 667 return compare; |
667 } | 668 } |
668 | 669 |
669 | 670 |
670 HValue* HGraphBuilder::CheckBuilder::CheckIntegerCompare(HValue* left, | 671 HValue* HGraphBuilder::CheckBuilder::CheckIntegerCompare(HValue* left, |
671 HValue* right, | 672 HValue* right, |
672 Token::Value op) { | 673 Token::Value op) { |
673 HEnvironment* env = builder_->environment(); | 674 HEnvironment* env = builder_->environment(); |
674 HCompareIDAndBranch* compare = | 675 HCompareIDAndBranch* compare = |
675 new(zone()) HCompareIDAndBranch(left, right, op); | 676 new(zone()) HCompareIDAndBranch(left, right, op); |
676 compare->AssumeRepresentation(Representation::Integer32()); | 677 compare->AssumeRepresentation(Representation::Integer32()); |
677 HBasicBlock* success_block = | 678 HBasicBlock* success_block = builder_->CreateBasicBlock(env->Copy()); |
678 builder_->CreateBasicBlock(env->CopyWithoutHistory()); | 679 HBasicBlock* failure_block = builder_->CreateBasicBlock(env->Copy()); |
679 HBasicBlock* failure_block = | |
680 builder_->CreateBasicBlock(env->CopyWithoutHistory()); | |
681 compare->SetSuccessorAt(0, success_block); | 680 compare->SetSuccessorAt(0, success_block); |
682 compare->SetSuccessorAt(1, failure_block); | 681 compare->SetSuccessorAt(1, failure_block); |
683 failure_block->Goto(failure_block_); | 682 failure_block->GotoNoSimulate(failure_block_); |
684 builder_->current_block()->Finish(compare); | 683 builder_->current_block()->Finish(compare); |
685 builder_->set_current_block(success_block); | 684 builder_->set_current_block(success_block); |
686 return compare; | 685 return compare; |
687 } | 686 } |
688 | 687 |
689 | 688 |
690 HValue* HGraphBuilder::CheckBuilder::CheckIntegerEq(HValue* left, | 689 HValue* HGraphBuilder::CheckBuilder::CheckIntegerEq(HValue* left, |
691 HValue* right) { | 690 HValue* right) { |
692 return CheckIntegerCompare(left, right, Token::EQ); | 691 return CheckIntegerCompare(left, right, Token::EQ); |
693 } | 692 } |
694 | 693 |
695 | 694 |
696 void HGraphBuilder::CheckBuilder::End() { | 695 void HGraphBuilder::CheckBuilder::End() { |
697 ASSERT(!finished_); | 696 ASSERT(!finished_); |
698 builder_->current_block()->Goto(merge_block_); | 697 builder_->current_block()->GotoNoSimulate(merge_block_); |
699 failure_block_->FinishExitWithDeoptimization(HDeoptimize::kUseAll); | 698 if (failure_block_->HasPredecessor()) { |
700 failure_block_->SetJoinId(id_); | 699 failure_block_->FinishExitWithDeoptimization(HDeoptimize::kUseAll); |
| 700 } |
701 builder_->set_current_block(merge_block_); | 701 builder_->set_current_block(merge_block_); |
702 merge_block_->SetJoinId(id_); | |
703 finished_ = true; | 702 finished_ = true; |
704 } | 703 } |
705 | 704 |
706 | 705 |
707 HConstant* HGraph::GetInvalidContext() { | 706 HConstant* HGraph::GetInvalidContext() { |
708 return GetConstantInt32(&constant_invalid_context_, 0xFFFFC0C7); | 707 return GetConstantInt32(&constant_invalid_context_, 0xFFFFC0C7); |
709 } | 708 } |
710 | 709 |
711 | 710 |
712 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, BailoutId id) | 711 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, int position) |
713 : builder_(builder), | 712 : builder_(builder), |
| 713 position_(position), |
714 finished_(false), | 714 finished_(false), |
| 715 did_then_(false), |
715 did_else_(false), | 716 did_else_(false), |
716 id_(id) { | 717 deopt_then_(false), |
| 718 deopt_else_(false), |
| 719 did_and_(false), |
| 720 did_or_(false), |
| 721 captured_(false), |
| 722 needs_compare_(true), |
| 723 split_edge_merge_block_(NULL) { |
717 HEnvironment* env = builder->environment(); | 724 HEnvironment* env = builder->environment(); |
718 first_true_block_ = builder->CreateBasicBlock(env->Copy()); | 725 first_true_block_ = builder->CreateBasicBlock(env->Copy()); |
719 last_true_block_ = NULL; | 726 last_true_block_ = NULL; |
720 first_false_block_ = builder->CreateBasicBlock(env->Copy()); | 727 first_false_block_ = builder->CreateBasicBlock(env->Copy()); |
721 } | 728 } |
722 | 729 |
723 | 730 |
724 HInstruction* HGraphBuilder::IfBuilder::BeginIf( | 731 HGraphBuilder::IfBuilder::IfBuilder( |
| 732 HGraphBuilder* builder, |
| 733 HIfContinuation* continuation) |
| 734 : builder_(builder), |
| 735 position_(RelocInfo::kNoPosition), |
| 736 finished_(false), |
| 737 did_then_(false), |
| 738 did_else_(false), |
| 739 deopt_then_(false), |
| 740 deopt_else_(false), |
| 741 did_and_(false), |
| 742 did_or_(false), |
| 743 captured_(false), |
| 744 needs_compare_(false), |
| 745 first_true_block_(NULL), |
| 746 first_false_block_(NULL), |
| 747 split_edge_merge_block_(NULL), |
| 748 merge_block_(NULL) { |
| 749 continuation->Continue(&first_true_block_, |
| 750 &first_false_block_, |
| 751 &position_); |
| 752 } |
| 753 |
| 754 |
| 755 HInstruction* HGraphBuilder::IfBuilder::IfCompare( |
725 HValue* left, | 756 HValue* left, |
726 HValue* right, | 757 HValue* right, |
727 Token::Value token, | 758 Token::Value token, |
728 Representation input_representation) { | 759 Representation input_representation) { |
729 HCompareIDAndBranch* compare = | 760 HCompareIDAndBranch* compare = |
730 new(zone()) HCompareIDAndBranch(left, right, token); | 761 new(zone()) HCompareIDAndBranch(left, right, token); |
731 compare->set_observed_input_representation(input_representation, | 762 compare->set_observed_input_representation(input_representation, |
732 input_representation); | 763 input_representation); |
733 compare->ChangeRepresentation(input_representation); | 764 compare->ChangeRepresentation(input_representation); |
734 compare->SetSuccessorAt(0, first_true_block_); | 765 AddCompare(compare); |
735 compare->SetSuccessorAt(1, first_false_block_); | |
736 builder_->current_block()->Finish(compare); | |
737 builder_->set_current_block(first_true_block_); | |
738 return compare; | 766 return compare; |
739 } | 767 } |
740 | 768 |
741 | 769 |
742 HInstruction* HGraphBuilder::IfBuilder::BeginIfObjectsEqual( | 770 HInstruction* HGraphBuilder::IfBuilder::IfCompareMap(HValue* left, |
743 HValue* left, | 771 Handle<Map> map) { |
744 HValue* right) { | 772 HCompareMap* compare = |
745 HCompareObjectEqAndBranch* compare = | 773 new(zone()) HCompareMap(left, map, |
746 new(zone()) HCompareObjectEqAndBranch(left, right); | 774 first_true_block_, first_false_block_); |
747 compare->SetSuccessorAt(0, first_true_block_); | 775 AddCompare(compare); |
748 compare->SetSuccessorAt(1, first_false_block_); | |
749 builder_->current_block()->Finish(compare); | |
750 builder_->set_current_block(first_true_block_); | |
751 return compare; | 776 return compare; |
752 } | 777 } |
753 | 778 |
754 | 779 |
755 HInstruction* HGraphBuilder::IfBuilder::BeginIfMapEquals(HValue* value, | 780 void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) { |
756 Handle<Map> map) { | 781 if (split_edge_merge_block_ != NULL) { |
757 HCompareMap* compare = new(zone()) | 782 HEnvironment* env = first_false_block_->last_environment(); |
758 HCompareMap(value, map, first_true_block_, first_false_block_); | 783 HBasicBlock* split_edge = |
| 784 builder_->CreateBasicBlock(env->Copy()); |
| 785 if (did_or_) { |
| 786 compare->SetSuccessorAt(0, split_edge); |
| 787 compare->SetSuccessorAt(1, first_false_block_); |
| 788 } else { |
| 789 compare->SetSuccessorAt(0, first_true_block_); |
| 790 compare->SetSuccessorAt(1, split_edge); |
| 791 } |
| 792 split_edge->GotoNoSimulate(split_edge_merge_block_); |
| 793 } else { |
| 794 compare->SetSuccessorAt(0, first_true_block_); |
| 795 compare->SetSuccessorAt(1, first_false_block_); |
| 796 } |
759 builder_->current_block()->Finish(compare); | 797 builder_->current_block()->Finish(compare); |
760 builder_->set_current_block(first_true_block_); | 798 needs_compare_ = false; |
761 return compare; | |
762 } | 799 } |
763 | 800 |
764 | 801 |
765 void HGraphBuilder::IfBuilder::BeginElse() { | 802 void HGraphBuilder::IfBuilder::Or() { |
| 803 ASSERT(!did_and_); |
| 804 did_or_ = true; |
| 805 HEnvironment* env = first_false_block_->last_environment(); |
| 806 if (split_edge_merge_block_ == NULL) { |
| 807 split_edge_merge_block_ = |
| 808 builder_->CreateBasicBlock(env->Copy()); |
| 809 first_true_block_->GotoNoSimulate(split_edge_merge_block_); |
| 810 first_true_block_ = split_edge_merge_block_; |
| 811 } |
| 812 builder_->set_current_block(first_false_block_); |
| 813 first_false_block_ = builder_->CreateBasicBlock(env->Copy()); |
| 814 } |
| 815 |
| 816 |
| 817 void HGraphBuilder::IfBuilder::And() { |
| 818 ASSERT(!did_or_); |
| 819 did_and_ = true; |
| 820 HEnvironment* env = first_false_block_->last_environment(); |
| 821 if (split_edge_merge_block_ == NULL) { |
| 822 split_edge_merge_block_ = builder_->CreateBasicBlock(env->Copy()); |
| 823 first_false_block_->GotoNoSimulate(split_edge_merge_block_); |
| 824 first_false_block_ = split_edge_merge_block_; |
| 825 } |
| 826 builder_->set_current_block(first_true_block_); |
| 827 first_true_block_ = builder_->CreateBasicBlock(env->Copy()); |
| 828 } |
| 829 |
| 830 |
| 831 void HGraphBuilder::IfBuilder::CaptureContinuation( |
| 832 HIfContinuation* continuation) { |
| 833 ASSERT(!finished_); |
| 834 ASSERT(!captured_); |
| 835 HBasicBlock* true_block = last_true_block_ == NULL |
| 836 ? first_true_block_ |
| 837 : last_true_block_; |
| 838 HBasicBlock* false_block = |
| 839 did_else_ ? builder_->current_block() : first_false_block_; |
| 840 continuation->Capture(true_block, false_block, position_); |
| 841 captured_ = true; |
| 842 End(); |
| 843 } |
| 844 |
| 845 |
| 846 void HGraphBuilder::IfBuilder::Then() { |
| 847 ASSERT(!captured_); |
| 848 ASSERT(!finished_); |
| 849 did_then_ = true; |
| 850 if (needs_compare_) { |
| 851 // Handle if's without any expressions, they jump directly to the "else" |
| 852 // branch. |
| 853 builder_->current_block()->GotoNoSimulate(first_false_block_); |
| 854 first_true_block_ = NULL; |
| 855 } |
| 856 builder_->set_current_block(first_true_block_); |
| 857 } |
| 858 |
| 859 |
| 860 void HGraphBuilder::IfBuilder::Else() { |
| 861 ASSERT(did_then_); |
| 862 ASSERT(!captured_); |
| 863 ASSERT(!finished_); |
766 last_true_block_ = builder_->current_block(); | 864 last_true_block_ = builder_->current_block(); |
767 ASSERT(!last_true_block_->IsFinished()); | 865 ASSERT(first_true_block_ == NULL || !last_true_block_->IsFinished()); |
768 builder_->set_current_block(first_false_block_); | 866 builder_->set_current_block(first_false_block_); |
769 did_else_ = true; | 867 did_else_ = true; |
770 } | 868 } |
771 | 869 |
772 | 870 |
| 871 void HGraphBuilder::IfBuilder::Deopt() { |
| 872 ASSERT(!(did_then_ ^ did_else_)); |
| 873 HBasicBlock* block = builder_->current_block(); |
| 874 block->FinishExitWithDeoptimization(HDeoptimize::kUseAll); |
| 875 if (did_else_) { |
| 876 first_false_block_ = NULL; |
| 877 did_else_ = false; |
| 878 } else { |
| 879 first_true_block_ = NULL; |
| 880 } |
| 881 } |
| 882 |
| 883 |
773 void HGraphBuilder::IfBuilder::End() { | 884 void HGraphBuilder::IfBuilder::End() { |
774 ASSERT(!finished_); | 885 if (!captured_) { |
775 if (!did_else_) BeginElse(); | 886 ASSERT(did_then_); |
776 ASSERT(!last_true_block_->IsFinished()); | 887 if (!did_else_) { |
777 HBasicBlock* last_false_block = builder_->current_block(); | 888 last_true_block_ = builder_->current_block(); |
778 ASSERT(!last_false_block->IsFinished()); | 889 } |
779 HEnvironment* merge_env = | 890 if (first_true_block_ == NULL) { |
780 last_true_block_->last_environment()->CopyWithoutHistory(); | 891 // Deopt on true. Nothing to do, just continue the else block. |
781 merge_block_ = builder_->CreateBasicBlock(merge_env); | 892 } else if (first_false_block_ == NULL) { |
782 last_true_block_->Goto(merge_block_); | 893 builder_->set_current_block(last_true_block_); |
783 last_false_block->Goto(merge_block_); | 894 } else { |
784 merge_block_->SetJoinId(id_); | 895 HEnvironment* merge_env = last_true_block_->last_environment()->Copy(); |
785 builder_->set_current_block(merge_block_); | 896 merge_block_ = builder_->CreateBasicBlock(merge_env); |
| 897 ASSERT(!finished_); |
| 898 if (!did_else_) Else(); |
| 899 ASSERT(!last_true_block_->IsFinished()); |
| 900 HBasicBlock* last_false_block = builder_->current_block(); |
| 901 ASSERT(!last_false_block->IsFinished()); |
| 902 last_true_block_->GotoNoSimulate(merge_block_); |
| 903 last_false_block->GotoNoSimulate(merge_block_); |
| 904 builder_->set_current_block(merge_block_); |
| 905 } |
| 906 } |
786 finished_ = true; | 907 finished_ = true; |
787 } | 908 } |
788 | 909 |
789 | 910 |
790 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, | 911 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, |
791 HValue* context, | 912 HValue* context, |
792 LoopBuilder::Direction direction, | 913 LoopBuilder::Direction direction) |
793 BailoutId id) | |
794 : builder_(builder), | 914 : builder_(builder), |
795 context_(context), | 915 context_(context), |
796 direction_(direction), | 916 direction_(direction), |
797 id_(id), | |
798 finished_(false) { | 917 finished_(false) { |
799 header_block_ = builder->CreateLoopHeaderBlock(); | 918 header_block_ = builder->CreateLoopHeaderBlock(); |
800 body_block_ = NULL; | 919 body_block_ = NULL; |
801 exit_block_ = NULL; | 920 exit_block_ = NULL; |
802 } | 921 } |
803 | 922 |
804 | 923 |
805 HValue* HGraphBuilder::LoopBuilder::BeginBody( | 924 HValue* HGraphBuilder::LoopBuilder::BeginBody( |
806 HValue* initial, | 925 HValue* initial, |
807 HValue* terminating, | 926 HValue* terminating, |
808 Token::Value token, | 927 Token::Value token, |
809 Representation input_representation) { | 928 Representation input_representation) { |
810 HEnvironment* env = builder_->environment(); | 929 HEnvironment* env = builder_->environment(); |
811 phi_ = new(zone()) HPhi(env->values()->length(), zone()); | 930 phi_ = new(zone()) HPhi(env->values()->length(), zone()); |
812 header_block_->AddPhi(phi_); | 931 header_block_->AddPhi(phi_); |
813 phi_->AddInput(initial); | 932 phi_->AddInput(initial); |
814 phi_->ChangeRepresentation(Representation::Integer32()); | 933 phi_->ChangeRepresentation(Representation::Integer32()); |
815 env->Push(initial); | 934 env->Push(initial); |
816 builder_->current_block()->Goto(header_block_); | 935 builder_->current_block()->GotoNoSimulate(header_block_); |
817 | 936 |
818 HEnvironment* body_env = env->Copy(); | 937 HEnvironment* body_env = env->Copy(); |
819 HEnvironment* exit_env = env->Copy(); | 938 HEnvironment* exit_env = env->Copy(); |
820 body_block_ = builder_->CreateBasicBlock(body_env); | 939 body_block_ = builder_->CreateBasicBlock(body_env); |
821 exit_block_ = builder_->CreateBasicBlock(exit_env); | 940 exit_block_ = builder_->CreateBasicBlock(exit_env); |
822 // Remove the phi from the expression stack | 941 // Remove the phi from the expression stack |
823 body_env->Pop(); | 942 body_env->Pop(); |
824 | 943 |
825 builder_->set_current_block(header_block_); | 944 builder_->set_current_block(header_block_); |
826 HCompareIDAndBranch* compare = | 945 HCompareIDAndBranch* compare = |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
860 } else { | 979 } else { |
861 increment_ = HSub::New(zone(), context_, phi_, one); | 980 increment_ = HSub::New(zone(), context_, phi_, one); |
862 } | 981 } |
863 increment_->ClearFlag(HValue::kCanOverflow); | 982 increment_->ClearFlag(HValue::kCanOverflow); |
864 increment_->ChangeRepresentation(Representation::Integer32()); | 983 increment_->ChangeRepresentation(Representation::Integer32()); |
865 builder_->AddInstruction(increment_); | 984 builder_->AddInstruction(increment_); |
866 } | 985 } |
867 | 986 |
868 // Push the new increment value on the expression stack to merge into the phi. | 987 // Push the new increment value on the expression stack to merge into the phi. |
869 builder_->environment()->Push(increment_); | 988 builder_->environment()->Push(increment_); |
870 builder_->current_block()->Goto(header_block_); | 989 builder_->current_block()->GotoNoSimulate(header_block_); |
871 header_block_->loop_information()->RegisterBackEdge(body_block_); | 990 header_block_->loop_information()->RegisterBackEdge(body_block_); |
872 header_block_->SetJoinId(id_); | |
873 | 991 |
874 builder_->set_current_block(exit_block_); | 992 builder_->set_current_block(exit_block_); |
875 // Pop the phi from the expression stack | 993 // Pop the phi from the expression stack |
876 builder_->environment()->Pop(); | 994 builder_->environment()->Pop(); |
877 finished_ = true; | 995 finished_ = true; |
878 } | 996 } |
879 | 997 |
880 | 998 |
881 HGraph* HGraphBuilder::CreateGraph() { | 999 HGraph* HGraphBuilder::CreateGraph() { |
882 graph_ = new(zone()) HGraph(info_); | 1000 graph_ = new(zone()) HGraph(info_); |
(...skipping 14 matching lines...) Expand all Loading... |
897 } | 1015 } |
898 return instr; | 1016 return instr; |
899 } | 1017 } |
900 | 1018 |
901 | 1019 |
902 void HGraphBuilder::AddSimulate(BailoutId id, | 1020 void HGraphBuilder::AddSimulate(BailoutId id, |
903 RemovableSimulate removable) { | 1021 RemovableSimulate removable) { |
904 ASSERT(current_block() != NULL); | 1022 ASSERT(current_block() != NULL); |
905 ASSERT(no_side_effects_scope_count_ == 0); | 1023 ASSERT(no_side_effects_scope_count_ == 0); |
906 current_block()->AddSimulate(id, removable); | 1024 current_block()->AddSimulate(id, removable); |
907 environment()->set_ast_id(id); | |
908 } | 1025 } |
909 | 1026 |
910 | 1027 |
911 HBoundsCheck* HGraphBuilder::AddBoundsCheck(HValue* index, | 1028 HBoundsCheck* HGraphBuilder::AddBoundsCheck(HValue* index, |
912 HValue* length, | 1029 HValue* length, |
913 BoundsCheckKeyMode key_mode, | 1030 BoundsCheckKeyMode key_mode, |
914 Representation r) { | 1031 Representation r) { |
915 if (!index->type().IsSmi()) { | 1032 if (!index->type().IsSmi()) { |
916 index = new(graph()->zone()) HCheckSmiOrInt32(index); | 1033 index = new(graph()->zone()) HCheckSmiOrInt32(index); |
917 AddInstruction(HCheckSmiOrInt32::cast(index)); | 1034 AddInstruction(HCheckSmiOrInt32::cast(index)); |
(...skipping 30 matching lines...) Expand all Loading... |
948 | 1065 |
949 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { | 1066 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { |
950 HBasicBlock* header = graph()->CreateBasicBlock(); | 1067 HBasicBlock* header = graph()->CreateBasicBlock(); |
951 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); | 1068 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); |
952 header->SetInitialEnvironment(entry_env); | 1069 header->SetInitialEnvironment(entry_env); |
953 header->AttachLoopInformation(); | 1070 header->AttachLoopInformation(); |
954 return header; | 1071 return header; |
955 } | 1072 } |
956 | 1073 |
957 | 1074 |
| 1075 HValue* HGraphBuilder::BuildCheckNonSmi(HValue* obj) { |
| 1076 HCheckNonSmi* check = new(zone()) HCheckNonSmi(obj); |
| 1077 AddInstruction(check); |
| 1078 return check; |
| 1079 } |
| 1080 |
| 1081 |
| 1082 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, |
| 1083 Handle<Map> map) { |
| 1084 HCheckMaps* check = new(zone()) HCheckMaps(obj, map, zone()); |
| 1085 AddInstruction(check); |
| 1086 return check; |
| 1087 } |
| 1088 |
| 1089 |
958 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess( | 1090 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess( |
959 HValue* external_elements, | 1091 HValue* external_elements, |
960 HValue* checked_key, | 1092 HValue* checked_key, |
961 HValue* val, | 1093 HValue* val, |
962 HValue* dependency, | 1094 HValue* dependency, |
963 ElementsKind elements_kind, | 1095 ElementsKind elements_kind, |
964 bool is_store) { | 1096 bool is_store) { |
965 Zone* zone = this->zone(); | 1097 Zone* zone = this->zone(); |
966 if (is_store) { | 1098 if (is_store) { |
967 ASSERT(val != NULL); | 1099 ASSERT(val != NULL); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1042 elements_kind); | 1174 elements_kind); |
1043 } | 1175 } |
1044 | 1176 |
1045 | 1177 |
1046 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, | 1178 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, |
1047 HValue* elements, | 1179 HValue* elements, |
1048 ElementsKind kind, | 1180 ElementsKind kind, |
1049 HValue* length, | 1181 HValue* length, |
1050 HValue* key, | 1182 HValue* key, |
1051 bool is_js_array) { | 1183 bool is_js_array) { |
1052 BailoutId ast_id = environment()->ast_id(); | |
1053 Zone* zone = this->zone(); | 1184 Zone* zone = this->zone(); |
1054 IfBuilder length_checker(this, ast_id); | 1185 IfBuilder length_checker(this); |
1055 | 1186 |
1056 length_checker.BeginIf(length, key, Token::EQ); | 1187 length_checker.IfCompare(length, key, Token::EQ); |
| 1188 length_checker.Then(); |
1057 | 1189 |
1058 HValue* current_capacity = | 1190 HValue* current_capacity = |
1059 AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | 1191 AddInstruction(new(zone) HFixedArrayBaseLength(elements)); |
1060 | 1192 |
1061 IfBuilder capacity_checker(this, ast_id); | 1193 IfBuilder capacity_checker(this); |
1062 | 1194 |
1063 capacity_checker.BeginIf(length, current_capacity, Token::EQ); | 1195 capacity_checker.IfCompare(length, current_capacity, Token::EQ); |
| 1196 capacity_checker.Then(); |
1064 | 1197 |
1065 HValue* context = environment()->LookupContext(); | 1198 HValue* context = environment()->LookupContext(); |
1066 | 1199 |
1067 HValue* new_capacity = | 1200 HValue* new_capacity = |
1068 BuildNewElementsCapacity(context, current_capacity); | 1201 BuildNewElementsCapacity(context, current_capacity); |
1069 | 1202 |
1070 HValue* new_elements = BuildGrowElementsCapacity(object, elements, | 1203 HValue* new_elements = BuildGrowElementsCapacity(object, elements, |
1071 kind, length, | 1204 kind, length, |
1072 new_capacity, ast_id); | 1205 new_capacity); |
1073 | 1206 |
1074 environment()->Push(new_elements); | 1207 environment()->Push(new_elements); |
1075 capacity_checker.BeginElse(); | 1208 capacity_checker.Else(); |
1076 | 1209 |
1077 environment()->Push(elements); | 1210 environment()->Push(elements); |
1078 capacity_checker.End(); | 1211 capacity_checker.End(); |
1079 | 1212 |
1080 if (is_js_array) { | 1213 if (is_js_array) { |
1081 HValue* new_length = AddInstruction( | 1214 HValue* new_length = AddInstruction( |
1082 HAdd::New(zone, context, length, graph_->GetConstant1())); | 1215 HAdd::New(zone, context, length, graph_->GetConstant1())); |
1083 new_length->ChangeRepresentation(Representation::Integer32()); | 1216 new_length->ChangeRepresentation(Representation::Integer32()); |
1084 new_length->ClearFlag(HValue::kCanOverflow); | 1217 new_length->ClearFlag(HValue::kCanOverflow); |
1085 | 1218 |
1086 Factory* factory = isolate()->factory(); | 1219 Factory* factory = isolate()->factory(); |
1087 HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField( | 1220 HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField( |
1088 object, | 1221 object, |
1089 factory->length_field_string(), | 1222 factory->length_field_string(), |
1090 new_length, true, | 1223 new_length, true, |
1091 JSArray::kLengthOffset)); | 1224 JSArray::kLengthOffset)); |
1092 length_store->SetGVNFlag(kChangesArrayLengths); | 1225 length_store->SetGVNFlag(kChangesArrayLengths); |
1093 } | 1226 } |
1094 | 1227 |
1095 length_checker.BeginElse(); | 1228 length_checker.Else(); |
1096 | 1229 |
1097 AddBoundsCheck(key, length, ALLOW_SMI_KEY); | 1230 AddBoundsCheck(key, length, ALLOW_SMI_KEY); |
1098 environment()->Push(elements); | 1231 environment()->Push(elements); |
1099 | 1232 |
1100 length_checker.End(); | 1233 length_checker.End(); |
1101 | 1234 |
1102 return environment()->Pop(); | 1235 return environment()->Pop(); |
1103 } | 1236 } |
1104 | 1237 |
1105 | 1238 |
1106 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object, | 1239 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object, |
1107 HValue* elements, | 1240 HValue* elements, |
1108 ElementsKind kind, | 1241 ElementsKind kind, |
1109 HValue* length) { | 1242 HValue* length) { |
1110 BailoutId ast_id = environment()->ast_id(); | |
1111 Zone* zone = this->zone(); | 1243 Zone* zone = this->zone(); |
1112 Heap* heap = isolate()->heap(); | 1244 Heap* heap = isolate()->heap(); |
1113 | 1245 |
1114 IfBuilder cow_checker(this, ast_id); | 1246 IfBuilder cow_checker(this); |
1115 | 1247 |
1116 cow_checker.BeginIfMapEquals(elements, | 1248 cow_checker.IfCompareMap(elements, |
1117 Handle<Map>(heap->fixed_cow_array_map())); | 1249 Handle<Map>(heap->fixed_cow_array_map())); |
| 1250 cow_checker.Then(); |
1118 | 1251 |
1119 HValue* capacity = | 1252 HValue* capacity = |
1120 AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | 1253 AddInstruction(new(zone) HFixedArrayBaseLength(elements)); |
1121 | 1254 |
1122 HValue* new_elements = BuildGrowElementsCapacity(object, elements, | 1255 HValue* new_elements = BuildGrowElementsCapacity(object, elements, |
1123 kind, length, | 1256 kind, length, capacity); |
1124 capacity, ast_id); | |
1125 | 1257 |
1126 environment()->Push(new_elements); | 1258 environment()->Push(new_elements); |
1127 | 1259 |
1128 cow_checker.BeginElse(); | 1260 cow_checker.Else(); |
1129 | 1261 |
1130 environment()->Push(elements); | 1262 environment()->Push(elements); |
1131 | 1263 |
1132 cow_checker.End(); | 1264 cow_checker.End(); |
1133 | 1265 |
1134 return environment()->Pop(); | 1266 return environment()->Pop(); |
1135 } | 1267 } |
1136 | 1268 |
1137 | 1269 |
1138 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 1270 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1173 HInstruction* length = NULL; | 1305 HInstruction* length = NULL; |
1174 if (is_js_array) { | 1306 if (is_js_array) { |
1175 length = AddInstruction( | 1307 length = AddInstruction( |
1176 HLoadNamedField::NewArrayLength(zone, object, mapcheck, HType::Smi())); | 1308 HLoadNamedField::NewArrayLength(zone, object, mapcheck, HType::Smi())); |
1177 } else { | 1309 } else { |
1178 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | 1310 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); |
1179 } | 1311 } |
1180 HValue* checked_key = NULL; | 1312 HValue* checked_key = NULL; |
1181 if (IsExternalArrayElementsKind(elements_kind)) { | 1313 if (IsExternalArrayElementsKind(elements_kind)) { |
1182 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 1314 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
| 1315 NoObservableSideEffectsScope no_effects(this); |
1183 HLoadExternalArrayPointer* external_elements = | 1316 HLoadExternalArrayPointer* external_elements = |
1184 new(zone) HLoadExternalArrayPointer(elements); | 1317 new(zone) HLoadExternalArrayPointer(elements); |
1185 AddInstruction(external_elements); | 1318 AddInstruction(external_elements); |
1186 BailoutId previous_id = environment()->ast_id(); | 1319 IfBuilder length_checker(this); |
1187 ASSERT(!previous_id.IsNone()); | 1320 length_checker.IfCompare(key, length, Token::LT); |
1188 IfBuilder length_checker(this, previous_id); | 1321 length_checker.Then(); |
1189 length_checker.BeginIf(key, length, Token::LT); | 1322 CheckBuilder negative_checker(this); |
1190 CheckBuilder negative_checker(this, previous_id); | |
1191 HValue* bounds_check = negative_checker.CheckIntegerCompare( | 1323 HValue* bounds_check = negative_checker.CheckIntegerCompare( |
1192 key, graph()->GetConstant0(), Token::GTE); | 1324 key, graph()->GetConstant0(), Token::GTE); |
1193 negative_checker.End(); | 1325 negative_checker.End(); |
1194 HInstruction* result = BuildExternalArrayElementAccess( | 1326 HInstruction* result = BuildExternalArrayElementAccess( |
1195 external_elements, key, val, bounds_check, | 1327 external_elements, key, val, bounds_check, |
1196 elements_kind, is_store); | 1328 elements_kind, is_store); |
1197 AddInstruction(result); | 1329 AddInstruction(result); |
1198 length_checker.End(); | 1330 length_checker.End(); |
1199 return result; | 1331 return result; |
1200 } else { | 1332 } else { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1243 } | 1375 } |
1244 } | 1376 } |
1245 return AddInstruction( | 1377 return AddInstruction( |
1246 BuildFastElementAccess(elements, checked_key, val, mapcheck, | 1378 BuildFastElementAccess(elements, checked_key, val, mapcheck, |
1247 elements_kind, is_store, store_mode)); | 1379 elements_kind, is_store, store_mode)); |
1248 } | 1380 } |
1249 | 1381 |
1250 | 1382 |
1251 HValue* HGraphBuilder::BuildAllocateElements(HValue* context, | 1383 HValue* HGraphBuilder::BuildAllocateElements(HValue* context, |
1252 ElementsKind kind, | 1384 ElementsKind kind, |
1253 HValue* capacity, | 1385 HValue* capacity) { |
1254 BailoutId ast_id) { | |
1255 Zone* zone = this->zone(); | 1386 Zone* zone = this->zone(); |
1256 | 1387 |
1257 int elements_size = IsFastDoubleElementsKind(kind) | 1388 int elements_size = IsFastDoubleElementsKind(kind) |
1258 ? kDoubleSize : kPointerSize; | 1389 ? kDoubleSize : kPointerSize; |
1259 HConstant* elements_size_value = | 1390 HConstant* elements_size_value = |
1260 new(zone) HConstant(elements_size, Representation::Integer32()); | 1391 new(zone) HConstant(elements_size, Representation::Integer32()); |
1261 AddInstruction(elements_size_value); | 1392 AddInstruction(elements_size_value); |
1262 HValue* mul = AddInstruction( | 1393 HValue* mul = AddInstruction( |
1263 HMul::New(zone, context, capacity, elements_size_value)); | 1394 HMul::New(zone, context, capacity, elements_size_value)); |
1264 mul->ChangeRepresentation(Representation::Integer32()); | 1395 mul->ChangeRepresentation(Representation::Integer32()); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1308 HInstruction* store_length = | 1439 HInstruction* store_length = |
1309 new(zone) HStoreNamedField(elements, fixed_array_length_field_name, | 1440 new(zone) HStoreNamedField(elements, fixed_array_length_field_name, |
1310 capacity, true, FixedArray::kLengthOffset); | 1441 capacity, true, FixedArray::kLengthOffset); |
1311 AddInstruction(store_length); | 1442 AddInstruction(store_length); |
1312 } | 1443 } |
1313 | 1444 |
1314 | 1445 |
1315 HValue* HGraphBuilder::BuildAllocateAndInitializeElements(HValue* context, | 1446 HValue* HGraphBuilder::BuildAllocateAndInitializeElements(HValue* context, |
1316 ElementsKind kind, | 1447 ElementsKind kind, |
1317 HValue* capacity) { | 1448 HValue* capacity) { |
1318 BailoutId ast_id = environment()->ast_id(); | 1449 HValue* new_elements = BuildAllocateElements(context, kind, capacity); |
1319 HValue* new_elements = | |
1320 BuildAllocateElements(context, kind, capacity, ast_id); | |
1321 BuildInitializeElements(new_elements, kind, capacity); | 1450 BuildInitializeElements(new_elements, kind, capacity); |
1322 return new_elements; | 1451 return new_elements; |
1323 } | 1452 } |
1324 | 1453 |
1325 | 1454 |
1326 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, | 1455 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, |
1327 HValue* map) { | 1456 HValue* map) { |
1328 Zone* zone = this->zone(); | 1457 Zone* zone = this->zone(); |
1329 Factory* factory = isolate()->factory(); | 1458 Factory* factory = isolate()->factory(); |
1330 Handle<String> map_field_name = factory->map_field_string(); | 1459 Handle<String> map_field_name = factory->map_field_string(); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1387 AddInstruction(new(zone) | 1516 AddInstruction(new(zone) |
1388 HBoundsCheck(length, max_size_constant, | 1517 HBoundsCheck(length, max_size_constant, |
1389 DONT_ALLOW_SMI_KEY, Representation::Integer32())); | 1518 DONT_ALLOW_SMI_KEY, Representation::Integer32())); |
1390 } | 1519 } |
1391 | 1520 |
1392 | 1521 |
1393 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, | 1522 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, |
1394 HValue* elements, | 1523 HValue* elements, |
1395 ElementsKind kind, | 1524 ElementsKind kind, |
1396 HValue* length, | 1525 HValue* length, |
1397 HValue* new_capacity, | 1526 HValue* new_capacity) { |
1398 BailoutId ast_id) { | |
1399 Zone* zone = this->zone(); | 1527 Zone* zone = this->zone(); |
1400 HValue* context = environment()->LookupContext(); | 1528 HValue* context = environment()->LookupContext(); |
1401 | 1529 |
1402 BuildNewSpaceArrayCheck(new_capacity, kind); | 1530 BuildNewSpaceArrayCheck(new_capacity, kind); |
1403 | 1531 |
1404 HValue* new_elements = | 1532 HValue* new_elements = |
1405 BuildAllocateAndInitializeElements(context, kind, new_capacity); | 1533 BuildAllocateAndInitializeElements(context, kind, new_capacity); |
1406 | 1534 |
1407 BuildCopyElements(context, elements, kind, | 1535 BuildCopyElements(context, elements, kind, |
1408 new_elements, kind, | 1536 new_elements, kind, |
1409 length, new_capacity, ast_id); | 1537 length, new_capacity); |
1410 | 1538 |
1411 Factory* factory = isolate()->factory(); | 1539 Factory* factory = isolate()->factory(); |
1412 HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField( | 1540 HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField( |
1413 object, | 1541 object, |
1414 factory->elements_field_string(), | 1542 factory->elements_field_string(), |
1415 new_elements, true, | 1543 new_elements, true, |
1416 JSArray::kElementsOffset)); | 1544 JSArray::kElementsOffset)); |
1417 elements_store->SetGVNFlag(kChangesElementsPointer); | 1545 elements_store->SetGVNFlag(kChangesElementsPointer); |
1418 | 1546 |
1419 return new_elements; | 1547 return new_elements; |
1420 } | 1548 } |
1421 | 1549 |
1422 | 1550 |
1423 void HGraphBuilder::BuildFillElementsWithHole(HValue* context, | 1551 void HGraphBuilder::BuildFillElementsWithHole(HValue* context, |
1424 HValue* elements, | 1552 HValue* elements, |
1425 ElementsKind elements_kind, | 1553 ElementsKind elements_kind, |
1426 HValue* from, | 1554 HValue* from, |
1427 HValue* to, | 1555 HValue* to) { |
1428 BailoutId ast_id) { | |
1429 // Fast elements kinds need to be initialized in case statements below cause | 1556 // Fast elements kinds need to be initialized in case statements below cause |
1430 // a garbage collection. | 1557 // a garbage collection. |
1431 Factory* factory = isolate()->factory(); | 1558 Factory* factory = isolate()->factory(); |
1432 | 1559 |
1433 double nan_double = FixedDoubleArray::hole_nan_as_double(); | 1560 double nan_double = FixedDoubleArray::hole_nan_as_double(); |
1434 Zone* zone = this->zone(); | 1561 Zone* zone = this->zone(); |
1435 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) | 1562 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) |
1436 ? AddInstruction(new(zone) HConstant(factory->the_hole_value(), | 1563 ? AddInstruction(new(zone) HConstant(factory->the_hole_value(), |
1437 Representation::Tagged())) | 1564 Representation::Tagged())) |
1438 : AddInstruction(new(zone) HConstant(nan_double, | 1565 : AddInstruction(new(zone) HConstant(nan_double, |
1439 Representation::Double())); | 1566 Representation::Double())); |
1440 | 1567 |
1441 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, ast_id); | 1568 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement); |
1442 | 1569 |
1443 HValue* key = builder.BeginBody(from, to, Token::LT); | 1570 HValue* key = builder.BeginBody(from, to, Token::LT); |
1444 | 1571 |
1445 AddInstruction(new(zone) HStoreKeyed(elements, key, hole, elements_kind)); | 1572 AddInstruction(new(zone) HStoreKeyed(elements, key, hole, elements_kind)); |
1446 | 1573 |
1447 builder.EndBody(); | 1574 builder.EndBody(); |
1448 } | 1575 } |
1449 | 1576 |
1450 | 1577 |
1451 void HGraphBuilder::BuildCopyElements(HValue* context, | 1578 void HGraphBuilder::BuildCopyElements(HValue* context, |
1452 HValue* from_elements, | 1579 HValue* from_elements, |
1453 ElementsKind from_elements_kind, | 1580 ElementsKind from_elements_kind, |
1454 HValue* to_elements, | 1581 HValue* to_elements, |
1455 ElementsKind to_elements_kind, | 1582 ElementsKind to_elements_kind, |
1456 HValue* length, | 1583 HValue* length, |
1457 HValue* capacity, | 1584 HValue* capacity) { |
1458 BailoutId ast_id) { | |
1459 bool pre_fill_with_holes = | 1585 bool pre_fill_with_holes = |
1460 IsFastDoubleElementsKind(from_elements_kind) && | 1586 IsFastDoubleElementsKind(from_elements_kind) && |
1461 IsFastObjectElementsKind(to_elements_kind); | 1587 IsFastObjectElementsKind(to_elements_kind); |
1462 | 1588 |
1463 if (pre_fill_with_holes) { | 1589 if (pre_fill_with_holes) { |
1464 // If the copy might trigger a GC, make sure that the FixedArray is | 1590 // If the copy might trigger a GC, make sure that the FixedArray is |
1465 // pre-initialized with holes to make sure that it's always in a consistent | 1591 // pre-initialized with holes to make sure that it's always in a consistent |
1466 // state. | 1592 // state. |
1467 BuildFillElementsWithHole(context, to_elements, to_elements_kind, | 1593 BuildFillElementsWithHole(context, to_elements, to_elements_kind, |
1468 graph()->GetConstant0(), capacity, ast_id); | 1594 graph()->GetConstant0(), capacity); |
1469 } | 1595 } |
1470 | 1596 |
1471 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, ast_id); | 1597 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement); |
1472 | 1598 |
1473 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT); | 1599 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT); |
1474 | 1600 |
1475 HValue* element = | 1601 HValue* element = |
1476 AddInstruction(new(zone()) HLoadKeyed(from_elements, key, NULL, | 1602 AddInstruction(new(zone()) HLoadKeyed(from_elements, key, NULL, |
1477 from_elements_kind, | 1603 from_elements_kind, |
1478 ALLOW_RETURN_HOLE)); | 1604 ALLOW_RETURN_HOLE)); |
1479 | 1605 |
1480 AddInstruction(new(zone()) HStoreKeyed(to_elements, key, element, | 1606 AddInstruction(new(zone()) HStoreKeyed(to_elements, key, element, |
1481 to_elements_kind)); | 1607 to_elements_kind)); |
1482 | 1608 |
1483 builder.EndBody(); | 1609 builder.EndBody(); |
1484 | 1610 |
1485 if (!pre_fill_with_holes && length != capacity) { | 1611 if (!pre_fill_with_holes && length != capacity) { |
1486 // Fill unused capacity with the hole. | 1612 // Fill unused capacity with the hole. |
1487 BuildFillElementsWithHole(context, to_elements, to_elements_kind, | 1613 BuildFillElementsWithHole(context, to_elements, to_elements_kind, |
1488 key, capacity, ast_id); | 1614 key, capacity); |
1489 } | 1615 } |
1490 } | 1616 } |
1491 | 1617 |
1492 | 1618 |
1493 HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context, | 1619 HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context, |
1494 HValue* boilerplate, | 1620 HValue* boilerplate, |
1495 AllocationSiteMode mode, | 1621 AllocationSiteMode mode, |
1496 ElementsKind kind, | 1622 ElementsKind kind, |
1497 int length) { | 1623 int length) { |
1498 Zone* zone = this->zone(); | 1624 Zone* zone = this->zone(); |
(...skipping 2605 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4104 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 4230 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
4105 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 4231 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
4106 instr->SetSuccessorAt(0, empty_true); | 4232 instr->SetSuccessorAt(0, empty_true); |
4107 instr->SetSuccessorAt(1, empty_false); | 4233 instr->SetSuccessorAt(1, empty_false); |
4108 owner()->current_block()->Finish(instr); | 4234 owner()->current_block()->Finish(instr); |
4109 HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id); | 4235 HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id); |
4110 owner()->set_current_block(join); | 4236 owner()->set_current_block(join); |
4111 } | 4237 } |
4112 | 4238 |
4113 | 4239 |
| 4240 void EffectContext::ReturnContinuation(HIfContinuation* continuation, |
| 4241 BailoutId ast_id) { |
| 4242 HBasicBlock* true_branch = NULL; |
| 4243 HBasicBlock* false_branch = NULL; |
| 4244 continuation->Continue(&true_branch, &false_branch, NULL); |
| 4245 if (!continuation->IsTrueReachable()) { |
| 4246 owner()->set_current_block(false_branch); |
| 4247 } else if (!continuation->IsFalseReachable()) { |
| 4248 owner()->set_current_block(true_branch); |
| 4249 } else { |
| 4250 HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id); |
| 4251 owner()->set_current_block(join); |
| 4252 } |
| 4253 } |
| 4254 |
| 4255 |
4114 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 4256 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
4115 ASSERT(!instr->IsControlInstruction()); | 4257 ASSERT(!instr->IsControlInstruction()); |
4116 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { | 4258 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
4117 return owner()->Bailout("bad value context for arguments object value"); | 4259 return owner()->Bailout("bad value context for arguments object value"); |
4118 } | 4260 } |
4119 owner()->AddInstruction(instr); | 4261 owner()->AddInstruction(instr); |
4120 owner()->Push(instr); | 4262 owner()->Push(instr); |
4121 if (instr->HasObservableSideEffects()) { | 4263 if (instr->HasObservableSideEffects()) { |
4122 owner()->AddSimulate(ast_id, REMOVABLE_SIMULATE); | 4264 owner()->AddSimulate(ast_id, REMOVABLE_SIMULATE); |
4123 } | 4265 } |
(...skipping 13 matching lines...) Expand all Loading... |
4137 owner()->set_current_block(materialize_true); | 4279 owner()->set_current_block(materialize_true); |
4138 owner()->Push(owner()->graph()->GetConstantTrue()); | 4280 owner()->Push(owner()->graph()->GetConstantTrue()); |
4139 owner()->set_current_block(materialize_false); | 4281 owner()->set_current_block(materialize_false); |
4140 owner()->Push(owner()->graph()->GetConstantFalse()); | 4282 owner()->Push(owner()->graph()->GetConstantFalse()); |
4141 HBasicBlock* join = | 4283 HBasicBlock* join = |
4142 owner()->CreateJoin(materialize_true, materialize_false, ast_id); | 4284 owner()->CreateJoin(materialize_true, materialize_false, ast_id); |
4143 owner()->set_current_block(join); | 4285 owner()->set_current_block(join); |
4144 } | 4286 } |
4145 | 4287 |
4146 | 4288 |
| 4289 void ValueContext::ReturnContinuation(HIfContinuation* continuation, |
| 4290 BailoutId ast_id) { |
| 4291 HBasicBlock* materialize_true = NULL; |
| 4292 HBasicBlock* materialize_false = NULL; |
| 4293 continuation->Continue(&materialize_true, &materialize_false, NULL); |
| 4294 if (continuation->IsTrueReachable()) { |
| 4295 owner()->set_current_block(materialize_true); |
| 4296 owner()->Push(owner()->graph()->GetConstantTrue()); |
| 4297 owner()->set_current_block(materialize_true); |
| 4298 } |
| 4299 if (continuation->IsFalseReachable()) { |
| 4300 owner()->set_current_block(materialize_false); |
| 4301 owner()->Push(owner()->graph()->GetConstantFalse()); |
| 4302 owner()->set_current_block(materialize_false); |
| 4303 } |
| 4304 if (continuation->TrueAndFalseReachable()) { |
| 4305 HBasicBlock* join = |
| 4306 owner()->CreateJoin(materialize_true, materialize_false, ast_id); |
| 4307 owner()->set_current_block(join); |
| 4308 } |
| 4309 } |
| 4310 |
| 4311 |
4147 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { | 4312 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) { |
4148 ASSERT(!instr->IsControlInstruction()); | 4313 ASSERT(!instr->IsControlInstruction()); |
4149 HOptimizedGraphBuilder* builder = owner(); | 4314 HOptimizedGraphBuilder* builder = owner(); |
4150 builder->AddInstruction(instr); | 4315 builder->AddInstruction(instr); |
4151 // We expect a simulate after every expression with side effects, though | 4316 // We expect a simulate after every expression with side effects, though |
4152 // this one isn't actually needed (and wouldn't work if it were targeted). | 4317 // this one isn't actually needed (and wouldn't work if it were targeted). |
4153 if (instr->HasObservableSideEffects()) { | 4318 if (instr->HasObservableSideEffects()) { |
4154 builder->Push(instr); | 4319 builder->Push(instr); |
4155 builder->AddSimulate(ast_id, REMOVABLE_SIMULATE); | 4320 builder->AddSimulate(ast_id, REMOVABLE_SIMULATE); |
4156 builder->Pop(); | 4321 builder->Pop(); |
4157 } | 4322 } |
4158 BuildBranch(instr); | 4323 BuildBranch(instr); |
4159 } | 4324 } |
4160 | 4325 |
4161 | 4326 |
4162 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { | 4327 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) { |
4163 ASSERT(!instr->HasObservableSideEffects()); | 4328 ASSERT(!instr->HasObservableSideEffects()); |
4164 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); | 4329 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
4165 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); | 4330 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
4166 instr->SetSuccessorAt(0, empty_true); | 4331 instr->SetSuccessorAt(0, empty_true); |
4167 instr->SetSuccessorAt(1, empty_false); | 4332 instr->SetSuccessorAt(1, empty_false); |
4168 owner()->current_block()->Finish(instr); | 4333 owner()->current_block()->Finish(instr); |
4169 empty_true->Goto(if_true(), owner()->function_state()); | 4334 empty_true->Goto(if_true(), owner()->function_state()); |
4170 empty_false->Goto(if_false(), owner()->function_state()); | 4335 empty_false->Goto(if_false(), owner()->function_state()); |
4171 owner()->set_current_block(NULL); | 4336 owner()->set_current_block(NULL); |
4172 } | 4337 } |
4173 | 4338 |
4174 | 4339 |
| 4340 void TestContext::ReturnContinuation(HIfContinuation* continuation, |
| 4341 BailoutId ast_id) { |
| 4342 HBasicBlock* true_branch = NULL; |
| 4343 HBasicBlock* false_branch = NULL; |
| 4344 continuation->Continue(&true_branch, &false_branch, NULL); |
| 4345 if (continuation->IsTrueReachable()) { |
| 4346 true_branch->Goto(if_true(), owner()->function_state()); |
| 4347 } |
| 4348 if (continuation->IsFalseReachable()) { |
| 4349 false_branch->Goto(if_false(), owner()->function_state()); |
| 4350 } |
| 4351 owner()->set_current_block(NULL); |
| 4352 } |
| 4353 |
| 4354 |
4175 void TestContext::BuildBranch(HValue* value) { | 4355 void TestContext::BuildBranch(HValue* value) { |
4176 // We expect the graph to be in edge-split form: there is no edge that | 4356 // We expect the graph to be in edge-split form: there is no edge that |
4177 // connects a branch node to a join node. We conservatively ensure that | 4357 // connects a branch node to a join node. We conservatively ensure that |
4178 // property by always adding an empty block on the outgoing edges of this | 4358 // property by always adding an empty block on the outgoing edges of this |
4179 // branch. | 4359 // branch. |
4180 HOptimizedGraphBuilder* builder = owner(); | 4360 HOptimizedGraphBuilder* builder = owner(); |
4181 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { | 4361 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { |
4182 builder->Bailout("arguments object value in a test context"); | 4362 builder->Bailout("arguments object value in a test context"); |
4183 } | 4363 } |
4184 if (value->IsConstant()) { | 4364 if (value->IsConstant()) { |
(...skipping 2623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6808 CHECK_ALIVE(VisitForValue(expr->value())); | 6988 CHECK_ALIVE(VisitForValue(expr->value())); |
6809 HValue* value = Pop(); | 6989 HValue* value = Pop(); |
6810 HValue* key = Pop(); | 6990 HValue* key = Pop(); |
6811 HValue* object = Pop(); | 6991 HValue* object = Pop(); |
6812 bool has_side_effects = false; | 6992 bool has_side_effects = false; |
6813 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), | 6993 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), |
6814 expr->position(), | 6994 expr->position(), |
6815 true, // is_store | 6995 true, // is_store |
6816 &has_side_effects); | 6996 &has_side_effects); |
6817 Push(value); | 6997 Push(value); |
6818 ASSERT(has_side_effects); // Stores always have side effects. | |
6819 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | 6998 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); |
6820 return ast_context()->ReturnValue(Pop()); | 6999 return ast_context()->ReturnValue(Pop()); |
6821 } | 7000 } |
6822 } | 7001 } |
6823 | 7002 |
6824 | 7003 |
6825 // Because not every expression has a position and there is not common | 7004 // Because not every expression has a position and there is not common |
6826 // superclass of Assignment and CountOperation, we cannot just pass the | 7005 // superclass of Assignment and CountOperation, we cannot just pass the |
6827 // owning expression instead of position and ast_id separately. | 7006 // owning expression instead of position and ast_id separately. |
6828 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 7007 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
(...skipping 4864 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11693 } | 11872 } |
11694 } | 11873 } |
11695 | 11874 |
11696 #ifdef DEBUG | 11875 #ifdef DEBUG |
11697 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 11876 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
11698 if (allocator_ != NULL) allocator_->Verify(); | 11877 if (allocator_ != NULL) allocator_->Verify(); |
11699 #endif | 11878 #endif |
11700 } | 11879 } |
11701 | 11880 |
11702 } } // namespace v8::internal | 11881 } } // namespace v8::internal |
OLD | NEW |