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

Side by Side Diff: src/hydrogen.cc

Issue 15993014: hydrogen: split switch optimization code into multiple functions (Closed) Base URL: gh:v8/v8.git@master
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 4892 matching lines...) Expand 10 before | Expand all | Expand 10 after
4903 4903
4904 4904
4905 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) { 4905 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) {
4906 ASSERT(!HasStackOverflow()); 4906 ASSERT(!HasStackOverflow());
4907 ASSERT(current_block() != NULL); 4907 ASSERT(current_block() != NULL);
4908 ASSERT(current_block()->HasPredecessor()); 4908 ASSERT(current_block()->HasPredecessor());
4909 return Bailout("WithStatement"); 4909 return Bailout("WithStatement");
4910 } 4910 }
4911 4911
4912 4912
4913 void HOptimizedGraphBuilder::GlueSwitchClauses(SwitchStatement* stmt,
4914 ZoneList<HBasicBlock*>* bodies) {
4915 // Save the current block to use for the default or to join with the
4916 // exit. This block is NULL if we deoptimized.
4917 HBasicBlock* last_block = current_block();
4918
4919 // Loop over the clauses and the linked list of tests in lockstep,
4920 // translating the clause bodies.
4921 HBasicBlock* fall_through_block = NULL;
4922
4923 ZoneList<CaseClause*>* clauses = stmt->cases();
4924 int clause_count = clauses->length();
4925
4926 BreakAndContinueInfo break_info(stmt);
4927 { BreakAndContinueScope push(&break_info, this);
4928 for (int i = 0; i < clause_count; ++i) {
4929 CaseClause* clause = clauses->at(i);
4930
4931 // Identify the block where normal (non-fall-through) control flow
4932 // goes to.
4933 HBasicBlock* normal_block = bodies->at(i);
4934 if (clause->is_default()) {
4935 ASSERT(normal_block == NULL);
4936 if (last_block != NULL) {
4937 normal_block = last_block;
4938 last_block = NULL; // Cleared to indicate we've handled it.
4939 }
4940 }
4941
4942 // Identify a block to emit the body into.
4943 if (normal_block == NULL) {
4944 if (fall_through_block == NULL) {
4945 // (a) Unreachable.
4946 if (clause->is_default()) {
4947 continue; // Might still be reachable clause bodies.
4948 } else {
4949 break;
4950 }
4951 } else {
4952 // (b) Reachable only as fall through.
4953 set_current_block(fall_through_block);
4954 }
4955 } else if (fall_through_block == NULL) {
4956 // (c) Reachable only normally.
4957 set_current_block(normal_block);
4958 } else {
4959 // (d) Reachable both ways.
4960 HBasicBlock* join = CreateJoin(fall_through_block,
4961 normal_block,
4962 clause->EntryId());
4963 set_current_block(join);
4964 }
4965
4966 CHECK_BAILOUT(VisitStatements(clause->statements()));
4967 fall_through_block = current_block();
4968 }
4969 }
4970
4971 // Create an up-to-3-way join. Use the break block if it exists since
4972 // it's already a join block.
4973 HBasicBlock* break_block = break_info.break_block();
4974 if (break_block == NULL) {
4975 set_current_block(CreateJoin(fall_through_block,
4976 last_block,
4977 stmt->ExitId()));
4978 } else {
4979 if (fall_through_block != NULL) fall_through_block->Goto(break_block);
4980 if (last_block != NULL) last_block->Goto(break_block);
4981 break_block->SetJoinId(stmt->ExitId());
4982 set_current_block(break_block);
4983 }
4984 }
4985
4986
4913 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { 4987 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
4914 ASSERT(!HasStackOverflow()); 4988 ASSERT(!HasStackOverflow());
4915 ASSERT(current_block() != NULL); 4989 ASSERT(current_block() != NULL);
4916 ASSERT(current_block()->HasPredecessor()); 4990 ASSERT(current_block()->HasPredecessor());
4917 4991
4918 // We only optimize switch statements with smi-literal smi comparisons, 4992 // We only optimize switch statements with smi-literal smi comparisons,
4919 // with a bounded number of clauses. 4993 // with a bounded number of clauses.
4920 const int kCaseClauseLimit = 128; 4994 const int kCaseClauseLimit = 128;
4921 ZoneList<CaseClause*>* clauses = stmt->cases(); 4995 ZoneList<CaseClause*>* clauses = stmt->cases();
4922 int clause_count = clauses->length(); 4996 int clause_count = clauses->length();
(...skipping 22 matching lines...) Expand all
4945 first_test_block = graph()->CreateBasicBlock(); 5019 first_test_block = graph()->CreateBasicBlock();
4946 not_string_block = graph()->CreateBasicBlock(); 5020 not_string_block = graph()->CreateBasicBlock();
4947 5021
4948 string_check->SetSuccessorAt(0, first_test_block); 5022 string_check->SetSuccessorAt(0, first_test_block);
4949 string_check->SetSuccessorAt(1, not_string_block); 5023 string_check->SetSuccessorAt(1, not_string_block);
4950 current_block()->Finish(string_check); 5024 current_block()->Finish(string_check);
4951 5025
4952 set_current_block(first_test_block); 5026 set_current_block(first_test_block);
4953 } 5027 }
4954 5028
4955 // 1. Build all the tests, with dangling true branches 5029 // Build all the tests, with dangling true branches
4956 BailoutId default_id = BailoutId::None(); 5030 BailoutId default_id = BailoutId::None();
5031 ZoneList<HBasicBlock*> bodies(clause_count, zone());
4957 for (int i = 0; i < clause_count; ++i) { 5032 for (int i = 0; i < clause_count; ++i) {
4958 CaseClause* clause = clauses->at(i); 5033 CaseClause* clause = clauses->at(i);
4959 if (clause->is_default()) { 5034 if (clause->is_default()) {
4960 default_id = clause->EntryId(); 5035 default_id = clause->EntryId();
5036 bodies.Add(NULL, zone());
4961 continue; 5037 continue;
4962 } 5038 }
4963 5039
4964 // Generate a compare and branch. 5040 // Generate a compare and branch.
4965 CHECK_ALIVE(VisitForValue(clause->label())); 5041 CHECK_ALIVE(VisitForValue(clause->label()));
4966 HValue* label_value = Pop(); 5042 HValue* label_value = Pop();
4967 5043
4968 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); 5044 HBasicBlock* next_test_block = graph()->CreateBasicBlock();
4969 HBasicBlock* body_block = graph()->CreateBasicBlock(); 5045 HBasicBlock* body_block = graph()->CreateBasicBlock();
5046 bodies.Add(body_block, zone());
4970 5047
4971 HControlInstruction* compare; 5048 HControlInstruction* compare;
4972 5049
4973 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { 5050 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) {
4974 if (!clause->IsSmiCompare()) { 5051 if (!clause->IsSmiCompare()) {
4975 // Finish with deoptimize and add uses of enviroment values to 5052 // Finish with deoptimize and add uses of enviroment values to
4976 // account for invisible uses. 5053 // account for invisible uses.
4977 current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll); 5054 current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll);
4978 set_current_block(NULL); 5055 set_current_block(NULL);
4979 break; 5056 break;
(...skipping 12 matching lines...) Expand all
4992 Token::EQ_STRICT); 5069 Token::EQ_STRICT);
4993 } 5070 }
4994 5071
4995 compare->SetSuccessorAt(0, body_block); 5072 compare->SetSuccessorAt(0, body_block);
4996 compare->SetSuccessorAt(1, next_test_block); 5073 compare->SetSuccessorAt(1, next_test_block);
4997 current_block()->Finish(compare); 5074 current_block()->Finish(compare);
4998 5075
4999 set_current_block(next_test_block); 5076 set_current_block(next_test_block);
5000 } 5077 }
5001 5078
5002 // Save the current block to use for the default or to join with the 5079 // Join non-string case with the exit block of switch statement
5003 // exit. This block is NULL if we deoptimized.
5004 HBasicBlock* last_block = current_block(); 5080 HBasicBlock* last_block = current_block();
5005
5006 if (not_string_block != NULL) { 5081 if (not_string_block != NULL) {
5007 BailoutId join_id = !default_id.IsNone() ? default_id : stmt->ExitId(); 5082 BailoutId join_id = !default_id.IsNone() ? default_id : stmt->ExitId();
5008 last_block = CreateJoin(last_block, not_string_block, join_id); 5083 last_block = CreateJoin(last_block, not_string_block, join_id);
5084 set_current_block(last_block);
5009 } 5085 }
5010 5086
5011 // 2. Loop over the clauses and the linked list of tests in lockstep, 5087 // Emit and glue bodies together
5012 // translating the clause bodies. 5088 GlueSwitchClauses(stmt, &bodies);
5013 HBasicBlock* curr_test_block = first_test_block;
5014 HBasicBlock* fall_through_block = NULL;
5015
5016 BreakAndContinueInfo break_info(stmt);
5017 { BreakAndContinueScope push(&break_info, this);
5018 for (int i = 0; i < clause_count; ++i) {
5019 CaseClause* clause = clauses->at(i);
5020
5021 // Identify the block where normal (non-fall-through) control flow
5022 // goes to.
5023 HBasicBlock* normal_block = NULL;
5024 if (clause->is_default()) {
5025 if (last_block != NULL) {
5026 normal_block = last_block;
5027 last_block = NULL; // Cleared to indicate we've handled it.
5028 }
5029 } else if (!curr_test_block->end()->IsDeoptimize()) {
5030 normal_block = curr_test_block->end()->FirstSuccessor();
5031 curr_test_block = curr_test_block->end()->SecondSuccessor();
5032 }
5033
5034 // Identify a block to emit the body into.
5035 if (normal_block == NULL) {
5036 if (fall_through_block == NULL) {
5037 // (a) Unreachable.
5038 if (clause->is_default()) {
5039 continue; // Might still be reachable clause bodies.
5040 } else {
5041 break;
5042 }
5043 } else {
5044 // (b) Reachable only as fall through.
5045 set_current_block(fall_through_block);
5046 }
5047 } else if (fall_through_block == NULL) {
5048 // (c) Reachable only normally.
5049 set_current_block(normal_block);
5050 } else {
5051 // (d) Reachable both ways.
5052 HBasicBlock* join = CreateJoin(fall_through_block,
5053 normal_block,
5054 clause->EntryId());
5055 set_current_block(join);
5056 }
5057
5058 CHECK_BAILOUT(VisitStatements(clause->statements()));
5059 fall_through_block = current_block();
5060 }
5061 }
5062
5063 // Create an up-to-3-way join. Use the break block if it exists since
5064 // it's already a join block.
5065 HBasicBlock* break_block = break_info.break_block();
5066 if (break_block == NULL) {
5067 set_current_block(CreateJoin(fall_through_block,
5068 last_block,
5069 stmt->ExitId()));
5070 } else {
5071 if (fall_through_block != NULL) fall_through_block->Goto(break_block);
5072 if (last_block != NULL) last_block->Goto(break_block);
5073 break_block->SetJoinId(stmt->ExitId());
5074 set_current_block(break_block);
5075 }
5076 } 5089 }
5077 5090
5078 5091
5079 bool HOptimizedGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { 5092 bool HOptimizedGraphBuilder::HasOsrEntryAt(IterationStatement* statement) {
5080 return statement->OsrEntryId() == info()->osr_ast_id(); 5093 return statement->OsrEntryId() == info()->osr_ast_id();
5081 } 5094 }
5082 5095
5083 5096
5084 bool HOptimizedGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { 5097 bool HOptimizedGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) {
5085 if (!HasOsrEntryAt(statement)) return false; 5098 if (!HasOsrEntryAt(statement)) return false;
(...skipping 6459 matching lines...) Expand 10 before | Expand all | Expand 10 after
11545 } 11558 }
11546 } 11559 }
11547 11560
11548 #ifdef DEBUG 11561 #ifdef DEBUG
11549 if (graph_ != NULL) graph_->Verify(false); // No full verify. 11562 if (graph_ != NULL) graph_->Verify(false); // No full verify.
11550 if (allocator_ != NULL) allocator_->Verify(); 11563 if (allocator_ != NULL) allocator_->Verify();
11551 #endif 11564 #endif
11552 } 11565 }
11553 11566
11554 } } // namespace v8::internal 11567 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698