| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |