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

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: 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
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 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
637 HConstant* HGraph::GetConstantHole() { 640 HConstant* HGraph::GetConstantHole() {
638 return GetConstant(&constant_hole_, isolate()->factory()->the_hole_value()); 641 return GetConstant(&constant_hole_, isolate()->factory()->the_hole_value());
639 } 642 }
640 643
641 644
642 HGraphBuilder::CheckBuilder::CheckBuilder(HGraphBuilder* builder, BailoutId id) 645 HGraphBuilder::CheckBuilder::CheckBuilder(HGraphBuilder* builder, BailoutId id)
643 : builder_(builder), 646 : builder_(builder),
644 finished_(false), 647 finished_(false),
645 id_(id) { 648 id_(id) {
646 HEnvironment* env = builder->environment(); 649 HEnvironment* env = builder->environment();
647 failure_block_ = builder->CreateBasicBlock(env->Copy()); 650 failure_block_ = builder->CreateBasicBlock(env->CopyWithoutHistory());
648 merge_block_ = builder->CreateBasicBlock(env->Copy()); 651 merge_block_ = builder->CreateBasicBlock(env->CopyWithoutHistory());
649 } 652 }
650 653
651 654
652 void HGraphBuilder::CheckBuilder::CheckNotUndefined(HValue* value) { 655 HValue* HGraphBuilder::CheckBuilder::CheckNotUndefined(HValue* value) {
653 HEnvironment* env = builder_->environment(); 656 HEnvironment* env = builder_->environment();
654 HIsNilAndBranch* compare = 657 HIsNilAndBranch* compare =
655 new(zone()) HIsNilAndBranch(value, kStrictEquality, kUndefinedValue); 658 new(zone()) HIsNilAndBranch(value, kStrictEquality, kUndefinedValue);
656 HBasicBlock* success_block = builder_->CreateBasicBlock(env->Copy()); 659 HBasicBlock* success_block =
657 HBasicBlock* failure_block = builder_->CreateBasicBlock(env->Copy()); 660 builder_->CreateBasicBlock(env->CopyWithoutHistory());
661 HBasicBlock* failure_block =
662 builder_->CreateBasicBlock(env->CopyWithoutHistory());
658 compare->SetSuccessorAt(0, failure_block); 663 compare->SetSuccessorAt(0, failure_block);
659 compare->SetSuccessorAt(1, success_block); 664 compare->SetSuccessorAt(1, success_block);
660 failure_block->Goto(failure_block_); 665 failure_block->Goto(failure_block_);
661 builder_->current_block()->Finish(compare); 666 builder_->current_block()->Finish(compare);
662 builder_->set_current_block(success_block); 667 builder_->set_current_block(success_block);
668 return compare;
663 } 669 }
664 670
665 671
666 void HGraphBuilder::CheckBuilder::CheckIntegerEq(HValue* left, HValue* right) { 672 HValue* HGraphBuilder::CheckBuilder::CheckIntegerCompare(HValue* left,
673 HValue* right,
674 Token::Value op) {
667 HEnvironment* env = builder_->environment(); 675 HEnvironment* env = builder_->environment();
668 HCompareIDAndBranch* compare = 676 HCompareIDAndBranch* compare =
669 new(zone()) HCompareIDAndBranch(left, right, Token::EQ); 677 new(zone()) HCompareIDAndBranch(left, right, op);
670 compare->AssumeRepresentation(Representation::Integer32()); 678 compare->AssumeRepresentation(Representation::Integer32());
671 HBasicBlock* success_block = builder_->CreateBasicBlock(env->Copy()); 679 HBasicBlock* success_block =
672 HBasicBlock* failure_block = builder_->CreateBasicBlock(env->Copy()); 680 builder_->CreateBasicBlock(env->CopyWithoutHistory());
681 HBasicBlock* failure_block =
682 builder_->CreateBasicBlock(env->CopyWithoutHistory());
673 compare->SetSuccessorAt(0, success_block); 683 compare->SetSuccessorAt(0, success_block);
674 compare->SetSuccessorAt(1, failure_block); 684 compare->SetSuccessorAt(1, failure_block);
675 failure_block->Goto(failure_block_); 685 failure_block->Goto(failure_block_);
676 builder_->current_block()->Finish(compare); 686 builder_->current_block()->Finish(compare);
677 builder_->set_current_block(success_block); 687 builder_->set_current_block(success_block);
688 return compare;
678 } 689 }
679 690
680 691
692 HValue* HGraphBuilder::CheckBuilder::CheckIntegerEq(HValue* left,
693 HValue* right) {
694 return CheckIntegerCompare(left, right, Token::EQ);
695 }
696
697
681 void HGraphBuilder::CheckBuilder::End() { 698 void HGraphBuilder::CheckBuilder::End() {
682 ASSERT(!finished_); 699 ASSERT(!finished_);
683 builder_->current_block()->Goto(merge_block_); 700 builder_->current_block()->Goto(merge_block_);
684 failure_block_->FinishExitWithDeoptimization(HDeoptimize::kUseAll); 701 failure_block_->FinishExitWithDeoptimization(HDeoptimize::kUseAll);
685 failure_block_->SetJoinId(id_); 702 failure_block_->SetJoinId(id_);
686 builder_->set_current_block(merge_block_); 703 builder_->set_current_block(merge_block_);
687 merge_block_->SetJoinId(id_); 704 merge_block_->SetJoinId(id_);
688 finished_ = true; 705 finished_ = true;
689 } 706 }
690 707
691 708
692 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, BailoutId id) 709 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, BailoutId id)
693 : builder_(builder), 710 : builder_(builder),
694 finished_(false), 711 finished_(false),
712 did_else_(false),
695 id_(id) { 713 id_(id) {
696 HEnvironment* env = builder->environment(); 714 HEnvironment* env = builder->environment();
697 first_true_block_ = builder->CreateBasicBlock(env->Copy()); 715 first_true_block_ = builder->CreateBasicBlock(env->Copy());
698 last_true_block_ = NULL; 716 last_true_block_ = NULL;
699 first_false_block_ = builder->CreateBasicBlock(env->Copy()); 717 first_false_block_ = builder->CreateBasicBlock(env->Copy());
700 } 718 }
701 719
702 720
703 HInstruction* HGraphBuilder::IfBuilder::BeginTrue( 721 HInstruction* HGraphBuilder::IfBuilder::BeginIf(
704 HValue* left, 722 HValue* left,
705 HValue* right, 723 HValue* right,
706 Token::Value token, 724 Token::Value token,
707 Representation input_representation) { 725 Representation input_representation) {
708 HCompareIDAndBranch* compare = 726 HCompareIDAndBranch* compare =
709 new(zone()) HCompareIDAndBranch(left, right, token); 727 new(zone()) HCompareIDAndBranch(left, right, token);
710 compare->set_observed_input_representation(input_representation, 728 compare->set_observed_input_representation(input_representation,
711 input_representation); 729 input_representation);
712 compare->ChangeRepresentation(input_representation); 730 compare->ChangeRepresentation(input_representation);
713 compare->SetSuccessorAt(0, first_true_block_); 731 compare->SetSuccessorAt(0, first_true_block_);
714 compare->SetSuccessorAt(1, first_false_block_); 732 compare->SetSuccessorAt(1, first_false_block_);
715 builder_->current_block()->Finish(compare); 733 builder_->current_block()->Finish(compare);
716 builder_->set_current_block(first_true_block_); 734 builder_->set_current_block(first_true_block_);
717 return compare; 735 return compare;
718 } 736 }
719 737
720 738
721 void HGraphBuilder::IfBuilder::BeginFalse() { 739 HInstruction* HGraphBuilder::IfBuilder::BeginIfObjectsEqual(
740 HValue* left,
741 HValue* right) {
742 HCompareObjectEqAndBranch* compare =
743 new(zone()) HCompareObjectEqAndBranch(left, right);
744 compare->SetSuccessorAt(0, first_true_block_);
745 compare->SetSuccessorAt(1, first_false_block_);
746 builder_->current_block()->Finish(compare);
747 builder_->set_current_block(first_true_block_);
748 return compare;
749 }
750
751
752 HInstruction* HGraphBuilder::IfBuilder::BeginIfMapsEqual(HValue* value,
753 Handle<Map> map) {
754 HCompareMap* compare = new(zone())
755 HCompareMap(value, map, first_true_block_, first_false_block_);
756 builder_->current_block()->Finish(compare);
757 builder_->set_current_block(first_true_block_);
758 return compare;
759 }
760
761
762 void HGraphBuilder::IfBuilder::BeginElse() {
722 last_true_block_ = builder_->current_block(); 763 last_true_block_ = builder_->current_block();
723 ASSERT(!last_true_block_->IsFinished()); 764 ASSERT(!last_true_block_->IsFinished());
724 builder_->set_current_block(first_false_block_); 765 builder_->set_current_block(first_false_block_);
766 did_else_ = true;
725 } 767 }
726 768
727 769
728 void HGraphBuilder::IfBuilder::End() { 770 void HGraphBuilder::IfBuilder::End() {
729 ASSERT(!finished_); 771 ASSERT(!finished_);
772 if (!did_else_) BeginElse();
730 ASSERT(!last_true_block_->IsFinished()); 773 ASSERT(!last_true_block_->IsFinished());
731 HBasicBlock* last_false_block = builder_->current_block(); 774 HBasicBlock* last_false_block = builder_->current_block();
732 ASSERT(!last_false_block->IsFinished()); 775 ASSERT(!last_false_block->IsFinished());
733 HEnvironment* merge_env = 776 HEnvironment* merge_env =
734 last_true_block_->last_environment()->Copy(); 777 last_true_block_->last_environment()->CopyWithoutHistory();
735 merge_block_ = builder_->CreateBasicBlock(merge_env); 778 merge_block_ = builder_->CreateBasicBlock(merge_env);
736 last_true_block_->Goto(merge_block_); 779 last_true_block_->Goto(merge_block_);
737 last_false_block->Goto(merge_block_); 780 last_false_block->Goto(merge_block_);
738 merge_block_->SetJoinId(id_); 781 merge_block_->SetJoinId(id_);
739 builder_->set_current_block(merge_block_); 782 builder_->set_current_block(merge_block_);
740 finished_ = true; 783 finished_ = true;
741 } 784 }
742 785
743 786
744 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, 787 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder,
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
846 ASSERT(current_block() != NULL); 889 ASSERT(current_block() != NULL);
847 current_block()->AddInstruction(instr); 890 current_block()->AddInstruction(instr);
848 return instr; 891 return instr;
849 } 892 }
850 893
851 894
852 void HGraphBuilder::AddSimulate(BailoutId id, 895 void HGraphBuilder::AddSimulate(BailoutId id,
853 RemovableSimulate removable) { 896 RemovableSimulate removable) {
854 ASSERT(current_block() != NULL); 897 ASSERT(current_block() != NULL);
855 current_block()->AddSimulate(id, removable); 898 current_block()->AddSimulate(id, removable);
899 environment()->set_ast_id(id);
856 } 900 }
857 901
858 902
859 HBoundsCheck* HGraphBuilder::AddBoundsCheck(HValue* index, 903 HBoundsCheck* HGraphBuilder::AddBoundsCheck(HValue* index,
860 HValue* length, 904 HValue* length,
861 BoundsCheckKeyMode key_mode, 905 BoundsCheckKeyMode key_mode,
862 Representation r) { 906 Representation r) {
863 if (!index->type().IsSmi()) { 907 if (!index->type().IsSmi()) {
864 index = new(graph()->zone()) HCheckSmiOrInt32(index); 908 index = new(graph()->zone()) HCheckSmiOrInt32(index);
865 AddInstruction(HCheckSmiOrInt32::cast(index)); 909 AddInstruction(HCheckSmiOrInt32::cast(index));
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
943 } 987 }
944 } 988 }
945 989
946 990
947 HInstruction* HGraphBuilder::BuildFastElementAccess( 991 HInstruction* HGraphBuilder::BuildFastElementAccess(
948 HValue* elements, 992 HValue* elements,
949 HValue* checked_key, 993 HValue* checked_key,
950 HValue* val, 994 HValue* val,
951 HValue* load_dependency, 995 HValue* load_dependency,
952 ElementsKind elements_kind, 996 ElementsKind elements_kind,
953 bool is_store) { 997 bool is_store,
998 KeyedAccessStoreMode store_mode) {
954 Zone* zone = this->zone(); 999 Zone* zone = this->zone();
955 if (is_store) { 1000 if (is_store) {
956 ASSERT(val != NULL); 1001 ASSERT(val != NULL);
957 switch (elements_kind) { 1002 switch (elements_kind) {
958 case FAST_SMI_ELEMENTS: 1003 case FAST_SMI_ELEMENTS:
959 case FAST_HOLEY_SMI_ELEMENTS: 1004 case FAST_HOLEY_SMI_ELEMENTS:
960 // Smi-only arrays need a smi check. 1005 // Smi-only arrays need a smi check.
961 AddInstruction(new(zone) HCheckSmi(val)); 1006 AddInstruction(new(zone) HCheckSmi(val));
962 // Fall through. 1007 // Fall through.
963 case FAST_ELEMENTS: 1008 case FAST_ELEMENTS:
964 case FAST_HOLEY_ELEMENTS: 1009 case FAST_HOLEY_ELEMENTS:
965 case FAST_DOUBLE_ELEMENTS: 1010 case FAST_DOUBLE_ELEMENTS:
966 case FAST_HOLEY_DOUBLE_ELEMENTS: 1011 case FAST_HOLEY_DOUBLE_ELEMENTS:
967 return new(zone) HStoreKeyed(elements, checked_key, val, elements_kind); 1012 return new(zone) HStoreKeyed(elements, checked_key, val, elements_kind);
968 default: 1013 default:
969 UNREACHABLE(); 1014 UNREACHABLE();
970 return NULL; 1015 return NULL;
971 } 1016 }
972 } 1017 }
973 // It's an element load (!is_store). 1018 // It's an element load (!is_store).
974 return new(zone) HLoadKeyed(elements, 1019 return new(zone) HLoadKeyed(elements,
975 checked_key, 1020 checked_key,
976 load_dependency, 1021 load_dependency,
977 elements_kind); 1022 elements_kind);
978 } 1023 }
979 1024
980 1025
1026 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
1027 HValue* elements,
1028 ElementsKind kind,
1029 HValue* length,
1030 HValue* key,
1031 bool is_js_array) {
1032 BailoutId ast_id = environment()->ast_id();
1033 Zone* zone = this->zone();
1034 IfBuilder length_checker(this, ast_id);
1035
1036 length_checker.BeginIf(length, key, Token::EQ);
1037
1038 HValue* current_capacity =
1039 AddInstruction(new(zone) HFixedArrayBaseLength(elements));
1040
1041 IfBuilder capacity_checker(this, ast_id);
1042
1043 capacity_checker.BeginIf(length, current_capacity, Token::EQ);
1044
1045 HValue* context = environment()->LookupContext();
1046
1047 HValue* new_capacity =
1048 BuildNewElementsCapacity(context, current_capacity);
1049
1050 HValue* new_elements = BuildGrowElementsCapacity(object, elements,
1051 kind, length,
1052 new_capacity, ast_id);
1053
1054 environment()->Push(new_elements);
1055 capacity_checker.BeginElse();
1056
1057 environment()->Push(elements);
1058 capacity_checker.End();
1059
1060 if (is_js_array) {
1061 HValue* new_length = AddInstruction(
1062 HAdd::New(zone, context, length, graph_->GetConstant1()));
1063 new_length->ChangeRepresentation(Representation::Integer32());
1064 new_length->ClearFlag(HValue::kCanOverflow);
1065 AddSimulate(ast_id, REMOVABLE_SIMULATE);
1066
1067 Factory* factory = isolate()->factory();
1068 HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField(
1069 object,
1070 factory->length_field_string(),
1071 new_length, true,
1072 JSArray::kLengthOffset));
1073 length_store->SetGVNFlag(kChangesArrayLengths);
1074 AddSimulate(ast_id, REMOVABLE_SIMULATE);
1075 }
1076
1077 length_checker.BeginElse();
1078
1079 AddBoundsCheck(key, length, ALLOW_SMI_KEY);
1080 environment()->Push(elements);
1081
1082 length_checker.End();
1083
1084 return environment()->Pop();
1085 }
1086
1087
1088 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
1089 HValue* elements,
1090 ElementsKind kind,
1091 HValue* length) {
1092 BailoutId ast_id = environment()->ast_id();
1093 Zone* zone = this->zone();
1094 Heap* heap = isolate()->heap();
1095
1096 IfBuilder cow_checker(this, ast_id);
1097
1098 cow_checker.BeginIfMapsEqual(elements,
1099 Handle<Map>(heap->fixed_cow_array_map()));
1100
1101 HValue* capacity =
1102 AddInstruction(new(zone) HFixedArrayBaseLength(elements));
1103
1104 HValue* new_elements = BuildGrowElementsCapacity(object, elements,
1105 kind, length,
1106 capacity, ast_id);
1107
1108 environment()->Push(new_elements);
1109
1110 cow_checker.BeginElse();
1111
1112 environment()->Push(elements);
1113
1114 cow_checker.End();
1115
1116 return environment()->Pop();
1117 }
1118
1119
981 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( 1120 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
982 HValue* object, 1121 HValue* object,
983 HValue* key, 1122 HValue* key,
984 HValue* val, 1123 HValue* val,
985 HCheckMaps* mapcheck, 1124 HCheckMaps* mapcheck,
986 bool is_js_array, 1125 bool is_js_array,
987 ElementsKind elements_kind, 1126 ElementsKind elements_kind,
988 bool is_store, 1127 bool is_store,
1128 KeyedAccessStoreMode store_mode,
989 Representation checked_index_representation) { 1129 Representation checked_index_representation) {
1130 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array);
990 Zone* zone = this->zone(); 1131 Zone* zone = this->zone();
991 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency 1132 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
992 // on a HElementsTransition instruction. The flag can also be removed if the 1133 // on a HElementsTransition instruction. The flag can also be removed if the
993 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further 1134 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
994 // ElementsKind transitions. Finally, the dependency can be removed for stores 1135 // ElementsKind transitions. Finally, the dependency can be removed for stores
995 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the 1136 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
996 // generated store code. 1137 // generated store code.
997 if ((elements_kind == FAST_HOLEY_ELEMENTS) || 1138 if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
998 (elements_kind == FAST_ELEMENTS && is_store)) { 1139 (elements_kind == FAST_ELEMENTS && is_store)) {
999 if (mapcheck != NULL) { 1140 if (mapcheck != NULL) {
1000 mapcheck->ClearGVNFlag(kDependsOnElementsKind); 1141 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
1001 } 1142 }
1002 } 1143 }
1003 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); 1144 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
1004 bool fast_elements = IsFastObjectElementsKind(elements_kind); 1145 bool fast_elements = IsFastObjectElementsKind(elements_kind);
1005 HInstruction* elements = 1146 HValue* elements =
1006 AddInstruction(new(zone) HLoadElements(object, mapcheck)); 1147 AddInstruction(new(zone) HLoadElements(object, mapcheck));
1007 if (is_store && (fast_elements || fast_smi_only_elements)) { 1148 if (is_store && (fast_elements || fast_smi_only_elements) &&
1149 store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
1008 HCheckMaps* check_cow_map = new(zone) HCheckMaps( 1150 HCheckMaps* check_cow_map = new(zone) HCheckMaps(
1009 elements, isolate()->factory()->fixed_array_map(), zone); 1151 elements, isolate()->factory()->fixed_array_map(), zone);
1010 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); 1152 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
1011 AddInstruction(check_cow_map); 1153 AddInstruction(check_cow_map);
1012 } 1154 }
1013 HInstruction* length = NULL; 1155 HInstruction* length = NULL;
1014 HInstruction* checked_key = NULL;
1015 if (IsExternalArrayElementsKind(elements_kind)) {
1016 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
1017 checked_key = AddBoundsCheck(
1018 key, length, ALLOW_SMI_KEY, checked_index_representation);
1019 HLoadExternalArrayPointer* external_elements =
1020 new(zone) HLoadExternalArrayPointer(elements);
1021 AddInstruction(external_elements);
1022 return BuildExternalArrayElementAccess(
1023 external_elements, checked_key, val, mapcheck,
1024 elements_kind, is_store);
1025 }
1026 ASSERT(fast_smi_only_elements ||
1027 fast_elements ||
1028 IsFastDoubleElementsKind(elements_kind));
1029 if (is_js_array) { 1156 if (is_js_array) {
1030 length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck, 1157 length = AddInstruction(new(zone) HJSArrayLength(object, mapcheck,
1031 HType::Smi())); 1158 HType::Smi()));
1032 } else { 1159 } else {
1033 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); 1160 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
1034 } 1161 }
1035 checked_key = AddBoundsCheck( 1162 HValue* checked_key = NULL;
1036 key, length, ALLOW_SMI_KEY, checked_index_representation); 1163 if (IsExternalArrayElementsKind(elements_kind)) {
1037 return BuildFastElementAccess(elements, checked_key, val, mapcheck, 1164 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
1038 elements_kind, is_store); 1165 HLoadExternalArrayPointer* external_elements =
1166 new(zone) HLoadExternalArrayPointer(elements);
1167 AddInstruction(external_elements);
1168 BailoutId previous_id = environment()->ast_id();
1169 ASSERT(!previous_id.IsNone());
1170 IfBuilder length_checker(this, previous_id);
1171 length_checker.BeginIf(key, length, Token::LT);
1172 CheckBuilder negative_checker(this, previous_id);
1173 HValue* bounds_check = negative_checker.CheckIntegerCompare(
1174 key, graph()->GetConstant0(), Token::GTE);
1175 negative_checker.End();
1176 HInstruction* result = BuildExternalArrayElementAccess(
1177 external_elements, key, val, bounds_check,
1178 elements_kind, is_store);
1179 AddInstruction(result);
1180 length_checker.End();
1181 return result;
1182 } else {
1183 ASSERT(store_mode == STANDARD_STORE);
1184 checked_key = AddBoundsCheck(
1185 key, length, ALLOW_SMI_KEY, checked_index_representation);
1186 HLoadExternalArrayPointer* external_elements =
1187 new(zone) HLoadExternalArrayPointer(elements);
1188 AddInstruction(external_elements);
1189 return AddInstruction(BuildExternalArrayElementAccess(
1190 external_elements, checked_key, val, mapcheck,
1191 elements_kind, is_store));
1192 }
1193 }
1194 ASSERT(fast_smi_only_elements ||
1195 fast_elements ||
1196 IsFastDoubleElementsKind(elements_kind));
1197
1198 if (is_store && IsFastSmiElementsKind(elements_kind) &&
1199 val->type().IsTagged() && !val->type().IsSmi()) {
Jakob Kummerow 2013/03/14 15:00:20 I meant that you can remove the val->type().IsTagg
danno 2013/03/20 10:04:34 Done.
1200 AddInstruction(new(zone) HCheckSmi(val));
1201 }
1202
1203 if (IsGrowStoreMode(store_mode)) {
1204 elements = BuildCheckForCapacityGrow(object, elements, elements_kind,
1205 length, key, is_js_array);
1206 checked_key = key;
1207 } else {
1208 checked_key = AddBoundsCheck(
1209 key, length, ALLOW_SMI_KEY, checked_index_representation);
1210
1211 if (is_store && (fast_elements || fast_smi_only_elements)) {
1212 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
1213 elements = BuildCopyElementsOnWrite(object, elements, elements_kind,
1214 length);
1215 } else {
1216 HCheckMaps* check_cow_map = new(zone) HCheckMaps(
1217 elements, isolate()->factory()->fixed_array_map(), zone);
1218 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
1219 AddInstruction(check_cow_map);
1220 }
1221 }
1222 }
1223 return AddInstruction(
1224 BuildFastElementAccess(elements, checked_key, val, mapcheck,
1225 elements_kind, is_store, store_mode));
1039 } 1226 }
1040 1227
1041 1228
1042 HValue* HGraphBuilder::BuildAllocateElements(HContext* context, 1229 HValue* HGraphBuilder::BuildAllocateElements(HValue* context,
1043 ElementsKind kind, 1230 ElementsKind kind,
1044 HValue* capacity) { 1231 HValue* capacity,
1232 BailoutId ast_id) {
1045 Zone* zone = this->zone(); 1233 Zone* zone = this->zone();
1046 1234
1047 int elements_size = IsFastDoubleElementsKind(kind) 1235 int elements_size = IsFastDoubleElementsKind(kind)
1048 ? kDoubleSize : kPointerSize; 1236 ? kDoubleSize : kPointerSize;
1049 HConstant* elements_size_value = 1237 HConstant* elements_size_value =
1050 new(zone) HConstant(elements_size, Representation::Integer32()); 1238 new(zone) HConstant(elements_size, Representation::Integer32());
1051 AddInstruction(elements_size_value); 1239 AddInstruction(elements_size_value);
1052 HValue* mul = AddInstruction( 1240 HValue* mul = AddInstruction(
1053 HMul::New(zone, context, capacity, elements_size_value)); 1241 HMul::New(zone, context, capacity, elements_size_value));
1054 mul->ChangeRepresentation(Representation::Integer32()); 1242 mul->ChangeRepresentation(Representation::Integer32());
(...skipping 14 matching lines...) Expand all
1069 } 1257 }
1070 1258
1071 HValue* elements = 1259 HValue* elements =
1072 AddInstruction(new(zone) HAllocate(context, total_size, 1260 AddInstruction(new(zone) HAllocate(context, total_size,
1073 HType::JSArray(), flags)); 1261 HType::JSArray(), flags));
1074 1262
1075 Factory* factory = isolate()->factory(); 1263 Factory* factory = isolate()->factory();
1076 Handle<Map> map = IsFastDoubleElementsKind(kind) 1264 Handle<Map> map = IsFastDoubleElementsKind(kind)
1077 ? factory->fixed_double_array_map() 1265 ? factory->fixed_double_array_map()
1078 : factory->fixed_array_map(); 1266 : factory->fixed_array_map();
1079 BuildStoreMap(elements, map, BailoutId::StubEntry()); 1267 BuildStoreMap(elements, map, ast_id);
1080 1268
1081 Handle<String> fixed_array_length_field_name = factory->length_field_string(); 1269 Handle<String> fixed_array_length_field_name = factory->length_field_string();
1082 HInstruction* store_length = 1270 HInstruction* store_length =
1083 new(zone) HStoreNamedField(elements, fixed_array_length_field_name, 1271 new(zone) HStoreNamedField(elements, fixed_array_length_field_name,
1084 capacity, true, FixedArray::kLengthOffset); 1272 capacity, true, FixedArray::kLengthOffset);
1085 AddInstruction(store_length); 1273 AddInstruction(store_length);
1086 AddSimulate(BailoutId::StubEntry(), FIXED_SIMULATE); 1274 AddSimulate(ast_id, REMOVABLE_SIMULATE);
1087 1275
1088 return elements; 1276 return elements;
1089 } 1277 }
1090 1278
1091 1279
1092 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, 1280 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object,
1093 HValue* map, 1281 HValue* map,
1094 BailoutId id) { 1282 BailoutId id) {
1095 Zone* zone = this->zone(); 1283 Zone* zone = this->zone();
1096 Factory* factory = isolate()->factory(); 1284 Factory* factory = isolate()->factory();
1097 Handle<String> map_field_name = factory->map_field_string(); 1285 Handle<String> map_field_name = factory->map_field_string();
1098 HInstruction* store_map = 1286 HInstruction* store_map =
1099 new(zone) HStoreNamedField(object, map_field_name, map, 1287 new(zone) HStoreNamedField(object, map_field_name, map,
1100 true, JSObject::kMapOffset); 1288 true, JSObject::kMapOffset);
1101 store_map->SetGVNFlag(kChangesMaps); 1289 store_map->SetGVNFlag(kChangesMaps);
1102 AddInstruction(store_map); 1290 AddInstruction(store_map);
1103 AddSimulate(id, FIXED_SIMULATE); 1291 AddSimulate(id, REMOVABLE_SIMULATE);
1104 return store_map; 1292 return store_map;
1105 } 1293 }
1106 1294
1107 1295
1108 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object, 1296 HInstruction* HGraphBuilder::BuildStoreMap(HValue* object,
1109 Handle<Map> map, 1297 Handle<Map> map,
1110 BailoutId id) { 1298 BailoutId id) {
1111 Zone* zone = this->zone(); 1299 Zone* zone = this->zone();
1112 HValue* map_constant = 1300 HValue* map_constant =
1113 AddInstruction(new(zone) HConstant(map, Representation::Tagged())); 1301 AddInstruction(new(zone) HConstant(map, Representation::Tagged()));
1114 return BuildStoreMap(object, map_constant, id); 1302 return BuildStoreMap(object, map_constant, id);
1115 } 1303 }
1116 1304
1117 1305
1118 void HGraphBuilder::BuildCopyElements(HContext* context, 1306 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context,
1307 HValue* old_capacity) {
1308 Zone* zone = this->zone();
1309 HValue* half_old_capacity =
1310 AddInstruction(HShr::New(zone, context, old_capacity,
1311 graph_->GetConstant1()));
1312 half_old_capacity->ChangeRepresentation(Representation::Integer32());
1313 half_old_capacity->ClearFlag(HValue::kCanOverflow);
1314
1315 HValue* new_capacity = AddInstruction(
1316 HAdd::New(zone, context, half_old_capacity, old_capacity));
1317 new_capacity->ChangeRepresentation(Representation::Integer32());
1318 new_capacity->ClearFlag(HValue::kCanOverflow);
1319
1320 HValue* min_growth =
1321 AddInstruction(new(zone) HConstant(16, Representation::Integer32()));
1322
1323 new_capacity = AddInstruction(
1324 HAdd::New(zone, context, new_capacity, min_growth));
1325 new_capacity->ChangeRepresentation(Representation::Integer32());
1326 new_capacity->ClearFlag(HValue::kCanOverflow);
1327
1328 return new_capacity;
1329 }
1330
1331
1332 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) {
1333 Zone* zone = this->zone();
1334 Heap* heap = isolate()->heap();
1335 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize
1336 : kPointerSize;
1337 int max_size = heap->MaxNewSpaceAllocationSize() / element_size;
1338 max_size -= JSArray::kSize / element_size;
1339 HConstant* max_size_constant =
1340 new(zone) HConstant(max_size, Representation::Integer32());
1341 AddInstruction(max_size_constant);
1342 // Since we're forcing Integer32 representation for this HBoundsCheck,
1343 // there's no need to Smi-check the index.
1344 AddInstruction(new(zone)
1345 HBoundsCheck(length, max_size_constant,
1346 DONT_ALLOW_SMI_KEY, Representation::Integer32()));
1347 }
1348
1349
1350 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
1351 HValue* elements,
1352 ElementsKind kind,
1353 HValue* length,
1354 HValue* new_capacity,
1355 BailoutId ast_id) {
1356 Zone* zone = this->zone();
1357 HValue* context = environment()->LookupContext();
1358
1359 BuildNewSpaceArrayCheck(new_capacity, kind);
1360
1361 HValue* new_elements =
1362 BuildAllocateElements(context, kind, new_capacity, ast_id);
1363
1364 BuildCopyElements(context, elements, kind,
1365 new_elements, kind,
1366 length, new_capacity, ast_id);
1367
1368 Factory* factory = isolate()->factory();
1369 HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField(
1370 object,
1371 factory->elements_field_string(),
1372 new_elements, true,
1373 JSArray::kElementsOffset));
1374 elements_store->SetGVNFlag(kChangesElementsPointer);
1375
1376 return new_elements;
1377 }
1378
1379
1380 void HGraphBuilder::BuildFillElementsWithHole(HValue* context,
1381 HValue* elements,
1382 ElementsKind elements_kind,
1383 HValue* from,
1384 HValue* to,
1385 BailoutId ast_id) {
1386 // Fast elements kinds need to be initialized in case statements below cause
1387 // a garbage collection.
1388 Factory* factory = isolate()->factory();
1389
1390 double nan_double = FixedDoubleArray::hole_nan_as_double();
1391 Zone* zone = this->zone();
1392 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
1393 ? AddInstruction(new(zone) HConstant(factory->the_hole_value(),
1394 Representation::Tagged()))
1395 : AddInstruction(new(zone) HConstant(nan_double,
1396 Representation::Double()));
1397
1398 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, ast_id);
1399
1400 HValue* key = builder.BeginBody(from, to, Token::LT);
1401
1402 AddInstruction(new(zone) HStoreKeyed(elements, key, hole, elements_kind));
1403 AddSimulate(ast_id, REMOVABLE_SIMULATE);
1404
1405 builder.EndBody();
1406 }
1407
1408
1409 void HGraphBuilder::BuildCopyElements(HValue* context,
1119 HValue* from_elements, 1410 HValue* from_elements,
1120 ElementsKind from_elements_kind, 1411 ElementsKind from_elements_kind,
1121 HValue* to_elements, 1412 HValue* to_elements,
1122 ElementsKind to_elements_kind, 1413 ElementsKind to_elements_kind,
1123 HValue* length) { 1414 HValue* length,
1124 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, 1415 HValue* capacity,
1125 BailoutId::StubEntry()); 1416 BailoutId ast_id) {
1417 bool pre_fill_with_holes =
1418 IsFastDoubleElementsKind(from_elements_kind) &&
1419 IsFastObjectElementsKind(to_elements_kind);
1126 1420
1127 HValue* key = builder.BeginBody(graph()->GetConstant0(), 1421 if (pre_fill_with_holes) {
1128 length, Token::LT); 1422 // If the copy might trigger a GC, make sure that the FixedArray is
1423 // pre-initialized with holes to make sure that it's always in a consistent
1424 // state.
1425 BuildFillElementsWithHole(context, to_elements, to_elements_kind,
1426 graph()->GetConstant0(), capacity, ast_id);
1427 }
1428
1429 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement, ast_id);
1430
1431 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT);
1129 1432
1130 HValue* element = 1433 HValue* element =
1131 AddInstruction(new(zone()) HLoadKeyed(from_elements, key, NULL, 1434 AddInstruction(new(zone()) HLoadKeyed(from_elements, key, NULL,
1132 from_elements_kind, 1435 from_elements_kind,
1133 ALLOW_RETURN_HOLE)); 1436 ALLOW_RETURN_HOLE));
1134 1437
1135 AddInstruction(new(zone()) HStoreKeyed(to_elements, key, element, 1438 AddInstruction(new(zone()) HStoreKeyed(to_elements, key, element,
1136 to_elements_kind)); 1439 to_elements_kind));
1137 AddSimulate(BailoutId::StubEntry(), REMOVABLE_SIMULATE); 1440 AddSimulate(ast_id, REMOVABLE_SIMULATE);
1138 1441
1139 builder.EndBody(); 1442 builder.EndBody();
1443
1444 if (!pre_fill_with_holes && length != capacity) {
1445 // Fill unused capacity with the hole.
1446 BuildFillElementsWithHole(context, to_elements, to_elements_kind,
1447 key, capacity, ast_id);
1448 }
1140 } 1449 }
1141 1450
1142 1451
1143 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, 1452 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info,
1144 TypeFeedbackOracle* oracle) 1453 TypeFeedbackOracle* oracle)
1145 : HGraphBuilder(info), 1454 : HGraphBuilder(info),
1146 function_state_(NULL), 1455 function_state_(NULL),
1147 initial_function_state_(this, info, oracle, NORMAL_RETURN), 1456 initial_function_state_(this, info, oracle, NORMAL_RETURN),
1148 ast_context_(NULL), 1457 ast_context_(NULL),
1149 break_scope_(NULL), 1458 break_scope_(NULL),
(...skipping 5624 matching lines...) Expand 10 before | Expand all | Expand 10 after
6774 return new(zone()) HLoadKeyedGeneric(context, object, key); 7083 return new(zone()) HLoadKeyedGeneric(context, object, key);
6775 } 7084 }
6776 7085
6777 7086
6778 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( 7087 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
6779 HValue* object, 7088 HValue* object,
6780 HValue* key, 7089 HValue* key,
6781 HValue* val, 7090 HValue* val,
6782 HValue* dependency, 7091 HValue* dependency,
6783 Handle<Map> map, 7092 Handle<Map> map,
6784 bool is_store) { 7093 bool is_store,
7094 KeyedAccessStoreMode store_mode) {
6785 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map, 7095 HCheckMaps* mapcheck = new(zone()) HCheckMaps(object, map,
6786 zone(), dependency); 7096 zone(), dependency);
6787 AddInstruction(mapcheck); 7097 AddInstruction(mapcheck);
6788 if (dependency) { 7098 if (dependency) {
6789 mapcheck->ClearGVNFlag(kDependsOnElementsKind); 7099 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
6790 } 7100 }
6791 return BuildUncheckedMonomorphicElementAccess( 7101 return BuildUncheckedMonomorphicElementAccess(
6792 object, key, val, 7102 object, key, val,
6793 mapcheck, map->instance_type() == JS_ARRAY_TYPE, 7103 mapcheck, map->instance_type() == JS_ARRAY_TYPE,
6794 map->elements_kind(), is_store); 7104 map->elements_kind(), is_store, store_mode);
6795 } 7105 }
6796 7106
6797 7107
6798 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( 7108 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
6799 HValue* object, 7109 HValue* object,
6800 HValue* key, 7110 HValue* key,
6801 HValue* val, 7111 HValue* val,
6802 SmallMapList* maps) { 7112 SmallMapList* maps) {
6803 // For polymorphic loads of similar elements kinds (i.e. all tagged or all 7113 // For polymorphic loads of similar elements kinds (i.e. all tagged or all
6804 // double), always use the "worst case" code without a transition. This is 7114 // double), always use the "worst case" code without a transition. This is
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
6839 } 7149 }
6840 } 7150 }
6841 if (!has_double_maps && !has_smi_or_object_maps) return NULL; 7151 if (!has_double_maps && !has_smi_or_object_maps) return NULL;
6842 7152
6843 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone()); 7153 HCheckMaps* check_maps = new(zone()) HCheckMaps(object, maps, zone());
6844 AddInstruction(check_maps); 7154 AddInstruction(check_maps);
6845 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( 7155 HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
6846 object, key, val, check_maps, 7156 object, key, val, check_maps,
6847 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, 7157 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
6848 most_general_consolidated_map->elements_kind(), 7158 most_general_consolidated_map->elements_kind(),
6849 false); 7159 false, STANDARD_STORE);
6850 return instr; 7160 return instr;
6851 } 7161 }
6852 7162
6853 7163
6854 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( 7164 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
6855 HValue* object, 7165 HValue* object,
6856 HValue* key, 7166 HValue* key,
6857 HValue* val, 7167 HValue* val,
6858 Expression* prop, 7168 Expression* prop,
6859 BailoutId ast_id, 7169 BailoutId ast_id,
6860 int position, 7170 int position,
6861 bool is_store, 7171 bool is_store,
7172 KeyedAccessStoreMode store_mode,
6862 bool* has_side_effects) { 7173 bool* has_side_effects) {
6863 *has_side_effects = false; 7174 *has_side_effects = false;
6864 AddInstruction(new(zone()) HCheckNonSmi(object)); 7175 AddInstruction(new(zone()) HCheckNonSmi(object));
6865 SmallMapList* maps = prop->GetReceiverTypes(); 7176 SmallMapList* maps = prop->GetReceiverTypes();
6866 bool todo_external_array = false; 7177 bool todo_external_array = false;
6867 7178
6868 if (!is_store) { 7179 if (!is_store) {
6869 HInstruction* consolidated_load = 7180 HInstruction* consolidated_load =
6870 TryBuildConsolidatedElementLoad(object, key, val, maps); 7181 TryBuildConsolidatedElementLoad(object, key, val, maps);
6871 if (consolidated_load != NULL) { 7182 if (consolidated_load != NULL) {
6872 AddInstruction(consolidated_load);
6873 *has_side_effects |= consolidated_load->HasObservableSideEffects(); 7183 *has_side_effects |= consolidated_load->HasObservableSideEffects();
6874 if (position != RelocInfo::kNoPosition) { 7184 if (position != RelocInfo::kNoPosition) {
6875 consolidated_load->set_position(position); 7185 consolidated_load->set_position(position);
6876 } 7186 }
6877 return consolidated_load; 7187 return consolidated_load;
6878 } 7188 }
6879 } 7189 }
6880 7190
6881 static const int kNumElementTypes = kElementsKindCount; 7191 static const int kNumElementTypes = kElementsKindCount;
6882 bool type_todo[kNumElementTypes]; 7192 bool type_todo[kNumElementTypes];
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
6929 } 7239 }
6930 7240
6931 // If only one map is left after transitioning, handle this case 7241 // If only one map is left after transitioning, handle this case
6932 // monomorphically. 7242 // monomorphically.
6933 if (num_untransitionable_maps == 1) { 7243 if (num_untransitionable_maps == 1) {
6934 HInstruction* instr = NULL; 7244 HInstruction* instr = NULL;
6935 if (untransitionable_map->has_slow_elements_kind()) { 7245 if (untransitionable_map->has_slow_elements_kind()) {
6936 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) 7246 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val)
6937 : BuildLoadKeyedGeneric(object, key)); 7247 : BuildLoadKeyedGeneric(object, key));
6938 } else { 7248 } else {
6939 instr = AddInstruction(BuildMonomorphicElementAccess( 7249 instr = BuildMonomorphicElementAccess(
6940 object, key, val, transition, untransitionable_map, is_store)); 7250 object, key, val, transition, untransitionable_map, is_store,
7251 store_mode);
6941 } 7252 }
6942 *has_side_effects |= instr->HasObservableSideEffects(); 7253 *has_side_effects |= instr->HasObservableSideEffects();
6943 if (position != RelocInfo::kNoPosition) instr->set_position(position); 7254 if (position != RelocInfo::kNoPosition) instr->set_position(position);
6944 return is_store ? NULL : instr; 7255 return is_store ? NULL : instr;
6945 } 7256 }
6946 7257
6947 HInstruction* checkspec = 7258 HInstruction* checkspec =
6948 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone())); 7259 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone()));
6949 HBasicBlock* join = graph()->CreateBasicBlock(); 7260 HBasicBlock* join = graph()->CreateBasicBlock();
6950 7261
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
7011 typecheck->SetSuccessorAt(1, if_fastobject); 7322 typecheck->SetSuccessorAt(1, if_fastobject);
7012 current_block()->Finish(typecheck); 7323 current_block()->Finish(typecheck);
7013 7324
7014 set_current_block(if_jsarray); 7325 set_current_block(if_jsarray);
7015 HInstruction* length; 7326 HInstruction* length;
7016 length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck, 7327 length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck,
7017 HType::Smi())); 7328 HType::Smi()));
7018 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); 7329 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY);
7019 access = AddInstruction(BuildFastElementAccess( 7330 access = AddInstruction(BuildFastElementAccess(
7020 elements, checked_key, val, elements_kind_branch, 7331 elements, checked_key, val, elements_kind_branch,
7021 elements_kind, is_store)); 7332 elements_kind, is_store, STANDARD_STORE));
7022 if (!is_store) { 7333 if (!is_store) {
7023 Push(access); 7334 Push(access);
7024 } 7335 }
7025 7336
7026 *has_side_effects |= access->HasObservableSideEffects(); 7337 *has_side_effects |= access->HasObservableSideEffects();
7027 if (position != -1) { 7338 if (position != -1) {
7028 access->set_position(position); 7339 access->set_position(position);
7029 } 7340 }
7030 if_jsarray->Goto(join); 7341 if_jsarray->Goto(join);
7031 7342
7032 set_current_block(if_fastobject); 7343 set_current_block(if_fastobject);
7033 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 7344 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
7034 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY); 7345 checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY);
7035 access = AddInstruction(BuildFastElementAccess( 7346 access = AddInstruction(BuildFastElementAccess(
7036 elements, checked_key, val, elements_kind_branch, 7347 elements, checked_key, val, elements_kind_branch,
7037 elements_kind, is_store)); 7348 elements_kind, is_store, STANDARD_STORE));
7038 } else if (elements_kind == DICTIONARY_ELEMENTS) { 7349 } else if (elements_kind == DICTIONARY_ELEMENTS) {
7039 if (is_store) { 7350 if (is_store) {
7040 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); 7351 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
7041 } else { 7352 } else {
7042 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); 7353 access = AddInstruction(BuildLoadKeyedGeneric(object, key));
7043 } 7354 }
7044 } else { // External array elements. 7355 } else { // External array elements.
7045 access = AddInstruction(BuildExternalArrayElementAccess( 7356 access = AddInstruction(BuildExternalArrayElementAccess(
7046 external_elements, checked_key, val, 7357 external_elements, checked_key, val,
7047 elements_kind_branch, elements_kind, is_store)); 7358 elements_kind_branch, elements_kind, is_store));
(...skipping 25 matching lines...) Expand all
7073 int position, 7384 int position,
7074 bool is_store, 7385 bool is_store,
7075 bool* has_side_effects) { 7386 bool* has_side_effects) {
7076 ASSERT(!expr->IsPropertyName()); 7387 ASSERT(!expr->IsPropertyName());
7077 HInstruction* instr = NULL; 7388 HInstruction* instr = NULL;
7078 if (expr->IsMonomorphic()) { 7389 if (expr->IsMonomorphic()) {
7079 Handle<Map> map = expr->GetMonomorphicReceiverType(); 7390 Handle<Map> map = expr->GetMonomorphicReceiverType();
7080 if (map->has_slow_elements_kind()) { 7391 if (map->has_slow_elements_kind()) {
7081 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) 7392 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val)
7082 : BuildLoadKeyedGeneric(obj, key); 7393 : BuildLoadKeyedGeneric(obj, key);
7394 AddInstruction(instr);
7083 } else { 7395 } else {
7084 AddInstruction(new(zone()) HCheckNonSmi(obj)); 7396 AddInstruction(new(zone()) HCheckNonSmi(obj));
7085 instr = BuildMonomorphicElementAccess(obj, key, val, NULL, map, is_store); 7397 instr = BuildMonomorphicElementAccess(
7398 obj, key, val, NULL, map, is_store, expr->GetStoreMode());
7086 } 7399 }
7087 } else if (expr->GetReceiverTypes() != NULL && 7400 } else if (expr->GetReceiverTypes() != NULL &&
7088 !expr->GetReceiverTypes()->is_empty()) { 7401 !expr->GetReceiverTypes()->is_empty()) {
7089 return HandlePolymorphicElementAccess( 7402 return HandlePolymorphicElementAccess(
7090 obj, key, val, expr, ast_id, position, is_store, has_side_effects); 7403 obj, key, val, expr, ast_id, position, is_store,
7404 expr->GetStoreMode(), has_side_effects);
7091 } else { 7405 } else {
7092 if (is_store) { 7406 if (is_store) {
7093 instr = BuildStoreKeyedGeneric(obj, key, val); 7407 instr = BuildStoreKeyedGeneric(obj, key, val);
7094 } else { 7408 } else {
7095 instr = BuildLoadKeyedGeneric(obj, key); 7409 instr = BuildLoadKeyedGeneric(obj, key);
7096 } 7410 }
7411 AddInstruction(instr);
7097 } 7412 }
7098 if (position != RelocInfo::kNoPosition) instr->set_position(position); 7413 if (position != RelocInfo::kNoPosition) instr->set_position(position);
7099 AddInstruction(instr);
7100 *has_side_effects = instr->HasObservableSideEffects(); 7414 *has_side_effects = instr->HasObservableSideEffects();
7101 return instr; 7415 return instr;
7102 } 7416 }
7103 7417
7104 7418
7105 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric( 7419 HInstruction* HOptimizedGraphBuilder::BuildStoreKeyedGeneric(
7106 HValue* object, 7420 HValue* object,
7107 HValue* key, 7421 HValue* key,
7108 HValue* value) { 7422 HValue* value) {
7109 HValue* context = environment()->LookupContext(); 7423 HValue* context = environment()->LookupContext();
(...skipping 3753 matching lines...) Expand 10 before | Expand all | Expand 10 after
10863 } 11177 }
10864 } 11178 }
10865 11179
10866 #ifdef DEBUG 11180 #ifdef DEBUG
10867 if (graph_ != NULL) graph_->Verify(false); // No full verify. 11181 if (graph_ != NULL) graph_->Verify(false); // No full verify.
10868 if (allocator_ != NULL) allocator_->Verify(); 11182 if (allocator_ != NULL) allocator_->Verify();
10869 #endif 11183 #endif
10870 } 11184 }
10871 11185
10872 } } // namespace v8::internal 11186 } } // namespace v8::internal
OLDNEW
« src/hydrogen.h ('K') | « 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