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

Side by Side Diff: src/hydrogen.cc

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 5 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 15 matching lines...) Expand all
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 #include "hydrogen.h" 29 #include "hydrogen.h"
30 30
31 #include "codegen.h" 31 #include "codegen.h"
32 #include "full-codegen.h" 32 #include "full-codegen.h"
33 #include "hashmap.h" 33 #include "hashmap.h"
34 #include "lithium-allocator.h" 34 #include "lithium-allocator.h"
35 #include "parser.h" 35 #include "parser.h"
36 #include "scopeinfo.h"
36 #include "scopes.h" 37 #include "scopes.h"
37 #include "stub-cache.h" 38 #include "stub-cache.h"
38 39
39 #if V8_TARGET_ARCH_IA32 40 #if V8_TARGET_ARCH_IA32
40 #include "ia32/lithium-codegen-ia32.h" 41 #include "ia32/lithium-codegen-ia32.h"
41 #elif V8_TARGET_ARCH_X64 42 #elif V8_TARGET_ARCH_X64
42 #include "x64/lithium-codegen-x64.h" 43 #include "x64/lithium-codegen-x64.h"
43 #elif V8_TARGET_ARCH_ARM 44 #elif V8_TARGET_ARCH_ARM
44 #include "arm/lithium-codegen-arm.h" 45 #include "arm/lithium-codegen-arm.h"
45 #elif V8_TARGET_ARCH_MIPS 46 #elif V8_TARGET_ARCH_MIPS
(...skipping 15 matching lines...) Expand all
61 loop_information_(NULL), 62 loop_information_(NULL),
62 predecessors_(2), 63 predecessors_(2),
63 dominator_(NULL), 64 dominator_(NULL),
64 dominated_blocks_(4), 65 dominated_blocks_(4),
65 last_environment_(NULL), 66 last_environment_(NULL),
66 argument_count_(-1), 67 argument_count_(-1),
67 first_instruction_index_(-1), 68 first_instruction_index_(-1),
68 last_instruction_index_(-1), 69 last_instruction_index_(-1),
69 deleted_phis_(4), 70 deleted_phis_(4),
70 parent_loop_header_(NULL), 71 parent_loop_header_(NULL),
71 is_inline_return_target_(false) { 72 is_inline_return_target_(false),
72 } 73 is_deoptimizing_(false) { }
73 74
74 75
75 void HBasicBlock::AttachLoopInformation() { 76 void HBasicBlock::AttachLoopInformation() {
76 ASSERT(!IsLoopHeader()); 77 ASSERT(!IsLoopHeader());
77 loop_information_ = new(zone()) HLoopInformation(this); 78 loop_information_ = new(zone()) HLoopInformation(this);
78 } 79 }
79 80
80 81
81 void HBasicBlock::DetachLoopInformation() { 82 void HBasicBlock::DetachLoopInformation() {
82 ASSERT(IsLoopHeader()); 83 ASSERT(IsLoopHeader());
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 HDeoptimize* instr = new(zone()) HDeoptimize(environment->length()); 125 HDeoptimize* instr = new(zone()) HDeoptimize(environment->length());
125 for (int i = 0; i < environment->length(); i++) { 126 for (int i = 0; i < environment->length(); i++) {
126 HValue* val = environment->values()->at(i); 127 HValue* val = environment->values()->at(i);
127 instr->AddEnvironmentValue(val); 128 instr->AddEnvironmentValue(val);
128 } 129 }
129 130
130 return instr; 131 return instr;
131 } 132 }
132 133
133 134
134 HSimulate* HBasicBlock::CreateSimulate(int id) { 135 HSimulate* HBasicBlock::CreateSimulate(int ast_id) {
135 ASSERT(HasEnvironment()); 136 ASSERT(HasEnvironment());
136 HEnvironment* environment = last_environment(); 137 HEnvironment* environment = last_environment();
137 ASSERT(id == AstNode::kNoNumber || 138 ASSERT(ast_id == AstNode::kNoNumber ||
138 environment->closure()->shared()->VerifyBailoutId(id)); 139 environment->closure()->shared()->VerifyBailoutId(ast_id));
139 140
140 int push_count = environment->push_count(); 141 int push_count = environment->push_count();
141 int pop_count = environment->pop_count(); 142 int pop_count = environment->pop_count();
142 143
143 HSimulate* instr = new(zone()) HSimulate(id, pop_count); 144 HSimulate* instr = new(zone()) HSimulate(ast_id, pop_count);
144 for (int i = push_count - 1; i >= 0; --i) { 145 for (int i = push_count - 1; i >= 0; --i) {
145 instr->AddPushedValue(environment->ExpressionStackAt(i)); 146 instr->AddPushedValue(environment->ExpressionStackAt(i));
146 } 147 }
147 for (int i = 0; i < environment->assigned_variables()->length(); ++i) { 148 for (int i = 0; i < environment->assigned_variables()->length(); ++i) {
148 int index = environment->assigned_variables()->at(i); 149 int index = environment->assigned_variables()->at(i);
149 instr->AddAssignedValue(index, environment->Lookup(index)); 150 instr->AddAssignedValue(index, environment->Lookup(index));
150 } 151 }
151 environment->ClearHistory(); 152 environment->ClearHistory();
152 return instr; 153 return instr;
153 } 154 }
154 155
155 156
156 void HBasicBlock::Finish(HControlInstruction* end) { 157 void HBasicBlock::Finish(HControlInstruction* end) {
157 ASSERT(!IsFinished()); 158 ASSERT(!IsFinished());
158 AddInstruction(end); 159 AddInstruction(end);
159 end_ = end; 160 end_ = end;
160 if (end->FirstSuccessor() != NULL) { 161 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
161 end->FirstSuccessor()->RegisterPredecessor(this); 162 it.Current()->RegisterPredecessor(this);
162 if (end->SecondSuccessor() != NULL) {
163 end->SecondSuccessor()->RegisterPredecessor(this);
164 }
165 } 163 }
166 } 164 }
167 165
168 166
169 void HBasicBlock::Goto(HBasicBlock* block, bool include_stack_check) { 167 void HBasicBlock::Goto(HBasicBlock* block) {
170 if (block->IsInlineReturnTarget()) { 168 if (block->IsInlineReturnTarget()) {
171 AddInstruction(new(zone()) HLeaveInlined); 169 AddInstruction(new(zone()) HLeaveInlined);
172 last_environment_ = last_environment()->outer(); 170 last_environment_ = last_environment()->outer();
173 } 171 }
174 AddSimulate(AstNode::kNoNumber); 172 AddSimulate(AstNode::kNoNumber);
175 HGoto* instr = new(zone()) HGoto(block); 173 HGoto* instr = new(zone()) HGoto(block);
176 instr->set_include_stack_check(include_stack_check);
177 Finish(instr); 174 Finish(instr);
178 } 175 }
179 176
180 177
181 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { 178 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) {
182 ASSERT(target->IsInlineReturnTarget()); 179 ASSERT(target->IsInlineReturnTarget());
183 ASSERT(return_value != NULL); 180 ASSERT(return_value != NULL);
184 AddInstruction(new(zone()) HLeaveInlined); 181 AddInstruction(new(zone()) HLeaveInlined);
185 last_environment_ = last_environment()->outer(); 182 last_environment_ = last_environment()->outer();
186 last_environment()->Push(return_value); 183 last_environment()->Push(return_value);
187 AddSimulate(AstNode::kNoNumber); 184 AddSimulate(AstNode::kNoNumber);
188 HGoto* instr = new(zone()) HGoto(target); 185 HGoto* instr = new(zone()) HGoto(target);
189 Finish(instr); 186 Finish(instr);
190 } 187 }
191 188
192 189
193 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { 190 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
194 ASSERT(!HasEnvironment()); 191 ASSERT(!HasEnvironment());
195 ASSERT(first() == NULL); 192 ASSERT(first() == NULL);
196 UpdateEnvironment(env); 193 UpdateEnvironment(env);
197 } 194 }
198 195
199 196
200 void HBasicBlock::SetJoinId(int id) { 197 void HBasicBlock::SetJoinId(int ast_id) {
201 int length = predecessors_.length(); 198 int length = predecessors_.length();
202 ASSERT(length > 0); 199 ASSERT(length > 0);
203 for (int i = 0; i < length; i++) { 200 for (int i = 0; i < length; i++) {
204 HBasicBlock* predecessor = predecessors_[i]; 201 HBasicBlock* predecessor = predecessors_[i];
205 ASSERT(predecessor->end()->IsGoto()); 202 ASSERT(predecessor->end()->IsGoto());
206 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous()); 203 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous());
207 // We only need to verify the ID once. 204 // We only need to verify the ID once.
208 ASSERT(i != 0 || 205 ASSERT(i != 0 ||
209 predecessor->last_environment()->closure()->shared() 206 predecessor->last_environment()->closure()->shared()
210 ->VerifyBailoutId(id)); 207 ->VerifyBailoutId(ast_id));
211 simulate->set_ast_id(id); 208 simulate->set_ast_id(ast_id);
212 } 209 }
213 } 210 }
214 211
215 212
216 bool HBasicBlock::Dominates(HBasicBlock* other) const { 213 bool HBasicBlock::Dominates(HBasicBlock* other) const {
217 HBasicBlock* current = other->dominator(); 214 HBasicBlock* current = other->dominator();
218 while (current != NULL) { 215 while (current != NULL) {
219 if (current == this) return true; 216 if (current == this) return true;
220 current = current->dominator(); 217 current = current->dominator();
221 } 218 }
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 !reachable_.Contains(block->block_id())) { 391 !reachable_.Contains(block->block_id())) {
395 reachable_.Add(block->block_id()); 392 reachable_.Add(block->block_id());
396 stack_.Add(block); 393 stack_.Add(block);
397 visited_count_++; 394 visited_count_++;
398 } 395 }
399 } 396 }
400 397
401 void Analyze() { 398 void Analyze() {
402 while (!stack_.is_empty()) { 399 while (!stack_.is_empty()) {
403 HControlInstruction* end = stack_.RemoveLast()->end(); 400 HControlInstruction* end = stack_.RemoveLast()->end();
404 PushBlock(end->FirstSuccessor()); 401 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
405 PushBlock(end->SecondSuccessor()); 402 PushBlock(it.Current());
403 }
406 } 404 }
407 } 405 }
408 406
409 int visited_count_; 407 int visited_count_;
410 ZoneList<HBasicBlock*> stack_; 408 ZoneList<HBasicBlock*> stack_;
411 BitVector reachable_; 409 BitVector reachable_;
412 HBasicBlock* dont_visit_; 410 HBasicBlock* dont_visit_;
413 }; 411 };
414 412
415 413
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 512
515 HConstant* HGraph::GetConstantTrue() { 513 HConstant* HGraph::GetConstantTrue() {
516 return GetConstant(&constant_true_, isolate()->heap()->true_value()); 514 return GetConstant(&constant_true_, isolate()->heap()->true_value());
517 } 515 }
518 516
519 517
520 HConstant* HGraph::GetConstantFalse() { 518 HConstant* HGraph::GetConstantFalse() {
521 return GetConstant(&constant_false_, isolate()->heap()->false_value()); 519 return GetConstant(&constant_false_, isolate()->heap()->false_value());
522 } 520 }
523 521
522
523 HConstant* HGraph::GetConstantHole() {
524 return GetConstant(&constant_hole_, isolate()->heap()->the_hole_value());
525 }
526
527
524 HGraphBuilder::HGraphBuilder(CompilationInfo* info, 528 HGraphBuilder::HGraphBuilder(CompilationInfo* info,
525 TypeFeedbackOracle* oracle) 529 TypeFeedbackOracle* oracle)
526 : function_state_(NULL), 530 : function_state_(NULL),
527 initial_function_state_(this, info, oracle), 531 initial_function_state_(this, info, oracle),
528 ast_context_(NULL), 532 ast_context_(NULL),
529 break_scope_(NULL), 533 break_scope_(NULL),
530 graph_(NULL), 534 graph_(NULL),
531 current_block_(NULL), 535 current_block_(NULL),
532 inlined_count_(0), 536 inlined_count_(0),
533 zone_(info->isolate()->zone()), 537 zone_(info->isolate()->zone()),
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
565 } 569 }
566 return exit_block; 570 return exit_block;
567 } 571 }
568 572
569 573
570 HBasicBlock* HGraphBuilder::CreateLoop(IterationStatement* statement, 574 HBasicBlock* HGraphBuilder::CreateLoop(IterationStatement* statement,
571 HBasicBlock* loop_entry, 575 HBasicBlock* loop_entry,
572 HBasicBlock* body_exit, 576 HBasicBlock* body_exit,
573 HBasicBlock* loop_successor, 577 HBasicBlock* loop_successor,
574 HBasicBlock* break_block) { 578 HBasicBlock* break_block) {
575 if (body_exit != NULL) body_exit->Goto(loop_entry, true); 579 if (body_exit != NULL) body_exit->Goto(loop_entry);
576 loop_entry->PostProcessLoopHeader(statement); 580 loop_entry->PostProcessLoopHeader(statement);
577 if (break_block != NULL) { 581 if (break_block != NULL) {
578 if (loop_successor != NULL) loop_successor->Goto(break_block); 582 if (loop_successor != NULL) loop_successor->Goto(break_block);
579 break_block->SetJoinId(statement->ExitId()); 583 break_block->SetJoinId(statement->ExitId());
580 return break_block; 584 return break_block;
581 } 585 }
582 return loop_successor; 586 return loop_successor;
583 } 587 }
584 588
585 589
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 } 688 }
685 } 689 }
686 690
687 691
688 void HGraph::PostorderLoopBlocks(HLoopInformation* loop, 692 void HGraph::PostorderLoopBlocks(HLoopInformation* loop,
689 BitVector* visited, 693 BitVector* visited,
690 ZoneList<HBasicBlock*>* order, 694 ZoneList<HBasicBlock*>* order,
691 HBasicBlock* loop_header) { 695 HBasicBlock* loop_header) {
692 for (int i = 0; i < loop->blocks()->length(); ++i) { 696 for (int i = 0; i < loop->blocks()->length(); ++i) {
693 HBasicBlock* b = loop->blocks()->at(i); 697 HBasicBlock* b = loop->blocks()->at(i);
694 Postorder(b->end()->SecondSuccessor(), visited, order, loop_header); 698 for (HSuccessorIterator it(b->end()); !it.Done(); it.Advance()) {
695 Postorder(b->end()->FirstSuccessor(), visited, order, loop_header); 699 Postorder(it.Current(), visited, order, loop_header);
700 }
696 if (b->IsLoopHeader() && b != loop->loop_header()) { 701 if (b->IsLoopHeader() && b != loop->loop_header()) {
697 PostorderLoopBlocks(b->loop_information(), visited, order, loop_header); 702 PostorderLoopBlocks(b->loop_information(), visited, order, loop_header);
698 } 703 }
699 } 704 }
700 } 705 }
701 706
702 707
703 void HGraph::Postorder(HBasicBlock* block, 708 void HGraph::Postorder(HBasicBlock* block,
704 BitVector* visited, 709 BitVector* visited,
705 ZoneList<HBasicBlock*>* order, 710 ZoneList<HBasicBlock*>* order,
706 HBasicBlock* loop_header) { 711 HBasicBlock* loop_header) {
707 if (block == NULL || visited->Contains(block->block_id())) return; 712 if (block == NULL || visited->Contains(block->block_id())) return;
708 if (block->parent_loop_header() != loop_header) return; 713 if (block->parent_loop_header() != loop_header) return;
709 visited->Add(block->block_id()); 714 visited->Add(block->block_id());
710 if (block->IsLoopHeader()) { 715 if (block->IsLoopHeader()) {
711 PostorderLoopBlocks(block->loop_information(), visited, order, loop_header); 716 PostorderLoopBlocks(block->loop_information(), visited, order, loop_header);
712 Postorder(block->end()->SecondSuccessor(), visited, order, block); 717 for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) {
713 Postorder(block->end()->FirstSuccessor(), visited, order, block); 718 Postorder(it.Current(), visited, order, block);
719 }
714 } else { 720 } else {
715 Postorder(block->end()->SecondSuccessor(), visited, order, loop_header); 721 for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) {
716 Postorder(block->end()->FirstSuccessor(), visited, order, loop_header); 722 Postorder(it.Current(), visited, order, loop_header);
723 }
717 } 724 }
718 ASSERT(block->end()->FirstSuccessor() == NULL || 725 ASSERT(block->end()->FirstSuccessor() == NULL ||
719 order->Contains(block->end()->FirstSuccessor()) || 726 order->Contains(block->end()->FirstSuccessor()) ||
720 block->end()->FirstSuccessor()->IsLoopHeader()); 727 block->end()->FirstSuccessor()->IsLoopHeader());
721 ASSERT(block->end()->SecondSuccessor() == NULL || 728 ASSERT(block->end()->SecondSuccessor() == NULL ||
722 order->Contains(block->end()->SecondSuccessor()) || 729 order->Contains(block->end()->SecondSuccessor()) ||
723 block->end()->SecondSuccessor()->IsLoopHeader()); 730 block->end()->SecondSuccessor()->IsLoopHeader());
724 order->Add(block); 731 order->Add(block);
725 } 732 }
726 733
727 734
728 void HGraph::AssignDominators() { 735 void HGraph::AssignDominators() {
729 HPhase phase("Assign dominators", this); 736 HPhase phase("Assign dominators", this);
730 for (int i = 0; i < blocks_.length(); ++i) { 737 for (int i = 0; i < blocks_.length(); ++i) {
731 if (blocks_[i]->IsLoopHeader()) { 738 if (blocks_[i]->IsLoopHeader()) {
732 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->first()); 739 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->first());
733 } else { 740 } else {
734 for (int j = 0; j < blocks_[i]->predecessors()->length(); ++j) { 741 for (int j = 0; j < blocks_[i]->predecessors()->length(); ++j) {
735 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); 742 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
736 } 743 }
737 } 744 }
738 } 745 }
746
747 // Propagate flag marking blocks containing unconditional deoptimize.
748 MarkAsDeoptimizingRecursively(entry_block());
739 } 749 }
740 750
741 751
752 // Mark all blocks that are dominated by an unconditional deoptimize.
753 void HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) {
754 for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
755 HBasicBlock* dominated = block->dominated_blocks()->at(i);
756 if (block->IsDeoptimizing()) dominated->MarkAsDeoptimizing();
757 MarkAsDeoptimizingRecursively(dominated);
758 }
759 }
760
742 void HGraph::EliminateRedundantPhis() { 761 void HGraph::EliminateRedundantPhis() {
743 HPhase phase("Redundant phi elimination", this); 762 HPhase phase("Redundant phi elimination", this);
744 763
745 // Worklist of phis that can potentially be eliminated. Initialized with 764 // Worklist of phis that can potentially be eliminated. Initialized with
746 // all phi nodes. When elimination of a phi node modifies another phi node 765 // all phi nodes. When elimination of a phi node modifies another phi node
747 // the modified phi node is added to the worklist. 766 // the modified phi node is added to the worklist.
748 ZoneList<HPhi*> worklist(blocks_.length()); 767 ZoneList<HPhi*> worklist(blocks_.length());
749 for (int i = 0; i < blocks_.length(); ++i) { 768 for (int i = 0; i < blocks_.length(); ++i) {
750 worklist.AddAll(*blocks_[i]->phis()); 769 worklist.AddAll(*blocks_[i]->phis());
751 } 770 }
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
819 838
820 bool HGraph::CollectPhis() { 839 bool HGraph::CollectPhis() {
821 int block_count = blocks_.length(); 840 int block_count = blocks_.length();
822 phi_list_ = new ZoneList<HPhi*>(block_count); 841 phi_list_ = new ZoneList<HPhi*>(block_count);
823 for (int i = 0; i < block_count; ++i) { 842 for (int i = 0; i < block_count; ++i) {
824 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { 843 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
825 HPhi* phi = blocks_[i]->phis()->at(j); 844 HPhi* phi = blocks_[i]->phis()->at(j);
826 phi_list_->Add(phi); 845 phi_list_->Add(phi);
827 // We don't support phi uses of arguments for now. 846 // We don't support phi uses of arguments for now.
828 if (phi->CheckFlag(HValue::kIsArguments)) return false; 847 if (phi->CheckFlag(HValue::kIsArguments)) return false;
848 // Check for the hole value (from an uninitialized const).
849 for (int k = 0; k < phi->OperandCount(); k++) {
850 if (phi->OperandAt(k) == GetConstantHole()) return false;
851 }
829 } 852 }
830 } 853 }
831 return true; 854 return true;
832 } 855 }
833 856
834 857
835 void HGraph::InferTypes(ZoneList<HValue*>* worklist) { 858 void HGraph::InferTypes(ZoneList<HValue*>* worklist) {
836 BitVector in_worklist(GetMaximumValueID()); 859 BitVector in_worklist(GetMaximumValueID());
837 for (int i = 0; i < worklist->length(); ++i) { 860 for (int i = 0; i < worklist->length(); ++i) {
838 ASSERT(!in_worklist.Contains(worklist->at(i)->id())); 861 ASSERT(!in_worklist.Contains(worklist->at(i)->id()));
(...skipping 18 matching lines...) Expand all
857 880
858 class HRangeAnalysis BASE_EMBEDDED { 881 class HRangeAnalysis BASE_EMBEDDED {
859 public: 882 public:
860 explicit HRangeAnalysis(HGraph* graph) : graph_(graph), changed_ranges_(16) {} 883 explicit HRangeAnalysis(HGraph* graph) : graph_(graph), changed_ranges_(16) {}
861 884
862 void Analyze(); 885 void Analyze();
863 886
864 private: 887 private:
865 void TraceRange(const char* msg, ...); 888 void TraceRange(const char* msg, ...);
866 void Analyze(HBasicBlock* block); 889 void Analyze(HBasicBlock* block);
867 void InferControlFlowRange(HTest* test, HBasicBlock* dest); 890 void InferControlFlowRange(HCompareIDAndBranch* test, HBasicBlock* dest);
868 void InferControlFlowRange(Token::Value op, HValue* value, HValue* other); 891 void UpdateControlFlowRange(Token::Value op, HValue* value, HValue* other);
869 void InferPhiRange(HPhi* phi);
870 void InferRange(HValue* value); 892 void InferRange(HValue* value);
871 void RollBackTo(int index); 893 void RollBackTo(int index);
872 void AddRange(HValue* value, Range* range); 894 void AddRange(HValue* value, Range* range);
873 895
874 HGraph* graph_; 896 HGraph* graph_;
875 ZoneList<HValue*> changed_ranges_; 897 ZoneList<HValue*> changed_ranges_;
876 }; 898 };
877 899
878 900
879 void HRangeAnalysis::TraceRange(const char* msg, ...) { 901 void HRangeAnalysis::TraceRange(const char* msg, ...) {
880 if (FLAG_trace_range) { 902 if (FLAG_trace_range) {
881 va_list arguments; 903 va_list arguments;
882 va_start(arguments, msg); 904 va_start(arguments, msg);
883 OS::VPrint(msg, arguments); 905 OS::VPrint(msg, arguments);
884 va_end(arguments); 906 va_end(arguments);
885 } 907 }
886 } 908 }
887 909
888 910
889 void HRangeAnalysis::Analyze() { 911 void HRangeAnalysis::Analyze() {
890 HPhase phase("Range analysis", graph_); 912 HPhase phase("Range analysis", graph_);
891 Analyze(graph_->blocks()->at(0)); 913 Analyze(graph_->entry_block());
892 } 914 }
893 915
894 916
895 void HRangeAnalysis::Analyze(HBasicBlock* block) { 917 void HRangeAnalysis::Analyze(HBasicBlock* block) {
896 TraceRange("Analyzing block B%d\n", block->block_id()); 918 TraceRange("Analyzing block B%d\n", block->block_id());
897 919
898 int last_changed_range = changed_ranges_.length() - 1; 920 int last_changed_range = changed_ranges_.length() - 1;
899 921
900 // Infer range based on control flow. 922 // Infer range based on control flow.
901 if (block->predecessors()->length() == 1) { 923 if (block->predecessors()->length() == 1) {
902 HBasicBlock* pred = block->predecessors()->first(); 924 HBasicBlock* pred = block->predecessors()->first();
903 if (pred->end()->IsTest()) { 925 if (pred->end()->IsCompareIDAndBranch()) {
904 InferControlFlowRange(HTest::cast(pred->end()), block); 926 InferControlFlowRange(HCompareIDAndBranch::cast(pred->end()), block);
905 } 927 }
906 } 928 }
907 929
908 // Process phi instructions. 930 // Process phi instructions.
909 for (int i = 0; i < block->phis()->length(); ++i) { 931 for (int i = 0; i < block->phis()->length(); ++i) {
910 HPhi* phi = block->phis()->at(i); 932 HPhi* phi = block->phis()->at(i);
911 InferPhiRange(phi); 933 InferRange(phi);
912 } 934 }
913 935
914 // Go through all instructions of the current block. 936 // Go through all instructions of the current block.
915 HInstruction* instr = block->first(); 937 HInstruction* instr = block->first();
916 while (instr != block->end()) { 938 while (instr != block->end()) {
917 InferRange(instr); 939 InferRange(instr);
918 instr = instr->next(); 940 instr = instr->next();
919 } 941 }
920 942
921 // Continue analysis in all dominated blocks. 943 // Continue analysis in all dominated blocks.
922 for (int i = 0; i < block->dominated_blocks()->length(); ++i) { 944 for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
923 Analyze(block->dominated_blocks()->at(i)); 945 Analyze(block->dominated_blocks()->at(i));
924 } 946 }
925 947
926 RollBackTo(last_changed_range); 948 RollBackTo(last_changed_range);
927 } 949 }
928 950
929 951
930 void HRangeAnalysis::InferControlFlowRange(HTest* test, HBasicBlock* dest) { 952 void HRangeAnalysis::InferControlFlowRange(HCompareIDAndBranch* test,
953 HBasicBlock* dest) {
931 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest)); 954 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest));
932 if (test->value()->IsCompare()) { 955 if (test->GetInputRepresentation().IsInteger32()) {
933 HCompare* compare = HCompare::cast(test->value()); 956 Token::Value op = test->token();
934 if (compare->GetInputRepresentation().IsInteger32()) { 957 if (test->SecondSuccessor() == dest) {
935 Token::Value op = compare->token(); 958 op = Token::NegateCompareOp(op);
936 if (test->SecondSuccessor() == dest) {
937 op = Token::NegateCompareOp(op);
938 }
939 Token::Value inverted_op = Token::InvertCompareOp(op);
940 InferControlFlowRange(op, compare->left(), compare->right());
941 InferControlFlowRange(inverted_op, compare->right(), compare->left());
942 } 959 }
960 Token::Value inverted_op = Token::InvertCompareOp(op);
961 UpdateControlFlowRange(op, test->left(), test->right());
962 UpdateControlFlowRange(inverted_op, test->right(), test->left());
943 } 963 }
944 } 964 }
945 965
946 966
947 // We know that value [op] other. Use this information to update the range on 967 // We know that value [op] other. Use this information to update the range on
948 // value. 968 // value.
949 void HRangeAnalysis::InferControlFlowRange(Token::Value op, 969 void HRangeAnalysis::UpdateControlFlowRange(Token::Value op,
950 HValue* value, 970 HValue* value,
951 HValue* other) { 971 HValue* other) {
952 Range temp_range; 972 Range temp_range;
953 Range* range = other->range() != NULL ? other->range() : &temp_range; 973 Range* range = other->range() != NULL ? other->range() : &temp_range;
954 Range* new_range = NULL; 974 Range* new_range = NULL;
955 975
956 TraceRange("Control flow range infer %d %s %d\n", 976 TraceRange("Control flow range infer %d %s %d\n",
957 value->id(), 977 value->id(),
958 Token::Name(op), 978 Token::Name(op),
959 other->id()); 979 other->id());
960 980
961 if (op == Token::EQ || op == Token::EQ_STRICT) { 981 if (op == Token::EQ || op == Token::EQ_STRICT) {
(...skipping 10 matching lines...) Expand all
972 new_range->AddConstant(1); 992 new_range->AddConstant(1);
973 } 993 }
974 } 994 }
975 995
976 if (new_range != NULL && !new_range->IsMostGeneric()) { 996 if (new_range != NULL && !new_range->IsMostGeneric()) {
977 AddRange(value, new_range); 997 AddRange(value, new_range);
978 } 998 }
979 } 999 }
980 1000
981 1001
982 void HRangeAnalysis::InferPhiRange(HPhi* phi) {
983 // TODO(twuerthinger): Infer loop phi ranges.
984 InferRange(phi);
985 }
986
987
988 void HRangeAnalysis::InferRange(HValue* value) { 1002 void HRangeAnalysis::InferRange(HValue* value) {
989 ASSERT(!value->HasRange()); 1003 ASSERT(!value->HasRange());
990 if (!value->representation().IsNone()) { 1004 if (!value->representation().IsNone()) {
991 value->ComputeInitialRange(); 1005 value->ComputeInitialRange();
992 Range* range = value->range(); 1006 Range* range = value->range();
993 TraceRange("Initial inferred range of %d (%s) set to [%d,%d]\n", 1007 TraceRange("Initial inferred range of %d (%s) set to [%d,%d]\n",
994 value->id(), 1008 value->id(),
995 value->Mnemonic(), 1009 value->Mnemonic(),
996 range->lower(), 1010 range->lower(),
997 range->upper()); 1011 range->upper());
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
1204 } 1218 }
1205 1219
1206 1220
1207 class HStackCheckEliminator BASE_EMBEDDED { 1221 class HStackCheckEliminator BASE_EMBEDDED {
1208 public: 1222 public:
1209 explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { } 1223 explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { }
1210 1224
1211 void Process(); 1225 void Process();
1212 1226
1213 private: 1227 private:
1214 void RemoveStackCheck(HBasicBlock* block);
1215
1216 HGraph* graph_; 1228 HGraph* graph_;
1217 }; 1229 };
1218 1230
1219 1231
1220 void HStackCheckEliminator::Process() { 1232 void HStackCheckEliminator::Process() {
1221 // For each loop block walk the dominator tree from the backwards branch to 1233 // For each loop block walk the dominator tree from the backwards branch to
1222 // the loop header. If a call instruction is encountered the backwards branch 1234 // the loop header. If a call instruction is encountered the backwards branch
1223 // is dominated by a call and the stack check in the backwards branch can be 1235 // is dominated by a call and the stack check in the backwards branch can be
1224 // removed. 1236 // removed.
1225 for (int i = 0; i < graph_->blocks()->length(); i++) { 1237 for (int i = 0; i < graph_->blocks()->length(); i++) {
1226 HBasicBlock* block = graph_->blocks()->at(i); 1238 HBasicBlock* block = graph_->blocks()->at(i);
1227 if (block->IsLoopHeader()) { 1239 if (block->IsLoopHeader()) {
1228 HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge(); 1240 HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge();
1229 HBasicBlock* dominator = back_edge; 1241 HBasicBlock* dominator = back_edge;
1230 bool back_edge_dominated_by_call = false; 1242 while (true) {
1231 while (dominator != block && !back_edge_dominated_by_call) {
1232 HInstruction* instr = dominator->first(); 1243 HInstruction* instr = dominator->first();
1233 while (instr != NULL && !back_edge_dominated_by_call) { 1244 while (instr != NULL) {
1234 if (instr->IsCall()) { 1245 if (instr->IsCall()) {
1235 RemoveStackCheck(back_edge); 1246 block->loop_information()->stack_check()->Eliminate();
1236 back_edge_dominated_by_call = true; 1247 break;
1237 } 1248 }
1238 instr = instr->next(); 1249 instr = instr->next();
1239 } 1250 }
1251
1252 // Done when the loop header is processed.
1253 if (dominator == block) break;
1254
1255 // Move up the dominator tree.
1240 dominator = dominator->dominator(); 1256 dominator = dominator->dominator();
1241 } 1257 }
1242 } 1258 }
1243 } 1259 }
1244 } 1260 }
1245 1261
1246 1262
1247 void HStackCheckEliminator::RemoveStackCheck(HBasicBlock* block) {
1248 HInstruction* instr = block->first();
1249 while (instr != NULL) {
1250 if (instr->IsGoto()) {
1251 HGoto::cast(instr)->set_include_stack_check(false);
1252 return;
1253 }
1254 instr = instr->next();
1255 }
1256 }
1257
1258
1259 // Simple sparse set with O(1) add, contains, and clear. 1263 // Simple sparse set with O(1) add, contains, and clear.
1260 class SparseSet { 1264 class SparseSet {
1261 public: 1265 public:
1262 SparseSet(Zone* zone, int capacity) 1266 SparseSet(Zone* zone, int capacity)
1263 : capacity_(capacity), 1267 : capacity_(capacity),
1264 length_(0), 1268 length_(0),
1265 dense_(zone->NewArray<int>(capacity)), 1269 dense_(zone->NewArray<int>(capacity)),
1266 sparse_(zone->NewArray<int>(capacity)) {} 1270 sparse_(zone->NewArray<int>(capacity)) {
1271 #ifndef NVALGRIND
1272 // Initialize the sparse array to make valgrind happy.
1273 memset(sparse_, 0, sizeof(sparse_[0]) * capacity);
1274 #endif
1275 }
1267 1276
1268 bool Contains(int n) const { 1277 bool Contains(int n) const {
1269 ASSERT(0 <= n && n < capacity_); 1278 ASSERT(0 <= n && n < capacity_);
1270 int d = sparse_[n]; 1279 int d = sparse_[n];
1271 return 0 <= d && d < length_ && dense_[d] == n; 1280 return 0 <= d && d < length_ && dense_[d] == n;
1272 } 1281 }
1273 1282
1274 bool Add(int n) { 1283 bool Add(int n) {
1275 if (Contains(n)) return false; 1284 if (Contains(n)) return false;
1276 dense_[length_] = n; 1285 dense_[length_] = n;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1339 SparseSet visited_on_paths_; 1348 SparseSet visited_on_paths_;
1340 }; 1349 };
1341 1350
1342 1351
1343 void HGlobalValueNumberer::Analyze() { 1352 void HGlobalValueNumberer::Analyze() {
1344 ComputeBlockSideEffects(); 1353 ComputeBlockSideEffects();
1345 if (FLAG_loop_invariant_code_motion) { 1354 if (FLAG_loop_invariant_code_motion) {
1346 LoopInvariantCodeMotion(); 1355 LoopInvariantCodeMotion();
1347 } 1356 }
1348 HValueMap* map = new(zone()) HValueMap(); 1357 HValueMap* map = new(zone()) HValueMap();
1349 AnalyzeBlock(graph_->blocks()->at(0), map); 1358 AnalyzeBlock(graph_->entry_block(), map);
1350 } 1359 }
1351 1360
1352 1361
1353 void HGlobalValueNumberer::ComputeBlockSideEffects() { 1362 void HGlobalValueNumberer::ComputeBlockSideEffects() {
1354 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { 1363 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) {
1355 // Compute side effects for the block. 1364 // Compute side effects for the block.
1356 HBasicBlock* block = graph_->blocks()->at(i); 1365 HBasicBlock* block = graph_->blocks()->at(i);
1357 HInstruction* instr = block->first(); 1366 HInstruction* instr = block->first();
1358 int id = block->block_id(); 1367 int id = block->block_id();
1359 int side_effects = 0; 1368 int side_effects = 0;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1431 } 1440 }
1432 1441
1433 1442
1434 bool HGlobalValueNumberer::AllowCodeMotion() { 1443 bool HGlobalValueNumberer::AllowCodeMotion() {
1435 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount; 1444 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount;
1436 } 1445 }
1437 1446
1438 1447
1439 bool HGlobalValueNumberer::ShouldMove(HInstruction* instr, 1448 bool HGlobalValueNumberer::ShouldMove(HInstruction* instr,
1440 HBasicBlock* loop_header) { 1449 HBasicBlock* loop_header) {
1441 // If we've disabled code motion, don't move any instructions. 1450 // If we've disabled code motion or we're in a block that unconditionally
1442 if (!AllowCodeMotion()) return false; 1451 // deoptimizes, don't move any instructions.
1443 1452 return AllowCodeMotion() && !instr->block()->IsDeoptimizing();
1444 // If --aggressive-loop-invariant-motion, move everything except change
1445 // instructions.
1446 if (FLAG_aggressive_loop_invariant_motion && !instr->IsChange()) {
1447 return true;
1448 }
1449
1450 // Otherwise only move instructions that postdominate the loop header
1451 // (i.e. are always executed inside the loop). This is to avoid
1452 // unnecessary deoptimizations assuming the loop is executed at least
1453 // once. TODO(fschneider): Better type feedback should give us
1454 // information about code that was never executed.
1455 HBasicBlock* block = instr->block();
1456 bool result = true;
1457 if (block != loop_header) {
1458 for (int i = 1; i < loop_header->predecessors()->length(); ++i) {
1459 bool found = false;
1460 HBasicBlock* pred = loop_header->predecessors()->at(i);
1461 while (pred != loop_header) {
1462 if (pred == block) found = true;
1463 pred = pred->dominator();
1464 }
1465 if (!found) {
1466 result = false;
1467 break;
1468 }
1469 }
1470 }
1471 return result;
1472 } 1453 }
1473 1454
1474 1455
1475 int HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock( 1456 int HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock(
1476 HBasicBlock* dominator, HBasicBlock* dominated) { 1457 HBasicBlock* dominator, HBasicBlock* dominated) {
1477 int side_effects = 0; 1458 int side_effects = 0;
1478 for (int i = 0; i < dominated->predecessors()->length(); ++i) { 1459 for (int i = 0; i < dominated->predecessors()->length(); ++i) {
1479 HBasicBlock* block = dominated->predecessors()->at(i); 1460 HBasicBlock* block = dominated->predecessors()->at(i);
1480 if (dominator->block_id() < block->block_id() && 1461 if (dominator->block_id() < block->block_id() &&
1481 block->block_id() < dominated->block_id() && 1462 block->block_id() < dominated->block_id() &&
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after
1834 } else { 1815 } else {
1835 next = HInstruction::cast(use_value); 1816 next = HInstruction::cast(use_value);
1836 } 1817 }
1837 1818
1838 // For constants we try to make the representation change at compile 1819 // For constants we try to make the representation change at compile
1839 // time. When a representation change is not possible without loss of 1820 // time. When a representation change is not possible without loss of
1840 // information we treat constants like normal instructions and insert the 1821 // information we treat constants like normal instructions and insert the
1841 // change instructions for them. 1822 // change instructions for them.
1842 HInstruction* new_value = NULL; 1823 HInstruction* new_value = NULL;
1843 bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32); 1824 bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32);
1825 bool deoptimize_on_undefined =
1826 use_value->CheckFlag(HValue::kDeoptimizeOnUndefined);
1844 if (value->IsConstant()) { 1827 if (value->IsConstant()) {
1845 HConstant* constant = HConstant::cast(value); 1828 HConstant* constant = HConstant::cast(value);
1846 // Try to create a new copy of the constant with the new representation. 1829 // Try to create a new copy of the constant with the new representation.
1847 new_value = is_truncating 1830 new_value = is_truncating
1848 ? constant->CopyToTruncatedInt32() 1831 ? constant->CopyToTruncatedInt32()
1849 : constant->CopyToRepresentation(to); 1832 : constant->CopyToRepresentation(to);
1850 } 1833 }
1851 1834
1852 if (new_value == NULL) { 1835 if (new_value == NULL) {
1853 new_value = 1836 new_value = new(zone()) HChange(value, value->representation(), to,
1854 new(zone()) HChange(value, value->representation(), to, is_truncating); 1837 is_truncating, deoptimize_on_undefined);
1855 } 1838 }
1856 1839
1857 new_value->InsertBefore(next); 1840 new_value->InsertBefore(next);
1858 use_value->SetOperandAt(use_index, new_value); 1841 use_value->SetOperandAt(use_index, new_value);
1859 } 1842 }
1860 1843
1861 1844
1862 void HGraph::InsertRepresentationChangesForValue(HValue* value) { 1845 void HGraph::InsertRepresentationChangesForValue(HValue* value) {
1863 Representation r = value->representation(); 1846 Representation r = value->representation();
1864 if (r.IsNone()) return; 1847 if (r.IsNone()) return;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1926 // Process normal instructions. 1909 // Process normal instructions.
1927 HInstruction* current = blocks_[i]->first(); 1910 HInstruction* current = blocks_[i]->first();
1928 while (current != NULL) { 1911 while (current != NULL) {
1929 InsertRepresentationChangesForValue(current); 1912 InsertRepresentationChangesForValue(current);
1930 current = current->next(); 1913 current = current->next();
1931 } 1914 }
1932 } 1915 }
1933 } 1916 }
1934 1917
1935 1918
1919 void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) {
1920 if (phi->CheckFlag(HValue::kDeoptimizeOnUndefined)) return;
1921 phi->SetFlag(HValue::kDeoptimizeOnUndefined);
1922 for (int i = 0; i < phi->OperandCount(); ++i) {
1923 HValue* input = phi->OperandAt(i);
1924 if (input->IsPhi()) {
1925 RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi::cast(input));
1926 }
1927 }
1928 }
1929
1930
1931 void HGraph::MarkDeoptimizeOnUndefined() {
1932 HPhase phase("MarkDeoptimizeOnUndefined", this);
1933 // Compute DeoptimizeOnUndefined flag for phis.
1934 // Any phi that can reach a use with DeoptimizeOnUndefined set must
1935 // have DeoptimizeOnUndefined set. Currently only HCompareIDAndBranch, with
1936 // double input representation, has this flag set.
1937 // The flag is used by HChange tagged->double, which must deoptimize
1938 // if one of its uses has this flag set.
1939 for (int i = 0; i < phi_list()->length(); i++) {
1940 HPhi* phi = phi_list()->at(i);
1941 if (phi->representation().IsDouble()) {
1942 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
1943 if (it.value()->CheckFlag(HValue::kDeoptimizeOnUndefined)) {
1944 RecursivelyMarkPhiDeoptimizeOnUndefined(phi);
1945 break;
1946 }
1947 }
1948 }
1949 }
1950 }
1951
1952
1936 void HGraph::ComputeMinusZeroChecks() { 1953 void HGraph::ComputeMinusZeroChecks() {
1937 BitVector visited(GetMaximumValueID()); 1954 BitVector visited(GetMaximumValueID());
1938 for (int i = 0; i < blocks_.length(); ++i) { 1955 for (int i = 0; i < blocks_.length(); ++i) {
1939 for (HInstruction* current = blocks_[i]->first(); 1956 for (HInstruction* current = blocks_[i]->first();
1940 current != NULL; 1957 current != NULL;
1941 current = current->next()) { 1958 current = current->next()) {
1942 if (current->IsChange()) { 1959 if (current->IsChange()) {
1943 HChange* change = HChange::cast(current); 1960 HChange* change = HChange::cast(current);
1944 // Propagate flags for negative zero checks upwards from conversions 1961 // Propagate flags for negative zero checks upwards from conversions
1945 // int32-to-tagged and int32-to-double. 1962 // int32-to-tagged and int32-to-double.
(...skipping 23 matching lines...) Expand all
1969 function_return_(NULL), 1986 function_return_(NULL),
1970 test_context_(NULL), 1987 test_context_(NULL),
1971 outer_(owner->function_state()) { 1988 outer_(owner->function_state()) {
1972 if (outer_ != NULL) { 1989 if (outer_ != NULL) {
1973 // State for an inline function. 1990 // State for an inline function.
1974 if (owner->ast_context()->IsTest()) { 1991 if (owner->ast_context()->IsTest()) {
1975 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); 1992 HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
1976 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); 1993 HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
1977 if_true->MarkAsInlineReturnTarget(); 1994 if_true->MarkAsInlineReturnTarget();
1978 if_false->MarkAsInlineReturnTarget(); 1995 if_false->MarkAsInlineReturnTarget();
1996 Expression* cond = TestContext::cast(owner->ast_context())->condition();
1979 // The AstContext constructor pushed on the context stack. This newed 1997 // The AstContext constructor pushed on the context stack. This newed
1980 // instance is the reason that AstContext can't be BASE_EMBEDDED. 1998 // instance is the reason that AstContext can't be BASE_EMBEDDED.
1981 test_context_ = new TestContext(owner, if_true, if_false); 1999 test_context_ = new TestContext(owner, cond, if_true, if_false);
1982 } else { 2000 } else {
1983 function_return_ = owner->graph()->CreateBasicBlock(); 2001 function_return_ = owner->graph()->CreateBasicBlock();
1984 function_return()->MarkAsInlineReturnTarget(); 2002 function_return()->MarkAsInlineReturnTarget();
1985 } 2003 }
1986 // Set this after possibly allocating a new TestContext above. 2004 // Set this after possibly allocating a new TestContext above.
1987 call_context_ = owner->ast_context(); 2005 call_context_ = owner->ast_context();
1988 } 2006 }
1989 2007
1990 // Push on the state stack. 2008 // Push on the state stack.
1991 owner->set_function_state(this); 2009 owner->set_function_state(this);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2045 owner()->Push(value); 2063 owner()->Push(value);
2046 } 2064 }
2047 2065
2048 2066
2049 void TestContext::ReturnValue(HValue* value) { 2067 void TestContext::ReturnValue(HValue* value) {
2050 BuildBranch(value); 2068 BuildBranch(value);
2051 } 2069 }
2052 2070
2053 2071
2054 void EffectContext::ReturnInstruction(HInstruction* instr, int ast_id) { 2072 void EffectContext::ReturnInstruction(HInstruction* instr, int ast_id) {
2073 ASSERT(!instr->IsControlInstruction());
2055 owner()->AddInstruction(instr); 2074 owner()->AddInstruction(instr);
2056 if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); 2075 if (instr->HasSideEffects()) owner()->AddSimulate(ast_id);
2057 } 2076 }
2058 2077
2059 2078
2079 void EffectContext::ReturnControl(HControlInstruction* instr, int ast_id) {
2080 ASSERT(!instr->HasSideEffects());
2081 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
2082 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
2083 instr->SetSuccessorAt(0, empty_true);
2084 instr->SetSuccessorAt(1, empty_false);
2085 owner()->current_block()->Finish(instr);
2086 HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id);
2087 owner()->set_current_block(join);
2088 }
2089
2090
2060 void ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) { 2091 void ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) {
2092 ASSERT(!instr->IsControlInstruction());
2061 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { 2093 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
2062 owner()->Bailout("bad value context for arguments object value"); 2094 return owner()->Bailout("bad value context for arguments object value");
2063 } 2095 }
2064 owner()->AddInstruction(instr); 2096 owner()->AddInstruction(instr);
2065 owner()->Push(instr); 2097 owner()->Push(instr);
2066 if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); 2098 if (instr->HasSideEffects()) owner()->AddSimulate(ast_id);
2067 } 2099 }
2068 2100
2069 2101
2102 void ValueContext::ReturnControl(HControlInstruction* instr, int ast_id) {
2103 ASSERT(!instr->HasSideEffects());
2104 if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
2105 return owner()->Bailout("bad value context for arguments object value");
2106 }
2107 HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
2108 HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
2109 instr->SetSuccessorAt(0, materialize_true);
2110 instr->SetSuccessorAt(1, materialize_false);
2111 owner()->current_block()->Finish(instr);
2112 owner()->set_current_block(materialize_true);
2113 owner()->Push(owner()->graph()->GetConstantTrue());
2114 owner()->set_current_block(materialize_false);
2115 owner()->Push(owner()->graph()->GetConstantFalse());
2116 HBasicBlock* join =
2117 owner()->CreateJoin(materialize_true, materialize_false, ast_id);
2118 owner()->set_current_block(join);
2119 }
2120
2121
2070 void TestContext::ReturnInstruction(HInstruction* instr, int ast_id) { 2122 void TestContext::ReturnInstruction(HInstruction* instr, int ast_id) {
2123 ASSERT(!instr->IsControlInstruction());
2071 HGraphBuilder* builder = owner(); 2124 HGraphBuilder* builder = owner();
2072 builder->AddInstruction(instr); 2125 builder->AddInstruction(instr);
2073 // We expect a simulate after every expression with side effects, though 2126 // We expect a simulate after every expression with side effects, though
2074 // this one isn't actually needed (and wouldn't work if it were targeted). 2127 // this one isn't actually needed (and wouldn't work if it were targeted).
2075 if (instr->HasSideEffects()) { 2128 if (instr->HasSideEffects()) {
2076 builder->Push(instr); 2129 builder->Push(instr);
2077 builder->AddSimulate(ast_id); 2130 builder->AddSimulate(ast_id);
2078 builder->Pop(); 2131 builder->Pop();
2079 } 2132 }
2080 BuildBranch(instr); 2133 BuildBranch(instr);
2081 } 2134 }
2082 2135
2083 2136
2137 void TestContext::ReturnControl(HControlInstruction* instr, int ast_id) {
2138 ASSERT(!instr->HasSideEffects());
2139 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
2140 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
2141 instr->SetSuccessorAt(0, empty_true);
2142 instr->SetSuccessorAt(1, empty_false);
2143 owner()->current_block()->Finish(instr);
2144 empty_true->Goto(if_true());
2145 empty_false->Goto(if_false());
2146 owner()->set_current_block(NULL);
2147 }
2148
2149
2084 void TestContext::BuildBranch(HValue* value) { 2150 void TestContext::BuildBranch(HValue* value) {
2085 // We expect the graph to be in edge-split form: there is no edge that 2151 // We expect the graph to be in edge-split form: there is no edge that
2086 // connects a branch node to a join node. We conservatively ensure that 2152 // connects a branch node to a join node. We conservatively ensure that
2087 // property by always adding an empty block on the outgoing edges of this 2153 // property by always adding an empty block on the outgoing edges of this
2088 // branch. 2154 // branch.
2089 HGraphBuilder* builder = owner(); 2155 HGraphBuilder* builder = owner();
2090 if (value->CheckFlag(HValue::kIsArguments)) { 2156 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
2091 builder->Bailout("arguments object value in a test context"); 2157 builder->Bailout("arguments object value in a test context");
2092 } 2158 }
2093 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); 2159 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
2094 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); 2160 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
2095 HTest* test = new(zone()) HTest(value, empty_true, empty_false); 2161 HBranch* test = new(zone()) HBranch(value, empty_true, empty_false);
2096 builder->current_block()->Finish(test); 2162 builder->current_block()->Finish(test);
2097 2163
2098 empty_true->Goto(if_true(), false); 2164 empty_true->Goto(if_true());
2099 empty_false->Goto(if_false(), false); 2165 empty_false->Goto(if_false());
2100 builder->set_current_block(NULL); 2166 builder->set_current_block(NULL);
2101 } 2167 }
2102 2168
2103 2169
2104 // HGraphBuilder infrastructure for bailing out and checking bailouts. 2170 // HGraphBuilder infrastructure for bailing out and checking bailouts.
2105 #define CHECK_BAILOUT(call) \ 2171 #define CHECK_BAILOUT(call) \
2106 do { \ 2172 do { \
2107 call; \ 2173 call; \
2108 if (HasStackOverflow()) return; \ 2174 if (HasStackOverflow()) return; \
2109 } while (false) 2175 } while (false)
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2141 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); 2207 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
2142 for_value.set_for_typeof(true); 2208 for_value.set_for_typeof(true);
2143 Visit(expr); 2209 Visit(expr);
2144 } 2210 }
2145 2211
2146 2212
2147 2213
2148 void HGraphBuilder::VisitForControl(Expression* expr, 2214 void HGraphBuilder::VisitForControl(Expression* expr,
2149 HBasicBlock* true_block, 2215 HBasicBlock* true_block,
2150 HBasicBlock* false_block) { 2216 HBasicBlock* false_block) {
2151 TestContext for_test(this, true_block, false_block); 2217 TestContext for_test(this, expr, true_block, false_block);
2152 Visit(expr); 2218 Visit(expr);
2153 } 2219 }
2154 2220
2155 2221
2156 void HGraphBuilder::VisitArgument(Expression* expr) { 2222 HValue* HGraphBuilder::VisitArgument(Expression* expr) {
2157 CHECK_ALIVE(VisitForValue(expr)); 2223 VisitForValue(expr);
2158 Push(AddInstruction(new(zone()) HPushArgument(Pop()))); 2224 if (HasStackOverflow() || current_block() == NULL) return NULL;
2225 HValue* value = Pop();
2226 Push(AddInstruction(new(zone()) HPushArgument(value)));
2227 return value;
2159 } 2228 }
2160 2229
2161 2230
2162 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { 2231 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) {
2163 for (int i = 0; i < arguments->length(); i++) { 2232 for (int i = 0; i < arguments->length(); i++) {
2164 CHECK_ALIVE(VisitArgument(arguments->at(i))); 2233 CHECK_ALIVE(VisitArgument(arguments->at(i)));
2165 } 2234 }
2166 } 2235 }
2167 2236
2168 2237
(...skipping 12 matching lines...) Expand all
2181 HPhase phase("Block building"); 2250 HPhase phase("Block building");
2182 current_block_ = graph()->entry_block(); 2251 current_block_ = graph()->entry_block();
2183 2252
2184 Scope* scope = info()->scope(); 2253 Scope* scope = info()->scope();
2185 if (scope->HasIllegalRedeclaration()) { 2254 if (scope->HasIllegalRedeclaration()) {
2186 Bailout("function with illegal redeclaration"); 2255 Bailout("function with illegal redeclaration");
2187 return NULL; 2256 return NULL;
2188 } 2257 }
2189 SetupScope(scope); 2258 SetupScope(scope);
2190 VisitDeclarations(scope->declarations()); 2259 VisitDeclarations(scope->declarations());
2191 AddInstruction(new(zone()) HStackCheck()); 2260 HValue* context = environment()->LookupContext();
2261 AddInstruction(
2262 new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry));
2192 2263
2193 // Add an edge to the body entry. This is warty: the graph's start 2264 // Add an edge to the body entry. This is warty: the graph's start
2194 // environment will be used by the Lithium translation as the initial 2265 // environment will be used by the Lithium translation as the initial
2195 // environment on graph entry, but it has now been mutated by the 2266 // environment on graph entry, but it has now been mutated by the
2196 // Hydrogen translation of the instructions in the start block. This 2267 // Hydrogen translation of the instructions in the start block. This
2197 // environment uses values which have not been defined yet. These 2268 // environment uses values which have not been defined yet. These
2198 // Hydrogen instructions will then be replayed by the Lithium 2269 // Hydrogen instructions will then be replayed by the Lithium
2199 // translation, so they cannot have an environment effect. The edge to 2270 // translation, so they cannot have an environment effect. The edge to
2200 // the body's entry block (along with some special logic for the start 2271 // the body's entry block (along with some special logic for the start
2201 // block in HInstruction::InsertAfter) seals the start block from 2272 // block in HInstruction::InsertAfter) seals the start block from
(...skipping 16 matching lines...) Expand all
2218 current_block()->FinishExit(instr); 2289 current_block()->FinishExit(instr);
2219 set_current_block(NULL); 2290 set_current_block(NULL);
2220 } 2291 }
2221 } 2292 }
2222 2293
2223 graph()->OrderBlocks(); 2294 graph()->OrderBlocks();
2224 graph()->AssignDominators(); 2295 graph()->AssignDominators();
2225 graph()->EliminateRedundantPhis(); 2296 graph()->EliminateRedundantPhis();
2226 if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis(); 2297 if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis();
2227 if (!graph()->CollectPhis()) { 2298 if (!graph()->CollectPhis()) {
2228 Bailout("Phi-use of arguments object"); 2299 Bailout("Unsupported phi-use");
2229 return NULL; 2300 return NULL;
2230 } 2301 }
2231 2302
2232 HInferRepresentation rep(graph()); 2303 HInferRepresentation rep(graph());
2233 rep.Analyze(); 2304 rep.Analyze();
2234 2305
2235 if (FLAG_use_range) { 2306 if (FLAG_use_range) {
2236 HRangeAnalysis rangeAnalysis(graph()); 2307 HRangeAnalysis rangeAnalysis(graph());
2237 rangeAnalysis.Analyze(); 2308 rangeAnalysis.Analyze();
2238 } 2309 }
2239 2310
2240 graph()->InitializeInferredTypes(); 2311 graph()->InitializeInferredTypes();
2241 graph()->Canonicalize(); 2312 graph()->Canonicalize();
2313 graph()->MarkDeoptimizeOnUndefined();
2242 graph()->InsertRepresentationChanges(); 2314 graph()->InsertRepresentationChanges();
2243 graph()->ComputeMinusZeroChecks(); 2315 graph()->ComputeMinusZeroChecks();
2244 2316
2245 // Eliminate redundant stack checks on backwards branches. 2317 // Eliminate redundant stack checks on backwards branches.
2246 HStackCheckEliminator sce(graph()); 2318 HStackCheckEliminator sce(graph());
2247 sce.Process(); 2319 sce.Process();
2248 2320
2249 // Perform common subexpression elimination and loop-invariant code motion. 2321 // Perform common subexpression elimination and loop-invariant code motion.
2250 if (FLAG_use_gvn) { 2322 if (FLAG_use_gvn) {
2251 HPhase phase("Global value numbering", graph()); 2323 HPhase phase("Global value numbering", graph());
2252 HGlobalValueNumberer gvn(graph(), info()); 2324 HGlobalValueNumberer gvn(graph(), info());
2253 gvn.Analyze(); 2325 gvn.Analyze();
2254 } 2326 }
2255 2327
2328 // Replace the results of check instructions with the original value, if the
2329 // result is used. This is safe now, since we don't do code motion after this
2330 // point. It enables better register allocation since the value produced by
2331 // check instructions is really a copy of the original value.
2332 graph()->ReplaceCheckedValues();
2333
2256 return graph(); 2334 return graph();
2257 } 2335 }
2258 2336
2259 2337
2338 void HGraph::ReplaceCheckedValues() {
2339 HPhase phase("Replace checked values", this);
2340 for (int i = 0; i < blocks()->length(); ++i) {
2341 HInstruction* instr = blocks()->at(i)->first();
2342 while (instr != NULL) {
2343 if (instr->IsBoundsCheck()) {
2344 // Replace all uses of the checked value with the original input.
2345 ASSERT(instr->UseCount() > 0);
2346 instr->ReplaceAllUsesWith(HBoundsCheck::cast(instr)->index());
2347 }
2348 instr = instr->next();
2349 }
2350 }
2351 }
2352
2353
2260 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { 2354 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
2261 ASSERT(current_block() != NULL); 2355 ASSERT(current_block() != NULL);
2262 current_block()->AddInstruction(instr); 2356 current_block()->AddInstruction(instr);
2263 return instr; 2357 return instr;
2264 } 2358 }
2265 2359
2266 2360
2267 void HGraphBuilder::AddSimulate(int id) { 2361 void HGraphBuilder::AddSimulate(int ast_id) {
2268 ASSERT(current_block() != NULL); 2362 ASSERT(current_block() != NULL);
2269 current_block()->AddSimulate(id); 2363 current_block()->AddSimulate(ast_id);
2270 } 2364 }
2271 2365
2272 2366
2273 void HGraphBuilder::AddPhi(HPhi* instr) { 2367 void HGraphBuilder::AddPhi(HPhi* instr) {
2274 ASSERT(current_block() != NULL); 2368 ASSERT(current_block() != NULL);
2275 current_block()->AddPhi(instr); 2369 current_block()->AddPhi(instr);
2276 } 2370 }
2277 2371
2278 2372
2279 void HGraphBuilder::PushAndAdd(HInstruction* instr) { 2373 void HGraphBuilder::PushAndAdd(HInstruction* instr) {
(...skipping 11 matching lines...) Expand all
2291 } 2385 }
2292 2386
2293 while (!arguments.is_empty()) { 2387 while (!arguments.is_empty()) {
2294 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); 2388 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast()));
2295 } 2389 }
2296 return call; 2390 return call;
2297 } 2391 }
2298 2392
2299 2393
2300 void HGraphBuilder::SetupScope(Scope* scope) { 2394 void HGraphBuilder::SetupScope(Scope* scope) {
2301 // We don't yet handle the function name for named function expressions.
2302 if (scope->function() != NULL) return Bailout("named function expression");
2303
2304 HConstant* undefined_constant = new(zone()) HConstant( 2395 HConstant* undefined_constant = new(zone()) HConstant(
2305 isolate()->factory()->undefined_value(), Representation::Tagged()); 2396 isolate()->factory()->undefined_value(), Representation::Tagged());
2306 AddInstruction(undefined_constant); 2397 AddInstruction(undefined_constant);
2307 graph_->set_undefined_constant(undefined_constant); 2398 graph_->set_undefined_constant(undefined_constant);
2308 2399
2309 // Set the initial values of parameters including "this". "This" has 2400 // Set the initial values of parameters including "this". "This" has
2310 // parameter index 0. 2401 // parameter index 0.
2311 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); 2402 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count());
2312 2403
2313 for (int i = 0; i < environment()->parameter_count(); ++i) { 2404 for (int i = 0; i < environment()->parameter_count(); ++i) {
2314 HInstruction* parameter = AddInstruction(new(zone()) HParameter(i)); 2405 HInstruction* parameter = AddInstruction(new(zone()) HParameter(i));
2315 environment()->Bind(i, parameter); 2406 environment()->Bind(i, parameter);
2316 } 2407 }
2317 2408
2318 // First special is HContext. 2409 // First special is HContext.
2319 HInstruction* context = AddInstruction(new(zone()) HContext); 2410 HInstruction* context = AddInstruction(new(zone()) HContext);
2320 environment()->BindContext(context); 2411 environment()->BindContext(context);
2321 2412
2322 // Initialize specials and locals to undefined. 2413 // Initialize specials and locals to undefined.
2323 for (int i = environment()->parameter_count() + 1; 2414 for (int i = environment()->parameter_count() + 1;
2324 i < environment()->length(); 2415 i < environment()->length();
2325 ++i) { 2416 ++i) {
2326 environment()->Bind(i, undefined_constant); 2417 environment()->Bind(i, undefined_constant);
2327 } 2418 }
2328 2419
2329 // Handle the arguments and arguments shadow variables specially (they do 2420 // Handle the arguments and arguments shadow variables specially (they do
2330 // not have declarations). 2421 // not have declarations).
2331 if (scope->arguments() != NULL) { 2422 if (scope->arguments() != NULL) {
2332 if (!scope->arguments()->IsStackAllocated() || 2423 if (!scope->arguments()->IsStackAllocated()) {
2333 (scope->arguments_shadow() != NULL &&
2334 !scope->arguments_shadow()->IsStackAllocated())) {
2335 return Bailout("context-allocated arguments"); 2424 return Bailout("context-allocated arguments");
2336 } 2425 }
2337 HArgumentsObject* object = new(zone()) HArgumentsObject; 2426 HArgumentsObject* object = new(zone()) HArgumentsObject;
2338 AddInstruction(object); 2427 AddInstruction(object);
2339 graph()->SetArgumentsObject(object); 2428 graph()->SetArgumentsObject(object);
2340 environment()->Bind(scope->arguments(), object); 2429 environment()->Bind(scope->arguments(), object);
2341 if (scope->arguments_shadow() != NULL) {
2342 environment()->Bind(scope->arguments_shadow(), object);
2343 }
2344 } 2430 }
2345 } 2431 }
2346 2432
2347 2433
2348 void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { 2434 void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
2349 for (int i = 0; i < statements->length(); i++) { 2435 for (int i = 0; i < statements->length(); i++) {
2350 CHECK_ALIVE(Visit(statements->at(i))); 2436 CHECK_ALIVE(Visit(statements->at(i)));
2351 } 2437 }
2352 } 2438 }
2353 2439
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
2426 2512
2427 if (cond_false->HasPredecessor()) { 2513 if (cond_false->HasPredecessor()) {
2428 cond_false->SetJoinId(stmt->ElseId()); 2514 cond_false->SetJoinId(stmt->ElseId());
2429 set_current_block(cond_false); 2515 set_current_block(cond_false);
2430 CHECK_BAILOUT(Visit(stmt->else_statement())); 2516 CHECK_BAILOUT(Visit(stmt->else_statement()));
2431 cond_false = current_block(); 2517 cond_false = current_block();
2432 } else { 2518 } else {
2433 cond_false = NULL; 2519 cond_false = NULL;
2434 } 2520 }
2435 2521
2436 HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->id()); 2522 HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId());
2437 set_current_block(join); 2523 set_current_block(join);
2438 } 2524 }
2439 } 2525 }
2440 2526
2441 2527
2442 HBasicBlock* HGraphBuilder::BreakAndContinueScope::Get( 2528 HBasicBlock* HGraphBuilder::BreakAndContinueScope::Get(
2443 BreakableStatement* stmt, 2529 BreakableStatement* stmt,
2444 BreakType type) { 2530 BreakType type) {
2445 BreakAndContinueScope* current = this; 2531 BreakAndContinueScope* current = this;
2446 while (current != NULL && current->info()->target() != stmt) { 2532 while (current != NULL && current->info()->target() != stmt) {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
2504 } else { 2590 } else {
2505 // Return from an inlined function, visit the subexpression in the 2591 // Return from an inlined function, visit the subexpression in the
2506 // expression context of the call. 2592 // expression context of the call.
2507 if (context->IsTest()) { 2593 if (context->IsTest()) {
2508 TestContext* test = TestContext::cast(context); 2594 TestContext* test = TestContext::cast(context);
2509 VisitForControl(stmt->expression(), 2595 VisitForControl(stmt->expression(),
2510 test->if_true(), 2596 test->if_true(),
2511 test->if_false()); 2597 test->if_false());
2512 } else if (context->IsEffect()) { 2598 } else if (context->IsEffect()) {
2513 CHECK_ALIVE(VisitForEffect(stmt->expression())); 2599 CHECK_ALIVE(VisitForEffect(stmt->expression()));
2514 current_block()->Goto(function_return(), false); 2600 current_block()->Goto(function_return());
2515 } else { 2601 } else {
2516 ASSERT(context->IsValue()); 2602 ASSERT(context->IsValue());
2517 CHECK_ALIVE(VisitForValue(stmt->expression())); 2603 CHECK_ALIVE(VisitForValue(stmt->expression()));
2518 HValue* return_value = environment()->Pop(); 2604 HValue* return_value = environment()->Pop();
2519 current_block()->AddLeaveInlined(return_value, function_return()); 2605 current_block()->AddLeaveInlined(return_value, function_return());
2520 } 2606 }
2521 set_current_block(NULL); 2607 set_current_block(NULL);
2522 } 2608 }
2523 } 2609 }
2524 2610
2525 2611
2526 void HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { 2612 void HGraphBuilder::VisitEnterWithContextStatement(
2613 EnterWithContextStatement* stmt) {
2527 ASSERT(!HasStackOverflow()); 2614 ASSERT(!HasStackOverflow());
2528 ASSERT(current_block() != NULL); 2615 ASSERT(current_block() != NULL);
2529 ASSERT(current_block()->HasPredecessor()); 2616 ASSERT(current_block()->HasPredecessor());
2530 return Bailout("WithEnterStatement"); 2617 return Bailout("EnterWithContextStatement");
2531 } 2618 }
2532 2619
2533 2620
2534 void HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) { 2621 void HGraphBuilder::VisitExitContextStatement(ExitContextStatement* stmt) {
2535 ASSERT(!HasStackOverflow()); 2622 ASSERT(!HasStackOverflow());
2536 ASSERT(current_block() != NULL); 2623 ASSERT(current_block() != NULL);
2537 ASSERT(current_block()->HasPredecessor()); 2624 ASSERT(current_block()->HasPredecessor());
2538 return Bailout("WithExitStatement"); 2625 return Bailout("ExitContextStatement");
2539 } 2626 }
2540 2627
2541 2628
2542 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { 2629 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
2543 ASSERT(!HasStackOverflow()); 2630 ASSERT(!HasStackOverflow());
2544 ASSERT(current_block() != NULL); 2631 ASSERT(current_block() != NULL);
2545 ASSERT(current_block()->HasPredecessor()); 2632 ASSERT(current_block()->HasPredecessor());
2546 // We only optimize switch statements with smi-literal smi comparisons, 2633 // We only optimize switch statements with smi-literal smi comparisons,
2547 // with a bounded number of clauses. 2634 // with a bounded number of clauses.
2548 const int kCaseClauseLimit = 128; 2635 const int kCaseClauseLimit = 128;
(...skipping 23 matching lines...) Expand all
2572 // Finish with deoptimize and add uses of enviroment values to 2659 // Finish with deoptimize and add uses of enviroment values to
2573 // account for invisible uses. 2660 // account for invisible uses.
2574 current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll); 2661 current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll);
2575 set_current_block(NULL); 2662 set_current_block(NULL);
2576 break; 2663 break;
2577 } 2664 }
2578 2665
2579 // Otherwise generate a compare and branch. 2666 // Otherwise generate a compare and branch.
2580 CHECK_ALIVE(VisitForValue(clause->label())); 2667 CHECK_ALIVE(VisitForValue(clause->label()));
2581 HValue* label_value = Pop(); 2668 HValue* label_value = Pop();
2582 HCompare* compare = 2669 HCompareIDAndBranch* compare =
2583 new(zone()) HCompare(tag_value, label_value, Token::EQ_STRICT); 2670 new(zone()) HCompareIDAndBranch(tag_value,
2671 label_value,
2672 Token::EQ_STRICT);
2584 compare->SetInputRepresentation(Representation::Integer32()); 2673 compare->SetInputRepresentation(Representation::Integer32());
2585 ASSERT(!compare->HasSideEffects());
2586 AddInstruction(compare);
2587 HBasicBlock* body_block = graph()->CreateBasicBlock(); 2674 HBasicBlock* body_block = graph()->CreateBasicBlock();
2588 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); 2675 HBasicBlock* next_test_block = graph()->CreateBasicBlock();
2589 HTest* branch = new(zone()) HTest(compare, body_block, next_test_block); 2676 compare->SetSuccessorAt(0, body_block);
2590 current_block()->Finish(branch); 2677 compare->SetSuccessorAt(1, next_test_block);
2678 current_block()->Finish(compare);
2591 set_current_block(next_test_block); 2679 set_current_block(next_test_block);
2592 } 2680 }
2593 2681
2594 // Save the current block to use for the default or to join with the 2682 // Save the current block to use for the default or to join with the
2595 // exit. This block is NULL if we deoptimized. 2683 // exit. This block is NULL if we deoptimized.
2596 HBasicBlock* last_block = current_block(); 2684 HBasicBlock* last_block = current_block();
2597 2685
2598 // 2. Loop over the clauses and the linked list of tests in lockstep, 2686 // 2. Loop over the clauses and the linked list of tests in lockstep,
2599 // translating the clause bodies. 2687 // translating the clause bodies.
2600 HBasicBlock* curr_test_block = first_test_block; 2688 HBasicBlock* curr_test_block = first_test_block;
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
2666 return statement->OsrEntryId() == info()->osr_ast_id(); 2754 return statement->OsrEntryId() == info()->osr_ast_id();
2667 } 2755 }
2668 2756
2669 2757
2670 void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { 2758 void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) {
2671 if (!HasOsrEntryAt(statement)) return; 2759 if (!HasOsrEntryAt(statement)) return;
2672 2760
2673 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); 2761 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock();
2674 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); 2762 HBasicBlock* osr_entry = graph()->CreateBasicBlock();
2675 HValue* true_value = graph()->GetConstantTrue(); 2763 HValue* true_value = graph()->GetConstantTrue();
2676 HTest* test = new(zone()) HTest(true_value, non_osr_entry, osr_entry); 2764 HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry);
2677 current_block()->Finish(test); 2765 current_block()->Finish(test);
2678 2766
2679 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); 2767 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock();
2680 non_osr_entry->Goto(loop_predecessor); 2768 non_osr_entry->Goto(loop_predecessor);
2681 2769
2682 set_current_block(osr_entry); 2770 set_current_block(osr_entry);
2683 int osr_entry_id = statement->OsrEntryId(); 2771 int osr_entry_id = statement->OsrEntryId();
2684 // We want the correct environment at the OsrEntry instruction. Build 2772 // We want the correct environment at the OsrEntry instruction. Build
2685 // it explicitly. The expression stack should be empty. 2773 // it explicitly. The expression stack should be empty.
2686 ASSERT(environment()->ExpressionStackIsEmpty()); 2774 ASSERT(environment()->ExpressionStackIsEmpty());
2687 for (int i = 0; i < environment()->length(); ++i) { 2775 for (int i = 0; i < environment()->length(); ++i) {
2688 HUnknownOSRValue* osr_value = new(zone()) HUnknownOSRValue; 2776 HUnknownOSRValue* osr_value = new(zone()) HUnknownOSRValue;
2689 AddInstruction(osr_value); 2777 AddInstruction(osr_value);
2690 environment()->Bind(i, osr_value); 2778 environment()->Bind(i, osr_value);
2691 } 2779 }
2692 2780
2693 AddSimulate(osr_entry_id); 2781 AddSimulate(osr_entry_id);
2694 AddInstruction(new(zone()) HOsrEntry(osr_entry_id)); 2782 AddInstruction(new(zone()) HOsrEntry(osr_entry_id));
2695 HContext* context = new(zone()) HContext; 2783 HContext* context = new(zone()) HContext;
2696 AddInstruction(context); 2784 AddInstruction(context);
2697 environment()->BindContext(context); 2785 environment()->BindContext(context);
2698 current_block()->Goto(loop_predecessor); 2786 current_block()->Goto(loop_predecessor);
2699 loop_predecessor->SetJoinId(statement->EntryId()); 2787 loop_predecessor->SetJoinId(statement->EntryId());
2700 set_current_block(loop_predecessor); 2788 set_current_block(loop_predecessor);
2701 } 2789 }
2702 2790
2703 2791
2792 void HGraphBuilder::VisitLoopBody(IterationStatement* stmt,
2793 HBasicBlock* loop_entry,
2794 BreakAndContinueInfo* break_info) {
2795 BreakAndContinueScope push(break_info, this);
2796 AddSimulate(stmt->StackCheckId());
2797 HValue* context = environment()->LookupContext();
2798 HStackCheck* stack_check =
2799 new(zone()) HStackCheck(context, HStackCheck::kBackwardsBranch);
2800 AddInstruction(stack_check);
2801 ASSERT(loop_entry->IsLoopHeader());
2802 loop_entry->loop_information()->set_stack_check(stack_check);
2803 CHECK_BAILOUT(Visit(stmt->body()));
2804 }
2805
2806
2704 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { 2807 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
2705 ASSERT(!HasStackOverflow()); 2808 ASSERT(!HasStackOverflow());
2706 ASSERT(current_block() != NULL); 2809 ASSERT(current_block() != NULL);
2707 ASSERT(current_block()->HasPredecessor()); 2810 ASSERT(current_block()->HasPredecessor());
2708 ASSERT(current_block() != NULL); 2811 ASSERT(current_block() != NULL);
2709 PreProcessOsrEntry(stmt); 2812 PreProcessOsrEntry(stmt);
2710 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); 2813 HBasicBlock* loop_entry = CreateLoopHeaderBlock();
2711 current_block()->Goto(loop_entry, false); 2814 current_block()->Goto(loop_entry);
2712 set_current_block(loop_entry); 2815 set_current_block(loop_entry);
2713 2816
2714 BreakAndContinueInfo break_info(stmt); 2817 BreakAndContinueInfo break_info(stmt);
2715 { BreakAndContinueScope push(&break_info, this); 2818 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
2716 CHECK_BAILOUT(Visit(stmt->body()));
2717 }
2718 HBasicBlock* body_exit = 2819 HBasicBlock* body_exit =
2719 JoinContinue(stmt, current_block(), break_info.continue_block()); 2820 JoinContinue(stmt, current_block(), break_info.continue_block());
2720 HBasicBlock* loop_successor = NULL; 2821 HBasicBlock* loop_successor = NULL;
2721 if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) { 2822 if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) {
2722 set_current_block(body_exit); 2823 set_current_block(body_exit);
2723 // The block for a true condition, the actual predecessor block of the 2824 // The block for a true condition, the actual predecessor block of the
2724 // back edge. 2825 // back edge.
2725 body_exit = graph()->CreateBasicBlock(); 2826 body_exit = graph()->CreateBasicBlock();
2726 loop_successor = graph()->CreateBasicBlock(); 2827 loop_successor = graph()->CreateBasicBlock();
2727 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor)); 2828 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor));
(...skipping 17 matching lines...) Expand all
2745 } 2846 }
2746 2847
2747 2848
2748 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { 2849 void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
2749 ASSERT(!HasStackOverflow()); 2850 ASSERT(!HasStackOverflow());
2750 ASSERT(current_block() != NULL); 2851 ASSERT(current_block() != NULL);
2751 ASSERT(current_block()->HasPredecessor()); 2852 ASSERT(current_block()->HasPredecessor());
2752 ASSERT(current_block() != NULL); 2853 ASSERT(current_block() != NULL);
2753 PreProcessOsrEntry(stmt); 2854 PreProcessOsrEntry(stmt);
2754 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); 2855 HBasicBlock* loop_entry = CreateLoopHeaderBlock();
2755 current_block()->Goto(loop_entry, false); 2856 current_block()->Goto(loop_entry);
2756 set_current_block(loop_entry); 2857 set_current_block(loop_entry);
2757 2858
2758 // If the condition is constant true, do not generate a branch. 2859 // If the condition is constant true, do not generate a branch.
2759 HBasicBlock* loop_successor = NULL; 2860 HBasicBlock* loop_successor = NULL;
2760 if (!stmt->cond()->ToBooleanIsTrue()) { 2861 if (!stmt->cond()->ToBooleanIsTrue()) {
2761 HBasicBlock* body_entry = graph()->CreateBasicBlock(); 2862 HBasicBlock* body_entry = graph()->CreateBasicBlock();
2762 loop_successor = graph()->CreateBasicBlock(); 2863 loop_successor = graph()->CreateBasicBlock();
2763 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); 2864 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
2764 if (body_entry->HasPredecessor()) { 2865 if (body_entry->HasPredecessor()) {
2765 body_entry->SetJoinId(stmt->BodyId()); 2866 body_entry->SetJoinId(stmt->BodyId());
2766 set_current_block(body_entry); 2867 set_current_block(body_entry);
2767 } 2868 }
2768 if (loop_successor->HasPredecessor()) { 2869 if (loop_successor->HasPredecessor()) {
2769 loop_successor->SetJoinId(stmt->ExitId()); 2870 loop_successor->SetJoinId(stmt->ExitId());
2770 } else { 2871 } else {
2771 loop_successor = NULL; 2872 loop_successor = NULL;
2772 } 2873 }
2773 } 2874 }
2774 2875
2775 BreakAndContinueInfo break_info(stmt); 2876 BreakAndContinueInfo break_info(stmt);
2776 if (current_block() != NULL) { 2877 if (current_block() != NULL) {
2777 BreakAndContinueScope push(&break_info, this); 2878 BreakAndContinueScope push(&break_info, this);
2778 CHECK_BAILOUT(Visit(stmt->body())); 2879 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
2779 } 2880 }
2780 HBasicBlock* body_exit = 2881 HBasicBlock* body_exit =
2781 JoinContinue(stmt, current_block(), break_info.continue_block()); 2882 JoinContinue(stmt, current_block(), break_info.continue_block());
2782 HBasicBlock* loop_exit = CreateLoop(stmt, 2883 HBasicBlock* loop_exit = CreateLoop(stmt,
2783 loop_entry, 2884 loop_entry,
2784 body_exit, 2885 body_exit,
2785 loop_successor, 2886 loop_successor,
2786 break_info.break_block()); 2887 break_info.break_block());
2787 set_current_block(loop_exit); 2888 set_current_block(loop_exit);
2788 } 2889 }
2789 2890
2790 2891
2791 void HGraphBuilder::VisitForStatement(ForStatement* stmt) { 2892 void HGraphBuilder::VisitForStatement(ForStatement* stmt) {
2792 ASSERT(!HasStackOverflow()); 2893 ASSERT(!HasStackOverflow());
2793 ASSERT(current_block() != NULL); 2894 ASSERT(current_block() != NULL);
2794 ASSERT(current_block()->HasPredecessor()); 2895 ASSERT(current_block()->HasPredecessor());
2795 if (stmt->init() != NULL) { 2896 if (stmt->init() != NULL) {
2796 CHECK_ALIVE(Visit(stmt->init())); 2897 CHECK_ALIVE(Visit(stmt->init()));
2797 } 2898 }
2798 ASSERT(current_block() != NULL); 2899 ASSERT(current_block() != NULL);
2799 PreProcessOsrEntry(stmt); 2900 PreProcessOsrEntry(stmt);
2800 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); 2901 HBasicBlock* loop_entry = CreateLoopHeaderBlock();
2801 current_block()->Goto(loop_entry, false); 2902 current_block()->Goto(loop_entry);
2802 set_current_block(loop_entry); 2903 set_current_block(loop_entry);
2803 2904
2804 HBasicBlock* loop_successor = NULL; 2905 HBasicBlock* loop_successor = NULL;
2805 if (stmt->cond() != NULL) { 2906 if (stmt->cond() != NULL) {
2806 HBasicBlock* body_entry = graph()->CreateBasicBlock(); 2907 HBasicBlock* body_entry = graph()->CreateBasicBlock();
2807 loop_successor = graph()->CreateBasicBlock(); 2908 loop_successor = graph()->CreateBasicBlock();
2808 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); 2909 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
2809 if (body_entry->HasPredecessor()) { 2910 if (body_entry->HasPredecessor()) {
2810 body_entry->SetJoinId(stmt->BodyId()); 2911 body_entry->SetJoinId(stmt->BodyId());
2811 set_current_block(body_entry); 2912 set_current_block(body_entry);
2812 } 2913 }
2813 if (loop_successor->HasPredecessor()) { 2914 if (loop_successor->HasPredecessor()) {
2814 loop_successor->SetJoinId(stmt->ExitId()); 2915 loop_successor->SetJoinId(stmt->ExitId());
2815 } else { 2916 } else {
2816 loop_successor = NULL; 2917 loop_successor = NULL;
2817 } 2918 }
2818 } 2919 }
2819 2920
2820 BreakAndContinueInfo break_info(stmt); 2921 BreakAndContinueInfo break_info(stmt);
2821 if (current_block() != NULL) { 2922 if (current_block() != NULL) {
2822 BreakAndContinueScope push(&break_info, this); 2923 BreakAndContinueScope push(&break_info, this);
2823 CHECK_BAILOUT(Visit(stmt->body())); 2924 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
2824 } 2925 }
2825 HBasicBlock* body_exit = 2926 HBasicBlock* body_exit =
2826 JoinContinue(stmt, current_block(), break_info.continue_block()); 2927 JoinContinue(stmt, current_block(), break_info.continue_block());
2827 2928
2828 if (stmt->next() != NULL && body_exit != NULL) { 2929 if (stmt->next() != NULL && body_exit != NULL) {
2829 set_current_block(body_exit); 2930 set_current_block(body_exit);
2830 CHECK_BAILOUT(Visit(stmt->next())); 2931 CHECK_BAILOUT(Visit(stmt->next()));
2831 body_exit = current_block(); 2932 body_exit = current_block();
2832 } 2933 }
2833 2934
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
2897 ASSERT(current_block() != NULL); 2998 ASSERT(current_block() != NULL);
2898 ASSERT(current_block()->HasPredecessor()); 2999 ASSERT(current_block()->HasPredecessor());
2899 Handle<SharedFunctionInfo> shared_info = 3000 Handle<SharedFunctionInfo> shared_info =
2900 SearchSharedFunctionInfo(info()->shared_info()->code(), 3001 SearchSharedFunctionInfo(info()->shared_info()->code(),
2901 expr); 3002 expr);
2902 if (shared_info.is_null()) { 3003 if (shared_info.is_null()) {
2903 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); 3004 shared_info = Compiler::BuildFunctionInfo(expr, info()->script());
2904 } 3005 }
2905 // We also have a stack overflow if the recursive compilation did. 3006 // We also have a stack overflow if the recursive compilation did.
2906 if (HasStackOverflow()) return; 3007 if (HasStackOverflow()) return;
3008 HValue* context = environment()->LookupContext();
2907 HFunctionLiteral* instr = 3009 HFunctionLiteral* instr =
2908 new(zone()) HFunctionLiteral(shared_info, expr->pretenure()); 3010 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure());
2909 ast_context()->ReturnInstruction(instr, expr->id()); 3011 return ast_context()->ReturnInstruction(instr, expr->id());
2910 } 3012 }
2911 3013
2912 3014
2913 void HGraphBuilder::VisitSharedFunctionInfoLiteral( 3015 void HGraphBuilder::VisitSharedFunctionInfoLiteral(
2914 SharedFunctionInfoLiteral* expr) { 3016 SharedFunctionInfoLiteral* expr) {
2915 ASSERT(!HasStackOverflow()); 3017 ASSERT(!HasStackOverflow());
2916 ASSERT(current_block() != NULL); 3018 ASSERT(current_block() != NULL);
2917 ASSERT(current_block()->HasPredecessor()); 3019 ASSERT(current_block()->HasPredecessor());
2918 return Bailout("SharedFunctionInfoLiteral"); 3020 return Bailout("SharedFunctionInfoLiteral");
2919 } 3021 }
(...skipping 24 matching lines...) Expand all
2944 CHECK_BAILOUT(Visit(expr->else_expression())); 3046 CHECK_BAILOUT(Visit(expr->else_expression()));
2945 cond_false = current_block(); 3047 cond_false = current_block();
2946 } else { 3048 } else {
2947 cond_false = NULL; 3049 cond_false = NULL;
2948 } 3050 }
2949 3051
2950 if (!ast_context()->IsTest()) { 3052 if (!ast_context()->IsTest()) {
2951 HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); 3053 HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id());
2952 set_current_block(join); 3054 set_current_block(join);
2953 if (join != NULL && !ast_context()->IsEffect()) { 3055 if (join != NULL && !ast_context()->IsEffect()) {
2954 ast_context()->ReturnValue(Pop()); 3056 return ast_context()->ReturnValue(Pop());
2955 } 3057 }
2956 } 3058 }
2957 } 3059 }
2958 3060
2959 3061
2960 HGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty( 3062 HGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty(
2961 Variable* var, LookupResult* lookup, bool is_store) { 3063 Variable* var, LookupResult* lookup, bool is_store) {
2962 if (var->is_this() || !info()->has_global_object()) { 3064 if (var->is_this() || !info()->has_global_object()) {
2963 return kUseGeneric; 3065 return kUseGeneric;
2964 } 3066 }
(...skipping 24 matching lines...) Expand all
2989 3091
2990 3092
2991 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { 3093 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
2992 ASSERT(!HasStackOverflow()); 3094 ASSERT(!HasStackOverflow());
2993 ASSERT(current_block() != NULL); 3095 ASSERT(current_block() != NULL);
2994 ASSERT(current_block()->HasPredecessor()); 3096 ASSERT(current_block()->HasPredecessor());
2995 Variable* variable = expr->AsVariable(); 3097 Variable* variable = expr->AsVariable();
2996 if (variable == NULL) { 3098 if (variable == NULL) {
2997 return Bailout("reference to rewritten variable"); 3099 return Bailout("reference to rewritten variable");
2998 } else if (variable->IsStackAllocated()) { 3100 } else if (variable->IsStackAllocated()) {
2999 ast_context()->ReturnValue(environment()->Lookup(variable)); 3101 HValue* value = environment()->Lookup(variable);
3102 if (variable->mode() == Variable::CONST &&
3103 value == graph()->GetConstantHole()) {
3104 return Bailout("reference to uninitialized const variable");
3105 }
3106 return ast_context()->ReturnValue(value);
3000 } else if (variable->IsContextSlot()) { 3107 } else if (variable->IsContextSlot()) {
3001 if (variable->mode() == Variable::CONST) { 3108 if (variable->mode() == Variable::CONST) {
3002 return Bailout("reference to const context slot"); 3109 return Bailout("reference to const context slot");
3003 } 3110 }
3004 HValue* context = BuildContextChainWalk(variable); 3111 HValue* context = BuildContextChainWalk(variable);
3005 int index = variable->AsSlot()->index(); 3112 int index = variable->AsSlot()->index();
3006 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, index); 3113 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, index);
3007 ast_context()->ReturnInstruction(instr, expr->id()); 3114 return ast_context()->ReturnInstruction(instr, expr->id());
3008 } else if (variable->is_global()) { 3115 } else if (variable->is_global()) {
3009 LookupResult lookup; 3116 LookupResult lookup;
3010 GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false); 3117 GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false);
3011 3118
3012 if (type == kUseCell && 3119 if (type == kUseCell &&
3013 info()->global_object()->IsAccessCheckNeeded()) { 3120 info()->global_object()->IsAccessCheckNeeded()) {
3014 type = kUseGeneric; 3121 type = kUseGeneric;
3015 } 3122 }
3016 3123
3017 if (type == kUseCell) { 3124 if (type == kUseCell) {
3018 Handle<GlobalObject> global(info()->global_object()); 3125 Handle<GlobalObject> global(info()->global_object());
3019 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 3126 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
3020 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); 3127 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
3021 HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole); 3128 HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole);
3022 ast_context()->ReturnInstruction(instr, expr->id()); 3129 return ast_context()->ReturnInstruction(instr, expr->id());
3023 } else { 3130 } else {
3024 HValue* context = environment()->LookupContext(); 3131 HValue* context = environment()->LookupContext();
3025 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 3132 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
3026 AddInstruction(global_object); 3133 AddInstruction(global_object);
3027 HLoadGlobalGeneric* instr = 3134 HLoadGlobalGeneric* instr =
3028 new(zone()) HLoadGlobalGeneric(context, 3135 new(zone()) HLoadGlobalGeneric(context,
3029 global_object, 3136 global_object,
3030 variable->name(), 3137 variable->name(),
3031 ast_context()->is_for_typeof()); 3138 ast_context()->is_for_typeof());
3032 instr->set_position(expr->position()); 3139 instr->set_position(expr->position());
3033 ASSERT(instr->HasSideEffects()); 3140 ASSERT(instr->HasSideEffects());
3034 ast_context()->ReturnInstruction(instr, expr->id()); 3141 return ast_context()->ReturnInstruction(instr, expr->id());
3035 } 3142 }
3036 } else { 3143 } else {
3037 return Bailout("reference to a variable which requires dynamic lookup"); 3144 return Bailout("reference to a variable which requires dynamic lookup");
3038 } 3145 }
3039 } 3146 }
3040 3147
3041 3148
3042 void HGraphBuilder::VisitLiteral(Literal* expr) { 3149 void HGraphBuilder::VisitLiteral(Literal* expr) {
3043 ASSERT(!HasStackOverflow()); 3150 ASSERT(!HasStackOverflow());
3044 ASSERT(current_block() != NULL); 3151 ASSERT(current_block() != NULL);
3045 ASSERT(current_block()->HasPredecessor()); 3152 ASSERT(current_block()->HasPredecessor());
3046 HConstant* instr = 3153 HConstant* instr =
3047 new(zone()) HConstant(expr->handle(), Representation::Tagged()); 3154 new(zone()) HConstant(expr->handle(), Representation::Tagged());
3048 ast_context()->ReturnInstruction(instr, expr->id()); 3155 return ast_context()->ReturnInstruction(instr, expr->id());
3049 } 3156 }
3050 3157
3051 3158
3052 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { 3159 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
3053 ASSERT(!HasStackOverflow()); 3160 ASSERT(!HasStackOverflow());
3054 ASSERT(current_block() != NULL); 3161 ASSERT(current_block() != NULL);
3055 ASSERT(current_block()->HasPredecessor()); 3162 ASSERT(current_block()->HasPredecessor());
3056 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(expr->pattern(), 3163 HValue* context = environment()->LookupContext();
3164
3165 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context,
3166 expr->pattern(),
3057 expr->flags(), 3167 expr->flags(),
3058 expr->literal_index()); 3168 expr->literal_index());
3059 ast_context()->ReturnInstruction(instr, expr->id()); 3169 return ast_context()->ReturnInstruction(instr, expr->id());
3060 } 3170 }
3061 3171
3062 3172
3063 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { 3173 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
3064 ASSERT(!HasStackOverflow()); 3174 ASSERT(!HasStackOverflow());
3065 ASSERT(current_block() != NULL); 3175 ASSERT(current_block() != NULL);
3066 ASSERT(current_block()->HasPredecessor()); 3176 ASSERT(current_block()->HasPredecessor());
3067 HValue* context = environment()->LookupContext(); 3177 HValue* context = environment()->LookupContext();
3068 HObjectLiteral* literal = 3178 HObjectLiteral* literal =
3069 new(zone()) HObjectLiteral(context, 3179 new(zone()) HObjectLiteral(context,
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
3119 } 3229 }
3120 3230
3121 if (expr->has_function()) { 3231 if (expr->has_function()) {
3122 // Return the result of the transformation to fast properties 3232 // Return the result of the transformation to fast properties
3123 // instead of the original since this operation changes the map 3233 // instead of the original since this operation changes the map
3124 // of the object. This makes sure that the original object won't 3234 // of the object. This makes sure that the original object won't
3125 // be used by other optimized code before it is transformed 3235 // be used by other optimized code before it is transformed
3126 // (e.g. because of code motion). 3236 // (e.g. because of code motion).
3127 HToFastProperties* result = new(zone()) HToFastProperties(Pop()); 3237 HToFastProperties* result = new(zone()) HToFastProperties(Pop());
3128 AddInstruction(result); 3238 AddInstruction(result);
3129 ast_context()->ReturnValue(result); 3239 return ast_context()->ReturnValue(result);
3130 } else { 3240 } else {
3131 ast_context()->ReturnValue(Pop()); 3241 return ast_context()->ReturnValue(Pop());
3132 } 3242 }
3133 } 3243 }
3134 3244
3135 3245
3136 void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { 3246 void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
3137 ASSERT(!HasStackOverflow()); 3247 ASSERT(!HasStackOverflow());
3138 ASSERT(current_block() != NULL); 3248 ASSERT(current_block() != NULL);
3139 ASSERT(current_block()->HasPredecessor()); 3249 ASSERT(current_block()->HasPredecessor());
3140 ZoneList<Expression*>* subexprs = expr->values(); 3250 ZoneList<Expression*>* subexprs = expr->values();
3141 int length = subexprs->length(); 3251 int length = subexprs->length();
3252 HValue* context = environment()->LookupContext();
3142 3253
3143 HArrayLiteral* literal = new(zone()) HArrayLiteral(expr->constant_elements(), 3254 HArrayLiteral* literal = new(zone()) HArrayLiteral(context,
3255 expr->constant_elements(),
3144 length, 3256 length,
3145 expr->literal_index(), 3257 expr->literal_index(),
3146 expr->depth()); 3258 expr->depth());
3147 // The array is expected in the bailout environment during computation 3259 // The array is expected in the bailout environment during computation
3148 // of the property values and is the value of the entire expression. 3260 // of the property values and is the value of the entire expression.
3149 PushAndAdd(literal); 3261 PushAndAdd(literal);
3150 3262
3151 HLoadElements* elements = NULL; 3263 HLoadElements* elements = NULL;
3152 3264
3153 for (int i = 0; i < length; i++) { 3265 for (int i = 0; i < length; i++) {
(...skipping 11 matching lines...) Expand all
3165 elements = new(zone()) HLoadElements(literal); 3277 elements = new(zone()) HLoadElements(literal);
3166 AddInstruction(elements); 3278 AddInstruction(elements);
3167 } 3279 }
3168 3280
3169 HValue* key = AddInstruction( 3281 HValue* key = AddInstruction(
3170 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), 3282 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)),
3171 Representation::Integer32())); 3283 Representation::Integer32()));
3172 AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value)); 3284 AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value));
3173 AddSimulate(expr->GetIdForElement(i)); 3285 AddSimulate(expr->GetIdForElement(i));
3174 } 3286 }
3175 ast_context()->ReturnValue(Pop()); 3287 return ast_context()->ReturnValue(Pop());
3176 }
3177
3178
3179 void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
3180 ASSERT(!HasStackOverflow());
3181 ASSERT(current_block() != NULL);
3182 ASSERT(current_block()->HasPredecessor());
3183 return Bailout("CatchExtensionObject");
3184 } 3288 }
3185 3289
3186 3290
3187 // Sets the lookup result and returns true if the store can be inlined. 3291 // Sets the lookup result and returns true if the store can be inlined.
3188 static bool ComputeStoredField(Handle<Map> type, 3292 static bool ComputeStoredField(Handle<Map> type,
3189 Handle<String> name, 3293 Handle<String> name,
3190 LookupResult* lookup) { 3294 LookupResult* lookup) {
3191 type->LookupInDescriptors(NULL, *name, lookup); 3295 type->LookupInDescriptors(NULL, *name, lookup);
3192 if (!lookup->IsPropertyOrTransition()) return false; 3296 if (!lookup->IsPropertyOrTransition()) return false;
3193 if (lookup->type() == FIELD) return true; 3297 if (lookup->type() == FIELD) return true;
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
3335 // unoptimized code). 3439 // unoptimized code).
3336 if (instr->HasSideEffects()) { 3440 if (instr->HasSideEffects()) {
3337 if (ast_context()->IsEffect()) { 3441 if (ast_context()->IsEffect()) {
3338 AddSimulate(expr->id()); 3442 AddSimulate(expr->id());
3339 } else { 3443 } else {
3340 Push(value); 3444 Push(value);
3341 AddSimulate(expr->id()); 3445 AddSimulate(expr->id());
3342 Drop(1); 3446 Drop(1);
3343 } 3447 }
3344 } 3448 }
3345 ast_context()->ReturnValue(value); 3449 return ast_context()->ReturnValue(value);
3346 return;
3347 } 3450 }
3348 } 3451 }
3349 3452
3350 ASSERT(join != NULL); 3453 ASSERT(join != NULL);
3351 join->SetJoinId(expr->id()); 3454 join->SetJoinId(expr->id());
3352 set_current_block(join); 3455 set_current_block(join);
3353 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); 3456 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
3354 } 3457 }
3355 3458
3356 3459
3357 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { 3460 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
3358 Property* prop = expr->target()->AsProperty(); 3461 Property* prop = expr->target()->AsProperty();
3359 ASSERT(prop != NULL); 3462 ASSERT(prop != NULL);
3360 expr->RecordTypeFeedback(oracle()); 3463 expr->RecordTypeFeedback(oracle());
3361 CHECK_ALIVE(VisitForValue(prop->obj())); 3464 CHECK_ALIVE(VisitForValue(prop->obj()));
3362 3465
3363 HValue* value = NULL; 3466 HValue* value = NULL;
(...skipping 23 matching lines...) Expand all
3387 instr = BuildStoreNamedGeneric(object, name, value); 3490 instr = BuildStoreNamedGeneric(object, name, value);
3388 } 3491 }
3389 3492
3390 } else { 3493 } else {
3391 // Keyed store. 3494 // Keyed store.
3392 CHECK_ALIVE(VisitForValue(prop->key())); 3495 CHECK_ALIVE(VisitForValue(prop->key()));
3393 CHECK_ALIVE(VisitForValue(expr->value())); 3496 CHECK_ALIVE(VisitForValue(expr->value()));
3394 value = Pop(); 3497 value = Pop();
3395 HValue* key = Pop(); 3498 HValue* key = Pop();
3396 HValue* object = Pop(); 3499 HValue* object = Pop();
3397 instr = BuildStoreKeyed(object, key, value, expr); 3500 bool has_side_effects = false;
3501 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(),
3502 expr->position(),
3503 true, // is_store
3504 &has_side_effects);
3505 Push(value);
3506 ASSERT(has_side_effects); // Stores always have side effects.
3507 AddSimulate(expr->AssignmentId());
3508 return ast_context()->ReturnValue(Pop());
3398 } 3509 }
3399 Push(value); 3510 Push(value);
3400 instr->set_position(expr->position()); 3511 instr->set_position(expr->position());
3401 AddInstruction(instr); 3512 AddInstruction(instr);
3402 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3513 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3403 ast_context()->ReturnValue(Pop()); 3514 return ast_context()->ReturnValue(Pop());
3404 } 3515 }
3405 3516
3406 3517
3407 // Because not every expression has a position and there is not common 3518 // Because not every expression has a position and there is not common
3408 // superclass of Assignment and CountOperation, we cannot just pass the 3519 // superclass of Assignment and CountOperation, we cannot just pass the
3409 // owning expression instead of position and ast_id separately. 3520 // owning expression instead of position and ast_id separately.
3410 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, 3521 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
3411 HValue* value, 3522 HValue* value,
3412 int position, 3523 int position,
3413 int ast_id) { 3524 int ast_id) {
(...skipping 30 matching lines...) Expand all
3444 VariableProxy* proxy = target->AsVariableProxy(); 3555 VariableProxy* proxy = target->AsVariableProxy();
3445 Variable* var = proxy->AsVariable(); 3556 Variable* var = proxy->AsVariable();
3446 Property* prop = target->AsProperty(); 3557 Property* prop = target->AsProperty();
3447 ASSERT(var == NULL || prop == NULL); 3558 ASSERT(var == NULL || prop == NULL);
3448 3559
3449 // We have a second position recorded in the FullCodeGenerator to have 3560 // We have a second position recorded in the FullCodeGenerator to have
3450 // type feedback for the binary operation. 3561 // type feedback for the binary operation.
3451 BinaryOperation* operation = expr->binary_operation(); 3562 BinaryOperation* operation = expr->binary_operation();
3452 3563
3453 if (var != NULL) { 3564 if (var != NULL) {
3565 if (var->mode() == Variable::CONST) {
3566 return Bailout("unsupported const compound assignment");
3567 }
3568
3454 CHECK_ALIVE(VisitForValue(operation)); 3569 CHECK_ALIVE(VisitForValue(operation));
3455 3570
3456 if (var->is_global()) { 3571 if (var->is_global()) {
3457 HandleGlobalVariableAssignment(var, 3572 HandleGlobalVariableAssignment(var,
3458 Top(), 3573 Top(),
3459 expr->position(), 3574 expr->position(),
3460 expr->AssignmentId()); 3575 expr->AssignmentId());
3461 } else if (var->IsStackAllocated()) { 3576 } else if (var->IsStackAllocated()) {
3462 Bind(var, Top()); 3577 Bind(var, Top());
3463 } else if (var->IsContextSlot()) { 3578 } else if (var->IsContextSlot()) {
3579 // Bail out if we try to mutate a parameter value in a function using
3580 // the arguments object. We do not (yet) correctly handle the
3581 // arguments property of the function.
3582 if (info()->scope()->arguments() != NULL) {
3583 // Parameters will rewrite to context slots. We have no direct way
3584 // to detect that the variable is a parameter.
3585 int count = info()->scope()->num_parameters();
3586 for (int i = 0; i < count; ++i) {
3587 if (var == info()->scope()->parameter(i)) {
3588 Bailout("assignment to parameter, function uses arguments object");
3589 }
3590 }
3591 }
3592
3464 HValue* context = BuildContextChainWalk(var); 3593 HValue* context = BuildContextChainWalk(var);
3465 int index = var->AsSlot()->index(); 3594 int index = var->AsSlot()->index();
3466 HStoreContextSlot* instr = 3595 HStoreContextSlot* instr =
3467 new(zone()) HStoreContextSlot(context, index, Top()); 3596 new(zone()) HStoreContextSlot(context, index, Top());
3468 AddInstruction(instr); 3597 AddInstruction(instr);
3469 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3598 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3470 } else { 3599 } else {
3471 return Bailout("compound assignment to lookup slot"); 3600 return Bailout("compound assignment to lookup slot");
3472 } 3601 }
3473 ast_context()->ReturnValue(Pop()); 3602 return ast_context()->ReturnValue(Pop());
3474 3603
3475 } else if (prop != NULL) { 3604 } else if (prop != NULL) {
3476 prop->RecordTypeFeedback(oracle()); 3605 prop->RecordTypeFeedback(oracle());
3477 3606
3478 if (prop->key()->IsPropertyName()) { 3607 if (prop->key()->IsPropertyName()) {
3479 // Named property. 3608 // Named property.
3480 CHECK_ALIVE(VisitForValue(prop->obj())); 3609 CHECK_ALIVE(VisitForValue(prop->obj()));
3481 HValue* obj = Top(); 3610 HValue* obj = Top();
3482 3611
3483 HInstruction* load = NULL; 3612 HInstruction* load = NULL;
(...skipping 14 matching lines...) Expand all
3498 HInstruction* instr = BuildBinaryOperation(operation, left, right); 3627 HInstruction* instr = BuildBinaryOperation(operation, left, right);
3499 PushAndAdd(instr); 3628 PushAndAdd(instr);
3500 if (instr->HasSideEffects()) AddSimulate(operation->id()); 3629 if (instr->HasSideEffects()) AddSimulate(operation->id());
3501 3630
3502 HInstruction* store = BuildStoreNamed(obj, instr, prop); 3631 HInstruction* store = BuildStoreNamed(obj, instr, prop);
3503 AddInstruction(store); 3632 AddInstruction(store);
3504 // Drop the simulated receiver and value. Return the value. 3633 // Drop the simulated receiver and value. Return the value.
3505 Drop(2); 3634 Drop(2);
3506 Push(instr); 3635 Push(instr);
3507 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3636 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
3508 ast_context()->ReturnValue(Pop()); 3637 return ast_context()->ReturnValue(Pop());
3509 3638
3510 } else { 3639 } else {
3511 // Keyed property. 3640 // Keyed property.
3512 CHECK_ALIVE(VisitForValue(prop->obj())); 3641 CHECK_ALIVE(VisitForValue(prop->obj()));
3513 CHECK_ALIVE(VisitForValue(prop->key())); 3642 CHECK_ALIVE(VisitForValue(prop->key()));
3514 HValue* obj = environment()->ExpressionStackAt(1); 3643 HValue* obj = environment()->ExpressionStackAt(1);
3515 HValue* key = environment()->ExpressionStackAt(0); 3644 HValue* key = environment()->ExpressionStackAt(0);
3516 3645
3517 HInstruction* load = BuildLoadKeyed(obj, key, prop); 3646 bool has_side_effects = false;
3518 PushAndAdd(load); 3647 HValue* load = HandleKeyedElementAccess(
3519 if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); 3648 obj, key, NULL, prop, expr->CompoundLoadId(), RelocInfo::kNoPosition,
3649 false, // is_store
3650 &has_side_effects);
3651 Push(load);
3652 if (has_side_effects) AddSimulate(expr->CompoundLoadId());
3653
3520 3654
3521 CHECK_ALIVE(VisitForValue(expr->value())); 3655 CHECK_ALIVE(VisitForValue(expr->value()));
3522 HValue* right = Pop(); 3656 HValue* right = Pop();
3523 HValue* left = Pop(); 3657 HValue* left = Pop();
3524 3658
3525 HInstruction* instr = BuildBinaryOperation(operation, left, right); 3659 HInstruction* instr = BuildBinaryOperation(operation, left, right);
3526 PushAndAdd(instr); 3660 PushAndAdd(instr);
3527 if (instr->HasSideEffects()) AddSimulate(operation->id()); 3661 if (instr->HasSideEffects()) AddSimulate(operation->id());
3528 3662
3529 expr->RecordTypeFeedback(oracle()); 3663 expr->RecordTypeFeedback(oracle());
3530 HInstruction* store = BuildStoreKeyed(obj, key, instr, expr); 3664 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(),
3531 AddInstruction(store); 3665 RelocInfo::kNoPosition,
3666 true, // is_store
3667 &has_side_effects);
3668
3532 // Drop the simulated receiver, key, and value. Return the value. 3669 // Drop the simulated receiver, key, and value. Return the value.
3533 Drop(3); 3670 Drop(3);
3534 Push(instr); 3671 Push(instr);
3535 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3672 ASSERT(has_side_effects); // Stores always have side effects.
3536 ast_context()->ReturnValue(Pop()); 3673 AddSimulate(expr->AssignmentId());
3674 return ast_context()->ReturnValue(Pop());
3537 } 3675 }
3538 3676
3539 } else { 3677 } else {
3540 return Bailout("invalid lhs in compound assignment"); 3678 return Bailout("invalid lhs in compound assignment");
3541 } 3679 }
3542 } 3680 }
3543 3681
3544 3682
3545 void HGraphBuilder::VisitAssignment(Assignment* expr) { 3683 void HGraphBuilder::VisitAssignment(Assignment* expr) {
3546 ASSERT(!HasStackOverflow()); 3684 ASSERT(!HasStackOverflow());
3547 ASSERT(current_block() != NULL); 3685 ASSERT(current_block() != NULL);
3548 ASSERT(current_block()->HasPredecessor()); 3686 ASSERT(current_block()->HasPredecessor());
3549 VariableProxy* proxy = expr->target()->AsVariableProxy(); 3687 VariableProxy* proxy = expr->target()->AsVariableProxy();
3550 Variable* var = proxy->AsVariable(); 3688 Variable* var = proxy->AsVariable();
3551 Property* prop = expr->target()->AsProperty(); 3689 Property* prop = expr->target()->AsProperty();
3552 ASSERT(var == NULL || prop == NULL); 3690 ASSERT(var == NULL || prop == NULL);
3553 3691
3554 if (expr->is_compound()) { 3692 if (expr->is_compound()) {
3555 HandleCompoundAssignment(expr); 3693 HandleCompoundAssignment(expr);
3556 return; 3694 return;
3557 } 3695 }
3558 3696
3559 if (var != NULL) { 3697 if (var != NULL) {
3698 if (var->mode() == Variable::CONST) {
3699 if (expr->op() != Token::INIT_CONST) {
3700 return Bailout("non-initializer assignment to const");
3701 }
3702 if (!var->IsStackAllocated()) {
3703 return Bailout("assignment to const context slot");
3704 }
3705 // We insert a use of the old value to detect unsupported uses of const
3706 // variables (e.g. initialization inside a loop).
3707 HValue* old_value = environment()->Lookup(var);
3708 AddInstruction(new HUseConst(old_value));
3709 }
3710
3560 if (proxy->IsArguments()) return Bailout("assignment to arguments"); 3711 if (proxy->IsArguments()) return Bailout("assignment to arguments");
3561 3712
3562 // Handle the assignment. 3713 // Handle the assignment.
3563 if (var->IsStackAllocated()) { 3714 if (var->IsStackAllocated()) {
3564 // We do not allow the arguments object to occur in a context where it 3715 // We do not allow the arguments object to occur in a context where it
3565 // may escape, but assignments to stack-allocated locals are 3716 // may escape, but assignments to stack-allocated locals are
3566 // permitted. 3717 // permitted.
3567 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); 3718 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
3568 HValue* value = Pop(); 3719 HValue* value = Pop();
3569 Bind(var, value); 3720 Bind(var, value);
3570 ast_context()->ReturnValue(value); 3721 return ast_context()->ReturnValue(value);
3571 3722
3572 } else if (var->IsContextSlot() && var->mode() != Variable::CONST) { 3723 } else if (var->IsContextSlot()) {
3724 ASSERT(var->mode() != Variable::CONST);
3725 // Bail out if we try to mutate a parameter value in a function using
3726 // the arguments object. We do not (yet) correctly handle the
3727 // arguments property of the function.
3728 if (info()->scope()->arguments() != NULL) {
3729 // Parameters will rewrite to context slots. We have no direct way
3730 // to detect that the variable is a parameter.
3731 int count = info()->scope()->num_parameters();
3732 for (int i = 0; i < count; ++i) {
3733 if (var == info()->scope()->parameter(i)) {
3734 Bailout("assignment to parameter, function uses arguments object");
3735 }
3736 }
3737 }
3738
3573 CHECK_ALIVE(VisitForValue(expr->value())); 3739 CHECK_ALIVE(VisitForValue(expr->value()));
3574 HValue* context = BuildContextChainWalk(var); 3740 HValue* context = BuildContextChainWalk(var);
3575 int index = var->AsSlot()->index(); 3741 int index = var->AsSlot()->index();
3576 HStoreContextSlot* instr = 3742 HStoreContextSlot* instr =
3577 new(zone()) HStoreContextSlot(context, index, Top()); 3743 new(zone()) HStoreContextSlot(context, index, Top());
3578 AddInstruction(instr); 3744 AddInstruction(instr);
3579 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3745 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3580 ast_context()->ReturnValue(Pop()); 3746 return ast_context()->ReturnValue(Pop());
3581 3747
3582 } else if (var->is_global()) { 3748 } else if (var->is_global()) {
3583 CHECK_ALIVE(VisitForValue(expr->value())); 3749 CHECK_ALIVE(VisitForValue(expr->value()));
3584 HandleGlobalVariableAssignment(var, 3750 HandleGlobalVariableAssignment(var,
3585 Top(), 3751 Top(),
3586 expr->position(), 3752 expr->position(),
3587 expr->AssignmentId()); 3753 expr->AssignmentId());
3588 ast_context()->ReturnValue(Pop()); 3754 return ast_context()->ReturnValue(Pop());
3589 3755
3590 } else { 3756 } else {
3591 return Bailout("assignment to LOOKUP or const CONTEXT variable"); 3757 return Bailout("assignment to LOOKUP or const CONTEXT variable");
3592 } 3758 }
3593 3759
3594 } else if (prop != NULL) { 3760 } else if (prop != NULL) {
3595 HandlePropertyAssignment(expr); 3761 HandlePropertyAssignment(expr);
3596 } else { 3762 } else {
3597 return Bailout("invalid left-hand side in assignment"); 3763 return Bailout("invalid left-hand side in assignment");
3598 } 3764 }
3599 } 3765 }
3600 3766
3601 3767
3602 void HGraphBuilder::VisitThrow(Throw* expr) { 3768 void HGraphBuilder::VisitThrow(Throw* expr) {
3603 ASSERT(!HasStackOverflow()); 3769 ASSERT(!HasStackOverflow());
3604 ASSERT(current_block() != NULL); 3770 ASSERT(current_block() != NULL);
3605 ASSERT(current_block()->HasPredecessor()); 3771 ASSERT(current_block()->HasPredecessor());
3606 // We don't optimize functions with invalid left-hand sides in 3772 // We don't optimize functions with invalid left-hand sides in
3607 // assignments, count operations, or for-in. Consequently throw can 3773 // assignments, count operations, or for-in. Consequently throw can
3608 // currently only occur in an effect context. 3774 // currently only occur in an effect context.
3609 ASSERT(ast_context()->IsEffect()); 3775 ASSERT(ast_context()->IsEffect());
3610 CHECK_ALIVE(VisitForValue(expr->exception())); 3776 CHECK_ALIVE(VisitForValue(expr->exception()));
3611 3777
3778 HValue* context = environment()->LookupContext();
3612 HValue* value = environment()->Pop(); 3779 HValue* value = environment()->Pop();
3613 HThrow* instr = new(zone()) HThrow(value); 3780 HThrow* instr = new(zone()) HThrow(context, value);
3614 instr->set_position(expr->position()); 3781 instr->set_position(expr->position());
3615 AddInstruction(instr); 3782 AddInstruction(instr);
3616 AddSimulate(expr->id()); 3783 AddSimulate(expr->id());
3617 current_block()->FinishExit(new(zone()) HAbnormalExit); 3784 current_block()->FinishExit(new(zone()) HAbnormalExit);
3618 set_current_block(NULL); 3785 set_current_block(NULL);
3619 } 3786 }
3620 3787
3621 3788
3622 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, 3789 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
3623 Property* expr, 3790 Property* expr,
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
3675 } 3842 }
3676 3843
3677 3844
3678 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 3845 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
3679 HValue* key) { 3846 HValue* key) {
3680 HValue* context = environment()->LookupContext(); 3847 HValue* context = environment()->LookupContext();
3681 return new(zone()) HLoadKeyedGeneric(context, object, key); 3848 return new(zone()) HLoadKeyedGeneric(context, object, key);
3682 } 3849 }
3683 3850
3684 3851
3685 HInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object, 3852 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess(
3686 HValue* key, 3853 HValue* external_elements,
3687 Property* expr) { 3854 HValue* checked_key,
3688 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); 3855 HValue* val,
3856 JSObject::ElementsKind elements_kind,
3857 bool is_store) {
3858 if (is_store) {
3859 ASSERT(val != NULL);
3860 switch (elements_kind) {
3861 case JSObject::EXTERNAL_PIXEL_ELEMENTS: {
3862 HClampToUint8* clamp = new(zone()) HClampToUint8(val);
3863 AddInstruction(clamp);
3864 val = clamp;
3865 break;
3866 }
3867 case JSObject::EXTERNAL_BYTE_ELEMENTS:
3868 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3869 case JSObject::EXTERNAL_SHORT_ELEMENTS:
3870 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3871 case JSObject::EXTERNAL_INT_ELEMENTS:
3872 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: {
3873 HToInt32* floor_val = new(zone()) HToInt32(val);
3874 AddInstruction(floor_val);
3875 val = floor_val;
3876 break;
3877 }
3878 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
3879 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
3880 break;
3881 case JSObject::FAST_ELEMENTS:
3882 case JSObject::FAST_DOUBLE_ELEMENTS:
3883 case JSObject::DICTIONARY_ELEMENTS:
3884 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
3885 UNREACHABLE();
3886 break;
3887 }
3888 return new(zone()) HStoreKeyedSpecializedArrayElement(
3889 external_elements, checked_key, val, elements_kind);
3890 } else {
3891 return new(zone()) HLoadKeyedSpecializedArrayElement(
3892 external_elements, checked_key, elements_kind);
3893 }
3894 }
3895
3896
3897 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
3898 HValue* key,
3899 HValue* val,
3900 Expression* expr,
3901 bool is_store) {
3902 ASSERT(expr->IsMonomorphic());
3903 Handle<Map> map = expr->GetMonomorphicReceiverType();
3904 if (!map->has_fast_elements() && !map->has_external_array_elements()) {
3905 return is_store ? BuildStoreKeyedGeneric(object, key, val)
3906 : BuildLoadKeyedGeneric(object, key);
3907 }
3689 AddInstruction(new(zone()) HCheckNonSmi(object)); 3908 AddInstruction(new(zone()) HCheckNonSmi(object));
3690 Handle<Map> map = expr->GetMonomorphicReceiverType(); 3909 AddInstruction(new(zone()) HCheckMap(object, map));
3910 HInstruction* elements = new(zone()) HLoadElements(object);
3911 HInstruction* length = NULL;
3912 HInstruction* checked_key = NULL;
3913 if (map->has_external_array_elements()) {
3914 AddInstruction(elements);
3915 length = AddInstruction(new(zone()) HExternalArrayLength(elements));
3916 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3917 HLoadExternalArrayPointer* external_elements =
3918 new(zone()) HLoadExternalArrayPointer(elements);
3919 AddInstruction(external_elements);
3920 return BuildExternalArrayElementAccess(external_elements, checked_key,
3921 val, map->elements_kind(), is_store);
3922 }
3691 ASSERT(map->has_fast_elements()); 3923 ASSERT(map->has_fast_elements());
3692 AddInstruction(new(zone()) HCheckMap(object, map)); 3924 if (map->instance_type() == JS_ARRAY_TYPE) {
3693 bool is_array = (map->instance_type() == JS_ARRAY_TYPE);
3694 HLoadElements* elements = new(zone()) HLoadElements(object);
3695 HInstruction* length = NULL;
3696 if (is_array) {
3697 length = AddInstruction(new(zone()) HJSArrayLength(object)); 3925 length = AddInstruction(new(zone()) HJSArrayLength(object));
3698 AddInstruction(new(zone()) HBoundsCheck(key, length)); 3926 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3699 AddInstruction(elements); 3927 AddInstruction(elements);
3700 } else { 3928 } else {
3701 AddInstruction(elements); 3929 AddInstruction(elements);
3702 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); 3930 length = AddInstruction(new(zone()) HFixedArrayLength(elements));
3703 AddInstruction(new(zone()) HBoundsCheck(key, length)); 3931 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3704 } 3932 }
3705 return new(zone()) HLoadKeyedFastElement(elements, key); 3933 if (is_store) {
3706 } 3934 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val);
3707 3935 } else {
3708 3936 return new(zone()) HLoadKeyedFastElement(elements, checked_key);
3709 HInstruction* HGraphBuilder::BuildLoadKeyedSpecializedArrayElement( 3937 }
3710 HValue* object, 3938 }
3711 HValue* key, 3939
3712 Property* expr) { 3940
3713 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); 3941 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
3942 HValue* key,
3943 HValue* val,
3944 Expression* prop,
3945 int ast_id,
3946 int position,
3947 bool is_store,
3948 bool* has_side_effects) {
3949 *has_side_effects = false;
3714 AddInstruction(new(zone()) HCheckNonSmi(object)); 3950 AddInstruction(new(zone()) HCheckNonSmi(object));
3715 Handle<Map> map = expr->GetMonomorphicReceiverType(); 3951 AddInstruction(HCheckInstanceType::NewIsSpecObject(object));
3716 ASSERT(!map->has_fast_elements()); 3952 ZoneMapList* maps = prop->GetReceiverTypes();
3717 ASSERT(map->has_external_array_elements()); 3953 bool todo_external_array = false;
3718 AddInstruction(new(zone()) HCheckMap(object, map)); 3954
3719 HLoadElements* elements = new(zone()) HLoadElements(object); 3955 static const int kNumElementTypes = JSObject::kElementsKindCount;
3720 AddInstruction(elements); 3956 bool type_todo[kNumElementTypes];
3721 HInstruction* length = new(zone()) HExternalArrayLength(elements); 3957 for (int i = 0; i < kNumElementTypes; ++i) {
3722 AddInstruction(length); 3958 type_todo[i] = false;
3723 AddInstruction(new(zone()) HBoundsCheck(key, length)); 3959 }
3724 HLoadExternalArrayPointer* external_elements = 3960
3725 new(zone()) HLoadExternalArrayPointer(elements); 3961 for (int i = 0; i < maps->length(); ++i) {
3726 AddInstruction(external_elements); 3962 ASSERT(maps->at(i)->IsMap());
3727 HLoadKeyedSpecializedArrayElement* pixel_array_value = 3963 type_todo[maps->at(i)->elements_kind()] = true;
3728 new(zone()) HLoadKeyedSpecializedArrayElement( 3964 if (maps->at(i)->elements_kind()
3729 external_elements, key, expr->external_array_type()); 3965 >= JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) {
3730 return pixel_array_value; 3966 todo_external_array = true;
3731 } 3967 }
3732 3968 }
3733 3969 // Support for FAST_DOUBLE_ELEMENTS isn't implemented yet, so we deopt.
3734 HInstruction* HGraphBuilder::BuildLoadKeyed(HValue* obj, 3970 type_todo[JSObject::FAST_DOUBLE_ELEMENTS] = false;
3735 HValue* key, 3971
3736 Property* prop) { 3972 HBasicBlock* join = graph()->CreateBasicBlock();
3737 if (prop->IsMonomorphic()) { 3973
3738 Handle<Map> receiver_type(prop->GetMonomorphicReceiverType()); 3974 HInstruction* elements_kind_instr =
3739 // An object has either fast elements or pixel array elements, but never 3975 AddInstruction(new(zone()) HElementsKind(object));
3740 // both. Pixel array maps that are assigned to pixel array elements are 3976 HInstruction* elements = NULL;
3741 // always created with the fast elements flag cleared. 3977 HLoadExternalArrayPointer* external_elements = NULL;
3742 if (receiver_type->has_external_array_elements()) { 3978 HInstruction* checked_key = NULL;
3743 return BuildLoadKeyedSpecializedArrayElement(obj, key, prop); 3979
3744 } else if (receiver_type->has_fast_elements()) { 3980 // FAST_ELEMENTS is assumed to be the first case.
3745 return BuildLoadKeyedFastElement(obj, key, prop); 3981 STATIC_ASSERT(JSObject::FAST_ELEMENTS == 0);
3746 } 3982
3747 } 3983 for (JSObject::ElementsKind elements_kind = JSObject::FAST_ELEMENTS;
3748 return BuildLoadKeyedGeneric(obj, key); 3984 elements_kind <= JSObject::LAST_ELEMENTS_KIND;
3749 } 3985 elements_kind = JSObject::ElementsKind(elements_kind + 1)) {
3750 3986 // After having handled FAST_ELEMENTS and DICTIONARY_ELEMENTS, we
3751 3987 // need to add some code that's executed for all external array cases.
3988 STATIC_ASSERT(JSObject::LAST_EXTERNAL_ARRAY_ELEMENTS_KIND ==
3989 JSObject::LAST_ELEMENTS_KIND);
3990 if (elements_kind == JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND
3991 && todo_external_array) {
3992 elements = AddInstruction(new(zone()) HLoadElements(object));
3993 // We need to forcibly prevent some ElementsKind-dependent instructions
3994 // from being hoisted out of any loops they might occur in, because
3995 // the current loop-invariant-code-motion algorithm isn't clever enough
3996 // to deal with them properly.
3997 // There's some performance to be gained by developing a smarter
3998 // solution for this.
3999 elements->ClearFlag(HValue::kUseGVN);
4000 HInstruction* length =
4001 AddInstruction(new(zone()) HExternalArrayLength(elements));
4002 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
4003 external_elements = new(zone()) HLoadExternalArrayPointer(elements);
4004 AddInstruction(external_elements);
4005 }
4006 if (type_todo[elements_kind]) {
4007 HBasicBlock* if_true = graph()->CreateBasicBlock();
4008 HBasicBlock* if_false = graph()->CreateBasicBlock();
4009 HCompareConstantEqAndBranch* compare =
4010 new(zone()) HCompareConstantEqAndBranch(elements_kind_instr,
4011 elements_kind,
4012 Token::EQ_STRICT);
4013 compare->SetSuccessorAt(0, if_true);
4014 compare->SetSuccessorAt(1, if_false);
4015 current_block()->Finish(compare);
4016
4017 set_current_block(if_true);
4018 HInstruction* access;
4019 if (elements_kind == JSObject::FAST_ELEMENTS) {
4020 HBasicBlock* if_jsarray = graph()->CreateBasicBlock();
4021 HBasicBlock* if_fastobject = graph()->CreateBasicBlock();
4022 HHasInstanceTypeAndBranch* typecheck =
4023 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE);
4024 typecheck->SetSuccessorAt(0, if_jsarray);
4025 typecheck->SetSuccessorAt(1, if_fastobject);
4026 current_block()->Finish(typecheck);
4027
4028 set_current_block(if_jsarray);
4029 HInstruction* length = new(zone()) HJSArrayLength(object);
4030 AddInstruction(length);
4031 length->ClearFlag(HValue::kUseGVN);
4032 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
4033 elements = AddInstruction(new(zone()) HLoadElements(object));
4034 elements->ClearFlag(HValue::kUseGVN);
4035 if (is_store) {
4036 access = AddInstruction(
4037 new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
4038 } else {
4039 access = AddInstruction(
4040 new(zone()) HLoadKeyedFastElement(elements, checked_key));
4041 Push(access);
4042 }
4043 *has_side_effects |= access->HasSideEffects();
4044 if (position != -1) {
4045 access->set_position(position);
4046 }
4047 if_jsarray->Goto(join);
4048
4049 set_current_block(if_fastobject);
4050 elements = AddInstruction(new(zone()) HLoadElements(object));
4051 elements->ClearFlag(HValue::kUseGVN);
4052 length = AddInstruction(new(zone()) HFixedArrayLength(elements));
4053 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
4054 if (is_store) {
4055 access = AddInstruction(
4056 new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
4057 } else {
4058 access = AddInstruction(
4059 new(zone()) HLoadKeyedFastElement(elements, checked_key));
4060 }
4061 } else if (elements_kind == JSObject::DICTIONARY_ELEMENTS) {
4062 if (is_store) {
4063 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
4064 } else {
4065 access = AddInstruction(BuildLoadKeyedGeneric(object, key));
4066 }
4067 } else { // External array elements.
4068 access = AddInstruction(BuildExternalArrayElementAccess(
4069 external_elements, checked_key, val, elements_kind, is_store));
4070 }
4071 *has_side_effects |= access->HasSideEffects();
4072 access->set_position(position);
4073 if (!is_store) {
4074 Push(access);
4075 }
4076 current_block()->Goto(join);
4077 set_current_block(if_false);
4078 }
4079 }
4080
4081 // Deopt if none of the cases matched.
4082 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses);
4083 join->SetJoinId(ast_id);
4084 set_current_block(join);
4085 return is_store ? NULL : Pop();
4086 }
4087
4088
4089 HValue* HGraphBuilder::HandleKeyedElementAccess(HValue* obj,
4090 HValue* key,
4091 HValue* val,
4092 Expression* expr,
4093 int ast_id,
4094 int position,
4095 bool is_store,
4096 bool* has_side_effects) {
4097 ASSERT(!expr->IsPropertyName());
4098 HInstruction* instr = NULL;
4099 if (expr->IsMonomorphic()) {
4100 instr = BuildMonomorphicElementAccess(obj, key, val, expr, is_store);
4101 } else if (expr->GetReceiverTypes() != NULL &&
4102 !expr->GetReceiverTypes()->is_empty()) {
4103 return HandlePolymorphicElementAccess(
4104 obj, key, val, expr, ast_id, position, is_store, has_side_effects);
4105 } else {
4106 if (is_store) {
4107 instr = BuildStoreKeyedGeneric(obj, key, val);
4108 } else {
4109 instr = BuildLoadKeyedGeneric(obj, key);
4110 }
4111 }
4112 instr->set_position(position);
4113 AddInstruction(instr);
4114 *has_side_effects = instr->HasSideEffects();
4115 return instr;
4116 }
4117
4118
3752 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object, 4119 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object,
3753 HValue* key, 4120 HValue* key,
3754 HValue* value) { 4121 HValue* value) {
3755 HValue* context = environment()->LookupContext(); 4122 HValue* context = environment()->LookupContext();
3756 return new(zone()) HStoreKeyedGeneric( 4123 return new(zone()) HStoreKeyedGeneric(
3757 context, 4124 context,
3758 object, 4125 object,
3759 key, 4126 key,
3760 value, 4127 value,
3761 function_strict_mode()); 4128 function_strict_mode());
3762 } 4129 }
3763 4130
3764
3765 HInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object,
3766 HValue* key,
3767 HValue* val,
3768 Expression* expr) {
3769 ASSERT(expr->IsMonomorphic());
3770 AddInstruction(new(zone()) HCheckNonSmi(object));
3771 Handle<Map> map = expr->GetMonomorphicReceiverType();
3772 ASSERT(map->has_fast_elements());
3773 AddInstruction(new(zone()) HCheckMap(object, map));
3774 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
3775 AddInstruction(new(zone()) HCheckMap(
3776 elements, isolate()->factory()->fixed_array_map()));
3777 bool is_array = (map->instance_type() == JS_ARRAY_TYPE);
3778 HInstruction* length = NULL;
3779 if (is_array) {
3780 length = AddInstruction(new(zone()) HJSArrayLength(object));
3781 } else {
3782 length = AddInstruction(new(zone()) HFixedArrayLength(elements));
3783 }
3784 AddInstruction(new(zone()) HBoundsCheck(key, length));
3785 return new(zone()) HStoreKeyedFastElement(elements, key, val);
3786 }
3787
3788
3789 HInstruction* HGraphBuilder::BuildStoreKeyedSpecializedArrayElement(
3790 HValue* object,
3791 HValue* key,
3792 HValue* val,
3793 Expression* expr) {
3794 ASSERT(expr->IsMonomorphic());
3795 AddInstruction(new(zone()) HCheckNonSmi(object));
3796 Handle<Map> map = expr->GetMonomorphicReceiverType();
3797 ASSERT(!map->has_fast_elements());
3798 ASSERT(map->has_external_array_elements());
3799 AddInstruction(new(zone()) HCheckMap(object, map));
3800 HLoadElements* elements = new(zone()) HLoadElements(object);
3801 AddInstruction(elements);
3802 HInstruction* length = AddInstruction(
3803 new(zone()) HExternalArrayLength(elements));
3804 AddInstruction(new(zone()) HBoundsCheck(key, length));
3805 HLoadExternalArrayPointer* external_elements =
3806 new(zone()) HLoadExternalArrayPointer(elements);
3807 AddInstruction(external_elements);
3808 if (expr->external_array_type() == kExternalPixelArray) {
3809 HClampToUint8* clamp = new(zone()) HClampToUint8(val);
3810 AddInstruction(clamp);
3811 val = clamp;
3812 }
3813 return new(zone()) HStoreKeyedSpecializedArrayElement(
3814 external_elements,
3815 key,
3816 val,
3817 expr->external_array_type());
3818 }
3819
3820
3821 HInstruction* HGraphBuilder::BuildStoreKeyed(HValue* object,
3822 HValue* key,
3823 HValue* value,
3824 Expression* expr) {
3825 if (expr->IsMonomorphic()) {
3826 Handle<Map> receiver_type(expr->GetMonomorphicReceiverType());
3827 // An object has either fast elements or external array elements, but
3828 // never both. Pixel array maps that are assigned to pixel array elements
3829 // are always created with the fast elements flag cleared.
3830 if (receiver_type->has_external_array_elements()) {
3831 return BuildStoreKeyedSpecializedArrayElement(object,
3832 key,
3833 value,
3834 expr);
3835 } else if (receiver_type->has_fast_elements()) {
3836 return BuildStoreKeyedFastElement(object, key, value, expr);
3837 }
3838 }
3839 return BuildStoreKeyedGeneric(object, key, value);
3840 }
3841
3842
3843 bool HGraphBuilder::TryArgumentsAccess(Property* expr) { 4131 bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
3844 VariableProxy* proxy = expr->obj()->AsVariableProxy(); 4132 VariableProxy* proxy = expr->obj()->AsVariableProxy();
3845 if (proxy == NULL) return false; 4133 if (proxy == NULL) return false;
3846 if (!proxy->var()->IsStackAllocated()) return false; 4134 if (!proxy->var()->IsStackAllocated()) return false;
3847 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { 4135 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
3848 return false; 4136 return false;
3849 } 4137 }
3850 4138
4139 // Our implementation of arguments (based on this stack frame or an
4140 // adapter below it) does not work for inlined functions.
4141 if (function_state()->outer() != NULL) {
4142 Bailout("arguments access in inlined function");
4143 return true;
4144 }
4145
3851 HInstruction* result = NULL; 4146 HInstruction* result = NULL;
3852 if (expr->key()->IsPropertyName()) { 4147 if (expr->key()->IsPropertyName()) {
3853 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 4148 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
3854 if (!name->IsEqualTo(CStrVector("length"))) return false; 4149 if (!name->IsEqualTo(CStrVector("length"))) return false;
3855 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 4150 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
3856 result = new(zone()) HArgumentsLength(elements); 4151 result = new(zone()) HArgumentsLength(elements);
3857 } else { 4152 } else {
3858 Push(graph()->GetArgumentsObject()); 4153 Push(graph()->GetArgumentsObject());
3859 VisitForValue(expr->key()); 4154 VisitForValue(expr->key());
3860 if (HasStackOverflow() || current_block() == NULL) return true; 4155 if (HasStackOverflow() || current_block() == NULL) return true;
3861 HValue* key = Pop(); 4156 HValue* key = Pop();
3862 Drop(1); // Arguments object. 4157 Drop(1); // Arguments object.
3863 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 4158 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
3864 HInstruction* length = AddInstruction( 4159 HInstruction* length = AddInstruction(
3865 new(zone()) HArgumentsLength(elements)); 4160 new(zone()) HArgumentsLength(elements));
3866 AddInstruction(new(zone()) HBoundsCheck(key, length)); 4161 HInstruction* checked_key =
3867 result = new(zone()) HAccessArgumentsAt(elements, length, key); 4162 AddInstruction(new(zone()) HBoundsCheck(key, length));
4163 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key);
3868 } 4164 }
3869 ast_context()->ReturnInstruction(result, expr->id()); 4165 ast_context()->ReturnInstruction(result, expr->id());
3870 return true; 4166 return true;
3871 } 4167 }
3872 4168
3873 4169
3874 void HGraphBuilder::VisitProperty(Property* expr) { 4170 void HGraphBuilder::VisitProperty(Property* expr) {
3875 ASSERT(!HasStackOverflow()); 4171 ASSERT(!HasStackOverflow());
3876 ASSERT(current_block() != NULL); 4172 ASSERT(current_block() != NULL);
3877 ASSERT(current_block()->HasPredecessor()); 4173 ASSERT(current_block()->HasPredecessor());
(...skipping 12 matching lines...) Expand all
3890 4186
3891 } else if (expr->IsStringLength()) { 4187 } else if (expr->IsStringLength()) {
3892 HValue* string = Pop(); 4188 HValue* string = Pop();
3893 AddInstruction(new(zone()) HCheckNonSmi(string)); 4189 AddInstruction(new(zone()) HCheckNonSmi(string));
3894 AddInstruction(HCheckInstanceType::NewIsString(string)); 4190 AddInstruction(HCheckInstanceType::NewIsString(string));
3895 instr = new(zone()) HStringLength(string); 4191 instr = new(zone()) HStringLength(string);
3896 } else if (expr->IsStringAccess()) { 4192 } else if (expr->IsStringAccess()) {
3897 CHECK_ALIVE(VisitForValue(expr->key())); 4193 CHECK_ALIVE(VisitForValue(expr->key()));
3898 HValue* index = Pop(); 4194 HValue* index = Pop();
3899 HValue* string = Pop(); 4195 HValue* string = Pop();
3900 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); 4196 HValue* context = environment()->LookupContext();
4197 HStringCharCodeAt* char_code =
4198 BuildStringCharCodeAt(context, string, index);
3901 AddInstruction(char_code); 4199 AddInstruction(char_code);
3902 instr = new(zone()) HStringCharFromCode(char_code); 4200 instr = new(zone()) HStringCharFromCode(context, char_code);
3903 4201
3904 } else if (expr->IsFunctionPrototype()) { 4202 } else if (expr->IsFunctionPrototype()) {
3905 HValue* function = Pop(); 4203 HValue* function = Pop();
3906 AddInstruction(new(zone()) HCheckNonSmi(function)); 4204 AddInstruction(new(zone()) HCheckNonSmi(function));
3907 instr = new(zone()) HLoadFunctionPrototype(function); 4205 instr = new(zone()) HLoadFunctionPrototype(function);
3908 4206
3909 } else if (expr->key()->IsPropertyName()) { 4207 } else if (expr->key()->IsPropertyName()) {
3910 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 4208 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
3911 ZoneMapList* types = expr->GetReceiverTypes(); 4209 ZoneMapList* types = expr->GetReceiverTypes();
3912 4210
3913 HValue* obj = Pop(); 4211 HValue* obj = Pop();
3914 if (expr->IsMonomorphic()) { 4212 if (expr->IsMonomorphic()) {
3915 instr = BuildLoadNamed(obj, expr, types->first(), name); 4213 instr = BuildLoadNamed(obj, expr, types->first(), name);
3916 } else if (types != NULL && types->length() > 1) { 4214 } else if (types != NULL && types->length() > 1) {
3917 AddInstruction(new(zone()) HCheckNonSmi(obj)); 4215 AddInstruction(new(zone()) HCheckNonSmi(obj));
3918 instr = new(zone()) HLoadNamedFieldPolymorphic(obj, types, name); 4216 HValue* context = environment()->LookupContext();
4217 instr = new(zone()) HLoadNamedFieldPolymorphic(context, obj, types, name);
3919 } else { 4218 } else {
3920 instr = BuildLoadNamedGeneric(obj, expr); 4219 instr = BuildLoadNamedGeneric(obj, expr);
3921 } 4220 }
3922 4221
3923 } else { 4222 } else {
3924 CHECK_ALIVE(VisitForValue(expr->key())); 4223 CHECK_ALIVE(VisitForValue(expr->key()));
3925 4224
3926 HValue* key = Pop(); 4225 HValue* key = Pop();
3927 HValue* obj = Pop(); 4226 HValue* obj = Pop();
3928 instr = BuildLoadKeyed(obj, key, expr); 4227
4228 bool has_side_effects = false;
4229 HValue* load = HandleKeyedElementAccess(
4230 obj, key, NULL, expr, expr->id(), expr->position(),
4231 false, // is_store
4232 &has_side_effects);
4233 if (has_side_effects) {
4234 if (ast_context()->IsEffect()) {
4235 AddSimulate(expr->id());
4236 } else {
4237 Push(load);
4238 AddSimulate(expr->id());
4239 Drop(1);
4240 }
4241 }
4242 return ast_context()->ReturnValue(load);
3929 } 4243 }
3930 instr->set_position(expr->position()); 4244 instr->set_position(expr->position());
3931 ast_context()->ReturnInstruction(instr, expr->id()); 4245 return ast_context()->ReturnInstruction(instr, expr->id());
3932 } 4246 }
3933 4247
3934 4248
3935 void HGraphBuilder::AddCheckConstantFunction(Call* expr, 4249 void HGraphBuilder::AddCheckConstantFunction(Call* expr,
3936 HValue* receiver, 4250 HValue* receiver,
3937 Handle<Map> receiver_map, 4251 Handle<Map> receiver_map,
3938 bool smi_and_map_check) { 4252 bool smi_and_map_check) {
3939 // Constant functions have the nice property that the map will change if they 4253 // Constant functions have the nice property that the map will change if they
3940 // are overwritten. Therefore it is enough to check the map of the holder and 4254 // are overwritten. Therefore it is enough to check the map of the holder and
3941 // its prototypes. 4255 // its prototypes.
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
4009 HValue* context = environment()->LookupContext(); 4323 HValue* context = environment()->LookupContext();
4010 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); 4324 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count);
4011 call->set_position(expr->position()); 4325 call->set_position(expr->position());
4012 PreProcessCall(call); 4326 PreProcessCall(call);
4013 4327
4014 if (join != NULL) { 4328 if (join != NULL) {
4015 AddInstruction(call); 4329 AddInstruction(call);
4016 if (!ast_context()->IsEffect()) Push(call); 4330 if (!ast_context()->IsEffect()) Push(call);
4017 current_block()->Goto(join); 4331 current_block()->Goto(join);
4018 } else { 4332 } else {
4019 ast_context()->ReturnInstruction(call, expr->id()); 4333 return ast_context()->ReturnInstruction(call, expr->id());
4020 return;
4021 } 4334 }
4022 } 4335 }
4023 4336
4024 // We assume that control flow is always live after an expression. So 4337 // We assume that control flow is always live after an expression. So
4025 // even without predecessors to the join block, we set it as the exit 4338 // even without predecessors to the join block, we set it as the exit
4026 // block and continue by adding instructions there. 4339 // block and continue by adding instructions there.
4027 ASSERT(join != NULL); 4340 ASSERT(join != NULL);
4028 if (join->HasPredecessor()) { 4341 if (join->HasPredecessor()) {
4029 set_current_block(join); 4342 set_current_block(join);
4030 join->SetJoinId(expr->id()); 4343 join->SetJoinId(expr->id());
4031 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); 4344 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
4032 } else { 4345 } else {
4033 set_current_block(NULL); 4346 set_current_block(NULL);
4034 } 4347 }
4035 } 4348 }
4036 4349
4037 4350
4038 void HGraphBuilder::TraceInline(Handle<JSFunction> target, 4351 void HGraphBuilder::TraceInline(Handle<JSFunction> target,
4039 Handle<JSFunction> caller, 4352 Handle<JSFunction> caller,
4040 const char* reason) { 4353 const char* reason) {
4041 if (FLAG_trace_inlining) { 4354 if (FLAG_trace_inlining) {
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
4133 } 4446 }
4134 FunctionLiteral* function = target_info.function(); 4447 FunctionLiteral* function = target_info.function();
4135 4448
4136 // Count the number of AST nodes added by inlining this call. 4449 // Count the number of AST nodes added by inlining this call.
4137 int nodes_added = AstNode::Count() - count_before; 4450 int nodes_added = AstNode::Count() - count_before;
4138 if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) { 4451 if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) {
4139 TraceInline(target, caller, "target AST is too large"); 4452 TraceInline(target, caller, "target AST is too large");
4140 return false; 4453 return false;
4141 } 4454 }
4142 4455
4143 // Check if we can handle all declarations in the inlined functions.
4144 VisitDeclarations(target_info.scope()->declarations());
4145 if (HasStackOverflow()) {
4146 TraceInline(target, caller, "target has non-trivial declaration");
4147 ClearStackOverflow();
4148 return false;
4149 }
4150
4151 // Don't inline functions that uses the arguments object or that 4456 // Don't inline functions that uses the arguments object or that
4152 // have a mismatching number of parameters. 4457 // have a mismatching number of parameters.
4153 int arity = expr->arguments()->length(); 4458 int arity = expr->arguments()->length();
4154 if (function->scope()->arguments() != NULL || 4459 if (function->scope()->arguments() != NULL ||
4155 arity != target_shared->formal_parameter_count()) { 4460 arity != target_shared->formal_parameter_count()) {
4156 TraceInline(target, caller, "target requires special argument handling"); 4461 TraceInline(target, caller, "target requires special argument handling");
4157 return false; 4462 return false;
4158 } 4463 }
4159 4464
4465 // All declarations must be inlineable.
4466 ZoneList<Declaration*>* decls = target_info.scope()->declarations();
4467 int decl_count = decls->length();
4468 for (int i = 0; i < decl_count; ++i) {
4469 if (!decls->at(i)->IsInlineable()) {
4470 TraceInline(target, caller, "target has non-trivial declaration");
4471 return false;
4472 }
4473 }
4160 // All statements in the body must be inlineable. 4474 // All statements in the body must be inlineable.
4161 for (int i = 0, count = function->body()->length(); i < count; ++i) { 4475 for (int i = 0, count = function->body()->length(); i < count; ++i) {
4162 if (!function->body()->at(i)->IsInlineable()) { 4476 if (!function->body()->at(i)->IsInlineable()) {
4163 TraceInline(target, caller, "target contains unsupported syntax"); 4477 TraceInline(target, caller, "target contains unsupported syntax");
4164 return false; 4478 return false;
4165 } 4479 }
4166 } 4480 }
4167 4481
4168 // Generate the deoptimization data for the unoptimized version of 4482 // Generate the deoptimization data for the unoptimized version of
4169 // the target function if we don't already have it. 4483 // the target function if we don't already have it.
4170 if (!target_shared->has_deoptimization_support()) { 4484 if (!target_shared->has_deoptimization_support()) {
4171 // Note that we compile here using the same AST that we will use for 4485 // Note that we compile here using the same AST that we will use for
4172 // generating the optimized inline code. 4486 // generating the optimized inline code.
4173 target_info.EnableDeoptimizationSupport(); 4487 target_info.EnableDeoptimizationSupport();
4174 if (!FullCodeGenerator::MakeCode(&target_info)) { 4488 if (!FullCodeGenerator::MakeCode(&target_info)) {
4175 TraceInline(target, caller, "could not generate deoptimization info"); 4489 TraceInline(target, caller, "could not generate deoptimization info");
4176 return false; 4490 return false;
4177 } 4491 }
4492 if (target_shared->scope_info() == SerializedScopeInfo::Empty()) {
4493 // The scope info might not have been set if a lazily compiled
4494 // function is inlined before being called for the first time.
4495 Handle<SerializedScopeInfo> target_scope_info =
4496 SerializedScopeInfo::Create(target_info.scope());
4497 target_shared->set_scope_info(*target_scope_info);
4498 }
4178 target_shared->EnableDeoptimizationSupport(*target_info.code()); 4499 target_shared->EnableDeoptimizationSupport(*target_info.code());
4179 Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG, 4500 Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG,
4180 &target_info, 4501 &target_info,
4181 target_shared); 4502 target_shared);
4182 } 4503 }
4183 4504
4184 // ---------------------------------------------------------------- 4505 // ----------------------------------------------------------------
4506 // After this point, we've made a decision to inline this function (so
4507 // TryInline should always return true).
4508
4185 // Save the pending call context and type feedback oracle. Set up new ones 4509 // Save the pending call context and type feedback oracle. Set up new ones
4186 // for the inlined function. 4510 // for the inlined function.
4187 ASSERT(target_shared->has_deoptimization_support()); 4511 ASSERT(target_shared->has_deoptimization_support());
4188 TypeFeedbackOracle target_oracle( 4512 TypeFeedbackOracle target_oracle(
4189 Handle<Code>(target_shared->code()), 4513 Handle<Code>(target_shared->code()),
4190 Handle<Context>(target->context()->global_context())); 4514 Handle<Context>(target->context()->global_context()));
4191 FunctionState target_state(this, &target_info, &target_oracle); 4515 FunctionState target_state(this, &target_info, &target_oracle);
4192 4516
4193 HConstant* undefined = graph()->GetConstantUndefined(); 4517 HConstant* undefined = graph()->GetConstantUndefined();
4194 HEnvironment* inner_env = 4518 HEnvironment* inner_env =
4195 environment()->CopyForInlining(target, 4519 environment()->CopyForInlining(target,
4196 function, 4520 function,
4197 HEnvironment::HYDROGEN,
4198 undefined, 4521 undefined,
4199 call_kind); 4522 call_kind);
4200 HBasicBlock* body_entry = CreateBasicBlock(inner_env); 4523 HBasicBlock* body_entry = CreateBasicBlock(inner_env);
4201 current_block()->Goto(body_entry); 4524 current_block()->Goto(body_entry);
4202
4203 body_entry->SetJoinId(expr->ReturnId()); 4525 body_entry->SetJoinId(expr->ReturnId());
4204 set_current_block(body_entry); 4526 set_current_block(body_entry);
4205 AddInstruction(new(zone()) HEnterInlined(target, 4527 AddInstruction(new(zone()) HEnterInlined(target,
4206 function, 4528 function,
4207 call_kind)); 4529 call_kind));
4530 VisitDeclarations(target_info.scope()->declarations());
4208 VisitStatements(function->body()); 4531 VisitStatements(function->body());
4209 if (HasStackOverflow()) { 4532 if (HasStackOverflow()) {
4210 // Bail out if the inline function did, as we cannot residualize a call 4533 // Bail out if the inline function did, as we cannot residualize a call
4211 // instead. 4534 // instead.
4212 TraceInline(target, caller, "inline graph construction failed"); 4535 TraceInline(target, caller, "inline graph construction failed");
4213 target_shared->DisableOptimization(*target); 4536 target_shared->DisableOptimization(*target);
4214 inline_bailout_ = true; 4537 inline_bailout_ = true;
4215 return true; 4538 return true;
4216 } 4539 }
4217 4540
4218 // Update inlined nodes count. 4541 // Update inlined nodes count.
4219 inlined_count_ += nodes_added; 4542 inlined_count_ += nodes_added;
4220 4543
4221 TraceInline(target, caller, NULL); 4544 TraceInline(target, caller, NULL);
4222 4545
4223 if (current_block() != NULL) { 4546 if (current_block() != NULL) {
4224 // Add a return of undefined if control can fall off the body. In a 4547 // Add a return of undefined if control can fall off the body. In a
4225 // test context, undefined is false. 4548 // test context, undefined is false.
4226 if (inlined_test_context() == NULL) { 4549 if (inlined_test_context() == NULL) {
4227 ASSERT(function_return() != NULL); 4550 ASSERT(function_return() != NULL);
4228 ASSERT(call_context()->IsEffect() || call_context()->IsValue()); 4551 ASSERT(call_context()->IsEffect() || call_context()->IsValue());
4229 if (call_context()->IsEffect()) { 4552 if (call_context()->IsEffect()) {
4230 current_block()->Goto(function_return(), false); 4553 current_block()->Goto(function_return());
4231 } else { 4554 } else {
4232 current_block()->AddLeaveInlined(undefined, function_return()); 4555 current_block()->AddLeaveInlined(undefined, function_return());
4233 } 4556 }
4234 } else { 4557 } else {
4235 // The graph builder assumes control can reach both branches of a 4558 // The graph builder assumes control can reach both branches of a
4236 // test, so we materialize the undefined value and test it rather than 4559 // test, so we materialize the undefined value and test it rather than
4237 // simply jumping to the false target. 4560 // simply jumping to the false target.
4238 // 4561 //
4239 // TODO(3168478): refactor to avoid this. 4562 // TODO(3168478): refactor to avoid this.
4240 HBasicBlock* empty_true = graph()->CreateBasicBlock(); 4563 HBasicBlock* empty_true = graph()->CreateBasicBlock();
4241 HBasicBlock* empty_false = graph()->CreateBasicBlock(); 4564 HBasicBlock* empty_false = graph()->CreateBasicBlock();
4242 HTest* test = new(zone()) HTest(undefined, empty_true, empty_false); 4565 HBranch* test = new(zone()) HBranch(undefined, empty_true, empty_false);
4243 current_block()->Finish(test); 4566 current_block()->Finish(test);
4244 4567
4245 empty_true->Goto(inlined_test_context()->if_true(), false); 4568 empty_true->Goto(inlined_test_context()->if_true());
4246 empty_false->Goto(inlined_test_context()->if_false(), false); 4569 empty_false->Goto(inlined_test_context()->if_false());
4247 } 4570 }
4248 } 4571 }
4249 4572
4250 // Fix up the function exits. 4573 // Fix up the function exits.
4251 if (inlined_test_context() != NULL) { 4574 if (inlined_test_context() != NULL) {
4252 HBasicBlock* if_true = inlined_test_context()->if_true(); 4575 HBasicBlock* if_true = inlined_test_context()->if_true();
4253 HBasicBlock* if_false = inlined_test_context()->if_false(); 4576 HBasicBlock* if_false = inlined_test_context()->if_false();
4254 if_true->SetJoinId(expr->id()); 4577
4255 if_false->SetJoinId(expr->id()); 4578 // Pop the return test context from the expression context stack.
4256 ASSERT(ast_context() == inlined_test_context()); 4579 ASSERT(ast_context() == inlined_test_context());
4257 // Pop the return test context from the expression context stack.
4258 ClearInlinedTestContext(); 4580 ClearInlinedTestContext();
4259 4581
4260 // Forward to the real test context. 4582 // Forward to the real test context.
4261 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 4583 if (if_true->HasPredecessor()) {
4262 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 4584 if_true->SetJoinId(expr->id());
4263 if_true->Goto(true_target, false); 4585 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
4264 if_false->Goto(false_target, false); 4586 if_true->Goto(true_target);
4265 4587 }
4266 // TODO(kmillikin): Come up with a better way to handle this. It is too 4588 if (if_false->HasPredecessor()) {
4267 // subtle. NULL here indicates that the enclosing context has no control 4589 if_false->SetJoinId(expr->id());
4268 // flow to handle. 4590 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
4591 if_false->Goto(false_target);
4592 }
4269 set_current_block(NULL); 4593 set_current_block(NULL);
4270 4594
4271 } else if (function_return()->HasPredecessor()) { 4595 } else if (function_return()->HasPredecessor()) {
4272 function_return()->SetJoinId(expr->id()); 4596 function_return()->SetJoinId(expr->id());
4273 set_current_block(function_return()); 4597 set_current_block(function_return());
4274 } else { 4598 } else {
4275 set_current_block(NULL); 4599 set_current_block(NULL);
4276 } 4600 }
4277 4601
4278 return true; 4602 return true;
4279 } 4603 }
4280 4604
4281 4605
4282 bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr, 4606 bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr,
4283 HValue* receiver, 4607 HValue* receiver,
4284 Handle<Map> receiver_map, 4608 Handle<Map> receiver_map,
4285 CheckType check_type) { 4609 CheckType check_type) {
4286 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); 4610 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null());
4287 // Try to inline calls like Math.* as operations in the calling function. 4611 // Try to inline calls like Math.* as operations in the calling function.
4288 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; 4612 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
4289 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 4613 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
4290 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4614 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
4291 switch (id) { 4615 switch (id) {
4292 case kStringCharCodeAt: 4616 case kStringCharCodeAt:
4293 case kStringCharAt: 4617 case kStringCharAt:
4294 if (argument_count == 2 && check_type == STRING_CHECK) { 4618 if (argument_count == 2 && check_type == STRING_CHECK) {
4295 HValue* index = Pop(); 4619 HValue* index = Pop();
4296 HValue* string = Pop(); 4620 HValue* string = Pop();
4621 HValue* context = environment()->LookupContext();
4297 ASSERT(!expr->holder().is_null()); 4622 ASSERT(!expr->holder().is_null());
4298 AddInstruction(new(zone()) HCheckPrototypeMaps( 4623 AddInstruction(new(zone()) HCheckPrototypeMaps(
4299 oracle()->GetPrototypeForPrimitiveCheck(STRING_CHECK), 4624 oracle()->GetPrototypeForPrimitiveCheck(STRING_CHECK),
4300 expr->holder())); 4625 expr->holder()));
4301 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); 4626 HStringCharCodeAt* char_code =
4627 BuildStringCharCodeAt(context, string, index);
4302 if (id == kStringCharCodeAt) { 4628 if (id == kStringCharCodeAt) {
4303 ast_context()->ReturnInstruction(char_code, expr->id()); 4629 ast_context()->ReturnInstruction(char_code, expr->id());
4304 return true; 4630 return true;
4305 } 4631 }
4306 AddInstruction(char_code); 4632 AddInstruction(char_code);
4307 HStringCharFromCode* result = 4633 HStringCharFromCode* result =
4308 new(zone()) HStringCharFromCode(char_code); 4634 new(zone()) HStringCharFromCode(context, char_code);
4309 ast_context()->ReturnInstruction(result, expr->id()); 4635 ast_context()->ReturnInstruction(result, expr->id());
4310 return true; 4636 return true;
4311 } 4637 }
4312 break; 4638 break;
4313 case kMathRound: 4639 case kMathRound:
4314 case kMathFloor: 4640 case kMathFloor:
4315 case kMathAbs: 4641 case kMathAbs:
4316 case kMathSqrt: 4642 case kMathSqrt:
4317 case kMathLog: 4643 case kMathLog:
4318 case kMathSin: 4644 case kMathSin:
4319 case kMathCos: 4645 case kMathCos:
4320 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { 4646 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) {
4321 AddCheckConstantFunction(expr, receiver, receiver_map, true); 4647 AddCheckConstantFunction(expr, receiver, receiver_map, true);
4322 HValue* argument = Pop(); 4648 HValue* argument = Pop();
4649 HValue* context = environment()->LookupContext();
4323 Drop(1); // Receiver. 4650 Drop(1); // Receiver.
4324 HUnaryMathOperation* op = new(zone()) HUnaryMathOperation(argument, id); 4651 HUnaryMathOperation* op =
4652 new(zone()) HUnaryMathOperation(context, argument, id);
4325 op->set_position(expr->position()); 4653 op->set_position(expr->position());
4326 ast_context()->ReturnInstruction(op, expr->id()); 4654 ast_context()->ReturnInstruction(op, expr->id());
4327 return true; 4655 return true;
4328 } 4656 }
4329 break; 4657 break;
4330 case kMathPow: 4658 case kMathPow:
4331 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 4659 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
4332 AddCheckConstantFunction(expr, receiver, receiver_map, true); 4660 AddCheckConstantFunction(expr, receiver, receiver_map, true);
4333 HValue* right = Pop(); 4661 HValue* right = Pop();
4334 HValue* left = Pop(); 4662 HValue* left = Pop();
4335 Pop(); // Pop receiver. 4663 Pop(); // Pop receiver.
4664 HValue* context = environment()->LookupContext();
4336 HInstruction* result = NULL; 4665 HInstruction* result = NULL;
4337 // Use sqrt() if exponent is 0.5 or -0.5. 4666 // Use sqrt() if exponent is 0.5 or -0.5.
4338 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { 4667 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
4339 double exponent = HConstant::cast(right)->DoubleValue(); 4668 double exponent = HConstant::cast(right)->DoubleValue();
4340 if (exponent == 0.5) { 4669 if (exponent == 0.5) {
4341 result = new(zone()) HUnaryMathOperation(left, kMathPowHalf); 4670 result =
4671 new(zone()) HUnaryMathOperation(context, left, kMathPowHalf);
4342 } else if (exponent == -0.5) { 4672 } else if (exponent == -0.5) {
4343 HConstant* double_one = 4673 HConstant* double_one =
4344 new(zone()) HConstant(Handle<Object>(Smi::FromInt(1)), 4674 new(zone()) HConstant(Handle<Object>(Smi::FromInt(1)),
4345 Representation::Double()); 4675 Representation::Double());
4346 AddInstruction(double_one); 4676 AddInstruction(double_one);
4347 HUnaryMathOperation* square_root = 4677 HUnaryMathOperation* square_root =
4348 new(zone()) HUnaryMathOperation(left, kMathPowHalf); 4678 new(zone()) HUnaryMathOperation(context, left, kMathPowHalf);
4349 AddInstruction(square_root); 4679 AddInstruction(square_root);
4350 // MathPowHalf doesn't have side effects so there's no need for 4680 // MathPowHalf doesn't have side effects so there's no need for
4351 // an environment simulation here. 4681 // an environment simulation here.
4352 ASSERT(!square_root->HasSideEffects()); 4682 ASSERT(!square_root->HasSideEffects());
4353 result = new(zone()) HDiv(double_one, square_root); 4683 result = new(zone()) HDiv(context, double_one, square_root);
4354 } else if (exponent == 2.0) { 4684 } else if (exponent == 2.0) {
4355 result = new(zone()) HMul(left, left); 4685 result = new(zone()) HMul(context, left, left);
4356 } 4686 }
4357 } else if (right->IsConstant() && 4687 } else if (right->IsConstant() &&
4358 HConstant::cast(right)->HasInteger32Value() && 4688 HConstant::cast(right)->HasInteger32Value() &&
4359 HConstant::cast(right)->Integer32Value() == 2) { 4689 HConstant::cast(right)->Integer32Value() == 2) {
4360 result = new(zone()) HMul(left, left); 4690 result = new(zone()) HMul(context, left, left);
4361 } 4691 }
4362 4692
4363 if (result == NULL) { 4693 if (result == NULL) {
4364 result = new(zone()) HPower(left, right); 4694 result = new(zone()) HPower(left, right);
4365 } 4695 }
4366 ast_context()->ReturnInstruction(result, expr->id()); 4696 ast_context()->ReturnInstruction(result, expr->id());
4367 return true; 4697 return true;
4368 } 4698 }
4369 break; 4699 break;
4370 default: 4700 default:
(...skipping 18 matching lines...) Expand all
4389 if (args->length() != 2) return false; 4719 if (args->length() != 2) return false;
4390 4720
4391 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); 4721 VariableProxy* arg_two = args->at(1)->AsVariableProxy();
4392 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; 4722 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
4393 HValue* arg_two_value = environment()->Lookup(arg_two->var()); 4723 HValue* arg_two_value = environment()->Lookup(arg_two->var());
4394 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; 4724 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
4395 4725
4396 if (!expr->IsMonomorphic() || 4726 if (!expr->IsMonomorphic() ||
4397 expr->check_type() != RECEIVER_MAP_CHECK) return false; 4727 expr->check_type() != RECEIVER_MAP_CHECK) return false;
4398 4728
4729 // Our implementation of arguments (based on this stack frame or an
4730 // adapter below it) does not work for inlined functions.
4731 if (function_state()->outer() != NULL) {
4732 Bailout("Function.prototype.apply optimization in inlined function");
4733 return true;
4734 }
4735
4399 // Found pattern f.apply(receiver, arguments). 4736 // Found pattern f.apply(receiver, arguments).
4400 VisitForValue(prop->obj()); 4737 VisitForValue(prop->obj());
4401 if (HasStackOverflow() || current_block() == NULL) return true; 4738 if (HasStackOverflow() || current_block() == NULL) return true;
4402 HValue* function = Pop(); 4739 HValue* function = Pop();
4403 VisitForValue(args->at(0)); 4740 VisitForValue(args->at(0));
4404 if (HasStackOverflow() || current_block() == NULL) return true; 4741 if (HasStackOverflow() || current_block() == NULL) return true;
4405 HValue* receiver = Pop(); 4742 HValue* receiver = Pop();
4406 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 4743 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
4407 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); 4744 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements));
4408 AddCheckConstantFunction(expr, 4745 AddCheckConstantFunction(expr,
(...skipping 13 matching lines...) Expand all
4422 ASSERT(current_block() != NULL); 4759 ASSERT(current_block() != NULL);
4423 ASSERT(current_block()->HasPredecessor()); 4760 ASSERT(current_block()->HasPredecessor());
4424 Expression* callee = expr->expression(); 4761 Expression* callee = expr->expression();
4425 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4762 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
4426 HInstruction* call = NULL; 4763 HInstruction* call = NULL;
4427 4764
4428 Property* prop = callee->AsProperty(); 4765 Property* prop = callee->AsProperty();
4429 if (prop != NULL) { 4766 if (prop != NULL) {
4430 if (!prop->key()->IsPropertyName()) { 4767 if (!prop->key()->IsPropertyName()) {
4431 // Keyed function call. 4768 // Keyed function call.
4432 CHECK_ALIVE(VisitForValue(prop->obj())); 4769 CHECK_ALIVE(VisitArgument(prop->obj()));
4433 4770
4434 CHECK_ALIVE(VisitForValue(prop->key())); 4771 CHECK_ALIVE(VisitForValue(prop->key()));
4435 // Push receiver and key like the non-optimized code generator expects it. 4772 // Push receiver and key like the non-optimized code generator expects it.
4436 HValue* key = Pop(); 4773 HValue* key = Pop();
4437 HValue* receiver = Pop(); 4774 HValue* receiver = Pop();
4438 Push(key); 4775 Push(key);
4439 Push(receiver); 4776 Push(receiver);
4440 4777
4441 CHECK_ALIVE(VisitExpressions(expr->arguments())); 4778 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
4442 4779
4443 HValue* context = environment()->LookupContext(); 4780 HValue* context = environment()->LookupContext();
4444 call = PreProcessCall( 4781 call = new(zone()) HCallKeyed(context, key, argument_count);
4445 new(zone()) HCallKeyed(context, key, argument_count));
4446 call->set_position(expr->position()); 4782 call->set_position(expr->position());
4447 Drop(1); // Key. 4783 Drop(argument_count + 1); // 1 is the key.
4448 ast_context()->ReturnInstruction(call, expr->id()); 4784 return ast_context()->ReturnInstruction(call, expr->id());
4449 return;
4450 } 4785 }
4451 4786
4452 // Named function call. 4787 // Named function call.
4453 expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD); 4788 expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD);
4454 4789
4455 if (TryCallApply(expr)) return; 4790 if (TryCallApply(expr)) return;
4456 4791
4457 CHECK_ALIVE(VisitForValue(prop->obj())); 4792 CHECK_ALIVE(VisitForValue(prop->obj()));
4458 CHECK_ALIVE(VisitExpressions(expr->arguments())); 4793 CHECK_ALIVE(VisitExpressions(expr->arguments()));
4459 4794
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
4497 } else { 4832 } else {
4498 HValue* context = environment()->LookupContext(); 4833 HValue* context = environment()->LookupContext();
4499 call = PreProcessCall( 4834 call = PreProcessCall(
4500 new(zone()) HCallNamed(context, name, argument_count)); 4835 new(zone()) HCallNamed(context, name, argument_count));
4501 } 4836 }
4502 4837
4503 } else { 4838 } else {
4504 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 4839 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
4505 bool global_call = (var != NULL) && var->is_global() && !var->is_this(); 4840 bool global_call = (var != NULL) && var->is_global() && !var->is_this();
4506 4841
4507 if (!global_call) {
4508 ++argument_count;
4509 CHECK_ALIVE(VisitForValue(expr->expression()));
4510 }
4511
4512 if (global_call) { 4842 if (global_call) {
4513 bool known_global_function = false; 4843 bool known_global_function = false;
4514 // If there is a global property cell for the name at compile time and 4844 // If there is a global property cell for the name at compile time and
4515 // access check is not enabled we assume that the function will not change 4845 // access check is not enabled we assume that the function will not change
4516 // and generate optimized code for calling the function. 4846 // and generate optimized code for calling the function.
4517 LookupResult lookup; 4847 LookupResult lookup;
4518 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); 4848 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
4519 if (type == kUseCell && 4849 if (type == kUseCell &&
4520 !info()->global_object()->IsAccessCheckNeeded()) { 4850 !info()->global_object()->IsAccessCheckNeeded()) {
4521 Handle<GlobalObject> global(info()->global_object()); 4851 Handle<GlobalObject> global(info()->global_object());
(...skipping 19 matching lines...) Expand all
4541 AddInstruction(global_receiver); 4871 AddInstruction(global_receiver);
4542 ASSERT(environment()->ExpressionStackAt(receiver_index)-> 4872 ASSERT(environment()->ExpressionStackAt(receiver_index)->
4543 IsGlobalObject()); 4873 IsGlobalObject());
4544 environment()->SetExpressionStackAt(receiver_index, global_receiver); 4874 environment()->SetExpressionStackAt(receiver_index, global_receiver);
4545 4875
4546 if (TryInline(expr)) return; 4876 if (TryInline(expr)) return;
4547 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), 4877 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(),
4548 argument_count)); 4878 argument_count));
4549 } else { 4879 } else {
4550 HValue* context = environment()->LookupContext(); 4880 HValue* context = environment()->LookupContext();
4551 PushAndAdd(new(zone()) HGlobalObject(context)); 4881 HGlobalObject* receiver = new(zone()) HGlobalObject(context);
4552 CHECK_ALIVE(VisitExpressions(expr->arguments())); 4882 AddInstruction(receiver);
4883 PushAndAdd(new(zone()) HPushArgument(receiver));
4884 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
4553 4885
4554 call = PreProcessCall(new(zone()) HCallGlobal(context, 4886 call = new(zone()) HCallGlobal(context, var->name(), argument_count);
4555 var->name(), 4887 Drop(argument_count);
4556 argument_count));
4557 } 4888 }
4558 4889
4559 } else { 4890 } else {
4891 CHECK_ALIVE(VisitArgument(expr->expression()));
4560 HValue* context = environment()->LookupContext(); 4892 HValue* context = environment()->LookupContext();
4561 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 4893 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
4894 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global_object);
4562 AddInstruction(global_object); 4895 AddInstruction(global_object);
4563 PushAndAdd(new(zone()) HGlobalReceiver(global_object)); 4896 AddInstruction(receiver);
4564 CHECK_ALIVE(VisitExpressions(expr->arguments())); 4897 PushAndAdd(new(zone()) HPushArgument(receiver));
4898 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
4565 4899
4566 call = PreProcessCall(new(zone()) HCallFunction(context, argument_count)); 4900 // The function to call is treated as an argument to the call function
4901 // stub.
4902 call = new(zone()) HCallFunction(context, argument_count + 1);
4903 Drop(argument_count + 1);
4567 } 4904 }
4568 } 4905 }
4569 4906
4570 call->set_position(expr->position()); 4907 call->set_position(expr->position());
4571 ast_context()->ReturnInstruction(call, expr->id()); 4908 return ast_context()->ReturnInstruction(call, expr->id());
4572 } 4909 }
4573 4910
4574 4911
4575 void HGraphBuilder::VisitCallNew(CallNew* expr) { 4912 void HGraphBuilder::VisitCallNew(CallNew* expr) {
4576 ASSERT(!HasStackOverflow()); 4913 ASSERT(!HasStackOverflow());
4577 ASSERT(current_block() != NULL); 4914 ASSERT(current_block() != NULL);
4578 ASSERT(current_block()->HasPredecessor()); 4915 ASSERT(current_block()->HasPredecessor());
4579 // The constructor function is also used as the receiver argument to the 4916 // The constructor function is also used as the receiver argument to the
4580 // JS construct call builtin. 4917 // JS construct call builtin.
4581 CHECK_ALIVE(VisitForValue(expr->expression())); 4918 HValue* constructor = NULL;
4582 CHECK_ALIVE(VisitExpressions(expr->arguments())); 4919 CHECK_ALIVE(constructor = VisitArgument(expr->expression()));
4920 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
4583 4921
4584 HValue* context = environment()->LookupContext(); 4922 HValue* context = environment()->LookupContext();
4585 4923
4586 // The constructor is both an operand to the instruction and an argument 4924 // The constructor is both an operand to the instruction and an argument
4587 // to the construct call. 4925 // to the construct call.
4588 int arg_count = expr->arguments()->length() + 1; // Plus constructor. 4926 int arg_count = expr->arguments()->length() + 1; // Plus constructor.
4589 HValue* constructor = environment()->ExpressionStackAt(arg_count - 1);
4590 HCallNew* call = new(zone()) HCallNew(context, constructor, arg_count); 4927 HCallNew* call = new(zone()) HCallNew(context, constructor, arg_count);
4591 call->set_position(expr->position()); 4928 call->set_position(expr->position());
4592 PreProcessCall(call); 4929 Drop(arg_count);
4593 ast_context()->ReturnInstruction(call, expr->id()); 4930 return ast_context()->ReturnInstruction(call, expr->id());
4594 } 4931 }
4595 4932
4596 4933
4597 // Support for generating inlined runtime functions. 4934 // Support for generating inlined runtime functions.
4598 4935
4599 // Lookup table for generators for runtime calls that are generated inline. 4936 // Lookup table for generators for runtime calls that are generated inline.
4600 // Elements of the table are member pointers to functions of HGraphBuilder. 4937 // Elements of the table are member pointers to functions of HGraphBuilder.
4601 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ 4938 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
4602 &HGraphBuilder::Generate##Name, 4939 &HGraphBuilder::Generate##Name,
4603 4940
(...skipping 25 matching lines...) Expand all
4629 ASSERT(static_cast<size_t>(lookup_index) < 4966 ASSERT(static_cast<size_t>(lookup_index) <
4630 ARRAY_SIZE(kInlineFunctionGenerators)); 4967 ARRAY_SIZE(kInlineFunctionGenerators));
4631 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; 4968 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
4632 4969
4633 // Call the inline code generator using the pointer-to-member. 4970 // Call the inline code generator using the pointer-to-member.
4634 (this->*generator)(expr); 4971 (this->*generator)(expr);
4635 } else { 4972 } else {
4636 ASSERT(function->intrinsic_type == Runtime::RUNTIME); 4973 ASSERT(function->intrinsic_type == Runtime::RUNTIME);
4637 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 4974 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
4638 4975
4976 HValue* context = environment()->LookupContext();
4639 Handle<String> name = expr->name(); 4977 Handle<String> name = expr->name();
4640 int argument_count = expr->arguments()->length(); 4978 int argument_count = expr->arguments()->length();
4641 HCallRuntime* call = 4979 HCallRuntime* call =
4642 new(zone()) HCallRuntime(name, function, argument_count); 4980 new(zone()) HCallRuntime(context, name, function, argument_count);
4643 call->set_position(RelocInfo::kNoPosition); 4981 call->set_position(RelocInfo::kNoPosition);
4644 Drop(argument_count); 4982 Drop(argument_count);
4645 ast_context()->ReturnInstruction(call, expr->id()); 4983 return ast_context()->ReturnInstruction(call, expr->id());
4646 } 4984 }
4647 } 4985 }
4648 4986
4649 4987
4650 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { 4988 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
4651 ASSERT(!HasStackOverflow()); 4989 ASSERT(!HasStackOverflow());
4652 ASSERT(current_block() != NULL); 4990 ASSERT(current_block() != NULL);
4653 ASSERT(current_block()->HasPredecessor()); 4991 ASSERT(current_block()->HasPredecessor());
4654 switch (expr->op()) { 4992 switch (expr->op()) {
4655 case Token::DELETE: return VisitDelete(expr); 4993 case Token::DELETE: return VisitDelete(expr);
4656 case Token::VOID: return VisitVoid(expr); 4994 case Token::VOID: return VisitVoid(expr);
4657 case Token::TYPEOF: return VisitTypeof(expr); 4995 case Token::TYPEOF: return VisitTypeof(expr);
4658 case Token::ADD: return VisitAdd(expr); 4996 case Token::ADD: return VisitAdd(expr);
4659 case Token::SUB: return VisitSub(expr); 4997 case Token::SUB: return VisitSub(expr);
4660 case Token::BIT_NOT: return VisitBitNot(expr); 4998 case Token::BIT_NOT: return VisitBitNot(expr);
4661 case Token::NOT: return VisitNot(expr); 4999 case Token::NOT: return VisitNot(expr);
4662 default: UNREACHABLE(); 5000 default: UNREACHABLE();
4663 } 5001 }
4664 } 5002 }
4665 5003
4666 void HGraphBuilder::VisitDelete(UnaryOperation* expr) { 5004 void HGraphBuilder::VisitDelete(UnaryOperation* expr) {
4667 Property* prop = expr->expression()->AsProperty(); 5005 Property* prop = expr->expression()->AsProperty();
4668 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 5006 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
4669 if (prop == NULL && var == NULL) { 5007 if (prop == NULL && var == NULL) {
4670 // Result of deleting non-property, non-variable reference is true. 5008 // Result of deleting non-property, non-variable reference is true.
4671 // Evaluate the subexpression for side effects. 5009 // Evaluate the subexpression for side effects.
4672 CHECK_ALIVE(VisitForEffect(expr->expression())); 5010 CHECK_ALIVE(VisitForEffect(expr->expression()));
4673 ast_context()->ReturnValue(graph()->GetConstantTrue()); 5011 return ast_context()->ReturnValue(graph()->GetConstantTrue());
4674 } else if (var != NULL && 5012 } else if (var != NULL &&
4675 !var->is_global() && 5013 !var->is_global() &&
4676 var->AsSlot() != NULL && 5014 var->AsSlot() != NULL &&
4677 var->AsSlot()->type() != Slot::LOOKUP) { 5015 var->AsSlot()->type() != Slot::LOOKUP) {
4678 // Result of deleting non-global, non-dynamic variables is false. 5016 // Result of deleting non-global, non-dynamic variables is false.
4679 // The subexpression does not have side effects. 5017 // The subexpression does not have side effects.
4680 ast_context()->ReturnValue(graph()->GetConstantFalse()); 5018 return ast_context()->ReturnValue(graph()->GetConstantFalse());
4681 } else if (prop != NULL) { 5019 } else if (prop != NULL) {
4682 if (prop->is_synthetic()) { 5020 if (prop->is_synthetic()) {
4683 // Result of deleting parameters is false, even when they rewrite 5021 // Result of deleting parameters is false, even when they rewrite
4684 // to accesses on the arguments object. 5022 // to accesses on the arguments object.
4685 ast_context()->ReturnValue(graph()->GetConstantFalse()); 5023 return ast_context()->ReturnValue(graph()->GetConstantFalse());
4686 } else { 5024 } else {
4687 CHECK_ALIVE(VisitForValue(prop->obj())); 5025 CHECK_ALIVE(VisitForValue(prop->obj()));
4688 CHECK_ALIVE(VisitForValue(prop->key())); 5026 CHECK_ALIVE(VisitForValue(prop->key()));
4689 HValue* key = Pop(); 5027 HValue* key = Pop();
4690 HValue* obj = Pop(); 5028 HValue* obj = Pop();
4691 HDeleteProperty* instr = new(zone()) HDeleteProperty(obj, key); 5029 HValue* context = environment()->LookupContext();
4692 ast_context()->ReturnInstruction(instr, expr->id()); 5030 HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key);
5031 return ast_context()->ReturnInstruction(instr, expr->id());
4693 } 5032 }
4694 } else if (var->is_global()) { 5033 } else if (var->is_global()) {
4695 Bailout("delete with global variable"); 5034 Bailout("delete with global variable");
4696 } else { 5035 } else {
4697 Bailout("delete with non-global variable"); 5036 Bailout("delete with non-global variable");
4698 } 5037 }
4699 } 5038 }
4700 5039
4701 5040
4702 void HGraphBuilder::VisitVoid(UnaryOperation* expr) { 5041 void HGraphBuilder::VisitVoid(UnaryOperation* expr) {
4703 CHECK_ALIVE(VisitForEffect(expr->expression())); 5042 CHECK_ALIVE(VisitForEffect(expr->expression()));
4704 ast_context()->ReturnValue(graph()->GetConstantUndefined()); 5043 return ast_context()->ReturnValue(graph()->GetConstantUndefined());
4705 } 5044 }
4706 5045
4707 5046
4708 void HGraphBuilder::VisitTypeof(UnaryOperation* expr) { 5047 void HGraphBuilder::VisitTypeof(UnaryOperation* expr) {
4709 CHECK_ALIVE(VisitForTypeOf(expr->expression())); 5048 CHECK_ALIVE(VisitForTypeOf(expr->expression()));
4710 HValue* value = Pop(); 5049 HValue* value = Pop();
4711 ast_context()->ReturnInstruction(new(zone()) HTypeof(value), expr->id()); 5050 HValue* context = environment()->LookupContext();
5051 HInstruction* instr = new(zone()) HTypeof(context, value);
5052 return ast_context()->ReturnInstruction(instr, expr->id());
4712 } 5053 }
4713 5054
4714 5055
4715 void HGraphBuilder::VisitAdd(UnaryOperation* expr) { 5056 void HGraphBuilder::VisitAdd(UnaryOperation* expr) {
4716 CHECK_ALIVE(VisitForValue(expr->expression())); 5057 CHECK_ALIVE(VisitForValue(expr->expression()));
4717 HValue* value = Pop(); 5058 HValue* value = Pop();
4718 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstant1()); 5059 HValue* context = environment()->LookupContext();
4719 ast_context()->ReturnInstruction(instr, expr->id()); 5060 HInstruction* instr =
5061 new(zone()) HMul(context, value, graph_->GetConstant1());
5062 return ast_context()->ReturnInstruction(instr, expr->id());
4720 } 5063 }
4721 5064
4722 5065
4723 void HGraphBuilder::VisitSub(UnaryOperation* expr) { 5066 void HGraphBuilder::VisitSub(UnaryOperation* expr) {
4724 CHECK_ALIVE(VisitForValue(expr->expression())); 5067 CHECK_ALIVE(VisitForValue(expr->expression()));
4725 HValue* value = Pop(); 5068 HValue* value = Pop();
4726 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstantMinus1()); 5069 HValue* context = environment()->LookupContext();
5070 HInstruction* instr =
5071 new(zone()) HMul(context, value, graph_->GetConstantMinus1());
4727 TypeInfo info = oracle()->UnaryType(expr); 5072 TypeInfo info = oracle()->UnaryType(expr);
5073 if (info.IsUninitialized()) {
5074 AddInstruction(new(zone()) HSoftDeoptimize);
5075 current_block()->MarkAsDeoptimizing();
5076 info = TypeInfo::Unknown();
5077 }
4728 Representation rep = ToRepresentation(info); 5078 Representation rep = ToRepresentation(info);
4729 TraceRepresentation(expr->op(), info, instr, rep); 5079 TraceRepresentation(expr->op(), info, instr, rep);
4730 instr->AssumeRepresentation(rep); 5080 instr->AssumeRepresentation(rep);
4731 ast_context()->ReturnInstruction(instr, expr->id()); 5081 return ast_context()->ReturnInstruction(instr, expr->id());
4732 } 5082 }
4733 5083
4734 5084
4735 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) { 5085 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) {
4736 CHECK_ALIVE(VisitForValue(expr->expression())); 5086 CHECK_ALIVE(VisitForValue(expr->expression()));
4737 HValue* value = Pop(); 5087 HValue* value = Pop();
5088 TypeInfo info = oracle()->UnaryType(expr);
5089 if (info.IsUninitialized()) {
5090 AddInstruction(new(zone()) HSoftDeoptimize);
5091 current_block()->MarkAsDeoptimizing();
5092 }
4738 HInstruction* instr = new(zone()) HBitNot(value); 5093 HInstruction* instr = new(zone()) HBitNot(value);
4739 ast_context()->ReturnInstruction(instr, expr->id()); 5094 return ast_context()->ReturnInstruction(instr, expr->id());
4740 } 5095 }
4741 5096
4742 5097
4743 void HGraphBuilder::VisitNot(UnaryOperation* expr) { 5098 void HGraphBuilder::VisitNot(UnaryOperation* expr) {
4744 // TODO(svenpanne) Perhaps a switch/virtual function is nicer here. 5099 // TODO(svenpanne) Perhaps a switch/virtual function is nicer here.
4745 if (ast_context()->IsTest()) { 5100 if (ast_context()->IsTest()) {
4746 TestContext* context = TestContext::cast(ast_context()); 5101 TestContext* context = TestContext::cast(ast_context());
4747 VisitForControl(expr->expression(), 5102 VisitForControl(expr->expression(),
4748 context->if_false(), 5103 context->if_false(),
4749 context->if_true()); 5104 context->if_true());
(...skipping 24 matching lines...) Expand all
4774 materialize_true->SetJoinId(expr->expression()->id()); 5129 materialize_true->SetJoinId(expr->expression()->id());
4775 set_current_block(materialize_true); 5130 set_current_block(materialize_true);
4776 Push(graph()->GetConstantTrue()); 5131 Push(graph()->GetConstantTrue());
4777 } else { 5132 } else {
4778 materialize_true = NULL; 5133 materialize_true = NULL;
4779 } 5134 }
4780 5135
4781 HBasicBlock* join = 5136 HBasicBlock* join =
4782 CreateJoin(materialize_false, materialize_true, expr->id()); 5137 CreateJoin(materialize_false, materialize_true, expr->id());
4783 set_current_block(join); 5138 set_current_block(join);
4784 if (join != NULL) ast_context()->ReturnValue(Pop()); 5139 if (join != NULL) return ast_context()->ReturnValue(Pop());
4785 } 5140 }
4786 5141
4787 5142
4788 HInstruction* HGraphBuilder::BuildIncrement(bool returns_original_input, 5143 HInstruction* HGraphBuilder::BuildIncrement(bool returns_original_input,
4789 CountOperation* expr) { 5144 CountOperation* expr) {
4790 // The input to the count operation is on top of the expression stack. 5145 // The input to the count operation is on top of the expression stack.
4791 TypeInfo info = oracle()->IncrementType(expr); 5146 TypeInfo info = oracle()->IncrementType(expr);
4792 Representation rep = ToRepresentation(info); 5147 Representation rep = ToRepresentation(info);
4793 if (rep.IsTagged()) { 5148 if (rep.IsTagged()) {
4794 rep = Representation::Integer32(); 5149 rep = Representation::Integer32();
4795 } 5150 }
4796 5151
4797 if (returns_original_input) { 5152 if (returns_original_input) {
4798 // We need an explicit HValue representing ToNumber(input). The 5153 // We need an explicit HValue representing ToNumber(input). The
4799 // actual HChange instruction we need is (sometimes) added in a later 5154 // actual HChange instruction we need is (sometimes) added in a later
4800 // phase, so it is not available now to be used as an input to HAdd and 5155 // phase, so it is not available now to be used as an input to HAdd and
4801 // as the return value. 5156 // as the return value.
4802 HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep); 5157 HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep);
4803 AddInstruction(number_input); 5158 AddInstruction(number_input);
4804 Push(number_input); 5159 Push(number_input);
4805 } 5160 }
4806 5161
4807 // The addition has no side effects, so we do not need 5162 // The addition has no side effects, so we do not need
4808 // to simulate the expression stack after this instruction. 5163 // to simulate the expression stack after this instruction.
4809 // Any later failures deopt to the load of the input or earlier. 5164 // Any later failures deopt to the load of the input or earlier.
4810 HConstant* delta = (expr->op() == Token::INC) 5165 HConstant* delta = (expr->op() == Token::INC)
4811 ? graph_->GetConstant1() 5166 ? graph_->GetConstant1()
4812 : graph_->GetConstantMinus1(); 5167 : graph_->GetConstantMinus1();
4813 HInstruction* instr = new(zone()) HAdd(Top(), delta); 5168 HValue* context = environment()->LookupContext();
5169 HInstruction* instr = new(zone()) HAdd(context, Top(), delta);
4814 TraceRepresentation(expr->op(), info, instr, rep); 5170 TraceRepresentation(expr->op(), info, instr, rep);
4815 instr->AssumeRepresentation(rep); 5171 instr->AssumeRepresentation(rep);
4816 AddInstruction(instr); 5172 AddInstruction(instr);
4817 return instr; 5173 return instr;
4818 } 5174 }
4819 5175
4820 5176
4821 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { 5177 void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
4822 ASSERT(!HasStackOverflow()); 5178 ASSERT(!HasStackOverflow());
4823 ASSERT(current_block() != NULL); 5179 ASSERT(current_block() != NULL);
4824 ASSERT(current_block()->HasPredecessor()); 5180 ASSERT(current_block()->HasPredecessor());
4825 Expression* target = expr->expression(); 5181 Expression* target = expr->expression();
4826 VariableProxy* proxy = target->AsVariableProxy(); 5182 VariableProxy* proxy = target->AsVariableProxy();
4827 Variable* var = proxy->AsVariable(); 5183 Variable* var = proxy->AsVariable();
4828 Property* prop = target->AsProperty(); 5184 Property* prop = target->AsProperty();
4829 if (var == NULL && prop == NULL) { 5185 if (var == NULL && prop == NULL) {
4830 return Bailout("invalid lhs in count operation"); 5186 return Bailout("invalid lhs in count operation");
4831 } 5187 }
4832 5188
4833 // Match the full code generator stack by simulating an extra stack 5189 // Match the full code generator stack by simulating an extra stack
4834 // element for postfix operations in a non-effect context. The return 5190 // element for postfix operations in a non-effect context. The return
4835 // value is ToNumber(input). 5191 // value is ToNumber(input).
4836 bool returns_original_input = 5192 bool returns_original_input =
4837 expr->is_postfix() && !ast_context()->IsEffect(); 5193 expr->is_postfix() && !ast_context()->IsEffect();
4838 HValue* input = NULL; // ToNumber(original_input). 5194 HValue* input = NULL; // ToNumber(original_input).
4839 HValue* after = NULL; // The result after incrementing or decrementing. 5195 HValue* after = NULL; // The result after incrementing or decrementing.
4840 5196
4841 if (var != NULL) { 5197 if (var != NULL) {
5198 if (var->mode() == Variable::CONST) {
5199 return Bailout("unsupported count operation with const");
5200 }
4842 // Argument of the count operation is a variable, not a property. 5201 // Argument of the count operation is a variable, not a property.
4843 ASSERT(prop == NULL); 5202 ASSERT(prop == NULL);
4844 CHECK_ALIVE(VisitForValue(target)); 5203 CHECK_ALIVE(VisitForValue(target));
4845 5204
4846 after = BuildIncrement(returns_original_input, expr); 5205 after = BuildIncrement(returns_original_input, expr);
4847 input = returns_original_input ? Top() : Pop(); 5206 input = returns_original_input ? Top() : Pop();
4848 Push(after); 5207 Push(after);
4849 5208
4850 if (var->is_global()) { 5209 if (var->is_global()) {
4851 HandleGlobalVariableAssignment(var, 5210 HandleGlobalVariableAssignment(var,
4852 after, 5211 after,
4853 expr->position(), 5212 expr->position(),
4854 expr->AssignmentId()); 5213 expr->AssignmentId());
4855 } else if (var->IsStackAllocated()) { 5214 } else if (var->IsStackAllocated()) {
4856 Bind(var, after); 5215 Bind(var, after);
4857 } else if (var->IsContextSlot()) { 5216 } else if (var->IsContextSlot()) {
5217 // Bail out if we try to mutate a parameter value in a function using
5218 // the arguments object. We do not (yet) correctly handle the
5219 // arguments property of the function.
5220 if (info()->scope()->arguments() != NULL) {
5221 // Parameters will rewrite to context slots. We have no direct way
5222 // to detect that the variable is a parameter.
5223 int count = info()->scope()->num_parameters();
5224 for (int i = 0; i < count; ++i) {
5225 if (var == info()->scope()->parameter(i)) {
5226 Bailout("assignment to parameter, function uses arguments object");
5227 }
5228 }
5229 }
5230
4858 HValue* context = BuildContextChainWalk(var); 5231 HValue* context = BuildContextChainWalk(var);
4859 int index = var->AsSlot()->index(); 5232 int index = var->AsSlot()->index();
4860 HStoreContextSlot* instr = 5233 HStoreContextSlot* instr =
4861 new(zone()) HStoreContextSlot(context, index, after); 5234 new(zone()) HStoreContextSlot(context, index, after);
4862 AddInstruction(instr); 5235 AddInstruction(instr);
4863 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); 5236 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
4864 } else { 5237 } else {
4865 return Bailout("lookup variable in count operation"); 5238 return Bailout("lookup variable in count operation");
4866 } 5239 }
4867 5240
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
4903 5276
4904 } else { 5277 } else {
4905 // Keyed property. 5278 // Keyed property.
4906 if (returns_original_input) Push(graph_->GetConstantUndefined()); 5279 if (returns_original_input) Push(graph_->GetConstantUndefined());
4907 5280
4908 CHECK_ALIVE(VisitForValue(prop->obj())); 5281 CHECK_ALIVE(VisitForValue(prop->obj()));
4909 CHECK_ALIVE(VisitForValue(prop->key())); 5282 CHECK_ALIVE(VisitForValue(prop->key()));
4910 HValue* obj = environment()->ExpressionStackAt(1); 5283 HValue* obj = environment()->ExpressionStackAt(1);
4911 HValue* key = environment()->ExpressionStackAt(0); 5284 HValue* key = environment()->ExpressionStackAt(0);
4912 5285
4913 HInstruction* load = BuildLoadKeyed(obj, key, prop); 5286 bool has_side_effects = false;
4914 PushAndAdd(load); 5287 HValue* load = HandleKeyedElementAccess(
4915 if (load->HasSideEffects()) AddSimulate(expr->CountId()); 5288 obj, key, NULL, prop, expr->CountId(), RelocInfo::kNoPosition,
5289 false, // is_store
5290 &has_side_effects);
5291 Push(load);
5292 if (has_side_effects) AddSimulate(expr->CountId());
4916 5293
4917 after = BuildIncrement(returns_original_input, expr); 5294 after = BuildIncrement(returns_original_input, expr);
4918 input = Pop(); 5295 input = Pop();
4919 5296
4920 expr->RecordTypeFeedback(oracle()); 5297 expr->RecordTypeFeedback(oracle());
4921 HInstruction* store = BuildStoreKeyed(obj, key, after, expr); 5298 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(),
4922 AddInstruction(store); 5299 RelocInfo::kNoPosition,
5300 true, // is_store
5301 &has_side_effects);
4923 5302
4924 // Drop the key from the bailout environment. Overwrite the receiver 5303 // Drop the key from the bailout environment. Overwrite the receiver
4925 // with the result of the operation, and the placeholder with the 5304 // with the result of the operation, and the placeholder with the
4926 // original value if necessary. 5305 // original value if necessary.
4927 Drop(1); 5306 Drop(1);
4928 environment()->SetExpressionStackAt(0, after); 5307 environment()->SetExpressionStackAt(0, after);
4929 if (returns_original_input) environment()->SetExpressionStackAt(1, input); 5308 if (returns_original_input) environment()->SetExpressionStackAt(1, input);
4930 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 5309 ASSERT(has_side_effects); // Stores always have side effects.
5310 AddSimulate(expr->AssignmentId());
4931 } 5311 }
4932 } 5312 }
4933 5313
4934 Drop(returns_original_input ? 2 : 1); 5314 Drop(returns_original_input ? 2 : 1);
4935 ast_context()->ReturnValue(expr->is_postfix() ? input : after); 5315 return ast_context()->ReturnValue(expr->is_postfix() ? input : after);
4936 } 5316 }
4937 5317
4938 5318
4939 HCompareSymbolEq* HGraphBuilder::BuildSymbolCompare(HValue* left, 5319 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* context,
4940 HValue* right, 5320 HValue* string,
4941 Token::Value op) {
4942 ASSERT(op == Token::EQ || op == Token::EQ_STRICT);
4943 AddInstruction(new(zone()) HCheckNonSmi(left));
4944 AddInstruction(HCheckInstanceType::NewIsSymbol(left));
4945 AddInstruction(new(zone()) HCheckNonSmi(right));
4946 AddInstruction(HCheckInstanceType::NewIsSymbol(right));
4947 return new(zone()) HCompareSymbolEq(left, right, op);
4948 }
4949
4950
4951 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* string,
4952 HValue* index) { 5321 HValue* index) {
4953 AddInstruction(new(zone()) HCheckNonSmi(string)); 5322 AddInstruction(new(zone()) HCheckNonSmi(string));
4954 AddInstruction(HCheckInstanceType::NewIsString(string)); 5323 AddInstruction(HCheckInstanceType::NewIsString(string));
4955 HStringLength* length = new(zone()) HStringLength(string); 5324 HStringLength* length = new(zone()) HStringLength(string);
4956 AddInstruction(length); 5325 AddInstruction(length);
4957 AddInstruction(new(zone()) HBoundsCheck(index, length)); 5326 HInstruction* checked_index =
4958 return new(zone()) HStringCharCodeAt(string, index); 5327 AddInstruction(new(zone()) HBoundsCheck(index, length));
5328 return new(zone()) HStringCharCodeAt(context, string, checked_index);
4959 } 5329 }
4960 5330
4961 5331
4962 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, 5332 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
4963 HValue* left, 5333 HValue* left,
4964 HValue* right) { 5334 HValue* right) {
5335 HValue* context = environment()->LookupContext();
4965 TypeInfo info = oracle()->BinaryType(expr); 5336 TypeInfo info = oracle()->BinaryType(expr);
4966 HInstruction* instr = BuildBinaryOperation(expr->op(), left, right, info); 5337 if (info.IsUninitialized()) {
5338 AddInstruction(new(zone()) HSoftDeoptimize);
5339 current_block()->MarkAsDeoptimizing();
5340 info = TypeInfo::Unknown();
5341 }
5342 HInstruction* instr = NULL;
5343 switch (expr->op()) {
5344 case Token::ADD:
5345 if (info.IsString()) {
5346 AddInstruction(new(zone()) HCheckNonSmi(left));
5347 AddInstruction(HCheckInstanceType::NewIsString(left));
5348 AddInstruction(new(zone()) HCheckNonSmi(right));
5349 AddInstruction(HCheckInstanceType::NewIsString(right));
5350 instr = new(zone()) HStringAdd(context, left, right);
5351 } else {
5352 instr = new(zone()) HAdd(context, left, right);
5353 }
5354 break;
5355 case Token::SUB:
5356 instr = new(zone()) HSub(context, left, right);
5357 break;
5358 case Token::MUL:
5359 instr = new(zone()) HMul(context, left, right);
5360 break;
5361 case Token::MOD:
5362 instr = new(zone()) HMod(context, left, right);
5363 break;
5364 case Token::DIV:
5365 instr = new(zone()) HDiv(context, left, right);
5366 break;
5367 case Token::BIT_XOR:
5368 instr = new(zone()) HBitXor(context, left, right);
5369 break;
5370 case Token::BIT_AND:
5371 instr = new(zone()) HBitAnd(context, left, right);
5372 break;
5373 case Token::BIT_OR:
5374 instr = new(zone()) HBitOr(context, left, right);
5375 break;
5376 case Token::SAR:
5377 instr = new(zone()) HSar(context, left, right);
5378 break;
5379 case Token::SHR:
5380 instr = new(zone()) HShr(context, left, right);
5381 break;
5382 case Token::SHL:
5383 instr = new(zone()) HShl(context, left, right);
5384 break;
5385 default:
5386 UNREACHABLE();
5387 }
5388
4967 // If we hit an uninitialized binary op stub we will get type info 5389 // If we hit an uninitialized binary op stub we will get type info
4968 // for a smi operation. If one of the operands is a constant string 5390 // for a smi operation. If one of the operands is a constant string
4969 // do not generate code assuming it is a smi operation. 5391 // do not generate code assuming it is a smi operation.
4970 if (info.IsSmi() && 5392 if (info.IsSmi() &&
4971 ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) || 5393 ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) ||
4972 (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) { 5394 (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) {
4973 return instr; 5395 return instr;
4974 } 5396 }
4975 Representation rep = ToRepresentation(info); 5397 Representation rep = ToRepresentation(info);
4976 // We only generate either int32 or generic tagged bitwise operations. 5398 // We only generate either int32 or generic tagged bitwise operations.
4977 if (instr->IsBitwiseBinaryOperation() && rep.IsDouble()) { 5399 if (instr->IsBitwiseBinaryOperation() && rep.IsDouble()) {
4978 rep = Representation::Integer32(); 5400 rep = Representation::Integer32();
4979 } 5401 }
4980 TraceRepresentation(expr->op(), info, instr, rep); 5402 TraceRepresentation(expr->op(), info, instr, rep);
4981 instr->AssumeRepresentation(rep); 5403 instr->AssumeRepresentation(rep);
4982 return instr; 5404 return instr;
4983 } 5405 }
4984 5406
4985 5407
4986 HInstruction* HGraphBuilder::BuildBinaryOperation(
4987 Token::Value op, HValue* left, HValue* right, TypeInfo info) {
4988 switch (op) {
4989 case Token::ADD:
4990 if (info.IsString()) {
4991 AddInstruction(new(zone()) HCheckNonSmi(left));
4992 AddInstruction(HCheckInstanceType::NewIsString(left));
4993 AddInstruction(new(zone()) HCheckNonSmi(right));
4994 AddInstruction(HCheckInstanceType::NewIsString(right));
4995 return new(zone()) HStringAdd(left, right);
4996 } else {
4997 return new(zone()) HAdd(left, right);
4998 }
4999 case Token::SUB: return new(zone()) HSub(left, right);
5000 case Token::MUL: return new(zone()) HMul(left, right);
5001 case Token::MOD: return new(zone()) HMod(left, right);
5002 case Token::DIV: return new(zone()) HDiv(left, right);
5003 case Token::BIT_XOR: return new(zone()) HBitXor(left, right);
5004 case Token::BIT_AND: return new(zone()) HBitAnd(left, right);
5005 case Token::BIT_OR: return new(zone()) HBitOr(left, right);
5006 case Token::SAR: return new(zone()) HSar(left, right);
5007 case Token::SHR: return new(zone()) HShr(left, right);
5008 case Token::SHL: return new(zone()) HShl(left, right);
5009 default:
5010 UNREACHABLE();
5011 return NULL;
5012 }
5013 }
5014
5015
5016 // Check for the form (%_ClassOf(foo) === 'BarClass'). 5408 // Check for the form (%_ClassOf(foo) === 'BarClass').
5017 static bool IsClassOfTest(CompareOperation* expr) { 5409 static bool IsClassOfTest(CompareOperation* expr) {
5018 if (expr->op() != Token::EQ_STRICT) return false; 5410 if (expr->op() != Token::EQ_STRICT) return false;
5019 CallRuntime* call = expr->left()->AsCallRuntime(); 5411 CallRuntime* call = expr->left()->AsCallRuntime();
5020 if (call == NULL) return false; 5412 if (call == NULL) return false;
5021 Literal* literal = expr->right()->AsLiteral(); 5413 Literal* literal = expr->right()->AsLiteral();
5022 if (literal == NULL) return false; 5414 if (literal == NULL) return false;
5023 if (!literal->handle()->IsString()) return false; 5415 if (!literal->handle()->IsString()) return false;
5024 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; 5416 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false;
5025 ASSERT(call->arguments()->length() == 1); 5417 ASSERT(call->arguments()->length() == 1);
5026 return true; 5418 return true;
5027 } 5419 }
5028 5420
5029 5421
5030 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { 5422 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
5031 ASSERT(!HasStackOverflow()); 5423 ASSERT(!HasStackOverflow());
5032 ASSERT(current_block() != NULL); 5424 ASSERT(current_block() != NULL);
5033 ASSERT(current_block()->HasPredecessor()); 5425 ASSERT(current_block()->HasPredecessor());
5034 switch (expr->op()) { 5426 switch (expr->op()) {
5035 case Token::COMMA: return VisitComma(expr); 5427 case Token::COMMA:
5036 case Token::OR: return VisitAndOr(expr, false); 5428 return VisitComma(expr);
5037 case Token::AND: return VisitAndOr(expr, true); 5429 case Token::OR:
5038 default: return VisitCommon(expr); 5430 case Token::AND:
5431 return VisitLogicalExpression(expr);
5432 default:
5433 return VisitArithmeticExpression(expr);
5039 } 5434 }
5040 } 5435 }
5041 5436
5042 5437
5043 void HGraphBuilder::VisitComma(BinaryOperation* expr) { 5438 void HGraphBuilder::VisitComma(BinaryOperation* expr) {
5044 CHECK_ALIVE(VisitForEffect(expr->left())); 5439 CHECK_ALIVE(VisitForEffect(expr->left()));
5045 // Visit the right subexpression in the same AST context as the entire 5440 // Visit the right subexpression in the same AST context as the entire
5046 // expression. 5441 // expression.
5047 Visit(expr->right()); 5442 Visit(expr->right());
5048 } 5443 }
5049 5444
5050 5445
5051 void HGraphBuilder::VisitAndOr(BinaryOperation* expr, bool is_logical_and) { 5446 void HGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
5447 bool is_logical_and = expr->op() == Token::AND;
5052 if (ast_context()->IsTest()) { 5448 if (ast_context()->IsTest()) {
5053 TestContext* context = TestContext::cast(ast_context()); 5449 TestContext* context = TestContext::cast(ast_context());
5054 // Translate left subexpression. 5450 // Translate left subexpression.
5055 HBasicBlock* eval_right = graph()->CreateBasicBlock(); 5451 HBasicBlock* eval_right = graph()->CreateBasicBlock();
5056 if (is_logical_and) { 5452 if (is_logical_and) {
5057 CHECK_BAILOUT(VisitForControl(expr->left(), 5453 CHECK_BAILOUT(VisitForControl(expr->left(),
5058 eval_right, 5454 eval_right,
5059 context->if_false())); 5455 context->if_false()));
5060 } else { 5456 } else {
5061 CHECK_BAILOUT(VisitForControl(expr->left(), 5457 CHECK_BAILOUT(VisitForControl(expr->left(),
5062 context->if_true(), 5458 context->if_true(),
5063 eval_right)); 5459 eval_right));
5064 } 5460 }
5065 5461
5066 // Translate right subexpression by visiting it in the same AST 5462 // Translate right subexpression by visiting it in the same AST
5067 // context as the entire expression. 5463 // context as the entire expression.
5068 if (eval_right->HasPredecessor()) { 5464 if (eval_right->HasPredecessor()) {
5069 eval_right->SetJoinId(expr->RightId()); 5465 eval_right->SetJoinId(expr->RightId());
5070 set_current_block(eval_right); 5466 set_current_block(eval_right);
5071 Visit(expr->right()); 5467 Visit(expr->right());
5072 } 5468 }
5073 5469
5074 } else if (ast_context()->IsValue()) { 5470 } else if (ast_context()->IsValue()) {
5075 CHECK_ALIVE(VisitForValue(expr->left())); 5471 CHECK_ALIVE(VisitForValue(expr->left()));
5076 ASSERT(current_block() != NULL); 5472 ASSERT(current_block() != NULL);
5077 5473
5078 // We need an extra block to maintain edge-split form. 5474 // We need an extra block to maintain edge-split form.
5079 HBasicBlock* empty_block = graph()->CreateBasicBlock(); 5475 HBasicBlock* empty_block = graph()->CreateBasicBlock();
5080 HBasicBlock* eval_right = graph()->CreateBasicBlock(); 5476 HBasicBlock* eval_right = graph()->CreateBasicBlock();
5081 HTest* test = is_logical_and 5477 HBranch* test = is_logical_and
5082 ? new(zone()) HTest(Top(), eval_right, empty_block) 5478 ? new(zone()) HBranch(Top(), eval_right, empty_block)
5083 : new(zone()) HTest(Top(), empty_block, eval_right); 5479 : new(zone()) HBranch(Top(), empty_block, eval_right);
5084 current_block()->Finish(test); 5480 current_block()->Finish(test);
5085 5481
5086 set_current_block(eval_right); 5482 set_current_block(eval_right);
5087 Drop(1); // Value of the left subexpression. 5483 Drop(1); // Value of the left subexpression.
5088 CHECK_BAILOUT(VisitForValue(expr->right())); 5484 CHECK_BAILOUT(VisitForValue(expr->right()));
5089 5485
5090 HBasicBlock* join_block = 5486 HBasicBlock* join_block =
5091 CreateJoin(empty_block, current_block(), expr->id()); 5487 CreateJoin(empty_block, current_block(), expr->id());
5092 set_current_block(join_block); 5488 set_current_block(join_block);
5093 ast_context()->ReturnValue(Pop()); 5489 return ast_context()->ReturnValue(Pop());
5094 5490
5095 } else { 5491 } else {
5096 ASSERT(ast_context()->IsEffect()); 5492 ASSERT(ast_context()->IsEffect());
5097 // In an effect context, we don't need the value of the left subexpression, 5493 // In an effect context, we don't need the value of the left subexpression,
5098 // only its control flow and side effects. We need an extra block to 5494 // only its control flow and side effects. We need an extra block to
5099 // maintain edge-split form. 5495 // maintain edge-split form.
5100 HBasicBlock* empty_block = graph()->CreateBasicBlock(); 5496 HBasicBlock* empty_block = graph()->CreateBasicBlock();
5101 HBasicBlock* right_block = graph()->CreateBasicBlock(); 5497 HBasicBlock* right_block = graph()->CreateBasicBlock();
5102 if (is_logical_and) { 5498 if (is_logical_and) {
5103 CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block)); 5499 CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
(...skipping 24 matching lines...) Expand all
5128 5524
5129 HBasicBlock* join_block = 5525 HBasicBlock* join_block =
5130 CreateJoin(empty_block, right_block, expr->id()); 5526 CreateJoin(empty_block, right_block, expr->id());
5131 set_current_block(join_block); 5527 set_current_block(join_block);
5132 // We did not materialize any value in the predecessor environments, 5528 // We did not materialize any value in the predecessor environments,
5133 // so there is no need to handle it here. 5529 // so there is no need to handle it here.
5134 } 5530 }
5135 } 5531 }
5136 5532
5137 5533
5138 void HGraphBuilder::VisitCommon(BinaryOperation* expr) { 5534 void HGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
5139 CHECK_ALIVE(VisitForValue(expr->left())); 5535 CHECK_ALIVE(VisitForValue(expr->left()));
5140 CHECK_ALIVE(VisitForValue(expr->right())); 5536 CHECK_ALIVE(VisitForValue(expr->right()));
5141 HValue* right = Pop(); 5537 HValue* right = Pop();
5142 HValue* left = Pop(); 5538 HValue* left = Pop();
5143 HInstruction* instr = BuildBinaryOperation(expr, left, right); 5539 HInstruction* instr = BuildBinaryOperation(expr, left, right);
5144 instr->set_position(expr->position()); 5540 instr->set_position(expr->position());
5145 ast_context()->ReturnInstruction(instr, expr->id()); 5541 return ast_context()->ReturnInstruction(instr, expr->id());
5146 } 5542 }
5147 5543
5148 5544
5149 void HGraphBuilder::TraceRepresentation(Token::Value op, 5545 void HGraphBuilder::TraceRepresentation(Token::Value op,
5150 TypeInfo info, 5546 TypeInfo info,
5151 HValue* value, 5547 HValue* value,
5152 Representation rep) { 5548 Representation rep) {
5153 if (!FLAG_trace_representation) return; 5549 if (!FLAG_trace_representation) return;
5154 // TODO(svenpanne) Under which circumstances are we actually not flexible? 5550 // TODO(svenpanne) Under which circumstances are we actually not flexible?
5155 // At first glance, this looks a bit weird... 5551 // At first glance, this looks a bit weird...
(...skipping 12 matching lines...) Expand all
5168 5564
5169 Representation HGraphBuilder::ToRepresentation(TypeInfo info) { 5565 Representation HGraphBuilder::ToRepresentation(TypeInfo info) {
5170 if (info.IsSmi()) return Representation::Integer32(); 5566 if (info.IsSmi()) return Representation::Integer32();
5171 if (info.IsInteger32()) return Representation::Integer32(); 5567 if (info.IsInteger32()) return Representation::Integer32();
5172 if (info.IsDouble()) return Representation::Double(); 5568 if (info.IsDouble()) return Representation::Double();
5173 if (info.IsNumber()) return Representation::Double(); 5569 if (info.IsNumber()) return Representation::Double();
5174 return Representation::Tagged(); 5570 return Representation::Tagged();
5175 } 5571 }
5176 5572
5177 5573
5574 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* compare_expr,
5575 Expression* expr,
5576 Handle<String> check) {
5577 CHECK_ALIVE(VisitForTypeOf(expr));
5578 HValue* expr_value = Pop();
5579 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(expr_value, check);
5580 instr->set_position(compare_expr->position());
5581 return ast_context()->ReturnControl(instr, compare_expr->id());
5582 }
5583
5584
5585 void HGraphBuilder::HandleLiteralCompareUndefined(
5586 CompareOperation* compare_expr, Expression* expr) {
5587 CHECK_ALIVE(VisitForValue(expr));
5588 HValue* lhs = Pop();
5589 HValue* rhs = graph()->GetConstantUndefined();
5590 HCompareObjectEqAndBranch* instr =
5591 new(zone()) HCompareObjectEqAndBranch(lhs, rhs);
5592 instr->set_position(compare_expr->position());
5593 return ast_context()->ReturnControl(instr, compare_expr->id());
5594 }
5595
5596
5178 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { 5597 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
5179 ASSERT(!HasStackOverflow()); 5598 ASSERT(!HasStackOverflow());
5180 ASSERT(current_block() != NULL); 5599 ASSERT(current_block() != NULL);
5181 ASSERT(current_block()->HasPredecessor()); 5600 ASSERT(current_block()->HasPredecessor());
5182 if (IsClassOfTest(expr)) { 5601 if (IsClassOfTest(expr)) {
5183 CallRuntime* call = expr->left()->AsCallRuntime(); 5602 CallRuntime* call = expr->left()->AsCallRuntime();
5603 ASSERT(call->arguments()->length() == 1);
5184 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5604 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5185 HValue* value = Pop(); 5605 HValue* value = Pop();
5186 Literal* literal = expr->right()->AsLiteral(); 5606 Literal* literal = expr->right()->AsLiteral();
5187 Handle<String> rhs = Handle<String>::cast(literal->handle()); 5607 Handle<String> rhs = Handle<String>::cast(literal->handle());
5188 HInstruction* instr = new(zone()) HClassOfTest(value, rhs); 5608 HClassOfTestAndBranch* instr =
5609 new(zone()) HClassOfTestAndBranch(value, rhs);
5189 instr->set_position(expr->position()); 5610 instr->set_position(expr->position());
5190 ast_context()->ReturnInstruction(instr, expr->id()); 5611 return ast_context()->ReturnControl(instr, expr->id());
5612 }
5613
5614 // Check for special cases that compare against literals.
5615 Expression *sub_expr;
5616 Handle<String> check;
5617 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
5618 HandleLiteralCompareTypeof(expr, sub_expr, check);
5191 return; 5619 return;
5192 } 5620 }
5193 5621
5194 // Check for the pattern: typeof <expression> == <string literal>. 5622 if (expr->IsLiteralCompareUndefined(&sub_expr)) {
5195 UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); 5623 HandleLiteralCompareUndefined(expr, sub_expr);
5196 Literal* right_literal = expr->right()->AsLiteral();
5197 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) &&
5198 left_unary != NULL && left_unary->op() == Token::TYPEOF &&
5199 right_literal != NULL && right_literal->handle()->IsString()) {
5200 CHECK_ALIVE(VisitForTypeOf(left_unary->expression()));
5201 HValue* left = Pop();
5202 HInstruction* instr = new(zone()) HTypeofIs(left,
5203 Handle<String>::cast(right_literal->handle()));
5204 instr->set_position(expr->position());
5205 ast_context()->ReturnInstruction(instr, expr->id());
5206 return; 5624 return;
5207 } 5625 }
5208 5626
5627 TypeInfo type_info = oracle()->CompareType(expr);
5628 // Check if this expression was ever executed according to type feedback.
5629 if (type_info.IsUninitialized()) {
5630 AddInstruction(new(zone()) HSoftDeoptimize);
5631 current_block()->MarkAsDeoptimizing();
5632 type_info = TypeInfo::Unknown();
5633 }
5634
5209 CHECK_ALIVE(VisitForValue(expr->left())); 5635 CHECK_ALIVE(VisitForValue(expr->left()));
5210 CHECK_ALIVE(VisitForValue(expr->right())); 5636 CHECK_ALIVE(VisitForValue(expr->right()));
5211 5637
5638 HValue* context = environment()->LookupContext();
5212 HValue* right = Pop(); 5639 HValue* right = Pop();
5213 HValue* left = Pop(); 5640 HValue* left = Pop();
5214 Token::Value op = expr->op(); 5641 Token::Value op = expr->op();
5215 5642
5216 TypeInfo type_info = oracle()->CompareType(expr);
5217 HInstruction* instr = NULL;
5218 if (op == Token::INSTANCEOF) { 5643 if (op == Token::INSTANCEOF) {
5219 // Check to see if the rhs of the instanceof is a global function not 5644 // Check to see if the rhs of the instanceof is a global function not
5220 // residing in new space. If it is we assume that the function will stay the 5645 // residing in new space. If it is we assume that the function will stay the
5221 // same. 5646 // same.
5222 Handle<JSFunction> target = Handle<JSFunction>::null(); 5647 Handle<JSFunction> target = Handle<JSFunction>::null();
5223 Variable* var = expr->right()->AsVariableProxy()->AsVariable(); 5648 Variable* var = expr->right()->AsVariableProxy()->AsVariable();
5224 bool global_function = (var != NULL) && var->is_global() && !var->is_this(); 5649 bool global_function = (var != NULL) && var->is_global() && !var->is_this();
5225 if (global_function && 5650 if (global_function &&
5226 info()->has_global_object() && 5651 info()->has_global_object() &&
5227 !info()->global_object()->IsAccessCheckNeeded()) { 5652 !info()->global_object()->IsAccessCheckNeeded()) {
5228 Handle<String> name = var->name(); 5653 Handle<String> name = var->name();
5229 Handle<GlobalObject> global(info()->global_object()); 5654 Handle<GlobalObject> global(info()->global_object());
5230 LookupResult lookup; 5655 LookupResult lookup;
5231 global->Lookup(*name, &lookup); 5656 global->Lookup(*name, &lookup);
5232 if (lookup.IsProperty() && 5657 if (lookup.IsProperty() &&
5233 lookup.type() == NORMAL && 5658 lookup.type() == NORMAL &&
5234 lookup.GetValue()->IsJSFunction()) { 5659 lookup.GetValue()->IsJSFunction()) {
5235 Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue())); 5660 Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue()));
5236 // If the function is in new space we assume it's more likely to 5661 // If the function is in new space we assume it's more likely to
5237 // change and thus prefer the general IC code. 5662 // change and thus prefer the general IC code.
5238 if (!isolate()->heap()->InNewSpace(*candidate)) { 5663 if (!isolate()->heap()->InNewSpace(*candidate)) {
5239 target = candidate; 5664 target = candidate;
5240 } 5665 }
5241 } 5666 }
5242 } 5667 }
5243 5668
5244 // If the target is not null we have found a known global function that is 5669 // If the target is not null we have found a known global function that is
5245 // assumed to stay the same for this instanceof. 5670 // assumed to stay the same for this instanceof.
5246 if (target.is_null()) { 5671 if (target.is_null()) {
5247 HValue* context = environment()->LookupContext(); 5672 HInstanceOf* result = new(zone()) HInstanceOf(context, left, right);
5248 instr = new(zone()) HInstanceOf(context, left, right); 5673 result->set_position(expr->position());
5674 return ast_context()->ReturnInstruction(result, expr->id());
5249 } else { 5675 } else {
5250 AddInstruction(new(zone()) HCheckFunction(right, target)); 5676 AddInstruction(new(zone()) HCheckFunction(right, target));
5251 instr = new(zone()) HInstanceOfKnownGlobal(left, target); 5677 HInstanceOfKnownGlobal* result =
5678 new(zone()) HInstanceOfKnownGlobal(context, left, target);
5679 result->set_position(expr->position());
5680 return ast_context()->ReturnInstruction(result, expr->id());
5252 } 5681 }
5253 } else if (op == Token::IN) { 5682 } else if (op == Token::IN) {
5254 instr = new(zone()) HIn(left, right); 5683 HIn* result = new(zone()) HIn(context, left, right);
5684 result->set_position(expr->position());
5685 return ast_context()->ReturnInstruction(result, expr->id());
5255 } else if (type_info.IsNonPrimitive()) { 5686 } else if (type_info.IsNonPrimitive()) {
5256 switch (op) { 5687 switch (op) {
5257 case Token::EQ: 5688 case Token::EQ:
5258 case Token::EQ_STRICT: { 5689 case Token::EQ_STRICT: {
5259 AddInstruction(new(zone()) HCheckNonSmi(left)); 5690 AddInstruction(new(zone()) HCheckNonSmi(left));
5260 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left)); 5691 AddInstruction(HCheckInstanceType::NewIsSpecObject(left));
5261 AddInstruction(new(zone()) HCheckNonSmi(right)); 5692 AddInstruction(new(zone()) HCheckNonSmi(right));
5262 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right)); 5693 AddInstruction(HCheckInstanceType::NewIsSpecObject(right));
5263 instr = new(zone()) HCompareJSObjectEq(left, right); 5694 HCompareObjectEqAndBranch* result =
5264 break; 5695 new(zone()) HCompareObjectEqAndBranch(left, right);
5696 result->set_position(expr->position());
5697 return ast_context()->ReturnControl(result, expr->id());
5265 } 5698 }
5266 default: 5699 default:
5267 return Bailout("Unsupported non-primitive compare"); 5700 return Bailout("Unsupported non-primitive compare");
5268 break;
5269 } 5701 }
5270 } else if (type_info.IsString() && oracle()->IsSymbolCompare(expr) && 5702 } else if (type_info.IsString() && oracle()->IsSymbolCompare(expr) &&
5271 (op == Token::EQ || op == Token::EQ_STRICT)) { 5703 (op == Token::EQ || op == Token::EQ_STRICT)) {
5272 instr = BuildSymbolCompare(left, right, op); 5704 AddInstruction(new(zone()) HCheckNonSmi(left));
5705 AddInstruction(HCheckInstanceType::NewIsSymbol(left));
5706 AddInstruction(new(zone()) HCheckNonSmi(right));
5707 AddInstruction(HCheckInstanceType::NewIsSymbol(right));
5708 HCompareObjectEqAndBranch* result =
5709 new(zone()) HCompareObjectEqAndBranch(left, right);
5710 result->set_position(expr->position());
5711 return ast_context()->ReturnControl(result, expr->id());
5273 } else { 5712 } else {
5274 HCompare* compare = new(zone()) HCompare(left, right, op);
5275 Representation r = ToRepresentation(type_info); 5713 Representation r = ToRepresentation(type_info);
5276 compare->SetInputRepresentation(r); 5714 if (r.IsTagged()) {
5277 instr = compare; 5715 HCompareGeneric* result =
5716 new(zone()) HCompareGeneric(context, left, right, op);
5717 result->set_position(expr->position());
5718 return ast_context()->ReturnInstruction(result, expr->id());
5719 } else {
5720 HCompareIDAndBranch* result =
5721 new(zone()) HCompareIDAndBranch(left, right, op);
5722 result->set_position(expr->position());
5723 result->SetInputRepresentation(r);
5724 return ast_context()->ReturnControl(result, expr->id());
5725 }
5278 } 5726 }
5279 instr->set_position(expr->position());
5280 ast_context()->ReturnInstruction(instr, expr->id());
5281 } 5727 }
5282 5728
5283 5729
5284 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { 5730 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) {
5285 ASSERT(!HasStackOverflow()); 5731 ASSERT(!HasStackOverflow());
5286 ASSERT(current_block() != NULL); 5732 ASSERT(current_block() != NULL);
5287 ASSERT(current_block()->HasPredecessor()); 5733 ASSERT(current_block()->HasPredecessor());
5288 CHECK_ALIVE(VisitForValue(expr->expression())); 5734 CHECK_ALIVE(VisitForValue(expr->expression()));
5289
5290 HValue* value = Pop(); 5735 HValue* value = Pop();
5291 HIsNull* compare = new(zone()) HIsNull(value, expr->is_strict()); 5736 HIsNullAndBranch* instr =
5292 ast_context()->ReturnInstruction(compare, expr->id()); 5737 new(zone()) HIsNullAndBranch(value, expr->is_strict());
5738 return ast_context()->ReturnControl(instr, expr->id());
5293 } 5739 }
5294 5740
5295 5741
5296 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { 5742 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
5297 ASSERT(!HasStackOverflow()); 5743 ASSERT(!HasStackOverflow());
5298 ASSERT(current_block() != NULL); 5744 ASSERT(current_block() != NULL);
5299 ASSERT(current_block()->HasPredecessor()); 5745 ASSERT(current_block()->HasPredecessor());
5300 return Bailout("ThisFunction"); 5746 HThisFunction* self = new(zone()) HThisFunction;
5747 return ast_context()->ReturnInstruction(self, expr->id());
5301 } 5748 }
5302 5749
5303 5750
5304 void HGraphBuilder::VisitDeclaration(Declaration* decl) { 5751 void HGraphBuilder::VisitDeclaration(Declaration* decl) {
5305 // We allow only declarations that do not require code generation. 5752 // We support only declarations that do not require code generation.
5306 // The following all require code generation: global variables and
5307 // functions, variables with slot type LOOKUP, declarations with
5308 // mode CONST, and functions.
5309 Variable* var = decl->proxy()->var(); 5753 Variable* var = decl->proxy()->var();
5310 Slot* slot = var->AsSlot(); 5754 if (!var->IsStackAllocated() || decl->fun() != NULL) {
5311 if (var->is_global() ||
5312 (slot != NULL && slot->type() == Slot::LOOKUP) ||
5313 decl->mode() == Variable::CONST ||
5314 decl->fun() != NULL) {
5315 return Bailout("unsupported declaration"); 5755 return Bailout("unsupported declaration");
5316 } 5756 }
5757
5758 if (decl->mode() == Variable::CONST) {
5759 ASSERT(var->IsStackAllocated());
5760 environment()->Bind(var, graph()->GetConstantHole());
5761 }
5317 } 5762 }
5318 5763
5319 5764
5320 // Generators for inline runtime functions. 5765 // Generators for inline runtime functions.
5321 // Support for types. 5766 // Support for types.
5322 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) { 5767 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) {
5323 ASSERT(call->arguments()->length() == 1); 5768 ASSERT(call->arguments()->length() == 1);
5324 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5769 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5325 HValue* value = Pop(); 5770 HValue* value = Pop();
5326 HIsSmi* result = new(zone()) HIsSmi(value); 5771 HIsSmiAndBranch* result = new(zone()) HIsSmiAndBranch(value);
5327 ast_context()->ReturnInstruction(result, call->id()); 5772 return ast_context()->ReturnControl(result, call->id());
5328 } 5773 }
5329 5774
5330 5775
5331 void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { 5776 void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) {
5332 ASSERT(call->arguments()->length() == 1); 5777 ASSERT(call->arguments()->length() == 1);
5333 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5778 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5334 HValue* value = Pop(); 5779 HValue* value = Pop();
5335 HHasInstanceType* result = 5780 HHasInstanceTypeAndBranch* result =
5336 new(zone()) HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE); 5781 new(zone()) HHasInstanceTypeAndBranch(value,
5337 ast_context()->ReturnInstruction(result, call->id()); 5782 FIRST_SPEC_OBJECT_TYPE,
5783 LAST_SPEC_OBJECT_TYPE);
5784 return ast_context()->ReturnControl(result, call->id());
5338 } 5785 }
5339 5786
5340 5787
5341 void HGraphBuilder::GenerateIsFunction(CallRuntime* call) { 5788 void HGraphBuilder::GenerateIsFunction(CallRuntime* call) {
5342 ASSERT(call->arguments()->length() == 1); 5789 ASSERT(call->arguments()->length() == 1);
5343 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5790 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5344 HValue* value = Pop(); 5791 HValue* value = Pop();
5345 HHasInstanceType* result = 5792 HHasInstanceTypeAndBranch* result =
5346 new(zone()) HHasInstanceType(value, JS_FUNCTION_TYPE); 5793 new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_TYPE);
5347 ast_context()->ReturnInstruction(result, call->id()); 5794 return ast_context()->ReturnControl(result, call->id());
5348 } 5795 }
5349 5796
5350 5797
5351 void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { 5798 void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
5352 ASSERT(call->arguments()->length() == 1); 5799 ASSERT(call->arguments()->length() == 1);
5353 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5800 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5354 HValue* value = Pop(); 5801 HValue* value = Pop();
5355 HHasCachedArrayIndex* result = new(zone()) HHasCachedArrayIndex(value); 5802 HHasCachedArrayIndexAndBranch* result =
5356 ast_context()->ReturnInstruction(result, call->id()); 5803 new(zone()) HHasCachedArrayIndexAndBranch(value);
5804 return ast_context()->ReturnControl(result, call->id());
5357 } 5805 }
5358 5806
5359 5807
5360 void HGraphBuilder::GenerateIsArray(CallRuntime* call) { 5808 void HGraphBuilder::GenerateIsArray(CallRuntime* call) {
5361 ASSERT(call->arguments()->length() == 1); 5809 ASSERT(call->arguments()->length() == 1);
5362 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5810 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5363 HValue* value = Pop(); 5811 HValue* value = Pop();
5364 HHasInstanceType* result = new(zone()) HHasInstanceType(value, JS_ARRAY_TYPE); 5812 HHasInstanceTypeAndBranch* result =
5365 ast_context()->ReturnInstruction(result, call->id()); 5813 new(zone()) HHasInstanceTypeAndBranch(value, JS_ARRAY_TYPE);
5814 return ast_context()->ReturnControl(result, call->id());
5366 } 5815 }
5367 5816
5368 5817
5369 void HGraphBuilder::GenerateIsRegExp(CallRuntime* call) { 5818 void HGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
5370 ASSERT(call->arguments()->length() == 1); 5819 ASSERT(call->arguments()->length() == 1);
5371 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5820 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5372 HValue* value = Pop(); 5821 HValue* value = Pop();
5373 HHasInstanceType* result = 5822 HHasInstanceTypeAndBranch* result =
5374 new(zone()) HHasInstanceType(value, JS_REGEXP_TYPE); 5823 new(zone()) HHasInstanceTypeAndBranch(value, JS_REGEXP_TYPE);
5375 ast_context()->ReturnInstruction(result, call->id()); 5824 return ast_context()->ReturnControl(result, call->id());
5376 } 5825 }
5377 5826
5378 5827
5379 void HGraphBuilder::GenerateIsObject(CallRuntime* call) { 5828 void HGraphBuilder::GenerateIsObject(CallRuntime* call) {
5380 ASSERT(call->arguments()->length() == 1); 5829 ASSERT(call->arguments()->length() == 1);
5381 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5830 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5382 HValue* value = Pop(); 5831 HValue* value = Pop();
5383 HIsObject* test = new(zone()) HIsObject(value); 5832 HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value);
5384 ast_context()->ReturnInstruction(test, call->id()); 5833 return ast_context()->ReturnControl(result, call->id());
5385 } 5834 }
5386 5835
5387 5836
5388 void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { 5837 void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) {
5389 return Bailout("inlined runtime function: IsNonNegativeSmi"); 5838 return Bailout("inlined runtime function: IsNonNegativeSmi");
5390 } 5839 }
5391 5840
5392 5841
5393 void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { 5842 void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
5394 ASSERT(call->arguments()->length() == 1); 5843 ASSERT(call->arguments()->length() == 1);
5395 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5844 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5396 HValue* value = Pop(); 5845 HValue* value = Pop();
5397 ast_context()->ReturnInstruction(new(zone()) HIsUndetectable(value), 5846 HIsUndetectableAndBranch* result =
5398 call->id()); 5847 new(zone()) HIsUndetectableAndBranch(value);
5848 return ast_context()->ReturnControl(result, call->id());
5399 } 5849 }
5400 5850
5401 5851
5402 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( 5852 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
5403 CallRuntime* call) { 5853 CallRuntime* call) {
5404 return Bailout( 5854 return Bailout(
5405 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); 5855 "inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
5406 } 5856 }
5407 5857
5408 5858
5409 // Support for construct call checks. 5859 // Support for construct call checks.
5410 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { 5860 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
5411 ASSERT(call->arguments()->length() == 0); 5861 ASSERT(call->arguments()->length() == 0);
5412 if (function_state()->outer() != NULL) { 5862 if (function_state()->outer() != NULL) {
5413 // We are generating graph for inlined function. Currently 5863 // We are generating graph for inlined function. Currently
5414 // constructor inlining is not supported and we can just return 5864 // constructor inlining is not supported and we can just return
5415 // false from %_IsConstructCall(). 5865 // false from %_IsConstructCall().
5416 ast_context()->ReturnValue(graph()->GetConstantFalse()); 5866 return ast_context()->ReturnValue(graph()->GetConstantFalse());
5417 } else { 5867 } else {
5418 ast_context()->ReturnInstruction(new(zone()) HIsConstructCall, call->id()); 5868 return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch,
5869 call->id());
5419 } 5870 }
5420 } 5871 }
5421 5872
5422 5873
5423 // Support for arguments.length and arguments[?]. 5874 // Support for arguments.length and arguments[?].
5424 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { 5875 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
5876 // Our implementation of arguments (based on this stack frame or an
5877 // adapter below it) does not work for inlined functions. This runtime
5878 // function is blacklisted by AstNode::IsInlineable.
5879 ASSERT(function_state()->outer() == NULL);
5425 ASSERT(call->arguments()->length() == 0); 5880 ASSERT(call->arguments()->length() == 0);
5426 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 5881 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
5427 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); 5882 HArgumentsLength* result = new(zone()) HArgumentsLength(elements);
5428 ast_context()->ReturnInstruction(result, call->id()); 5883 return ast_context()->ReturnInstruction(result, call->id());
5429 } 5884 }
5430 5885
5431 5886
5432 void HGraphBuilder::GenerateArguments(CallRuntime* call) { 5887 void HGraphBuilder::GenerateArguments(CallRuntime* call) {
5888 // Our implementation of arguments (based on this stack frame or an
5889 // adapter below it) does not work for inlined functions. This runtime
5890 // function is blacklisted by AstNode::IsInlineable.
5891 ASSERT(function_state()->outer() == NULL);
5433 ASSERT(call->arguments()->length() == 1); 5892 ASSERT(call->arguments()->length() == 1);
5434 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5893 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5435 HValue* index = Pop(); 5894 HValue* index = Pop();
5436 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 5895 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
5437 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); 5896 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements));
5438 HAccessArgumentsAt* result = 5897 HAccessArgumentsAt* result =
5439 new(zone()) HAccessArgumentsAt(elements, length, index); 5898 new(zone()) HAccessArgumentsAt(elements, length, index);
5440 ast_context()->ReturnInstruction(result, call->id()); 5899 return ast_context()->ReturnInstruction(result, call->id());
5441 } 5900 }
5442 5901
5443 5902
5444 // Support for accessing the class and value fields of an object. 5903 // Support for accessing the class and value fields of an object.
5445 void HGraphBuilder::GenerateClassOf(CallRuntime* call) { 5904 void HGraphBuilder::GenerateClassOf(CallRuntime* call) {
5446 // The special form detected by IsClassOfTest is detected before we get here 5905 // The special form detected by IsClassOfTest is detected before we get here
5447 // and does not cause a bailout. 5906 // and does not cause a bailout.
5448 return Bailout("inlined runtime function: ClassOf"); 5907 return Bailout("inlined runtime function: ClassOf");
5449 } 5908 }
5450 5909
5451 5910
5452 void HGraphBuilder::GenerateValueOf(CallRuntime* call) { 5911 void HGraphBuilder::GenerateValueOf(CallRuntime* call) {
5453 ASSERT(call->arguments()->length() == 1); 5912 ASSERT(call->arguments()->length() == 1);
5454 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5913 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5455 HValue* value = Pop(); 5914 HValue* value = Pop();
5456 HValueOf* result = new(zone()) HValueOf(value); 5915 HValueOf* result = new(zone()) HValueOf(value);
5457 ast_context()->ReturnInstruction(result, call->id()); 5916 return ast_context()->ReturnInstruction(result, call->id());
5458 } 5917 }
5459 5918
5460 5919
5461 void HGraphBuilder::GenerateSetValueOf(CallRuntime* call) { 5920 void HGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
5462 return Bailout("inlined runtime function: SetValueOf"); 5921 return Bailout("inlined runtime function: SetValueOf");
5463 } 5922 }
5464 5923
5465 5924
5466 // Fast support for charCodeAt(n). 5925 // Fast support for charCodeAt(n).
5467 void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { 5926 void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
5468 ASSERT(call->arguments()->length() == 2); 5927 ASSERT(call->arguments()->length() == 2);
5469 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5928 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5470 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 5929 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
5471 HValue* index = Pop(); 5930 HValue* index = Pop();
5472 HValue* string = Pop(); 5931 HValue* string = Pop();
5473 HStringCharCodeAt* result = BuildStringCharCodeAt(string, index); 5932 HValue* context = environment()->LookupContext();
5474 ast_context()->ReturnInstruction(result, call->id()); 5933 HStringCharCodeAt* result = BuildStringCharCodeAt(context, string, index);
5934 return ast_context()->ReturnInstruction(result, call->id());
5475 } 5935 }
5476 5936
5477 5937
5478 // Fast support for string.charAt(n) and string[n]. 5938 // Fast support for string.charAt(n) and string[n].
5479 void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { 5939 void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
5480 ASSERT(call->arguments()->length() == 1); 5940 ASSERT(call->arguments()->length() == 1);
5481 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5941 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5482 HValue* char_code = Pop(); 5942 HValue* char_code = Pop();
5483 HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code); 5943 HValue* context = environment()->LookupContext();
5484 ast_context()->ReturnInstruction(result, call->id()); 5944 HStringCharFromCode* result =
5945 new(zone()) HStringCharFromCode(context, char_code);
5946 return ast_context()->ReturnInstruction(result, call->id());
5485 } 5947 }
5486 5948
5487 5949
5488 // Fast support for string.charAt(n) and string[n]. 5950 // Fast support for string.charAt(n) and string[n].
5489 void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) { 5951 void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
5490 ASSERT(call->arguments()->length() == 2); 5952 ASSERT(call->arguments()->length() == 2);
5491 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5953 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5492 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 5954 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
5493 HValue* index = Pop(); 5955 HValue* index = Pop();
5494 HValue* string = Pop(); 5956 HValue* string = Pop();
5495 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); 5957 HValue* context = environment()->LookupContext();
5958 HStringCharCodeAt* char_code = BuildStringCharCodeAt(context, string, index);
5496 AddInstruction(char_code); 5959 AddInstruction(char_code);
5497 HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code); 5960 HStringCharFromCode* result =
5498 ast_context()->ReturnInstruction(result, call->id()); 5961 new(zone()) HStringCharFromCode(context, char_code);
5962 return ast_context()->ReturnInstruction(result, call->id());
5499 } 5963 }
5500 5964
5501 5965
5502 // Fast support for object equality testing. 5966 // Fast support for object equality testing.
5503 void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) { 5967 void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
5504 ASSERT(call->arguments()->length() == 2); 5968 ASSERT(call->arguments()->length() == 2);
5505 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5969 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5506 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 5970 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
5507 HValue* right = Pop(); 5971 HValue* right = Pop();
5508 HValue* left = Pop(); 5972 HValue* left = Pop();
5509 HCompareJSObjectEq* result = new(zone()) HCompareJSObjectEq(left, right); 5973 HCompareObjectEqAndBranch* result =
5510 ast_context()->ReturnInstruction(result, call->id()); 5974 new(zone()) HCompareObjectEqAndBranch(left, right);
5975 return ast_context()->ReturnControl(result, call->id());
5511 } 5976 }
5512 5977
5513 5978
5514 void HGraphBuilder::GenerateLog(CallRuntime* call) { 5979 void HGraphBuilder::GenerateLog(CallRuntime* call) {
5515 // %_Log is ignored in optimized code. 5980 // %_Log is ignored in optimized code.
5516 ast_context()->ReturnValue(graph()->GetConstantUndefined()); 5981 return ast_context()->ReturnValue(graph()->GetConstantUndefined());
5517 } 5982 }
5518 5983
5519 5984
5520 // Fast support for Math.random(). 5985 // Fast support for Math.random().
5521 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { 5986 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) {
5522 return Bailout("inlined runtime function: RandomHeapNumber"); 5987 return Bailout("inlined runtime function: RandomHeapNumber");
5523 } 5988 }
5524 5989
5525 5990
5526 // Fast support for StringAdd. 5991 // Fast support for StringAdd.
5527 void HGraphBuilder::GenerateStringAdd(CallRuntime* call) { 5992 void HGraphBuilder::GenerateStringAdd(CallRuntime* call) {
5528 ASSERT_EQ(2, call->arguments()->length()); 5993 ASSERT_EQ(2, call->arguments()->length());
5529 CHECK_ALIVE(VisitArgumentList(call->arguments())); 5994 CHECK_ALIVE(VisitArgumentList(call->arguments()));
5530 HValue* context = environment()->LookupContext(); 5995 HValue* context = environment()->LookupContext();
5531 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); 5996 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2);
5532 Drop(2); 5997 Drop(2);
5533 ast_context()->ReturnInstruction(result, call->id()); 5998 return ast_context()->ReturnInstruction(result, call->id());
5534 } 5999 }
5535 6000
5536 6001
5537 // Fast support for SubString. 6002 // Fast support for SubString.
5538 void HGraphBuilder::GenerateSubString(CallRuntime* call) { 6003 void HGraphBuilder::GenerateSubString(CallRuntime* call) {
5539 ASSERT_EQ(3, call->arguments()->length()); 6004 ASSERT_EQ(3, call->arguments()->length());
5540 CHECK_ALIVE(VisitArgumentList(call->arguments())); 6005 CHECK_ALIVE(VisitArgumentList(call->arguments()));
5541 HValue* context = environment()->LookupContext(); 6006 HValue* context = environment()->LookupContext();
5542 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); 6007 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3);
5543 Drop(3); 6008 Drop(3);
5544 ast_context()->ReturnInstruction(result, call->id()); 6009 return ast_context()->ReturnInstruction(result, call->id());
5545 } 6010 }
5546 6011
5547 6012
5548 // Fast support for StringCompare. 6013 // Fast support for StringCompare.
5549 void HGraphBuilder::GenerateStringCompare(CallRuntime* call) { 6014 void HGraphBuilder::GenerateStringCompare(CallRuntime* call) {
5550 ASSERT_EQ(2, call->arguments()->length()); 6015 ASSERT_EQ(2, call->arguments()->length());
5551 CHECK_ALIVE(VisitArgumentList(call->arguments())); 6016 CHECK_ALIVE(VisitArgumentList(call->arguments()));
5552 HValue* context = environment()->LookupContext(); 6017 HValue* context = environment()->LookupContext();
5553 HCallStub* result = 6018 HCallStub* result =
5554 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); 6019 new(zone()) HCallStub(context, CodeStub::StringCompare, 2);
5555 Drop(2); 6020 Drop(2);
5556 ast_context()->ReturnInstruction(result, call->id()); 6021 return ast_context()->ReturnInstruction(result, call->id());
5557 } 6022 }
5558 6023
5559 6024
5560 // Support for direct calls from JavaScript to native RegExp code. 6025 // Support for direct calls from JavaScript to native RegExp code.
5561 void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) { 6026 void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
5562 ASSERT_EQ(4, call->arguments()->length()); 6027 ASSERT_EQ(4, call->arguments()->length());
5563 CHECK_ALIVE(VisitArgumentList(call->arguments())); 6028 CHECK_ALIVE(VisitArgumentList(call->arguments()));
5564 HValue* context = environment()->LookupContext(); 6029 HValue* context = environment()->LookupContext();
5565 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); 6030 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4);
5566 Drop(4); 6031 Drop(4);
5567 ast_context()->ReturnInstruction(result, call->id()); 6032 return ast_context()->ReturnInstruction(result, call->id());
5568 } 6033 }
5569 6034
5570 6035
5571 // Construct a RegExp exec result with two in-object properties. 6036 // Construct a RegExp exec result with two in-object properties.
5572 void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { 6037 void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
5573 ASSERT_EQ(3, call->arguments()->length()); 6038 ASSERT_EQ(3, call->arguments()->length());
5574 CHECK_ALIVE(VisitArgumentList(call->arguments())); 6039 CHECK_ALIVE(VisitArgumentList(call->arguments()));
5575 HValue* context = environment()->LookupContext(); 6040 HValue* context = environment()->LookupContext();
5576 HCallStub* result = 6041 HCallStub* result =
5577 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); 6042 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3);
5578 Drop(3); 6043 Drop(3);
5579 ast_context()->ReturnInstruction(result, call->id()); 6044 return ast_context()->ReturnInstruction(result, call->id());
5580 } 6045 }
5581 6046
5582 6047
5583 // Support for fast native caches. 6048 // Support for fast native caches.
5584 void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) { 6049 void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
5585 return Bailout("inlined runtime function: GetFromCache"); 6050 return Bailout("inlined runtime function: GetFromCache");
5586 } 6051 }
5587 6052
5588 6053
5589 // Fast support for number to string. 6054 // Fast support for number to string.
5590 void HGraphBuilder::GenerateNumberToString(CallRuntime* call) { 6055 void HGraphBuilder::GenerateNumberToString(CallRuntime* call) {
5591 ASSERT_EQ(1, call->arguments()->length()); 6056 ASSERT_EQ(1, call->arguments()->length());
5592 CHECK_ALIVE(VisitArgumentList(call->arguments())); 6057 CHECK_ALIVE(VisitArgumentList(call->arguments()));
5593 HValue* context = environment()->LookupContext(); 6058 HValue* context = environment()->LookupContext();
5594 HCallStub* result = 6059 HCallStub* result =
5595 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); 6060 new(zone()) HCallStub(context, CodeStub::NumberToString, 1);
5596 Drop(1); 6061 Drop(1);
5597 ast_context()->ReturnInstruction(result, call->id()); 6062 return ast_context()->ReturnInstruction(result, call->id());
5598 } 6063 }
5599 6064
5600 6065
5601 // Fast swapping of elements. Takes three expressions, the object and two 6066 // Fast swapping of elements. Takes three expressions, the object and two
5602 // indices. This should only be used if the indices are known to be 6067 // indices. This should only be used if the indices are known to be
5603 // non-negative and within bounds of the elements array at the call site. 6068 // non-negative and within bounds of the elements array at the call site.
5604 void HGraphBuilder::GenerateSwapElements(CallRuntime* call) { 6069 void HGraphBuilder::GenerateSwapElements(CallRuntime* call) {
5605 return Bailout("inlined runtime function: SwapElements"); 6070 return Bailout("inlined runtime function: SwapElements");
5606 } 6071 }
5607 6072
5608 6073
5609 // Fast call for custom callbacks. 6074 // Fast call for custom callbacks.
5610 void HGraphBuilder::GenerateCallFunction(CallRuntime* call) { 6075 void HGraphBuilder::GenerateCallFunction(CallRuntime* call) {
5611 // 1 ~ The function to call is not itself an argument to the call. 6076 // 1 ~ The function to call is not itself an argument to the call.
5612 int arg_count = call->arguments()->length() - 1; 6077 int arg_count = call->arguments()->length() - 1;
5613 ASSERT(arg_count >= 1); // There's always at least a receiver. 6078 ASSERT(arg_count >= 1); // There's always at least a receiver.
5614 6079
5615 for (int i = 0; i < arg_count; ++i) { 6080 for (int i = 0; i < arg_count; ++i) {
5616 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); 6081 CHECK_ALIVE(VisitArgument(call->arguments()->at(i)));
5617 } 6082 }
5618 CHECK_ALIVE(VisitForValue(call->arguments()->last())); 6083 CHECK_ALIVE(VisitForValue(call->arguments()->last()));
5619 HValue* function = Pop(); 6084 HValue* function = Pop();
5620 HValue* context = environment()->LookupContext(); 6085 HValue* context = environment()->LookupContext();
5621 HInvokeFunction* result = 6086 HInvokeFunction* result =
5622 new(zone()) HInvokeFunction(context, function, arg_count); 6087 new(zone()) HInvokeFunction(context, function, arg_count);
5623 Drop(arg_count); 6088 Drop(arg_count);
5624 ast_context()->ReturnInstruction(result, call->id()); 6089 return ast_context()->ReturnInstruction(result, call->id());
5625 } 6090 }
5626 6091
5627 6092
5628 // Fast call to math functions. 6093 // Fast call to math functions.
5629 void HGraphBuilder::GenerateMathPow(CallRuntime* call) { 6094 void HGraphBuilder::GenerateMathPow(CallRuntime* call) {
5630 ASSERT_EQ(2, call->arguments()->length()); 6095 ASSERT_EQ(2, call->arguments()->length());
5631 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 6096 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5632 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 6097 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
5633 HValue* right = Pop(); 6098 HValue* right = Pop();
5634 HValue* left = Pop(); 6099 HValue* left = Pop();
5635 HPower* result = new(zone()) HPower(left, right); 6100 HPower* result = new(zone()) HPower(left, right);
5636 ast_context()->ReturnInstruction(result, call->id()); 6101 return ast_context()->ReturnInstruction(result, call->id());
5637 } 6102 }
5638 6103
5639 6104
5640 void HGraphBuilder::GenerateMathSin(CallRuntime* call) { 6105 void HGraphBuilder::GenerateMathSin(CallRuntime* call) {
5641 ASSERT_EQ(1, call->arguments()->length()); 6106 ASSERT_EQ(1, call->arguments()->length());
5642 CHECK_ALIVE(VisitArgumentList(call->arguments())); 6107 CHECK_ALIVE(VisitArgumentList(call->arguments()));
5643 HValue* context = environment()->LookupContext(); 6108 HValue* context = environment()->LookupContext();
5644 HCallStub* result = 6109 HCallStub* result =
5645 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 6110 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
5646 result->set_transcendental_type(TranscendentalCache::SIN); 6111 result->set_transcendental_type(TranscendentalCache::SIN);
5647 Drop(1); 6112 Drop(1);
5648 ast_context()->ReturnInstruction(result, call->id()); 6113 return ast_context()->ReturnInstruction(result, call->id());
5649 } 6114 }
5650 6115
5651 6116
5652 void HGraphBuilder::GenerateMathCos(CallRuntime* call) { 6117 void HGraphBuilder::GenerateMathCos(CallRuntime* call) {
5653 ASSERT_EQ(1, call->arguments()->length()); 6118 ASSERT_EQ(1, call->arguments()->length());
5654 CHECK_ALIVE(VisitArgumentList(call->arguments())); 6119 CHECK_ALIVE(VisitArgumentList(call->arguments()));
5655 HValue* context = environment()->LookupContext(); 6120 HValue* context = environment()->LookupContext();
5656 HCallStub* result = 6121 HCallStub* result =
5657 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 6122 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
5658 result->set_transcendental_type(TranscendentalCache::COS); 6123 result->set_transcendental_type(TranscendentalCache::COS);
5659 Drop(1); 6124 Drop(1);
5660 ast_context()->ReturnInstruction(result, call->id()); 6125 return ast_context()->ReturnInstruction(result, call->id());
5661 } 6126 }
5662 6127
5663 6128
5664 void HGraphBuilder::GenerateMathLog(CallRuntime* call) { 6129 void HGraphBuilder::GenerateMathLog(CallRuntime* call) {
5665 ASSERT_EQ(1, call->arguments()->length()); 6130 ASSERT_EQ(1, call->arguments()->length());
5666 CHECK_ALIVE(VisitArgumentList(call->arguments())); 6131 CHECK_ALIVE(VisitArgumentList(call->arguments()));
5667 HValue* context = environment()->LookupContext(); 6132 HValue* context = environment()->LookupContext();
5668 HCallStub* result = 6133 HCallStub* result =
5669 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 6134 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1);
5670 result->set_transcendental_type(TranscendentalCache::LOG); 6135 result->set_transcendental_type(TranscendentalCache::LOG);
5671 Drop(1); 6136 Drop(1);
5672 ast_context()->ReturnInstruction(result, call->id()); 6137 return ast_context()->ReturnInstruction(result, call->id());
5673 } 6138 }
5674 6139
5675 6140
5676 void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) { 6141 void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
5677 return Bailout("inlined runtime function: MathSqrt"); 6142 return Bailout("inlined runtime function: MathSqrt");
5678 } 6143 }
5679 6144
5680 6145
5681 // Check whether two RegExps are equivalent 6146 // Check whether two RegExps are equivalent
5682 void HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { 6147 void HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) {
5683 return Bailout("inlined runtime function: IsRegExpEquivalent"); 6148 return Bailout("inlined runtime function: IsRegExpEquivalent");
5684 } 6149 }
5685 6150
5686 6151
5687 void HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { 6152 void HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
5688 ASSERT(call->arguments()->length() == 1); 6153 ASSERT(call->arguments()->length() == 1);
5689 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 6154 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5690 HValue* value = Pop(); 6155 HValue* value = Pop();
5691 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); 6156 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value);
5692 ast_context()->ReturnInstruction(result, call->id()); 6157 return ast_context()->ReturnInstruction(result, call->id());
5693 } 6158 }
5694 6159
5695 6160
5696 void HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { 6161 void HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) {
5697 return Bailout("inlined runtime function: FastAsciiArrayJoin"); 6162 return Bailout("inlined runtime function: FastAsciiArrayJoin");
5698 } 6163 }
5699 6164
5700 6165
6166 void HGraphBuilder::GenerateIsNativeOrStrictMode(CallRuntime* call) {
6167 return Bailout("inlined runtime function: IsNativeOrStrictMode");
6168 }
6169
6170
5701 #undef CHECK_BAILOUT 6171 #undef CHECK_BAILOUT
5702 #undef CHECK_ALIVE 6172 #undef CHECK_ALIVE
5703 6173
5704 6174
5705 HEnvironment::HEnvironment(HEnvironment* outer, 6175 HEnvironment::HEnvironment(HEnvironment* outer,
5706 Scope* scope, 6176 Scope* scope,
5707 Handle<JSFunction> closure) 6177 Handle<JSFunction> closure)
5708 : closure_(closure), 6178 : closure_(closure),
5709 values_(0), 6179 values_(0),
5710 assigned_variables_(4), 6180 assigned_variables_(4),
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
5853 loop_header->AddPhi(phi); 6323 loop_header->AddPhi(phi);
5854 } 6324 }
5855 new_env->ClearHistory(); 6325 new_env->ClearHistory();
5856 return new_env; 6326 return new_env;
5857 } 6327 }
5858 6328
5859 6329
5860 HEnvironment* HEnvironment::CopyForInlining( 6330 HEnvironment* HEnvironment::CopyForInlining(
5861 Handle<JSFunction> target, 6331 Handle<JSFunction> target,
5862 FunctionLiteral* function, 6332 FunctionLiteral* function,
5863 CompilationPhase compilation_phase,
5864 HConstant* undefined, 6333 HConstant* undefined,
5865 CallKind call_kind) const { 6334 CallKind call_kind) const {
5866 // Outer environment is a copy of this one without the arguments. 6335 // Outer environment is a copy of this one without the arguments.
5867 int arity = function->scope()->num_parameters(); 6336 int arity = function->scope()->num_parameters();
5868 HEnvironment* outer = Copy(); 6337 HEnvironment* outer = Copy();
5869 outer->Drop(arity + 1); // Including receiver. 6338 outer->Drop(arity + 1); // Including receiver.
5870 outer->ClearHistory(); 6339 outer->ClearHistory();
5871 Zone* zone = closure()->GetIsolate()->zone(); 6340 Zone* zone = closure()->GetIsolate()->zone();
5872 HEnvironment* inner = 6341 HEnvironment* inner =
5873 new(zone) HEnvironment(outer, function->scope(), target); 6342 new(zone) HEnvironment(outer, function->scope(), target);
5874 // Get the argument values from the original environment. 6343 // Get the argument values from the original environment.
5875 if (compilation_phase == HYDROGEN) { 6344 for (int i = 0; i <= arity; ++i) { // Include receiver.
5876 for (int i = 0; i <= arity; ++i) { // Include receiver. 6345 HValue* push = ExpressionStackAt(arity - i);
5877 HValue* push = ExpressionStackAt(arity - i); 6346 inner->SetValueAt(i, push);
5878 inner->SetValueAt(i, push);
5879 }
5880 } else {
5881 ASSERT(compilation_phase == LITHIUM);
5882 for (int i = 0; i <= arity; ++i) { // Include receiver.
5883 HValue* push = ExpressionStackAt(arity - i);
5884 inner->SetValueAt(i, push);
5885 }
5886 } 6347 }
5887 // If the function we are inlining is a strict mode function, pass 6348 // If the function we are inlining is a strict mode function or a
5888 // undefined as the receiver for function calls (instead of the 6349 // builtin function, pass undefined as the receiver for function
5889 // global receiver). 6350 // calls (instead of the global receiver).
5890 if (function->strict_mode() && call_kind == CALL_AS_FUNCTION) { 6351 if ((target->shared()->native() || function->strict_mode()) &&
6352 call_kind == CALL_AS_FUNCTION) {
5891 inner->SetValueAt(0, undefined); 6353 inner->SetValueAt(0, undefined);
5892 } 6354 }
5893 inner->SetValueAt(arity + 1, outer->LookupContext()); 6355 inner->SetValueAt(arity + 1, outer->LookupContext());
5894 for (int i = arity + 2; i < inner->length(); ++i) { 6356 for (int i = arity + 2; i < inner->length(); ++i) {
5895 inner->SetValueAt(i, undefined); 6357 inner->SetValueAt(i, undefined);
5896 } 6358 }
5897 6359
5898 inner->set_ast_id(AstNode::kFunctionEntryId); 6360 inner->set_ast_id(AstNode::kFunctionEntryId);
5899 return inner; 6361 return inner;
5900 } 6362 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
5962 PrintIndent(); 6424 PrintIndent();
5963 trace_.Add("predecessors"); 6425 trace_.Add("predecessors");
5964 for (int j = 0; j < current->predecessors()->length(); ++j) { 6426 for (int j = 0; j < current->predecessors()->length(); ++j) {
5965 trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id()); 6427 trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id());
5966 } 6428 }
5967 trace_.Add("\n"); 6429 trace_.Add("\n");
5968 } else { 6430 } else {
5969 PrintEmptyProperty("predecessors"); 6431 PrintEmptyProperty("predecessors");
5970 } 6432 }
5971 6433
5972 if (current->end() == NULL || current->end()->FirstSuccessor() == NULL) { 6434 if (current->end()->SuccessorCount() == 0) {
5973 PrintEmptyProperty("successors"); 6435 PrintEmptyProperty("successors");
5974 } else if (current->end()->SecondSuccessor() == NULL) { 6436 } else {
5975 PrintBlockProperty("successors", 6437 PrintIndent();
5976 current->end()->FirstSuccessor()->block_id()); 6438 trace_.Add("successors");
5977 } else { 6439 for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) {
5978 PrintBlockProperty("successors", 6440 trace_.Add(" \"B%d\"", it.Current()->block_id());
5979 current->end()->FirstSuccessor()->block_id(), 6441 }
5980 current->end()->SecondSuccessor()->block_id()); 6442 trace_.Add("\n");
5981 } 6443 }
5982 6444
5983 PrintEmptyProperty("xhandlers"); 6445 PrintEmptyProperty("xhandlers");
5984 PrintEmptyProperty("flags"); 6446 PrintEmptyProperty("flags");
5985 6447
5986 if (current->dominator() != NULL) { 6448 if (current->dominator() != NULL) {
5987 PrintBlockProperty("dominator", current->dominator()->block_id()); 6449 PrintBlockProperty("dominator", current->dominator()->block_id());
5988 } 6450 }
5989 6451
5990 if (chunk != NULL) { 6452 if (chunk != NULL) {
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
6230 } 6692 }
6231 } 6693 }
6232 6694
6233 #ifdef DEBUG 6695 #ifdef DEBUG
6234 if (graph_ != NULL) graph_->Verify(); 6696 if (graph_ != NULL) graph_->Verify();
6235 if (allocator_ != NULL) allocator_->Verify(); 6697 if (allocator_ != NULL) allocator_->Verify();
6236 #endif 6698 #endif
6237 } 6699 }
6238 6700
6239 } } // namespace v8::internal 6701 } } // 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