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

Side by Side Diff: src/hydrogen.cc

Issue 6664001: [Isolates] Merge (7083,7111] from bleeding_edge. (Closed)
Patch Set: Created 9 years, 9 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') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 540 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 } 551 }
552 552
553 553
554 void HBasicBlock::FinishExit(HControlInstruction* instruction) { 554 void HBasicBlock::FinishExit(HControlInstruction* instruction) {
555 Finish(instruction); 555 Finish(instruction);
556 ClearEnvironment(); 556 ClearEnvironment();
557 } 557 }
558 558
559 559
560 HGraph::HGraph(CompilationInfo* info) 560 HGraph::HGraph(CompilationInfo* info)
561 : HSubgraph(this), 561 : next_block_id_(0),
562 next_block_id_(0), 562 entry_block_(NULL),
563 blocks_(8), 563 blocks_(8),
564 values_(16), 564 values_(16),
565 phi_list_(NULL) { 565 phi_list_(NULL) {
566 start_environment_ = new HEnvironment(NULL, info->scope(), info->closure()); 566 start_environment_ = new HEnvironment(NULL, info->scope(), info->closure());
567 start_environment_->set_ast_id(info->function()->id()); 567 start_environment_->set_ast_id(info->function()->id());
568 entry_block_ = CreateBasicBlock();
569 entry_block_->SetInitialEnvironment(start_environment_);
568 } 570 }
569 571
570 572
571 Handle<Code> HGraph::Compile(CompilationInfo* info) { 573 Handle<Code> HGraph::Compile(CompilationInfo* info) {
572 int values = GetMaximumValueID(); 574 int values = GetMaximumValueID();
573 if (values > LAllocator::max_initial_value_ids()) { 575 if (values > LAllocator::max_initial_value_ids()) {
574 if (FLAG_trace_bailout) PrintF("Function is too big\n"); 576 if (FLAG_trace_bailout) PrintF("Function is too big\n");
575 return Handle<Code>::null(); 577 return Handle<Code>::null();
576 } 578 }
577 579
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 634
633 635
634 void HGraph::OrderBlocks() { 636 void HGraph::OrderBlocks() {
635 HPhase phase("Block ordering"); 637 HPhase phase("Block ordering");
636 BitVector visited(blocks_.length()); 638 BitVector visited(blocks_.length());
637 639
638 ZoneList<HBasicBlock*> reverse_result(8); 640 ZoneList<HBasicBlock*> reverse_result(8);
639 HBasicBlock* start = blocks_[0]; 641 HBasicBlock* start = blocks_[0];
640 Postorder(start, &visited, &reverse_result, NULL); 642 Postorder(start, &visited, &reverse_result, NULL);
641 643
642 blocks_.Clear(); 644 blocks_.Rewind(0);
643 int index = 0; 645 int index = 0;
644 for (int i = reverse_result.length() - 1; i >= 0; --i) { 646 for (int i = reverse_result.length() - 1; i >= 0; --i) {
645 HBasicBlock* b = reverse_result[i]; 647 HBasicBlock* b = reverse_result[i];
646 blocks_.Add(b); 648 blocks_.Add(b);
647 b->set_block_id(index++); 649 b->set_block_id(index++);
648 } 650 }
649 } 651 }
650 652
651 653
652 void HGraph::PostorderLoopBlocks(HLoopInformation* loop, 654 void HGraph::PostorderLoopBlocks(HLoopInformation* loop,
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 // because in case of throwing an error we need this value to 751 // because in case of throwing an error we need this value to
750 // construct a stack trace. 752 // construct a stack trace.
751 block->RemovePhi(phi); 753 block->RemovePhi(phi);
752 block->RecordDeletedPhi(phi->merged_index()); 754 block->RecordDeletedPhi(phi->merged_index());
753 } 755 }
754 } 756 }
755 } 757 }
756 758
757 759
758 bool HGraph::CollectPhis() { 760 bool HGraph::CollectPhis() {
759 const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); 761 int block_count = blocks_.length();
760 phi_list_ = new ZoneList<HPhi*>(blocks->length()); 762 phi_list_ = new ZoneList<HPhi*>(block_count);
761 for (int i = 0; i < blocks->length(); ++i) { 763 for (int i = 0; i < block_count; ++i) {
762 for (int j = 0; j < blocks->at(i)->phis()->length(); j++) { 764 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
763 HPhi* phi = blocks->at(i)->phis()->at(j); 765 HPhi* phi = blocks_[i]->phis()->at(j);
764 phi_list_->Add(phi); 766 phi_list_->Add(phi);
765 // We don't support phi uses of arguments for now. 767 // We don't support phi uses of arguments for now.
766 if (phi->CheckFlag(HValue::kIsArguments)) return false; 768 if (phi->CheckFlag(HValue::kIsArguments)) return false;
767 } 769 }
768 } 770 }
769 return true; 771 return true;
770 } 772 }
771 773
772 774
773 void HGraph::InferTypes(ZoneList<HValue*>* worklist) { 775 void HGraph::InferTypes(ZoneList<HValue*>* worklist) {
(...skipping 965 matching lines...) Expand 10 before | Expand all | Expand 10 after
1739 bool a_truncate = a->CheckFlag(HValue::kTruncatingToInt32); 1741 bool a_truncate = a->CheckFlag(HValue::kTruncatingToInt32);
1740 bool b_truncate = b->CheckFlag(HValue::kTruncatingToInt32); 1742 bool b_truncate = b->CheckFlag(HValue::kTruncatingToInt32);
1741 if (a_truncate != b_truncate) { 1743 if (a_truncate != b_truncate) {
1742 return a_truncate ? -1 : 1; 1744 return a_truncate ? -1 : 1;
1743 } 1745 }
1744 // Sort by increasing block ID. 1746 // Sort by increasing block ID.
1745 return a->block()->block_id() - b->block()->block_id(); 1747 return a->block()->block_id() - b->block()->block_id();
1746 } 1748 }
1747 1749
1748 1750
1749 void HGraph::InsertRepresentationChanges(HValue* current) { 1751 void HGraph::InsertRepresentationChangesForValue(
1752 HValue* current,
1753 ZoneList<HValue*>* to_convert,
1754 ZoneList<Representation>* to_convert_reps) {
1750 Representation r = current->representation(); 1755 Representation r = current->representation();
1751 if (r.IsNone()) return; 1756 if (r.IsNone()) return;
1752 if (current->uses()->length() == 0) return; 1757 if (current->uses()->length() == 0) return;
1753 1758
1754 // Collect the representation changes in a sorted list. This allows 1759 // Collect the representation changes in a sorted list. This allows
1755 // us to avoid duplicate changes without searching the list. 1760 // us to avoid duplicate changes without searching the list.
1756 ZoneList<HValue*> to_convert(2); 1761 ASSERT(to_convert->is_empty());
1757 ZoneList<Representation> to_convert_reps(2); 1762 ASSERT(to_convert_reps->is_empty());
1758 for (int i = 0; i < current->uses()->length(); ++i) { 1763 for (int i = 0; i < current->uses()->length(); ++i) {
1759 HValue* use = current->uses()->at(i); 1764 HValue* use = current->uses()->at(i);
1760 // The occurrences index means the index within the operand array of "use" 1765 // The occurrences index means the index within the operand array of "use"
1761 // at which "current" is used. While iterating through the use array we 1766 // at which "current" is used. While iterating through the use array we
1762 // also have to iterate over the different occurrence indices. 1767 // also have to iterate over the different occurrence indices.
1763 int occurrence_index = 0; 1768 int occurrence_index = 0;
1764 if (use->UsesMultipleTimes(current)) { 1769 if (use->UsesMultipleTimes(current)) {
1765 occurrence_index = current->uses()->CountOccurrences(use, 0, i - 1); 1770 occurrence_index = current->uses()->CountOccurrences(use, 0, i - 1);
1766 if (FLAG_trace_representation) { 1771 if (FLAG_trace_representation) {
1767 PrintF("Instruction %d is used multiple times at %d; occurrence=%d\n", 1772 PrintF("Instruction %d is used multiple times at %d; occurrence=%d\n",
1768 current->id(), 1773 current->id(),
1769 use->id(), 1774 use->id(),
1770 occurrence_index); 1775 occurrence_index);
1771 } 1776 }
1772 } 1777 }
1773 int operand_index = use->LookupOperandIndex(occurrence_index, current); 1778 int operand_index = use->LookupOperandIndex(occurrence_index, current);
1774 Representation req = use->RequiredInputRepresentation(operand_index); 1779 Representation req = use->RequiredInputRepresentation(operand_index);
1775 if (req.IsNone() || req.Equals(r)) continue; 1780 if (req.IsNone() || req.Equals(r)) continue;
1776 int index = 0; 1781 int index = 0;
1777 while (to_convert.length() > index && 1782 while (index < to_convert->length() &&
1778 CompareConversionUses(to_convert[index], 1783 CompareConversionUses(to_convert->at(index),
1779 use, 1784 use,
1780 to_convert_reps[index], 1785 to_convert_reps->at(index),
1781 req) < 0) { 1786 req) < 0) {
1782 ++index; 1787 ++index;
1783 } 1788 }
1784 if (FLAG_trace_representation) { 1789 if (FLAG_trace_representation) {
1785 PrintF("Inserting a representation change to %s of %d for use at %d\n", 1790 PrintF("Inserting a representation change to %s of %d for use at %d\n",
1786 req.Mnemonic(), 1791 req.Mnemonic(),
1787 current->id(), 1792 current->id(),
1788 use->id()); 1793 use->id());
1789 } 1794 }
1790 to_convert.InsertAt(index, use); 1795 to_convert->InsertAt(index, use);
1791 to_convert_reps.InsertAt(index, req); 1796 to_convert_reps->InsertAt(index, req);
1792 } 1797 }
1793 1798
1794 for (int i = 0; i < to_convert.length(); ++i) { 1799 for (int i = 0; i < to_convert->length(); ++i) {
1795 HValue* use = to_convert[i]; 1800 HValue* use = to_convert->at(i);
1796 Representation r_to = to_convert_reps[i]; 1801 Representation r_to = to_convert_reps->at(i);
1797 InsertRepresentationChangeForUse(current, use, r_to); 1802 InsertRepresentationChangeForUse(current, use, r_to);
1798 } 1803 }
1799 1804
1800 if (current->uses()->is_empty()) { 1805 if (current->uses()->is_empty()) {
1801 ASSERT(current->IsConstant()); 1806 ASSERT(current->IsConstant());
1802 current->Delete(); 1807 current->Delete();
1803 } 1808 }
1809 to_convert->Rewind(0);
1810 to_convert_reps->Rewind(0);
1804 } 1811 }
1805 1812
1806 1813
1807 void HGraph::InsertRepresentationChanges() { 1814 void HGraph::InsertRepresentationChanges() {
1808 HPhase phase("Insert representation changes", this); 1815 HPhase phase("Insert representation changes", this);
1809 1816
1810 1817
1811 // Compute truncation flag for phis: Initially assume that all 1818 // Compute truncation flag for phis: Initially assume that all
1812 // int32-phis allow truncation and iteratively remove the ones that 1819 // int32-phis allow truncation and iteratively remove the ones that
1813 // are used in an operation that does not allow a truncating 1820 // are used in an operation that does not allow a truncating
(...skipping 15 matching lines...) Expand all
1829 HValue* use = phi->uses()->at(j); 1836 HValue* use = phi->uses()->at(j);
1830 if (!use->CheckFlag(HValue::kTruncatingToInt32)) { 1837 if (!use->CheckFlag(HValue::kTruncatingToInt32)) {
1831 phi->ClearFlag(HValue::kTruncatingToInt32); 1838 phi->ClearFlag(HValue::kTruncatingToInt32);
1832 change = true; 1839 change = true;
1833 break; 1840 break;
1834 } 1841 }
1835 } 1842 }
1836 } 1843 }
1837 } 1844 }
1838 1845
1846 ZoneList<HValue*> value_list(4);
1847 ZoneList<Representation> rep_list(4);
1839 for (int i = 0; i < blocks_.length(); ++i) { 1848 for (int i = 0; i < blocks_.length(); ++i) {
1840 // Process phi instructions first. 1849 // Process phi instructions first.
1841 for (int j = 0; j < blocks_[i]->phis()->length(); j++) { 1850 for (int j = 0; j < blocks_[i]->phis()->length(); j++) {
1842 HPhi* phi = blocks_[i]->phis()->at(j); 1851 HPhi* phi = blocks_[i]->phis()->at(j);
1843 InsertRepresentationChanges(phi); 1852 InsertRepresentationChangesForValue(phi, &value_list, &rep_list);
1844 } 1853 }
1845 1854
1846 // Process normal instructions. 1855 // Process normal instructions.
1847 HInstruction* current = blocks_[i]->first(); 1856 HInstruction* current = blocks_[i]->first();
1848 while (current != NULL) { 1857 while (current != NULL) {
1849 InsertRepresentationChanges(current); 1858 InsertRepresentationChangesForValue(current, &value_list, &rep_list);
1850 current = current->next(); 1859 current = current->next();
1851 } 1860 }
1852 } 1861 }
1853 } 1862 }
1854 1863
1855 1864
1856 void HGraph::ComputeMinusZeroChecks() { 1865 void HGraph::ComputeMinusZeroChecks() {
1857 BitVector visited(GetMaximumValueID()); 1866 BitVector visited(GetMaximumValueID());
1858 for (int i = 0; i < blocks_.length(); ++i) { 1867 for (int i = 0; i < blocks_.length(); ++i) {
1859 for (HInstruction* current = blocks_[i]->first(); 1868 for (HInstruction* current = blocks_[i]->first();
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
2037 } while (false) 2046 } while (false)
2038 2047
2039 2048
2040 #define VISIT_FOR_CONTROL(expr, true_block, false_block) \ 2049 #define VISIT_FOR_CONTROL(expr, true_block, false_block) \
2041 do { \ 2050 do { \
2042 VisitForControl(expr, true_block, false_block); \ 2051 VisitForControl(expr, true_block, false_block); \
2043 if (HasStackOverflow()) return; \ 2052 if (HasStackOverflow()) return; \
2044 } while (false) 2053 } while (false)
2045 2054
2046 2055
2047 // 'thing' could be an expression, statement, or list of statements.
2048 #define ADD_TO_SUBGRAPH(graph, thing) \
2049 do { \
2050 AddToSubgraph(graph, thing); \
2051 if (HasStackOverflow()) return; \
2052 } while (false)
2053
2054
2055 class HGraphBuilder::SubgraphScope BASE_EMBEDDED {
2056 public:
2057 SubgraphScope(HGraphBuilder* builder, HSubgraph* new_subgraph)
2058 : builder_(builder) {
2059 old_subgraph_ = builder_->current_subgraph_;
2060 subgraph_ = new_subgraph;
2061 builder_->current_subgraph_ = subgraph_;
2062 }
2063
2064 ~SubgraphScope() {
2065 builder_->current_subgraph_ = old_subgraph_;
2066 }
2067
2068 HSubgraph* subgraph() const { return subgraph_; }
2069
2070 private:
2071 HGraphBuilder* builder_;
2072 HSubgraph* old_subgraph_;
2073 HSubgraph* subgraph_;
2074 };
2075
2076
2077 void HGraphBuilder::Bailout(const char* reason) { 2056 void HGraphBuilder::Bailout(const char* reason) {
2078 if (FLAG_trace_bailout) { 2057 if (FLAG_trace_bailout) {
2079 SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString()); 2058 SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
2080 PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *name, reason); 2059 PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *name, reason);
2081 } 2060 }
2082 SetStackOverflow(); 2061 SetStackOverflow();
2083 } 2062 }
2084 2063
2085 2064
2086 void HGraphBuilder::VisitForEffect(Expression* expr) { 2065 void HGraphBuilder::VisitForEffect(Expression* expr) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2118 2097
2119 2098
2120 void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) { 2099 void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) {
2121 for (int i = 0; i < exprs->length(); ++i) { 2100 for (int i = 0; i < exprs->length(); ++i) {
2122 VISIT_FOR_VALUE(exprs->at(i)); 2101 VISIT_FOR_VALUE(exprs->at(i));
2123 } 2102 }
2124 } 2103 }
2125 2104
2126 2105
2127 HGraph* HGraphBuilder::CreateGraph() { 2106 HGraph* HGraphBuilder::CreateGraph() {
2128 ASSERT(subgraph() == NULL);
2129 graph_ = new HGraph(info()); 2107 graph_ = new HGraph(info());
2130
2131 { 2108 {
2132 HPhase phase("Block building"); 2109 HPhase phase("Block building");
2133 graph()->Initialize(CreateBasicBlock(graph()->start_environment())); 2110 current_block_ = graph()->entry_block();
2134 current_subgraph_ = graph();
2135 2111
2136 Scope* scope = info()->scope(); 2112 Scope* scope = info()->scope();
2137 if (scope->HasIllegalRedeclaration()) { 2113 if (scope->HasIllegalRedeclaration()) {
2138 Bailout("function with illegal redeclaration"); 2114 Bailout("function with illegal redeclaration");
2139 return NULL; 2115 return NULL;
2140 } 2116 }
2141 SetupScope(scope); 2117 SetupScope(scope);
2142 VisitDeclarations(scope->declarations()); 2118 VisitDeclarations(scope->declarations());
2143 AddInstruction(new HStackCheck()); 2119 AddInstruction(new HStackCheck());
2144 2120
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2201 if (FLAG_use_gvn) { 2177 if (FLAG_use_gvn) {
2202 HPhase phase("Global value numbering", graph()); 2178 HPhase phase("Global value numbering", graph());
2203 HGlobalValueNumberer gvn(graph(), info()); 2179 HGlobalValueNumberer gvn(graph(), info());
2204 gvn.Analyze(); 2180 gvn.Analyze();
2205 } 2181 }
2206 2182
2207 return graph(); 2183 return graph();
2208 } 2184 }
2209 2185
2210 2186
2211 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, Statement* stmt) {
2212 SubgraphScope scope(this, graph);
2213 Visit(stmt);
2214 }
2215
2216
2217 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, Expression* expr) {
2218 SubgraphScope scope(this, graph);
2219 VisitForValue(expr);
2220 }
2221
2222
2223 void HGraphBuilder::AddToSubgraph(HSubgraph* graph,
2224 ZoneList<Statement*>* stmts) {
2225 SubgraphScope scope(this, graph);
2226 VisitStatements(stmts);
2227 }
2228
2229
2230 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { 2187 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
2231 ASSERT(current_block() != NULL); 2188 ASSERT(current_block() != NULL);
2232 current_block()->AddInstruction(instr); 2189 current_block()->AddInstruction(instr);
2233 return instr; 2190 return instr;
2234 } 2191 }
2235 2192
2236 2193
2237 void HGraphBuilder::AddSimulate(int id) { 2194 void HGraphBuilder::AddSimulate(int id) {
2238 ASSERT(current_block() != NULL); 2195 ASSERT(current_block() != NULL);
2239 current_block()->AddSimulate(id); 2196 current_block()->AddSimulate(id);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2316 } 2273 }
2317 2274
2318 2275
2319 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { 2276 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
2320 HBasicBlock* b = graph()->CreateBasicBlock(); 2277 HBasicBlock* b = graph()->CreateBasicBlock();
2321 b->SetInitialEnvironment(env); 2278 b->SetInitialEnvironment(env);
2322 return b; 2279 return b;
2323 } 2280 }
2324 2281
2325 2282
2326 HSubgraph* HGraphBuilder::CreateEmptySubgraph() {
2327 HSubgraph* subgraph = new HSubgraph(graph());
2328 subgraph->Initialize(graph()->CreateBasicBlock());
2329 return subgraph;
2330 }
2331
2332
2333 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { 2283 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
2334 HBasicBlock* header = graph()->CreateBasicBlock(); 2284 HBasicBlock* header = graph()->CreateBasicBlock();
2335 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); 2285 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
2336 header->SetInitialEnvironment(entry_env); 2286 header->SetInitialEnvironment(entry_env);
2337 header->AttachLoopInformation(); 2287 header->AttachLoopInformation();
2338 return header; 2288 return header;
2339 } 2289 }
2340 2290
2341 2291
2342 void HGraphBuilder::VisitBlock(Block* stmt) { 2292 void HGraphBuilder::VisitBlock(Block* stmt) {
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
2470 void HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { 2420 void HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
2471 BAILOUT("WithEnterStatement"); 2421 BAILOUT("WithEnterStatement");
2472 } 2422 }
2473 2423
2474 2424
2475 void HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) { 2425 void HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
2476 BAILOUT("WithExitStatement"); 2426 BAILOUT("WithExitStatement");
2477 } 2427 }
2478 2428
2479 2429
2480 HCompare* HGraphBuilder::BuildSwitchCompare(HSubgraph* subgraph,
2481 HValue* switch_value,
2482 CaseClause* clause) {
2483 AddToSubgraph(subgraph, clause->label());
2484 if (HasStackOverflow()) return NULL;
2485 HValue* clause_value = subgraph->exit_block()->last_environment()->Pop();
2486 HCompare* compare = new HCompare(switch_value,
2487 clause_value,
2488 Token::EQ_STRICT);
2489 compare->SetInputRepresentation(Representation::Integer32());
2490 subgraph->exit_block()->AddInstruction(compare);
2491 return compare;
2492 }
2493
2494
2495 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { 2430 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
2431 // We only optimize switch statements with smi-literal smi comparisons,
2432 // with a bounded number of clauses.
2433 const int kCaseClauseLimit = 128;
2434 ZoneList<CaseClause*>* clauses = stmt->cases();
2435 int clause_count = clauses->length();
2436 if (clause_count > kCaseClauseLimit) {
2437 BAILOUT("SwitchStatement: too many clauses");
2438 }
2439
2496 VISIT_FOR_VALUE(stmt->tag()); 2440 VISIT_FOR_VALUE(stmt->tag());
2497 // TODO(3168478): simulate added for tag should be enough. 2441 HValue* tag_value = Pop();
2498 AddSimulate(stmt->EntryId()); 2442 HBasicBlock* first_test_block = current_block();
2499 HValue* switch_value = Pop();
2500 2443
2501 ZoneList<CaseClause*>* clauses = stmt->cases(); 2444 // 1. Build all the tests, with dangling true branches. Unconditionally
2502 int num_clauses = clauses->length(); 2445 // deoptimize if we encounter a non-smi comparison.
2503 if (num_clauses == 0) return; 2446 for (int i = 0; i < clause_count; ++i) {
2504 if (num_clauses > 128) BAILOUT("SwitchStatement: too many clauses");
2505
2506 int num_smi_clauses = num_clauses;
2507 for (int i = 0; i < num_clauses; i++) {
2508 CaseClause* clause = clauses->at(i); 2447 CaseClause* clause = clauses->at(i);
2509 if (clause->is_default()) continue; 2448 if (clause->is_default()) continue;
2510 clause->RecordTypeFeedback(oracle());
2511 if (!clause->IsSmiCompare()) {
2512 if (i == 0) BAILOUT("SwitchStatement: no smi compares");
2513 // We will deoptimize if the first non-smi compare is reached.
2514 num_smi_clauses = i;
2515 break;
2516 }
2517 if (!clause->label()->IsSmiLiteral()) { 2449 if (!clause->label()->IsSmiLiteral()) {
2518 BAILOUT("SwitchStatement: non-literal switch label"); 2450 BAILOUT("SwitchStatement: non-literal switch label");
2519 } 2451 }
2452
2453 // Unconditionally deoptimize on the first non-smi compare.
2454 clause->RecordTypeFeedback(oracle());
2455 if (!clause->IsSmiCompare()) {
2456 if (current_block() == first_test_block) {
2457 // If the first test is the one that deopts and if the tag value is
2458 // a phi, we need to have some use of that phi to prevent phi
2459 // elimination from removing it. This HSimulate is such a use.
2460 Push(tag_value);
2461 AddSimulate(stmt->EntryId());
2462 Drop(1);
2463 }
2464 current_block()->Finish(new HDeoptimize());
2465 set_current_block(NULL);
2466 break;
2467 }
2468
2469 // Otherwise generate a compare and branch.
2470 VISIT_FOR_VALUE(clause->label());
2471 HValue* label_value = Pop();
2472 HCompare* compare = new HCompare(tag_value, label_value, Token::EQ_STRICT);
2473 compare->SetInputRepresentation(Representation::Integer32());
2474 ASSERT(!compare->HasSideEffects());
2475 AddInstruction(compare);
2476 HBasicBlock* body_block = graph()->CreateBasicBlock();
2477 HBasicBlock* next_test_block = graph()->CreateBasicBlock();
2478 HTest* branch = new HTest(compare, body_block, next_test_block);
2479 current_block()->Finish(branch);
2480 set_current_block(next_test_block);
2520 } 2481 }
2521 2482
2522 // The single exit block of the whole switch statement. 2483 // Save the current block to use for the default or to join with the
2523 HBasicBlock* single_exit_block = graph_->CreateBasicBlock(); 2484 // exit. This block is NULL if we deoptimized.
2485 HBasicBlock* last_block = current_block();
2524 2486
2525 // Build a series of empty subgraphs for the comparisons. 2487 // 2. Loop over the clauses and the linked list of tests in lockstep,
2526 // The default clause does not have a comparison subgraph. 2488 // translating the clause bodies.
2527 ZoneList<HSubgraph*> compare_graphs(num_smi_clauses); 2489 HBasicBlock* curr_test_block = first_test_block;
2528 for (int i = 0; i < num_smi_clauses; i++) { 2490 HBasicBlock* fall_through_block = NULL;
2529 if (clauses->at(i)->is_default()) { 2491 BreakAndContinueInfo break_info(stmt);
2530 compare_graphs.Add(NULL); 2492 { BreakAndContinueScope push(&break_info, this);
2531 } else { 2493 for (int i = 0; i < clause_count; ++i) {
2532 compare_graphs.Add(CreateEmptySubgraph()); 2494 CaseClause* clause = clauses->at(i);
2495
2496 // Identify the block where normal (non-fall-through) control flow
2497 // goes to.
2498 HBasicBlock* normal_block = NULL;
2499 if (clause->is_default() && last_block != NULL) {
2500 normal_block = last_block;
2501 last_block = NULL; // Cleared to indicate we've handled it.
2502 } else if (!curr_test_block->end()->IsDeoptimize()) {
2503 normal_block = curr_test_block->end()->FirstSuccessor();
2504 curr_test_block = curr_test_block->end()->SecondSuccessor();
2505 }
2506
2507 // Identify a block to emit the body into.
2508 if (normal_block == NULL) {
2509 if (fall_through_block == NULL) {
2510 // (a) Unreachable.
2511 if (clause->is_default()) {
2512 continue; // Might still be reachable clause bodies.
2513 } else {
2514 break;
2515 }
2516 } else {
2517 // (b) Reachable only as fall through.
2518 set_current_block(fall_through_block);
2519 }
2520 } else if (fall_through_block == NULL) {
2521 // (c) Reachable only normally.
2522 set_current_block(normal_block);
2523 } else {
2524 // (d) Reachable both ways.
2525 HBasicBlock* join = CreateJoin(fall_through_block,
2526 normal_block,
2527 clause->EntryId());
2528 set_current_block(join);
2529 }
2530
2531 VisitStatements(clause->statements());
2532 CHECK_BAILOUT;
2533 fall_through_block = current_block();
2533 } 2534 }
2534 } 2535 }
2535 2536
2536 HSubgraph* prev_graph = current_subgraph_; 2537 // Create an up-to-3-way join. Use the break block if it exists since
2537 HCompare* prev_compare_inst = NULL; 2538 // it's already a join block.
2538 for (int i = 0; i < num_smi_clauses; i++) { 2539 HBasicBlock* break_block = break_info.break_block();
2539 CaseClause* clause = clauses->at(i); 2540 if (break_block == NULL) {
2540 if (clause->is_default()) continue; 2541 set_current_block(CreateJoin(fall_through_block,
2541 2542 last_block,
2542 // Finish the previous graph by connecting it to the current. 2543 stmt->ExitId()));
2543 HSubgraph* subgraph = compare_graphs.at(i);
2544 if (prev_compare_inst == NULL) {
2545 ASSERT(prev_graph == current_subgraph_);
2546 prev_graph->exit_block()->Finish(new HGoto(subgraph->entry_block()));
2547 } else {
2548 HBasicBlock* empty = graph()->CreateBasicBlock();
2549 prev_graph->exit_block()->Finish(new HTest(prev_compare_inst,
2550 empty,
2551 subgraph->entry_block()));
2552 }
2553
2554 // Build instructions for current subgraph.
2555 ASSERT(clause->IsSmiCompare());
2556 prev_compare_inst = BuildSwitchCompare(subgraph, switch_value, clause);
2557 if (HasStackOverflow()) return;
2558
2559 prev_graph = subgraph;
2560 }
2561
2562 // Finish last comparison if there was at least one comparison.
2563 // last_false_block is the (empty) false-block of the last comparison. If
2564 // there are no comparisons at all (a single default clause), it is just
2565 // the last block of the current subgraph.
2566 HBasicBlock* last_false_block = current_block();
2567 if (prev_graph != current_subgraph_) {
2568 last_false_block = graph()->CreateBasicBlock();
2569 HBasicBlock* empty = graph()->CreateBasicBlock();
2570 prev_graph->exit_block()->Finish(new HTest(prev_compare_inst,
2571 empty,
2572 last_false_block));
2573 }
2574
2575 // If we have a non-smi compare clause, we deoptimize after trying
2576 // all the previous compares.
2577 if (num_smi_clauses < num_clauses) {
2578 last_false_block->Finish(new HDeoptimize);
2579 }
2580
2581 // Build statement blocks, connect them to their comparison block and
2582 // to the previous statement block, if there is a fall-through.
2583 HSubgraph* previous_subgraph = NULL;
2584 for (int i = 0; i < num_clauses; i++) {
2585 CaseClause* clause = clauses->at(i);
2586 // Subgraph for the statements of the clause is only created when
2587 // it's reachable either from the corresponding compare or as a
2588 // fall-through from previous statements.
2589 HSubgraph* subgraph = NULL;
2590
2591 if (i < num_smi_clauses) {
2592 if (clause->is_default()) {
2593 if (!last_false_block->IsFinished()) {
2594 // Default clause: Connect it to the last false block.
2595 subgraph = CreateEmptySubgraph();
2596 last_false_block->Finish(new HGoto(subgraph->entry_block()));
2597 }
2598 } else {
2599 ASSERT(clause->IsSmiCompare());
2600 // Connect with the corresponding comparison.
2601 subgraph = CreateEmptySubgraph();
2602 HBasicBlock* empty =
2603 compare_graphs.at(i)->exit_block()->end()->FirstSuccessor();
2604 empty->Finish(new HGoto(subgraph->entry_block()));
2605 }
2606 }
2607
2608 // Check for fall-through from previous statement block.
2609 if (previous_subgraph != NULL && previous_subgraph->exit_block() != NULL) {
2610 if (subgraph == NULL) subgraph = CreateEmptySubgraph();
2611 previous_subgraph->exit_block()->
2612 Finish(new HGoto(subgraph->entry_block()));
2613 }
2614
2615 if (subgraph != NULL) {
2616 BreakAndContinueInfo break_info(stmt);
2617 { BreakAndContinueScope push(&break_info, this);
2618 ADD_TO_SUBGRAPH(subgraph, clause->statements());
2619 }
2620 if (break_info.break_block() != NULL) {
2621 break_info.break_block()->SetJoinId(stmt->ExitId());
2622 break_info.break_block()->Finish(new HGoto(single_exit_block));
2623 }
2624 }
2625
2626 previous_subgraph = subgraph;
2627 }
2628
2629 // If the last statement block has a fall-through, connect it to the
2630 // single exit block.
2631 if (previous_subgraph != NULL && previous_subgraph->exit_block() != NULL) {
2632 previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block));
2633 }
2634
2635 // If there is no default clause finish the last comparison's false target.
2636 if (!last_false_block->IsFinished()) {
2637 last_false_block->Finish(new HGoto(single_exit_block));
2638 }
2639
2640 if (single_exit_block->HasPredecessor()) {
2641 set_current_block(single_exit_block);
2642 } else { 2544 } else {
2643 set_current_block(NULL); 2545 if (fall_through_block != NULL) fall_through_block->Goto(break_block);
2546 if (last_block != NULL) last_block->Goto(break_block);
2547 break_block->SetJoinId(stmt->ExitId());
2548 set_current_block(break_block);
2644 } 2549 }
2645 } 2550 }
2646 2551
2552
2647 bool HGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { 2553 bool HGraphBuilder::HasOsrEntryAt(IterationStatement* statement) {
2648 return statement->OsrEntryId() == info()->osr_ast_id(); 2554 return statement->OsrEntryId() == info()->osr_ast_id();
2649 } 2555 }
2650 2556
2651 2557
2652 void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { 2558 void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) {
2653 if (!HasOsrEntryAt(statement)) return; 2559 if (!HasOsrEntryAt(statement)) return;
2654 2560
2655 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); 2561 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock();
2656 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); 2562 HBasicBlock* osr_entry = graph()->CreateBasicBlock();
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after
3245 } else { 3151 } else {
3246 // Keyed store. 3152 // Keyed store.
3247 VISIT_FOR_VALUE(prop->key()); 3153 VISIT_FOR_VALUE(prop->key());
3248 VISIT_FOR_VALUE(expr->value()); 3154 VISIT_FOR_VALUE(expr->value());
3249 value = Pop(); 3155 value = Pop();
3250 HValue* key = Pop(); 3156 HValue* key = Pop();
3251 HValue* object = Pop(); 3157 HValue* object = Pop();
3252 3158
3253 if (expr->IsMonomorphic()) { 3159 if (expr->IsMonomorphic()) {
3254 Handle<Map> receiver_type(expr->GetMonomorphicReceiverType()); 3160 Handle<Map> receiver_type(expr->GetMonomorphicReceiverType());
3255 // An object has either fast elements or pixel array elements, but never 3161 // An object has either fast elements or external array elements, but
3256 // both. Pixel array maps that are assigned to pixel array elements are 3162 // never both. Pixel array maps that are assigned to pixel array elements
3257 // always created with the fast elements flag cleared. 3163 // are always created with the fast elements flag cleared.
3258 if (receiver_type->has_pixel_array_elements()) { 3164 if (receiver_type->has_external_array_elements()) {
3259 instr = BuildStoreKeyedPixelArrayElement(object, key, value, expr); 3165 if (expr->GetExternalArrayType() == kExternalPixelArray) {
3166 instr = BuildStoreKeyedPixelArrayElement(object, key, value, expr);
3167 }
3260 } else if (receiver_type->has_fast_elements()) { 3168 } else if (receiver_type->has_fast_elements()) {
3261 instr = BuildStoreKeyedFastElement(object, key, value, expr); 3169 instr = BuildStoreKeyedFastElement(object, key, value, expr);
3262 } 3170 }
3263 } 3171 }
3264 if (instr == NULL) { 3172 if (instr == NULL) {
3265 instr = BuildStoreKeyedGeneric(object, key, value); 3173 instr = BuildStoreKeyedGeneric(object, key, value);
3266 } 3174 }
3267 } 3175 }
3268 3176
3269 Push(value); 3177 Push(value);
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after
3632 } 3540 }
3633 3541
3634 3542
3635 HInstruction* HGraphBuilder::BuildLoadKeyedPixelArrayElement(HValue* object, 3543 HInstruction* HGraphBuilder::BuildLoadKeyedPixelArrayElement(HValue* object,
3636 HValue* key, 3544 HValue* key,
3637 Property* expr) { 3545 Property* expr) {
3638 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); 3546 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic());
3639 AddInstruction(new HCheckNonSmi(object)); 3547 AddInstruction(new HCheckNonSmi(object));
3640 Handle<Map> map = expr->GetMonomorphicReceiverType(); 3548 Handle<Map> map = expr->GetMonomorphicReceiverType();
3641 ASSERT(!map->has_fast_elements()); 3549 ASSERT(!map->has_fast_elements());
3642 ASSERT(map->has_pixel_array_elements()); 3550 ASSERT(map->has_external_array_elements());
3643 AddInstruction(new HCheckMap(object, map)); 3551 AddInstruction(new HCheckMap(object, map));
3644 HLoadElements* elements = new HLoadElements(object); 3552 HLoadElements* elements = new HLoadElements(object);
3645 AddInstruction(elements); 3553 AddInstruction(elements);
3646 HInstruction* length = new HPixelArrayLength(elements); 3554 HInstruction* length = new HExternalArrayLength(elements);
3647 AddInstruction(length); 3555 AddInstruction(length);
3648 AddInstruction(new HBoundsCheck(key, length)); 3556 AddInstruction(new HBoundsCheck(key, length));
3649 HLoadPixelArrayExternalPointer* external_elements = 3557 HLoadExternalArrayPointer* external_elements =
3650 new HLoadPixelArrayExternalPointer(elements); 3558 new HLoadExternalArrayPointer(elements);
3651 AddInstruction(external_elements); 3559 AddInstruction(external_elements);
3652 HLoadPixelArrayElement* pixel_array_value = 3560 HLoadPixelArrayElement* pixel_array_value =
3653 new HLoadPixelArrayElement(external_elements, key); 3561 new HLoadPixelArrayElement(external_elements, key);
3654 return pixel_array_value; 3562 return pixel_array_value;
3655 } 3563 }
3656 3564
3657 3565
3658 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object, 3566 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object,
3659 HValue* key, 3567 HValue* key,
3660 HValue* value) { 3568 HValue* value) {
(...skipping 28 matching lines...) Expand all
3689 3597
3690 HInstruction* HGraphBuilder::BuildStoreKeyedPixelArrayElement( 3598 HInstruction* HGraphBuilder::BuildStoreKeyedPixelArrayElement(
3691 HValue* object, 3599 HValue* object,
3692 HValue* key, 3600 HValue* key,
3693 HValue* val, 3601 HValue* val,
3694 Expression* expr) { 3602 Expression* expr) {
3695 ASSERT(expr->IsMonomorphic()); 3603 ASSERT(expr->IsMonomorphic());
3696 AddInstruction(new HCheckNonSmi(object)); 3604 AddInstruction(new HCheckNonSmi(object));
3697 Handle<Map> map = expr->GetMonomorphicReceiverType(); 3605 Handle<Map> map = expr->GetMonomorphicReceiverType();
3698 ASSERT(!map->has_fast_elements()); 3606 ASSERT(!map->has_fast_elements());
3699 ASSERT(map->has_pixel_array_elements()); 3607 ASSERT(map->has_external_array_elements());
3700 AddInstruction(new HCheckMap(object, map)); 3608 AddInstruction(new HCheckMap(object, map));
3701 HLoadElements* elements = new HLoadElements(object); 3609 HLoadElements* elements = new HLoadElements(object);
3702 AddInstruction(elements); 3610 AddInstruction(elements);
3703 HInstruction* length = AddInstruction(new HPixelArrayLength(elements)); 3611 HInstruction* length = AddInstruction(new HExternalArrayLength(elements));
3704 AddInstruction(new HBoundsCheck(key, length)); 3612 AddInstruction(new HBoundsCheck(key, length));
3705 HLoadPixelArrayExternalPointer* external_elements = 3613 HLoadExternalArrayPointer* external_elements =
3706 new HLoadPixelArrayExternalPointer(elements); 3614 new HLoadExternalArrayPointer(elements);
3707 AddInstruction(external_elements); 3615 AddInstruction(external_elements);
3708 return new HStorePixelArrayElement(external_elements, key, val); 3616 return new HStorePixelArrayElement(external_elements, key, val);
3709 } 3617 }
3710 3618
3711 3619
3712 bool HGraphBuilder::TryArgumentsAccess(Property* expr) { 3620 bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
3713 VariableProxy* proxy = expr->obj()->AsVariableProxy(); 3621 VariableProxy* proxy = expr->obj()->AsVariableProxy();
3714 if (proxy == NULL) return false; 3622 if (proxy == NULL) return false;
3715 if (!proxy->var()->IsStackAllocated()) return false; 3623 if (!proxy->var()->IsStackAllocated()) return false;
3716 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { 3624 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
3786 VISIT_FOR_VALUE(expr->key()); 3694 VISIT_FOR_VALUE(expr->key());
3787 3695
3788 HValue* key = Pop(); 3696 HValue* key = Pop();
3789 HValue* obj = Pop(); 3697 HValue* obj = Pop();
3790 3698
3791 if (expr->IsMonomorphic()) { 3699 if (expr->IsMonomorphic()) {
3792 Handle<Map> receiver_type(expr->GetMonomorphicReceiverType()); 3700 Handle<Map> receiver_type(expr->GetMonomorphicReceiverType());
3793 // An object has either fast elements or pixel array elements, but never 3701 // An object has either fast elements or pixel array elements, but never
3794 // both. Pixel array maps that are assigned to pixel array elements are 3702 // both. Pixel array maps that are assigned to pixel array elements are
3795 // always created with the fast elements flag cleared. 3703 // always created with the fast elements flag cleared.
3796 if (receiver_type->has_pixel_array_elements()) { 3704 if (receiver_type->has_external_array_elements()) {
3797 instr = BuildLoadKeyedPixelArrayElement(obj, key, expr); 3705 if (expr->GetExternalArrayType() == kExternalPixelArray) {
3706 instr = BuildLoadKeyedPixelArrayElement(obj, key, expr);
3707 }
3798 } else if (receiver_type->has_fast_elements()) { 3708 } else if (receiver_type->has_fast_elements()) {
3799 instr = BuildLoadKeyedFastElement(obj, key, expr); 3709 instr = BuildLoadKeyedFastElement(obj, key, expr);
3800 } 3710 }
3801 } 3711 }
3802 if (instr == NULL) { 3712 if (instr == NULL) {
3803 instr = BuildLoadKeyedGeneric(obj, key); 3713 instr = BuildLoadKeyedGeneric(obj, key);
3804 } 3714 }
3805 } 3715 }
3806 instr->set_position(expr->position()); 3716 instr->set_position(expr->position());
3807 ast_context()->ReturnInstruction(instr, expr->id()); 3717 ast_context()->ReturnInstruction(instr, expr->id());
(...skipping 2146 matching lines...) Expand 10 before | Expand all | Expand 10 after
5954 } 5864 }
5955 } 5865 }
5956 5866
5957 #ifdef DEBUG 5867 #ifdef DEBUG
5958 if (graph_ != NULL) graph_->Verify(); 5868 if (graph_ != NULL) graph_->Verify();
5959 if (allocator_ != NULL) allocator_->Verify(); 5869 if (allocator_ != NULL) allocator_->Verify();
5960 #endif 5870 #endif
5961 } 5871 }
5962 5872
5963 } } // namespace v8::internal 5873 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698