| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 9be31760d92f11d300d6fe3db47c9bf424a1edda..41f17223ad504c202c70175d56c318fd36076a86 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -106,18 +106,10 @@ void HBasicBlock::AddInstruction(HInstruction* instr) {
|
| if (first_ == NULL) {
|
| HBlockEntry* entry = new HBlockEntry();
|
| entry->InitializeAsFirst(this);
|
| - first_ = entry;
|
| + first_ = last_ = entry;
|
| }
|
| - instr->InsertAfter(GetLastInstruction());
|
| -}
|
| -
|
| -
|
| -HInstruction* HBasicBlock::GetLastInstruction() {
|
| - if (end_ != NULL) return end_->previous();
|
| - if (first_ == NULL) return NULL;
|
| - if (last_ == NULL) last_ = first_;
|
| - while (last_->next() != NULL) last_ = last_->next();
|
| - return last_;
|
| + instr->InsertAfter(last_);
|
| + last_ = instr;
|
| }
|
|
|
|
|
| @@ -178,7 +170,7 @@ void HBasicBlock::SetJoinId(int id) {
|
| for (int i = 0; i < length; i++) {
|
| HBasicBlock* predecessor = predecessors_[i];
|
| ASSERT(predecessor->end()->IsGoto());
|
| - HSimulate* simulate = HSimulate::cast(predecessor->GetLastInstruction());
|
| + HSimulate* simulate = HSimulate::cast(predecessor->end()->previous());
|
| // We only need to verify the ID once.
|
| ASSERT(i != 0 ||
|
| predecessor->last_environment()->closure()->shared()
|
| @@ -3086,53 +3078,47 @@ void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
|
| }
|
|
|
|
|
| -HBasicBlock* HGraphBuilder::BuildTypeSwitch(ZoneMapList* maps,
|
| - ZoneList<HSubgraph*>* subgraphs,
|
| - HValue* receiver,
|
| +HBasicBlock* HGraphBuilder::BuildTypeSwitch(HValue* receiver,
|
| + ZoneMapList* maps,
|
| + ZoneList<HSubgraph*>* body_graphs,
|
| + HSubgraph* default_graph,
|
| int join_id) {
|
| - ASSERT(subgraphs->length() == (maps->length() + 1));
|
| -
|
| - // Build map compare subgraphs for all but the first map.
|
| - ZoneList<HSubgraph*> map_compare_subgraphs(maps->length() - 1);
|
| - for (int i = maps->length() - 1; i > 0; --i) {
|
| - HSubgraph* subgraph = CreateBranchSubgraph(environment());
|
| - SubgraphScope scope(this, subgraph);
|
| - HSubgraph* else_subgraph =
|
| - (i == (maps->length() - 1))
|
| - ? subgraphs->last()
|
| - : map_compare_subgraphs.last();
|
| - HCompareMap* compare = new HCompareMap(receiver,
|
| - maps->at(i),
|
| - subgraphs->at(i)->entry_block(),
|
| - else_subgraph->entry_block());
|
| - current_subgraph_->exit_block()->Finish(compare);
|
| - map_compare_subgraphs.Add(subgraph);
|
| - }
|
| -
|
| - // Generate first map check to end the current block.
|
| + ASSERT(maps->length() == body_graphs->length());
|
| + HBasicBlock* join_block = graph()->CreateBasicBlock();
|
| AddInstruction(new HCheckNonSmi(receiver));
|
| - HSubgraph* else_subgraph =
|
| - (maps->length() == 1) ? subgraphs->at(1) : map_compare_subgraphs.last();
|
| - HCompareMap* compare = new HCompareMap(receiver,
|
| - Handle<Map>(maps->first()),
|
| - subgraphs->first()->entry_block(),
|
| - else_subgraph->entry_block());
|
| - current_subgraph_->exit_block()->Finish(compare);
|
| -
|
| - // Join all the call subgraphs in a new basic block and make
|
| - // this basic block the current basic block.
|
| - HBasicBlock* join_block = graph_->CreateBasicBlock();
|
| - for (int i = 0; i < subgraphs->length(); ++i) {
|
| - HSubgraph* subgraph = subgraphs->at(i);
|
| - if (subgraph->HasExit()) {
|
| +
|
| + for (int i = 0; i < maps->length(); ++i) {
|
| + // Build the branches, connect all the target subgraphs to the join
|
| + // block. Use the default as a target of the last branch.
|
| + HSubgraph* if_true = body_graphs->at(i);
|
| + HSubgraph* if_false = (i == maps->length() - 1)
|
| + ? default_graph
|
| + : CreateBranchSubgraph(environment());
|
| + HCompareMap* compare =
|
| + new HCompareMap(receiver,
|
| + maps->at(i),
|
| + if_true->entry_block(),
|
| + if_false->entry_block());
|
| + subgraph()->exit_block()->Finish(compare);
|
| +
|
| + if (if_true->HasExit()) {
|
| // In an effect context the value of the type switch is not needed.
|
| // There is no need to merge it at the join block only to discard it.
|
| - HBasicBlock* subgraph_exit = subgraph->exit_block();
|
| if (ast_context()->IsEffect()) {
|
| - subgraph_exit->last_environment()->Drop(1);
|
| + if_true->exit_block()->last_environment()->Drop(1);
|
| }
|
| - subgraph_exit->Goto(join_block);
|
| + if_true->exit_block()->Goto(join_block);
|
| + }
|
| +
|
| + subgraph()->set_exit_block(if_false->exit_block());
|
| + }
|
| +
|
| + // Connect the default if necessary.
|
| + if (subgraph()->HasExit()) {
|
| + if (ast_context()->IsEffect()) {
|
| + environment()->Drop(1);
|
| }
|
| + subgraph()->exit_block()->Goto(join_block);
|
| }
|
|
|
| if (join_block->predecessors()->is_empty()) return NULL;
|
| @@ -3238,7 +3224,7 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
|
| Handle<String> name) {
|
| int number_of_types = Min(types->length(), kMaxStorePolymorphism);
|
| ZoneMapList maps(number_of_types);
|
| - ZoneList<HSubgraph*> subgraphs(number_of_types + 1);
|
| + ZoneList<HSubgraph*> subgraphs(number_of_types);
|
| bool needs_generic = (types->length() > kMaxStorePolymorphism);
|
|
|
| // Build subgraphs for each of the specific maps.
|
| @@ -3250,7 +3236,6 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
|
| Handle<Map> map = types->at(i);
|
| LookupResult lookup;
|
| if (ComputeStoredField(map, name, &lookup)) {
|
| - maps.Add(map);
|
| HSubgraph* subgraph = CreateBranchSubgraph(environment());
|
| SubgraphScope scope(this, subgraph);
|
| HInstruction* instr =
|
| @@ -3258,6 +3243,7 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
|
| Push(value);
|
| instr->set_position(expr->position());
|
| AddInstruction(instr);
|
| + maps.Add(map);
|
| subgraphs.Add(subgraph);
|
| } else {
|
| needs_generic = true;
|
| @@ -3275,22 +3261,20 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
|
| ast_context()->ReturnValue(Pop());
|
| } else {
|
| // Build subgraph for generic store through IC.
|
| - {
|
| - HSubgraph* subgraph = CreateBranchSubgraph(environment());
|
| - SubgraphScope scope(this, subgraph);
|
| + HSubgraph* default_graph = CreateBranchSubgraph(environment());
|
| + { SubgraphScope scope(this, default_graph);
|
| if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
|
| - subgraph->FinishExit(new HDeoptimize());
|
| + default_graph->FinishExit(new HDeoptimize());
|
| } else {
|
| HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
|
| Push(value);
|
| instr->set_position(expr->position());
|
| AddInstruction(instr);
|
| }
|
| - subgraphs.Add(subgraph);
|
| }
|
|
|
| HBasicBlock* new_exit_block =
|
| - BuildTypeSwitch(&maps, &subgraphs, object, expr->id());
|
| + BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id());
|
| subgraph()->set_exit_block(new_exit_block);
|
| // In an effect context, we did not materialized the value in the
|
| // predecessor environments so there's no need to handle it here.
|
| @@ -3565,7 +3549,7 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
|
| Handle<String> name) {
|
| int number_of_types = Min(types->length(), kMaxLoadPolymorphism);
|
| ZoneMapList maps(number_of_types);
|
| - ZoneList<HSubgraph*> subgraphs(number_of_types + 1);
|
| + ZoneList<HSubgraph*> subgraphs(number_of_types);
|
| bool needs_generic = (types->length() > kMaxLoadPolymorphism);
|
|
|
| // Build subgraphs for each of the specific maps.
|
| @@ -3578,7 +3562,6 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
|
| LookupResult lookup;
|
| map->LookupInDescriptors(NULL, *name, &lookup);
|
| if (lookup.IsProperty() && lookup.type() == FIELD) {
|
| - maps.Add(map);
|
| HSubgraph* subgraph = CreateBranchSubgraph(environment());
|
| SubgraphScope scope(this, subgraph);
|
| HLoadNamedField* instr =
|
| @@ -3586,6 +3569,7 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
|
| instr->set_position(expr->position());
|
| instr->ClearFlag(HValue::kUseGVN); // Don't do GVN on polymorphic loads.
|
| PushAndAdd(instr);
|
| + maps.Add(map);
|
| subgraphs.Add(subgraph);
|
| } else {
|
| needs_generic = true;
|
| @@ -3600,21 +3584,19 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
|
| ast_context()->ReturnInstruction(instr, expr->id());
|
| } else {
|
| // Build subgraph for generic load through IC.
|
| - {
|
| - HSubgraph* subgraph = CreateBranchSubgraph(environment());
|
| - SubgraphScope scope(this, subgraph);
|
| + HSubgraph* default_graph = CreateBranchSubgraph(environment());
|
| + { SubgraphScope scope(this, default_graph);
|
| if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
|
| - subgraph->FinishExit(new HDeoptimize());
|
| + default_graph->FinishExit(new HDeoptimize());
|
| } else {
|
| HInstruction* instr = BuildLoadNamedGeneric(object, expr);
|
| instr->set_position(expr->position());
|
| PushAndAdd(instr);
|
| }
|
| - subgraphs.Add(subgraph);
|
| }
|
|
|
| HBasicBlock* new_exit_block =
|
| - BuildTypeSwitch(&maps, &subgraphs, object, expr->id());
|
| + BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id());
|
| subgraph()->set_exit_block(new_exit_block);
|
| // In an effect context, we did not materialized the value in the
|
| // predecessor environments so there's no need to handle it here.
|
| @@ -3891,7 +3873,7 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
|
| int argument_count = expr->arguments()->length() + 1; // Plus receiver.
|
| int number_of_types = Min(types->length(), kMaxCallPolymorphism);
|
| ZoneMapList maps(number_of_types);
|
| - ZoneList<HSubgraph*> subgraphs(number_of_types + 1);
|
| + ZoneList<HSubgraph*> subgraphs(number_of_types);
|
| bool needs_generic = (types->length() > kMaxCallPolymorphism);
|
|
|
| // Build subgraphs for each of the specific maps.
|
| @@ -3902,7 +3884,6 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
|
| for (int i = 0; i < number_of_types; ++i) {
|
| Handle<Map> map = types->at(i);
|
| if (expr->ComputeTarget(map, name)) {
|
| - maps.Add(map);
|
| HSubgraph* subgraph = CreateBranchSubgraph(environment());
|
| SubgraphScope scope(this, subgraph);
|
| AddCheckConstantFunction(expr, receiver, map, false);
|
| @@ -3919,6 +3900,7 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
|
| PreProcessCall(call);
|
| PushAndAdd(call);
|
| }
|
| + maps.Add(map);
|
| subgraphs.Add(subgraph);
|
| } else {
|
| needs_generic = true;
|
| @@ -3936,11 +3918,10 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
|
| ast_context()->ReturnInstruction(call, expr->id());
|
| } else {
|
| // Build subgraph for generic call through IC.
|
| - {
|
| - HSubgraph* subgraph = CreateBranchSubgraph(environment());
|
| - SubgraphScope scope(this, subgraph);
|
| + HSubgraph* default_graph = CreateBranchSubgraph(environment());
|
| + { SubgraphScope scope(this, default_graph);
|
| if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
|
| - subgraph->FinishExit(new HDeoptimize());
|
| + default_graph->FinishExit(new HDeoptimize());
|
| } else {
|
| HContext* context = new HContext;
|
| AddInstruction(context);
|
| @@ -3949,11 +3930,10 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
|
| PreProcessCall(call);
|
| PushAndAdd(call);
|
| }
|
| - subgraphs.Add(subgraph);
|
| }
|
|
|
| HBasicBlock* new_exit_block =
|
| - BuildTypeSwitch(&maps, &subgraphs, receiver, expr->id());
|
| + BuildTypeSwitch(receiver, &maps, &subgraphs, default_graph, expr->id());
|
| subgraph()->set_exit_block(new_exit_block);
|
| // In an effect context, we did not materialized the value in the
|
| // predecessor environments so there's no need to handle it here.
|
|
|