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

Side by Side Diff: src/hydrogen.cc

Issue 148573005: A64: Synchronize with r16249. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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/hydrogen-dce.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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 ASSERT(last_environment() != NULL); 143 ASSERT(last_environment() != NULL);
144 ASSERT(!last_environment()->ast_id().IsNone()); 144 ASSERT(!last_environment()->ast_id().IsNone());
145 HBlockEntry* entry = new(zone()) HBlockEntry(); 145 HBlockEntry* entry = new(zone()) HBlockEntry();
146 entry->InitializeAsFirst(this); 146 entry->InitializeAsFirst(this);
147 first_ = last_ = entry; 147 first_ = last_ = entry;
148 } 148 }
149 instr->InsertAfter(last_); 149 instr->InsertAfter(last_);
150 } 150 }
151 151
152 152
153 HPhi* HBasicBlock::AddNewPhi(int merged_index) {
154 if (graph()->IsInsideNoSideEffectsScope()) {
155 merged_index = HPhi::kInvalidMergedIndex;
156 }
157 HPhi* phi = new(zone()) HPhi(merged_index, zone());
158 AddPhi(phi);
159 return phi;
160 }
161
162
153 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id, 163 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id,
154 RemovableSimulate removable) { 164 RemovableSimulate removable) {
155 ASSERT(HasEnvironment()); 165 ASSERT(HasEnvironment());
156 HEnvironment* environment = last_environment(); 166 HEnvironment* environment = last_environment();
157 ASSERT(ast_id.IsNone() || 167 ASSERT(ast_id.IsNone() ||
158 ast_id == BailoutId::StubEntry() || 168 ast_id == BailoutId::StubEntry() ||
159 environment->closure()->shared()->VerifyBailoutId(ast_id)); 169 environment->closure()->shared()->VerifyBailoutId(ast_id));
160 170
161 int push_count = environment->push_count(); 171 int push_count = environment->push_count();
162 int pop_count = environment->pop_count(); 172 int pop_count = environment->pop_count();
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 FunctionState* state, 208 FunctionState* state,
199 bool add_simulate) { 209 bool add_simulate) {
200 bool drop_extra = state != NULL && 210 bool drop_extra = state != NULL &&
201 state->inlining_kind() == DROP_EXTRA_ON_RETURN; 211 state->inlining_kind() == DROP_EXTRA_ON_RETURN;
202 212
203 if (block->IsInlineReturnTarget()) { 213 if (block->IsInlineReturnTarget()) {
204 AddInstruction(new(zone()) HLeaveInlined()); 214 AddInstruction(new(zone()) HLeaveInlined());
205 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); 215 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
206 } 216 }
207 217
208 if (add_simulate) AddSimulate(BailoutId::None()); 218 if (add_simulate) AddNewSimulate(BailoutId::None());
209 HGoto* instr = new(zone()) HGoto(block); 219 HGoto* instr = new(zone()) HGoto(block);
210 Finish(instr); 220 Finish(instr);
211 } 221 }
212 222
213 223
214 void HBasicBlock::AddLeaveInlined(HValue* return_value, 224 void HBasicBlock::AddLeaveInlined(HValue* return_value,
215 FunctionState* state) { 225 FunctionState* state) {
216 HBasicBlock* target = state->function_return(); 226 HBasicBlock* target = state->function_return();
217 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN; 227 bool drop_extra = state->inlining_kind() == DROP_EXTRA_ON_RETURN;
218 228
219 ASSERT(target->IsInlineReturnTarget()); 229 ASSERT(target->IsInlineReturnTarget());
220 ASSERT(return_value != NULL); 230 ASSERT(return_value != NULL);
221 AddInstruction(new(zone()) HLeaveInlined()); 231 AddInstruction(new(zone()) HLeaveInlined());
222 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra)); 232 UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
223 last_environment()->Push(return_value); 233 last_environment()->Push(return_value);
224 AddSimulate(BailoutId::None()); 234 AddNewSimulate(BailoutId::None());
225 HGoto* instr = new(zone()) HGoto(target); 235 HGoto* instr = new(zone()) HGoto(target);
226 Finish(instr); 236 Finish(instr);
227 } 237 }
228 238
229 239
230 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { 240 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
231 ASSERT(!HasEnvironment()); 241 ASSERT(!HasEnvironment());
232 ASSERT(first() == NULL); 242 ASSERT(first() == NULL);
233 UpdateEnvironment(env); 243 UpdateEnvironment(env);
234 } 244 }
(...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after
819 ASSERT(did_then_); 829 ASSERT(did_then_);
820 ASSERT(!captured_); 830 ASSERT(!captured_);
821 ASSERT(!finished_); 831 ASSERT(!finished_);
822 last_true_block_ = builder_->current_block(); 832 last_true_block_ = builder_->current_block();
823 ASSERT(first_true_block_ == NULL || !last_true_block_->IsFinished()); 833 ASSERT(first_true_block_ == NULL || !last_true_block_->IsFinished());
824 builder_->set_current_block(first_false_block_); 834 builder_->set_current_block(first_false_block_);
825 did_else_ = true; 835 did_else_ = true;
826 } 836 }
827 837
828 838
829 void HGraphBuilder::IfBuilder::Deopt() { 839 void HGraphBuilder::IfBuilder::Deopt(const char* reason) {
830 ASSERT(did_then_); 840 ASSERT(did_then_);
831 if (did_else_) { 841 if (did_else_) {
832 deopt_else_ = true; 842 deopt_else_ = true;
833 } else { 843 } else {
834 deopt_then_ = true; 844 deopt_then_ = true;
835 } 845 }
836 builder_->Add<HDeoptimize>(Deoptimizer::EAGER); 846 builder_->Add<HDeoptimize>(reason, Deoptimizer::EAGER);
837 } 847 }
838 848
839 849
840 void HGraphBuilder::IfBuilder::Return(HValue* value) { 850 void HGraphBuilder::IfBuilder::Return(HValue* value) {
841 HBasicBlock* block = builder_->current_block(); 851 HBasicBlock* block = builder_->current_block();
842 HValue* parameter_count = builder_->graph()->GetConstantMinus1(); 852 HValue* parameter_count = builder_->graph()->GetConstantMinus1();
843 block->FinishExit(builder_->New<HReturn>(value, parameter_count)); 853 block->FinishExit(builder_->New<HReturn>(value, parameter_count));
844 builder_->set_current_block(NULL); 854 builder_->set_current_block(NULL);
845 if (did_else_) { 855 if (did_else_) {
846 first_false_block_ = NULL; 856 first_false_block_ = NULL;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
899 body_block_ = NULL; 909 body_block_ = NULL;
900 exit_block_ = NULL; 910 exit_block_ = NULL;
901 } 911 }
902 912
903 913
904 HValue* HGraphBuilder::LoopBuilder::BeginBody( 914 HValue* HGraphBuilder::LoopBuilder::BeginBody(
905 HValue* initial, 915 HValue* initial,
906 HValue* terminating, 916 HValue* terminating,
907 Token::Value token) { 917 Token::Value token) {
908 HEnvironment* env = builder_->environment(); 918 HEnvironment* env = builder_->environment();
909 phi_ = new(zone()) HPhi(env->values()->length(), zone()); 919 phi_ = header_block_->AddNewPhi(env->values()->length());
910 header_block_->AddPhi(phi_);
911 phi_->AddInput(initial); 920 phi_->AddInput(initial);
912 env->Push(initial); 921 env->Push(initial);
913 builder_->current_block()->GotoNoSimulate(header_block_); 922 builder_->current_block()->GotoNoSimulate(header_block_);
914 923
915 HEnvironment* body_env = env->Copy(); 924 HEnvironment* body_env = env->Copy();
916 HEnvironment* exit_env = env->Copy(); 925 HEnvironment* exit_env = env->Copy();
917 body_block_ = builder_->CreateBasicBlock(body_env); 926 body_block_ = builder_->CreateBasicBlock(body_env);
918 exit_block_ = builder_->CreateBasicBlock(exit_env); 927 exit_block_ = builder_->CreateBasicBlock(exit_env);
919 // Remove the phi from the expression stack 928 // Remove the phi from the expression stack
920 body_env->Pop(); 929 body_env->Pop();
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 set_current_block(graph()->entry_block()); 986 set_current_block(graph()->entry_block());
978 if (!BuildGraph()) return NULL; 987 if (!BuildGraph()) return NULL;
979 graph()->FinalizeUniqueValueIds(); 988 graph()->FinalizeUniqueValueIds();
980 return graph_; 989 return graph_;
981 } 990 }
982 991
983 992
984 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { 993 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
985 ASSERT(current_block() != NULL); 994 ASSERT(current_block() != NULL);
986 current_block()->AddInstruction(instr); 995 current_block()->AddInstruction(instr);
987 if (no_side_effects_scope_count_ > 0) { 996 if (graph()->IsInsideNoSideEffectsScope()) {
988 instr->SetFlag(HValue::kHasNoObservableSideEffects); 997 instr->SetFlag(HValue::kHasNoObservableSideEffects);
989 } 998 }
990 return instr; 999 return instr;
991 } 1000 }
992 1001
993 1002
994 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter, 1003 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter,
995 HValue* context) { 1004 HValue* context) {
996 if (FLAG_native_code_counters && counter->Enabled()) { 1005 if (FLAG_native_code_counters && counter->Enabled()) {
997 HValue* reference = Add<HConstant>(ExternalReference(counter)); 1006 HValue* reference = Add<HConstant>(ExternalReference(counter));
998 HValue* old_value = Add<HLoadNamedField>(reference, 1007 HValue* old_value = Add<HLoadNamedField>(reference,
999 HObjectAccess::ForCounter()); 1008 HObjectAccess::ForCounter());
1000 HValue* new_value = Add<HAdd>(old_value, graph()->GetConstant1()); 1009 HValue* new_value = Add<HAdd>(old_value, graph()->GetConstant1());
1001 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow 1010 new_value->ClearFlag(HValue::kCanOverflow); // Ignore counter overflow
1002 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(), 1011 Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(),
1003 new_value); 1012 new_value);
1004 } 1013 }
1005 } 1014 }
1006 1015
1007 1016
1008 void HGraphBuilder::AddSimulate(BailoutId id, 1017 void HGraphBuilder::AddSimulate(BailoutId id,
1009 RemovableSimulate removable) { 1018 RemovableSimulate removable) {
1010 ASSERT(current_block() != NULL); 1019 ASSERT(current_block() != NULL);
1011 ASSERT(no_side_effects_scope_count_ == 0); 1020 ASSERT(!graph()->IsInsideNoSideEffectsScope());
1012 current_block()->AddSimulate(id, removable); 1021 current_block()->AddNewSimulate(id, removable);
1013 } 1022 }
1014 1023
1015 1024
1016 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { 1025 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
1017 HBasicBlock* b = graph()->CreateBasicBlock(); 1026 HBasicBlock* b = graph()->CreateBasicBlock();
1018 b->SetInitialEnvironment(env); 1027 b->SetInitialEnvironment(env);
1019 return b; 1028 return b;
1020 } 1029 }
1021 1030
1022 1031
1023 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { 1032 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
1024 HBasicBlock* header = graph()->CreateBasicBlock(); 1033 HBasicBlock* header = graph()->CreateBasicBlock();
1025 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); 1034 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
1026 header->SetInitialEnvironment(entry_env); 1035 header->SetInitialEnvironment(entry_env);
1027 header->AttachLoopInformation(); 1036 header->AttachLoopInformation();
1028 return header; 1037 return header;
1029 } 1038 }
1030 1039
1031 1040
1032 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { 1041 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) {
1033 if (obj->type().IsHeapObject()) return obj; 1042 if (obj->type().IsHeapObject()) return obj;
1034 return Add<HCheckHeapObject>(obj); 1043 return Add<HCheckHeapObject>(obj);
1035 } 1044 }
1036 1045
1037 1046
1038 void HGraphBuilder::FinishExitWithHardDeoptimization( 1047 void HGraphBuilder::FinishExitWithHardDeoptimization(
1039 HBasicBlock* continuation) { 1048 const char* reason, HBasicBlock* continuation) {
1040 PadEnvironmentForContinuation(current_block(), continuation); 1049 PadEnvironmentForContinuation(current_block(), continuation);
1041 Add<HDeoptimize>(Deoptimizer::EAGER); 1050 Add<HDeoptimize>(reason, Deoptimizer::EAGER);
1042 if (no_side_effects_scope_count_ > 0) { 1051 if (graph()->IsInsideNoSideEffectsScope()) {
1043 current_block()->GotoNoSimulate(continuation); 1052 current_block()->GotoNoSimulate(continuation);
1044 } else { 1053 } else {
1045 current_block()->Goto(continuation); 1054 current_block()->Goto(continuation);
1046 } 1055 }
1047 } 1056 }
1048 1057
1049 1058
1050 void HGraphBuilder::PadEnvironmentForContinuation( 1059 void HGraphBuilder::PadEnvironmentForContinuation(
1051 HBasicBlock* from, 1060 HBasicBlock* from,
1052 HBasicBlock* continuation) { 1061 HBasicBlock* continuation) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1103 Token::GTE); 1112 Token::GTE);
1104 capacity_checker.Then(); 1113 capacity_checker.Then();
1105 1114
1106 HValue* context = environment()->context(); 1115 HValue* context = environment()->context();
1107 1116
1108 HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap)); 1117 HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
1109 HValue* max_capacity = Add<HAdd>(current_capacity, max_gap); 1118 HValue* max_capacity = Add<HAdd>(current_capacity, max_gap);
1110 IfBuilder key_checker(this); 1119 IfBuilder key_checker(this);
1111 key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT); 1120 key_checker.If<HCompareNumericAndBranch>(key, max_capacity, Token::LT);
1112 key_checker.Then(); 1121 key_checker.Then();
1113 key_checker.ElseDeopt(); 1122 key_checker.ElseDeopt("Key out of capacity range");
1114 key_checker.End(); 1123 key_checker.End();
1115 1124
1116 HValue* new_capacity = BuildNewElementsCapacity(key); 1125 HValue* new_capacity = BuildNewElementsCapacity(key);
1117 HValue* new_elements = BuildGrowElementsCapacity(object, elements, 1126 HValue* new_elements = BuildGrowElementsCapacity(object, elements,
1118 kind, kind, length, 1127 kind, kind, length,
1119 new_capacity); 1128 new_capacity);
1120 1129
1121 environment()->Push(new_elements); 1130 environment()->Push(new_elements);
1122 capacity_checker.Else(); 1131 capacity_checker.Else();
1123 1132
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1177 ElementsKind to_kind, 1186 ElementsKind to_kind,
1178 bool is_jsarray) { 1187 bool is_jsarray) {
1179 ASSERT(!IsFastHoleyElementsKind(from_kind) || 1188 ASSERT(!IsFastHoleyElementsKind(from_kind) ||
1180 IsFastHoleyElementsKind(to_kind)); 1189 IsFastHoleyElementsKind(to_kind));
1181 1190
1182 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) { 1191 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) {
1183 Add<HTrapAllocationMemento>(object); 1192 Add<HTrapAllocationMemento>(object);
1184 } 1193 }
1185 1194
1186 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) { 1195 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) {
1187 HInstruction* elements = AddLoadElements(object); 1196 HInstruction* elements = AddLoadElements(object, NULL);
1188 1197
1189 HInstruction* empty_fixed_array = Add<HConstant>( 1198 HInstruction* empty_fixed_array = Add<HConstant>(
1190 isolate()->factory()->empty_fixed_array()); 1199 isolate()->factory()->empty_fixed_array());
1191 1200
1192 IfBuilder if_builder(this); 1201 IfBuilder if_builder(this);
1193 1202
1194 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array); 1203 if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array);
1195 1204
1196 if_builder.Then(); 1205 if_builder.Then();
1197 1206
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1259 Add<HLoadExternalArrayPointer>(elements); 1268 Add<HLoadExternalArrayPointer>(elements);
1260 IfBuilder length_checker(this); 1269 IfBuilder length_checker(this);
1261 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); 1270 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
1262 length_checker.Then(); 1271 length_checker.Then();
1263 IfBuilder negative_checker(this); 1272 IfBuilder negative_checker(this);
1264 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( 1273 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
1265 key, graph()->GetConstant0(), Token::GTE); 1274 key, graph()->GetConstant0(), Token::GTE);
1266 negative_checker.Then(); 1275 negative_checker.Then();
1267 HInstruction* result = AddExternalArrayElementAccess( 1276 HInstruction* result = AddExternalArrayElementAccess(
1268 external_elements, key, val, bounds_check, elements_kind, is_store); 1277 external_elements, key, val, bounds_check, elements_kind, is_store);
1269 negative_checker.ElseDeopt(); 1278 negative_checker.ElseDeopt("Negative key encountered");
1270 length_checker.End(); 1279 length_checker.End();
1271 return result; 1280 return result;
1272 } else { 1281 } else {
1273 ASSERT(store_mode == STANDARD_STORE); 1282 ASSERT(store_mode == STANDARD_STORE);
1274 checked_key = Add<HBoundsCheck>(key, length); 1283 checked_key = Add<HBoundsCheck>(key, length);
1275 HLoadExternalArrayPointer* external_elements = 1284 HLoadExternalArrayPointer* external_elements =
1276 Add<HLoadExternalArrayPointer>(elements); 1285 Add<HLoadExternalArrayPointer>(elements);
1277 return AddExternalArrayElementAccess( 1286 return AddExternalArrayElementAccess(
1278 external_elements, checked_key, val, 1287 external_elements, checked_key, val,
1279 mapcheck, elements_kind, is_store); 1288 mapcheck, elements_kind, is_store);
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
1621 1630
1622 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); 1631 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
1623 1632
1624 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT); 1633 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT);
1625 1634
1626 HValue* element = Add<HLoadKeyed>(from_elements, key, 1635 HValue* element = Add<HLoadKeyed>(from_elements, key,
1627 static_cast<HValue*>(NULL), 1636 static_cast<HValue*>(NULL),
1628 from_elements_kind, 1637 from_elements_kind,
1629 ALLOW_RETURN_HOLE); 1638 ALLOW_RETURN_HOLE);
1630 1639
1631 ElementsKind holey_kind = IsFastSmiElementsKind(to_elements_kind) 1640 ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) &&
1641 IsFastSmiElementsKind(to_elements_kind))
1632 ? FAST_HOLEY_ELEMENTS : to_elements_kind; 1642 ? FAST_HOLEY_ELEMENTS : to_elements_kind;
1633 HInstruction* holey_store = Add<HStoreKeyed>(to_elements, key, 1643
1634 element, holey_kind); 1644 if (IsHoleyElementsKind(from_elements_kind) &&
1635 // Allow NaN hole values to converted to their tagged counterparts. 1645 from_elements_kind != to_elements_kind) {
1636 if (IsFastHoleyElementsKind(to_elements_kind)) { 1646 IfBuilder if_hole(this);
1637 holey_store->SetFlag(HValue::kAllowUndefinedAsNaN); 1647 if_hole.If<HCompareHoleAndBranch>(element);
1648 if_hole.Then();
1649 HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind)
1650 ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double())
1651 : graph()->GetConstantHole();
1652 Add<HStoreKeyed>(to_elements, key, hole_constant, kind);
1653 if_hole.Else();
1654 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind);
1655 store->SetFlag(HValue::kAllowUndefinedAsNaN);
1656 if_hole.End();
1657 } else {
1658 HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind);
1659 store->SetFlag(HValue::kAllowUndefinedAsNaN);
1638 } 1660 }
1639 1661
1640 builder.EndBody(); 1662 builder.EndBody();
1641 1663
1642 if (!pre_fill_with_holes && length != capacity) { 1664 if (!pre_fill_with_holes && length != capacity) {
1643 // Fill unused capacity with the hole. 1665 // Fill unused capacity with the hole.
1644 BuildFillElementsWithHole(to_elements, to_elements_kind, 1666 BuildFillElementsWithHole(to_elements, to_elements_kind,
1645 key, capacity); 1667 key, capacity);
1646 } 1668 }
1647 } 1669 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1686 } 1708 }
1687 1709
1688 // Create an allocation site info if requested. 1710 // Create an allocation site info if requested.
1689 if (mode == TRACK_ALLOCATION_SITE) { 1711 if (mode == TRACK_ALLOCATION_SITE) {
1690 BuildCreateAllocationMemento(object, JSArray::kSize, allocation_site); 1712 BuildCreateAllocationMemento(object, JSArray::kSize, allocation_site);
1691 } 1713 }
1692 1714
1693 if (length > 0) { 1715 if (length > 0) {
1694 // Get hold of the elements array of the boilerplate and setup the 1716 // Get hold of the elements array of the boilerplate and setup the
1695 // elements pointer in the resulting object. 1717 // elements pointer in the resulting object.
1696 HValue* boilerplate_elements = AddLoadElements(boilerplate); 1718 HValue* boilerplate_elements = AddLoadElements(boilerplate, NULL);
1697 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset); 1719 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset);
1698 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), 1720 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
1699 object_elements); 1721 object_elements);
1700 1722
1701 // Copy the elements array header. 1723 // Copy the elements array header.
1702 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { 1724 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) {
1703 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); 1725 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i);
1704 Add<HStoreNamedField>(object_elements, access, 1726 Add<HStoreNamedField>(object_elements, access,
1705 Add<HLoadNamedField>(boilerplate_elements, access)); 1727 Add<HLoadNamedField>(boilerplate_elements, access));
1706 } 1728 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1746 if_nil.Then(); 1768 if_nil.Then();
1747 if_nil.Else(); 1769 if_nil.Else();
1748 if (type->NumClasses() == 1) { 1770 if (type->NumClasses() == 1) {
1749 BuildCheckHeapObject(value); 1771 BuildCheckHeapObject(value);
1750 // For ICs, the map checked below is a sentinel map that gets replaced by 1772 // For ICs, the map checked below is a sentinel map that gets replaced by
1751 // the monomorphic map when the code is used as a template to generate a 1773 // the monomorphic map when the code is used as a template to generate a
1752 // new IC. For optimized functions, there is no sentinel map, the map 1774 // new IC. For optimized functions, there is no sentinel map, the map
1753 // emitted below is the actual monomorphic map. 1775 // emitted below is the actual monomorphic map.
1754 BuildCheckMap(value, type->Classes().Current()); 1776 BuildCheckMap(value, type->Classes().Current());
1755 } else { 1777 } else {
1756 if_nil.Deopt(); 1778 if_nil.Deopt("Too many undetectable types");
1757 } 1779 }
1758 } 1780 }
1759 1781
1760 if_nil.CaptureContinuation(continuation); 1782 if_nil.CaptureContinuation(continuation);
1761 } 1783 }
1762 1784
1763 1785
1764 HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object, 1786 HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object,
1765 int previous_object_size, 1787 int previous_object_size,
1766 HValue* alloc_site) { 1788 HValue* alloc_site) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1819 constructor_function_(constructor_function) { 1841 constructor_function_(constructor_function) {
1820 } 1842 }
1821 1843
1822 1844
1823 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() { 1845 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
1824 if (kind_ == GetInitialFastElementsKind()) { 1846 if (kind_ == GetInitialFastElementsKind()) {
1825 // No need for a context lookup if the kind_ matches the initial 1847 // No need for a context lookup if the kind_ matches the initial
1826 // map, because we can just load the map in that case. 1848 // map, because we can just load the map in that case.
1827 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); 1849 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
1828 return builder()->AddInstruction( 1850 return builder()->AddInstruction(
1829 builder()->BuildLoadNamedField(constructor_function_, access)); 1851 builder()->BuildLoadNamedField(constructor_function_, access, NULL));
1830 } 1852 }
1831 1853
1832 HInstruction* native_context = builder()->BuildGetNativeContext(); 1854 HInstruction* native_context = builder()->BuildGetNativeContext();
1833 HInstruction* index = builder()->Add<HConstant>( 1855 HInstruction* index = builder()->Add<HConstant>(
1834 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX)); 1856 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX));
1835 1857
1836 HInstruction* map_array = builder()->Add<HLoadKeyed>( 1858 HInstruction* map_array = builder()->Add<HLoadKeyed>(
1837 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS); 1859 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
1838 1860
1839 HInstruction* kind_index = builder()->Add<HConstant>(kind_); 1861 HInstruction* kind_index = builder()->Add<HConstant>(kind_);
1840 1862
1841 return builder()->Add<HLoadKeyed>( 1863 return builder()->Add<HLoadKeyed>(
1842 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); 1864 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
1843 } 1865 }
1844 1866
1845 1867
1846 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { 1868 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
1847 // Find the map near the constructor function 1869 // Find the map near the constructor function
1848 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); 1870 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
1849 return builder()->AddInstruction( 1871 return builder()->AddInstruction(
1850 builder()->BuildLoadNamedField(constructor_function_, access)); 1872 builder()->BuildLoadNamedField(constructor_function_, access, NULL));
1851 } 1873 }
1852 1874
1853 1875
1854 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( 1876 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize(
1855 HValue* length_node) { 1877 HValue* length_node) {
1856 ASSERT(length_node != NULL); 1878 ASSERT(length_node != NULL);
1857 1879
1858 int base_size = JSArray::kSize; 1880 int base_size = JSArray::kSize;
1859 if (mode_ == TRACK_ALLOCATION_SITE) { 1881 if (mode_ == TRACK_ALLOCATION_SITE) {
1860 base_size += AllocationMemento::kSize; 1882 base_size += AllocationMemento::kSize;
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
2044 phi_list_(NULL), 2066 phi_list_(NULL),
2045 uint32_instructions_(NULL), 2067 uint32_instructions_(NULL),
2046 osr_(NULL), 2068 osr_(NULL),
2047 info_(info), 2069 info_(info),
2048 zone_(info->zone()), 2070 zone_(info->zone()),
2049 is_recursive_(false), 2071 is_recursive_(false),
2050 use_optimistic_licm_(false), 2072 use_optimistic_licm_(false),
2051 has_soft_deoptimize_(false), 2073 has_soft_deoptimize_(false),
2052 depends_on_empty_array_proto_elements_(false), 2074 depends_on_empty_array_proto_elements_(false),
2053 type_change_checksum_(0), 2075 type_change_checksum_(0),
2054 maximum_environment_size_(0) { 2076 maximum_environment_size_(0),
2077 no_side_effects_scope_count_(0) {
2055 if (info->IsStub()) { 2078 if (info->IsStub()) {
2056 HydrogenCodeStub* stub = info->code_stub(); 2079 HydrogenCodeStub* stub = info->code_stub();
2057 CodeStubInterfaceDescriptor* descriptor = 2080 CodeStubInterfaceDescriptor* descriptor =
2058 stub->GetInterfaceDescriptor(isolate_); 2081 stub->GetInterfaceDescriptor(isolate_);
2059 start_environment_ = 2082 start_environment_ =
2060 new(zone_) HEnvironment(zone_, descriptor->environment_length()); 2083 new(zone_) HEnvironment(zone_, descriptor->environment_length());
2061 } else { 2084 } else {
2062 start_environment_ = 2085 start_environment_ =
2063 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); 2086 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
2064 } 2087 }
(...skipping 876 matching lines...) Expand 10 before | Expand all | Expand 10 after
2941 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with 2964 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with
2942 // zero. 2965 // zero.
2943 if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>(); 2966 if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>();
2944 2967
2945 if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>(); 2968 if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>();
2946 2969
2947 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); 2970 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>();
2948 2971
2949 if (FLAG_use_range) Run<HRangeAnalysisPhase>(); 2972 if (FLAG_use_range) Run<HRangeAnalysisPhase>();
2950 2973
2974 Run<HComputeChangeUndefinedToNaN>();
2951 Run<HComputeMinusZeroChecksPhase>(); 2975 Run<HComputeMinusZeroChecksPhase>();
2952 2976
2953 // Eliminate redundant stack checks on backwards branches. 2977 // Eliminate redundant stack checks on backwards branches.
2954 Run<HStackCheckEliminationPhase>(); 2978 Run<HStackCheckEliminationPhase>();
2955 2979
2956 if (FLAG_array_bounds_checks_elimination) { 2980 if (FLAG_array_bounds_checks_elimination) {
2957 Run<HBoundsCheckEliminationPhase>(); 2981 Run<HBoundsCheckEliminationPhase>();
2958 } 2982 }
2959 if (FLAG_array_bounds_checks_hoisting) { 2983 if (FLAG_array_bounds_checks_hoisting) {
2960 Run<HBoundsCheckHoistingPhase>(); 2984 Run<HBoundsCheckHoistingPhase>();
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
3342 CHECK_ALIVE(VisitForValue(clause->label())); 3366 CHECK_ALIVE(VisitForValue(clause->label()));
3343 HValue* label_value = Pop(); 3367 HValue* label_value = Pop();
3344 3368
3345 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); 3369 HBasicBlock* next_test_block = graph()->CreateBasicBlock();
3346 HBasicBlock* body_block = graph()->CreateBasicBlock(); 3370 HBasicBlock* body_block = graph()->CreateBasicBlock();
3347 3371
3348 HControlInstruction* compare; 3372 HControlInstruction* compare;
3349 3373
3350 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { 3374 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) {
3351 if (!clause->compare_type()->Is(Type::Smi())) { 3375 if (!clause->compare_type()->Is(Type::Smi())) {
3352 Add<HDeoptimize>(Deoptimizer::SOFT); 3376 Add<HDeoptimize>("Non-smi switch type", Deoptimizer::SOFT);
3353 } 3377 }
3354 3378
3355 HCompareNumericAndBranch* compare_ = 3379 HCompareNumericAndBranch* compare_ =
3356 new(zone()) HCompareNumericAndBranch(tag_value, 3380 new(zone()) HCompareNumericAndBranch(tag_value,
3357 label_value, 3381 label_value,
3358 Token::EQ_STRICT); 3382 Token::EQ_STRICT);
3359 compare_->set_observed_input_representation( 3383 compare_->set_observed_input_representation(
3360 Representation::Smi(), Representation::Smi()); 3384 Representation::Smi(), Representation::Smi());
3361 compare = compare_; 3385 compare = compare_;
3362 } else { 3386 } else {
(...skipping 920 matching lines...) Expand 10 before | Expand all | Expand 10 after
4283 // TODO(mvstanton): This heuristic is only a temporary solution. In the 4307 // TODO(mvstanton): This heuristic is only a temporary solution. In the
4284 // end, we want to quit creating allocation site info after a certain number 4308 // end, we want to quit creating allocation site info after a certain number
4285 // of GCs for a call site. 4309 // of GCs for a call site.
4286 AllocationSiteMode mode = AllocationSite::GetMode( 4310 AllocationSiteMode mode = AllocationSite::GetMode(
4287 boilerplate_elements_kind); 4311 boilerplate_elements_kind);
4288 4312
4289 // Check whether to use fast or slow deep-copying for boilerplate. 4313 // Check whether to use fast or slow deep-copying for boilerplate.
4290 int data_size = 0; 4314 int data_size = 0;
4291 int pointer_size = 0; 4315 int pointer_size = 0;
4292 int max_properties = kMaxFastLiteralProperties; 4316 int max_properties = kMaxFastLiteralProperties;
4317 HCheckMaps* type_check = NULL;
4293 if (IsFastLiteral(original_boilerplate_object, 4318 if (IsFastLiteral(original_boilerplate_object,
4294 kMaxFastLiteralDepth, 4319 kMaxFastLiteralDepth,
4295 &max_properties, 4320 &max_properties,
4296 &data_size, 4321 &data_size,
4297 &pointer_size)) { 4322 &pointer_size)) {
4298 if (mode == TRACK_ALLOCATION_SITE) { 4323 if (mode == TRACK_ALLOCATION_SITE) {
4299 pointer_size += AllocationMemento::kSize; 4324 pointer_size += AllocationMemento::kSize;
4300 } 4325 }
4301 4326
4302 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object); 4327 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object);
(...skipping 17 matching lines...) Expand all
4320 4345
4321 Runtime::FunctionId function_id = (expr->depth() > 1) 4346 Runtime::FunctionId function_id = (expr->depth() > 1)
4322 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; 4347 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow;
4323 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), 4348 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
4324 Runtime::FunctionForId(function_id), 4349 Runtime::FunctionForId(function_id),
4325 3); 4350 3);
4326 4351
4327 // De-opt if elements kind changed from boilerplate_elements_kind. 4352 // De-opt if elements kind changed from boilerplate_elements_kind.
4328 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), 4353 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(),
4329 isolate()); 4354 isolate());
4330 Add<HCheckMaps>(literal, map, top_info()); 4355 type_check = Add<HCheckMaps>(literal, map, top_info());
4331 } 4356 }
4332 4357
4333 // The array is expected in the bailout environment during computation 4358 // The array is expected in the bailout environment during computation
4334 // of the property values and is the value of the entire expression. 4359 // of the property values and is the value of the entire expression.
4335 Push(literal); 4360 Push(literal);
4336 // The literal index is on the stack, too. 4361 // The literal index is on the stack, too.
4337 Push(Add<HConstant>(expr->literal_index())); 4362 Push(Add<HConstant>(expr->literal_index()));
4338 4363
4339 HInstruction* elements = NULL; 4364 HInstruction* elements = NULL;
4340 4365
4341 for (int i = 0; i < length; i++) { 4366 for (int i = 0; i < length; i++) {
4342 Expression* subexpr = subexprs->at(i); 4367 Expression* subexpr = subexprs->at(i);
4343 // If the subexpression is a literal or a simple materialized literal it 4368 // If the subexpression is a literal or a simple materialized literal it
4344 // is already set in the cloned array. 4369 // is already set in the cloned array.
4345 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 4370 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
4346 4371
4347 CHECK_ALIVE(VisitForValue(subexpr)); 4372 CHECK_ALIVE(VisitForValue(subexpr));
4348 HValue* value = Pop(); 4373 HValue* value = Pop();
4349 if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral); 4374 if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral);
4350 4375
4351 elements = AddLoadElements(literal); 4376 elements = AddLoadElements(literal, type_check);
4352 4377
4353 HValue* key = Add<HConstant>(i); 4378 HValue* key = Add<HConstant>(i);
4354 4379
4355 switch (boilerplate_elements_kind) { 4380 switch (boilerplate_elements_kind) {
4356 case FAST_SMI_ELEMENTS: 4381 case FAST_SMI_ELEMENTS:
4357 case FAST_HOLEY_SMI_ELEMENTS: 4382 case FAST_HOLEY_SMI_ELEMENTS:
4358 case FAST_ELEMENTS: 4383 case FAST_ELEMENTS:
4359 case FAST_HOLEY_ELEMENTS: 4384 case FAST_HOLEY_ELEMENTS:
4360 case FAST_DOUBLE_ELEMENTS: 4385 case FAST_DOUBLE_ELEMENTS:
4361 case FAST_HOLEY_DOUBLE_ELEMENTS: { 4386 case FAST_HOLEY_DOUBLE_ELEMENTS: {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
4395 if (!is_store) return false; 4420 if (!is_store) return false;
4396 4421
4397 // 2nd chance: A store into a non-existent field can still be inlined if we 4422 // 2nd chance: A store into a non-existent field can still be inlined if we
4398 // have a matching transition and some room left in the object. 4423 // have a matching transition and some room left in the object.
4399 type->LookupTransition(NULL, *name, lookup); 4424 type->LookupTransition(NULL, *name, lookup);
4400 return lookup->IsTransitionToField(*type) && 4425 return lookup->IsTransitionToField(*type) &&
4401 (type->unused_property_fields() > 0); 4426 (type->unused_property_fields() > 0);
4402 } 4427 }
4403 4428
4404 4429
4405 void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) { 4430 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object,
4431 Handle<Map> map) {
4406 BuildCheckHeapObject(object); 4432 BuildCheckHeapObject(object);
4407 Add<HCheckMaps>(object, map, top_info()); 4433 return Add<HCheckMaps>(object, map, top_info());
4408 } 4434 }
4409 4435
4410 4436
4411 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( 4437 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
4412 HValue* object, 4438 HValue* object,
4413 Handle<String> name, 4439 Handle<String> name,
4414 HValue* value, 4440 HValue* value,
4415 Handle<Map> map, 4441 Handle<Map> map,
4416 LookupResult* lookup) { 4442 LookupResult* lookup) {
4417 ASSERT(lookup->IsFound()); 4443 ASSERT(lookup->IsFound());
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
4563 // In-objectness did not match. 4589 // In-objectness did not match.
4564 break; 4590 break;
4565 } 4591 }
4566 access = access.WithRepresentation( 4592 access = access.WithRepresentation(
4567 access.representation().generalize(new_access.representation())); 4593 access.representation().generalize(new_access.representation()));
4568 } 4594 }
4569 4595
4570 if (count == types->length()) { 4596 if (count == types->length()) {
4571 // Everything matched; can use monomorphic load. 4597 // Everything matched; can use monomorphic load.
4572 BuildCheckHeapObject(object); 4598 BuildCheckHeapObject(object);
4573 Add<HCheckMaps>(object, types); 4599 HCheckMaps* type_check = Add<HCheckMaps>(object, types);
4574 return BuildLoadNamedField(object, access); 4600 return BuildLoadNamedField(object, access, type_check);
4575 } 4601 }
4576 4602
4577 if (count != 0) return NULL; 4603 if (count != 0) return NULL;
4578 4604
4579 // Second chance: the property is on the prototype and all maps have the 4605 // Second chance: the property is on the prototype and all maps have the
4580 // same prototype. 4606 // same prototype.
4581 Handle<Map> map(types->at(0)); 4607 Handle<Map> map(types->at(0));
4582 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL; 4608 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL;
4583 4609
4584 Handle<Object> prototype(map->prototype(), isolate()); 4610 Handle<Object> prototype(map->prototype(), isolate());
4585 for (count = 1; count < types->length(); ++count) { 4611 for (count = 1; count < types->length(); ++count) {
4586 Handle<Map> test_map(types->at(count)); 4612 Handle<Map> test_map(types->at(count));
4587 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL; 4613 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL;
4588 if (test_map->prototype() != *prototype) return NULL; 4614 if (test_map->prototype() != *prototype) return NULL;
4589 } 4615 }
4590 4616
4591 LookupInPrototypes(map, name, &lookup); 4617 LookupInPrototypes(map, name, &lookup);
4592 if (!lookup.IsField()) return NULL; 4618 if (!lookup.IsField()) return NULL;
4593 4619
4594 BuildCheckHeapObject(object); 4620 BuildCheckHeapObject(object);
4595 Add<HCheckMaps>(object, types); 4621 HCheckMaps* type_check = Add<HCheckMaps>(object, types);
4596 4622
4597 Handle<JSObject> holder(lookup.holder()); 4623 Handle<JSObject> holder(lookup.holder());
4598 Handle<Map> holder_map(holder->map()); 4624 Handle<Map> holder_map(holder->map());
4599 BuildCheckPrototypeMaps(Handle<JSObject>::cast(prototype), holder); 4625 BuildCheckPrototypeMaps(Handle<JSObject>::cast(prototype), holder);
4600 HValue* holder_value = Add<HConstant>(holder); 4626 HValue* holder_value = Add<HConstant>(holder);
4601 return BuildLoadNamedField(holder_value, 4627 return BuildLoadNamedField(holder_value,
4602 HObjectAccess::ForField(holder_map, &lookup, name)); 4628 HObjectAccess::ForField(holder_map, &lookup, name), type_check);
4603 } 4629 }
4604 4630
4605 4631
4632 // Returns true if an instance of this map can never find a property with this
4633 // name in its prototype chain. This means all prototypes up to the top are
4634 // fast and don't have the name in them. It would be good if we could optimize
4635 // polymorphic loads where the property is sometimes found in the prototype
4636 // chain.
4637 static bool PrototypeChainCanNeverResolve(
4638 Handle<Map> map, Handle<String> name) {
4639 Isolate* isolate = map->GetIsolate();
4640 Object* current = map->prototype();
4641 while (current != isolate->heap()->null_value()) {
4642 if (current->IsJSGlobalProxy() ||
4643 current->IsGlobalObject() ||
4644 !current->IsJSObject() ||
4645 JSObject::cast(current)->map()->has_named_interceptor() ||
4646 JSObject::cast(current)->IsAccessCheckNeeded() ||
4647 !JSObject::cast(current)->HasFastProperties()) {
4648 return false;
4649 }
4650
4651 LookupResult lookup(isolate);
4652 Map* map = JSObject::cast(current)->map();
4653 map->LookupDescriptor(NULL, *name, &lookup);
4654 if (lookup.IsFound()) return false;
4655 if (!lookup.IsCacheable()) return false;
4656 current = JSObject::cast(current)->GetPrototype();
4657 }
4658 return true;
4659 }
4660
4661
4606 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( 4662 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
4607 Property* expr, 4663 Property* expr,
4608 HValue* object, 4664 HValue* object,
4609 SmallMapList* types, 4665 SmallMapList* types,
4610 Handle<String> name) { 4666 Handle<String> name) {
4611 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( 4667 HInstruction* instr = TryLoadPolymorphicAsMonomorphic(
4612 expr, object, types, name); 4668 expr, object, types, name);
4613 if (instr == NULL) { 4669 if (instr != NULL) {
4614 // Something did not match; must use a polymorphic load. 4670 instr->set_position(expr->position());
4615 BuildCheckHeapObject(object); 4671 return ast_context()->ReturnInstruction(instr, expr->id());
4616 HValue* context = environment()->context();
4617 instr = new(zone()) HLoadNamedFieldPolymorphic(
4618 context, object, types, name, zone());
4619 } 4672 }
4620 4673
4621 instr->set_position(expr->position()); 4674 // Something did not match; must use a polymorphic load.
4622 return ast_context()->ReturnInstruction(instr, expr->id()); 4675 int count = 0;
4676 HBasicBlock* join = NULL;
4677 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
4678 Handle<Map> map = types->at(i);
4679 LookupResult lookup(isolate());
4680 if (ComputeLoadStoreField(map, name, &lookup, false) ||
4681 (lookup.IsCacheable() &&
4682 !map->is_dictionary_map() &&
4683 !map->has_named_interceptor() &&
4684 (lookup.IsConstant() ||
4685 (!lookup.IsFound() &&
4686 PrototypeChainCanNeverResolve(map, name))))) {
4687 if (count == 0) {
4688 BuildCheckHeapObject(object);
4689 join = graph()->CreateBasicBlock();
4690 }
4691 ++count;
4692 HBasicBlock* if_true = graph()->CreateBasicBlock();
4693 HBasicBlock* if_false = graph()->CreateBasicBlock();
4694 HCompareMap* compare =
4695 new(zone()) HCompareMap(object, map, if_true, if_false);
4696 current_block()->Finish(compare);
4697
4698 set_current_block(if_true);
4699
4700 // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic.
4701 if (lookup.IsField()) {
4702 HObjectAccess access = HObjectAccess::ForField(map, &lookup, name);
4703 HLoadNamedField* load = BuildLoadNamedField(object, access, compare);
4704 load->set_position(expr->position());
4705 AddInstruction(load);
4706 if (!ast_context()->IsEffect()) Push(load);
4707 } else if (lookup.IsConstant()) {
4708 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate());
4709 HConstant* hconstant = Add<HConstant>(constant);
4710 if (!ast_context()->IsEffect()) Push(hconstant);
4711 } else {
4712 ASSERT(!lookup.IsFound());
4713 if (map->prototype()->IsJSObject()) {
4714 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
4715 Handle<JSObject> holder = prototype;
4716 while (holder->map()->prototype()->IsJSObject()) {
4717 holder = handle(JSObject::cast(holder->map()->prototype()));
4718 }
4719 BuildCheckPrototypeMaps(prototype, holder);
4720 }
4721 if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
4722 }
4723
4724 current_block()->Goto(join);
4725 set_current_block(if_false);
4726 }
4727 }
4728
4729 // Finish up. Unconditionally deoptimize if we've handled all the maps we
4730 // know about and do not want to handle ones we've never seen. Otherwise
4731 // use a generic IC.
4732 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
4733 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join);
4734 } else {
4735 HInstruction* load = BuildLoadNamedGeneric(object, name, expr);
4736 load->set_position(expr->position());
4737 AddInstruction(load);
4738 if (!ast_context()->IsEffect()) Push(load);
4739
4740 if (join != NULL) {
4741 current_block()->Goto(join);
4742 } else {
4743 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
4744 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
4745 return;
4746 }
4747 }
4748
4749 ASSERT(join != NULL);
4750 join->SetJoinId(expr->id());
4751 set_current_block(join);
4752 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
4623 } 4753 }
4624 4754
4625 4755
4626 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( 4756 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic(
4627 int position, 4757 int position,
4628 BailoutId assignment_id, 4758 BailoutId assignment_id,
4629 HValue* object, 4759 HValue* object,
4630 HValue* store_value, 4760 HValue* store_value,
4631 HValue* result_value, 4761 HValue* result_value,
4632 SmallMapList* types, 4762 SmallMapList* types,
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
4731 current_block()->Goto(join); 4861 current_block()->Goto(join);
4732 4862
4733 set_current_block(if_false); 4863 set_current_block(if_false);
4734 } 4864 }
4735 } 4865 }
4736 4866
4737 // Finish up. Unconditionally deoptimize if we've handled all the maps we 4867 // Finish up. Unconditionally deoptimize if we've handled all the maps we
4738 // know about and do not want to handle ones we've never seen. Otherwise 4868 // know about and do not want to handle ones we've never seen. Otherwise
4739 // use a generic IC. 4869 // use a generic IC.
4740 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 4870 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
4741 FinishExitWithHardDeoptimization(join); 4871 FinishExitWithHardDeoptimization("Unknown map in polymorphic store", join);
4742 } else { 4872 } else {
4743 HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value); 4873 HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value);
4744 instr->set_position(position); 4874 instr->set_position(position);
4745 AddInstruction(instr); 4875 AddInstruction(instr);
4746 4876
4747 if (join != NULL) { 4877 if (join != NULL) {
4748 if (!ast_context()->IsEffect()) { 4878 if (!ast_context()->IsEffect()) {
4749 Push(result_value); 4879 Push(result_value);
4750 } 4880 }
4751 current_block()->Goto(join); 4881 current_block()->Goto(join);
(...skipping 27 matching lines...) Expand all
4779 Property* prop = expr->target()->AsProperty(); 4909 Property* prop = expr->target()->AsProperty();
4780 ASSERT(prop != NULL); 4910 ASSERT(prop != NULL);
4781 CHECK_ALIVE(VisitForValue(prop->obj())); 4911 CHECK_ALIVE(VisitForValue(prop->obj()));
4782 4912
4783 if (prop->key()->IsPropertyName()) { 4913 if (prop->key()->IsPropertyName()) {
4784 // Named store. 4914 // Named store.
4785 CHECK_ALIVE(VisitForValue(expr->value())); 4915 CHECK_ALIVE(VisitForValue(expr->value()));
4786 HValue* value = environment()->ExpressionStackAt(0); 4916 HValue* value = environment()->ExpressionStackAt(0);
4787 HValue* object = environment()->ExpressionStackAt(1); 4917 HValue* object = environment()->ExpressionStackAt(1);
4788 4918
4789 if (expr->IsUninitialized()) Add<HDeoptimize>(Deoptimizer::SOFT); 4919 if (expr->IsUninitialized()) {
4920 Add<HDeoptimize>("Insufficient type feedback for property assignment",
4921 Deoptimizer::SOFT);
4922 }
4790 return BuildStoreNamed(expr, expr->id(), expr->position(), 4923 return BuildStoreNamed(expr, expr->id(), expr->position(),
4791 expr->AssignmentId(), prop, object, value, value); 4924 expr->AssignmentId(), prop, object, value, value);
4792 } else { 4925 } else {
4793 // Keyed store. 4926 // Keyed store.
4794 CHECK_ALIVE(VisitForValue(prop->key())); 4927 CHECK_ALIVE(VisitForValue(prop->key()));
4795 CHECK_ALIVE(VisitForValue(expr->value())); 4928 CHECK_ALIVE(VisitForValue(expr->value()));
4796 HValue* value = environment()->ExpressionStackAt(0); 4929 HValue* value = environment()->ExpressionStackAt(0);
4797 HValue* key = environment()->ExpressionStackAt(1); 4930 HValue* key = environment()->ExpressionStackAt(1);
4798 HValue* object = environment()->ExpressionStackAt(2); 4931 HValue* object = environment()->ExpressionStackAt(2);
4799 bool has_side_effects = false; 4932 bool has_side_effects = false;
(...skipping 25 matching lines...) Expand all
4825 if (cell->type()->IsConstant()) { 4958 if (cell->type()->IsConstant()) {
4826 IfBuilder builder(this); 4959 IfBuilder builder(this);
4827 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); 4960 HValue* constant = Add<HConstant>(cell->type()->AsConstant());
4828 if (cell->type()->AsConstant()->IsNumber()) { 4961 if (cell->type()->AsConstant()->IsNumber()) {
4829 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); 4962 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ);
4830 } else { 4963 } else {
4831 builder.If<HCompareObjectEqAndBranch>(value, constant); 4964 builder.If<HCompareObjectEqAndBranch>(value, constant);
4832 } 4965 }
4833 builder.Then(); 4966 builder.Then();
4834 builder.Else(); 4967 builder.Else();
4835 Add<HDeoptimize>(Deoptimizer::EAGER); 4968 Add<HDeoptimize>("Constant global variable assignment",
4969 Deoptimizer::EAGER);
4836 builder.End(); 4970 builder.End();
4837 } 4971 }
4838 HInstruction* instr = 4972 HInstruction* instr =
4839 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); 4973 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails());
4840 instr->set_position(position); 4974 instr->set_position(position);
4841 if (instr->HasObservableSideEffects()) { 4975 if (instr->HasObservableSideEffects()) {
4842 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 4976 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
4843 } 4977 }
4844 } else { 4978 } else {
4845 HGlobalObject* global_object = Add<HGlobalObject>(); 4979 HGlobalObject* global_object = Add<HGlobalObject>();
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
5266 return BuildLoadNamedField( 5400 return BuildLoadNamedField(
5267 object, HObjectAccess::ForStringLength(), typecheck); 5401 object, HObjectAccess::ForStringLength(), typecheck);
5268 } 5402 }
5269 5403
5270 5404
5271 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( 5405 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric(
5272 HValue* object, 5406 HValue* object,
5273 Handle<String> name, 5407 Handle<String> name,
5274 Property* expr) { 5408 Property* expr) {
5275 if (expr->IsUninitialized()) { 5409 if (expr->IsUninitialized()) {
5276 Add<HDeoptimize>(Deoptimizer::SOFT); 5410 Add<HDeoptimize>("Insufficient feedback for generic named load",
5411 Deoptimizer::SOFT);
5277 } 5412 }
5278 HValue* context = environment()->context(); 5413 HValue* context = environment()->context();
5279 return new(zone()) HLoadNamedGeneric(context, object, name); 5414 return new(zone()) HLoadNamedGeneric(context, object, name);
5280 } 5415 }
5281 5416
5282 5417
5283 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( 5418 HInstruction* HOptimizedGraphBuilder::BuildCallGetter(
5284 HValue* object, 5419 HValue* object,
5285 Handle<Map> map, 5420 Handle<Map> map,
5286 Handle<JSFunction> getter, 5421 Handle<JSFunction> getter,
5287 Handle<JSObject> holder) { 5422 Handle<JSObject> holder) {
5288 AddCheckConstantFunction(holder, object, map); 5423 AddCheckConstantFunction(holder, object, map);
5289 Add<HPushArgument>(object); 5424 Add<HPushArgument>(object);
5290 return new(zone()) HCallConstantFunction(getter, 1); 5425 return new(zone()) HCallConstantFunction(getter, 1);
5291 } 5426 }
5292 5427
5293 5428
5294 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic( 5429 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
5295 HValue* object, 5430 HValue* object,
5296 Handle<String> name, 5431 Handle<String> name,
5297 Property* expr, 5432 Property* expr,
5298 Handle<Map> map) { 5433 Handle<Map> map) {
5299 // Handle a load from a known field. 5434 // Handle a load from a known field.
5300 ASSERT(!map->is_dictionary_map()); 5435 ASSERT(!map->is_dictionary_map());
5301 5436
5302 // Handle access to various length properties 5437 // Handle access to various length properties
5303 if (name->Equals(isolate()->heap()->length_string())) { 5438 if (name->Equals(isolate()->heap()->length_string())) {
5304 if (map->instance_type() == JS_ARRAY_TYPE) { 5439 if (map->instance_type() == JS_ARRAY_TYPE) {
5305 AddCheckMap(object, map); 5440 HCheckMaps* type_check = AddCheckMap(object, map);
5306 return New<HLoadNamedField>(object, 5441 return New<HLoadNamedField>(object,
5307 HObjectAccess::ForArrayLength(map->elements_kind())); 5442 HObjectAccess::ForArrayLength(map->elements_kind()), type_check);
5308 } 5443 }
5309 } 5444 }
5310 5445
5311 LookupResult lookup(isolate()); 5446 LookupResult lookup(isolate());
5312 map->LookupDescriptor(NULL, *name, &lookup); 5447 map->LookupDescriptor(NULL, *name, &lookup);
5313 if (lookup.IsField()) { 5448 if (lookup.IsField()) {
5314 AddCheckMap(object, map); 5449 HCheckMaps* type_check = AddCheckMap(object, map);
5315 return BuildLoadNamedField(object, 5450 return BuildLoadNamedField(object,
5316 HObjectAccess::ForField(map, &lookup, name)); 5451 HObjectAccess::ForField(map, &lookup, name), type_check);
5317 } 5452 }
5318 5453
5319 // Handle a load of a constant known function. 5454 // Handle a load of a constant known function.
5320 if (lookup.IsConstant()) { 5455 if (lookup.IsConstant()) {
5321 AddCheckMap(object, map); 5456 AddCheckMap(object, map);
5322 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate()); 5457 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate());
5323 return New<HConstant>(constant); 5458 return New<HConstant>(constant);
5324 } 5459 }
5325 5460
5326 // Handle a load from a known field somewhere in the prototype chain. 5461 // Handle a load from a known field somewhere in the prototype chain.
5327 LookupInPrototypes(map, name, &lookup); 5462 LookupInPrototypes(map, name, &lookup);
5328 if (lookup.IsField()) { 5463 if (lookup.IsField()) {
5329 Handle<JSObject> prototype(JSObject::cast(map->prototype())); 5464 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
5330 Handle<JSObject> holder(lookup.holder()); 5465 Handle<JSObject> holder(lookup.holder());
5331 Handle<Map> holder_map(holder->map()); 5466 Handle<Map> holder_map(holder->map());
5332 AddCheckMap(object, map); 5467 HCheckMaps* type_check = AddCheckMap(object, map);
5333 BuildCheckPrototypeMaps(prototype, holder); 5468 BuildCheckPrototypeMaps(prototype, holder);
5334 HValue* holder_value = Add<HConstant>(holder); 5469 HValue* holder_value = Add<HConstant>(holder);
5335 return BuildLoadNamedField(holder_value, 5470 return BuildLoadNamedField(holder_value,
5336 HObjectAccess::ForField(holder_map, &lookup, name)); 5471 HObjectAccess::ForField(holder_map, &lookup, name), type_check);
5337 } 5472 }
5338 5473
5339 // Handle a load of a constant function somewhere in the prototype chain. 5474 // Handle a load of a constant function somewhere in the prototype chain.
5340 if (lookup.IsConstant()) { 5475 if (lookup.IsConstant()) {
5341 Handle<JSObject> prototype(JSObject::cast(map->prototype())); 5476 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
5342 Handle<JSObject> holder(lookup.holder()); 5477 Handle<JSObject> holder(lookup.holder());
5343 Handle<Map> holder_map(holder->map()); 5478 Handle<Map> holder_map(holder->map());
5344 AddCheckMap(object, map); 5479 AddCheckMap(object, map);
5345 BuildCheckPrototypeMaps(prototype, holder); 5480 BuildCheckPrototypeMaps(prototype, holder);
5346 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate()); 5481 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate());
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
5577 external_elements, checked_key, val, 5712 external_elements, checked_key, val,
5578 mapcompare, elements_kind, is_store); 5713 mapcompare, elements_kind, is_store);
5579 } 5714 }
5580 *has_side_effects |= access->HasObservableSideEffects(); 5715 *has_side_effects |= access->HasObservableSideEffects();
5581 // The caller will use has_side_effects and add a correct Simulate. 5716 // The caller will use has_side_effects and add a correct Simulate.
5582 access->SetFlag(HValue::kHasNoObservableSideEffects); 5717 access->SetFlag(HValue::kHasNoObservableSideEffects);
5583 if (position != RelocInfo::kNoPosition) access->set_position(position); 5718 if (position != RelocInfo::kNoPosition) access->set_position(position);
5584 if (!is_store) { 5719 if (!is_store) {
5585 Push(access); 5720 Push(access);
5586 } 5721 }
5722 NoObservableSideEffectsScope scope(this);
5587 current_block()->GotoNoSimulate(join); 5723 current_block()->GotoNoSimulate(join);
5588 set_current_block(other_map); 5724 set_current_block(other_map);
5589 } 5725 }
5590 5726
5591 // Deopt if none of the cases matched. 5727 // Deopt if none of the cases matched.
5592 NoObservableSideEffectsScope scope(this); 5728 NoObservableSideEffectsScope scope(this);
5593 FinishExitWithHardDeoptimization(join); 5729 FinishExitWithHardDeoptimization("Unknown type in polymorphic element access",
5730 join);
5594 set_current_block(join); 5731 set_current_block(join);
5595 return is_store ? NULL : Pop(); 5732 return is_store ? NULL : Pop();
5596 } 5733 }
5597 5734
5598 5735
5599 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( 5736 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
5600 HValue* obj, 5737 HValue* obj,
5601 HValue* key, 5738 HValue* key,
5602 HValue* val, 5739 HValue* val,
5603 Expression* expr, 5740 Expression* expr,
(...skipping 15 matching lines...) Expand all
5619 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); 5756 obj, key, val, NULL, map, is_store, expr->GetStoreMode());
5620 } 5757 }
5621 } else if (expr->GetReceiverTypes() != NULL && 5758 } else if (expr->GetReceiverTypes() != NULL &&
5622 !expr->GetReceiverTypes()->is_empty()) { 5759 !expr->GetReceiverTypes()->is_empty()) {
5623 return HandlePolymorphicElementAccess( 5760 return HandlePolymorphicElementAccess(
5624 obj, key, val, expr, ast_id, position, is_store, 5761 obj, key, val, expr, ast_id, position, is_store,
5625 expr->GetStoreMode(), has_side_effects); 5762 expr->GetStoreMode(), has_side_effects);
5626 } else { 5763 } else {
5627 if (is_store) { 5764 if (is_store) {
5628 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) { 5765 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) {
5629 Add<HDeoptimize>(Deoptimizer::SOFT); 5766 Add<HDeoptimize>("Insufficient feedback for keyed store",
5767 Deoptimizer::SOFT);
5630 } 5768 }
5631 instr = BuildStoreKeyedGeneric(obj, key, val); 5769 instr = BuildStoreKeyedGeneric(obj, key, val);
5632 } else { 5770 } else {
5633 if (expr->AsProperty()->IsUninitialized()) { 5771 if (expr->AsProperty()->IsUninitialized()) {
5634 Add<HDeoptimize>(Deoptimizer::SOFT); 5772 Add<HDeoptimize>("Insufficient feedback for keyed load",
5773 Deoptimizer::SOFT);
5635 } 5774 }
5636 instr = BuildLoadKeyedGeneric(obj, key); 5775 instr = BuildLoadKeyedGeneric(obj, key);
5637 } 5776 }
5638 AddInstruction(instr); 5777 AddInstruction(instr);
5639 } 5778 }
5640 if (position != RelocInfo::kNoPosition) instr->set_position(position); 5779 if (position != RelocInfo::kNoPosition) instr->set_position(position);
5641 *has_side_effects = instr->HasObservableSideEffects(); 5780 *has_side_effects = instr->HasObservableSideEffects();
5642 return instr; 5781 return instr;
5643 } 5782 }
5644 5783
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after
6071 } 6210 }
6072 6211
6073 // Finish up. Unconditionally deoptimize if we've handled all the maps we 6212 // Finish up. Unconditionally deoptimize if we've handled all the maps we
6074 // know about and do not want to handle ones we've never seen. Otherwise 6213 // know about and do not want to handle ones we've never seen. Otherwise
6075 // use a generic IC. 6214 // use a generic IC.
6076 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { 6215 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
6077 // Because the deopt may be the only path in the polymorphic call, make sure 6216 // Because the deopt may be the only path in the polymorphic call, make sure
6078 // that the environment stack matches the depth on deopt that it otherwise 6217 // that the environment stack matches the depth on deopt that it otherwise
6079 // would have had after a successful call. 6218 // would have had after a successful call.
6080 Drop(argument_count - (ast_context()->IsEffect() ? 0 : 1)); 6219 Drop(argument_count - (ast_context()->IsEffect() ? 0 : 1));
6081 FinishExitWithHardDeoptimization(join); 6220 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join);
6082 } else { 6221 } else {
6083 HValue* context = environment()->context(); 6222 HValue* context = environment()->context();
6084 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); 6223 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count);
6085 call->set_position(expr->position()); 6224 call->set_position(expr->position());
6086 PreProcessCall(call); 6225 PreProcessCall(call);
6087 6226
6088 if (join != NULL) { 6227 if (join != NULL) {
6089 AddInstruction(call); 6228 AddInstruction(call);
6090 if (!ast_context()->IsEffect()) Push(call); 6229 if (!ast_context()->IsEffect()) Push(call);
6091 current_block()->Goto(join); 6230 current_block()->Goto(join);
(...skipping 1043 matching lines...) Expand 10 before | Expand all | Expand 10 after
7135 call->set_position(expr->position()); 7274 call->set_position(expr->position());
7136 return ast_context()->ReturnInstruction(call, expr->id()); 7275 return ast_context()->ReturnInstruction(call, expr->id());
7137 } else { 7276 } else {
7138 // The constructor function is both an operand to the instruction and an 7277 // The constructor function is both an operand to the instruction and an
7139 // argument to the construct call. 7278 // argument to the construct call.
7140 Handle<JSFunction> array_function( 7279 Handle<JSFunction> array_function(
7141 isolate()->global_context()->array_function(), isolate()); 7280 isolate()->global_context()->array_function(), isolate());
7142 CHECK_ALIVE(VisitArgument(expr->expression())); 7281 CHECK_ALIVE(VisitArgument(expr->expression()));
7143 HValue* constructor = HPushArgument::cast(Top())->argument(); 7282 HValue* constructor = HPushArgument::cast(Top())->argument();
7144 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 7283 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
7145 HCallNew* call; 7284 HBinaryCall* call;
7146 if (expr->target().is_identical_to(array_function)) { 7285 if (expr->target().is_identical_to(array_function)) {
7147 Handle<Cell> cell = expr->allocation_info_cell(); 7286 Handle<Cell> cell = expr->allocation_info_cell();
7148 Add<HCheckFunction>(constructor, array_function); 7287 Add<HCheckFunction>(constructor, array_function);
7149 call = new(zone()) HCallNewArray(context, constructor, argument_count, 7288 call = new(zone()) HCallNewArray(context, constructor, argument_count,
7150 cell, expr->elements_kind()); 7289 cell, expr->elements_kind());
7151 } else { 7290 } else {
7152 call = new(zone()) HCallNew(context, constructor, argument_count); 7291 call = new(zone()) HCallNew(context, constructor, argument_count);
7153 } 7292 }
7154 Drop(argument_count); 7293 Drop(argument_count);
7155 call->set_position(expr->position()); 7294 call->set_position(expr->position());
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after
7631 7770
7632 if (expr->op() != Token::ADD || 7771 if (expr->op() != Token::ADD ||
7633 (left->type().IsNonString() && right->type().IsNonString())) { 7772 (left->type().IsNonString() && right->type().IsNonString())) {
7634 // For addition we can only truncate the arguments to number if we can 7773 // For addition we can only truncate the arguments to number if we can
7635 // prove that we will not end up in string concatenation mode. 7774 // prove that we will not end up in string concatenation mode.
7636 left = TruncateToNumber(left, &left_type); 7775 left = TruncateToNumber(left, &left_type);
7637 right = TruncateToNumber(right, &right_type); 7776 right = TruncateToNumber(right, &right_type);
7638 } 7777 }
7639 7778
7640 if (left_type->Is(Type::None())) { 7779 if (left_type->Is(Type::None())) {
7641 Add<HDeoptimize>(Deoptimizer::SOFT); 7780 Add<HDeoptimize>("Insufficient type feedback for left side",
7781 Deoptimizer::SOFT);
7642 // TODO(rossberg): we should be able to get rid of non-continuous defaults. 7782 // TODO(rossberg): we should be able to get rid of non-continuous defaults.
7643 left_type = handle(Type::Any(), isolate()); 7783 left_type = handle(Type::Any(), isolate());
7644 } 7784 }
7645 if (right_type->Is(Type::None())) { 7785 if (right_type->Is(Type::None())) {
7646 Add<HDeoptimize>(Deoptimizer::SOFT); 7786 Add<HDeoptimize>("Insufficient type feedback for right side",
7787 Deoptimizer::SOFT);
7647 right_type = handle(Type::Any(), isolate()); 7788 right_type = handle(Type::Any(), isolate());
7648 } 7789 }
7649 HInstruction* instr = NULL; 7790 HInstruction* instr = NULL;
7650 switch (expr->op()) { 7791 switch (expr->op()) {
7651 case Token::ADD: 7792 case Token::ADD:
7652 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { 7793 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) {
7653 BuildCheckHeapObject(left); 7794 BuildCheckHeapObject(left);
7654 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); 7795 AddInstruction(HCheckInstanceType::NewIsString(left, zone()));
7655 BuildCheckHeapObject(right); 7796 BuildCheckHeapObject(right);
7656 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); 7797 AddInstruction(HCheckInstanceType::NewIsString(right, zone()));
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
7986 // TODO(olivf) InvokeFunction produces a check for the parameter count, 8127 // TODO(olivf) InvokeFunction produces a check for the parameter count,
7987 // even though we are certain to pass the correct number of arguments here. 8128 // even though we are certain to pass the correct number of arguments here.
7988 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2); 8129 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2);
7989 result->set_position(expr->position()); 8130 result->set_position(expr->position());
7990 return ast_context()->ReturnInstruction(result, expr->id()); 8131 return ast_context()->ReturnInstruction(result, expr->id());
7991 } 8132 }
7992 8133
7993 // Cases handled below depend on collected type feedback. They should 8134 // Cases handled below depend on collected type feedback. They should
7994 // soft deoptimize when there is no type feedback. 8135 // soft deoptimize when there is no type feedback.
7995 if (combined_type->Is(Type::None())) { 8136 if (combined_type->Is(Type::None())) {
7996 Add<HDeoptimize>(Deoptimizer::SOFT); 8137 Add<HDeoptimize>("insufficient type feedback for combined type",
8138 Deoptimizer::SOFT);
7997 combined_type = left_type = right_type = handle(Type::Any(), isolate()); 8139 combined_type = left_type = right_type = handle(Type::Any(), isolate());
7998 } 8140 }
7999 8141
8000 if (combined_type->Is(Type::Receiver())) { 8142 if (combined_type->Is(Type::Receiver())) {
8001 switch (op) { 8143 switch (op) {
8002 case Token::EQ: 8144 case Token::EQ:
8003 case Token::EQ_STRICT: { 8145 case Token::EQ_STRICT: {
8004 // Can we get away with map check and not instance type check? 8146 // Can we get away with map check and not instance type check?
8005 if (combined_type->IsClass()) { 8147 if (combined_type->IsClass()) {
8006 Handle<Map> map = combined_type->AsClass(); 8148 Handle<Map> map = combined_type->AsClass();
(...skipping 29 matching lines...) Expand all
8036 return ast_context()->ReturnControl(result, expr->id()); 8178 return ast_context()->ReturnControl(result, expr->id());
8037 } else { 8179 } else {
8038 if (combined_rep.IsTagged() || combined_rep.IsNone()) { 8180 if (combined_rep.IsTagged() || combined_rep.IsNone()) {
8039 HCompareGeneric* result = 8181 HCompareGeneric* result =
8040 new(zone()) HCompareGeneric(context, left, right, op); 8182 new(zone()) HCompareGeneric(context, left, right, op);
8041 result->set_observed_input_representation(1, left_rep); 8183 result->set_observed_input_representation(1, left_rep);
8042 result->set_observed_input_representation(2, right_rep); 8184 result->set_observed_input_representation(2, right_rep);
8043 result->set_position(expr->position()); 8185 result->set_position(expr->position());
8044 return ast_context()->ReturnInstruction(result, expr->id()); 8186 return ast_context()->ReturnInstruction(result, expr->id());
8045 } else { 8187 } else {
8046 // TODO(verwaest): Remove once Representation::FromType properly
8047 // returns Smi when the IC measures Smi.
8048 if (left_type->Is(Type::Smi())) left_rep = Representation::Smi();
8049 if (right_type->Is(Type::Smi())) right_rep = Representation::Smi();
8050 HCompareNumericAndBranch* result = 8188 HCompareNumericAndBranch* result =
8051 new(zone()) HCompareNumericAndBranch(left, right, op); 8189 new(zone()) HCompareNumericAndBranch(left, right, op);
8052 result->set_observed_input_representation(left_rep, right_rep); 8190 result->set_observed_input_representation(left_rep, right_rep);
8053 result->set_position(expr->position()); 8191 result->set_position(expr->position());
8054 return ast_context()->ReturnControl(result, expr->id()); 8192 return ast_context()->ReturnControl(result, expr->id());
8055 } 8193 }
8056 } 8194 }
8057 } 8195 }
8058 8196
8059 8197
(...skipping 1150 matching lines...) Expand 10 before | Expand all | Expand 10 after
9210 ASSERT(!block->IsLoopHeader()); 9348 ASSERT(!block->IsLoopHeader());
9211 ASSERT(values_.length() == other->values_.length()); 9349 ASSERT(values_.length() == other->values_.length());
9212 9350
9213 int length = values_.length(); 9351 int length = values_.length();
9214 for (int i = 0; i < length; ++i) { 9352 for (int i = 0; i < length; ++i) {
9215 HValue* value = values_[i]; 9353 HValue* value = values_[i];
9216 if (value != NULL && value->IsPhi() && value->block() == block) { 9354 if (value != NULL && value->IsPhi() && value->block() == block) {
9217 // There is already a phi for the i'th value. 9355 // There is already a phi for the i'th value.
9218 HPhi* phi = HPhi::cast(value); 9356 HPhi* phi = HPhi::cast(value);
9219 // Assert index is correct and that we haven't missed an incoming edge. 9357 // Assert index is correct and that we haven't missed an incoming edge.
9220 ASSERT(phi->merged_index() == i); 9358 ASSERT(phi->merged_index() == i || !phi->HasMergedIndex());
9221 ASSERT(phi->OperandCount() == block->predecessors()->length()); 9359 ASSERT(phi->OperandCount() == block->predecessors()->length());
9222 phi->AddInput(other->values_[i]); 9360 phi->AddInput(other->values_[i]);
9223 } else if (values_[i] != other->values_[i]) { 9361 } else if (values_[i] != other->values_[i]) {
9224 // There is a fresh value on the incoming edge, a phi is needed. 9362 // There is a fresh value on the incoming edge, a phi is needed.
9225 ASSERT(values_[i] != NULL && other->values_[i] != NULL); 9363 ASSERT(values_[i] != NULL && other->values_[i] != NULL);
9226 HPhi* phi = new(zone()) HPhi(i, zone()); 9364 HPhi* phi = block->AddNewPhi(i);
9227 HValue* old_value = values_[i]; 9365 HValue* old_value = values_[i];
9228 for (int j = 0; j < block->predecessors()->length(); j++) { 9366 for (int j = 0; j < block->predecessors()->length(); j++) {
9229 phi->AddInput(old_value); 9367 phi->AddInput(old_value);
9230 } 9368 }
9231 phi->AddInput(other->values_[i]); 9369 phi->AddInput(other->values_[i]);
9232 this->values_[i] = phi; 9370 this->values_[i] = phi;
9233 block->AddPhi(phi);
9234 } 9371 }
9235 } 9372 }
9236 } 9373 }
9237 9374
9238 9375
9239 void HEnvironment::Bind(int index, HValue* value) { 9376 void HEnvironment::Bind(int index, HValue* value) {
9240 ASSERT(value != NULL); 9377 ASSERT(value != NULL);
9241 assigned_variables_.Add(index, zone()); 9378 assigned_variables_.Add(index, zone());
9242 values_[index] = value; 9379 values_[index] = value;
9243 } 9380 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
9284 HEnvironment* HEnvironment::CopyWithoutHistory() const { 9421 HEnvironment* HEnvironment::CopyWithoutHistory() const {
9285 HEnvironment* result = Copy(); 9422 HEnvironment* result = Copy();
9286 result->ClearHistory(); 9423 result->ClearHistory();
9287 return result; 9424 return result;
9288 } 9425 }
9289 9426
9290 9427
9291 HEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const { 9428 HEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const {
9292 HEnvironment* new_env = Copy(); 9429 HEnvironment* new_env = Copy();
9293 for (int i = 0; i < values_.length(); ++i) { 9430 for (int i = 0; i < values_.length(); ++i) {
9294 HPhi* phi = new(zone()) HPhi(i, zone()); 9431 HPhi* phi = loop_header->AddNewPhi(i);
9295 phi->AddInput(values_[i]); 9432 phi->AddInput(values_[i]);
9296 new_env->values_[i] = phi; 9433 new_env->values_[i] = phi;
9297 loop_header->AddPhi(phi);
9298 } 9434 }
9299 new_env->ClearHistory(); 9435 new_env->ClearHistory();
9300 return new_env; 9436 return new_env;
9301 } 9437 }
9302 9438
9303 9439
9304 HEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer, 9440 HEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer,
9305 Handle<JSFunction> target, 9441 Handle<JSFunction> target,
9306 FrameType frame_type, 9442 FrameType frame_type,
9307 int arguments) const { 9443 int arguments) const {
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after
9709 if (ShouldProduceTraceOutput()) { 9845 if (ShouldProduceTraceOutput()) {
9710 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 9846 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
9711 } 9847 }
9712 9848
9713 #ifdef DEBUG 9849 #ifdef DEBUG
9714 graph_->Verify(false); // No full verify. 9850 graph_->Verify(false); // No full verify.
9715 #endif 9851 #endif
9716 } 9852 }
9717 9853
9718 } } // namespace v8::internal 9854 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-dce.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698