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