| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 } | 99 } |
| 100 | 100 |
| 101 | 101 |
| 102 void HBasicBlock::AddInstruction(HInstruction* instr) { | 102 void HBasicBlock::AddInstruction(HInstruction* instr) { |
| 103 ASSERT(!IsStartBlock() || !IsFinished()); | 103 ASSERT(!IsStartBlock() || !IsFinished()); |
| 104 ASSERT(!instr->IsLinked()); | 104 ASSERT(!instr->IsLinked()); |
| 105 ASSERT(!IsFinished()); | 105 ASSERT(!IsFinished()); |
| 106 if (first_ == NULL) { | 106 if (first_ == NULL) { |
| 107 HBlockEntry* entry = new HBlockEntry(); | 107 HBlockEntry* entry = new HBlockEntry(); |
| 108 entry->InitializeAsFirst(this); | 108 entry->InitializeAsFirst(this); |
| 109 first_ = entry; | 109 first_ = last_ = entry; |
| 110 } | 110 } |
| 111 instr->InsertAfter(GetLastInstruction()); | 111 instr->InsertAfter(last_); |
| 112 last_ = instr; |
| 112 } | 113 } |
| 113 | 114 |
| 114 | 115 |
| 115 HInstruction* HBasicBlock::GetLastInstruction() { | |
| 116 if (end_ != NULL) return end_->previous(); | |
| 117 if (first_ == NULL) return NULL; | |
| 118 if (last_ == NULL) last_ = first_; | |
| 119 while (last_->next() != NULL) last_ = last_->next(); | |
| 120 return last_; | |
| 121 } | |
| 122 | |
| 123 | |
| 124 HSimulate* HBasicBlock::CreateSimulate(int id) { | 116 HSimulate* HBasicBlock::CreateSimulate(int id) { |
| 125 ASSERT(HasEnvironment()); | 117 ASSERT(HasEnvironment()); |
| 126 HEnvironment* environment = last_environment(); | 118 HEnvironment* environment = last_environment(); |
| 127 ASSERT(id == AstNode::kNoNumber || | 119 ASSERT(id == AstNode::kNoNumber || |
| 128 environment->closure()->shared()->VerifyBailoutId(id)); | 120 environment->closure()->shared()->VerifyBailoutId(id)); |
| 129 | 121 |
| 130 int push_count = environment->push_count(); | 122 int push_count = environment->push_count(); |
| 131 int pop_count = environment->pop_count(); | 123 int pop_count = environment->pop_count(); |
| 132 | 124 |
| 133 int length = environment->length(); | 125 int length = environment->length(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 UpdateEnvironment(env); | 163 UpdateEnvironment(env); |
| 172 } | 164 } |
| 173 | 165 |
| 174 | 166 |
| 175 void HBasicBlock::SetJoinId(int id) { | 167 void HBasicBlock::SetJoinId(int id) { |
| 176 int length = predecessors_.length(); | 168 int length = predecessors_.length(); |
| 177 ASSERT(length > 0); | 169 ASSERT(length > 0); |
| 178 for (int i = 0; i < length; i++) { | 170 for (int i = 0; i < length; i++) { |
| 179 HBasicBlock* predecessor = predecessors_[i]; | 171 HBasicBlock* predecessor = predecessors_[i]; |
| 180 ASSERT(predecessor->end()->IsGoto()); | 172 ASSERT(predecessor->end()->IsGoto()); |
| 181 HSimulate* simulate = HSimulate::cast(predecessor->GetLastInstruction()); | 173 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous()); |
| 182 // We only need to verify the ID once. | 174 // We only need to verify the ID once. |
| 183 ASSERT(i != 0 || | 175 ASSERT(i != 0 || |
| 184 predecessor->last_environment()->closure()->shared() | 176 predecessor->last_environment()->closure()->shared() |
| 185 ->VerifyBailoutId(id)); | 177 ->VerifyBailoutId(id)); |
| 186 simulate->set_ast_id(id); | 178 simulate->set_ast_id(id); |
| 187 } | 179 } |
| 188 } | 180 } |
| 189 | 181 |
| 190 | 182 |
| 191 bool HBasicBlock::Dominates(HBasicBlock* other) const { | 183 bool HBasicBlock::Dominates(HBasicBlock* other) const { |
| (...skipping 2887 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3079 } | 3071 } |
| 3080 ast_context()->ReturnValue(Pop()); | 3072 ast_context()->ReturnValue(Pop()); |
| 3081 } | 3073 } |
| 3082 | 3074 |
| 3083 | 3075 |
| 3084 void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { | 3076 void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { |
| 3085 BAILOUT("CatchExtensionObject"); | 3077 BAILOUT("CatchExtensionObject"); |
| 3086 } | 3078 } |
| 3087 | 3079 |
| 3088 | 3080 |
| 3089 HBasicBlock* HGraphBuilder::BuildTypeSwitch(ZoneMapList* maps, | 3081 HBasicBlock* HGraphBuilder::BuildTypeSwitch(HValue* receiver, |
| 3090 ZoneList<HSubgraph*>* subgraphs, | 3082 ZoneMapList* maps, |
| 3091 HValue* receiver, | 3083 ZoneList<HSubgraph*>* body_graphs, |
| 3084 HSubgraph* default_graph, |
| 3092 int join_id) { | 3085 int join_id) { |
| 3093 ASSERT(subgraphs->length() == (maps->length() + 1)); | 3086 ASSERT(maps->length() == body_graphs->length()); |
| 3087 HBasicBlock* join_block = graph()->CreateBasicBlock(); |
| 3088 AddInstruction(new HCheckNonSmi(receiver)); |
| 3094 | 3089 |
| 3095 // Build map compare subgraphs for all but the first map. | 3090 for (int i = 0; i < maps->length(); ++i) { |
| 3096 ZoneList<HSubgraph*> map_compare_subgraphs(maps->length() - 1); | 3091 // Build the branches, connect all the target subgraphs to the join |
| 3097 for (int i = maps->length() - 1; i > 0; --i) { | 3092 // block. Use the default as a target of the last branch. |
| 3098 HSubgraph* subgraph = CreateBranchSubgraph(environment()); | 3093 HSubgraph* if_true = body_graphs->at(i); |
| 3099 SubgraphScope scope(this, subgraph); | 3094 HSubgraph* if_false = (i == maps->length() - 1) |
| 3100 HSubgraph* else_subgraph = | 3095 ? default_graph |
| 3101 (i == (maps->length() - 1)) | 3096 : CreateBranchSubgraph(environment()); |
| 3102 ? subgraphs->last() | 3097 HCompareMap* compare = |
| 3103 : map_compare_subgraphs.last(); | 3098 new HCompareMap(receiver, |
| 3104 HCompareMap* compare = new HCompareMap(receiver, | 3099 maps->at(i), |
| 3105 maps->at(i), | 3100 if_true->entry_block(), |
| 3106 subgraphs->at(i)->entry_block(), | 3101 if_false->entry_block()); |
| 3107 else_subgraph->entry_block()); | 3102 subgraph()->exit_block()->Finish(compare); |
| 3108 current_subgraph_->exit_block()->Finish(compare); | 3103 |
| 3109 map_compare_subgraphs.Add(subgraph); | 3104 if (if_true->HasExit()) { |
| 3105 // In an effect context the value of the type switch is not needed. |
| 3106 // There is no need to merge it at the join block only to discard it. |
| 3107 if (ast_context()->IsEffect()) { |
| 3108 if_true->exit_block()->last_environment()->Drop(1); |
| 3109 } |
| 3110 if_true->exit_block()->Goto(join_block); |
| 3111 } |
| 3112 |
| 3113 subgraph()->set_exit_block(if_false->exit_block()); |
| 3110 } | 3114 } |
| 3111 | 3115 |
| 3112 // Generate first map check to end the current block. | 3116 // Connect the default if necessary. |
| 3113 AddInstruction(new HCheckNonSmi(receiver)); | 3117 if (subgraph()->HasExit()) { |
| 3114 HSubgraph* else_subgraph = | 3118 if (ast_context()->IsEffect()) { |
| 3115 (maps->length() == 1) ? subgraphs->at(1) : map_compare_subgraphs.last(); | 3119 environment()->Drop(1); |
| 3116 HCompareMap* compare = new HCompareMap(receiver, | |
| 3117 Handle<Map>(maps->first()), | |
| 3118 subgraphs->first()->entry_block(), | |
| 3119 else_subgraph->entry_block()); | |
| 3120 current_subgraph_->exit_block()->Finish(compare); | |
| 3121 | |
| 3122 // Join all the call subgraphs in a new basic block and make | |
| 3123 // this basic block the current basic block. | |
| 3124 HBasicBlock* join_block = graph_->CreateBasicBlock(); | |
| 3125 for (int i = 0; i < subgraphs->length(); ++i) { | |
| 3126 HSubgraph* subgraph = subgraphs->at(i); | |
| 3127 if (subgraph->HasExit()) { | |
| 3128 // In an effect context the value of the type switch is not needed. | |
| 3129 // There is no need to merge it at the join block only to discard it. | |
| 3130 HBasicBlock* subgraph_exit = subgraph->exit_block(); | |
| 3131 if (ast_context()->IsEffect()) { | |
| 3132 subgraph_exit->last_environment()->Drop(1); | |
| 3133 } | |
| 3134 subgraph_exit->Goto(join_block); | |
| 3135 } | 3120 } |
| 3121 subgraph()->exit_block()->Goto(join_block); |
| 3136 } | 3122 } |
| 3137 | 3123 |
| 3138 if (join_block->predecessors()->is_empty()) return NULL; | 3124 if (join_block->predecessors()->is_empty()) return NULL; |
| 3139 join_block->SetJoinId(join_id); | 3125 join_block->SetJoinId(join_id); |
| 3140 return join_block; | 3126 return join_block; |
| 3141 } | 3127 } |
| 3142 | 3128 |
| 3143 | 3129 |
| 3144 // Sets the lookup result and returns true if the store can be inlined. | 3130 // Sets the lookup result and returns true if the store can be inlined. |
| 3145 static bool ComputeStoredField(Handle<Map> type, | 3131 static bool ComputeStoredField(Handle<Map> type, |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3231 } | 3217 } |
| 3232 | 3218 |
| 3233 | 3219 |
| 3234 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, | 3220 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, |
| 3235 HValue* object, | 3221 HValue* object, |
| 3236 HValue* value, | 3222 HValue* value, |
| 3237 ZoneMapList* types, | 3223 ZoneMapList* types, |
| 3238 Handle<String> name) { | 3224 Handle<String> name) { |
| 3239 int number_of_types = Min(types->length(), kMaxStorePolymorphism); | 3225 int number_of_types = Min(types->length(), kMaxStorePolymorphism); |
| 3240 ZoneMapList maps(number_of_types); | 3226 ZoneMapList maps(number_of_types); |
| 3241 ZoneList<HSubgraph*> subgraphs(number_of_types + 1); | 3227 ZoneList<HSubgraph*> subgraphs(number_of_types); |
| 3242 bool needs_generic = (types->length() > kMaxStorePolymorphism); | 3228 bool needs_generic = (types->length() > kMaxStorePolymorphism); |
| 3243 | 3229 |
| 3244 // Build subgraphs for each of the specific maps. | 3230 // Build subgraphs for each of the specific maps. |
| 3245 // | 3231 // |
| 3246 // TODO(ager): We should recognize when the prototype chains for | 3232 // TODO(ager): We should recognize when the prototype chains for |
| 3247 // different maps are identical. In that case we can avoid | 3233 // different maps are identical. In that case we can avoid |
| 3248 // repeatedly generating the same prototype map checks. | 3234 // repeatedly generating the same prototype map checks. |
| 3249 for (int i = 0; i < number_of_types; ++i) { | 3235 for (int i = 0; i < number_of_types; ++i) { |
| 3250 Handle<Map> map = types->at(i); | 3236 Handle<Map> map = types->at(i); |
| 3251 LookupResult lookup; | 3237 LookupResult lookup; |
| 3252 if (ComputeStoredField(map, name, &lookup)) { | 3238 if (ComputeStoredField(map, name, &lookup)) { |
| 3253 maps.Add(map); | |
| 3254 HSubgraph* subgraph = CreateBranchSubgraph(environment()); | 3239 HSubgraph* subgraph = CreateBranchSubgraph(environment()); |
| 3255 SubgraphScope scope(this, subgraph); | 3240 SubgraphScope scope(this, subgraph); |
| 3256 HInstruction* instr = | 3241 HInstruction* instr = |
| 3257 BuildStoreNamedField(object, name, value, map, &lookup, false); | 3242 BuildStoreNamedField(object, name, value, map, &lookup, false); |
| 3258 Push(value); | 3243 Push(value); |
| 3259 instr->set_position(expr->position()); | 3244 instr->set_position(expr->position()); |
| 3260 AddInstruction(instr); | 3245 AddInstruction(instr); |
| 3246 maps.Add(map); |
| 3261 subgraphs.Add(subgraph); | 3247 subgraphs.Add(subgraph); |
| 3262 } else { | 3248 } else { |
| 3263 needs_generic = true; | 3249 needs_generic = true; |
| 3264 } | 3250 } |
| 3265 } | 3251 } |
| 3266 | 3252 |
| 3267 // If none of the properties were named fields we generate a | 3253 // If none of the properties were named fields we generate a |
| 3268 // generic store. | 3254 // generic store. |
| 3269 if (maps.length() == 0) { | 3255 if (maps.length() == 0) { |
| 3270 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); | 3256 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); |
| 3271 Push(value); | 3257 Push(value); |
| 3272 instr->set_position(expr->position()); | 3258 instr->set_position(expr->position()); |
| 3273 AddInstruction(instr); | 3259 AddInstruction(instr); |
| 3274 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 3260 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
| 3275 ast_context()->ReturnValue(Pop()); | 3261 ast_context()->ReturnValue(Pop()); |
| 3276 } else { | 3262 } else { |
| 3277 // Build subgraph for generic store through IC. | 3263 // Build subgraph for generic store through IC. |
| 3278 { | 3264 HSubgraph* default_graph = CreateBranchSubgraph(environment()); |
| 3279 HSubgraph* subgraph = CreateBranchSubgraph(environment()); | 3265 { SubgraphScope scope(this, default_graph); |
| 3280 SubgraphScope scope(this, subgraph); | |
| 3281 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { | 3266 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { |
| 3282 subgraph->FinishExit(new HDeoptimize()); | 3267 default_graph->FinishExit(new HDeoptimize()); |
| 3283 } else { | 3268 } else { |
| 3284 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); | 3269 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); |
| 3285 Push(value); | 3270 Push(value); |
| 3286 instr->set_position(expr->position()); | 3271 instr->set_position(expr->position()); |
| 3287 AddInstruction(instr); | 3272 AddInstruction(instr); |
| 3288 } | 3273 } |
| 3289 subgraphs.Add(subgraph); | |
| 3290 } | 3274 } |
| 3291 | 3275 |
| 3292 HBasicBlock* new_exit_block = | 3276 HBasicBlock* new_exit_block = |
| 3293 BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); | 3277 BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id()); |
| 3294 subgraph()->set_exit_block(new_exit_block); | 3278 subgraph()->set_exit_block(new_exit_block); |
| 3295 // In an effect context, we did not materialized the value in the | 3279 // In an effect context, we did not materialized the value in the |
| 3296 // predecessor environments so there's no need to handle it here. | 3280 // predecessor environments so there's no need to handle it here. |
| 3297 if (subgraph()->HasExit() && !ast_context()->IsEffect()) { | 3281 if (subgraph()->HasExit() && !ast_context()->IsEffect()) { |
| 3298 ast_context()->ReturnValue(Pop()); | 3282 ast_context()->ReturnValue(Pop()); |
| 3299 } | 3283 } |
| 3300 } | 3284 } |
| 3301 } | 3285 } |
| 3302 | 3286 |
| 3303 | 3287 |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3558 current_subgraph_->FinishExit(new HAbnormalExit); | 3542 current_subgraph_->FinishExit(new HAbnormalExit); |
| 3559 } | 3543 } |
| 3560 | 3544 |
| 3561 | 3545 |
| 3562 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, | 3546 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, |
| 3563 HValue* object, | 3547 HValue* object, |
| 3564 ZoneMapList* types, | 3548 ZoneMapList* types, |
| 3565 Handle<String> name) { | 3549 Handle<String> name) { |
| 3566 int number_of_types = Min(types->length(), kMaxLoadPolymorphism); | 3550 int number_of_types = Min(types->length(), kMaxLoadPolymorphism); |
| 3567 ZoneMapList maps(number_of_types); | 3551 ZoneMapList maps(number_of_types); |
| 3568 ZoneList<HSubgraph*> subgraphs(number_of_types + 1); | 3552 ZoneList<HSubgraph*> subgraphs(number_of_types); |
| 3569 bool needs_generic = (types->length() > kMaxLoadPolymorphism); | 3553 bool needs_generic = (types->length() > kMaxLoadPolymorphism); |
| 3570 | 3554 |
| 3571 // Build subgraphs for each of the specific maps. | 3555 // Build subgraphs for each of the specific maps. |
| 3572 // | 3556 // |
| 3573 // TODO(ager): We should recognize when the prototype chains for | 3557 // TODO(ager): We should recognize when the prototype chains for |
| 3574 // different maps are identical. In that case we can avoid | 3558 // different maps are identical. In that case we can avoid |
| 3575 // repeatedly generating the same prototype map checks. | 3559 // repeatedly generating the same prototype map checks. |
| 3576 for (int i = 0; i < number_of_types; ++i) { | 3560 for (int i = 0; i < number_of_types; ++i) { |
| 3577 Handle<Map> map = types->at(i); | 3561 Handle<Map> map = types->at(i); |
| 3578 LookupResult lookup; | 3562 LookupResult lookup; |
| 3579 map->LookupInDescriptors(NULL, *name, &lookup); | 3563 map->LookupInDescriptors(NULL, *name, &lookup); |
| 3580 if (lookup.IsProperty() && lookup.type() == FIELD) { | 3564 if (lookup.IsProperty() && lookup.type() == FIELD) { |
| 3581 maps.Add(map); | |
| 3582 HSubgraph* subgraph = CreateBranchSubgraph(environment()); | 3565 HSubgraph* subgraph = CreateBranchSubgraph(environment()); |
| 3583 SubgraphScope scope(this, subgraph); | 3566 SubgraphScope scope(this, subgraph); |
| 3584 HLoadNamedField* instr = | 3567 HLoadNamedField* instr = |
| 3585 BuildLoadNamedField(object, expr, map, &lookup, false); | 3568 BuildLoadNamedField(object, expr, map, &lookup, false); |
| 3586 instr->set_position(expr->position()); | 3569 instr->set_position(expr->position()); |
| 3587 instr->ClearFlag(HValue::kUseGVN); // Don't do GVN on polymorphic loads. | 3570 instr->ClearFlag(HValue::kUseGVN); // Don't do GVN on polymorphic loads. |
| 3588 PushAndAdd(instr); | 3571 PushAndAdd(instr); |
| 3572 maps.Add(map); |
| 3589 subgraphs.Add(subgraph); | 3573 subgraphs.Add(subgraph); |
| 3590 } else { | 3574 } else { |
| 3591 needs_generic = true; | 3575 needs_generic = true; |
| 3592 } | 3576 } |
| 3593 } | 3577 } |
| 3594 | 3578 |
| 3595 // If none of the properties were named fields we generate a | 3579 // If none of the properties were named fields we generate a |
| 3596 // generic load. | 3580 // generic load. |
| 3597 if (maps.length() == 0) { | 3581 if (maps.length() == 0) { |
| 3598 HInstruction* instr = BuildLoadNamedGeneric(object, expr); | 3582 HInstruction* instr = BuildLoadNamedGeneric(object, expr); |
| 3599 instr->set_position(expr->position()); | 3583 instr->set_position(expr->position()); |
| 3600 ast_context()->ReturnInstruction(instr, expr->id()); | 3584 ast_context()->ReturnInstruction(instr, expr->id()); |
| 3601 } else { | 3585 } else { |
| 3602 // Build subgraph for generic load through IC. | 3586 // Build subgraph for generic load through IC. |
| 3603 { | 3587 HSubgraph* default_graph = CreateBranchSubgraph(environment()); |
| 3604 HSubgraph* subgraph = CreateBranchSubgraph(environment()); | 3588 { SubgraphScope scope(this, default_graph); |
| 3605 SubgraphScope scope(this, subgraph); | |
| 3606 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { | 3589 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { |
| 3607 subgraph->FinishExit(new HDeoptimize()); | 3590 default_graph->FinishExit(new HDeoptimize()); |
| 3608 } else { | 3591 } else { |
| 3609 HInstruction* instr = BuildLoadNamedGeneric(object, expr); | 3592 HInstruction* instr = BuildLoadNamedGeneric(object, expr); |
| 3610 instr->set_position(expr->position()); | 3593 instr->set_position(expr->position()); |
| 3611 PushAndAdd(instr); | 3594 PushAndAdd(instr); |
| 3612 } | 3595 } |
| 3613 subgraphs.Add(subgraph); | |
| 3614 } | 3596 } |
| 3615 | 3597 |
| 3616 HBasicBlock* new_exit_block = | 3598 HBasicBlock* new_exit_block = |
| 3617 BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); | 3599 BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id()); |
| 3618 subgraph()->set_exit_block(new_exit_block); | 3600 subgraph()->set_exit_block(new_exit_block); |
| 3619 // In an effect context, we did not materialized the value in the | 3601 // In an effect context, we did not materialized the value in the |
| 3620 // predecessor environments so there's no need to handle it here. | 3602 // predecessor environments so there's no need to handle it here. |
| 3621 if (subgraph()->HasExit() && !ast_context()->IsEffect()) { | 3603 if (subgraph()->HasExit() && !ast_context()->IsEffect()) { |
| 3622 ast_context()->ReturnValue(Pop()); | 3604 ast_context()->ReturnValue(Pop()); |
| 3623 } | 3605 } |
| 3624 } | 3606 } |
| 3625 } | 3607 } |
| 3626 | 3608 |
| 3627 | 3609 |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3884 } | 3866 } |
| 3885 | 3867 |
| 3886 | 3868 |
| 3887 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, | 3869 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, |
| 3888 HValue* receiver, | 3870 HValue* receiver, |
| 3889 ZoneMapList* types, | 3871 ZoneMapList* types, |
| 3890 Handle<String> name) { | 3872 Handle<String> name) { |
| 3891 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 3873 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 3892 int number_of_types = Min(types->length(), kMaxCallPolymorphism); | 3874 int number_of_types = Min(types->length(), kMaxCallPolymorphism); |
| 3893 ZoneMapList maps(number_of_types); | 3875 ZoneMapList maps(number_of_types); |
| 3894 ZoneList<HSubgraph*> subgraphs(number_of_types + 1); | 3876 ZoneList<HSubgraph*> subgraphs(number_of_types); |
| 3895 bool needs_generic = (types->length() > kMaxCallPolymorphism); | 3877 bool needs_generic = (types->length() > kMaxCallPolymorphism); |
| 3896 | 3878 |
| 3897 // Build subgraphs for each of the specific maps. | 3879 // Build subgraphs for each of the specific maps. |
| 3898 // | 3880 // |
| 3899 // TODO(ager): We should recognize when the prototype chains for different | 3881 // TODO(ager): We should recognize when the prototype chains for different |
| 3900 // maps are identical. In that case we can avoid repeatedly generating the | 3882 // maps are identical. In that case we can avoid repeatedly generating the |
| 3901 // same prototype map checks. | 3883 // same prototype map checks. |
| 3902 for (int i = 0; i < number_of_types; ++i) { | 3884 for (int i = 0; i < number_of_types; ++i) { |
| 3903 Handle<Map> map = types->at(i); | 3885 Handle<Map> map = types->at(i); |
| 3904 if (expr->ComputeTarget(map, name)) { | 3886 if (expr->ComputeTarget(map, name)) { |
| 3905 maps.Add(map); | |
| 3906 HSubgraph* subgraph = CreateBranchSubgraph(environment()); | 3887 HSubgraph* subgraph = CreateBranchSubgraph(environment()); |
| 3907 SubgraphScope scope(this, subgraph); | 3888 SubgraphScope scope(this, subgraph); |
| 3908 AddCheckConstantFunction(expr, receiver, map, false); | 3889 AddCheckConstantFunction(expr, receiver, map, false); |
| 3909 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { | 3890 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { |
| 3910 PrintF("Trying to inline the polymorphic call to %s\n", | 3891 PrintF("Trying to inline the polymorphic call to %s\n", |
| 3911 *name->ToCString()); | 3892 *name->ToCString()); |
| 3912 } | 3893 } |
| 3913 if (!FLAG_polymorphic_inlining || !TryInline(expr)) { | 3894 if (!FLAG_polymorphic_inlining || !TryInline(expr)) { |
| 3914 // Check for bailout, as trying to inline might fail due to bailout | 3895 // Check for bailout, as trying to inline might fail due to bailout |
| 3915 // during hydrogen processing. | 3896 // during hydrogen processing. |
| 3916 CHECK_BAILOUT; | 3897 CHECK_BAILOUT; |
| 3917 HCall* call = new HCallConstantFunction(expr->target(), argument_count); | 3898 HCall* call = new HCallConstantFunction(expr->target(), argument_count); |
| 3918 call->set_position(expr->position()); | 3899 call->set_position(expr->position()); |
| 3919 PreProcessCall(call); | 3900 PreProcessCall(call); |
| 3920 PushAndAdd(call); | 3901 PushAndAdd(call); |
| 3921 } | 3902 } |
| 3903 maps.Add(map); |
| 3922 subgraphs.Add(subgraph); | 3904 subgraphs.Add(subgraph); |
| 3923 } else { | 3905 } else { |
| 3924 needs_generic = true; | 3906 needs_generic = true; |
| 3925 } | 3907 } |
| 3926 } | 3908 } |
| 3927 | 3909 |
| 3928 // If we couldn't compute the target for any of the maps just perform an | 3910 // If we couldn't compute the target for any of the maps just perform an |
| 3929 // IC call. | 3911 // IC call. |
| 3930 if (maps.length() == 0) { | 3912 if (maps.length() == 0) { |
| 3931 HContext* context = new HContext; | 3913 HContext* context = new HContext; |
| 3932 AddInstruction(context); | 3914 AddInstruction(context); |
| 3933 HCall* call = new HCallNamed(context, name, argument_count); | 3915 HCall* call = new HCallNamed(context, name, argument_count); |
| 3934 call->set_position(expr->position()); | 3916 call->set_position(expr->position()); |
| 3935 PreProcessCall(call); | 3917 PreProcessCall(call); |
| 3936 ast_context()->ReturnInstruction(call, expr->id()); | 3918 ast_context()->ReturnInstruction(call, expr->id()); |
| 3937 } else { | 3919 } else { |
| 3938 // Build subgraph for generic call through IC. | 3920 // Build subgraph for generic call through IC. |
| 3939 { | 3921 HSubgraph* default_graph = CreateBranchSubgraph(environment()); |
| 3940 HSubgraph* subgraph = CreateBranchSubgraph(environment()); | 3922 { SubgraphScope scope(this, default_graph); |
| 3941 SubgraphScope scope(this, subgraph); | |
| 3942 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { | 3923 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { |
| 3943 subgraph->FinishExit(new HDeoptimize()); | 3924 default_graph->FinishExit(new HDeoptimize()); |
| 3944 } else { | 3925 } else { |
| 3945 HContext* context = new HContext; | 3926 HContext* context = new HContext; |
| 3946 AddInstruction(context); | 3927 AddInstruction(context); |
| 3947 HCall* call = new HCallNamed(context, name, argument_count); | 3928 HCall* call = new HCallNamed(context, name, argument_count); |
| 3948 call->set_position(expr->position()); | 3929 call->set_position(expr->position()); |
| 3949 PreProcessCall(call); | 3930 PreProcessCall(call); |
| 3950 PushAndAdd(call); | 3931 PushAndAdd(call); |
| 3951 } | 3932 } |
| 3952 subgraphs.Add(subgraph); | |
| 3953 } | 3933 } |
| 3954 | 3934 |
| 3955 HBasicBlock* new_exit_block = | 3935 HBasicBlock* new_exit_block = |
| 3956 BuildTypeSwitch(&maps, &subgraphs, receiver, expr->id()); | 3936 BuildTypeSwitch(receiver, &maps, &subgraphs, default_graph, expr->id()); |
| 3957 subgraph()->set_exit_block(new_exit_block); | 3937 subgraph()->set_exit_block(new_exit_block); |
| 3958 // In an effect context, we did not materialized the value in the | 3938 // In an effect context, we did not materialized the value in the |
| 3959 // predecessor environments so there's no need to handle it here. | 3939 // predecessor environments so there's no need to handle it here. |
| 3960 if (new_exit_block != NULL && !ast_context()->IsEffect()) { | 3940 if (new_exit_block != NULL && !ast_context()->IsEffect()) { |
| 3961 ast_context()->ReturnValue(Pop()); | 3941 ast_context()->ReturnValue(Pop()); |
| 3962 } | 3942 } |
| 3963 } | 3943 } |
| 3964 } | 3944 } |
| 3965 | 3945 |
| 3966 | 3946 |
| (...skipping 2025 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5992 } | 5972 } |
| 5993 } | 5973 } |
| 5994 | 5974 |
| 5995 #ifdef DEBUG | 5975 #ifdef DEBUG |
| 5996 if (graph_ != NULL) graph_->Verify(); | 5976 if (graph_ != NULL) graph_->Verify(); |
| 5997 if (allocator_ != NULL) allocator_->Verify(); | 5977 if (allocator_ != NULL) allocator_->Verify(); |
| 5998 #endif | 5978 #endif |
| 5999 } | 5979 } |
| 6000 | 5980 |
| 6001 } } // namespace v8::internal | 5981 } } // namespace v8::internal |
| OLD | NEW |