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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 phis_.RemoveElement(phi); | 107 phis_.RemoveElement(phi); |
108 phi->SetBlock(NULL); | 108 phi->SetBlock(NULL); |
109 } | 109 } |
110 | 110 |
111 | 111 |
112 void HBasicBlock::AddInstruction(HInstruction* instr) { | 112 void HBasicBlock::AddInstruction(HInstruction* instr) { |
113 ASSERT(!IsStartBlock() || !IsFinished()); | 113 ASSERT(!IsStartBlock() || !IsFinished()); |
114 ASSERT(!instr->IsLinked()); | 114 ASSERT(!instr->IsLinked()); |
115 ASSERT(!IsFinished()); | 115 ASSERT(!IsFinished()); |
116 if (first_ == NULL) { | 116 if (first_ == NULL) { |
| 117 ASSERT(last_environment() != NULL); |
| 118 ASSERT(!last_environment()->ast_id().IsNone()); |
117 HBlockEntry* entry = new(zone()) HBlockEntry(); | 119 HBlockEntry* entry = new(zone()) HBlockEntry(); |
118 entry->InitializeAsFirst(this); | 120 entry->InitializeAsFirst(this); |
119 first_ = last_ = entry; | 121 first_ = last_ = entry; |
120 } | 122 } |
121 instr->InsertAfter(last_); | 123 instr->InsertAfter(last_); |
122 } | 124 } |
123 | 125 |
124 | 126 |
125 HDeoptimize* HBasicBlock::CreateDeoptimize( | 127 HDeoptimize* HBasicBlock::CreateDeoptimize( |
126 HDeoptimize::UseEnvironment has_uses) { | 128 HDeoptimize::UseEnvironment has_uses) { |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 for (int i = 0; i < length; i++) { | 226 for (int i = 0; i < length; i++) { |
225 HBasicBlock* predecessor = predecessors_[i]; | 227 HBasicBlock* predecessor = predecessors_[i]; |
226 ASSERT(predecessor->end()->IsGoto()); | 228 ASSERT(predecessor->end()->IsGoto()); |
227 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous()); | 229 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous()); |
228 // We only need to verify the ID once. | 230 // We only need to verify the ID once. |
229 ASSERT(i != 0 || | 231 ASSERT(i != 0 || |
230 (predecessor->last_environment()->closure().is_null() || | 232 (predecessor->last_environment()->closure().is_null() || |
231 predecessor->last_environment()->closure()->shared() | 233 predecessor->last_environment()->closure()->shared() |
232 ->VerifyBailoutId(ast_id))); | 234 ->VerifyBailoutId(ast_id))); |
233 simulate->set_ast_id(ast_id); | 235 simulate->set_ast_id(ast_id); |
| 236 predecessor->last_environment()->set_ast_id(ast_id); |
234 } | 237 } |
235 } | 238 } |
236 | 239 |
237 | 240 |
238 bool HBasicBlock::Dominates(HBasicBlock* other) const { | 241 bool HBasicBlock::Dominates(HBasicBlock* other) const { |
239 HBasicBlock* current = other->dominator(); | 242 HBasicBlock* current = other->dominator(); |
240 while (current != NULL) { | 243 while (current != NULL) { |
241 if (current == this) return true; | 244 if (current == this) return true; |
242 current = current->dominator(); | 245 current = current->dominator(); |
243 } | 246 } |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
635 DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false) | 638 DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false) |
636 | 639 |
637 #undef DEFINE_GET_CONSTANT | 640 #undef DEFINE_GET_CONSTANT |
638 | 641 |
639 | 642 |
640 HGraphBuilder::CheckBuilder::CheckBuilder(HGraphBuilder* builder, BailoutId id) | 643 HGraphBuilder::CheckBuilder::CheckBuilder(HGraphBuilder* builder, BailoutId id) |
641 : builder_(builder), | 644 : builder_(builder), |
642 finished_(false), | 645 finished_(false), |
643 id_(id) { | 646 id_(id) { |
644 HEnvironment* env = builder->environment(); | 647 HEnvironment* env = builder->environment(); |
645 failure_block_ = builder->CreateBasicBlock(env->Copy()); | 648 failure_block_ = builder->CreateBasicBlock(env->CopyWithoutHistory()); |
646 merge_block_ = builder->CreateBasicBlock(env->Copy()); | 649 merge_block_ = builder->CreateBasicBlock(env->CopyWithoutHistory()); |
647 } | 650 } |
648 | 651 |
649 | 652 |
650 void HGraphBuilder::CheckBuilder::CheckNotUndefined(HValue* value) { | 653 HValue* HGraphBuilder::CheckBuilder::CheckNotUndefined(HValue* value) { |
651 HEnvironment* env = builder_->environment(); | 654 HEnvironment* env = builder_->environment(); |
652 HIsNilAndBranch* compare = | 655 HIsNilAndBranch* compare = |
653 new(zone()) HIsNilAndBranch(value, kStrictEquality, kUndefinedValue); | 656 new(zone()) HIsNilAndBranch(value, kStrictEquality, kUndefinedValue); |
654 HBasicBlock* success_block = builder_->CreateBasicBlock(env->Copy()); | 657 HBasicBlock* success_block = |
655 HBasicBlock* failure_block = builder_->CreateBasicBlock(env->Copy()); | 658 builder_->CreateBasicBlock(env->CopyWithoutHistory()); |
| 659 HBasicBlock* failure_block = |
| 660 builder_->CreateBasicBlock(env->CopyWithoutHistory()); |
656 compare->SetSuccessorAt(0, failure_block); | 661 compare->SetSuccessorAt(0, failure_block); |
657 compare->SetSuccessorAt(1, success_block); | 662 compare->SetSuccessorAt(1, success_block); |
658 failure_block->Goto(failure_block_); | 663 failure_block->Goto(failure_block_); |
659 builder_->current_block()->Finish(compare); | 664 builder_->current_block()->Finish(compare); |
660 builder_->set_current_block(success_block); | 665 builder_->set_current_block(success_block); |
| 666 return compare; |
661 } | 667 } |
662 | 668 |
663 | 669 |
664 void HGraphBuilder::CheckBuilder::CheckIntegerEq(HValue* left, HValue* right) { | 670 HValue* HGraphBuilder::CheckBuilder::CheckIntegerCompare(HValue* left, |
| 671 HValue* right, |
| 672 Token::Value op) { |
665 HEnvironment* env = builder_->environment(); | 673 HEnvironment* env = builder_->environment(); |
666 HCompareIDAndBranch* compare = | 674 HCompareIDAndBranch* compare = |
667 new(zone()) HCompareIDAndBranch(left, right, Token::EQ); | 675 new(zone()) HCompareIDAndBranch(left, right, op); |
668 compare->AssumeRepresentation(Representation::Integer32()); | 676 compare->AssumeRepresentation(Representation::Integer32()); |
669 HBasicBlock* success_block = builder_->CreateBasicBlock(env->Copy()); | 677 HBasicBlock* success_block = |
670 HBasicBlock* failure_block = builder_->CreateBasicBlock(env->Copy()); | 678 builder_->CreateBasicBlock(env->CopyWithoutHistory()); |
| 679 HBasicBlock* failure_block = |
| 680 builder_->CreateBasicBlock(env->CopyWithoutHistory()); |
671 compare->SetSuccessorAt(0, success_block); | 681 compare->SetSuccessorAt(0, success_block); |
672 compare->SetSuccessorAt(1, failure_block); | 682 compare->SetSuccessorAt(1, failure_block); |
673 failure_block->Goto(failure_block_); | 683 failure_block->Goto(failure_block_); |
674 builder_->current_block()->Finish(compare); | 684 builder_->current_block()->Finish(compare); |
675 builder_->set_current_block(success_block); | 685 builder_->set_current_block(success_block); |
| 686 return compare; |
676 } | 687 } |
677 | 688 |
678 | 689 |
| 690 HValue* HGraphBuilder::CheckBuilder::CheckIntegerEq(HValue* left, |
| 691 HValue* right) { |
| 692 return CheckIntegerCompare(left, right, Token::EQ); |
| 693 } |
| 694 |
| 695 |
679 void HGraphBuilder::CheckBuilder::End() { | 696 void HGraphBuilder::CheckBuilder::End() { |
680 ASSERT(!finished_); | 697 ASSERT(!finished_); |
681 builder_->current_block()->Goto(merge_block_); | 698 builder_->current_block()->Goto(merge_block_); |
682 failure_block_->FinishExitWithDeoptimization(HDeoptimize::kUseAll); | 699 failure_block_->FinishExitWithDeoptimization(HDeoptimize::kUseAll); |
683 failure_block_->SetJoinId(id_); | 700 failure_block_->SetJoinId(id_); |
684 builder_->set_current_block(merge_block_); | 701 builder_->set_current_block(merge_block_); |
685 merge_block_->SetJoinId(id_); | 702 merge_block_->SetJoinId(id_); |
686 finished_ = true; | 703 finished_ = true; |
687 } | 704 } |
688 | 705 |
689 | 706 |
690 HConstant* HGraph::GetInvalidContext() { | 707 HConstant* HGraph::GetInvalidContext() { |
691 return GetConstantInt32(&constant_invalid_context_, 0xFFFFC0C7); | 708 return GetConstantInt32(&constant_invalid_context_, 0xFFFFC0C7); |
692 } | 709 } |
693 | 710 |
694 | 711 |
695 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, BailoutId id) | 712 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, BailoutId id) |
696 : builder_(builder), | 713 : builder_(builder), |
697 finished_(false), | 714 finished_(false), |
| 715 did_else_(false), |
698 id_(id) { | 716 id_(id) { |
699 HEnvironment* env = builder->environment(); | 717 HEnvironment* env = builder->environment(); |
700 first_true_block_ = builder->CreateBasicBlock(env->Copy()); | 718 first_true_block_ = builder->CreateBasicBlock(env->Copy()); |
701 last_true_block_ = NULL; | 719 last_true_block_ = NULL; |
702 first_false_block_ = builder->CreateBasicBlock(env->Copy()); | 720 first_false_block_ = builder->CreateBasicBlock(env->Copy()); |
703 } | 721 } |
704 | 722 |
705 | 723 |
706 HInstruction* HGraphBuilder::IfBuilder::BeginTrue( | 724 HInstruction* HGraphBuilder::IfBuilder::BeginIf( |
707 HValue* left, | 725 HValue* left, |
708 HValue* right, | 726 HValue* right, |
709 Token::Value token, | 727 Token::Value token, |
710 Representation input_representation) { | 728 Representation input_representation) { |
711 HCompareIDAndBranch* compare = | 729 HCompareIDAndBranch* compare = |
712 new(zone()) HCompareIDAndBranch(left, right, token); | 730 new(zone()) HCompareIDAndBranch(left, right, token); |
713 compare->set_observed_input_representation(input_representation, | 731 compare->set_observed_input_representation(input_representation, |
714 input_representation); | 732 input_representation); |
715 compare->ChangeRepresentation(input_representation); | 733 compare->ChangeRepresentation(input_representation); |
716 compare->SetSuccessorAt(0, first_true_block_); | 734 compare->SetSuccessorAt(0, first_true_block_); |
717 compare->SetSuccessorAt(1, first_false_block_); | 735 compare->SetSuccessorAt(1, first_false_block_); |
718 builder_->current_block()->Finish(compare); | 736 builder_->current_block()->Finish(compare); |
719 builder_->set_current_block(first_true_block_); | 737 builder_->set_current_block(first_true_block_); |
720 return compare; | 738 return compare; |
721 } | 739 } |
722 | 740 |
723 | 741 |
724 void HGraphBuilder::IfBuilder::BeginFalse() { | 742 HInstruction* HGraphBuilder::IfBuilder::BeginIfObjectsEqual( |
| 743 HValue* left, |
| 744 HValue* right) { |
| 745 HCompareObjectEqAndBranch* compare = |
| 746 new(zone()) HCompareObjectEqAndBranch(left, right); |
| 747 compare->SetSuccessorAt(0, first_true_block_); |
| 748 compare->SetSuccessorAt(1, first_false_block_); |
| 749 builder_->current_block()->Finish(compare); |
| 750 builder_->set_current_block(first_true_block_); |
| 751 return compare; |
| 752 } |
| 753 |
| 754 |
| 755 HInstruction* HGraphBuilder::IfBuilder::BeginIfMapEquals(HValue* value, |
| 756 Handle<Map> map) { |
| 757 HCompareMap* compare = new(zone()) |
| 758 HCompareMap(value, map, first_true_block_, first_false_block_); |
| 759 builder_->current_block()->Finish(compare); |
| 760 builder_->set_current_block(first_true_block_); |
| 761 return compare; |
| 762 } |
| 763 |
| 764 |
| 765 void HGraphBuilder::IfBuilder::BeginElse() { |
725 last_true_block_ = builder_->current_block(); | 766 last_true_block_ = builder_->current_block(); |
726 ASSERT(!last_true_block_->IsFinished()); | 767 ASSERT(!last_true_block_->IsFinished()); |
727 builder_->set_current_block(first_false_block_); | 768 builder_->set_current_block(first_false_block_); |
| 769 did_else_ = true; |
728 } | 770 } |
729 | 771 |
730 | 772 |
731 void HGraphBuilder::IfBuilder::End() { | 773 void HGraphBuilder::IfBuilder::End() { |
732 ASSERT(!finished_); | 774 ASSERT(!finished_); |
| 775 if (!did_else_) BeginElse(); |
733 ASSERT(!last_true_block_->IsFinished()); | 776 ASSERT(!last_true_block_->IsFinished()); |
734 HBasicBlock* last_false_block = builder_->current_block(); | 777 HBasicBlock* last_false_block = builder_->current_block(); |
735 ASSERT(!last_false_block->IsFinished()); | 778 ASSERT(!last_false_block->IsFinished()); |
736 HEnvironment* merge_env = | 779 HEnvironment* merge_env = |
737 last_true_block_->last_environment()->Copy(); | 780 last_true_block_->last_environment()->CopyWithoutHistory(); |
738 merge_block_ = builder_->CreateBasicBlock(merge_env); | 781 merge_block_ = builder_->CreateBasicBlock(merge_env); |
739 last_true_block_->Goto(merge_block_); | 782 last_true_block_->Goto(merge_block_); |
740 last_false_block->Goto(merge_block_); | 783 last_false_block->Goto(merge_block_); |
741 merge_block_->SetJoinId(id_); | 784 merge_block_->SetJoinId(id_); |
742 builder_->set_current_block(merge_block_); | 785 builder_->set_current_block(merge_block_); |
743 finished_ = true; | 786 finished_ = true; |
744 } | 787 } |
745 | 788 |
746 | 789 |
747 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, | 790 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
849 ASSERT(current_block() != NULL); | 892 ASSERT(current_block() != NULL); |
850 current_block()->AddInstruction(instr); | 893 current_block()->AddInstruction(instr); |
851 return instr; | 894 return instr; |
852 } | 895 } |
853 | 896 |
854 | 897 |
855 void HGraphBuilder::AddSimulate(BailoutId id, | 898 void HGraphBuilder::AddSimulate(BailoutId id, |
856 RemovableSimulate removable) { | 899 RemovableSimulate removable) { |
857 ASSERT(current_block() != NULL); | 900 ASSERT(current_block() != NULL); |
858 current_block()->AddSimulate(id, removable); | 901 current_block()->AddSimulate(id, removable); |
| 902 environment()->set_ast_id(id); |
859 } | 903 } |
860 | 904 |
861 | 905 |
862 HBoundsCheck* HGraphBuilder::AddBoundsCheck(HValue* index, | 906 HBoundsCheck* HGraphBuilder::AddBoundsCheck(HValue* index, |
863 HValue* length, | 907 HValue* length, |
864 BoundsCheckKeyMode key_mode, | 908 BoundsCheckKeyMode key_mode, |
865 Representation r) { | 909 Representation r) { |
866 if (!index->type().IsSmi()) { | 910 if (!index->type().IsSmi()) { |
867 index = new(graph()->zone()) HCheckSmiOrInt32(index); | 911 index = new(graph()->zone()) HCheckSmiOrInt32(index); |
868 AddInstruction(HCheckSmiOrInt32::cast(index)); | 912 AddInstruction(HCheckSmiOrInt32::cast(index)); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
958 } | 1002 } |
959 } | 1003 } |
960 | 1004 |
961 | 1005 |
962 HInstruction* HGraphBuilder::BuildFastElementAccess( | 1006 HInstruction* HGraphBuilder::BuildFastElementAccess( |
963 HValue* elements, | 1007 HValue* elements, |
964 HValue* checked_key, | 1008 HValue* checked_key, |
965 HValue* val, | 1009 HValue* val, |
966 HValue* load_dependency, | 1010 HValue* load_dependency, |
967 ElementsKind elements_kind, | 1011 ElementsKind elements_kind, |
968 bool is_store) { | 1012 bool is_store, |
| 1013 KeyedAccessStoreMode store_mode) { |
969 Zone* zone = this->zone(); | 1014 Zone* zone = this->zone(); |
970 if (is_store) { | 1015 if (is_store) { |
971 ASSERT(val != NULL); | 1016 ASSERT(val != NULL); |
972 switch (elements_kind) { | 1017 switch (elements_kind) { |
973 case FAST_SMI_ELEMENTS: | 1018 case FAST_SMI_ELEMENTS: |
974 case FAST_HOLEY_SMI_ELEMENTS: | 1019 case FAST_HOLEY_SMI_ELEMENTS: |
975 // Smi-only arrays need a smi check. | 1020 // Smi-only arrays need a smi check. |
976 AddInstruction(new(zone) HCheckSmi(val)); | 1021 AddInstruction(new(zone) HCheckSmi(val)); |
977 // Fall through. | 1022 // Fall through. |
978 case FAST_ELEMENTS: | 1023 case FAST_ELEMENTS: |
979 case FAST_HOLEY_ELEMENTS: | 1024 case FAST_HOLEY_ELEMENTS: |
980 case FAST_DOUBLE_ELEMENTS: | 1025 case FAST_DOUBLE_ELEMENTS: |
981 case FAST_HOLEY_DOUBLE_ELEMENTS: | 1026 case FAST_HOLEY_DOUBLE_ELEMENTS: |
982 return new(zone) HStoreKeyed(elements, checked_key, val, elements_kind); | 1027 return new(zone) HStoreKeyed(elements, checked_key, val, elements_kind); |
983 default: | 1028 default: |
984 UNREACHABLE(); | 1029 UNREACHABLE(); |
985 return NULL; | 1030 return NULL; |
986 } | 1031 } |
987 } | 1032 } |
988 // It's an element load (!is_store). | 1033 // It's an element load (!is_store). |
989 return new(zone) HLoadKeyed(elements, | 1034 return new(zone) HLoadKeyed(elements, |
990 checked_key, | 1035 checked_key, |
991 load_dependency, | 1036 load_dependency, |
992 elements_kind); | 1037 elements_kind); |
993 } | 1038 } |
994 | 1039 |
995 | 1040 |
| 1041 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, |
| 1042 HValue* elements, |
| 1043 ElementsKind kind, |
| 1044 HValue* length, |
| 1045 HValue* key, |
| 1046 bool is_js_array) { |
| 1047 BailoutId ast_id = environment()->ast_id(); |
| 1048 Zone* zone = this->zone(); |
| 1049 IfBuilder length_checker(this, ast_id); |
| 1050 |
| 1051 length_checker.BeginIf(length, key, Token::EQ); |
| 1052 |
| 1053 HValue* current_capacity = |
| 1054 AddInstruction(new(zone) HFixedArrayBaseLength(elements)); |
| 1055 |
| 1056 IfBuilder capacity_checker(this, ast_id); |
| 1057 |
| 1058 capacity_checker.BeginIf(length, current_capacity, Token::EQ); |
| 1059 |
| 1060 HValue* context = environment()->LookupContext(); |
| 1061 |
| 1062 HValue* new_capacity = |
| 1063 BuildNewElementsCapacity(context, current_capacity); |
| 1064 |
| 1065 HValue* new_elements = BuildGrowElementsCapacity(object, elements, |
| 1066 kind, length, |
| 1067 new_capacity, ast_id); |
| 1068 |
| 1069 environment()->Push(new_elements); |
| 1070 capacity_checker.BeginElse(); |
| 1071 |
| 1072 environment()->Push(elements); |
| 1073 capacity_checker.End(); |
| 1074 |
| 1075 if (is_js_array) { |
| 1076 HValue* new_length = AddInstruction( |
| 1077 HAdd::New(zone, context, length, graph_->GetConstant1())); |
| 1078 new_length->ChangeRepresentation(Representation::Integer32()); |
| 1079 new_length->ClearFlag(HValue::kCanOverflow); |
| 1080 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
| 1081 |
| 1082 Factory* factory = isolate()->factory(); |
| 1083 HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField( |
| 1084 object, |
| 1085 factory->length_field_string(), |
| 1086 new_length, true, |
| 1087 JSArray::kLengthOffset)); |
| 1088 length_store->SetGVNFlag(kChangesArrayLengths); |
| 1089 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
| 1090 } |
| 1091 |
| 1092 length_checker.BeginElse(); |
| 1093 |
| 1094 AddBoundsCheck(key, length, ALLOW_SMI_KEY); |
| 1095 environment()->Push(elements); |
| 1096 |
| 1097 length_checker.End(); |
| 1098 |
| 1099 return environment()->Pop(); |
| 1100 } |
| 1101 |
| 1102 |
| 1103 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object, |
| 1104 HValue* elements, |
| 1105 ElementsKind kind, |
| 1106 HValue* length) { |
| 1107 BailoutId ast_id = environment()->ast_id(); |
| 1108 Zone* zone = this->zone(); |
| 1109 Heap* heap = isolate()->heap(); |
| 1110 |
| 1111 IfBuilder cow_checker(this, ast_id); |
| 1112 |
| 1113 cow_checker.BeginIfMapEquals(elements, |
| 1114 Handle<Map>(heap->fixed_cow_array_map())); |
| 1115 |
| 1116 HValue* capacity = |
| 1117 AddInstruction(new(zone) HFixedArrayBaseLength(elements)); |
| 1118 |
| 1119 HValue* new_elements = BuildGrowElementsCapacity(object, elements, |
| 1120 kind, length, |
| 1121 capacity, ast_id); |
| 1122 |
| 1123 environment()->Push(new_elements); |
| 1124 |
| 1125 cow_checker.BeginElse(); |
| 1126 |
| 1127 environment()->Push(elements); |
| 1128 |
| 1129 cow_checker.End(); |
| 1130 |
| 1131 return environment()->Pop(); |
| 1132 } |
| 1133 |
| 1134 |
996 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 1135 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
997 HValue* object, | 1136 HValue* object, |
998 HValue* key, | 1137 HValue* key, |
999 HValue* val, | 1138 HValue* val, |
1000 HCheckMaps* mapcheck, | 1139 HCheckMaps* mapcheck, |
1001 bool is_js_array, | 1140 bool is_js_array, |
1002 ElementsKind elements_kind, | 1141 ElementsKind elements_kind, |
1003 bool is_store, | 1142 bool is_store, |
| 1143 KeyedAccessStoreMode store_mode, |
1004 Representation checked_index_representation) { | 1144 Representation checked_index_representation) { |
| 1145 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); |
1005 Zone* zone = this->zone(); | 1146 Zone* zone = this->zone(); |
1006 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency | 1147 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency |
1007 // on a HElementsTransition instruction. The flag can also be removed if the | 1148 // on a HElementsTransition instruction. The flag can also be removed if the |
1008 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further | 1149 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further |
1009 // ElementsKind transitions. Finally, the dependency can be removed for stores | 1150 // ElementsKind transitions. Finally, the dependency can be removed for stores |
1010 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the | 1151 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the |
1011 // generated store code. | 1152 // generated store code. |
1012 if ((elements_kind == FAST_HOLEY_ELEMENTS) || | 1153 if ((elements_kind == FAST_HOLEY_ELEMENTS) || |
1013 (elements_kind == FAST_ELEMENTS && is_store)) { | 1154 (elements_kind == FAST_ELEMENTS && is_store)) { |
1014 if (mapcheck != NULL) { | 1155 if (mapcheck != NULL) { |
1015 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 1156 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
1016 } | 1157 } |
1017 } | 1158 } |
1018 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); | 1159 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); |
1019 bool fast_elements = IsFastObjectElementsKind(elements_kind); | 1160 bool fast_elements = IsFastObjectElementsKind(elements_kind); |
1020 HInstruction* elements = | 1161 HValue* elements = |
1021 AddInstruction(new(zone) HLoadElements(object, mapcheck)); | 1162 AddInstruction(new(zone) HLoadElements(object, mapcheck)); |
1022 if (is_store && (fast_elements || fast_smi_only_elements)) { | 1163 if (is_store && (fast_elements || fast_smi_only_elements) && |
| 1164 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
1023 HCheckMaps* check_cow_map = new(zone) HCheckMaps( | 1165 HCheckMaps* check_cow_map = new(zone) HCheckMaps( |
1024 elements, isolate()->factory()->fixed_array_map(), zone); | 1166 elements, isolate()->factory()->fixed_array_map(), zone); |
1025 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 1167 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
1026 AddInstruction(check_cow_map); | 1168 AddInstruction(check_cow_map); |
1027 } | 1169 } |
1028 HInstruction* length = NULL; | 1170 HInstruction* length = NULL; |
1029 HInstruction* checked_key = NULL; | |
1030 if (IsExternalArrayElementsKind(elements_kind)) { | |
1031 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | |
1032 checked_key = AddBoundsCheck( | |
1033 key, length, ALLOW_SMI_KEY, checked_index_representation); | |
1034 HLoadExternalArrayPointer* external_elements = | |
1035 new(zone) HLoadExternalArrayPointer(elements); | |
1036 AddInstruction(external_elements); | |
1037 return BuildExternalArrayElementAccess( | |
1038 external_elements, checked_key, val, mapcheck, | |
1039 elements_kind, is_store); | |
1040 } | |
1041 ASSERT(fast_smi_only_elements || | |
1042 fast_elements || | |
1043 IsFastDoubleElementsKind(elements_kind)); | |
1044 if (is_js_array) { | 1171 if (is_js_array) { |
1045 length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck, | 1172 length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck, |
1046 HType::Smi())); | 1173 HType::Smi())); |
1047 } else { | 1174 } else { |
1048 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); | 1175 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); |
1049 } | 1176 } |
1050 checked_key = AddBoundsCheck( | 1177 HValue* checked_key = NULL; |
1051 key, length, ALLOW_SMI_KEY, checked_index_representation); | 1178 if (IsExternalArrayElementsKind(elements_kind)) { |
1052 return BuildFastElementAccess(elements, checked_key, val, mapcheck, | 1179 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
1053 elements_kind, is_store); | 1180 HLoadExternalArrayPointer* external_elements = |
| 1181 new(zone) HLoadExternalArrayPointer(elements); |
| 1182 AddInstruction(external_elements); |
| 1183 BailoutId previous_id = environment()->ast_id(); |
| 1184 ASSERT(!previous_id.IsNone()); |
| 1185 IfBuilder length_checker(this, previous_id); |
| 1186 length_checker.BeginIf(key, length, Token::LT); |
| 1187 CheckBuilder negative_checker(this, previous_id); |
| 1188 HValue* bounds_check = negative_checker.CheckIntegerCompare( |
| 1189 key, graph()->GetConstant0(), Token::GTE); |
| 1190 negative_checker.End(); |
| 1191 HInstruction* result = BuildExternalArrayElementAccess( |
| 1192 external_elements, key, val, bounds_check, |
| 1193 elements_kind, is_store); |
| 1194 AddInstruction(result); |
| 1195 length_checker.End(); |
| 1196 return result; |
| 1197 } else { |
| 1198 ASSERT(store_mode == STANDARD_STORE); |
| 1199 checked_key = AddBoundsCheck( |
| 1200 key, length, ALLOW_SMI_KEY, checked_index_representation); |
| 1201 HLoadExternalArrayPointer* external_elements = |
| 1202 new(zone) HLoadExternalArrayPointer(elements); |
| 1203 AddInstruction(external_elements); |
| 1204 return AddInstruction(BuildExternalArrayElementAccess( |
| 1205 external_elements, checked_key, val, mapcheck, |
| 1206 elements_kind, is_store)); |
| 1207 } |
| 1208 } |
| 1209 ASSERT(fast_smi_only_elements || |
| 1210 fast_elements || |
| 1211 IsFastDoubleElementsKind(elements_kind)); |
| 1212 |
| 1213 if (is_store && IsFastSmiElementsKind(elements_kind) && |
| 1214 !val->type().IsSmi()) { |
| 1215 AddInstruction(new(zone) HCheckSmi(val)); |
| 1216 } |
| 1217 |
| 1218 if (IsGrowStoreMode(store_mode)) { |
| 1219 elements = BuildCheckForCapacityGrow(object, elements, elements_kind, |
| 1220 length, key, is_js_array); |
| 1221 checked_key = key; |
| 1222 } else { |
| 1223 checked_key = AddBoundsCheck( |
| 1224 key, length, ALLOW_SMI_KEY, checked_index_representation); |
| 1225 |
| 1226 if (is_store && (fast_elements || fast_smi_only_elements)) { |
| 1227 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { |
| 1228 elements = BuildCopyElementsOnWrite(object, elements, elements_kind, |
| 1229 length); |
| 1230 } else { |
| 1231 HCheckMaps* check_cow_map = new(zone) HCheckMaps( |
| 1232 elements, isolate()->factory()->fixed_array_map(), zone); |
| 1233 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
| 1234 AddInstruction(check_cow_map); |
| 1235 } |
| 1236 } |
| 1237 } |
| 1238 return AddInstruction( |
| 1239 BuildFastElementAccess(elements, checked_key, val, mapcheck, |
| 1240 elements_kind, is_store, store_mode)); |
1054 } | 1241 } |
1055 | 1242 |
1056 | 1243 |
1057 HValue* HGraphBuilder::BuildAllocateElements(HContext* context, | 1244 HValue* HGraphBuilder::BuildAllocateElements(HValue* context, |
1058 ElementsKind kind, | 1245 ElementsKind kind, |
1059 HValue* capacity) { | 1246 HValue* capacity, |
| 1247 BailoutId ast_id) { |
1060 Zone* zone = this->zone(); | 1248 Zone* zone = this->zone(); |
1061 | 1249 |
1062 int elements_size = IsFastDoubleElementsKind(kind) | 1250 int elements_size = IsFastDoubleElementsKind(kind) |
1063 ? kDoubleSize : kPointerSize; | 1251 ? kDoubleSize : kPointerSize; |
1064 HConstant* elements_size_value = | 1252 HConstant* elements_size_value = |
1065 new(zone) HConstant(elements_size, Representation::Integer32()); | 1253 new(zone) HConstant(elements_size, Representation::Integer32()); |
1066 AddInstruction(elements_size_value); | 1254 AddInstruction(elements_size_value); |
1067 HValue* mul = AddInstruction( | 1255 HValue* mul = AddInstruction( |
1068 HMul::New(zone, context, capacity, elements_size_value)); | 1256 HMul::New(zone, context, capacity, elements_size_value)); |
1069 mul->ChangeRepresentation(Representation::Integer32()); | 1257 mul->ChangeRepresentation(Representation::Integer32()); |
(...skipping 19 matching lines...) Expand all Loading... |
1089 } | 1277 } |
1090 | 1278 |
1091 HValue* elements = | 1279 HValue* elements = |
1092 AddInstruction(new(zone) HAllocate(context, total_size, | 1280 AddInstruction(new(zone) HAllocate(context, total_size, |
1093 HType::JSArray(), flags)); | 1281 HType::JSArray(), flags)); |
1094 | 1282 |
1095 Factory* factory = isolate()->factory(); | 1283 Factory* factory = isolate()->factory(); |
1096 Handle<Map> map = IsFastDoubleElementsKind(kind) | 1284 Handle<Map> map = IsFastDoubleElementsKind(kind) |
1097 ? factory->fixed_double_array_map() | 1285 ? factory->fixed_double_array_map() |
1098 : factory->fixed_array_map(); | 1286 : factory->fixed_array_map(); |
1099 BuildStoreMap(elements, map, BailoutId::StubEntry()); | 1287 BuildStoreMap(elements, map, ast_id); |
1100 | 1288 |
1101 Handle<String> fixed_array_length_field_name = factory->length_field_string(); | 1289 Handle<String> fixed_array_length_field_name = factory->length_field_string(); |
1102 HInstruction* store_length = | 1290 HInstruction* store_length = |
1103 new(zone) HStoreNamedField(elements, fixed_array_length_field_name, | 1291 new(zone) HStoreNamedField(elements, fixed_array_length_field_name, |
1104 capacity, true, FixedArray::kLengthOffset); | 1292 capacity, true, FixedArray::kLengthOffset); |
1105 AddInstruction(store_length); | 1293 AddInstruction(store_length); |
1106 AddSimulate(BailoutId::StubEntry(), FIXED_SIMULATE); | 1294 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
1107 | 1295 |
1108 return elements; | 1296 return elements; |
1109 } | 1297 } |
1110 | 1298 |
1111 | 1299 |
1112 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, | 1300 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, |
1113 HValue* map, | 1301 HValue* map, |
1114 BailoutId id) { | 1302 BailoutId id) { |
1115 Zone* zone = this->zone(); | 1303 Zone* zone = this->zone(); |
1116 Factory* factory = isolate()->factory(); | 1304 Factory* factory = isolate()->factory(); |
1117 Handle<String> map_field_name = factory->map_field_string(); | 1305 Handle<String> map_field_name = factory->map_field_string(); |
1118 HInstruction* store_map = | 1306 HInstruction* store_map = |
1119 new(zone) HStoreNamedField(object, map_field_name, map, | 1307 new(zone) HStoreNamedField(object, map_field_name, map, |
1120 true, JSObject::kMapOffset); | 1308 true, JSObject::kMapOffset); |
1121 store_map->SetGVNFlag(kChangesMaps); | 1309 store_map->SetGVNFlag(kChangesMaps); |
1122 AddInstruction(store_map); | 1310 AddInstruction(store_map); |
1123 AddSimulate(id, FIXED_SIMULATE); | 1311 AddSimulate(id, REMOVABLE_SIMULATE); |
1124 return store_map; | 1312 return store_map; |
1125 } | 1313 } |
1126 | 1314 |
1127 | 1315 |
1128 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, | 1316 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, |
1129 Handle<Map> map, | 1317 Handle<Map> map, |
1130 BailoutId id) { | 1318 BailoutId id) { |
1131 Zone* zone = this->zone(); | 1319 Zone* zone = this->zone(); |
1132 HValue* map_constant = | 1320 HValue* map_constant = |
1133 AddInstruction(new(zone) HConstant(map, Representation::Tagged())); | 1321 AddInstruction(new(zone) HConstant(map, Representation::Tagged())); |
1134 return BuildStoreMap(object, map_constant, id); | 1322 return BuildStoreMap(object, map_constant, id); |
1135 } | 1323 } |
1136 | 1324 |
1137 | 1325 |
1138 void HGraphBuilder::BuildCopyElements(HContext* context, | 1326 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, |
| 1327 HValue* old_capacity) { |
| 1328 Zone* zone = this->zone(); |
| 1329 HValue* half_old_capacity = |
| 1330 AddInstruction(HShr::New(zone, context, old_capacity, |
| 1331 graph_->GetConstant1())); |
| 1332 half_old_capacity->ChangeRepresentation(Representation::Integer32()); |
| 1333 half_old_capacity->ClearFlag(HValue::kCanOverflow); |
| 1334 |
| 1335 HValue* new_capacity = AddInstruction( |
| 1336 HAdd::New(zone, context, half_old_capacity, old_capacity)); |
| 1337 new_capacity->ChangeRepresentation(Representation::Integer32()); |
| 1338 new_capacity->ClearFlag(HValue::kCanOverflow); |
| 1339 |
| 1340 HValue* min_growth = |
| 1341 AddInstruction(new(zone) HConstant(16, Representation::Integer32())); |
| 1342 |
| 1343 new_capacity = AddInstruction( |
| 1344 HAdd::New(zone, context, new_capacity, min_growth)); |
| 1345 new_capacity->ChangeRepresentation(Representation::Integer32()); |
| 1346 new_capacity->ClearFlag(HValue::kCanOverflow); |
| 1347 |
| 1348 return new_capacity; |
| 1349 } |
| 1350 |
| 1351 |
| 1352 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) { |
| 1353 Zone* zone = this->zone(); |
| 1354 Heap* heap = isolate()->heap(); |
| 1355 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize |
| 1356 : kPointerSize; |
| 1357 int max_size = heap->MaxNewSpaceAllocationSize() / element_size; |
| 1358 max_size -= JSArray::kSize / element_size; |
| 1359 HConstant* max_size_constant = |
| 1360 new(zone) HConstant(max_size, Representation::Integer32()); |
| 1361 AddInstruction(max_size_constant); |
| 1362 // Since we're forcing Integer32 representation for this HBoundsCheck, |
| 1363 // there's no need to Smi-check the index. |
| 1364 AddInstruction(new(zone) |
| 1365 HBoundsCheck(length, max_size_constant, |
| 1366 DONT_ALLOW_SMI_KEY, Representation::Integer32())); |
| 1367 } |
| 1368 |
| 1369 |
| 1370 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, |
| 1371 HValue* elements, |
| 1372 ElementsKind kind, |
| 1373 HValue* length, |
| 1374 HValue* new_capacity, |
| 1375 BailoutId ast_id) { |
| 1376 Zone* zone = this->zone(); |
| 1377 HValue* context = environment()->LookupContext(); |
| 1378 |
| 1379 BuildNewSpaceArrayCheck(new_capacity, kind); |
| 1380 |
| 1381 HValue* new_elements = |
| 1382 BuildAllocateElements(context, kind, new_capacity, ast_id); |
| 1383 |
| 1384 BuildCopyElements(context, elements, kind, |
| 1385 new_elements, kind, |
| 1386 length, new_capacity, ast_id); |
| 1387 |
| 1388 Factory* factory = isolate()->factory(); |
| 1389 HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField( |
| 1390 object, |
| 1391 factory->elements_field_string(), |
| 1392 new_elements, true, |
| 1393 JSArray::kElementsOffset)); |
| 1394 elements_store->SetGVNFlag(kChangesElementsPointer); |
| 1395 |
| 1396 return new_elements; |
| 1397 } |
| 1398 |
| 1399 |
| 1400 void HGraphBuilder::BuildFillElementsWithHole(HValue* context, |
| 1401 HValue* elements, |
| 1402 ElementsKind elements_kind, |
| 1403 HValue* from, |
| 1404 HValue* to, |
| 1405 BailoutId ast_id) { |
| 1406 // Fast elements kinds need to be initialized in case statements below cause |
| 1407 // a garbage collection. |
| 1408 Factory* factory = isolate()->factory(); |
| 1409 |
| 1410 double nan_double = FixedDoubleArray::hole_nan_as_double(); |
| 1411 Zone* zone = this->zone(); |
| 1412 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) |
| 1413 ? AddInstruction(new(zone) HConstant(factory->the_hole_value(), |
| 1414 Representation::Tagged())) |
| 1415 : AddInstruction(new(zone) HConstant(nan_double, |
| 1416 Representation::Double())); |
| 1417 |
| 1418 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, ast_id); |
| 1419 |
| 1420 HValue* key = builder.BeginBody(from, to, Token::LT); |
| 1421 |
| 1422 AddInstruction(new(zone) HStoreKeyed(elements, key, hole, elements_kind)); |
| 1423 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
| 1424 |
| 1425 builder.EndBody(); |
| 1426 } |
| 1427 |
| 1428 |
| 1429 void HGraphBuilder::BuildCopyElements(HValue* context, |
1139 HValue* from_elements, | 1430 HValue* from_elements, |
1140 ElementsKind from_elements_kind, | 1431 ElementsKind from_elements_kind, |
1141 HValue* to_elements, | 1432 HValue* to_elements, |
1142 ElementsKind to_elements_kind, | 1433 ElementsKind to_elements_kind, |
1143 HValue* length) { | 1434 HValue* length, |
1144 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, | 1435 HValue* capacity, |
1145 BailoutId::StubEntry()); | 1436 BailoutId ast_id) { |
| 1437 bool pre_fill_with_holes = |
| 1438 IsFastDoubleElementsKind(from_elements_kind) && |
| 1439 IsFastObjectElementsKind(to_elements_kind); |
1146 | 1440 |
1147 HValue* key = builder.BeginBody(graph()->GetConstant0(), | 1441 if (pre_fill_with_holes) { |
1148 length, Token::LT); | 1442 // If the copy might trigger a GC, make sure that the FixedArray is |
| 1443 // pre-initialized with holes to make sure that it's always in a consistent |
| 1444 // state. |
| 1445 BuildFillElementsWithHole(context, to_elements, to_elements_kind, |
| 1446 graph()->GetConstant0(), capacity, ast_id); |
| 1447 } |
| 1448 |
| 1449 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, ast_id); |
| 1450 |
| 1451 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT); |
1149 | 1452 |
1150 HValue* element = | 1453 HValue* element = |
1151 AddInstruction(new(zone()) HLoadKeyed(from_elements, key, NULL, | 1454 AddInstruction(new(zone()) HLoadKeyed(from_elements, key, NULL, |
1152 from_elements_kind, | 1455 from_elements_kind, |
1153 ALLOW_RETURN_HOLE)); | 1456 ALLOW_RETURN_HOLE)); |
1154 | 1457 |
1155 AddInstruction(new(zone()) HStoreKeyed(to_elements, key, element, | 1458 AddInstruction(new(zone()) HStoreKeyed(to_elements, key, element, |
1156 to_elements_kind)); | 1459 to_elements_kind)); |
1157 AddSimulate(BailoutId::StubEntry(), REMOVABLE_SIMULATE); | 1460 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
1158 | 1461 |
1159 builder.EndBody(); | 1462 builder.EndBody(); |
| 1463 |
| 1464 if (!pre_fill_with_holes && length != capacity) { |
| 1465 // Fill unused capacity with the hole. |
| 1466 BuildFillElementsWithHole(context, to_elements, to_elements_kind, |
| 1467 key, capacity, ast_id); |
| 1468 } |
1160 } | 1469 } |
1161 | 1470 |
1162 | 1471 |
1163 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, | 1472 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, |
1164 TypeFeedbackOracle* oracle) | 1473 TypeFeedbackOracle* oracle) |
1165 : HGraphBuilder(info), | 1474 : HGraphBuilder(info), |
1166 function_state_(NULL), | 1475 function_state_(NULL), |
1167 initial_function_state_(this, info, oracle, NORMAL_RETURN), | 1476 initial_function_state_(this, info, oracle, NORMAL_RETURN), |
1168 ast_context_(NULL), | 1477 ast_context_(NULL), |
1169 break_scope_(NULL), | 1478 break_scope_(NULL), |
(...skipping 5629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6799 return new(zone()) HLoadKeyedGeneric(context, object, key); | 7108 return new(zone()) HLoadKeyedGeneric(context, object, key); |
6800 } | 7109 } |
6801 | 7110 |
6802 | 7111 |
6803 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( | 7112 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( |
6804 HValue* object, | 7113 HValue* object, |
6805 HValue* key, | 7114 HValue* key, |
6806 HValue* val, | 7115 HValue* val, |
6807 HValue* dependency, | 7116 HValue* dependency, |
6808 Handle<Map> map, | 7117 Handle<Map> map, |
6809 bool is_store) { | 7118 bool is_store, |
| 7119 KeyedAccessStoreMode store_mode) { |
6810 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map, | 7120 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map, |
6811 zone(), dependency); | 7121 zone(), dependency); |
6812 AddInstruction(mapcheck); | 7122 AddInstruction(mapcheck); |
6813 if (dependency) { | 7123 if (dependency) { |
6814 mapcheck->ClearGVNFlag(kDependsOnElementsKind); | 7124 mapcheck->ClearGVNFlag(kDependsOnElementsKind); |
6815 } | 7125 } |
6816 return BuildUncheckedMonomorphicElementAccess( | 7126 return BuildUncheckedMonomorphicElementAccess( |
6817 object, key, val, | 7127 object, key, val, |
6818 mapcheck, map->instance_type() == JS_ARRAY_TYPE, | 7128 mapcheck, map->instance_type() == JS_ARRAY_TYPE, |
6819 map->elements_kind(), is_store); | 7129 map->elements_kind(), is_store, store_mode); |
6820 } | 7130 } |
6821 | 7131 |
6822 | 7132 |
6823 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( | 7133 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( |
6824 HValue* object, | 7134 HValue* object, |
6825 HValue* key, | 7135 HValue* key, |
6826 HValue* val, | 7136 HValue* val, |
6827 SmallMapList* maps) { | 7137 SmallMapList* maps) { |
6828 // For polymorphic loads of similar elements kinds (i.e. all tagged or all | 7138 // For polymorphic loads of similar elements kinds (i.e. all tagged or all |
6829 // double), always use the "worst case" code without a transition. This is | 7139 // double), always use the "worst case" code without a transition. This is |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6864 } | 7174 } |
6865 } | 7175 } |
6866 if (!has_double_maps && !has_smi_or_object_maps) return NULL; | 7176 if (!has_double_maps && !has_smi_or_object_maps) return NULL; |
6867 | 7177 |
6868 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone()); | 7178 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone()); |
6869 AddInstruction(check_maps); | 7179 AddInstruction(check_maps); |
6870 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( | 7180 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( |
6871 object, key, val, check_maps, | 7181 object, key, val, check_maps, |
6872 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, | 7182 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, |
6873 most_general_consolidated_map->elements_kind(), | 7183 most_general_consolidated_map->elements_kind(), |
6874 false); | 7184 false, STANDARD_STORE); |
6875 return instr; | 7185 return instr; |
6876 } | 7186 } |
6877 | 7187 |
6878 | 7188 |
6879 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( | 7189 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( |
6880 HValue* object, | 7190 HValue* object, |
6881 HValue* key, | 7191 HValue* key, |
6882 HValue* val, | 7192 HValue* val, |
6883 Expression* prop, | 7193 Expression* prop, |
6884 BailoutId ast_id, | 7194 BailoutId ast_id, |
6885 int position, | 7195 int position, |
6886 bool is_store, | 7196 bool is_store, |
| 7197 KeyedAccessStoreMode store_mode, |
6887 bool* has_side_effects) { | 7198 bool* has_side_effects) { |
6888 *has_side_effects = false; | 7199 *has_side_effects = false; |
6889 AddInstruction(new(zone()) HCheckNonSmi(object)); | 7200 AddInstruction(new(zone()) HCheckNonSmi(object)); |
6890 SmallMapList* maps = prop->GetReceiverTypes(); | 7201 SmallMapList* maps = prop->GetReceiverTypes(); |
6891 bool todo_external_array = false; | 7202 bool todo_external_array = false; |
6892 | 7203 |
6893 if (!is_store) { | 7204 if (!is_store) { |
6894 HInstruction* consolidated_load = | 7205 HInstruction* consolidated_load = |
6895 TryBuildConsolidatedElementLoad(object, key, val, maps); | 7206 TryBuildConsolidatedElementLoad(object, key, val, maps); |
6896 if (consolidated_load != NULL) { | 7207 if (consolidated_load != NULL) { |
6897 AddInstruction(consolidated_load); | |
6898 *has_side_effects |= consolidated_load->HasObservableSideEffects(); | 7208 *has_side_effects |= consolidated_load->HasObservableSideEffects(); |
6899 if (position != RelocInfo::kNoPosition) { | 7209 if (position != RelocInfo::kNoPosition) { |
6900 consolidated_load->set_position(position); | 7210 consolidated_load->set_position(position); |
6901 } | 7211 } |
6902 return consolidated_load; | 7212 return consolidated_load; |
6903 } | 7213 } |
6904 } | 7214 } |
6905 | 7215 |
6906 static const int kNumElementTypes = kElementsKindCount; | 7216 static const int kNumElementTypes = kElementsKindCount; |
6907 bool type_todo[kNumElementTypes]; | 7217 bool type_todo[kNumElementTypes]; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6954 } | 7264 } |
6955 | 7265 |
6956 // If only one map is left after transitioning, handle this case | 7266 // If only one map is left after transitioning, handle this case |
6957 // monomorphically. | 7267 // monomorphically. |
6958 if (num_untransitionable_maps == 1) { | 7268 if (num_untransitionable_maps == 1) { |
6959 HInstruction* instr = NULL; | 7269 HInstruction* instr = NULL; |
6960 if (untransitionable_map->has_slow_elements_kind()) { | 7270 if (untransitionable_map->has_slow_elements_kind()) { |
6961 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) | 7271 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) |
6962 : BuildLoadKeyedGeneric(object, key)); | 7272 : BuildLoadKeyedGeneric(object, key)); |
6963 } else { | 7273 } else { |
6964 instr = AddInstruction(BuildMonomorphicElementAccess( | 7274 instr = BuildMonomorphicElementAccess( |
6965 object, key, val, transition, untransitionable_map, is_store)); | 7275 object, key, val, transition, untransitionable_map, is_store, |
| 7276 store_mode); |
6966 } | 7277 } |
6967 *has_side_effects |= instr->HasObservableSideEffects(); | 7278 *has_side_effects |= instr->HasObservableSideEffects(); |
6968 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 7279 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
6969 return is_store ? NULL : instr; | 7280 return is_store ? NULL : instr; |
6970 } | 7281 } |
6971 | 7282 |
6972 HInstruction* checkspec = | 7283 HInstruction* checkspec = |
6973 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone())); | 7284 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone())); |
6974 HBasicBlock* join = graph()->CreateBasicBlock(); | 7285 HBasicBlock* join = graph()->CreateBasicBlock(); |
6975 | 7286 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7036 typecheck->SetSuccessorAt(1, if_fastobject); | 7347 typecheck->SetSuccessorAt(1, if_fastobject); |
7037 current_block()->Finish(typecheck); | 7348 current_block()->Finish(typecheck); |
7038 | 7349 |
7039 set_current_block(if_jsarray); | 7350 set_current_block(if_jsarray); |
7040 HInstruction* length; | 7351 HInstruction* length; |
7041 length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck, | 7352 length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck, |
7042 HType::Smi())); | 7353 HType::Smi())); |
7043 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); | 7354 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); |
7044 access = AddInstruction(BuildFastElementAccess( | 7355 access = AddInstruction(BuildFastElementAccess( |
7045 elements, checked_key, val, elements_kind_branch, | 7356 elements, checked_key, val, elements_kind_branch, |
7046 elements_kind, is_store)); | 7357 elements_kind, is_store, STANDARD_STORE)); |
7047 if (!is_store) { | 7358 if (!is_store) { |
7048 Push(access); | 7359 Push(access); |
7049 } | 7360 } |
7050 | 7361 |
7051 *has_side_effects |= access->HasObservableSideEffects(); | 7362 *has_side_effects |= access->HasObservableSideEffects(); |
7052 if (position != -1) { | 7363 if (position != -1) { |
7053 access->set_position(position); | 7364 access->set_position(position); |
7054 } | 7365 } |
7055 if_jsarray->Goto(join); | 7366 if_jsarray->Goto(join); |
7056 | 7367 |
7057 set_current_block(if_fastobject); | 7368 set_current_block(if_fastobject); |
7058 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); | 7369 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
7059 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); | 7370 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); |
7060 access = AddInstruction(BuildFastElementAccess( | 7371 access = AddInstruction(BuildFastElementAccess( |
7061 elements, checked_key, val, elements_kind_branch, | 7372 elements, checked_key, val, elements_kind_branch, |
7062 elements_kind, is_store)); | 7373 elements_kind, is_store, STANDARD_STORE)); |
7063 } else if (elements_kind == DICTIONARY_ELEMENTS) { | 7374 } else if (elements_kind == DICTIONARY_ELEMENTS) { |
7064 if (is_store) { | 7375 if (is_store) { |
7065 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); | 7376 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); |
7066 } else { | 7377 } else { |
7067 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); | 7378 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); |
7068 } | 7379 } |
7069 } else { // External array elements. | 7380 } else { // External array elements. |
7070 access = AddInstruction(BuildExternalArrayElementAccess( | 7381 access = AddInstruction(BuildExternalArrayElementAccess( |
7071 external_elements, checked_key, val, | 7382 external_elements, checked_key, val, |
7072 elements_kind_branch, elements_kind, is_store)); | 7383 elements_kind_branch, elements_kind, is_store)); |
(...skipping 25 matching lines...) Expand all Loading... |
7098 int position, | 7409 int position, |
7099 bool is_store, | 7410 bool is_store, |
7100 bool* has_side_effects) { | 7411 bool* has_side_effects) { |
7101 ASSERT(!expr->IsPropertyName()); | 7412 ASSERT(!expr->IsPropertyName()); |
7102 HInstruction* instr = NULL; | 7413 HInstruction* instr = NULL; |
7103 if (expr->IsMonomorphic()) { | 7414 if (expr->IsMonomorphic()) { |
7104 Handle<Map> map = expr->GetMonomorphicReceiverType(); | 7415 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
7105 if (map->has_slow_elements_kind()) { | 7416 if (map->has_slow_elements_kind()) { |
7106 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) | 7417 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) |
7107 : BuildLoadKeyedGeneric(obj, key); | 7418 : BuildLoadKeyedGeneric(obj, key); |
| 7419 AddInstruction(instr); |
7108 } else { | 7420 } else { |
7109 AddInstruction(new(zone()) HCheckNonSmi(obj)); | 7421 AddInstruction(new(zone()) HCheckNonSmi(obj)); |
7110 instr = BuildMonomorphicElementAccess(obj, key, val, NULL, map, is_store); | 7422 instr = BuildMonomorphicElementAccess( |
| 7423 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); |
7111 } | 7424 } |
7112 } else if (expr->GetReceiverTypes() != NULL && | 7425 } else if (expr->GetReceiverTypes() != NULL && |
7113 !expr->GetReceiverTypes()->is_empty()) { | 7426 !expr->GetReceiverTypes()->is_empty()) { |
7114 return HandlePolymorphicElementAccess( | 7427 return HandlePolymorphicElementAccess( |
7115 obj, key, val, expr, ast_id, position, is_store, has_side_effects); | 7428 obj, key, val, expr, ast_id, position, is_store, |
| 7429 expr->GetStoreMode(), has_side_effects); |
7116 } else { | 7430 } else { |
7117 if (is_store) { | 7431 if (is_store) { |
7118 instr = BuildStoreKeyedGeneric(obj, key, val); | 7432 instr = BuildStoreKeyedGeneric(obj, key, val); |
7119 } else { | 7433 } else { |
7120 instr = BuildLoadKeyedGeneric(obj, key); | 7434 instr = BuildLoadKeyedGeneric(obj, key); |
7121 } | 7435 } |
| 7436 AddInstruction(instr); |
7122 } | 7437 } |
7123 if (position != RelocInfo::kNoPosition) instr->set_position(position); | 7438 if (position != RelocInfo::kNoPosition) instr->set_position(position); |
7124 AddInstruction(instr); | |
7125 *has_side_effects = instr->HasObservableSideEffects(); | 7439 *has_side_effects = instr->HasObservableSideEffects(); |
7126 return instr; | 7440 return instr; |
7127 } | 7441 } |
7128 | 7442 |
7129 | 7443 |
7130 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( | 7444 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( |
7131 HValue* object, | 7445 HValue* object, |
7132 HValue* key, | 7446 HValue* key, |
7133 HValue* value) { | 7447 HValue* value) { |
7134 HValue* context = environment()->LookupContext(); | 7448 HValue* context = environment()->LookupContext(); |
(...skipping 3814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10949 } | 11263 } |
10950 } | 11264 } |
10951 | 11265 |
10952 #ifdef DEBUG | 11266 #ifdef DEBUG |
10953 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 11267 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
10954 if (allocator_ != NULL) allocator_->Verify(); | 11268 if (allocator_ != NULL) allocator_->Verify(); |
10955 #endif | 11269 #endif |
10956 } | 11270 } |
10957 | 11271 |
10958 } } // namespace v8::internal | 11272 } } // namespace v8::internal |
OLD | NEW |