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