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

Side by Side Diff: src/hydrogen.cc

Issue 12221064: Implement many KeyedStoreStubs using Crankshaft (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Final review feedback Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/ia32/code-stubs-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/ia32/code-stubs-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698