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

Side by Side Diff: src/hydrogen.cc

Issue 6614010: [Isolates] Merge 6700:7030 from bleeding_edge to isolates. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
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 | Annotate | Revision Log
« 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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 end_(NULL), 58 end_(NULL),
59 loop_information_(NULL), 59 loop_information_(NULL),
60 predecessors_(2), 60 predecessors_(2),
61 dominator_(NULL), 61 dominator_(NULL),
62 dominated_blocks_(4), 62 dominated_blocks_(4),
63 last_environment_(NULL), 63 last_environment_(NULL),
64 argument_count_(-1), 64 argument_count_(-1),
65 first_instruction_index_(-1), 65 first_instruction_index_(-1),
66 last_instruction_index_(-1), 66 last_instruction_index_(-1),
67 deleted_phis_(4), 67 deleted_phis_(4),
68 parent_loop_header_(NULL),
68 is_inline_return_target_(false) { 69 is_inline_return_target_(false) {
69 } 70 }
70 71
71 72
72 void HBasicBlock::AttachLoopInformation() { 73 void HBasicBlock::AttachLoopInformation() {
73 ASSERT(!IsLoopHeader()); 74 ASSERT(!IsLoopHeader());
74 loop_information_ = new HLoopInformation(this); 75 loop_information_ = new HLoopInformation(this);
75 } 76 }
76 77
77 78
(...skipping 20 matching lines...) Expand all
98 } 99 }
99 100
100 101
101 void HBasicBlock::AddInstruction(HInstruction* instr) { 102 void HBasicBlock::AddInstruction(HInstruction* instr) {
102 ASSERT(!IsStartBlock() || !IsFinished()); 103 ASSERT(!IsStartBlock() || !IsFinished());
103 ASSERT(!instr->IsLinked()); 104 ASSERT(!instr->IsLinked());
104 ASSERT(!IsFinished()); 105 ASSERT(!IsFinished());
105 if (first_ == NULL) { 106 if (first_ == NULL) {
106 HBlockEntry* entry = new HBlockEntry(); 107 HBlockEntry* entry = new HBlockEntry();
107 entry->InitializeAsFirst(this); 108 entry->InitializeAsFirst(this);
108 first_ = entry; 109 first_ = last_ = entry;
109 } 110 }
110 instr->InsertAfter(GetLastInstruction()); 111 instr->InsertAfter(last_);
111 } 112 last_ = instr;
112
113
114 HInstruction* HBasicBlock::GetLastInstruction() {
115 if (end_ != NULL) return end_->previous();
116 if (first_ == NULL) return NULL;
117 if (last_ == NULL) last_ = first_;
118 while (last_->next() != NULL) last_ = last_->next();
119 return last_;
120 } 113 }
121 114
122 115
123 HSimulate* HBasicBlock::CreateSimulate(int id) { 116 HSimulate* HBasicBlock::CreateSimulate(int id) {
124 ASSERT(HasEnvironment()); 117 ASSERT(HasEnvironment());
125 HEnvironment* environment = last_environment(); 118 HEnvironment* environment = last_environment();
126 ASSERT(id == AstNode::kNoNumber || 119 ASSERT(id == AstNode::kNoNumber ||
127 environment->closure()->shared()->VerifyBailoutId(id)); 120 environment->closure()->shared()->VerifyBailoutId(id));
128 121
129 int push_count = environment->push_count(); 122 int push_count = environment->push_count();
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 UpdateEnvironment(env); 163 UpdateEnvironment(env);
171 } 164 }
172 165
173 166
174 void HBasicBlock::SetJoinId(int id) { 167 void HBasicBlock::SetJoinId(int id) {
175 int length = predecessors_.length(); 168 int length = predecessors_.length();
176 ASSERT(length > 0); 169 ASSERT(length > 0);
177 for (int i = 0; i < length; i++) { 170 for (int i = 0; i < length; i++) {
178 HBasicBlock* predecessor = predecessors_[i]; 171 HBasicBlock* predecessor = predecessors_[i];
179 ASSERT(predecessor->end()->IsGoto()); 172 ASSERT(predecessor->end()->IsGoto());
180 HSimulate* simulate = HSimulate::cast(predecessor->GetLastInstruction()); 173 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous());
181 // We only need to verify the ID once. 174 // We only need to verify the ID once.
182 ASSERT(i != 0 || 175 ASSERT(i != 0 ||
183 predecessor->last_environment()->closure()->shared() 176 predecessor->last_environment()->closure()->shared()
184 ->VerifyBailoutId(id)); 177 ->VerifyBailoutId(id));
185 simulate->set_ast_id(id); 178 simulate->set_ast_id(id);
186 } 179 }
187 } 180 }
188 181
189 182
190 bool HBasicBlock::Dominates(HBasicBlock* other) const { 183 bool HBasicBlock::Dominates(HBasicBlock* other) const {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 UNREACHABLE(); 279 UNREACHABLE();
287 return -1; 280 return -1;
288 } 281 }
289 282
290 283
291 #ifdef DEBUG 284 #ifdef DEBUG
292 void HBasicBlock::Verify() { 285 void HBasicBlock::Verify() {
293 // Check that every block is finished. 286 // Check that every block is finished.
294 ASSERT(IsFinished()); 287 ASSERT(IsFinished());
295 ASSERT(block_id() >= 0); 288 ASSERT(block_id() >= 0);
296
297 // Verify that all blocks targetting a branch target, have the same boolean
298 // value on top of their expression stack.
299 if (!cond().is_null()) {
300 ASSERT(predecessors()->length() > 0);
301 for (int i = 1; i < predecessors()->length(); i++) {
302 HBasicBlock* pred = predecessors()->at(i);
303 HValue* top = pred->last_environment()->Top();
304 ASSERT(top->IsConstant());
305 Object* a = *HConstant::cast(top)->handle();
306 Object* b = *cond();
307 ASSERT(a == b);
308 }
309 }
310 } 289 }
311 #endif 290 #endif
312 291
313 292
314 void HLoopInformation::RegisterBackEdge(HBasicBlock* block) { 293 void HLoopInformation::RegisterBackEdge(HBasicBlock* block) {
315 this->back_edges_.Add(block); 294 this->back_edges_.Add(block);
316 AddBlock(block); 295 AddBlock(block);
317 } 296 }
318 297
319 298
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 HConstant* HGraph::GetConstantTrue() { 475 HConstant* HGraph::GetConstantTrue() {
497 return GetConstant(&constant_true_, HEAP->true_value()); 476 return GetConstant(&constant_true_, HEAP->true_value());
498 } 477 }
499 478
500 479
501 HConstant* HGraph::GetConstantFalse() { 480 HConstant* HGraph::GetConstantFalse() {
502 return GetConstant(&constant_false_, HEAP->false_value()); 481 return GetConstant(&constant_false_, HEAP->false_value());
503 } 482 }
504 483
505 484
506 void HSubgraph::AppendOptional(HSubgraph* graph, 485 HBasicBlock* HGraphBuilder::CreateJoin(HBasicBlock* first,
507 bool on_true_branch, 486 HBasicBlock* second,
508 HValue* value) { 487 int join_id) {
509 ASSERT(HasExit() && graph->HasExit()); 488 if (first == NULL) {
510 HBasicBlock* other_block = graph_->CreateBasicBlock(); 489 return second;
511 HBasicBlock* join_block = graph_->CreateBasicBlock(); 490 } else if (second == NULL) {
512 491 return first;
513 HTest* test = on_true_branch 492 } else {
514 ? new HTest(value, graph->entry_block(), other_block)
515 : new HTest(value, other_block, graph->entry_block());
516 exit_block_->Finish(test);
517 other_block->Goto(join_block);
518 graph->exit_block()->Goto(join_block);
519 exit_block_ = join_block;
520 }
521
522
523 void HSubgraph::AppendJoin(HSubgraph* then_graph,
524 HSubgraph* else_graph,
525 AstNode* node) {
526 if (then_graph->HasExit() && else_graph->HasExit()) {
527 // We need to merge, create new merge block.
528 HBasicBlock* join_block = graph_->CreateBasicBlock(); 493 HBasicBlock* join_block = graph_->CreateBasicBlock();
529 then_graph->exit_block()->Goto(join_block); 494 first->Goto(join_block);
530 else_graph->exit_block()->Goto(join_block); 495 second->Goto(join_block);
531 join_block->SetJoinId(node->id()); 496 join_block->SetJoinId(join_id);
532 exit_block_ = join_block; 497 return join_block;
533 } else if (then_graph->HasExit()) {
534 exit_block_ = then_graph->exit_block_;
535 } else if (else_graph->HasExit()) {
536 exit_block_ = else_graph->exit_block_;
537 } else {
538 exit_block_ = NULL;
539 } 498 }
540 } 499 }
541 500
542 501
543 void HSubgraph::ResolveContinue(IterationStatement* statement) { 502 HBasicBlock* HGraphBuilder::JoinContinue(IterationStatement* statement,
544 HBasicBlock* continue_block = BundleContinue(statement); 503 HBasicBlock* exit_block,
504 HBasicBlock* continue_block) {
545 if (continue_block != NULL) { 505 if (continue_block != NULL) {
546 exit_block_ = JoinBlocks(exit_block(), 506 if (exit_block != NULL) exit_block->Goto(continue_block);
547 continue_block, 507 continue_block->SetJoinId(statement->ContinueId());
548 statement->ContinueId()); 508 return continue_block;
549 } 509 }
510 return exit_block;
550 } 511 }
551 512
552 513
553 HBasicBlock* HSubgraph::BundleBreak(BreakableStatement* statement) { 514 HBasicBlock* HGraphBuilder::CreateLoop(IterationStatement* statement,
554 return BundleBreakContinue(statement, false, statement->ExitId()); 515 HBasicBlock* loop_entry,
516 HBasicBlock* body_exit,
517 HBasicBlock* loop_successor,
518 HBasicBlock* break_block) {
519 if (body_exit != NULL) body_exit->Goto(loop_entry, true);
520 loop_entry->PostProcessLoopHeader(statement);
521 if (break_block != NULL) {
522 if (loop_successor != NULL) loop_successor->Goto(break_block);
523 break_block->SetJoinId(statement->ExitId());
524 return break_block;
525 }
526 return loop_successor;
555 } 527 }
556 528
557 529
558 HBasicBlock* HSubgraph::BundleContinue(IterationStatement* statement) { 530 void HBasicBlock::FinishExit(HControlInstruction* instruction) {
559 return BundleBreakContinue(statement, true, statement->ContinueId()); 531 Finish(instruction);
560 } 532 ClearEnvironment();
561
562
563 HBasicBlock* HSubgraph::BundleBreakContinue(BreakableStatement* statement,
564 bool is_continue,
565 int join_id) {
566 HBasicBlock* result = NULL;
567 const ZoneList<BreakContinueInfo*>* infos = break_continue_info();
568 for (int i = 0; i < infos->length(); ++i) {
569 BreakContinueInfo* info = infos->at(i);
570 if (info->is_continue() == is_continue &&
571 info->target() == statement &&
572 !info->IsResolved()) {
573 if (result == NULL) {
574 result = graph_->CreateBasicBlock();
575 }
576 info->block()->Goto(result);
577 info->Resolve();
578 }
579 }
580
581 if (result != NULL) result->SetJoinId(join_id);
582
583 return result;
584 }
585
586
587 HBasicBlock* HSubgraph::JoinBlocks(HBasicBlock* a, HBasicBlock* b, int id) {
588 if (a == NULL) return b;
589 if (b == NULL) return a;
590 HBasicBlock* target = graph_->CreateBasicBlock();
591 a->Goto(target);
592 b->Goto(target);
593 target->SetJoinId(id);
594 return target;
595 }
596
597
598 void HSubgraph::AppendEndless(HSubgraph* body, IterationStatement* statement) {
599 ConnectExitTo(body->entry_block());
600 body->ResolveContinue(statement);
601 body->ConnectExitTo(body->entry_block(), true);
602 exit_block_ = body->BundleBreak(statement);
603 body->entry_block()->PostProcessLoopHeader(statement);
604 }
605
606
607 void HSubgraph::AppendDoWhile(HSubgraph* body,
608 IterationStatement* statement,
609 HSubgraph* go_back,
610 HSubgraph* exit) {
611 ConnectExitTo(body->entry_block());
612 go_back->ConnectExitTo(body->entry_block(), true);
613
614 HBasicBlock* break_block = body->BundleBreak(statement);
615 exit_block_ =
616 JoinBlocks(exit->exit_block(), break_block, statement->ExitId());
617 body->entry_block()->PostProcessLoopHeader(statement);
618 }
619
620
621 void HSubgraph::AppendWhile(HSubgraph* condition,
622 HSubgraph* body,
623 IterationStatement* statement,
624 HSubgraph* continue_subgraph,
625 HSubgraph* exit) {
626 ConnectExitTo(condition->entry_block());
627
628 HBasicBlock* break_block = body->BundleBreak(statement);
629 exit_block_ =
630 JoinBlocks(exit->exit_block(), break_block, statement->ExitId());
631
632 if (continue_subgraph != NULL) {
633 body->ConnectExitTo(continue_subgraph->entry_block(), true);
634 continue_subgraph->entry_block()->SetJoinId(statement->EntryId());
635 exit_block_ = JoinBlocks(exit_block_,
636 continue_subgraph->exit_block(),
637 statement->ExitId());
638 } else {
639 body->ConnectExitTo(condition->entry_block(), true);
640 }
641 condition->entry_block()->PostProcessLoopHeader(statement);
642 }
643
644
645 void HSubgraph::Append(HSubgraph* next, BreakableStatement* stmt) {
646 exit_block_->Goto(next->entry_block());
647 exit_block_ = next->exit_block_;
648
649 if (stmt != NULL) {
650 next->entry_block()->SetJoinId(stmt->EntryId());
651 HBasicBlock* break_block = next->BundleBreak(stmt);
652 exit_block_ = JoinBlocks(exit_block(), break_block, stmt->ExitId());
653 }
654 }
655
656
657 void HSubgraph::FinishExit(HControlInstruction* instruction) {
658 ASSERT(HasExit());
659 exit_block_->Finish(instruction);
660 exit_block_->ClearEnvironment();
661 exit_block_ = NULL;
662 }
663
664
665 void HSubgraph::FinishBreakContinue(BreakableStatement* target,
666 bool is_continue) {
667 ASSERT(!exit_block_->IsFinished());
668 BreakContinueInfo* info = new BreakContinueInfo(target, exit_block_,
669 is_continue);
670 break_continue_info_.Add(info);
671 exit_block_ = NULL;
672 } 533 }
673 534
674 535
675 HGraph::HGraph(CompilationInfo* info) 536 HGraph::HGraph(CompilationInfo* info)
676 : HSubgraph(this), 537 : HSubgraph(this),
677 next_block_id_(0), 538 next_block_id_(0),
678 info_(info), 539 info_(info),
679 blocks_(8), 540 blocks_(8),
680 values_(16), 541 values_(16),
681 phi_list_(NULL) { 542 phi_list_(NULL) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
732 593
733 594
734 HBasicBlock* HGraph::CreateBasicBlock() { 595 HBasicBlock* HGraph::CreateBasicBlock() {
735 HBasicBlock* result = new HBasicBlock(this); 596 HBasicBlock* result = new HBasicBlock(this);
736 blocks_.Add(result); 597 blocks_.Add(result);
737 return result; 598 return result;
738 } 599 }
739 600
740 601
741 void HGraph::Canonicalize() { 602 void HGraph::Canonicalize() {
603 if (!FLAG_use_canonicalizing) return;
742 HPhase phase("Canonicalize", this); 604 HPhase phase("Canonicalize", this);
743 if (FLAG_use_canonicalizing) { 605 for (int i = 0; i < blocks()->length(); ++i) {
744 for (int i = 0; i < blocks()->length(); ++i) { 606 HInstruction* instr = blocks()->at(i)->first();
745 HBasicBlock* b = blocks()->at(i); 607 while (instr != NULL) {
746 for (HInstruction* insn = b->first(); insn != NULL; insn = insn->next()) { 608 HValue* value = instr->Canonicalize();
747 HValue* value = insn->Canonicalize(); 609 if (value != instr) instr->ReplaceAndDelete(value);
748 if (value != insn) { 610 instr = instr->next();
749 if (value != NULL) {
750 insn->ReplaceAndDelete(value);
751 } else {
752 insn->Delete();
753 }
754 }
755 }
756 } 611 }
757 } 612 }
758 } 613 }
759 614
760 615
761 void HGraph::OrderBlocks() { 616 void HGraph::OrderBlocks() {
762 HPhase phase("Block ordering"); 617 HPhase phase("Block ordering");
763 BitVector visited(blocks_.length()); 618 BitVector visited(blocks_.length());
764 619
765 ZoneList<HBasicBlock*> reverse_result(8); 620 ZoneList<HBasicBlock*> reverse_result(8);
(...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after
1501 TraceGVN("Instruction %d kills\n", instr->id()); 1356 TraceGVN("Instruction %d kills\n", instr->id());
1502 } else if (instr->CheckFlag(HValue::kUseGVN)) { 1357 } else if (instr->CheckFlag(HValue::kUseGVN)) {
1503 HValue* other = map->Lookup(instr); 1358 HValue* other = map->Lookup(instr);
1504 if (other != NULL) { 1359 if (other != NULL) {
1505 ASSERT(instr->Equals(other) && other->Equals(instr)); 1360 ASSERT(instr->Equals(other) && other->Equals(instr));
1506 TraceGVN("Replacing value %d (%s) with value %d (%s)\n", 1361 TraceGVN("Replacing value %d (%s) with value %d (%s)\n",
1507 instr->id(), 1362 instr->id(),
1508 instr->Mnemonic(), 1363 instr->Mnemonic(),
1509 other->id(), 1364 other->id(),
1510 other->Mnemonic()); 1365 other->Mnemonic());
1511 instr->ReplaceValue(other); 1366 instr->ReplaceAndDelete(other);
1512 instr->Delete();
1513 } else { 1367 } else {
1514 map->Add(instr); 1368 map->Add(instr);
1515 } 1369 }
1516 } 1370 }
1517 instr = next; 1371 instr = next;
1518 } 1372 }
1519 1373
1520 // Recursively continue analysis for all immediately dominated blocks. 1374 // Recursively continue analysis for all immediately dominated blocks.
1521 int length = block->dominated_blocks()->length(); 1375 int length = block->dominated_blocks()->length();
1522 for (int i = 0; i < length; ++i) { 1376 for (int i = 0; i < length; ++i) {
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
1806 } 1660 }
1807 } 1661 }
1808 1662
1809 1663
1810 void HGraph::InsertRepresentationChangeForUse(HValue* value, 1664 void HGraph::InsertRepresentationChangeForUse(HValue* value,
1811 HValue* use, 1665 HValue* use,
1812 Representation to, 1666 Representation to,
1813 bool is_truncating) { 1667 bool is_truncating) {
1814 // Insert the representation change right before its use. For phi-uses we 1668 // Insert the representation change right before its use. For phi-uses we
1815 // insert at the end of the corresponding predecessor. 1669 // insert at the end of the corresponding predecessor.
1816 HBasicBlock* insert_block = use->block(); 1670 HInstruction* next = NULL;
1817 if (use->IsPhi()) { 1671 if (use->IsPhi()) {
1818 int index = 0; 1672 int index = 0;
1819 while (use->OperandAt(index) != value) ++index; 1673 while (use->OperandAt(index) != value) ++index;
1820 insert_block = insert_block->predecessors()->at(index); 1674 next = use->block()->predecessors()->at(index)->end();
1675 } else {
1676 next = HInstruction::cast(use);
1821 } 1677 }
1822 1678
1823 HInstruction* next = (insert_block == use->block())
1824 ? HInstruction::cast(use)
1825 : insert_block->end();
1826
1827 // For constants we try to make the representation change at compile 1679 // For constants we try to make the representation change at compile
1828 // time. When a representation change is not possible without loss of 1680 // time. When a representation change is not possible without loss of
1829 // information we treat constants like normal instructions and insert the 1681 // information we treat constants like normal instructions and insert the
1830 // change instructions for them. 1682 // change instructions for them.
1831 HInstruction* new_value = NULL; 1683 HInstruction* new_value = NULL;
1832 if (value->IsConstant()) { 1684 if (value->IsConstant()) {
1833 HConstant* constant = HConstant::cast(value); 1685 HConstant* constant = HConstant::cast(value);
1834 // Try to create a new copy of the constant with the new representation. 1686 // Try to create a new copy of the constant with the new representation.
1835 new_value = is_truncating 1687 new_value = is_truncating
1836 ? constant->CopyToTruncatedInt32() 1688 ? constant->CopyToTruncatedInt32()
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
2008 } 1860 }
2009 1861
2010 1862
2011 AstContext::~AstContext() { 1863 AstContext::~AstContext() {
2012 owner_->set_ast_context(outer_); // Pop. 1864 owner_->set_ast_context(outer_); // Pop.
2013 } 1865 }
2014 1866
2015 1867
2016 EffectContext::~EffectContext() { 1868 EffectContext::~EffectContext() {
2017 ASSERT(owner()->HasStackOverflow() || 1869 ASSERT(owner()->HasStackOverflow() ||
2018 !owner()->subgraph()->HasExit() || 1870 owner()->current_block() == NULL ||
2019 owner()->environment()->length() == original_length_); 1871 owner()->environment()->length() == original_length_);
2020 } 1872 }
2021 1873
2022 1874
2023 ValueContext::~ValueContext() { 1875 ValueContext::~ValueContext() {
2024 ASSERT(owner()->HasStackOverflow() || 1876 ASSERT(owner()->HasStackOverflow() ||
2025 !owner()->subgraph()->HasExit() || 1877 owner()->current_block() == NULL ||
2026 owner()->environment()->length() == original_length_ + 1); 1878 owner()->environment()->length() == original_length_ + 1);
2027 } 1879 }
2028 1880
2029 1881
2030 void EffectContext::ReturnValue(HValue* value) { 1882 void EffectContext::ReturnValue(HValue* value) {
2031 // The value is simply ignored. 1883 // The value is simply ignored.
2032 } 1884 }
2033 1885
2034 1886
2035 void ValueContext::ReturnValue(HValue* value) { 1887 void ValueContext::ReturnValue(HValue* value) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2073 1925
2074 void TestContext::BuildBranch(HValue* value) { 1926 void TestContext::BuildBranch(HValue* value) {
2075 // We expect the graph to be in edge-split form: there is no edge that 1927 // We expect the graph to be in edge-split form: there is no edge that
2076 // connects a branch node to a join node. We conservatively ensure that 1928 // connects a branch node to a join node. We conservatively ensure that
2077 // property by always adding an empty block on the outgoing edges of this 1929 // property by always adding an empty block on the outgoing edges of this
2078 // branch. 1930 // branch.
2079 HGraphBuilder* builder = owner(); 1931 HGraphBuilder* builder = owner();
2080 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); 1932 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
2081 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); 1933 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
2082 HTest* test = new HTest(value, empty_true, empty_false); 1934 HTest* test = new HTest(value, empty_true, empty_false);
2083 builder->CurrentBlock()->Finish(test); 1935 builder->current_block()->Finish(test);
2084 1936
2085 HValue* const no_return_value = NULL; 1937 HValue* const no_return_value = NULL;
2086 HBasicBlock* true_target = if_true(); 1938 HBasicBlock* true_target = if_true();
2087 if (true_target->IsInlineReturnTarget()) { 1939 if (true_target->IsInlineReturnTarget()) {
2088 empty_true->AddLeaveInlined(no_return_value, true_target); 1940 empty_true->AddLeaveInlined(no_return_value, true_target);
2089 } else { 1941 } else {
2090 empty_true->Goto(true_target); 1942 empty_true->Goto(true_target);
2091 } 1943 }
2092 1944
2093 HBasicBlock* false_target = if_false(); 1945 HBasicBlock* false_target = if_false();
2094 if (false_target->IsInlineReturnTarget()) { 1946 if (false_target->IsInlineReturnTarget()) {
2095 empty_false->AddLeaveInlined(no_return_value, false_target); 1947 empty_false->AddLeaveInlined(no_return_value, false_target);
2096 } else { 1948 } else {
2097 empty_false->Goto(false_target); 1949 empty_false->Goto(false_target);
2098 } 1950 }
2099 builder->subgraph()->set_exit_block(NULL); 1951 builder->set_current_block(NULL);
2100 } 1952 }
2101 1953
2102 1954
2103 // HGraphBuilder infrastructure for bailing out and checking bailouts. 1955 // HGraphBuilder infrastructure for bailing out and checking bailouts.
2104 #define BAILOUT(reason) \ 1956 #define BAILOUT(reason) \
2105 do { \ 1957 do { \
2106 Bailout(reason); \ 1958 Bailout(reason); \
2107 return; \ 1959 return; \
2108 } while (false) 1960 } while (false)
2109 1961
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2146 class HGraphBuilder::SubgraphScope BASE_EMBEDDED { 1998 class HGraphBuilder::SubgraphScope BASE_EMBEDDED {
2147 public: 1999 public:
2148 SubgraphScope(HGraphBuilder* builder, HSubgraph* new_subgraph) 2000 SubgraphScope(HGraphBuilder* builder, HSubgraph* new_subgraph)
2149 : builder_(builder) { 2001 : builder_(builder) {
2150 old_subgraph_ = builder_->current_subgraph_; 2002 old_subgraph_ = builder_->current_subgraph_;
2151 subgraph_ = new_subgraph; 2003 subgraph_ = new_subgraph;
2152 builder_->current_subgraph_ = subgraph_; 2004 builder_->current_subgraph_ = subgraph_;
2153 } 2005 }
2154 2006
2155 ~SubgraphScope() { 2007 ~SubgraphScope() {
2156 old_subgraph_->AddBreakContinueInfo(subgraph_);
2157 builder_->current_subgraph_ = old_subgraph_; 2008 builder_->current_subgraph_ = old_subgraph_;
2158 } 2009 }
2159 2010
2160 HSubgraph* subgraph() const { return subgraph_; } 2011 HSubgraph* subgraph() const { return subgraph_; }
2161 2012
2162 private: 2013 private:
2163 HGraphBuilder* builder_; 2014 HGraphBuilder* builder_;
2164 HSubgraph* old_subgraph_; 2015 HSubgraph* old_subgraph_;
2165 HSubgraph* subgraph_; 2016 HSubgraph* subgraph_;
2166 }; 2017 };
(...skipping 21 matching lines...) Expand all
2188 2039
2189 2040
2190 void HGraphBuilder::VisitForControl(Expression* expr, 2041 void HGraphBuilder::VisitForControl(Expression* expr,
2191 HBasicBlock* true_block, 2042 HBasicBlock* true_block,
2192 HBasicBlock* false_block) { 2043 HBasicBlock* false_block) {
2193 TestContext for_test(this, true_block, false_block); 2044 TestContext for_test(this, true_block, false_block);
2194 Visit(expr); 2045 Visit(expr);
2195 } 2046 }
2196 2047
2197 2048
2198 HValue* HGraphBuilder::VisitArgument(Expression* expr) { 2049 void HGraphBuilder::VisitArgument(Expression* expr) {
2199 VisitForValue(expr); 2050 VISIT_FOR_VALUE(expr);
2200 if (HasStackOverflow() || !subgraph()->HasExit()) return NULL; 2051 Push(AddInstruction(new HPushArgument(Pop())));
2201 return environment()->Top();
2202 } 2052 }
2203 2053
2204 2054
2205 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { 2055 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) {
2206 for (int i = 0; i < arguments->length(); i++) { 2056 for (int i = 0; i < arguments->length(); i++) {
2207 VisitArgument(arguments->at(i)); 2057 VisitArgument(arguments->at(i));
2208 if (HasStackOverflow() || !current_subgraph_->HasExit()) return; 2058 if (HasStackOverflow() || current_block() == NULL) return;
2059 }
2060 }
2061
2062
2063 void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) {
2064 for (int i = 0; i < exprs->length(); ++i) {
2065 VISIT_FOR_VALUE(exprs->at(i));
2209 } 2066 }
2210 } 2067 }
2211 2068
2212 2069
2213 HGraph* HGraphBuilder::CreateGraph(CompilationInfo* info) { 2070 HGraph* HGraphBuilder::CreateGraph(CompilationInfo* info) {
2214 ASSERT(current_subgraph_ == NULL); 2071 ASSERT(subgraph() == NULL);
2215 graph_ = new HGraph(info); 2072 graph_ = new HGraph(info);
2216 2073
2217 { 2074 {
2218 HPhase phase("Block building"); 2075 HPhase phase("Block building");
2219 graph_->Initialize(CreateBasicBlock(graph_->start_environment())); 2076 graph()->Initialize(CreateBasicBlock(graph()->start_environment()));
2220 current_subgraph_ = graph_; 2077 current_subgraph_ = graph();
2221 2078
2222 Scope* scope = info->scope(); 2079 Scope* scope = info->scope();
2080 if (scope->HasIllegalRedeclaration()) {
2081 Bailout("function with illegal redeclaration");
2082 return NULL;
2083 }
2223 SetupScope(scope); 2084 SetupScope(scope);
2224 VisitDeclarations(scope->declarations()); 2085 VisitDeclarations(scope->declarations());
2225
2226 AddInstruction(new HStackCheck()); 2086 AddInstruction(new HStackCheck());
2227 2087
2228 ZoneList<Statement*>* stmts = info->function()->body(); 2088 // Add an edge to the body entry. This is warty: the graph's start
2229 HSubgraph* body = CreateGotoSubgraph(environment()); 2089 // environment will be used by the Lithium translation as the initial
2230 AddToSubgraph(body, stmts); 2090 // environment on graph entry, but it has now been mutated by the
2091 // Hydrogen translation of the instructions in the start block. This
2092 // environment uses values which have not been defined yet. These
2093 // Hydrogen instructions will then be replayed by the Lithium
2094 // translation, so they cannot have an environment effect. The edge to
2095 // the body's entry block (along with some special logic for the start
2096 // block in HInstruction::InsertAfter) seals the start block from
2097 // getting unwanted instructions inserted.
2098 //
2099 // TODO(kmillikin): Fix this. Stop mutating the initial environment.
2100 // Make the Hydrogen instructions in the initial block into Hydrogen
2101 // values (but not instructions), present in the initial environment and
2102 // not replayed by the Lithium translation.
2103 HEnvironment* initial_env = environment()->CopyWithoutHistory();
2104 HBasicBlock* body_entry = CreateBasicBlock(initial_env);
2105 current_block()->Goto(body_entry);
2106 body_entry->SetJoinId(info->function()->id());
2107 set_current_block(body_entry);
2108 VisitStatements(info->function()->body());
2231 if (HasStackOverflow()) return NULL; 2109 if (HasStackOverflow()) return NULL;
2232 current_subgraph_->Append(body, NULL);
2233 body->entry_block()->SetJoinId(info->function()->id());
2234 2110
2235 if (graph_->HasExit()) { 2111 if (current_block() != NULL) {
2236 graph_->FinishExit(new HReturn(graph_->GetConstantUndefined())); 2112 HReturn* instr = new HReturn(graph()->GetConstantUndefined());
2113 current_block()->FinishExit(instr);
2114 set_current_block(NULL);
2237 } 2115 }
2238 } 2116 }
2239 2117
2240 graph_->OrderBlocks(); 2118 graph()->OrderBlocks();
2241 graph_->AssignDominators(); 2119 graph()->AssignDominators();
2242 graph_->EliminateRedundantPhis(); 2120 graph()->EliminateRedundantPhis();
2243 if (!graph_->CollectPhis()) { 2121 if (!graph()->CollectPhis()) {
2244 Bailout("Phi-use of arguments object"); 2122 Bailout("Phi-use of arguments object");
2245 return NULL; 2123 return NULL;
2246 } 2124 }
2247 2125
2248 HInferRepresentation rep(graph_); 2126 HInferRepresentation rep(graph());
2249 rep.Analyze(); 2127 rep.Analyze();
2250 2128
2251 if (FLAG_use_range) { 2129 if (FLAG_use_range) {
2252 HRangeAnalysis rangeAnalysis(graph_); 2130 HRangeAnalysis rangeAnalysis(graph());
2253 rangeAnalysis.Analyze(); 2131 rangeAnalysis.Analyze();
2254 } 2132 }
2255 2133
2256 graph_->InitializeInferredTypes(); 2134 graph()->InitializeInferredTypes();
2257 graph_->Canonicalize(); 2135 graph()->Canonicalize();
2258 graph_->InsertRepresentationChanges(); 2136 graph()->InsertRepresentationChanges();
2259 graph_->ComputeMinusZeroChecks(); 2137 graph()->ComputeMinusZeroChecks();
2260 2138
2261 // Eliminate redundant stack checks on backwards branches. 2139 // Eliminate redundant stack checks on backwards branches.
2262 HStackCheckEliminator sce(graph_); 2140 HStackCheckEliminator sce(graph());
2263 sce.Process(); 2141 sce.Process();
2264 2142
2265 // Perform common subexpression elimination and loop-invariant code motion. 2143 // Perform common subexpression elimination and loop-invariant code motion.
2266 if (FLAG_use_gvn) { 2144 if (FLAG_use_gvn) {
2267 HPhase phase("Global value numbering", graph_); 2145 HPhase phase("Global value numbering", graph());
2268 HGlobalValueNumberer gvn(graph_); 2146 HGlobalValueNumberer gvn(graph());
2269 gvn.Analyze(); 2147 gvn.Analyze();
2270 } 2148 }
2271 2149
2272 return graph_; 2150 return graph();
2273 } 2151 }
2274 2152
2275 2153
2276 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, Statement* stmt) { 2154 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, Statement* stmt) {
2277 SubgraphScope scope(this, graph); 2155 SubgraphScope scope(this, graph);
2278 Visit(stmt); 2156 Visit(stmt);
2279 } 2157 }
2280 2158
2281 2159
2282 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, Expression* expr) { 2160 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, Expression* expr) {
2283 SubgraphScope scope(this, graph); 2161 SubgraphScope scope(this, graph);
2284 VisitForValue(expr); 2162 VisitForValue(expr);
2285 } 2163 }
2286 2164
2287 2165
2288 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, 2166 void HGraphBuilder::AddToSubgraph(HSubgraph* graph,
2289 ZoneList<Statement*>* stmts) { 2167 ZoneList<Statement*>* stmts) {
2290 SubgraphScope scope(this, graph); 2168 SubgraphScope scope(this, graph);
2291 VisitStatements(stmts); 2169 VisitStatements(stmts);
2292 } 2170 }
2293 2171
2294 2172
2295 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { 2173 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
2296 ASSERT(current_subgraph_->HasExit()); 2174 ASSERT(current_block() != NULL);
2297 current_subgraph_->exit_block()->AddInstruction(instr); 2175 current_block()->AddInstruction(instr);
2298 return instr; 2176 return instr;
2299 } 2177 }
2300 2178
2301 2179
2302 void HGraphBuilder::AddSimulate(int id) { 2180 void HGraphBuilder::AddSimulate(int id) {
2303 ASSERT(current_subgraph_->HasExit()); 2181 ASSERT(current_block() != NULL);
2304 current_subgraph_->exit_block()->AddSimulate(id); 2182 current_block()->AddSimulate(id);
2305 } 2183 }
2306 2184
2307 2185
2308 void HGraphBuilder::AddPhi(HPhi* instr) { 2186 void HGraphBuilder::AddPhi(HPhi* instr) {
2309 ASSERT(current_subgraph_->HasExit()); 2187 ASSERT(current_block() != NULL);
2310 current_subgraph_->exit_block()->AddPhi(instr); 2188 current_block()->AddPhi(instr);
2311 } 2189 }
2312 2190
2313 2191
2314 void HGraphBuilder::PushAndAdd(HInstruction* instr) { 2192 void HGraphBuilder::PushAndAdd(HInstruction* instr) {
2315 Push(instr); 2193 Push(instr);
2316 AddInstruction(instr); 2194 AddInstruction(instr);
2317 } 2195 }
2318 2196
2319 2197
2320 void HGraphBuilder::PushArgumentsForStubCall(int argument_count) { 2198 template <int V>
2321 const int kMaxStubArguments = 4; 2199 HInstruction* HGraphBuilder::PreProcessCall(HCall<V>* call) {
2322 ASSERT_GE(kMaxStubArguments, argument_count); 2200 int count = call->argument_count();
2323 // Push the arguments on the stack. 2201 ZoneList<HValue*> arguments(count);
2324 HValue* arguments[kMaxStubArguments]; 2202 for (int i = 0; i < count; ++i) {
2325 for (int i = argument_count - 1; i >= 0; i--) { 2203 arguments.Add(Pop());
2326 arguments[i] = Pop();
2327 } 2204 }
2328 for (int i = 0; i < argument_count; i++) { 2205
2329 AddInstruction(new HPushArgument(arguments[i])); 2206 while (!arguments.is_empty()) {
2207 AddInstruction(new HPushArgument(arguments.RemoveLast()));
2330 } 2208 }
2209 return call;
2331 } 2210 }
2332 2211
2333 2212
2334 void HGraphBuilder::ProcessCall(HCall* call) {
2335 for (int i = call->argument_count() - 1; i >= 0; --i) {
2336 HValue* value = Pop();
2337 HPushArgument* push = new HPushArgument(value);
2338 call->SetArgumentAt(i, push);
2339 }
2340
2341 for (int i = 0; i < call->argument_count(); ++i) {
2342 AddInstruction(call->PushArgumentAt(i));
2343 }
2344 }
2345
2346
2347 void HGraphBuilder::SetupScope(Scope* scope) { 2213 void HGraphBuilder::SetupScope(Scope* scope) {
2348 // We don't yet handle the function name for named function expressions. 2214 // We don't yet handle the function name for named function expressions.
2349 if (scope->function() != NULL) BAILOUT("named function expression"); 2215 if (scope->function() != NULL) BAILOUT("named function expression");
2350 2216
2351 // We can't handle heap-allocated locals.
2352 if (scope->num_heap_slots() > 0) BAILOUT("heap allocated locals");
2353
2354 HConstant* undefined_constant = 2217 HConstant* undefined_constant =
2355 new HConstant(FACTORY->undefined_value(), Representation::Tagged()); 2218 new HConstant(FACTORY->undefined_value(), Representation::Tagged());
2356 AddInstruction(undefined_constant); 2219 AddInstruction(undefined_constant);
2357 graph_->set_undefined_constant(undefined_constant); 2220 graph_->set_undefined_constant(undefined_constant);
2358 2221
2359 // Set the initial values of parameters including "this". "This" has 2222 // Set the initial values of parameters including "this". "This" has
2360 // parameter index 0. 2223 // parameter index 0.
2361 int count = scope->num_parameters() + 1; 2224 int count = scope->num_parameters() + 1;
2362 for (int i = 0; i < count; ++i) { 2225 for (int i = 0; i < count; ++i) {
2363 HInstruction* parameter = AddInstruction(new HParameter(i)); 2226 HInstruction* parameter = AddInstruction(new HParameter(i));
2364 environment()->Bind(i, parameter); 2227 environment()->Bind(i, parameter);
2365 } 2228 }
2366 2229
2367 // Set the initial values of stack-allocated locals. 2230 // Set the initial values of stack-allocated locals.
2368 for (int i = count; i < environment()->length(); ++i) { 2231 for (int i = count; i < environment()->length(); ++i) {
2369 environment()->Bind(i, undefined_constant); 2232 environment()->Bind(i, undefined_constant);
2370 } 2233 }
2371 2234
2372 // Handle the arguments and arguments shadow variables specially (they do 2235 // Handle the arguments and arguments shadow variables specially (they do
2373 // not have declarations). 2236 // not have declarations).
2374 if (scope->arguments() != NULL) { 2237 if (scope->arguments() != NULL) {
2238 if (!scope->arguments()->IsStackAllocated() ||
2239 !scope->arguments_shadow()->IsStackAllocated()) {
2240 BAILOUT("context-allocated arguments");
2241 }
2375 HArgumentsObject* object = new HArgumentsObject; 2242 HArgumentsObject* object = new HArgumentsObject;
2376 AddInstruction(object); 2243 AddInstruction(object);
2377 graph()->SetArgumentsObject(object); 2244 graph()->SetArgumentsObject(object);
2378 environment()->Bind(scope->arguments(), object); 2245 environment()->Bind(scope->arguments(), object);
2379 environment()->Bind(scope->arguments_shadow(), object); 2246 environment()->Bind(scope->arguments_shadow(), object);
2380 } 2247 }
2381 } 2248 }
2382 2249
2383 2250
2384 void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { 2251 void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
2385 for (int i = 0; i < statements->length(); i++) { 2252 for (int i = 0; i < statements->length(); i++) {
2386 Visit(statements->at(i)); 2253 Visit(statements->at(i));
2387 if (HasStackOverflow() || !current_subgraph_->HasExit()) break; 2254 if (HasStackOverflow() || current_block() == NULL) break;
2388 } 2255 }
2389 } 2256 }
2390 2257
2391 2258
2392 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { 2259 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
2393 HBasicBlock* b = graph()->CreateBasicBlock(); 2260 HBasicBlock* b = graph()->CreateBasicBlock();
2394 b->SetInitialEnvironment(env); 2261 b->SetInitialEnvironment(env);
2395 return b; 2262 return b;
2396 } 2263 }
2397 2264
2398 2265
2399 HSubgraph* HGraphBuilder::CreateInlinedSubgraph(HEnvironment* outer, 2266 HSubgraph* HGraphBuilder::CreateInlinedSubgraph(HEnvironment* outer,
2400 Handle<JSFunction> target, 2267 Handle<JSFunction> target,
2401 FunctionLiteral* function) { 2268 FunctionLiteral* function) {
2402 HConstant* undefined = graph()->GetConstantUndefined(); 2269 HConstant* undefined = graph()->GetConstantUndefined();
2403 HEnvironment* inner = 2270 HEnvironment* inner =
2404 outer->CopyForInlining(target, function, true, undefined); 2271 outer->CopyForInlining(target, function, true, undefined);
2405 HSubgraph* subgraph = new HSubgraph(graph()); 2272 HSubgraph* subgraph = new HSubgraph(graph());
2406 subgraph->Initialize(CreateBasicBlock(inner)); 2273 subgraph->Initialize(CreateBasicBlock(inner));
2407 return subgraph; 2274 return subgraph;
2408 } 2275 }
2409 2276
2410 2277
2411 HSubgraph* HGraphBuilder::CreateGotoSubgraph(HEnvironment* env) {
2412 HSubgraph* subgraph = new HSubgraph(graph());
2413 HEnvironment* new_env = env->CopyWithoutHistory();
2414 subgraph->Initialize(CreateBasicBlock(new_env));
2415 return subgraph;
2416 }
2417
2418
2419 HSubgraph* HGraphBuilder::CreateEmptySubgraph() { 2278 HSubgraph* HGraphBuilder::CreateEmptySubgraph() {
2420 HSubgraph* subgraph = new HSubgraph(graph()); 2279 HSubgraph* subgraph = new HSubgraph(graph());
2421 subgraph->Initialize(graph()->CreateBasicBlock()); 2280 subgraph->Initialize(graph()->CreateBasicBlock());
2422 return subgraph; 2281 return subgraph;
2423 } 2282 }
2424 2283
2425 2284
2426 HSubgraph* HGraphBuilder::CreateBranchSubgraph(HEnvironment* env) { 2285 HSubgraph* HGraphBuilder::CreateBranchSubgraph(HEnvironment* env) {
2427 HSubgraph* subgraph = new HSubgraph(graph()); 2286 HSubgraph* subgraph = new HSubgraph(graph());
2428 HEnvironment* new_env = env->Copy(); 2287 HEnvironment* new_env = env->Copy();
2429 subgraph->Initialize(CreateBasicBlock(new_env)); 2288 subgraph->Initialize(CreateBasicBlock(new_env));
2430 return subgraph; 2289 return subgraph;
2431 } 2290 }
2432 2291
2433 2292
2434 HSubgraph* HGraphBuilder::CreateLoopHeaderSubgraph(HEnvironment* env) { 2293 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
2435 HSubgraph* subgraph = new HSubgraph(graph()); 2294 HBasicBlock* header = graph()->CreateBasicBlock();
2436 HBasicBlock* block = graph()->CreateBasicBlock(); 2295 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
2437 HEnvironment* new_env = env->CopyAsLoopHeader(block); 2296 header->SetInitialEnvironment(entry_env);
2438 block->SetInitialEnvironment(new_env); 2297 header->AttachLoopInformation();
2439 subgraph->Initialize(block); 2298 return header;
2440 subgraph->entry_block()->AttachLoopInformation();
2441 return subgraph;
2442 } 2299 }
2443 2300
2444 2301
2445 void HGraphBuilder::VisitBlock(Block* stmt) { 2302 void HGraphBuilder::VisitBlock(Block* stmt) {
2446 if (stmt->labels() != NULL) { 2303 BreakAndContinueInfo break_info(stmt);
2447 HSubgraph* block_graph = CreateGotoSubgraph(environment()); 2304 { BreakAndContinueScope push(&break_info, this);
2448 ADD_TO_SUBGRAPH(block_graph, stmt->statements());
2449 current_subgraph_->Append(block_graph, stmt);
2450 } else {
2451 VisitStatements(stmt->statements()); 2305 VisitStatements(stmt->statements());
2306 CHECK_BAILOUT;
2307 }
2308 HBasicBlock* break_block = break_info.break_block();
2309 if (break_block != NULL) {
2310 if (current_block() != NULL) current_block()->Goto(break_block);
2311 break_block->SetJoinId(stmt->ExitId());
2312 set_current_block(break_block);
2452 } 2313 }
2453 } 2314 }
2454 2315
2455 2316
2456 void HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { 2317 void HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
2457 VisitForEffect(stmt->expression()); 2318 VisitForEffect(stmt->expression());
2458 } 2319 }
2459 2320
2460 2321
2461 void HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { 2322 void HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
2462 } 2323 }
2463 2324
2464 2325
2465 void HGraphBuilder::VisitIfStatement(IfStatement* stmt) { 2326 void HGraphBuilder::VisitIfStatement(IfStatement* stmt) {
2466 if (stmt->condition()->ToBooleanIsTrue()) { 2327 if (stmt->condition()->ToBooleanIsTrue()) {
2467 AddSimulate(stmt->ThenId()); 2328 AddSimulate(stmt->ThenId());
2468 Visit(stmt->then_statement()); 2329 Visit(stmt->then_statement());
2469 } else if (stmt->condition()->ToBooleanIsFalse()) { 2330 } else if (stmt->condition()->ToBooleanIsFalse()) {
2470 AddSimulate(stmt->ElseId()); 2331 AddSimulate(stmt->ElseId());
2471 Visit(stmt->else_statement()); 2332 Visit(stmt->else_statement());
2472 } else { 2333 } else {
2473 HSubgraph* then_graph = CreateEmptySubgraph(); 2334 HBasicBlock* cond_true = graph()->CreateBasicBlock();
2474 HSubgraph* else_graph = CreateEmptySubgraph(); 2335 HBasicBlock* cond_false = graph()->CreateBasicBlock();
2475 VISIT_FOR_CONTROL(stmt->condition(), 2336 VISIT_FOR_CONTROL(stmt->condition(), cond_true, cond_false);
2476 then_graph->entry_block(), 2337 cond_true->SetJoinId(stmt->ThenId());
2477 else_graph->entry_block()); 2338 cond_false->SetJoinId(stmt->ElseId());
2478 2339
2479 then_graph->entry_block()->SetJoinId(stmt->ThenId()); 2340 set_current_block(cond_true);
2480 ADD_TO_SUBGRAPH(then_graph, stmt->then_statement()); 2341 Visit(stmt->then_statement());
2342 CHECK_BAILOUT;
2343 HBasicBlock* other = current_block();
2481 2344
2482 else_graph->entry_block()->SetJoinId(stmt->ElseId()); 2345 set_current_block(cond_false);
2483 ADD_TO_SUBGRAPH(else_graph, stmt->else_statement()); 2346 Visit(stmt->else_statement());
2347 CHECK_BAILOUT;
2484 2348
2485 current_subgraph_->AppendJoin(then_graph, else_graph, stmt); 2349 HBasicBlock* join = CreateJoin(other, current_block(), stmt->id());
2350 set_current_block(join);
2486 } 2351 }
2487 } 2352 }
2488 2353
2489 2354
2355 HBasicBlock* HGraphBuilder::BreakAndContinueScope::Get(
2356 BreakableStatement* stmt,
2357 BreakType type) {
2358 BreakAndContinueScope* current = this;
2359 while (current != NULL && current->info()->target() != stmt) {
2360 current = current->next();
2361 }
2362 ASSERT(current != NULL); // Always found (unless stack is malformed).
2363 HBasicBlock* block = NULL;
2364 switch (type) {
2365 case BREAK:
2366 block = current->info()->break_block();
2367 if (block == NULL) {
2368 block = current->owner()->graph()->CreateBasicBlock();
2369 current->info()->set_break_block(block);
2370 }
2371 break;
2372
2373 case CONTINUE:
2374 block = current->info()->continue_block();
2375 if (block == NULL) {
2376 block = current->owner()->graph()->CreateBasicBlock();
2377 current->info()->set_continue_block(block);
2378 }
2379 break;
2380 }
2381
2382 return block;
2383 }
2384
2385
2490 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { 2386 void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
2491 current_subgraph_->FinishBreakContinue(stmt->target(), true); 2387 HBasicBlock* continue_block = break_scope()->Get(stmt->target(), CONTINUE);
2388 current_block()->Goto(continue_block);
2389 set_current_block(NULL);
2492 } 2390 }
2493 2391
2494 2392
2495 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { 2393 void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
2496 current_subgraph_->FinishBreakContinue(stmt->target(), false); 2394 HBasicBlock* break_block = break_scope()->Get(stmt->target(), BREAK);
2395 current_block()->Goto(break_block);
2396 set_current_block(NULL);
2497 } 2397 }
2498 2398
2499 2399
2500 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { 2400 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
2501 AstContext* context = call_context(); 2401 AstContext* context = call_context();
2502 if (context == NULL) { 2402 if (context == NULL) {
2503 // Not an inlined return, so an actual one. 2403 // Not an inlined return, so an actual one.
2504 VISIT_FOR_VALUE(stmt->expression()); 2404 VISIT_FOR_VALUE(stmt->expression());
2505 HValue* result = environment()->Pop(); 2405 HValue* result = environment()->Pop();
2506 subgraph()->FinishExit(new HReturn(result)); 2406 current_block()->FinishExit(new HReturn(result));
2407 set_current_block(NULL);
2507 } else { 2408 } else {
2508 // Return from an inlined function, visit the subexpression in the 2409 // Return from an inlined function, visit the subexpression in the
2509 // expression context of the call. 2410 // expression context of the call.
2510 if (context->IsTest()) { 2411 if (context->IsTest()) {
2511 TestContext* test = TestContext::cast(context); 2412 TestContext* test = TestContext::cast(context);
2512 VisitForControl(stmt->expression(), 2413 VisitForControl(stmt->expression(),
2513 test->if_true(), 2414 test->if_true(),
2514 test->if_false()); 2415 test->if_false());
2515 } else { 2416 } else {
2516 HValue* return_value = NULL; 2417 HValue* return_value = NULL;
2517 if (context->IsEffect()) { 2418 if (context->IsEffect()) {
2518 VISIT_FOR_EFFECT(stmt->expression()); 2419 VISIT_FOR_EFFECT(stmt->expression());
2519 return_value = graph()->GetConstantUndefined(); 2420 return_value = graph()->GetConstantUndefined();
2520 } else { 2421 } else {
2521 ASSERT(context->IsValue()); 2422 ASSERT(context->IsValue());
2522 VISIT_FOR_VALUE(stmt->expression()); 2423 VISIT_FOR_VALUE(stmt->expression());
2523 return_value = environment()->Pop(); 2424 return_value = environment()->Pop();
2524 } 2425 }
2525 subgraph()->exit_block()->AddLeaveInlined(return_value, 2426 current_block()->AddLeaveInlined(return_value,
2526 function_return_); 2427 function_return_);
2527 subgraph()->set_exit_block(NULL); 2428 set_current_block(NULL);
2528 } 2429 }
2529 } 2430 }
2530 } 2431 }
2531 2432
2532 2433
2533 void HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { 2434 void HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
2534 BAILOUT("WithEnterStatement"); 2435 BAILOUT("WithEnterStatement");
2535 } 2436 }
2536 2437
2537 2438
2538 void HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) { 2439 void HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
2539 BAILOUT("WithExitStatement"); 2440 BAILOUT("WithExitStatement");
2540 } 2441 }
2541 2442
2542 2443
2543 HCompare* HGraphBuilder::BuildSwitchCompare(HSubgraph* subgraph, 2444 HCompare* HGraphBuilder::BuildSwitchCompare(HSubgraph* subgraph,
2544 HValue* switch_value, 2445 HValue* switch_value,
2545 CaseClause* clause) { 2446 CaseClause* clause) {
2546 AddToSubgraph(subgraph, clause->label()); 2447 AddToSubgraph(subgraph, clause->label());
2547 if (HasStackOverflow()) return NULL; 2448 if (HasStackOverflow()) return NULL;
2548 HValue* clause_value = subgraph->environment()->Pop(); 2449 HValue* clause_value = subgraph->exit_block()->last_environment()->Pop();
2549 HCompare* compare = new HCompare(switch_value, 2450 HCompare* compare = new HCompare(switch_value,
2550 clause_value, 2451 clause_value,
2551 Token::EQ_STRICT); 2452 Token::EQ_STRICT);
2552 compare->SetInputRepresentation(Representation::Integer32()); 2453 compare->SetInputRepresentation(Representation::Integer32());
2553 subgraph->exit_block()->AddInstruction(compare); 2454 subgraph->exit_block()->AddInstruction(compare);
2554 return compare; 2455 return compare;
2555 } 2456 }
2556 2457
2557 2458
2558 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { 2459 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2619 prev_compare_inst = BuildSwitchCompare(subgraph, switch_value, clause); 2520 prev_compare_inst = BuildSwitchCompare(subgraph, switch_value, clause);
2620 if (HasStackOverflow()) return; 2521 if (HasStackOverflow()) return;
2621 2522
2622 prev_graph = subgraph; 2523 prev_graph = subgraph;
2623 } 2524 }
2624 2525
2625 // Finish last comparison if there was at least one comparison. 2526 // Finish last comparison if there was at least one comparison.
2626 // last_false_block is the (empty) false-block of the last comparison. If 2527 // last_false_block is the (empty) false-block of the last comparison. If
2627 // there are no comparisons at all (a single default clause), it is just 2528 // there are no comparisons at all (a single default clause), it is just
2628 // the last block of the current subgraph. 2529 // the last block of the current subgraph.
2629 HBasicBlock* last_false_block = current_subgraph_->exit_block(); 2530 HBasicBlock* last_false_block = current_block();
2630 if (prev_graph != current_subgraph_) { 2531 if (prev_graph != current_subgraph_) {
2631 last_false_block = graph()->CreateBasicBlock(); 2532 last_false_block = graph()->CreateBasicBlock();
2632 HBasicBlock* empty = graph()->CreateBasicBlock(); 2533 HBasicBlock* empty = graph()->CreateBasicBlock();
2633 prev_graph->exit_block()->Finish(new HTest(prev_compare_inst, 2534 prev_graph->exit_block()->Finish(new HTest(prev_compare_inst,
2634 empty, 2535 empty,
2635 last_false_block)); 2536 last_false_block));
2636 } 2537 }
2637 2538
2638 // If we have a non-smi compare clause, we deoptimize after trying 2539 // If we have a non-smi compare clause, we deoptimize after trying
2639 // all the previous compares. 2540 // all the previous compares.
(...skipping 22 matching lines...) Expand all
2662 ASSERT(clause->IsSmiCompare()); 2563 ASSERT(clause->IsSmiCompare());
2663 // Connect with the corresponding comparison. 2564 // Connect with the corresponding comparison.
2664 subgraph = CreateEmptySubgraph(); 2565 subgraph = CreateEmptySubgraph();
2665 HBasicBlock* empty = 2566 HBasicBlock* empty =
2666 compare_graphs.at(i)->exit_block()->end()->FirstSuccessor(); 2567 compare_graphs.at(i)->exit_block()->end()->FirstSuccessor();
2667 empty->Finish(new HGoto(subgraph->entry_block())); 2568 empty->Finish(new HGoto(subgraph->entry_block()));
2668 } 2569 }
2669 } 2570 }
2670 2571
2671 // Check for fall-through from previous statement block. 2572 // Check for fall-through from previous statement block.
2672 if (previous_subgraph != NULL && previous_subgraph->HasExit()) { 2573 if (previous_subgraph != NULL && previous_subgraph->exit_block() != NULL) {
2673 if (subgraph == NULL) subgraph = CreateEmptySubgraph(); 2574 if (subgraph == NULL) subgraph = CreateEmptySubgraph();
2674 previous_subgraph->exit_block()-> 2575 previous_subgraph->exit_block()->
2675 Finish(new HGoto(subgraph->entry_block())); 2576 Finish(new HGoto(subgraph->entry_block()));
2676 } 2577 }
2677 2578
2678 if (subgraph != NULL) { 2579 if (subgraph != NULL) {
2679 ADD_TO_SUBGRAPH(subgraph, clause->statements()); 2580 BreakAndContinueInfo break_info(stmt);
2680 HBasicBlock* break_block = subgraph->BundleBreak(stmt); 2581 { BreakAndContinueScope push(&break_info, this);
2681 if (break_block != NULL) { 2582 ADD_TO_SUBGRAPH(subgraph, clause->statements());
2682 break_block->Finish(new HGoto(single_exit_block)); 2583 }
2584 if (break_info.break_block() != NULL) {
2585 break_info.break_block()->SetJoinId(stmt->ExitId());
2586 break_info.break_block()->Finish(new HGoto(single_exit_block));
2683 } 2587 }
2684 } 2588 }
2685 2589
2686 previous_subgraph = subgraph; 2590 previous_subgraph = subgraph;
2687 } 2591 }
2688 2592
2689 // If the last statement block has a fall-through, connect it to the 2593 // If the last statement block has a fall-through, connect it to the
2690 // single exit block. 2594 // single exit block.
2691 if (previous_subgraph != NULL && previous_subgraph->HasExit()) { 2595 if (previous_subgraph != NULL && previous_subgraph->exit_block() != NULL) {
2692 previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block)); 2596 previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block));
2693 } 2597 }
2694 2598
2695 // If there is no default clause finish the last comparison's false target. 2599 // If there is no default clause finish the last comparison's false target.
2696 if (!last_false_block->IsFinished()) { 2600 if (!last_false_block->IsFinished()) {
2697 last_false_block->Finish(new HGoto(single_exit_block)); 2601 last_false_block->Finish(new HGoto(single_exit_block));
2698 } 2602 }
2699 2603
2700 if (single_exit_block->HasPredecessor()) { 2604 if (single_exit_block->HasPredecessor()) {
2701 current_subgraph_->set_exit_block(single_exit_block); 2605 set_current_block(single_exit_block);
2702 } else { 2606 } else {
2703 current_subgraph_->set_exit_block(NULL); 2607 set_current_block(NULL);
2704 } 2608 }
2705 } 2609 }
2706 2610
2707 bool HGraph::HasOsrEntryAt(IterationStatement* statement) { 2611 bool HGraph::HasOsrEntryAt(IterationStatement* statement) {
2708 return statement->OsrEntryId() == info()->osr_ast_id(); 2612 return statement->OsrEntryId() == info()->osr_ast_id();
2709 } 2613 }
2710 2614
2711 2615
2712 void HSubgraph::PreProcessOsrEntry(IterationStatement* statement) { 2616 void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) {
2713 if (!graph()->HasOsrEntryAt(statement)) return; 2617 if (!graph()->HasOsrEntryAt(statement)) return;
2714 2618
2715 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); 2619 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock();
2716 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); 2620 HBasicBlock* osr_entry = graph()->CreateBasicBlock();
2717 HValue* true_value = graph()->GetConstantTrue(); 2621 HValue* true_value = graph()->GetConstantTrue();
2718 HTest* test = new HTest(true_value, non_osr_entry, osr_entry); 2622 HTest* test = new HTest(true_value, non_osr_entry, osr_entry);
2719 exit_block()->Finish(test); 2623 current_block()->Finish(test);
2720 2624
2721 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); 2625 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock();
2722 non_osr_entry->Goto(loop_predecessor); 2626 non_osr_entry->Goto(loop_predecessor);
2723 2627
2628 set_current_block(osr_entry);
2724 int osr_entry_id = statement->OsrEntryId(); 2629 int osr_entry_id = statement->OsrEntryId();
2725 // We want the correct environment at the OsrEntry instruction. Build 2630 // We want the correct environment at the OsrEntry instruction. Build
2726 // it explicitly. The expression stack should be empty. 2631 // it explicitly. The expression stack should be empty.
2727 int count = osr_entry->last_environment()->length(); 2632 int count = environment()->length();
2728 ASSERT(count == (osr_entry->last_environment()->parameter_count() + 2633 ASSERT(count ==
2729 osr_entry->last_environment()->local_count())); 2634 (environment()->parameter_count() + environment()->local_count()));
2730 for (int i = 0; i < count; ++i) { 2635 for (int i = 0; i < count; ++i) {
2731 HUnknownOSRValue* unknown = new HUnknownOSRValue; 2636 HUnknownOSRValue* unknown = new HUnknownOSRValue;
2732 osr_entry->AddInstruction(unknown); 2637 AddInstruction(unknown);
2733 osr_entry->last_environment()->Bind(i, unknown); 2638 environment()->Bind(i, unknown);
2734 } 2639 }
2735 2640
2736 osr_entry->AddSimulate(osr_entry_id); 2641 AddSimulate(osr_entry_id);
2737 osr_entry->AddInstruction(new HOsrEntry(osr_entry_id)); 2642 AddInstruction(new HOsrEntry(osr_entry_id));
2738 osr_entry->Goto(loop_predecessor); 2643 current_block()->Goto(loop_predecessor);
2739 loop_predecessor->SetJoinId(statement->EntryId()); 2644 loop_predecessor->SetJoinId(statement->EntryId());
2740 set_exit_block(loop_predecessor); 2645 set_current_block(loop_predecessor);
2741 } 2646 }
2742 2647
2743 2648
2744 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { 2649 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
2745 ASSERT(subgraph()->HasExit()); 2650 ASSERT(current_block() != NULL);
2746 subgraph()->PreProcessOsrEntry(stmt); 2651 PreProcessOsrEntry(stmt);
2652 HBasicBlock* loop_entry = CreateLoopHeaderBlock();
2653 current_block()->Goto(loop_entry, false);
2654 set_current_block(loop_entry);
2747 2655
2748 HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment()); 2656 BreakAndContinueInfo break_info(stmt);
2749 ADD_TO_SUBGRAPH(body_graph, stmt->body()); 2657 { BreakAndContinueScope push(&break_info, this);
2750 body_graph->ResolveContinue(stmt); 2658 Visit(stmt->body());
2751 2659 CHECK_BAILOUT;
2752 if (!body_graph->HasExit() || stmt->cond()->ToBooleanIsTrue()) {
2753 current_subgraph_->AppendEndless(body_graph, stmt);
2754 } else {
2755 HSubgraph* go_back = CreateEmptySubgraph();
2756 HSubgraph* exit = CreateEmptySubgraph();
2757 {
2758 SubgraphScope scope(this, body_graph);
2759 VISIT_FOR_CONTROL(stmt->cond(),
2760 go_back->entry_block(),
2761 exit->entry_block());
2762 go_back->entry_block()->SetJoinId(stmt->BackEdgeId());
2763 exit->entry_block()->SetJoinId(stmt->ExitId());
2764 }
2765 current_subgraph_->AppendDoWhile(body_graph, stmt, go_back, exit);
2766 } 2660 }
2767 } 2661 HBasicBlock* body_exit =
2768 2662 JoinContinue(stmt, current_block(), break_info.continue_block());
2769 2663 HBasicBlock* loop_successor = NULL;
2770 bool HGraphBuilder::ShouldPeel(HSubgraph* cond, HSubgraph* body) { 2664 if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) {
2771 return FLAG_use_peeling; 2665 set_current_block(body_exit);
2666 // The block for a true condition, the actual predecessor block of the
2667 // back edge.
2668 body_exit = graph()->CreateBasicBlock();
2669 loop_successor = graph()->CreateBasicBlock();
2670 VISIT_FOR_CONTROL(stmt->cond(), body_exit, loop_successor);
2671 body_exit->SetJoinId(stmt->BackEdgeId());
2672 loop_successor->SetJoinId(stmt->ExitId());
2673 }
2674 HBasicBlock* loop_exit = CreateLoop(stmt,
2675 loop_entry,
2676 body_exit,
2677 loop_successor,
2678 break_info.break_block());
2679 set_current_block(loop_exit);
2772 } 2680 }
2773 2681
2774 2682
2775 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { 2683 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
2776 ASSERT(subgraph()->HasExit()); 2684 ASSERT(current_block() != NULL);
2777 subgraph()->PreProcessOsrEntry(stmt); 2685 PreProcessOsrEntry(stmt);
2686 HBasicBlock* loop_entry = CreateLoopHeaderBlock();
2687 current_block()->Goto(loop_entry, false);
2688 set_current_block(loop_entry);
2778 2689
2779 HSubgraph* cond_graph = NULL; 2690 // If the condition is constant true, do not generate a branch.
2780 HSubgraph* body_graph = NULL; 2691 HBasicBlock* loop_successor = NULL;
2781 HSubgraph* exit_graph = NULL; 2692 if (!stmt->cond()->ToBooleanIsTrue()) {
2782 2693 HBasicBlock* body_entry = graph()->CreateBasicBlock();
2783 // If the condition is constant true, do not generate a condition subgraph. 2694 loop_successor = graph()->CreateBasicBlock();
2784 if (stmt->cond()->ToBooleanIsTrue()) { 2695 VISIT_FOR_CONTROL(stmt->cond(), body_entry, loop_successor);
2785 body_graph = CreateLoopHeaderSubgraph(environment()); 2696 body_entry->SetJoinId(stmt->BodyId());
2786 ADD_TO_SUBGRAPH(body_graph, stmt->body()); 2697 loop_successor->SetJoinId(stmt->ExitId());
2787 } else { 2698 set_current_block(body_entry);
2788 cond_graph = CreateLoopHeaderSubgraph(environment());
2789 body_graph = CreateEmptySubgraph();
2790 exit_graph = CreateEmptySubgraph();
2791 {
2792 SubgraphScope scope(this, cond_graph);
2793 VISIT_FOR_CONTROL(stmt->cond(),
2794 body_graph->entry_block(),
2795 exit_graph->entry_block());
2796 body_graph->entry_block()->SetJoinId(stmt->BodyId());
2797 exit_graph->entry_block()->SetJoinId(stmt->ExitId());
2798 }
2799 ADD_TO_SUBGRAPH(body_graph, stmt->body());
2800 } 2699 }
2801 2700
2802 body_graph->ResolveContinue(stmt); 2701 BreakAndContinueInfo break_info(stmt);
2803 2702 { BreakAndContinueScope push(&break_info, this);
2804 if (cond_graph != NULL) { 2703 Visit(stmt->body());
2805 AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph); 2704 CHECK_BAILOUT;
2806 } else {
2807 // TODO(fschneider): Implement peeling for endless loops as well.
2808 current_subgraph_->AppendEndless(body_graph, stmt);
2809 } 2705 }
2810 } 2706 HBasicBlock* body_exit =
2811 2707 JoinContinue(stmt, current_block(), break_info.continue_block());
2812 2708 HBasicBlock* loop_exit = CreateLoop(stmt,
2813 void HGraphBuilder::AppendPeeledWhile(IterationStatement* stmt, 2709 loop_entry,
2814 HSubgraph* cond_graph, 2710 body_exit,
2815 HSubgraph* body_graph, 2711 loop_successor,
2816 HSubgraph* exit_graph) { 2712 break_info.break_block());
2817 HSubgraph* loop = NULL; 2713 set_current_block(loop_exit);
2818 if (body_graph->HasExit() && stmt != peeled_statement_ &&
2819 ShouldPeel(cond_graph, body_graph)) {
2820 // Save the last peeled iteration statement to prevent infinite recursion.
2821 IterationStatement* outer_peeled_statement = peeled_statement_;
2822 peeled_statement_ = stmt;
2823 loop = CreateGotoSubgraph(body_graph->environment());
2824 ADD_TO_SUBGRAPH(loop, stmt);
2825 peeled_statement_ = outer_peeled_statement;
2826 }
2827 current_subgraph_->AppendWhile(cond_graph, body_graph, stmt, loop,
2828 exit_graph);
2829 } 2714 }
2830 2715
2831 2716
2832 void HGraphBuilder::VisitForStatement(ForStatement* stmt) { 2717 void HGraphBuilder::VisitForStatement(ForStatement* stmt) {
2833 // Only visit the init statement in the peeled part of the loop. 2718 if (stmt->init() != NULL) {
2834 if (stmt->init() != NULL && peeled_statement_ != stmt) {
2835 Visit(stmt->init()); 2719 Visit(stmt->init());
2836 CHECK_BAILOUT; 2720 CHECK_BAILOUT;
2837 } 2721 }
2838 ASSERT(subgraph()->HasExit()); 2722 ASSERT(current_block() != NULL);
2839 subgraph()->PreProcessOsrEntry(stmt); 2723 PreProcessOsrEntry(stmt);
2724 HBasicBlock* loop_entry = CreateLoopHeaderBlock();
2725 current_block()->Goto(loop_entry, false);
2726 set_current_block(loop_entry);
2840 2727
2841 HSubgraph* cond_graph = NULL; 2728 HBasicBlock* loop_successor = NULL;
2842 HSubgraph* body_graph = NULL;
2843 HSubgraph* exit_graph = NULL;
2844 if (stmt->cond() != NULL) { 2729 if (stmt->cond() != NULL) {
2845 cond_graph = CreateLoopHeaderSubgraph(environment()); 2730 HBasicBlock* body_entry = graph()->CreateBasicBlock();
2846 body_graph = CreateEmptySubgraph(); 2731 loop_successor = graph()->CreateBasicBlock();
2847 exit_graph = CreateEmptySubgraph(); 2732 VISIT_FOR_CONTROL(stmt->cond(), body_entry, loop_successor);
2848 { 2733 body_entry->SetJoinId(stmt->BodyId());
2849 SubgraphScope scope(this, cond_graph); 2734 loop_successor->SetJoinId(stmt->ExitId());
2850 VISIT_FOR_CONTROL(stmt->cond(), 2735 set_current_block(body_entry);
2851 body_graph->entry_block(),
2852 exit_graph->entry_block());
2853 body_graph->entry_block()->SetJoinId(stmt->BodyId());
2854 exit_graph->entry_block()->SetJoinId(stmt->ExitId());
2855 }
2856 } else {
2857 body_graph = CreateLoopHeaderSubgraph(environment());
2858 }
2859 ADD_TO_SUBGRAPH(body_graph, stmt->body());
2860
2861 HSubgraph* next_graph = NULL;
2862 body_graph->ResolveContinue(stmt);
2863
2864 if (stmt->next() != NULL && body_graph->HasExit()) {
2865 next_graph = CreateGotoSubgraph(body_graph->environment());
2866 ADD_TO_SUBGRAPH(next_graph, stmt->next());
2867 body_graph->Append(next_graph, NULL);
2868 next_graph->entry_block()->SetJoinId(stmt->ContinueId());
2869 } 2736 }
2870 2737
2871 if (cond_graph != NULL) { 2738 BreakAndContinueInfo break_info(stmt);
2872 AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph); 2739 { BreakAndContinueScope push(&break_info, this);
2873 } else { 2740 Visit(stmt->body());
2874 current_subgraph_->AppendEndless(body_graph, stmt); 2741 CHECK_BAILOUT;
2875 } 2742 }
2743 HBasicBlock* body_exit =
2744 JoinContinue(stmt, current_block(), break_info.continue_block());
2745
2746 if (stmt->next() != NULL && body_exit != NULL) {
2747 set_current_block(body_exit);
2748 Visit(stmt->next());
2749 CHECK_BAILOUT;
2750 body_exit = current_block();
2751 }
2752
2753 HBasicBlock* loop_exit = CreateLoop(stmt,
2754 loop_entry,
2755 body_exit,
2756 loop_successor,
2757 break_info.break_block());
2758 set_current_block(loop_exit);
2876 } 2759 }
2877 2760
2878 2761
2879 void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) { 2762 void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
2880 BAILOUT("ForInStatement"); 2763 BAILOUT("ForInStatement");
2881 } 2764 }
2882 2765
2883 2766
2884 void HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { 2767 void HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
2885 BAILOUT("TryCatchStatement"); 2768 BAILOUT("TryCatchStatement");
(...skipping 20 matching lines...) Expand all
2906 } 2789 }
2907 2790
2908 2791
2909 void HGraphBuilder::VisitSharedFunctionInfoLiteral( 2792 void HGraphBuilder::VisitSharedFunctionInfoLiteral(
2910 SharedFunctionInfoLiteral* expr) { 2793 SharedFunctionInfoLiteral* expr) {
2911 BAILOUT("SharedFunctionInfoLiteral"); 2794 BAILOUT("SharedFunctionInfoLiteral");
2912 } 2795 }
2913 2796
2914 2797
2915 void HGraphBuilder::VisitConditional(Conditional* expr) { 2798 void HGraphBuilder::VisitConditional(Conditional* expr) {
2916 HSubgraph* then_graph = CreateEmptySubgraph(); 2799 HBasicBlock* cond_true = graph()->CreateBasicBlock();
2917 HSubgraph* else_graph = CreateEmptySubgraph(); 2800 HBasicBlock* cond_false = graph()->CreateBasicBlock();
2918 VISIT_FOR_CONTROL(expr->condition(), 2801 VISIT_FOR_CONTROL(expr->condition(), cond_true, cond_false);
2919 then_graph->entry_block(), 2802 cond_true->SetJoinId(expr->ThenId());
2920 else_graph->entry_block()); 2803 cond_false->SetJoinId(expr->ElseId());
2921 2804
2922 then_graph->entry_block()->SetJoinId(expr->ThenId()); 2805 // TOOD(kmillikin): Visit the subexpressions in the same AST context as
2923 ADD_TO_SUBGRAPH(then_graph, expr->then_expression()); 2806 // the whole expression.
2807 set_current_block(cond_true);
2808 VISIT_FOR_VALUE(expr->then_expression());
2809 HBasicBlock* other = current_block();
2924 2810
2925 else_graph->entry_block()->SetJoinId(expr->ElseId()); 2811 set_current_block(cond_false);
2926 ADD_TO_SUBGRAPH(else_graph, expr->else_expression()); 2812 VISIT_FOR_VALUE(expr->else_expression());
2927 2813
2928 current_subgraph_->AppendJoin(then_graph, else_graph, expr); 2814 HBasicBlock* join = CreateJoin(other, current_block(), expr->id());
2815 set_current_block(join);
2929 ast_context()->ReturnValue(Pop()); 2816 ast_context()->ReturnValue(Pop());
2930 } 2817 }
2931 2818
2932 2819
2933 void HGraphBuilder::LookupGlobalPropertyCell(Variable* var, 2820 void HGraphBuilder::LookupGlobalPropertyCell(Variable* var,
2934 LookupResult* lookup, 2821 LookupResult* lookup,
2935 bool is_store) { 2822 bool is_store) {
2936 if (var->is_this()) { 2823 if (var->is_this()) {
2937 BAILOUT("global this reference"); 2824 BAILOUT("global this reference");
2938 } 2825 }
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
3015 2902
3016 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { 2903 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
3017 HRegExpLiteral* instr = new HRegExpLiteral(expr->pattern(), 2904 HRegExpLiteral* instr = new HRegExpLiteral(expr->pattern(),
3018 expr->flags(), 2905 expr->flags(),
3019 expr->literal_index()); 2906 expr->literal_index());
3020 ast_context()->ReturnInstruction(instr, expr->id()); 2907 ast_context()->ReturnInstruction(instr, expr->id());
3021 } 2908 }
3022 2909
3023 2910
3024 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { 2911 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
3025 HObjectLiteral* literal = (new HObjectLiteral(expr->constant_properties(), 2912 HContext* context = new HContext;
2913 AddInstruction(context);
2914 HObjectLiteral* literal = (new HObjectLiteral(context,
2915 expr->constant_properties(),
3026 expr->fast_elements(), 2916 expr->fast_elements(),
3027 expr->literal_index(), 2917 expr->literal_index(),
3028 expr->depth())); 2918 expr->depth()));
3029 // The object is expected in the bailout environment during computation 2919 // The object is expected in the bailout environment during computation
3030 // of the property values and is the value of the entire expression. 2920 // of the property values and is the value of the entire expression.
3031 PushAndAdd(literal); 2921 PushAndAdd(literal);
3032 2922
3033 expr->CalculateEmitStore(); 2923 expr->CalculateEmitStore();
3034 2924
3035 for (int i = 0; i < expr->properties()->length(); i++) { 2925 for (int i = 0; i < expr->properties()->length(); i++) {
3036 ObjectLiteral::Property* property = expr->properties()->at(i); 2926 ObjectLiteral::Property* property = expr->properties()->at(i);
3037 if (property->IsCompileTimeValue()) continue; 2927 if (property->IsCompileTimeValue()) continue;
3038 2928
3039 Literal* key = property->key(); 2929 Literal* key = property->key();
3040 Expression* value = property->value(); 2930 Expression* value = property->value();
3041 2931
3042 switch (property->kind()) { 2932 switch (property->kind()) {
3043 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 2933 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
3044 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 2934 ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
3045 // Fall through. 2935 // Fall through.
3046 case ObjectLiteral::Property::COMPUTED: 2936 case ObjectLiteral::Property::COMPUTED:
3047 if (key->handle()->IsSymbol()) { 2937 if (key->handle()->IsSymbol()) {
3048 if (property->emit_store()) { 2938 if (property->emit_store()) {
3049 VISIT_FOR_VALUE(value); 2939 VISIT_FOR_VALUE(value);
3050 HValue* value = Pop(); 2940 HValue* value = Pop();
3051 Handle<String> name = Handle<String>::cast(key->handle()); 2941 Handle<String> name = Handle<String>::cast(key->handle());
3052 AddInstruction(new HStoreNamedGeneric(literal, name, value)); 2942 HStoreNamedGeneric* store =
2943 new HStoreNamedGeneric(context, literal, name, value);
2944 AddInstruction(store);
3053 AddSimulate(key->id()); 2945 AddSimulate(key->id());
3054 } else { 2946 } else {
3055 VISIT_FOR_EFFECT(value); 2947 VISIT_FOR_EFFECT(value);
3056 } 2948 }
3057 break; 2949 break;
3058 } 2950 }
3059 // Fall through. 2951 // Fall through.
3060 case ObjectLiteral::Property::PROTOTYPE: 2952 case ObjectLiteral::Property::PROTOTYPE:
3061 case ObjectLiteral::Property::SETTER: 2953 case ObjectLiteral::Property::SETTER:
3062 case ObjectLiteral::Property::GETTER: 2954 case ObjectLiteral::Property::GETTER:
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
3105 } 2997 }
3106 ast_context()->ReturnValue(Pop()); 2998 ast_context()->ReturnValue(Pop());
3107 } 2999 }
3108 3000
3109 3001
3110 void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { 3002 void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
3111 BAILOUT("CatchExtensionObject"); 3003 BAILOUT("CatchExtensionObject");
3112 } 3004 }
3113 3005
3114 3006
3115 HBasicBlock* HGraphBuilder::BuildTypeSwitch(ZoneMapList* maps, 3007 HBasicBlock* HGraphBuilder::BuildTypeSwitch(HValue* receiver,
3116 ZoneList<HSubgraph*>* subgraphs, 3008 ZoneMapList* maps,
3117 HValue* receiver, 3009 ZoneList<HSubgraph*>* body_graphs,
3010 HSubgraph* default_graph,
3118 int join_id) { 3011 int join_id) {
3119 ASSERT(subgraphs->length() == (maps->length() + 1)); 3012 ASSERT(maps->length() == body_graphs->length());
3013 HBasicBlock* join_block = graph()->CreateBasicBlock();
3014 AddInstruction(new HCheckNonSmi(receiver));
3120 3015
3121 // Build map compare subgraphs for all but the first map. 3016 for (int i = 0; i < maps->length(); ++i) {
3122 ZoneList<HSubgraph*> map_compare_subgraphs(maps->length() - 1); 3017 // Build the branches, connect all the target subgraphs to the join
3123 for (int i = maps->length() - 1; i > 0; --i) { 3018 // block. Use the default as a target of the last branch.
3124 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3019 HSubgraph* if_true = body_graphs->at(i);
3125 SubgraphScope scope(this, subgraph); 3020 HSubgraph* if_false = (i == maps->length() - 1)
3126 HSubgraph* else_subgraph = 3021 ? default_graph
3127 (i == (maps->length() - 1)) 3022 : CreateBranchSubgraph(environment());
3128 ? subgraphs->last() 3023 HCompareMap* compare =
3129 : map_compare_subgraphs.last(); 3024 new HCompareMap(receiver,
3130 HCompareMap* compare = new HCompareMap(receiver, 3025 maps->at(i),
3131 maps->at(i), 3026 if_true->entry_block(),
3132 subgraphs->at(i)->entry_block(), 3027 if_false->entry_block());
3133 else_subgraph->entry_block()); 3028 current_block()->Finish(compare);
3134 current_subgraph_->exit_block()->Finish(compare); 3029
3135 map_compare_subgraphs.Add(subgraph); 3030 if (if_true->exit_block() != NULL) {
3031 // In an effect context the value of the type switch is not needed.
3032 // There is no need to merge it at the join block only to discard it.
3033 if (ast_context()->IsEffect()) {
3034 if_true->exit_block()->last_environment()->Drop(1);
3035 }
3036 if_true->exit_block()->Goto(join_block);
3037 }
3038
3039 set_current_block(if_false->exit_block());
3136 } 3040 }
3137 3041
3138 // Generate first map check to end the current block. 3042 // Connect the default if necessary.
3139 AddInstruction(new HCheckNonSmi(receiver)); 3043 if (current_block() != NULL) {
3140 HSubgraph* else_subgraph = 3044 if (ast_context()->IsEffect()) {
3141 (maps->length() == 1) ? subgraphs->at(1) : map_compare_subgraphs.last(); 3045 environment()->Drop(1);
3142 HCompareMap* compare = new HCompareMap(receiver,
3143 Handle<Map>(maps->first()),
3144 subgraphs->first()->entry_block(),
3145 else_subgraph->entry_block());
3146 current_subgraph_->exit_block()->Finish(compare);
3147
3148 // Join all the call subgraphs in a new basic block and make
3149 // this basic block the current basic block.
3150 HBasicBlock* join_block = graph_->CreateBasicBlock();
3151 for (int i = 0; i < subgraphs->length(); ++i) {
3152 HSubgraph* subgraph = subgraphs->at(i);
3153 if (subgraph->HasExit()) {
3154 // In an effect context the value of the type switch is not needed.
3155 // There is no need to merge it at the join block only to discard it.
3156 HBasicBlock* subgraph_exit = subgraph->exit_block();
3157 if (ast_context()->IsEffect()) {
3158 subgraph_exit->last_environment()->Drop(1);
3159 }
3160 subgraph_exit->Goto(join_block);
3161 } 3046 }
3047 current_block()->Goto(join_block);
3162 } 3048 }
3163 3049
3164 if (join_block->predecessors()->is_empty()) return NULL; 3050 if (join_block->predecessors()->is_empty()) return NULL;
3165 join_block->SetJoinId(join_id); 3051 join_block->SetJoinId(join_id);
3166 return join_block; 3052 return join_block;
3167 } 3053 }
3168 3054
3169 3055
3170 // Sets the lookup result and returns true if the store can be inlined. 3056 // Sets the lookup result and returns true if the store can be inlined.
3171 static bool ComputeStoredField(Handle<Map> type, 3057 static bool ComputeStoredField(Handle<Map> type,
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
3222 // enable elimination of redundant checks after the transition store. 3108 // enable elimination of redundant checks after the transition store.
3223 instr->SetFlag(HValue::kChangesMaps); 3109 instr->SetFlag(HValue::kChangesMaps);
3224 } 3110 }
3225 return instr; 3111 return instr;
3226 } 3112 }
3227 3113
3228 3114
3229 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, 3115 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object,
3230 Handle<String> name, 3116 Handle<String> name,
3231 HValue* value) { 3117 HValue* value) {
3232 return new HStoreNamedGeneric(object, name, value); 3118 HContext* context = new HContext;
3119 AddInstruction(context);
3120 return new HStoreNamedGeneric(context, object, name, value);
3233 } 3121 }
3234 3122
3235 3123
3236 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, 3124 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
3237 HValue* value, 3125 HValue* value,
3238 Expression* expr) { 3126 Expression* expr) {
3239 Property* prop = (expr->AsProperty() != NULL) 3127 Property* prop = (expr->AsProperty() != NULL)
3240 ? expr->AsProperty() 3128 ? expr->AsProperty()
3241 : expr->AsAssignment()->target()->AsProperty(); 3129 : expr->AsAssignment()->target()->AsProperty();
3242 Literal* key = prop->key()->AsLiteral(); 3130 Literal* key = prop->key()->AsLiteral();
(...skipping 12 matching lines...) Expand all
3255 } 3143 }
3256 3144
3257 3145
3258 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, 3146 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
3259 HValue* object, 3147 HValue* object,
3260 HValue* value, 3148 HValue* value,
3261 ZoneMapList* types, 3149 ZoneMapList* types,
3262 Handle<String> name) { 3150 Handle<String> name) {
3263 int number_of_types = Min(types->length(), kMaxStorePolymorphism); 3151 int number_of_types = Min(types->length(), kMaxStorePolymorphism);
3264 ZoneMapList maps(number_of_types); 3152 ZoneMapList maps(number_of_types);
3265 ZoneList<HSubgraph*> subgraphs(number_of_types + 1); 3153 ZoneList<HSubgraph*> subgraphs(number_of_types);
3266 bool needs_generic = (types->length() > kMaxStorePolymorphism); 3154 bool needs_generic = (types->length() > kMaxStorePolymorphism);
3267 3155
3268 // Build subgraphs for each of the specific maps. 3156 // Build subgraphs for each of the specific maps.
3269 // 3157 //
3270 // TODO(ager): We should recognize when the prototype chains for 3158 // TODO(ager): We should recognize when the prototype chains for
3271 // different maps are identical. In that case we can avoid 3159 // different maps are identical. In that case we can avoid
3272 // repeatedly generating the same prototype map checks. 3160 // repeatedly generating the same prototype map checks.
3273 for (int i = 0; i < number_of_types; ++i) { 3161 for (int i = 0; i < number_of_types; ++i) {
3274 Handle<Map> map = types->at(i); 3162 Handle<Map> map = types->at(i);
3275 LookupResult lookup; 3163 LookupResult lookup;
3276 if (ComputeStoredField(map, name, &lookup)) { 3164 if (ComputeStoredField(map, name, &lookup)) {
3277 maps.Add(map);
3278 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3165 HSubgraph* subgraph = CreateBranchSubgraph(environment());
3279 SubgraphScope scope(this, subgraph); 3166 SubgraphScope scope(this, subgraph);
3280 HInstruction* instr = 3167 HInstruction* instr =
3281 BuildStoreNamedField(object, name, value, map, &lookup, false); 3168 BuildStoreNamedField(object, name, value, map, &lookup, false);
3282 Push(value); 3169 Push(value);
3283 instr->set_position(expr->position()); 3170 instr->set_position(expr->position());
3284 AddInstruction(instr); 3171 AddInstruction(instr);
3172 maps.Add(map);
3285 subgraphs.Add(subgraph); 3173 subgraphs.Add(subgraph);
3286 } else { 3174 } else {
3287 needs_generic = true; 3175 needs_generic = true;
3288 } 3176 }
3289 } 3177 }
3290 3178
3291 // If none of the properties were named fields we generate a 3179 // If none of the properties were named fields we generate a
3292 // generic store. 3180 // generic store.
3293 if (maps.length() == 0) { 3181 if (maps.length() == 0) {
3294 HInstruction* instr = new HStoreNamedGeneric(object, name, value); 3182 HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
3295 Push(value); 3183 Push(value);
3296 instr->set_position(expr->position()); 3184 instr->set_position(expr->position());
3297 AddInstruction(instr); 3185 AddInstruction(instr);
3298 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3186 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3299 ast_context()->ReturnValue(Pop()); 3187 ast_context()->ReturnValue(Pop());
3300 } else { 3188 } else {
3301 // Build subgraph for generic store through IC. 3189 // Build subgraph for generic store through IC.
3302 { 3190 HSubgraph* default_graph = CreateBranchSubgraph(environment());
3303 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3191 { SubgraphScope scope(this, default_graph);
3304 SubgraphScope scope(this, subgraph);
3305 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { 3192 if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3306 subgraph->FinishExit(new HDeoptimize()); 3193 default_graph->exit_block()->FinishExit(new HDeoptimize());
3194 default_graph->set_exit_block(NULL);
3307 } else { 3195 } else {
3308 HInstruction* instr = new HStoreNamedGeneric(object, name, value); 3196 HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
3309 Push(value); 3197 Push(value);
3310 instr->set_position(expr->position()); 3198 instr->set_position(expr->position());
3311 AddInstruction(instr); 3199 AddInstruction(instr);
3312 } 3200 }
3313 subgraphs.Add(subgraph);
3314 } 3201 }
3315 3202
3316 HBasicBlock* new_exit_block = 3203 HBasicBlock* new_exit_block =
3317 BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); 3204 BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id());
3318 subgraph()->set_exit_block(new_exit_block); 3205 set_current_block(new_exit_block);
3319 // In an effect context, we did not materialized the value in the 3206 // In an effect context, we did not materialized the value in the
3320 // predecessor environments so there's no need to handle it here. 3207 // predecessor environments so there's no need to handle it here.
3321 if (subgraph()->HasExit() && !ast_context()->IsEffect()) { 3208 if (current_block() != NULL && !ast_context()->IsEffect()) {
3322 ast_context()->ReturnValue(Pop()); 3209 ast_context()->ReturnValue(Pop());
3323 } 3210 }
3324 } 3211 }
3325 } 3212 }
3326 3213
3327 3214
3328 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { 3215 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
3329 Property* prop = expr->target()->AsProperty(); 3216 Property* prop = expr->target()->AsProperty();
3330 ASSERT(prop != NULL); 3217 ASSERT(prop != NULL);
3331 expr->RecordTypeFeedback(oracle()); 3218 expr->RecordTypeFeedback(oracle());
(...skipping 16 matching lines...) Expand all
3348 LookupResult lookup; 3235 LookupResult lookup;
3349 3236
3350 if (expr->IsMonomorphic()) { 3237 if (expr->IsMonomorphic()) {
3351 instr = BuildStoreNamed(object, value, expr); 3238 instr = BuildStoreNamed(object, value, expr);
3352 3239
3353 } else if (types != NULL && types->length() > 1) { 3240 } else if (types != NULL && types->length() > 1) {
3354 HandlePolymorphicStoreNamedField(expr, object, value, types, name); 3241 HandlePolymorphicStoreNamedField(expr, object, value, types, name);
3355 return; 3242 return;
3356 3243
3357 } else { 3244 } else {
3358 instr = new HStoreNamedGeneric(object, name, value); 3245 instr = BuildStoreNamedGeneric(object, name, value);
3359 } 3246 }
3360 3247
3361 } else { 3248 } else {
3362 // Keyed store. 3249 // Keyed store.
3363 VISIT_FOR_VALUE(prop->key()); 3250 VISIT_FOR_VALUE(prop->key());
3364 VISIT_FOR_VALUE(expr->value()); 3251 VISIT_FOR_VALUE(expr->value());
3365 value = Pop(); 3252 value = Pop();
3366 HValue* key = Pop(); 3253 HValue* key = Pop();
3367 HValue* object = Pop(); 3254 HValue* object = Pop();
3368 3255
3369 bool is_fast_elements = expr->IsMonomorphic() && 3256 if (expr->IsMonomorphic()) {
3370 expr->GetMonomorphicReceiverType()->has_fast_elements(); 3257 Handle<Map> receiver_type(expr->GetMonomorphicReceiverType());
3371 3258 // An object has either fast elements or pixel array elements, but never
3372 instr = is_fast_elements 3259 // both. Pixel array maps that are assigned to pixel array elements are
3373 ? BuildStoreKeyedFastElement(object, key, value, expr) 3260 // always created with the fast elements flag cleared.
3374 : BuildStoreKeyedGeneric(object, key, value); 3261 if (receiver_type->has_pixel_array_elements()) {
3262 instr = BuildStoreKeyedPixelArrayElement(object, key, value, expr);
3263 } else if (receiver_type->has_fast_elements()) {
3264 instr = BuildStoreKeyedFastElement(object, key, value, expr);
3265 }
3266 }
3267 if (instr == NULL) {
3268 instr = BuildStoreKeyedGeneric(object, key, value);
3269 }
3375 } 3270 }
3376 3271
3377 Push(value); 3272 Push(value);
3378 instr->set_position(expr->position()); 3273 instr->set_position(expr->position());
3379 AddInstruction(instr); 3274 AddInstruction(instr);
3380 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3275 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3381 ast_context()->ReturnValue(Pop()); 3276 ast_context()->ReturnValue(Pop());
3382 } 3277 }
3383 3278
3384 3279
(...skipping 23 matching lines...) Expand all
3408 VariableProxy* proxy = target->AsVariableProxy(); 3303 VariableProxy* proxy = target->AsVariableProxy();
3409 Variable* var = proxy->AsVariable(); 3304 Variable* var = proxy->AsVariable();
3410 Property* prop = target->AsProperty(); 3305 Property* prop = target->AsProperty();
3411 ASSERT(var == NULL || prop == NULL); 3306 ASSERT(var == NULL || prop == NULL);
3412 3307
3413 // We have a second position recorded in the FullCodeGenerator to have 3308 // We have a second position recorded in the FullCodeGenerator to have
3414 // type feedback for the binary operation. 3309 // type feedback for the binary operation.
3415 BinaryOperation* operation = expr->binary_operation(); 3310 BinaryOperation* operation = expr->binary_operation();
3416 3311
3417 if (var != NULL) { 3312 if (var != NULL) {
3418 if (!var->is_global() && !var->IsStackAllocated()) {
3419 BAILOUT("non-stack/non-global in compound assignment");
3420 }
3421
3422 VISIT_FOR_VALUE(operation); 3313 VISIT_FOR_VALUE(operation);
3423 3314
3424 if (var->is_global()) { 3315 if (var->is_global()) {
3425 HandleGlobalVariableAssignment(var, 3316 HandleGlobalVariableAssignment(var,
3426 Top(), 3317 Top(),
3427 expr->position(), 3318 expr->position(),
3428 expr->AssignmentId()); 3319 expr->AssignmentId());
3320 } else if (var->IsStackAllocated()) {
3321 Bind(var, Top());
3322 } else if (var->IsContextSlot()) {
3323 HValue* context = BuildContextChainWalk(var);
3324 int index = var->AsSlot()->index();
3325 HStoreContextSlot* instr = new HStoreContextSlot(context, index, Top());
3326 AddInstruction(instr);
3327 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3429 } else { 3328 } else {
3430 Bind(var, Top()); 3329 BAILOUT("compound assignment to lookup slot");
3431 } 3330 }
3432 ast_context()->ReturnValue(Pop()); 3331 ast_context()->ReturnValue(Pop());
3433 3332
3434 } else if (prop != NULL) { 3333 } else if (prop != NULL) {
3435 prop->RecordTypeFeedback(oracle()); 3334 prop->RecordTypeFeedback(oracle());
3436 3335
3437 if (prop->key()->IsPropertyName()) { 3336 if (prop->key()->IsPropertyName()) {
3438 // Named property. 3337 // Named property.
3439 VISIT_FOR_VALUE(prop->obj()); 3338 VISIT_FOR_VALUE(prop->obj());
3440 HValue* obj = Top(); 3339 HValue* obj = Top();
(...skipping 27 matching lines...) Expand all
3468 3367
3469 } else { 3368 } else {
3470 // Keyed property. 3369 // Keyed property.
3471 VISIT_FOR_VALUE(prop->obj()); 3370 VISIT_FOR_VALUE(prop->obj());
3472 VISIT_FOR_VALUE(prop->key()); 3371 VISIT_FOR_VALUE(prop->key());
3473 HValue* obj = environment()->ExpressionStackAt(1); 3372 HValue* obj = environment()->ExpressionStackAt(1);
3474 HValue* key = environment()->ExpressionStackAt(0); 3373 HValue* key = environment()->ExpressionStackAt(0);
3475 3374
3476 bool is_fast_elements = prop->IsMonomorphic() && 3375 bool is_fast_elements = prop->IsMonomorphic() &&
3477 prop->GetMonomorphicReceiverType()->has_fast_elements(); 3376 prop->GetMonomorphicReceiverType()->has_fast_elements();
3478
3479 HInstruction* load = is_fast_elements 3377 HInstruction* load = is_fast_elements
3480 ? BuildLoadKeyedFastElement(obj, key, prop) 3378 ? BuildLoadKeyedFastElement(obj, key, prop)
3481 : BuildLoadKeyedGeneric(obj, key); 3379 : BuildLoadKeyedGeneric(obj, key);
3482 PushAndAdd(load); 3380 PushAndAdd(load);
3483 if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); 3381 if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId());
3484 3382
3485 VISIT_FOR_VALUE(expr->value()); 3383 VISIT_FOR_VALUE(expr->value());
3486 HValue* right = Pop(); 3384 HValue* right = Pop();
3487 HValue* left = Pop(); 3385 HValue* left = Pop();
3488 3386
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
3573 // assignments, count operations, or for-in. Consequently throw can 3471 // assignments, count operations, or for-in. Consequently throw can
3574 // currently only occur in an effect context. 3472 // currently only occur in an effect context.
3575 ASSERT(ast_context()->IsEffect()); 3473 ASSERT(ast_context()->IsEffect());
3576 VISIT_FOR_VALUE(expr->exception()); 3474 VISIT_FOR_VALUE(expr->exception());
3577 3475
3578 HValue* value = environment()->Pop(); 3476 HValue* value = environment()->Pop();
3579 HThrow* instr = new HThrow(value); 3477 HThrow* instr = new HThrow(value);
3580 instr->set_position(expr->position()); 3478 instr->set_position(expr->position());
3581 AddInstruction(instr); 3479 AddInstruction(instr);
3582 AddSimulate(expr->id()); 3480 AddSimulate(expr->id());
3583 current_subgraph_->FinishExit(new HAbnormalExit); 3481 current_block()->FinishExit(new HAbnormalExit);
3482 set_current_block(NULL);
3584 } 3483 }
3585 3484
3586 3485
3587 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, 3486 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
3588 HValue* object, 3487 HValue* object,
3589 ZoneMapList* types, 3488 ZoneMapList* types,
3590 Handle<String> name) { 3489 Handle<String> name) {
3591 int number_of_types = Min(types->length(), kMaxLoadPolymorphism); 3490 int number_of_types = Min(types->length(), kMaxLoadPolymorphism);
3592 ZoneMapList maps(number_of_types); 3491 ZoneMapList maps(number_of_types);
3593 ZoneList<HSubgraph*> subgraphs(number_of_types + 1); 3492 ZoneList<HSubgraph*> subgraphs(number_of_types);
3594 bool needs_generic = (types->length() > kMaxLoadPolymorphism); 3493 bool needs_generic = (types->length() > kMaxLoadPolymorphism);
3595 3494
3596 // Build subgraphs for each of the specific maps. 3495 // Build subgraphs for each of the specific maps.
3597 // 3496 //
3598 // TODO(ager): We should recognize when the prototype chains for 3497 // TODO(ager): We should recognize when the prototype chains for
3599 // different maps are identical. In that case we can avoid 3498 // different maps are identical. In that case we can avoid
3600 // repeatedly generating the same prototype map checks. 3499 // repeatedly generating the same prototype map checks.
3601 for (int i = 0; i < number_of_types; ++i) { 3500 for (int i = 0; i < number_of_types; ++i) {
3602 Handle<Map> map = types->at(i); 3501 Handle<Map> map = types->at(i);
3603 LookupResult lookup; 3502 LookupResult lookup;
3604 map->LookupInDescriptors(NULL, *name, &lookup); 3503 map->LookupInDescriptors(NULL, *name, &lookup);
3605 if (lookup.IsProperty() && lookup.type() == FIELD) { 3504 if (lookup.IsProperty() && lookup.type() == FIELD) {
3606 maps.Add(map);
3607 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3505 HSubgraph* subgraph = CreateBranchSubgraph(environment());
3608 SubgraphScope scope(this, subgraph); 3506 SubgraphScope scope(this, subgraph);
3609 HLoadNamedField* instr = 3507 HLoadNamedField* instr =
3610 BuildLoadNamedField(object, expr, map, &lookup, false); 3508 BuildLoadNamedField(object, expr, map, &lookup, false);
3611 instr->set_position(expr->position()); 3509 instr->set_position(expr->position());
3612 instr->ClearFlag(HValue::kUseGVN); // Don't do GVN on polymorphic loads. 3510 instr->ClearFlag(HValue::kUseGVN); // Don't do GVN on polymorphic loads.
3613 PushAndAdd(instr); 3511 PushAndAdd(instr);
3512 maps.Add(map);
3614 subgraphs.Add(subgraph); 3513 subgraphs.Add(subgraph);
3615 } else { 3514 } else {
3616 needs_generic = true; 3515 needs_generic = true;
3617 } 3516 }
3618 } 3517 }
3619 3518
3620 // If none of the properties were named fields we generate a 3519 // If none of the properties were named fields we generate a
3621 // generic load. 3520 // generic load.
3622 if (maps.length() == 0) { 3521 if (maps.length() == 0) {
3623 HInstruction* instr = BuildLoadNamedGeneric(object, expr); 3522 HInstruction* instr = BuildLoadNamedGeneric(object, expr);
3624 instr->set_position(expr->position()); 3523 instr->set_position(expr->position());
3625 ast_context()->ReturnInstruction(instr, expr->id()); 3524 ast_context()->ReturnInstruction(instr, expr->id());
3626 } else { 3525 } else {
3627 // Build subgraph for generic load through IC. 3526 // Build subgraph for generic load through IC.
3628 { 3527 HSubgraph* default_graph = CreateBranchSubgraph(environment());
3629 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3528 { SubgraphScope scope(this, default_graph);
3630 SubgraphScope scope(this, subgraph);
3631 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { 3529 if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3632 subgraph->FinishExit(new HDeoptimize()); 3530 default_graph->exit_block()->FinishExit(new HDeoptimize());
3531 default_graph->set_exit_block(NULL);
3633 } else { 3532 } else {
3634 HInstruction* instr = BuildLoadNamedGeneric(object, expr); 3533 HInstruction* instr = BuildLoadNamedGeneric(object, expr);
3635 instr->set_position(expr->position()); 3534 instr->set_position(expr->position());
3636 PushAndAdd(instr); 3535 PushAndAdd(instr);
3637 } 3536 }
3638 subgraphs.Add(subgraph);
3639 } 3537 }
3640 3538
3641 HBasicBlock* new_exit_block = 3539 HBasicBlock* new_exit_block =
3642 BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); 3540 BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id());
3643 subgraph()->set_exit_block(new_exit_block); 3541 set_current_block(new_exit_block);
3644 // In an effect context, we did not materialized the value in the 3542 // In an effect context, we did not materialized the value in the
3645 // predecessor environments so there's no need to handle it here. 3543 // predecessor environments so there's no need to handle it here.
3646 if (subgraph()->HasExit() && !ast_context()->IsEffect()) { 3544 if (current_block() != NULL && !ast_context()->IsEffect()) {
3647 ast_context()->ReturnValue(Pop()); 3545 ast_context()->ReturnValue(Pop());
3648 } 3546 }
3649 } 3547 }
3650 } 3548 }
3651 3549
3652 3550
3653 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, 3551 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
3654 Property* expr, 3552 Property* expr,
3655 Handle<Map> type, 3553 Handle<Map> type,
3656 LookupResult* lookup, 3554 LookupResult* lookup,
(...skipping 14 matching lines...) Expand all
3671 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; 3569 int offset = (index * kPointerSize) + FixedArray::kHeaderSize;
3672 return new HLoadNamedField(object, false, offset); 3570 return new HLoadNamedField(object, false, offset);
3673 } 3571 }
3674 } 3572 }
3675 3573
3676 3574
3677 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj, 3575 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj,
3678 Property* expr) { 3576 Property* expr) {
3679 ASSERT(expr->key()->IsPropertyName()); 3577 ASSERT(expr->key()->IsPropertyName());
3680 Handle<Object> name = expr->key()->AsLiteral()->handle(); 3578 Handle<Object> name = expr->key()->AsLiteral()->handle();
3681 return new HLoadNamedGeneric(obj, name); 3579 HContext* context = new HContext;
3580 AddInstruction(context);
3581 return new HLoadNamedGeneric(context, obj, name);
3682 } 3582 }
3683 3583
3684 3584
3685 HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj, 3585 HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj,
3686 Property* expr, 3586 Property* expr,
3687 Handle<Map> map, 3587 Handle<Map> map,
3688 Handle<String> name) { 3588 Handle<String> name) {
3689 LookupResult lookup; 3589 LookupResult lookup;
3690 map->LookupInDescriptors(NULL, *name, &lookup); 3590 map->LookupInDescriptors(NULL, *name, &lookup);
3691 if (lookup.IsProperty() && lookup.type() == FIELD) { 3591 if (lookup.IsProperty() && lookup.type() == FIELD) {
3692 return BuildLoadNamedField(obj, 3592 return BuildLoadNamedField(obj,
3693 expr, 3593 expr,
3694 map, 3594 map,
3695 &lookup, 3595 &lookup,
3696 true); 3596 true);
3697 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) { 3597 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) {
3698 AddInstruction(new HCheckNonSmi(obj)); 3598 AddInstruction(new HCheckNonSmi(obj));
3699 AddInstruction(new HCheckMap(obj, map)); 3599 AddInstruction(new HCheckMap(obj, map));
3700 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); 3600 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map));
3701 return new HConstant(function, Representation::Tagged()); 3601 return new HConstant(function, Representation::Tagged());
3702 } else { 3602 } else {
3703 return BuildLoadNamedGeneric(obj, expr); 3603 return BuildLoadNamedGeneric(obj, expr);
3704 } 3604 }
3705 } 3605 }
3706 3606
3707 3607
3708 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 3608 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
3709 HValue* key) { 3609 HValue* key) {
3710 return new HLoadKeyedGeneric(object, key); 3610 HContext* context = new HContext;
3611 AddInstruction(context);
3612 return new HLoadKeyedGeneric(context, object, key);
3711 } 3613 }
3712 3614
3713 3615
3714 HInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object, 3616 HInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object,
3715 HValue* key, 3617 HValue* key,
3716 Property* expr) { 3618 Property* expr) {
3717 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); 3619 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic());
3718 AddInstruction(new HCheckNonSmi(object)); 3620 AddInstruction(new HCheckNonSmi(object));
3719 Handle<Map> map = expr->GetMonomorphicReceiverType(); 3621 Handle<Map> map = expr->GetMonomorphicReceiverType();
3720 ASSERT(map->has_fast_elements()); 3622 ASSERT(map->has_fast_elements());
3721 AddInstruction(new HCheckMap(object, map)); 3623 AddInstruction(new HCheckMap(object, map));
3722 bool is_array = (map->instance_type() == JS_ARRAY_TYPE); 3624 bool is_array = (map->instance_type() == JS_ARRAY_TYPE);
3723 HLoadElements* elements = new HLoadElements(object); 3625 HLoadElements* elements = new HLoadElements(object);
3724 HInstruction* length = NULL; 3626 HInstruction* length = NULL;
3725 if (is_array) { 3627 if (is_array) {
3726 length = AddInstruction(new HJSArrayLength(object)); 3628 length = AddInstruction(new HJSArrayLength(object));
3727 AddInstruction(new HBoundsCheck(key, length)); 3629 AddInstruction(new HBoundsCheck(key, length));
3728 AddInstruction(elements); 3630 AddInstruction(elements);
3729 } else { 3631 } else {
3730 AddInstruction(elements); 3632 AddInstruction(elements);
3731 length = AddInstruction(new HFixedArrayLength(elements)); 3633 length = AddInstruction(new HFixedArrayLength(elements));
3732 AddInstruction(new HBoundsCheck(key, length)); 3634 AddInstruction(new HBoundsCheck(key, length));
3733 } 3635 }
3734 return new HLoadKeyedFastElement(elements, key); 3636 return new HLoadKeyedFastElement(elements, key);
3735 } 3637 }
3736 3638
3737 3639
3640 HInstruction* HGraphBuilder::BuildLoadKeyedPixelArrayElement(HValue* object,
3641 HValue* key,
3642 Property* expr) {
3643 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic());
3644 AddInstruction(new HCheckNonSmi(object));
3645 Handle<Map> map = expr->GetMonomorphicReceiverType();
3646 ASSERT(!map->has_fast_elements());
3647 ASSERT(map->has_pixel_array_elements());
3648 AddInstruction(new HCheckMap(object, map));
3649 HLoadElements* elements = new HLoadElements(object);
3650 AddInstruction(elements);
3651 HInstruction* length = new HPixelArrayLength(elements);
3652 AddInstruction(length);
3653 AddInstruction(new HBoundsCheck(key, length));
3654 HLoadPixelArrayExternalPointer* external_elements =
3655 new HLoadPixelArrayExternalPointer(elements);
3656 AddInstruction(external_elements);
3657 HLoadPixelArrayElement* pixel_array_value =
3658 new HLoadPixelArrayElement(external_elements, key);
3659 return pixel_array_value;
3660 }
3661
3662
3738 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object, 3663 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object,
3739 HValue* key, 3664 HValue* key,
3740 HValue* value) { 3665 HValue* value) {
3741 return new HStoreKeyedGeneric(object, key, value); 3666 HContext* context = new HContext;
3667 AddInstruction(context);
3668 return new HStoreKeyedGeneric(context, object, key, value);
3742 } 3669 }
3743 3670
3744 3671
3745 HInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object, 3672 HInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object,
3746 HValue* key, 3673 HValue* key,
3747 HValue* val, 3674 HValue* val,
3748 Expression* expr) { 3675 Expression* expr) {
3749 ASSERT(expr->IsMonomorphic()); 3676 ASSERT(expr->IsMonomorphic());
3750 AddInstruction(new HCheckNonSmi(object)); 3677 AddInstruction(new HCheckNonSmi(object));
3751 Handle<Map> map = expr->GetMonomorphicReceiverType(); 3678 Handle<Map> map = expr->GetMonomorphicReceiverType();
3752 ASSERT(map->has_fast_elements()); 3679 ASSERT(map->has_fast_elements());
3753 AddInstruction(new HCheckMap(object, map)); 3680 AddInstruction(new HCheckMap(object, map));
3754 HInstruction* elements = AddInstruction(new HLoadElements(object)); 3681 HInstruction* elements = AddInstruction(new HLoadElements(object));
3755 AddInstruction(new HCheckMap(elements, FACTORY->fixed_array_map())); 3682 AddInstruction(new HCheckMap(elements, FACTORY->fixed_array_map()));
3756 bool is_array = (map->instance_type() == JS_ARRAY_TYPE); 3683 bool is_array = (map->instance_type() == JS_ARRAY_TYPE);
3757 HInstruction* length = NULL; 3684 HInstruction* length = NULL;
3758 if (is_array) { 3685 if (is_array) {
3759 length = AddInstruction(new HJSArrayLength(object)); 3686 length = AddInstruction(new HJSArrayLength(object));
3760 } else { 3687 } else {
3761 length = AddInstruction(new HFixedArrayLength(elements)); 3688 length = AddInstruction(new HFixedArrayLength(elements));
3762 } 3689 }
3763 AddInstruction(new HBoundsCheck(key, length)); 3690 AddInstruction(new HBoundsCheck(key, length));
3764 return new HStoreKeyedFastElement(elements, key, val); 3691 return new HStoreKeyedFastElement(elements, key, val);
3765 } 3692 }
3766 3693
3767 3694
3695 HInstruction* HGraphBuilder::BuildStoreKeyedPixelArrayElement(
3696 HValue* object,
3697 HValue* key,
3698 HValue* val,
3699 Expression* expr) {
3700 ASSERT(expr->IsMonomorphic());
3701 AddInstruction(new HCheckNonSmi(object));
3702 Handle<Map> map = expr->GetMonomorphicReceiverType();
3703 ASSERT(!map->has_fast_elements());
3704 ASSERT(map->has_pixel_array_elements());
3705 AddInstruction(new HCheckMap(object, map));
3706 HLoadElements* elements = new HLoadElements(object);
3707 AddInstruction(elements);
3708 HInstruction* length = AddInstruction(new HPixelArrayLength(elements));
3709 AddInstruction(new HBoundsCheck(key, length));
3710 HLoadPixelArrayExternalPointer* external_elements =
3711 new HLoadPixelArrayExternalPointer(elements);
3712 AddInstruction(external_elements);
3713 return new HStorePixelArrayElement(external_elements, key, val);
3714 }
3715
3716
3768 bool HGraphBuilder::TryArgumentsAccess(Property* expr) { 3717 bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
3769 VariableProxy* proxy = expr->obj()->AsVariableProxy(); 3718 VariableProxy* proxy = expr->obj()->AsVariableProxy();
3770 if (proxy == NULL) return false; 3719 if (proxy == NULL) return false;
3771 if (!proxy->var()->IsStackAllocated()) return false; 3720 if (!proxy->var()->IsStackAllocated()) return false;
3772 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { 3721 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
3773 return false; 3722 return false;
3774 } 3723 }
3775 3724
3776 HInstruction* result = NULL; 3725 HInstruction* result = NULL;
3777 if (expr->key()->IsPropertyName()) { 3726 if (expr->key()->IsPropertyName()) {
3778 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 3727 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
3779 if (!name->IsEqualTo(CStrVector("length"))) return false; 3728 if (!name->IsEqualTo(CStrVector("length"))) return false;
3780 HInstruction* elements = AddInstruction(new HArgumentsElements); 3729 HInstruction* elements = AddInstruction(new HArgumentsElements);
3781 result = new HArgumentsLength(elements); 3730 result = new HArgumentsLength(elements);
3782 } else { 3731 } else {
3732 Push(graph()->GetArgumentsObject());
3783 VisitForValue(expr->key()); 3733 VisitForValue(expr->key());
3784 if (HasStackOverflow()) return false; 3734 if (HasStackOverflow()) return false;
3785 HValue* key = Pop(); 3735 HValue* key = Pop();
3736 Drop(1); // Arguments object.
3786 HInstruction* elements = AddInstruction(new HArgumentsElements); 3737 HInstruction* elements = AddInstruction(new HArgumentsElements);
3787 HInstruction* length = AddInstruction(new HArgumentsLength(elements)); 3738 HInstruction* length = AddInstruction(new HArgumentsLength(elements));
3788 AddInstruction(new HBoundsCheck(key, length)); 3739 AddInstruction(new HBoundsCheck(key, length));
3789 result = new HAccessArgumentsAt(elements, length, key); 3740 result = new HAccessArgumentsAt(elements, length, key);
3790 } 3741 }
3791 ast_context()->ReturnInstruction(result, expr->id()); 3742 ast_context()->ReturnInstruction(result, expr->id());
3792 return true; 3743 return true;
3793 } 3744 }
3794 3745
3795 3746
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
3835 } else { 3786 } else {
3836 instr = BuildLoadNamedGeneric(obj, expr); 3787 instr = BuildLoadNamedGeneric(obj, expr);
3837 } 3788 }
3838 3789
3839 } else { 3790 } else {
3840 VISIT_FOR_VALUE(expr->key()); 3791 VISIT_FOR_VALUE(expr->key());
3841 3792
3842 HValue* key = Pop(); 3793 HValue* key = Pop();
3843 HValue* obj = Pop(); 3794 HValue* obj = Pop();
3844 3795
3845 bool is_fast_elements = expr->IsMonomorphic() && 3796 if (expr->IsMonomorphic()) {
3846 expr->GetMonomorphicReceiverType()->has_fast_elements(); 3797 Handle<Map> receiver_type(expr->GetMonomorphicReceiverType());
3847 3798 // An object has either fast elements or pixel array elements, but never
3848 instr = is_fast_elements 3799 // both. Pixel array maps that are assigned to pixel array elements are
3849 ? BuildLoadKeyedFastElement(obj, key, expr) 3800 // always created with the fast elements flag cleared.
3850 : BuildLoadKeyedGeneric(obj, key); 3801 if (receiver_type->has_pixel_array_elements()) {
3802 instr = BuildLoadKeyedPixelArrayElement(obj, key, expr);
3803 } else if (receiver_type->has_fast_elements()) {
3804 instr = BuildLoadKeyedFastElement(obj, key, expr);
3805 }
3806 }
3807 if (instr == NULL) {
3808 instr = BuildLoadKeyedGeneric(obj, key);
3809 }
3851 } 3810 }
3852 instr->set_position(expr->position()); 3811 instr->set_position(expr->position());
3853 ast_context()->ReturnInstruction(instr, expr->id()); 3812 ast_context()->ReturnInstruction(instr, expr->id());
3854 } 3813 }
3855 3814
3856 3815
3857 void HGraphBuilder::AddCheckConstantFunction(Call* expr, 3816 void HGraphBuilder::AddCheckConstantFunction(Call* expr,
3858 HValue* receiver, 3817 HValue* receiver,
3859 Handle<Map> receiver_map, 3818 Handle<Map> receiver_map,
3860 bool smi_and_map_check) { 3819 bool smi_and_map_check) {
(...skipping 12 matching lines...) Expand all
3873 } 3832 }
3874 3833
3875 3834
3876 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, 3835 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
3877 HValue* receiver, 3836 HValue* receiver,
3878 ZoneMapList* types, 3837 ZoneMapList* types,
3879 Handle<String> name) { 3838 Handle<String> name) {
3880 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 3839 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
3881 int number_of_types = Min(types->length(), kMaxCallPolymorphism); 3840 int number_of_types = Min(types->length(), kMaxCallPolymorphism);
3882 ZoneMapList maps(number_of_types); 3841 ZoneMapList maps(number_of_types);
3883 ZoneList<HSubgraph*> subgraphs(number_of_types + 1); 3842 ZoneList<HSubgraph*> subgraphs(number_of_types);
3884 bool needs_generic = (types->length() > kMaxCallPolymorphism); 3843 bool needs_generic = (types->length() > kMaxCallPolymorphism);
3885 3844
3886 // Build subgraphs for each of the specific maps. 3845 // Build subgraphs for each of the specific maps.
3887 // 3846 //
3888 // TODO(ager): We should recognize when the prototype chains for different 3847 // TODO(ager): We should recognize when the prototype chains for different
3889 // maps are identical. In that case we can avoid repeatedly generating the 3848 // maps are identical. In that case we can avoid repeatedly generating the
3890 // same prototype map checks. 3849 // same prototype map checks.
3891 for (int i = 0; i < number_of_types; ++i) { 3850 for (int i = 0; i < number_of_types; ++i) {
3892 Handle<Map> map = types->at(i); 3851 Handle<Map> map = types->at(i);
3893 if (expr->ComputeTarget(map, name)) { 3852 if (expr->ComputeTarget(map, name)) {
3894 maps.Add(map);
3895 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3853 HSubgraph* subgraph = CreateBranchSubgraph(environment());
3896 SubgraphScope scope(this, subgraph); 3854 SubgraphScope scope(this, subgraph);
3897 AddCheckConstantFunction(expr, receiver, map, false); 3855 AddCheckConstantFunction(expr, receiver, map, false);
3898 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { 3856 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
3899 PrintF("Trying to inline the polymorphic call to %s\n", 3857 PrintF("Trying to inline the polymorphic call to %s\n",
3900 *name->ToCString()); 3858 *name->ToCString());
3901 } 3859 }
3902 if (!FLAG_polymorphic_inlining || !TryInline(expr)) { 3860 if (!FLAG_polymorphic_inlining || !TryInline(expr)) {
3903 // Check for bailout, as trying to inline might fail due to bailout 3861 // Check for bailout, as trying to inline might fail due to bailout
3904 // during hydrogen processing. 3862 // during hydrogen processing.
3905 CHECK_BAILOUT; 3863 CHECK_BAILOUT;
3906 HCall* call = new HCallConstantFunction(expr->target(), argument_count); 3864 HCallConstantFunction* call =
3865 new HCallConstantFunction(expr->target(), argument_count);
3907 call->set_position(expr->position()); 3866 call->set_position(expr->position());
3908 ProcessCall(call); 3867 PreProcessCall(call);
3909 PushAndAdd(call); 3868 PushAndAdd(call);
3910 } 3869 }
3870 maps.Add(map);
3911 subgraphs.Add(subgraph); 3871 subgraphs.Add(subgraph);
3912 } else { 3872 } else {
3913 needs_generic = true; 3873 needs_generic = true;
3914 } 3874 }
3915 } 3875 }
3916 3876
3917 // If we couldn't compute the target for any of the maps just perform an 3877 // If we couldn't compute the target for any of the maps just perform an
3918 // IC call. 3878 // IC call.
3919 if (maps.length() == 0) { 3879 if (maps.length() == 0) {
3920 HCall* call = new HCallNamed(name, argument_count); 3880 HContext* context = new HContext;
3881 AddInstruction(context);
3882 HCallNamed* call = new HCallNamed(context, name, argument_count);
3921 call->set_position(expr->position()); 3883 call->set_position(expr->position());
3922 ProcessCall(call); 3884 PreProcessCall(call);
3923 ast_context()->ReturnInstruction(call, expr->id()); 3885 ast_context()->ReturnInstruction(call, expr->id());
3924 } else { 3886 } else {
3925 // Build subgraph for generic call through IC. 3887 // Build subgraph for generic call through IC.
3926 { 3888 HSubgraph* default_graph = CreateBranchSubgraph(environment());
3927 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3889 { SubgraphScope scope(this, default_graph);
3928 SubgraphScope scope(this, subgraph);
3929 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { 3890 if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3930 subgraph->FinishExit(new HDeoptimize()); 3891 default_graph->exit_block()->FinishExit(new HDeoptimize());
3892 default_graph->set_exit_block(NULL);
3931 } else { 3893 } else {
3932 HCall* call = new HCallNamed(name, argument_count); 3894 HContext* context = new HContext;
3895 AddInstruction(context);
3896 HCallNamed* call = new HCallNamed(context, name, argument_count);
3933 call->set_position(expr->position()); 3897 call->set_position(expr->position());
3934 ProcessCall(call); 3898 PreProcessCall(call);
3935 PushAndAdd(call); 3899 PushAndAdd(call);
3936 } 3900 }
3937 subgraphs.Add(subgraph);
3938 } 3901 }
3939 3902
3940 HBasicBlock* new_exit_block = 3903 HBasicBlock* new_exit_block =
3941 BuildTypeSwitch(&maps, &subgraphs, receiver, expr->id()); 3904 BuildTypeSwitch(receiver, &maps, &subgraphs, default_graph, expr->id());
3942 subgraph()->set_exit_block(new_exit_block); 3905 set_current_block(new_exit_block);
3943 // In an effect context, we did not materialized the value in the 3906 // In an effect context, we did not materialized the value in the
3944 // predecessor environments so there's no need to handle it here. 3907 // predecessor environments so there's no need to handle it here.
3945 if (new_exit_block != NULL && !ast_context()->IsEffect()) { 3908 if (new_exit_block != NULL && !ast_context()->IsEffect()) {
3946 ast_context()->ReturnValue(Pop()); 3909 ast_context()->ReturnValue(Pop());
3947 } 3910 }
3948 } 3911 }
3949 } 3912 }
3950 3913
3951 3914
3952 void HGraphBuilder::TraceInline(Handle<JSFunction> target, bool result) { 3915 void HGraphBuilder::TraceInline(Handle<JSFunction> target, bool result) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
3998 if (FLAG_trace_inlining) TraceInline(target, false); 3961 if (FLAG_trace_inlining) TraceInline(target, false);
3999 return false; 3962 return false;
4000 } 3963 }
4001 3964
4002 int count_before = AstNode::Count(); 3965 int count_before = AstNode::Count();
4003 3966
4004 // Parse and allocate variables. 3967 // Parse and allocate variables.
4005 CompilationInfo inner_info(target); 3968 CompilationInfo inner_info(target);
4006 if (!ParserApi::Parse(&inner_info) || 3969 if (!ParserApi::Parse(&inner_info) ||
4007 !Scope::Analyze(&inner_info)) { 3970 !Scope::Analyze(&inner_info)) {
3971 if (inner_info.isolate()->has_pending_exception()) {
3972 SetStackOverflow();
3973 // Stop trying to optimize and inline this function.
3974 target->shared()->set_optimization_disabled(true);
3975 }
4008 return false; 3976 return false;
4009 } 3977 }
3978 if (inner_info.scope()->num_heap_slots() > 0) return false;
4010 FunctionLiteral* function = inner_info.function(); 3979 FunctionLiteral* function = inner_info.function();
4011 3980
4012 // Count the number of AST nodes added by inlining this call. 3981 // Count the number of AST nodes added by inlining this call.
4013 int nodes_added = AstNode::Count() - count_before; 3982 int nodes_added = AstNode::Count() - count_before;
4014 if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) { 3983 if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) {
4015 if (FLAG_trace_inlining) TraceInline(target, false); 3984 if (FLAG_trace_inlining) TraceInline(target, false);
4016 return false; 3985 return false;
4017 } 3986 }
4018 3987
4019 // Check if we can handle all declarations in the inlined functions. 3988 // Check if we can handle all declarations in the inlined functions.
(...skipping 19 matching lines...) Expand all
4039 4008
4040 // Generate the deoptimization data for the unoptimized version of 4009 // Generate the deoptimization data for the unoptimized version of
4041 // the target function if we don't already have it. 4010 // the target function if we don't already have it.
4042 if (!shared->has_deoptimization_support()) { 4011 if (!shared->has_deoptimization_support()) {
4043 // Note that we compile here using the same AST that we will use for 4012 // Note that we compile here using the same AST that we will use for
4044 // generating the optimized inline code. 4013 // generating the optimized inline code.
4045 inner_info.EnableDeoptimizationSupport(); 4014 inner_info.EnableDeoptimizationSupport();
4046 if (!FullCodeGenerator::MakeCode(&inner_info)) return false; 4015 if (!FullCodeGenerator::MakeCode(&inner_info)) return false;
4047 shared->EnableDeoptimizationSupport(*inner_info.code()); 4016 shared->EnableDeoptimizationSupport(*inner_info.code());
4048 Compiler::RecordFunctionCompilation( 4017 Compiler::RecordFunctionCompilation(
4049 Logger::FUNCTION_TAG, 4018 Logger::FUNCTION_TAG, &inner_info, shared);
4050 Handle<String>(shared->DebugName()),
4051 shared->start_position(),
4052 &inner_info);
4053 } 4019 }
4054 4020
4055 // Save the pending call context and type feedback oracle. Set up new ones 4021 // Save the pending call context and type feedback oracle. Set up new ones
4056 // for the inlined function. 4022 // for the inlined function.
4057 ASSERT(shared->has_deoptimization_support()); 4023 ASSERT(shared->has_deoptimization_support());
4058 AstContext* saved_call_context = call_context(); 4024 AstContext* saved_call_context = call_context();
4059 HBasicBlock* saved_function_return = function_return(); 4025 HBasicBlock* saved_function_return = function_return();
4060 TypeFeedbackOracle* saved_oracle = oracle(); 4026 TypeFeedbackOracle* saved_oracle = oracle();
4061 // On-stack replacement cannot target inlined functions. Since we don't 4027 // On-stack replacement cannot target inlined functions. Since we don't
4062 // use a separate CompilationInfo structure for the inlined function, we 4028 // use a separate CompilationInfo structure for the inlined function, we
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
4098 oracle_ = saved_oracle; 4064 oracle_ = saved_oracle;
4099 graph()->info()->SetOsrAstId(saved_osr_ast_id); 4065 graph()->info()->SetOsrAstId(saved_osr_ast_id);
4100 return false; 4066 return false;
4101 } 4067 }
4102 4068
4103 // Update inlined nodes count. 4069 // Update inlined nodes count.
4104 inlined_count_ += nodes_added; 4070 inlined_count_ += nodes_added;
4105 4071
4106 if (FLAG_trace_inlining) TraceInline(target, true); 4072 if (FLAG_trace_inlining) TraceInline(target, true);
4107 4073
4108 if (body->HasExit()) { 4074 if (body->exit_block() != NULL) {
4109 // Add a return of undefined if control can fall off the body. In a 4075 // Add a return of undefined if control can fall off the body. In a
4110 // test context, undefined is false. 4076 // test context, undefined is false.
4111 HValue* return_value = graph()->GetConstantUndefined(); 4077 HValue* return_value = graph()->GetConstantUndefined();
4112 if (test_context == NULL) { 4078 if (test_context == NULL) {
4113 ASSERT(function_return_ != NULL); 4079 ASSERT(function_return_ != NULL);
4114 body->exit_block()->AddLeaveInlined(return_value, function_return_); 4080 body->exit_block()->AddLeaveInlined(return_value, function_return_);
4115 } else { 4081 } else {
4116 // The graph builder assumes control can reach both branches of a 4082 // The graph builder assumes control can reach both branches of a
4117 // test, so we materialize the undefined value and test it rather than 4083 // test, so we materialize the undefined value and test it rather than
4118 // simply jumping to the false target. 4084 // simply jumping to the false target.
4119 // 4085 //
4120 // TODO(3168478): refactor to avoid this. 4086 // TODO(3168478): refactor to avoid this.
4121 HBasicBlock* empty_true = graph()->CreateBasicBlock(); 4087 HBasicBlock* empty_true = graph()->CreateBasicBlock();
4122 HBasicBlock* empty_false = graph()->CreateBasicBlock(); 4088 HBasicBlock* empty_false = graph()->CreateBasicBlock();
4123 HTest* test = new HTest(return_value, empty_true, empty_false); 4089 HTest* test = new HTest(return_value, empty_true, empty_false);
4124 body->exit_block()->Finish(test); 4090 body->exit_block()->Finish(test);
4125 4091
4126 HValue* const no_return_value = NULL; 4092 HValue* const no_return_value = NULL;
4127 empty_true->AddLeaveInlined(no_return_value, test_context->if_true()); 4093 empty_true->AddLeaveInlined(no_return_value, test_context->if_true());
4128 empty_false->AddLeaveInlined(no_return_value, test_context->if_false()); 4094 empty_false->AddLeaveInlined(no_return_value, test_context->if_false());
4129 } 4095 }
4130 body->set_exit_block(NULL); 4096 body->set_exit_block(NULL);
4131 } 4097 }
4132 4098
4133 // Record the environment at the inlined function call. 4099 // Record the environment at the inlined function call.
4134 AddSimulate(expr->ReturnId()); 4100 AddSimulate(expr->ReturnId());
4135 4101
4136 // Jump to the function entry (without re-recording the environment). 4102 // Jump to the function entry (without re-recording the environment).
4137 subgraph()->exit_block()->Finish(new HGoto(body->entry_block())); 4103 current_block()->Finish(new HGoto(body->entry_block()));
4138 4104
4139 // Fix up the function exits. 4105 // Fix up the function exits.
4140 if (test_context != NULL) { 4106 if (test_context != NULL) {
4141 HBasicBlock* if_true = test_context->if_true(); 4107 HBasicBlock* if_true = test_context->if_true();
4142 HBasicBlock* if_false = test_context->if_false(); 4108 HBasicBlock* if_false = test_context->if_false();
4143 if_true->SetJoinId(expr->id()); 4109 if_true->SetJoinId(expr->id());
4144 if_false->SetJoinId(expr->id()); 4110 if_false->SetJoinId(expr->id());
4145 ASSERT(ast_context() == test_context); 4111 ASSERT(ast_context() == test_context);
4146 delete test_context; // Destructor pops from expression context stack. 4112 delete test_context; // Destructor pops from expression context stack.
4147 4113
4148 // Forward to the real test context. 4114 // Forward to the real test context.
4149 HValue* const no_return_value = NULL; 4115 HValue* const no_return_value = NULL;
4150 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 4116 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
4151 if (true_target->IsInlineReturnTarget()) { 4117 if (true_target->IsInlineReturnTarget()) {
4152 if_true->AddLeaveInlined(no_return_value, true_target); 4118 if_true->AddLeaveInlined(no_return_value, true_target);
4153 } else { 4119 } else {
4154 if_true->Goto(true_target); 4120 if_true->Goto(true_target);
4155 } 4121 }
4156 4122
4157 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 4123 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
4158 if (false_target->IsInlineReturnTarget()) { 4124 if (false_target->IsInlineReturnTarget()) {
4159 if_false->AddLeaveInlined(no_return_value, false_target); 4125 if_false->AddLeaveInlined(no_return_value, false_target);
4160 } else { 4126 } else {
4161 if_false->Goto(false_target); 4127 if_false->Goto(false_target);
4162 } 4128 }
4163 4129
4164 // TODO(kmillikin): Come up with a better way to handle this. It is too 4130 // TODO(kmillikin): Come up with a better way to handle this. It is too
4165 // subtle. NULL here indicates that the enclosing context has no control 4131 // subtle. NULL here indicates that the enclosing context has no control
4166 // flow to handle. 4132 // flow to handle.
4167 subgraph()->set_exit_block(NULL); 4133 set_current_block(NULL);
4168 4134
4169 } else { 4135 } else {
4170 function_return_->SetJoinId(expr->id()); 4136 function_return_->SetJoinId(expr->id());
4171 subgraph()->set_exit_block(function_return_); 4137 set_current_block(function_return_);
4172 } 4138 }
4173 4139
4174 call_context_ = saved_call_context; 4140 call_context_ = saved_call_context;
4175 function_return_ = saved_function_return; 4141 function_return_ = saved_function_return;
4176 oracle_ = saved_oracle; 4142 oracle_ = saved_oracle;
4177 graph()->info()->SetOsrAstId(saved_osr_ast_id); 4143 graph()->info()->SetOsrAstId(saved_osr_ast_id);
4178 4144
4179 return true; 4145 return true;
4180 } 4146 }
4181 4147
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
4323 static bool HasCustomCallGenerator(Handle<JSFunction> function) { 4289 static bool HasCustomCallGenerator(Handle<JSFunction> function) {
4324 SharedFunctionInfo* info = function->shared(); 4290 SharedFunctionInfo* info = function->shared();
4325 return info->HasBuiltinFunctionId() && 4291 return info->HasBuiltinFunctionId() &&
4326 CallStubCompiler::HasCustomCallGenerator(info->builtin_function_id()); 4292 CallStubCompiler::HasCustomCallGenerator(info->builtin_function_id());
4327 } 4293 }
4328 4294
4329 4295
4330 void HGraphBuilder::VisitCall(Call* expr) { 4296 void HGraphBuilder::VisitCall(Call* expr) {
4331 Expression* callee = expr->expression(); 4297 Expression* callee = expr->expression();
4332 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4298 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
4333 HCall* call = NULL; 4299 HInstruction* call = NULL;
4334 4300
4335 Property* prop = callee->AsProperty(); 4301 Property* prop = callee->AsProperty();
4336 if (prop != NULL) { 4302 if (prop != NULL) {
4337 if (!prop->key()->IsPropertyName()) { 4303 if (!prop->key()->IsPropertyName()) {
4338 // Keyed function call. 4304 // Keyed function call.
4339 VisitArgument(prop->obj()); 4305 VISIT_FOR_VALUE(prop->obj());
4340 CHECK_BAILOUT;
4341 4306
4342 VISIT_FOR_VALUE(prop->key()); 4307 VISIT_FOR_VALUE(prop->key());
4343 // Push receiver and key like the non-optimized code generator expects it. 4308 // Push receiver and key like the non-optimized code generator expects it.
4344 HValue* key = Pop(); 4309 HValue* key = Pop();
4345 HValue* receiver = Pop(); 4310 HValue* receiver = Pop();
4346 Push(key); 4311 Push(key);
4347 Push(receiver); 4312 Push(receiver);
4348 4313
4349 VisitArgumentList(expr->arguments()); 4314 VisitExpressions(expr->arguments());
4350 CHECK_BAILOUT; 4315 CHECK_BAILOUT;
4351 4316
4352 call = new HCallKeyed(key, argument_count); 4317 HContext* context = new HContext;
4318 AddInstruction(context);
4319 call = PreProcessCall(new HCallKeyed(context, key, argument_count));
4353 call->set_position(expr->position()); 4320 call->set_position(expr->position());
4354 ProcessCall(call);
4355 Drop(1); // Key. 4321 Drop(1); // Key.
4356 ast_context()->ReturnInstruction(call, expr->id()); 4322 ast_context()->ReturnInstruction(call, expr->id());
4357 return; 4323 return;
4358 } 4324 }
4359 4325
4360 // Named function call. 4326 // Named function call.
4361 expr->RecordTypeFeedback(oracle()); 4327 expr->RecordTypeFeedback(oracle());
4362 4328
4363 if (TryCallApply(expr)) return; 4329 if (TryCallApply(expr)) return;
4364 CHECK_BAILOUT; 4330 CHECK_BAILOUT;
4365 4331
4366 HValue* receiver = VisitArgument(prop->obj()); 4332 VISIT_FOR_VALUE(prop->obj());
4367 CHECK_BAILOUT; 4333 VisitExpressions(expr->arguments());
4368 VisitArgumentList(expr->arguments());
4369 CHECK_BAILOUT; 4334 CHECK_BAILOUT;
4370 4335
4371 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4336 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4372 4337
4373 expr->RecordTypeFeedback(oracle()); 4338 expr->RecordTypeFeedback(oracle());
4374 ZoneMapList* types = expr->GetReceiverTypes(); 4339 ZoneMapList* types = expr->GetReceiverTypes();
4375 4340
4341 HValue* receiver =
4342 environment()->ExpressionStackAt(expr->arguments()->length());
4376 if (expr->IsMonomorphic()) { 4343 if (expr->IsMonomorphic()) {
4377 Handle<Map> receiver_map = 4344 Handle<Map> receiver_map =
4378 (types == NULL) ? Handle<Map>::null() : types->first(); 4345 (types == NULL) ? Handle<Map>::null() : types->first();
4379 if (TryInlineBuiltinFunction(expr, 4346 if (TryInlineBuiltinFunction(expr,
4380 receiver, 4347 receiver,
4381 receiver_map, 4348 receiver_map,
4382 expr->check_type())) { 4349 expr->check_type())) {
4383 return; 4350 return;
4384 } 4351 }
4385 4352
4386 if (HasCustomCallGenerator(expr->target()) || 4353 if (HasCustomCallGenerator(expr->target()) ||
4387 expr->check_type() != RECEIVER_MAP_CHECK) { 4354 expr->check_type() != RECEIVER_MAP_CHECK) {
4388 // When the target has a custom call IC generator, use the IC, 4355 // When the target has a custom call IC generator, use the IC,
4389 // because it is likely to generate better code. Also use the 4356 // because it is likely to generate better code. Also use the
4390 // IC when a primitive receiver check is required. 4357 // IC when a primitive receiver check is required.
4391 call = new HCallNamed(name, argument_count); 4358 HContext* context = new HContext;
4359 AddInstruction(context);
4360 call = PreProcessCall(new HCallNamed(context, name, argument_count));
4392 } else { 4361 } else {
4393 AddCheckConstantFunction(expr, receiver, receiver_map, true); 4362 AddCheckConstantFunction(expr, receiver, receiver_map, true);
4394 4363
4395 if (TryInline(expr)) { 4364 if (TryInline(expr)) {
4396 if (subgraph()->HasExit()) { 4365 if (current_block() != NULL) {
4397 HValue* return_value = Pop(); 4366 HValue* return_value = Pop();
4398 // If we inlined a function in a test context then we need to emit 4367 // If we inlined a function in a test context then we need to emit
4399 // a simulate here to shadow the ones at the end of the 4368 // a simulate here to shadow the ones at the end of the
4400 // predecessor blocks. Those environments contain the return 4369 // predecessor blocks. Those environments contain the return
4401 // value on top and do not correspond to any actual state of the 4370 // value on top and do not correspond to any actual state of the
4402 // unoptimized code. 4371 // unoptimized code.
4403 if (ast_context()->IsEffect()) AddSimulate(expr->id()); 4372 if (ast_context()->IsEffect()) AddSimulate(expr->id());
4404 ast_context()->ReturnValue(return_value); 4373 ast_context()->ReturnValue(return_value);
4405 } 4374 }
4406 return; 4375 return;
4407 } else { 4376 } else {
4408 // Check for bailout, as the TryInline call in the if condition above 4377 // Check for bailout, as the TryInline call in the if condition above
4409 // might return false due to bailout during hydrogen processing. 4378 // might return false due to bailout during hydrogen processing.
4410 CHECK_BAILOUT; 4379 CHECK_BAILOUT;
4411 call = new HCallConstantFunction(expr->target(), argument_count); 4380 call = PreProcessCall(new HCallConstantFunction(expr->target(),
4381 argument_count));
4412 } 4382 }
4413 } 4383 }
4414 } else if (types != NULL && types->length() > 1) { 4384 } else if (types != NULL && types->length() > 1) {
4415 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); 4385 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
4416 HandlePolymorphicCallNamed(expr, receiver, types, name); 4386 HandlePolymorphicCallNamed(expr, receiver, types, name);
4417 return; 4387 return;
4418 4388
4419 } else { 4389 } else {
4420 call = new HCallNamed(name, argument_count); 4390 HContext* context = new HContext;
4391 AddInstruction(context);
4392 call = PreProcessCall(new HCallNamed(context, name, argument_count));
4421 } 4393 }
4422 4394
4423 } else { 4395 } else {
4424 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 4396 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
4425 bool global_call = (var != NULL) && var->is_global() && !var->is_this(); 4397 bool global_call = (var != NULL) && var->is_global() && !var->is_this();
4426 4398
4427 if (!global_call) { 4399 if (!global_call) {
4428 ++argument_count; 4400 ++argument_count;
4429 VisitArgument(expr->expression()); 4401 VISIT_FOR_VALUE(expr->expression());
4430 CHECK_BAILOUT;
4431 } 4402 }
4432 4403
4433 if (global_call) { 4404 if (global_call) {
4434 // If there is a global property cell for the name at compile time and 4405 // If there is a global property cell for the name at compile time and
4435 // access check is not enabled we assume that the function will not change 4406 // access check is not enabled we assume that the function will not change
4436 // and generate optimized code for calling the function. 4407 // and generate optimized code for calling the function.
4437 CompilationInfo* info = graph()->info(); 4408 CompilationInfo* info = graph()->info();
4438 bool known_global_function = info->has_global_object() && 4409 bool known_global_function = info->has_global_object() &&
4439 !info->global_object()->IsAccessCheckNeeded() && 4410 !info->global_object()->IsAccessCheckNeeded() &&
4440 expr->ComputeGlobalTarget(Handle<GlobalObject>(info->global_object()), 4411 expr->ComputeGlobalTarget(Handle<GlobalObject>(info->global_object()),
4441 var->name()); 4412 var->name());
4442 if (known_global_function) { 4413 if (known_global_function) {
4443 // Push the global object instead of the global receiver because 4414 // Push the global object instead of the global receiver because
4444 // code generated by the full code generator expects it. 4415 // code generated by the full code generator expects it.
4445 HContext* context = new HContext; 4416 HContext* context = new HContext;
4446 HGlobalObject* global_object = new HGlobalObject(context); 4417 HGlobalObject* global_object = new HGlobalObject(context);
4447 AddInstruction(context); 4418 AddInstruction(context);
4448 PushAndAdd(global_object); 4419 PushAndAdd(global_object);
4449 VisitArgumentList(expr->arguments()); 4420 VisitExpressions(expr->arguments());
4450 CHECK_BAILOUT; 4421 CHECK_BAILOUT;
4451 4422
4452 VISIT_FOR_VALUE(expr->expression()); 4423 VISIT_FOR_VALUE(expr->expression());
4453 HValue* function = Pop(); 4424 HValue* function = Pop();
4454 AddInstruction(new HCheckFunction(function, expr->target())); 4425 AddInstruction(new HCheckFunction(function, expr->target()));
4455 4426
4456 // Replace the global object with the global receiver. 4427 // Replace the global object with the global receiver.
4457 HGlobalReceiver* global_receiver = new HGlobalReceiver(global_object); 4428 HGlobalReceiver* global_receiver = new HGlobalReceiver(global_object);
4458 // Index of the receiver from the top of the expression stack. 4429 // Index of the receiver from the top of the expression stack.
4459 const int receiver_index = argument_count - 1; 4430 const int receiver_index = argument_count - 1;
4460 AddInstruction(global_receiver); 4431 AddInstruction(global_receiver);
4461 ASSERT(environment()->ExpressionStackAt(receiver_index)-> 4432 ASSERT(environment()->ExpressionStackAt(receiver_index)->
4462 IsGlobalObject()); 4433 IsGlobalObject());
4463 environment()->SetExpressionStackAt(receiver_index, global_receiver); 4434 environment()->SetExpressionStackAt(receiver_index, global_receiver);
4464 4435
4465 if (TryInline(expr)) { 4436 if (TryInline(expr)) {
4466 if (subgraph()->HasExit()) { 4437 if (current_block() != NULL) {
4467 HValue* return_value = Pop(); 4438 HValue* return_value = Pop();
4468 // If we inlined a function in a test context then we need to 4439 // If we inlined a function in a test context then we need to
4469 // emit a simulate here to shadow the ones at the end of the 4440 // emit a simulate here to shadow the ones at the end of the
4470 // predecessor blocks. Those environments contain the return 4441 // predecessor blocks. Those environments contain the return
4471 // value on top and do not correspond to any actual state of the 4442 // value on top and do not correspond to any actual state of the
4472 // unoptimized code. 4443 // unoptimized code.
4473 if (ast_context()->IsEffect()) AddSimulate(expr->id()); 4444 if (ast_context()->IsEffect()) AddSimulate(expr->id());
4474 ast_context()->ReturnValue(return_value); 4445 ast_context()->ReturnValue(return_value);
4475 } 4446 }
4476 return; 4447 return;
4477 } 4448 }
4478 // Check for bailout, as trying to inline might fail due to bailout 4449 // Check for bailout, as trying to inline might fail due to bailout
4479 // during hydrogen processing. 4450 // during hydrogen processing.
4480 CHECK_BAILOUT; 4451 CHECK_BAILOUT;
4481 4452
4482 call = new HCallKnownGlobal(expr->target(), argument_count); 4453 call = PreProcessCall(new HCallKnownGlobal(expr->target(),
4454 argument_count));
4483 } else { 4455 } else {
4484 HContext* context = new HContext; 4456 HContext* context = new HContext;
4485 AddInstruction(context); 4457 AddInstruction(context);
4486 PushAndAdd(new HGlobalObject(context)); 4458 PushAndAdd(new HGlobalObject(context));
4487 VisitArgumentList(expr->arguments()); 4459 VisitExpressions(expr->arguments());
4488 CHECK_BAILOUT; 4460 CHECK_BAILOUT;
4489 4461
4490 call = new HCallGlobal(var->name(), argument_count); 4462 call = PreProcessCall(new HCallGlobal(context,
4463 var->name(),
4464 argument_count));
4491 } 4465 }
4492 4466
4493 } else { 4467 } else {
4494 HContext* context = new HContext; 4468 HContext* context = new HContext;
4495 HGlobalObject* global_object = new HGlobalObject(context); 4469 HGlobalObject* global_object = new HGlobalObject(context);
4496 AddInstruction(context); 4470 AddInstruction(context);
4497 AddInstruction(global_object); 4471 AddInstruction(global_object);
4498 PushAndAdd(new HGlobalReceiver(global_object)); 4472 PushAndAdd(new HGlobalReceiver(global_object));
4499 VisitArgumentList(expr->arguments()); 4473 VisitExpressions(expr->arguments());
4500 CHECK_BAILOUT; 4474 CHECK_BAILOUT;
4501 4475
4502 call = new HCallFunction(argument_count); 4476 call = PreProcessCall(new HCallFunction(context, argument_count));
4503 } 4477 }
4504 } 4478 }
4505 4479
4506 call->set_position(expr->position()); 4480 call->set_position(expr->position());
4507 ProcessCall(call);
4508 ast_context()->ReturnInstruction(call, expr->id()); 4481 ast_context()->ReturnInstruction(call, expr->id());
4509 } 4482 }
4510 4483
4511 4484
4512 void HGraphBuilder::VisitCallNew(CallNew* expr) { 4485 void HGraphBuilder::VisitCallNew(CallNew* expr) {
4513 // The constructor function is also used as the receiver argument to the 4486 // The constructor function is also used as the receiver argument to the
4514 // JS construct call builtin. 4487 // JS construct call builtin.
4515 VisitArgument(expr->expression()); 4488 VISIT_FOR_VALUE(expr->expression());
4516 CHECK_BAILOUT; 4489 VisitExpressions(expr->arguments());
4517 VisitArgumentList(expr->arguments());
4518 CHECK_BAILOUT; 4490 CHECK_BAILOUT;
4519 4491
4520 int argument_count = expr->arguments()->length() + 1; // Plus constructor. 4492 HContext* context = new HContext;
4521 HCall* call = new HCallNew(argument_count); 4493 AddInstruction(context);
4494
4495 // The constructor is both an operand to the instruction and an argument
4496 // to the construct call.
4497 int arg_count = expr->arguments()->length() + 1; // Plus constructor.
4498 HValue* constructor = environment()->ExpressionStackAt(arg_count - 1);
4499 HCallNew* call = new HCallNew(context, constructor, arg_count);
4522 call->set_position(expr->position()); 4500 call->set_position(expr->position());
4523 ProcessCall(call); 4501 PreProcessCall(call);
4524 ast_context()->ReturnInstruction(call, expr->id()); 4502 ast_context()->ReturnInstruction(call, expr->id());
4525 } 4503 }
4526 4504
4527 4505
4528 // Support for generating inlined runtime functions. 4506 // Support for generating inlined runtime functions.
4529 4507
4530 // Lookup table for generators for runtime calls that are generated inline. 4508 // Lookup table for generators for runtime calls that are generated inline.
4531 // Elements of the table are member pointers to functions of HGraphBuilder. 4509 // Elements of the table are member pointers to functions of HGraphBuilder.
4532 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ 4510 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
4533 &HGraphBuilder::Generate##Name, 4511 &HGraphBuilder::Generate##Name,
4534 4512
4535 const HGraphBuilder::InlineFunctionGenerator 4513 const HGraphBuilder::InlineFunctionGenerator
4536 HGraphBuilder::kInlineFunctionGenerators[] = { 4514 HGraphBuilder::kInlineFunctionGenerators[] = {
4537 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) 4515 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
4538 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) 4516 INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
4539 }; 4517 };
4540 #undef INLINE_FUNCTION_GENERATOR_ADDRESS 4518 #undef INLINE_FUNCTION_GENERATOR_ADDRESS
4541 4519
4542 4520
4543 void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { 4521 void HGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
4544 Handle<String> name = expr->name(); 4522 if (expr->is_jsruntime()) {
4545 if (name->IsEqualTo(CStrVector("_Log"))) { 4523 BAILOUT("call to a JavaScript runtime function");
4546 ast_context()->ReturnValue(graph()->GetConstantUndefined());
4547 return;
4548 } 4524 }
4549 4525
4550 const Runtime::Function* function = expr->function(); 4526 const Runtime::Function* function = expr->function();
4551 if (expr->is_jsruntime()) {
4552 BAILOUT("call to a JavaScript runtime function");
4553 }
4554 ASSERT(function != NULL); 4527 ASSERT(function != NULL);
4555
4556 VisitArgumentList(expr->arguments());
4557 CHECK_BAILOUT;
4558
4559 int argument_count = expr->arguments()->length();
4560 if (function->intrinsic_type == Runtime::INLINE) { 4528 if (function->intrinsic_type == Runtime::INLINE) {
4561 ASSERT(name->length() > 0); 4529 ASSERT(expr->name()->length() > 0);
4562 ASSERT(name->Get(0) == '_'); 4530 ASSERT(expr->name()->Get(0) == '_');
4563 // Call to an inline function. 4531 // Call to an inline function.
4564 int lookup_index = static_cast<int>(function->function_id) - 4532 int lookup_index = static_cast<int>(function->function_id) -
4565 static_cast<int>(Runtime::kFirstInlineFunction); 4533 static_cast<int>(Runtime::kFirstInlineFunction);
4566 ASSERT(lookup_index >= 0); 4534 ASSERT(lookup_index >= 0);
4567 ASSERT(static_cast<size_t>(lookup_index) < 4535 ASSERT(static_cast<size_t>(lookup_index) <
4568 ARRAY_SIZE(kInlineFunctionGenerators)); 4536 ARRAY_SIZE(kInlineFunctionGenerators));
4569 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; 4537 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
4570 4538
4571 // Call the inline code generator using the pointer-to-member. 4539 // Call the inline code generator using the pointer-to-member.
4572 (this->*generator)(argument_count, expr->id()); 4540 (this->*generator)(expr);
4573 } else { 4541 } else {
4574 ASSERT(function->intrinsic_type == Runtime::RUNTIME); 4542 ASSERT(function->intrinsic_type == Runtime::RUNTIME);
4575 HCall* call = new HCallRuntime(name, expr->function(), argument_count); 4543 VisitArgumentList(expr->arguments());
4544 CHECK_BAILOUT;
4545
4546 Handle<String> name = expr->name();
4547 int argument_count = expr->arguments()->length();
4548 HCallRuntime* call = new HCallRuntime(name, function, argument_count);
4576 call->set_position(RelocInfo::kNoPosition); 4549 call->set_position(RelocInfo::kNoPosition);
4577 ProcessCall(call); 4550 Drop(argument_count);
4578 ast_context()->ReturnInstruction(call, expr->id()); 4551 ast_context()->ReturnInstruction(call, expr->id());
4579 } 4552 }
4580 } 4553 }
4581 4554
4582 4555
4583 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { 4556 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
4584 Token::Value op = expr->op(); 4557 Token::Value op = expr->op();
4585 if (op == Token::VOID) { 4558 if (op == Token::VOID) {
4586 VISIT_FOR_EFFECT(expr->expression()); 4559 VISIT_FOR_EFFECT(expr->expression());
4587 ast_context()->ReturnValue(graph()->GetConstantUndefined()); 4560 ast_context()->ReturnValue(graph()->GetConstantUndefined());
4588 } else if (op == Token::DELETE) { 4561 } else if (op == Token::DELETE) {
4589 Property* prop = expr->expression()->AsProperty(); 4562 Property* prop = expr->expression()->AsProperty();
4590 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 4563 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
4591 if (prop == NULL && var == NULL) { 4564 if (prop == NULL && var == NULL) {
4592 // Result of deleting non-property, non-variable reference is true. 4565 // Result of deleting non-property, non-variable reference is true.
4593 // Evaluate the subexpression for side effects. 4566 // Evaluate the subexpression for side effects.
4594 VISIT_FOR_EFFECT(expr->expression()); 4567 VISIT_FOR_EFFECT(expr->expression());
4595 ast_context()->ReturnValue(graph()->GetConstantTrue()); 4568 ast_context()->ReturnValue(graph()->GetConstantTrue());
4596 } else if (var != NULL && 4569 } else if (var != NULL &&
4597 !var->is_global() && 4570 !var->is_global() &&
4598 var->AsSlot() != NULL && 4571 var->AsSlot() != NULL &&
4599 var->AsSlot()->type() != Slot::LOOKUP) { 4572 var->AsSlot()->type() != Slot::LOOKUP) {
4600 // Result of deleting non-global, non-dynamic variables is false. 4573 // Result of deleting non-global, non-dynamic variables is false.
4601 // The subexpression does not have side effects. 4574 // The subexpression does not have side effects.
4602 ast_context()->ReturnValue(graph()->GetConstantFalse()); 4575 ast_context()->ReturnValue(graph()->GetConstantFalse());
4603 } else if (prop != NULL) { 4576 } else if (prop != NULL) {
4604 VISIT_FOR_VALUE(prop->obj()); 4577 if (prop->is_synthetic()) {
4605 VISIT_FOR_VALUE(prop->key()); 4578 // Result of deleting parameters is false, even when they rewrite
4606 HValue* key = Pop(); 4579 // to accesses on the arguments object.
4607 HValue* obj = Pop(); 4580 ast_context()->ReturnValue(graph()->GetConstantFalse());
4608 ast_context()->ReturnInstruction(new HDeleteProperty(obj, key), 4581 } else {
4609 expr->id()); 4582 VISIT_FOR_VALUE(prop->obj());
4583 VISIT_FOR_VALUE(prop->key());
4584 HValue* key = Pop();
4585 HValue* obj = Pop();
4586 HDeleteProperty* instr = new HDeleteProperty(obj, key);
4587 ast_context()->ReturnInstruction(instr, expr->id());
4588 }
4610 } else if (var->is_global()) { 4589 } else if (var->is_global()) {
4611 BAILOUT("delete with global variable"); 4590 BAILOUT("delete with global variable");
4612 } else { 4591 } else {
4613 BAILOUT("delete with non-global variable"); 4592 BAILOUT("delete with non-global variable");
4614 } 4593 }
4615 } else if (op == Token::NOT) { 4594 } else if (op == Token::NOT) {
4616 if (ast_context()->IsTest()) { 4595 if (ast_context()->IsTest()) {
4617 TestContext* context = TestContext::cast(ast_context()); 4596 TestContext* context = TestContext::cast(ast_context());
4618 VisitForControl(expr->expression(), 4597 VisitForControl(expr->expression(),
4619 context->if_false(), 4598 context->if_false(),
4620 context->if_true()); 4599 context->if_true());
4600 } else if (ast_context()->IsValue()) {
4601 HBasicBlock* materialize_false = graph()->CreateBasicBlock();
4602 HBasicBlock* materialize_true = graph()->CreateBasicBlock();
4603 VISIT_FOR_CONTROL(expr->expression(),
4604 materialize_false,
4605 materialize_true);
4606 materialize_false->SetJoinId(expr->expression()->id());
4607 materialize_true->SetJoinId(expr->expression()->id());
4608
4609 set_current_block(materialize_false);
4610 Push(graph()->GetConstantFalse());
4611 set_current_block(materialize_true);
4612 Push(graph()->GetConstantTrue());
4613
4614 HBasicBlock* join =
4615 CreateJoin(materialize_false, materialize_true, expr->id());
4616 set_current_block(join);
4617 ast_context()->ReturnValue(Pop());
4621 } else { 4618 } else {
4622 HSubgraph* true_graph = CreateEmptySubgraph(); 4619 ASSERT(ast_context()->IsEffect());
4623 HSubgraph* false_graph = CreateEmptySubgraph(); 4620 VisitForEffect(expr->expression());
4624 VISIT_FOR_CONTROL(expr->expression(), 4621 }
4625 false_graph->entry_block(),
4626 true_graph->entry_block());
4627 true_graph->entry_block()->SetJoinId(expr->expression()->id());
4628 true_graph->environment()->Push(graph_->GetConstantTrue());
4629 4622
4630 false_graph->entry_block()->SetJoinId(expr->expression()->id());
4631 false_graph->environment()->Push(graph_->GetConstantFalse());
4632
4633 current_subgraph_->AppendJoin(true_graph, false_graph, expr);
4634 ast_context()->ReturnValue(Pop());
4635 }
4636 } else if (op == Token::BIT_NOT || op == Token::SUB) { 4623 } else if (op == Token::BIT_NOT || op == Token::SUB) {
4637 VISIT_FOR_VALUE(expr->expression()); 4624 VISIT_FOR_VALUE(expr->expression());
4638 HValue* value = Pop(); 4625 HValue* value = Pop();
4639 HInstruction* instr = NULL; 4626 HInstruction* instr = NULL;
4640 switch (op) { 4627 switch (op) {
4641 case Token::BIT_NOT: 4628 case Token::BIT_NOT:
4642 instr = new HBitNot(value); 4629 instr = new HBitNot(value);
4643 break; 4630 break;
4644 case Token::SUB: 4631 case Token::SUB:
4645 instr = new HMul(graph_->GetConstantMinus1(), value); 4632 instr = new HMul(graph_->GetConstantMinus1(), value);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
4679 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { 4666 void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
4680 IncrementOperation* increment = expr->increment(); 4667 IncrementOperation* increment = expr->increment();
4681 Expression* target = increment->expression(); 4668 Expression* target = increment->expression();
4682 VariableProxy* proxy = target->AsVariableProxy(); 4669 VariableProxy* proxy = target->AsVariableProxy();
4683 Variable* var = proxy->AsVariable(); 4670 Variable* var = proxy->AsVariable();
4684 Property* prop = target->AsProperty(); 4671 Property* prop = target->AsProperty();
4685 ASSERT(var == NULL || prop == NULL); 4672 ASSERT(var == NULL || prop == NULL);
4686 bool inc = expr->op() == Token::INC; 4673 bool inc = expr->op() == Token::INC;
4687 4674
4688 if (var != NULL) { 4675 if (var != NULL) {
4689 if (!var->is_global() && !var->IsStackAllocated()) {
4690 BAILOUT("non-stack/non-global variable in count operation");
4691 }
4692
4693 VISIT_FOR_VALUE(target); 4676 VISIT_FOR_VALUE(target);
4694 4677
4695 // Match the full code generator stack by simulating an extra stack 4678 // Match the full code generator stack by simulating an extra stack
4696 // element for postfix operations in a non-effect context. 4679 // element for postfix operations in a non-effect context.
4697 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); 4680 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4698 HValue* before = has_extra ? Top() : Pop(); 4681 HValue* before = has_extra ? Top() : Pop();
4699 HInstruction* after = BuildIncrement(before, inc); 4682 HInstruction* after = BuildIncrement(before, inc);
4700 AddInstruction(after); 4683 AddInstruction(after);
4701 Push(after); 4684 Push(after);
4702 4685
4703 if (var->is_global()) { 4686 if (var->is_global()) {
4704 HandleGlobalVariableAssignment(var, 4687 HandleGlobalVariableAssignment(var,
4705 after, 4688 after,
4706 expr->position(), 4689 expr->position(),
4707 expr->AssignmentId()); 4690 expr->AssignmentId());
4691 } else if (var->IsStackAllocated()) {
4692 Bind(var, after);
4693 } else if (var->IsContextSlot()) {
4694 HValue* context = BuildContextChainWalk(var);
4695 int index = var->AsSlot()->index();
4696 HStoreContextSlot* instr = new HStoreContextSlot(context, index, after);
4697 AddInstruction(instr);
4698 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
4708 } else { 4699 } else {
4709 ASSERT(var->IsStackAllocated()); 4700 BAILOUT("lookup variable in count operation");
4710 Bind(var, after);
4711 } 4701 }
4712 Drop(has_extra ? 2 : 1); 4702 Drop(has_extra ? 2 : 1);
4713 ast_context()->ReturnValue(expr->is_postfix() ? before : after); 4703 ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4714 4704
4715 } else if (prop != NULL) { 4705 } else if (prop != NULL) {
4716 prop->RecordTypeFeedback(oracle()); 4706 prop->RecordTypeFeedback(oracle());
4717 4707
4718 if (prop->key()->IsPropertyName()) { 4708 if (prop->key()->IsPropertyName()) {
4719 // Named property. 4709 // Named property.
4720 4710
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
4779 if (load->HasSideEffects()) AddSimulate(increment->id()); 4769 if (load->HasSideEffects()) AddSimulate(increment->id());
4780 4770
4781 HValue* before = Pop(); 4771 HValue* before = Pop();
4782 // There is no deoptimization to after the increment, so we don't need 4772 // There is no deoptimization to after the increment, so we don't need
4783 // to simulate the expression stack after this instruction. 4773 // to simulate the expression stack after this instruction.
4784 HInstruction* after = BuildIncrement(before, inc); 4774 HInstruction* after = BuildIncrement(before, inc);
4785 AddInstruction(after); 4775 AddInstruction(after);
4786 4776
4787 HInstruction* store = is_fast_elements 4777 HInstruction* store = is_fast_elements
4788 ? BuildStoreKeyedFastElement(obj, key, after, prop) 4778 ? BuildStoreKeyedFastElement(obj, key, after, prop)
4789 : new HStoreKeyedGeneric(obj, key, after); 4779 : BuildStoreKeyedGeneric(obj, key, after);
4790 AddInstruction(store); 4780 AddInstruction(store);
4791 4781
4792 // Drop the key from the bailout environment. Overwrite the receiver 4782 // Drop the key from the bailout environment. Overwrite the receiver
4793 // with the result of the operation, and the placeholder with the 4783 // with the result of the operation, and the placeholder with the
4794 // original value if necessary. 4784 // original value if necessary.
4795 Drop(1); 4785 Drop(1);
4796 environment()->SetExpressionStackAt(0, after); 4786 environment()->SetExpressionStackAt(0, after);
4797 if (has_extra) environment()->SetExpressionStackAt(1, before); 4787 if (has_extra) environment()->SetExpressionStackAt(1, before);
4798 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 4788 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
4799 Drop(has_extra ? 2 : 1); 4789 Drop(has_extra ? 2 : 1);
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
4911 HBasicBlock* eval_right = graph()->CreateBasicBlock(); 4901 HBasicBlock* eval_right = graph()->CreateBasicBlock();
4912 if (is_logical_and) { 4902 if (is_logical_and) {
4913 VISIT_FOR_CONTROL(expr->left(), eval_right, context->if_false()); 4903 VISIT_FOR_CONTROL(expr->left(), eval_right, context->if_false());
4914 } else { 4904 } else {
4915 VISIT_FOR_CONTROL(expr->left(), context->if_true(), eval_right); 4905 VISIT_FOR_CONTROL(expr->left(), context->if_true(), eval_right);
4916 } 4906 }
4917 eval_right->SetJoinId(expr->RightId()); 4907 eval_right->SetJoinId(expr->RightId());
4918 4908
4919 // Translate right subexpression by visiting it in the same AST 4909 // Translate right subexpression by visiting it in the same AST
4920 // context as the entire expression. 4910 // context as the entire expression.
4921 subgraph()->set_exit_block(eval_right); 4911 set_current_block(eval_right);
4922 Visit(expr->right()); 4912 Visit(expr->right());
4923 4913
4924 } else { 4914 } else if (ast_context()->IsValue()) {
4925 VISIT_FOR_VALUE(expr->left()); 4915 VISIT_FOR_VALUE(expr->left());
4926 ASSERT(current_subgraph_->HasExit()); 4916 ASSERT(current_block() != NULL);
4927 4917
4928 HValue* left = Top(); 4918 HValue* left = Top();
4929 HEnvironment* environment_copy = environment()->Copy(); 4919 HEnvironment* environment_copy = environment()->Copy();
4930 environment_copy->Pop(); 4920 environment_copy->Pop();
4931 HSubgraph* right_subgraph; 4921 HSubgraph* right_subgraph;
4932 right_subgraph = CreateBranchSubgraph(environment_copy); 4922 right_subgraph = CreateBranchSubgraph(environment_copy);
4933 ADD_TO_SUBGRAPH(right_subgraph, expr->right()); 4923 ADD_TO_SUBGRAPH(right_subgraph, expr->right());
4934 current_subgraph_->AppendOptional(right_subgraph, is_logical_and, left); 4924
4935 current_subgraph_->exit_block()->SetJoinId(expr->id()); 4925 ASSERT(current_block() != NULL &&
4926 right_subgraph->exit_block() != NULL);
4927 // We need an extra block to maintain edge-split form.
4928 HBasicBlock* empty_block = graph()->CreateBasicBlock();
4929 HBasicBlock* join_block = graph()->CreateBasicBlock();
4930
4931 HTest* test = is_logical_and
4932 ? new HTest(left, right_subgraph->entry_block(), empty_block)
4933 : new HTest(left, empty_block, right_subgraph->entry_block());
4934 current_block()->Finish(test);
4935 empty_block->Goto(join_block);
4936 right_subgraph->exit_block()->Goto(join_block);
4937 join_block->SetJoinId(expr->id());
4938 set_current_block(join_block);
4936 ast_context()->ReturnValue(Pop()); 4939 ast_context()->ReturnValue(Pop());
4940 } else {
4941 ASSERT(ast_context()->IsEffect());
4942 // In an effect context, we don't need the value of the left
4943 // subexpression, only its control flow and side effects. We need an
4944 // extra block to maintain edge-split form.
4945 HBasicBlock* empty_block = graph()->CreateBasicBlock();
4946 HBasicBlock* right_block = graph()->CreateBasicBlock();
4947 HBasicBlock* join_block = graph()->CreateBasicBlock();
4948 if (is_logical_and) {
4949 VISIT_FOR_CONTROL(expr->left(), right_block, empty_block);
4950 } else {
4951 VISIT_FOR_CONTROL(expr->left(), empty_block, right_block);
4952 }
4953 // TODO(kmillikin): Find a way to fix this. It's ugly that there are
4954 // actually two empty blocks (one here and one inserted by
4955 // TestContext::BuildBranch, and that they both have an HSimulate
4956 // though the second one is not a merge node, and that we really have
4957 // no good AST ID to put on that first HSimulate.
4958 empty_block->SetJoinId(expr->id());
4959 right_block->SetJoinId(expr->RightId());
4960 set_current_block(right_block);
4961 VISIT_FOR_EFFECT(expr->right());
4962
4963 empty_block->Goto(join_block);
4964 current_block()->Goto(join_block);
4965 join_block->SetJoinId(expr->id());
4966 set_current_block(join_block);
4967 // We did not materialize any value in the predecessor environments,
4968 // so there is no need to handle it here.
4937 } 4969 }
4938 4970
4939 } else { 4971 } else {
4940 VISIT_FOR_VALUE(expr->left()); 4972 VISIT_FOR_VALUE(expr->left());
4941 VISIT_FOR_VALUE(expr->right()); 4973 VISIT_FOR_VALUE(expr->right());
4942 4974
4943 HValue* right = Pop(); 4975 HValue* right = Pop();
4944 HValue* left = Pop(); 4976 HValue* left = Pop();
4945 HInstruction* instr = BuildBinaryOperation(expr, left, right); 4977 HInstruction* instr = BuildBinaryOperation(expr, left, right);
4946 instr->set_position(expr->position()); 4978 instr->set_position(expr->position());
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
5036 // change and thus prefer the general IC code. 5068 // change and thus prefer the general IC code.
5037 if (!info->isolate()->heap()->InNewSpace(*candidate)) { 5069 if (!info->isolate()->heap()->InNewSpace(*candidate)) {
5038 target = candidate; 5070 target = candidate;
5039 } 5071 }
5040 } 5072 }
5041 } 5073 }
5042 5074
5043 // If the target is not null we have found a known global function that is 5075 // If the target is not null we have found a known global function that is
5044 // assumed to stay the same for this instanceof. 5076 // assumed to stay the same for this instanceof.
5045 if (target.is_null()) { 5077 if (target.is_null()) {
5046 instr = new HInstanceOf(left, right); 5078 HContext* context = new HContext;
5079 AddInstruction(context);
5080 instr = new HInstanceOf(context, left, right);
5047 } else { 5081 } else {
5048 AddInstruction(new HCheckFunction(right, target)); 5082 AddInstruction(new HCheckFunction(right, target));
5049 instr = new HInstanceOfKnownGlobal(left, target); 5083 instr = new HInstanceOfKnownGlobal(left, target);
5050 } 5084 }
5051 } else if (op == Token::IN) { 5085 } else if (op == Token::IN) {
5052 BAILOUT("Unsupported comparison: in"); 5086 BAILOUT("Unsupported comparison: in");
5053 } else if (info.IsNonPrimitive()) { 5087 } else if (info.IsNonPrimitive()) {
5054 switch (op) { 5088 switch (op) {
5055 case Token::EQ: 5089 case Token::EQ:
5056 case Token::EQ_STRICT: { 5090 case Token::EQ_STRICT: {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
5101 (slot != NULL && slot->type() == Slot::LOOKUP) || 5135 (slot != NULL && slot->type() == Slot::LOOKUP) ||
5102 decl->mode() == Variable::CONST || 5136 decl->mode() == Variable::CONST ||
5103 decl->fun() != NULL) { 5137 decl->fun() != NULL) {
5104 BAILOUT("unsupported declaration"); 5138 BAILOUT("unsupported declaration");
5105 } 5139 }
5106 } 5140 }
5107 5141
5108 5142
5109 // Generators for inline runtime functions. 5143 // Generators for inline runtime functions.
5110 // Support for types. 5144 // Support for types.
5111 void HGraphBuilder::GenerateIsSmi(int argument_count, int ast_id) { 5145 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) {
5112 ASSERT(argument_count == 1); 5146 ASSERT(call->arguments()->length() == 1);
5147 VISIT_FOR_VALUE(call->arguments()->at(0));
5113 HValue* value = Pop(); 5148 HValue* value = Pop();
5114 HIsSmi* result = new HIsSmi(value); 5149 HIsSmi* result = new HIsSmi(value);
5115 ast_context()->ReturnInstruction(result, ast_id); 5150 ast_context()->ReturnInstruction(result, call->id());
5116 } 5151 }
5117 5152
5118 5153
5119 void HGraphBuilder::GenerateIsSpecObject(int argument_count, int ast_id) { 5154 void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) {
5120 ASSERT(argument_count == 1); 5155 ASSERT(call->arguments()->length() == 1);
5156 VISIT_FOR_VALUE(call->arguments()->at(0));
5121 HValue* value = Pop(); 5157 HValue* value = Pop();
5122 HHasInstanceType* result = 5158 HHasInstanceType* result =
5123 new HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE); 5159 new HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE);
5124 ast_context()->ReturnInstruction(result, ast_id); 5160 ast_context()->ReturnInstruction(result, call->id());
5125 } 5161 }
5126 5162
5127 5163
5128 void HGraphBuilder::GenerateIsFunction(int argument_count, int ast_id) { 5164 void HGraphBuilder::GenerateIsFunction(CallRuntime* call) {
5129 ASSERT(argument_count == 1); 5165 ASSERT(call->arguments()->length() == 1);
5166 VISIT_FOR_VALUE(call->arguments()->at(0));
5130 HValue* value = Pop(); 5167 HValue* value = Pop();
5131 HHasInstanceType* result = new HHasInstanceType(value, JS_FUNCTION_TYPE); 5168 HHasInstanceType* result = new HHasInstanceType(value, JS_FUNCTION_TYPE);
5132 ast_context()->ReturnInstruction(result, ast_id); 5169 ast_context()->ReturnInstruction(result, call->id());
5133 } 5170 }
5134 5171
5135 5172
5136 void HGraphBuilder::GenerateHasCachedArrayIndex(int argument_count, 5173 void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
5137 int ast_id) { 5174 ASSERT(call->arguments()->length() == 1);
5138 ASSERT(argument_count == 1); 5175 VISIT_FOR_VALUE(call->arguments()->at(0));
5139 HValue* value = Pop(); 5176 HValue* value = Pop();
5140 HHasCachedArrayIndex* result = new HHasCachedArrayIndex(value); 5177 HHasCachedArrayIndex* result = new HHasCachedArrayIndex(value);
5141 ast_context()->ReturnInstruction(result, ast_id); 5178 ast_context()->ReturnInstruction(result, call->id());
5142 } 5179 }
5143 5180
5144 5181
5145 void HGraphBuilder::GenerateIsArray(int argument_count, int ast_id) { 5182 void HGraphBuilder::GenerateIsArray(CallRuntime* call) {
5146 ASSERT(argument_count == 1); 5183 ASSERT(call->arguments()->length() == 1);
5184 VISIT_FOR_VALUE(call->arguments()->at(0));
5147 HValue* value = Pop(); 5185 HValue* value = Pop();
5148 HHasInstanceType* result = new HHasInstanceType(value, JS_ARRAY_TYPE); 5186 HHasInstanceType* result = new HHasInstanceType(value, JS_ARRAY_TYPE);
5149 ast_context()->ReturnInstruction(result, ast_id); 5187 ast_context()->ReturnInstruction(result, call->id());
5150 } 5188 }
5151 5189
5152 5190
5153 void HGraphBuilder::GenerateIsRegExp(int argument_count, int ast_id) { 5191 void HGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
5154 ASSERT(argument_count == 1); 5192 ASSERT(call->arguments()->length() == 1);
5193 VISIT_FOR_VALUE(call->arguments()->at(0));
5155 HValue* value = Pop(); 5194 HValue* value = Pop();
5156 HHasInstanceType* result = new HHasInstanceType(value, JS_REGEXP_TYPE); 5195 HHasInstanceType* result = new HHasInstanceType(value, JS_REGEXP_TYPE);
5157 ast_context()->ReturnInstruction(result, ast_id); 5196 ast_context()->ReturnInstruction(result, call->id());
5158 } 5197 }
5159 5198
5160 5199
5161 void HGraphBuilder::GenerateIsObject(int argument_count, int ast_id) { 5200 void HGraphBuilder::GenerateIsObject(CallRuntime* call) {
5162 ASSERT(argument_count == 1); 5201 ASSERT(call->arguments()->length() == 1);
5163 5202 VISIT_FOR_VALUE(call->arguments()->at(0));
5164 HValue* value = Pop(); 5203 HValue* value = Pop();
5165 HIsObject* test = new HIsObject(value); 5204 HIsObject* test = new HIsObject(value);
5166 ast_context()->ReturnInstruction(test, ast_id); 5205 ast_context()->ReturnInstruction(test, call->id());
5167 } 5206 }
5168 5207
5169 5208
5170 void HGraphBuilder::GenerateIsNonNegativeSmi(int argument_count, 5209 void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) {
5171 int ast_id) {
5172 BAILOUT("inlined runtime function: IsNonNegativeSmi"); 5210 BAILOUT("inlined runtime function: IsNonNegativeSmi");
5173 } 5211 }
5174 5212
5175 5213
5176 void HGraphBuilder::GenerateIsUndetectableObject(int argument_count, 5214 void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
5177 int ast_id) {
5178 BAILOUT("inlined runtime function: IsUndetectableObject"); 5215 BAILOUT("inlined runtime function: IsUndetectableObject");
5179 } 5216 }
5180 5217
5181 5218
5182 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( 5219 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
5183 int argument_count, 5220 CallRuntime* call) {
5184 int ast_id) {
5185 BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); 5221 BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
5186 } 5222 }
5187 5223
5188 5224
5189 // Support for construct call checks. 5225 // Support for construct call checks.
5190 void HGraphBuilder::GenerateIsConstructCall(int argument_count, int ast_id) { 5226 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
5191 ASSERT(argument_count == 0); 5227 ASSERT(call->arguments()->length() == 0);
5192 ast_context()->ReturnInstruction(new HIsConstructCall, ast_id); 5228 ast_context()->ReturnInstruction(new HIsConstructCall, call->id());
5193 } 5229 }
5194 5230
5195 5231
5196 // Support for arguments.length and arguments[?]. 5232 // Support for arguments.length and arguments[?].
5197 void HGraphBuilder::GenerateArgumentsLength(int argument_count, int ast_id) { 5233 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
5198 ASSERT(argument_count == 0); 5234 ASSERT(call->arguments()->length() == 0);
5199 HInstruction* elements = AddInstruction(new HArgumentsElements); 5235 HInstruction* elements = AddInstruction(new HArgumentsElements);
5200 HArgumentsLength* result = new HArgumentsLength(elements); 5236 HArgumentsLength* result = new HArgumentsLength(elements);
5201 ast_context()->ReturnInstruction(result, ast_id); 5237 ast_context()->ReturnInstruction(result, call->id());
5202 } 5238 }
5203 5239
5204 5240
5205 void HGraphBuilder::GenerateArguments(int argument_count, int ast_id) { 5241 void HGraphBuilder::GenerateArguments(CallRuntime* call) {
5206 ASSERT(argument_count == 1); 5242 ASSERT(call->arguments()->length() == 1);
5243 VISIT_FOR_VALUE(call->arguments()->at(0));
5207 HValue* index = Pop(); 5244 HValue* index = Pop();
5208 HInstruction* elements = AddInstruction(new HArgumentsElements); 5245 HInstruction* elements = AddInstruction(new HArgumentsElements);
5209 HInstruction* length = AddInstruction(new HArgumentsLength(elements)); 5246 HInstruction* length = AddInstruction(new HArgumentsLength(elements));
5210 HAccessArgumentsAt* result = new HAccessArgumentsAt(elements, length, index); 5247 HAccessArgumentsAt* result = new HAccessArgumentsAt(elements, length, index);
5211 ast_context()->ReturnInstruction(result, ast_id); 5248 ast_context()->ReturnInstruction(result, call->id());
5212 } 5249 }
5213 5250
5214 5251
5215 // Support for accessing the class and value fields of an object. 5252 // Support for accessing the class and value fields of an object.
5216 void HGraphBuilder::GenerateClassOf(int argument_count, int ast_id) { 5253 void HGraphBuilder::GenerateClassOf(CallRuntime* call) {
5217 // The special form detected by IsClassOfTest is detected before we get here 5254 // The special form detected by IsClassOfTest is detected before we get here
5218 // and does not cause a bailout. 5255 // and does not cause a bailout.
5219 BAILOUT("inlined runtime function: ClassOf"); 5256 BAILOUT("inlined runtime function: ClassOf");
5220 } 5257 }
5221 5258
5222 5259
5223 void HGraphBuilder::GenerateValueOf(int argument_count, int ast_id) { 5260 void HGraphBuilder::GenerateValueOf(CallRuntime* call) {
5224 ASSERT(argument_count == 1); 5261 ASSERT(call->arguments()->length() == 1);
5262 VISIT_FOR_VALUE(call->arguments()->at(0));
5225 HValue* value = Pop(); 5263 HValue* value = Pop();
5226 HValueOf* result = new HValueOf(value); 5264 HValueOf* result = new HValueOf(value);
5227 ast_context()->ReturnInstruction(result, ast_id); 5265 ast_context()->ReturnInstruction(result, call->id());
5228 } 5266 }
5229 5267
5230 5268
5231 void HGraphBuilder::GenerateSetValueOf(int argument_count, int ast_id) { 5269 void HGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
5232 BAILOUT("inlined runtime function: SetValueOf"); 5270 BAILOUT("inlined runtime function: SetValueOf");
5233 } 5271 }
5234 5272
5235 5273
5236 // Fast support for charCodeAt(n). 5274 // Fast support for charCodeAt(n).
5237 void HGraphBuilder::GenerateStringCharCodeAt(int argument_count, int ast_id) { 5275 void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
5238 ASSERT(argument_count == 2); 5276 ASSERT(call->arguments()->length() == 2);
5277 VISIT_FOR_VALUE(call->arguments()->at(0));
5278 VISIT_FOR_VALUE(call->arguments()->at(1));
5239 HValue* index = Pop(); 5279 HValue* index = Pop();
5240 HValue* string = Pop(); 5280 HValue* string = Pop();
5241 HStringCharCodeAt* result = BuildStringCharCodeAt(string, index); 5281 HStringCharCodeAt* result = BuildStringCharCodeAt(string, index);
5242 ast_context()->ReturnInstruction(result, ast_id); 5282 ast_context()->ReturnInstruction(result, call->id());
5243 } 5283 }
5244 5284
5245 5285
5246 // Fast support for string.charAt(n) and string[n]. 5286 // Fast support for string.charAt(n) and string[n].
5247 void HGraphBuilder::GenerateStringCharFromCode(int argument_count, 5287 void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
5248 int ast_id) {
5249 BAILOUT("inlined runtime function: StringCharFromCode"); 5288 BAILOUT("inlined runtime function: StringCharFromCode");
5250 } 5289 }
5251 5290
5252 5291
5253 // Fast support for string.charAt(n) and string[n]. 5292 // Fast support for string.charAt(n) and string[n].
5254 void HGraphBuilder::GenerateStringCharAt(int argument_count, int ast_id) { 5293 void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
5255 ASSERT_EQ(2, argument_count); 5294 ASSERT_EQ(2, call->arguments()->length());
5256 PushArgumentsForStubCall(argument_count); 5295 VisitArgumentList(call->arguments());
5257 HCallStub* result = new HCallStub(CodeStub::StringCharAt, argument_count); 5296 CHECK_BAILOUT;
5258 ast_context()->ReturnInstruction(result, ast_id); 5297 HContext* context = new HContext;
5298 AddInstruction(context);
5299 HCallStub* result = new HCallStub(context, CodeStub::StringCharAt, 2);
5300 Drop(2);
5301 ast_context()->ReturnInstruction(result, call->id());
5259 } 5302 }
5260 5303
5261 5304
5262 // Fast support for object equality testing. 5305 // Fast support for object equality testing.
5263 void HGraphBuilder::GenerateObjectEquals(int argument_count, int ast_id) { 5306 void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
5264 ASSERT(argument_count == 2); 5307 ASSERT(call->arguments()->length() == 2);
5308 VISIT_FOR_VALUE(call->arguments()->at(0));
5309 VISIT_FOR_VALUE(call->arguments()->at(1));
5265 HValue* right = Pop(); 5310 HValue* right = Pop();
5266 HValue* left = Pop(); 5311 HValue* left = Pop();
5267 HCompareJSObjectEq* result = new HCompareJSObjectEq(left, right); 5312 HCompareJSObjectEq* result = new HCompareJSObjectEq(left, right);
5268 ast_context()->ReturnInstruction(result, ast_id); 5313 ast_context()->ReturnInstruction(result, call->id());
5269 } 5314 }
5270 5315
5271 5316
5272 void HGraphBuilder::GenerateLog(int argument_count, int ast_id) { 5317 void HGraphBuilder::GenerateLog(CallRuntime* call) {
5273 UNREACHABLE(); // We caught this in VisitCallRuntime. 5318 // %_Log is ignored in optimized code.
5319 ast_context()->ReturnValue(graph()->GetConstantUndefined());
5274 } 5320 }
5275 5321
5276 5322
5277 // Fast support for Math.random(). 5323 // Fast support for Math.random().
5278 void HGraphBuilder::GenerateRandomHeapNumber(int argument_count, int ast_id) { 5324 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) {
5279 BAILOUT("inlined runtime function: RandomHeapNumber"); 5325 BAILOUT("inlined runtime function: RandomHeapNumber");
5280 } 5326 }
5281 5327
5282 5328
5283 // Fast support for StringAdd. 5329 // Fast support for StringAdd.
5284 void HGraphBuilder::GenerateStringAdd(int argument_count, int ast_id) { 5330 void HGraphBuilder::GenerateStringAdd(CallRuntime* call) {
5285 ASSERT_EQ(2, argument_count); 5331 ASSERT_EQ(2, call->arguments()->length());
5286 PushArgumentsForStubCall(argument_count); 5332 VisitArgumentList(call->arguments());
5287 HCallStub* result = new HCallStub(CodeStub::StringAdd, argument_count); 5333 CHECK_BAILOUT;
5288 ast_context()->ReturnInstruction(result, ast_id); 5334 HContext* context = new HContext;
5335 AddInstruction(context);
5336 HCallStub* result = new HCallStub(context, CodeStub::StringAdd, 2);
5337 Drop(2);
5338 ast_context()->ReturnInstruction(result, call->id());
5289 } 5339 }
5290 5340
5291 5341
5292 // Fast support for SubString. 5342 // Fast support for SubString.
5293 void HGraphBuilder::GenerateSubString(int argument_count, int ast_id) { 5343 void HGraphBuilder::GenerateSubString(CallRuntime* call) {
5294 ASSERT_EQ(3, argument_count); 5344 ASSERT_EQ(3, call->arguments()->length());
5295 PushArgumentsForStubCall(argument_count); 5345 VisitArgumentList(call->arguments());
5296 HCallStub* result = new HCallStub(CodeStub::SubString, argument_count); 5346 CHECK_BAILOUT;
5297 ast_context()->ReturnInstruction(result, ast_id); 5347 HContext* context = new HContext;
5348 AddInstruction(context);
5349 HCallStub* result = new HCallStub(context, CodeStub::SubString, 3);
5350 Drop(3);
5351 ast_context()->ReturnInstruction(result, call->id());
5298 } 5352 }
5299 5353
5300 5354
5301 // Fast support for StringCompare. 5355 // Fast support for StringCompare.
5302 void HGraphBuilder::GenerateStringCompare(int argument_count, int ast_id) { 5356 void HGraphBuilder::GenerateStringCompare(CallRuntime* call) {
5303 ASSERT_EQ(2, argument_count); 5357 ASSERT_EQ(2, call->arguments()->length());
5304 PushArgumentsForStubCall(argument_count); 5358 VisitArgumentList(call->arguments());
5305 HCallStub* result = new HCallStub(CodeStub::StringCompare, argument_count); 5359 CHECK_BAILOUT;
5306 ast_context()->ReturnInstruction(result, ast_id); 5360 HContext* context = new HContext;
5361 AddInstruction(context);
5362 HCallStub* result = new HCallStub(context, CodeStub::StringCompare, 2);
5363 Drop(2);
5364 ast_context()->ReturnInstruction(result, call->id());
5307 } 5365 }
5308 5366
5309 5367
5310 // Support for direct calls from JavaScript to native RegExp code. 5368 // Support for direct calls from JavaScript to native RegExp code.
5311 void HGraphBuilder::GenerateRegExpExec(int argument_count, int ast_id) { 5369 void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
5312 ASSERT_EQ(4, argument_count); 5370 ASSERT_EQ(4, call->arguments()->length());
5313 PushArgumentsForStubCall(argument_count); 5371 VisitArgumentList(call->arguments());
5314 HCallStub* result = new HCallStub(CodeStub::RegExpExec, argument_count); 5372 CHECK_BAILOUT;
5315 ast_context()->ReturnInstruction(result, ast_id); 5373 HContext* context = new HContext;
5374 AddInstruction(context);
5375 HCallStub* result = new HCallStub(context, CodeStub::RegExpExec, 4);
5376 Drop(4);
5377 ast_context()->ReturnInstruction(result, call->id());
5316 } 5378 }
5317 5379
5318 5380
5319 // Construct a RegExp exec result with two in-object properties. 5381 // Construct a RegExp exec result with two in-object properties.
5320 void HGraphBuilder::GenerateRegExpConstructResult(int argument_count, 5382 void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
5321 int ast_id) { 5383 ASSERT_EQ(3, call->arguments()->length());
5322 ASSERT_EQ(3, argument_count); 5384 VisitArgumentList(call->arguments());
5323 PushArgumentsForStubCall(argument_count); 5385 CHECK_BAILOUT;
5386 HContext* context = new HContext;
5387 AddInstruction(context);
5324 HCallStub* result = 5388 HCallStub* result =
5325 new HCallStub(CodeStub::RegExpConstructResult, argument_count); 5389 new HCallStub(context, CodeStub::RegExpConstructResult, 3);
5326 ast_context()->ReturnInstruction(result, ast_id); 5390 Drop(3);
5391 ast_context()->ReturnInstruction(result, call->id());
5327 } 5392 }
5328 5393
5329 5394
5330 // Support for fast native caches. 5395 // Support for fast native caches.
5331 void HGraphBuilder::GenerateGetFromCache(int argument_count, int ast_id) { 5396 void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
5332 BAILOUT("inlined runtime function: GetFromCache"); 5397 BAILOUT("inlined runtime function: GetFromCache");
5333 } 5398 }
5334 5399
5335 5400
5336 // Fast support for number to string. 5401 // Fast support for number to string.
5337 void HGraphBuilder::GenerateNumberToString(int argument_count, int ast_id) { 5402 void HGraphBuilder::GenerateNumberToString(CallRuntime* call) {
5338 ASSERT_EQ(1, argument_count); 5403 ASSERT_EQ(1, call->arguments()->length());
5339 PushArgumentsForStubCall(argument_count); 5404 VisitArgumentList(call->arguments());
5340 HCallStub* result = new HCallStub(CodeStub::NumberToString, argument_count); 5405 CHECK_BAILOUT;
5341 ast_context()->ReturnInstruction(result, ast_id); 5406 HContext* context = new HContext;
5407 AddInstruction(context);
5408 HCallStub* result = new HCallStub(context, CodeStub::NumberToString, 1);
5409 Drop(1);
5410 ast_context()->ReturnInstruction(result, call->id());
5342 } 5411 }
5343 5412
5344 5413
5345 // Fast swapping of elements. Takes three expressions, the object and two 5414 // Fast swapping of elements. Takes three expressions, the object and two
5346 // indices. This should only be used if the indices are known to be 5415 // indices. This should only be used if the indices are known to be
5347 // non-negative and within bounds of the elements array at the call site. 5416 // non-negative and within bounds of the elements array at the call site.
5348 void HGraphBuilder::GenerateSwapElements(int argument_count, int ast_id) { 5417 void HGraphBuilder::GenerateSwapElements(CallRuntime* call) {
5349 BAILOUT("inlined runtime function: SwapElements"); 5418 BAILOUT("inlined runtime function: SwapElements");
5350 } 5419 }
5351 5420
5352 5421
5353 // Fast call for custom callbacks. 5422 // Fast call for custom callbacks.
5354 void HGraphBuilder::GenerateCallFunction(int argument_count, int ast_id) { 5423 void HGraphBuilder::GenerateCallFunction(CallRuntime* call) {
5355 BAILOUT("inlined runtime function: CallFunction"); 5424 BAILOUT("inlined runtime function: CallFunction");
5356 } 5425 }
5357 5426
5358 5427
5359 // Fast call to math functions. 5428 // Fast call to math functions.
5360 void HGraphBuilder::GenerateMathPow(int argument_count, int ast_id) { 5429 void HGraphBuilder::GenerateMathPow(CallRuntime* call) {
5361 ASSERT_EQ(2, argument_count); 5430 ASSERT_EQ(2, call->arguments()->length());
5431 VISIT_FOR_VALUE(call->arguments()->at(0));
5432 VISIT_FOR_VALUE(call->arguments()->at(1));
5362 HValue* right = Pop(); 5433 HValue* right = Pop();
5363 HValue* left = Pop(); 5434 HValue* left = Pop();
5364 HPower* result = new HPower(left, right); 5435 HPower* result = new HPower(left, right);
5365 ast_context()->ReturnInstruction(result, ast_id); 5436 ast_context()->ReturnInstruction(result, call->id());
5366 } 5437 }
5367 5438
5368 5439
5369 void HGraphBuilder::GenerateMathSin(int argument_count, int ast_id) { 5440 void HGraphBuilder::GenerateMathSin(CallRuntime* call) {
5370 ASSERT_EQ(1, argument_count); 5441 ASSERT_EQ(1, call->arguments()->length());
5371 PushArgumentsForStubCall(argument_count); 5442 VisitArgumentList(call->arguments());
5372 HCallStub* result = 5443 CHECK_BAILOUT;
5373 new HCallStub(CodeStub::TranscendentalCache, argument_count); 5444 HContext* context = new HContext;
5445 AddInstruction(context);
5446 HCallStub* result = new HCallStub(context, CodeStub::TranscendentalCache, 1);
5374 result->set_transcendental_type(TranscendentalCache::SIN); 5447 result->set_transcendental_type(TranscendentalCache::SIN);
5375 ast_context()->ReturnInstruction(result, ast_id); 5448 Drop(1);
5376 } 5449 ast_context()->ReturnInstruction(result, call->id());
5377 5450 }
5378 5451
5379 void HGraphBuilder::GenerateMathCos(int argument_count, int ast_id) { 5452
5380 ASSERT_EQ(1, argument_count); 5453 void HGraphBuilder::GenerateMathCos(CallRuntime* call) {
5381 PushArgumentsForStubCall(argument_count); 5454 ASSERT_EQ(1, call->arguments()->length());
5382 HCallStub* result = 5455 VisitArgumentList(call->arguments());
5383 new HCallStub(CodeStub::TranscendentalCache, argument_count); 5456 CHECK_BAILOUT;
5457 HContext* context = new HContext;
5458 AddInstruction(context);
5459 HCallStub* result = new HCallStub(context, CodeStub::TranscendentalCache, 1);
5384 result->set_transcendental_type(TranscendentalCache::COS); 5460 result->set_transcendental_type(TranscendentalCache::COS);
5385 ast_context()->ReturnInstruction(result, ast_id); 5461 Drop(1);
5386 } 5462 ast_context()->ReturnInstruction(result, call->id());
5387 5463 }
5388 5464
5389 void HGraphBuilder::GenerateMathLog(int argument_count, int ast_id) { 5465
5390 ASSERT_EQ(1, argument_count); 5466 void HGraphBuilder::GenerateMathLog(CallRuntime* call) {
5391 PushArgumentsForStubCall(argument_count); 5467 ASSERT_EQ(1, call->arguments()->length());
5392 HCallStub* result = 5468 VisitArgumentList(call->arguments());
5393 new HCallStub(CodeStub::TranscendentalCache, argument_count); 5469 CHECK_BAILOUT;
5470 HContext* context = new HContext;
5471 AddInstruction(context);
5472 HCallStub* result = new HCallStub(context, CodeStub::TranscendentalCache, 1);
5394 result->set_transcendental_type(TranscendentalCache::LOG); 5473 result->set_transcendental_type(TranscendentalCache::LOG);
5395 ast_context()->ReturnInstruction(result, ast_id); 5474 Drop(1);
5396 } 5475 ast_context()->ReturnInstruction(result, call->id());
5397 5476 }
5398 5477
5399 void HGraphBuilder::GenerateMathSqrt(int argument_count, int ast_id) { 5478
5479 void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
5400 BAILOUT("inlined runtime function: MathSqrt"); 5480 BAILOUT("inlined runtime function: MathSqrt");
5401 } 5481 }
5402 5482
5403 5483
5404 // Check whether two RegExps are equivalent 5484 // Check whether two RegExps are equivalent
5405 void HGraphBuilder::GenerateIsRegExpEquivalent(int argument_count, 5485 void HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) {
5406 int ast_id) {
5407 BAILOUT("inlined runtime function: IsRegExpEquivalent"); 5486 BAILOUT("inlined runtime function: IsRegExpEquivalent");
5408 } 5487 }
5409 5488
5410 5489
5411 void HGraphBuilder::GenerateGetCachedArrayIndex(int argument_count, 5490 void HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
5412 int ast_id) { 5491 ASSERT(call->arguments()->length() == 1);
5413 BAILOUT("inlined runtime function: GetCachedArrayIndex"); 5492 VISIT_FOR_VALUE(call->arguments()->at(0));
5414 } 5493 HValue* value = Pop();
5415 5494 HGetCachedArrayIndex* result = new HGetCachedArrayIndex(value);
5416 5495 ast_context()->ReturnInstruction(result, call->id());
5417 void HGraphBuilder::GenerateFastAsciiArrayJoin(int argument_count, 5496 }
5418 int ast_id) { 5497
5498
5499 void HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) {
5419 BAILOUT("inlined runtime function: FastAsciiArrayJoin"); 5500 BAILOUT("inlined runtime function: FastAsciiArrayJoin");
5420 } 5501 }
5421 5502
5422 5503
5423 #undef BAILOUT 5504 #undef BAILOUT
5424 #undef CHECK_BAILOUT 5505 #undef CHECK_BAILOUT
5425 #undef VISIT_FOR_EFFECT 5506 #undef VISIT_FOR_EFFECT
5426 #undef VISIT_FOR_VALUE 5507 #undef VISIT_FOR_VALUE
5427 #undef ADD_TO_SUBGRAPH 5508 #undef ADD_TO_SUBGRAPH
5428 5509
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
5809 if (range->IsChild()) { 5890 if (range->IsChild()) {
5810 parent_index = range->parent()->id(); 5891 parent_index = range->parent()->id();
5811 } else { 5892 } else {
5812 parent_index = range->id(); 5893 parent_index = range->id();
5813 } 5894 }
5814 LOperand* op = range->FirstHint(); 5895 LOperand* op = range->FirstHint();
5815 int hint_index = -1; 5896 int hint_index = -1;
5816 if (op != NULL && op->IsUnallocated()) hint_index = op->VirtualRegister(); 5897 if (op != NULL && op->IsUnallocated()) hint_index = op->VirtualRegister();
5817 trace_.Add(" %d %d", parent_index, hint_index); 5898 trace_.Add(" %d %d", parent_index, hint_index);
5818 UseInterval* cur_interval = range->first_interval(); 5899 UseInterval* cur_interval = range->first_interval();
5819 while (cur_interval != NULL) { 5900 while (cur_interval != NULL && range->Covers(cur_interval->start())) {
5820 trace_.Add(" [%d, %d[", 5901 trace_.Add(" [%d, %d[",
5821 cur_interval->start().Value(), 5902 cur_interval->start().Value(),
5822 cur_interval->end().Value()); 5903 cur_interval->end().Value());
5823 cur_interval = cur_interval->next(); 5904 cur_interval = cur_interval->next();
5824 } 5905 }
5825 5906
5826 UsePosition* current_pos = range->first_pos(); 5907 UsePosition* current_pos = range->first_pos();
5827 while (current_pos != NULL) { 5908 while (current_pos != NULL) {
5828 if (current_pos->RegisterIsBeneficial()) { 5909 if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
5829 trace_.Add(" %d M", current_pos->pos().Value()); 5910 trace_.Add(" %d M", current_pos->pos().Value());
5830 } 5911 }
5831 current_pos = current_pos->next(); 5912 current_pos = current_pos->next();
5832 } 5913 }
5833 5914
5834 trace_.Add(" \"\"\n"); 5915 trace_.Add(" \"\"\n");
5835 } 5916 }
5836 } 5917 }
5837 5918
5838 5919
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
5926 } 6007 }
5927 } 6008 }
5928 6009
5929 #ifdef DEBUG 6010 #ifdef DEBUG
5930 if (graph_ != NULL) graph_->Verify(); 6011 if (graph_ != NULL) graph_->Verify();
5931 if (allocator_ != NULL) allocator_->Verify(); 6012 if (allocator_ != NULL) allocator_->Verify();
5932 #endif 6013 #endif
5933 } 6014 }
5934 6015
5935 } } // namespace v8::internal 6016 } } // 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