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

Unified Diff: src/hydrogen.cc

Issue 5812005: Deoptimize non-smi switch cases if they are reached. (Closed)
Patch Set: Rebased Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 05a59d26d3dc139ae3ec5aded1c79fb3bda7cfc4..6236f7849d6dc4a62a824ab671c02b9e60f15851 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -2574,6 +2574,8 @@ HCompare* HGraphBuilder::BuildSwitchCompare(HSubgraph* subgraph,
void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
VISIT_FOR_VALUE(stmt->tag());
+ // TODO(3168478): simulate added for tag should be enough.
+ AddSimulate(stmt->EntryId());
HValue* switch_value = Pop();
ZoneList<CaseClause*>* clauses = stmt->cases();
@@ -2581,11 +2583,16 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
if (num_clauses == 0) return;
if (num_clauses > 128) BAILOUT("SwitchStatement: too many clauses");
+ int num_smi_clauses = num_clauses;
for (int i = 0; i < num_clauses; i++) {
CaseClause* clause = clauses->at(i);
if (clause->is_default()) continue;
clause->RecordTypeFeedback(oracle());
- if (!clause->IsSmiCompare()) BAILOUT("SwitchStatement: non-smi compare");
+ if (!clause->IsSmiCompare()) {
+ // We will deoptimize if the first non-smi compare is reached.
+ num_smi_clauses = i;
+ break;
+ }
fschneider 2010/12/15 16:12:13 Does it make sense to check if all clauses have a
if (!clause->label()->IsSmiLiteral()) {
BAILOUT("SwitchStatement: non-literal switch label");
}
@@ -2596,17 +2603,18 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
// Build a series of empty subgraphs for the comparisons.
// The default clause does not have a comparison subgraph.
- ZoneList<HSubgraph*> compare_graphs(num_clauses);
- for (int i = 0; i < num_clauses; i++) {
- HSubgraph* subgraph = !clauses->at(i)->is_default()
- ? CreateEmptySubgraph()
- : NULL;
- compare_graphs.Add(subgraph);
+ ZoneList<HSubgraph*> compare_graphs(num_smi_clauses);
+ for (int i = 0; i < num_smi_clauses; i++) {
+ if (clauses->at(i)->is_default()) {
+ compare_graphs.Add(NULL);
+ } else {
+ compare_graphs.Add(CreateEmptySubgraph());
+ }
}
HSubgraph* prev_graph = current_subgraph_;
HCompare* prev_compare_inst = NULL;
- for (int i = 0; i < num_clauses; i++) {
+ for (int i = 0; i < num_smi_clauses; i++) {
CaseClause* clause = clauses->at(i);
if (clause->is_default()) continue;
@@ -2623,6 +2631,7 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
}
// Build instructions for current subgraph.
+ ASSERT(clause->IsSmiCompare());
prev_compare_inst = BuildSwitchCompare(subgraph, switch_value, clause);
if (HasStackOverflow()) return;
@@ -2642,33 +2651,52 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
prev_compare_inst));
}
+ // If we have a non-smi compare clause, we deoptimize after trying
+ // all the previous compares.
+ if (num_smi_clauses < num_clauses) {
+ last_false_block->Finish(new HDeoptimize);
+ }
+
// Build statement blocks, connect them to their comparison block and
// to the previous statement block, if there is a fall-through.
HSubgraph* previous_subgraph = NULL;
for (int i = 0; i < num_clauses; i++) {
CaseClause* clause = clauses->at(i);
- HSubgraph* subgraph = CreateEmptySubgraph();
-
- if (clause->is_default()) {
- // Default clause: Connect it to the last false block.
- last_false_block->Finish(new HGoto(subgraph->entry_block()));
- } else {
- // Connect with the corresponding comparison.
- HBasicBlock* empty =
- compare_graphs.at(i)->exit_block()->end()->FirstSuccessor();
- empty->Finish(new HGoto(subgraph->entry_block()));
+ // Subgraph for the statements of the clause is only created when
+ // it's reachable either from the corresponding compare or as a
+ // fall-through from previous statements.
+ HSubgraph* subgraph = NULL;
+
+ if (i < num_smi_clauses) {
+ if (clause->is_default()) {
+ if (!last_false_block->IsFinished()) {
+ // Default clause: Connect it to the last false block.
+ subgraph = CreateEmptySubgraph();
+ last_false_block->Finish(new HGoto(subgraph->entry_block()));
+ }
+ } else {
+ ASSERT(clause->IsSmiCompare());
+ // Connect with the corresponding comparison.
+ subgraph = CreateEmptySubgraph();
+ HBasicBlock* empty =
+ compare_graphs.at(i)->exit_block()->end()->FirstSuccessor();
+ empty->Finish(new HGoto(subgraph->entry_block()));
+ }
}
// Check for fall-through from previous statement block.
if (previous_subgraph != NULL && previous_subgraph->HasExit()) {
+ if (subgraph == NULL) subgraph = CreateEmptySubgraph();
previous_subgraph->exit_block()->
Finish(new HGoto(subgraph->entry_block()));
}
- ADD_TO_SUBGRAPH(subgraph, clause->statements());
- HBasicBlock* break_block = subgraph->BundleBreak(stmt);
- if (break_block != NULL) {
- break_block->Finish(new HGoto(single_exit_block));
+ if (subgraph != NULL) {
+ ADD_TO_SUBGRAPH(subgraph, clause->statements());
+ HBasicBlock* break_block = subgraph->BundleBreak(stmt);
+ if (break_block != NULL) {
+ break_block->Finish(new HGoto(single_exit_block));
+ }
}
previous_subgraph = subgraph;
@@ -2676,7 +2704,7 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
// If the last statement block has a fall-through, connect it to the
// single exit block.
- if (previous_subgraph->HasExit()) {
+ if (previous_subgraph != NULL && previous_subgraph->HasExit()) {
previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block));
}
« no previous file with comments | « no previous file | src/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698