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

Side by Side Diff: src/hydrogen.cc

Issue 6529032: Merge 6168:6800 from bleeding_edge to experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 10 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 2010 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
11 // with the distribution. 11 // with the distribution.
(...skipping 15 matching lines...) Expand all
27 27
28 #include "hydrogen.h" 28 #include "hydrogen.h"
29 29
30 #include "codegen.h" 30 #include "codegen.h"
31 #include "data-flow.h" 31 #include "data-flow.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 "scopes.h" 36 #include "scopes.h"
37 #include "stub-cache.h"
37 38
38 #if V8_TARGET_ARCH_IA32 39 #if V8_TARGET_ARCH_IA32
39 #include "ia32/lithium-codegen-ia32.h" 40 #include "ia32/lithium-codegen-ia32.h"
40 #elif V8_TARGET_ARCH_X64 41 #elif V8_TARGET_ARCH_X64
41 #include "x64/lithium-codegen-x64.h" 42 #include "x64/lithium-codegen-x64.h"
42 #elif V8_TARGET_ARCH_ARM 43 #elif V8_TARGET_ARCH_ARM
43 #include "arm/lithium-codegen-arm.h" 44 #include "arm/lithium-codegen-arm.h"
44 #else 45 #else
45 #error Unsupported target architecture. 46 #error Unsupported target architecture.
46 #endif 47 #endif
(...skipping 10 matching lines...) Expand all
57 end_(NULL), 58 end_(NULL),
58 loop_information_(NULL), 59 loop_information_(NULL),
59 predecessors_(2), 60 predecessors_(2),
60 dominator_(NULL), 61 dominator_(NULL),
61 dominated_blocks_(4), 62 dominated_blocks_(4),
62 last_environment_(NULL), 63 last_environment_(NULL),
63 argument_count_(-1), 64 argument_count_(-1),
64 first_instruction_index_(-1), 65 first_instruction_index_(-1),
65 last_instruction_index_(-1), 66 last_instruction_index_(-1),
66 deleted_phis_(4), 67 deleted_phis_(4),
68 parent_loop_header_(NULL),
67 is_inline_return_target_(false) { 69 is_inline_return_target_(false) {
68 } 70 }
69 71
70 72
71 void HBasicBlock::AttachLoopInformation() { 73 void HBasicBlock::AttachLoopInformation() {
72 ASSERT(!IsLoopHeader()); 74 ASSERT(!IsLoopHeader());
73 loop_information_ = new HLoopInformation(this); 75 loop_information_ = new HLoopInformation(this);
74 } 76 }
75 77
76 78
(...skipping 20 matching lines...) Expand all
97 } 99 }
98 100
99 101
100 void HBasicBlock::AddInstruction(HInstruction* instr) { 102 void HBasicBlock::AddInstruction(HInstruction* instr) {
101 ASSERT(!IsStartBlock() || !IsFinished()); 103 ASSERT(!IsStartBlock() || !IsFinished());
102 ASSERT(!instr->IsLinked()); 104 ASSERT(!instr->IsLinked());
103 ASSERT(!IsFinished()); 105 ASSERT(!IsFinished());
104 if (first_ == NULL) { 106 if (first_ == NULL) {
105 HBlockEntry* entry = new HBlockEntry(); 107 HBlockEntry* entry = new HBlockEntry();
106 entry->InitializeAsFirst(this); 108 entry->InitializeAsFirst(this);
107 first_ = entry; 109 first_ = last_ = entry;
108 } 110 }
109 instr->InsertAfter(GetLastInstruction()); 111 instr->InsertAfter(last_);
110 } 112 last_ = instr;
111
112
113 HInstruction* HBasicBlock::GetLastInstruction() {
114 if (end_ != NULL) return end_->previous();
115 if (first_ == NULL) return NULL;
116 if (last_ == NULL) last_ = first_;
117 while (last_->next() != NULL) last_ = last_->next();
118 return last_;
119 } 113 }
120 114
121 115
122 HSimulate* HBasicBlock::CreateSimulate(int id) { 116 HSimulate* HBasicBlock::CreateSimulate(int id) {
123 ASSERT(HasEnvironment()); 117 ASSERT(HasEnvironment());
124 HEnvironment* environment = last_environment(); 118 HEnvironment* environment = last_environment();
125 ASSERT(id == AstNode::kNoNumber || 119 ASSERT(id == AstNode::kNoNumber ||
126 environment->closure()->shared()->VerifyBailoutId(id)); 120 environment->closure()->shared()->VerifyBailoutId(id));
127 121
128 int push_count = environment->push_count(); 122 int push_count = environment->push_count();
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 UpdateEnvironment(env); 163 UpdateEnvironment(env);
170 } 164 }
171 165
172 166
173 void HBasicBlock::SetJoinId(int id) { 167 void HBasicBlock::SetJoinId(int id) {
174 int length = predecessors_.length(); 168 int length = predecessors_.length();
175 ASSERT(length > 0); 169 ASSERT(length > 0);
176 for (int i = 0; i < length; i++) { 170 for (int i = 0; i < length; i++) {
177 HBasicBlock* predecessor = predecessors_[i]; 171 HBasicBlock* predecessor = predecessors_[i];
178 ASSERT(predecessor->end()->IsGoto()); 172 ASSERT(predecessor->end()->IsGoto());
179 HSimulate* simulate = HSimulate::cast(predecessor->GetLastInstruction()); 173 HSimulate* simulate = HSimulate::cast(predecessor->end()->previous());
180 // We only need to verify the ID once. 174 // We only need to verify the ID once.
181 ASSERT(i != 0 || 175 ASSERT(i != 0 ||
182 predecessor->last_environment()->closure()->shared() 176 predecessor->last_environment()->closure()->shared()
183 ->VerifyBailoutId(id)); 177 ->VerifyBailoutId(id));
184 simulate->set_ast_id(id); 178 simulate->set_ast_id(id);
185 } 179 }
186 } 180 }
187 181
188 182
189 bool HBasicBlock::Dominates(HBasicBlock* other) const { 183 bool HBasicBlock::Dominates(HBasicBlock* other) const {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 UNREACHABLE(); 279 UNREACHABLE();
286 return -1; 280 return -1;
287 } 281 }
288 282
289 283
290 #ifdef DEBUG 284 #ifdef DEBUG
291 void HBasicBlock::Verify() { 285 void HBasicBlock::Verify() {
292 // Check that every block is finished. 286 // Check that every block is finished.
293 ASSERT(IsFinished()); 287 ASSERT(IsFinished());
294 ASSERT(block_id() >= 0); 288 ASSERT(block_id() >= 0);
295
296 // Verify that all blocks targetting a branch target, have the same boolean
297 // value on top of their expression stack.
298 if (!cond().is_null()) {
299 ASSERT(predecessors()->length() > 0);
300 for (int i = 1; i < predecessors()->length(); i++) {
301 HBasicBlock* pred = predecessors()->at(i);
302 HValue* top = pred->last_environment()->Top();
303 ASSERT(top->IsConstant());
304 Object* a = *HConstant::cast(top)->handle();
305 Object* b = *cond();
306 ASSERT(a == b);
307 }
308 }
309 } 289 }
310 #endif 290 #endif
311 291
312 292
313 void HLoopInformation::RegisterBackEdge(HBasicBlock* block) { 293 void HLoopInformation::RegisterBackEdge(HBasicBlock* block) {
314 this->back_edges_.Add(block); 294 this->back_edges_.Add(block);
315 AddBlock(block); 295 AddBlock(block);
316 } 296 }
317 297
318 298
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 } 477 }
498 478
499 479
500 HConstant* HGraph::GetConstantFalse() { 480 HConstant* HGraph::GetConstantFalse() {
501 return GetConstant(&constant_false_, Heap::false_value()); 481 return GetConstant(&constant_false_, Heap::false_value());
502 } 482 }
503 483
504 484
505 void HSubgraph::AppendOptional(HSubgraph* graph, 485 void HSubgraph::AppendOptional(HSubgraph* graph,
506 bool on_true_branch, 486 bool on_true_branch,
507 HValue* boolean_value) { 487 HValue* value) {
508 ASSERT(HasExit() && graph->HasExit()); 488 ASSERT(HasExit() && graph->HasExit());
509 HBasicBlock* other_block = graph_->CreateBasicBlock(); 489 HBasicBlock* other_block = graph_->CreateBasicBlock();
510 HBasicBlock* join_block = graph_->CreateBasicBlock(); 490 HBasicBlock* join_block = graph_->CreateBasicBlock();
511 491
512 HBasicBlock* true_branch = other_block; 492 HTest* test = on_true_branch
513 HBasicBlock* false_branch = graph->entry_block(); 493 ? new HTest(value, graph->entry_block(), other_block)
514 if (on_true_branch) { 494 : new HTest(value, other_block, graph->entry_block());
515 true_branch = graph->entry_block(); 495 exit_block_->Finish(test);
516 false_branch = other_block;
517 }
518
519 exit_block_->Finish(new HBranch(true_branch, false_branch, boolean_value));
520 other_block->Goto(join_block); 496 other_block->Goto(join_block);
521 graph->exit_block()->Goto(join_block); 497 graph->exit_block()->Goto(join_block);
522 exit_block_ = join_block; 498 exit_block_ = join_block;
523 } 499 }
524 500
525 501
526 void HSubgraph::AppendJoin(HSubgraph* then_graph, 502 void HSubgraph::AppendJoin(HSubgraph* then_graph,
527 HSubgraph* else_graph, 503 HSubgraph* else_graph,
528 AstNode* node) { 504 AstNode* node) {
529 if (then_graph->HasExit() && else_graph->HasExit()) { 505 if (then_graph->HasExit() && else_graph->HasExit()) {
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
680 next_block_id_(0), 656 next_block_id_(0),
681 info_(info), 657 info_(info),
682 blocks_(8), 658 blocks_(8),
683 values_(16), 659 values_(16),
684 phi_list_(NULL) { 660 phi_list_(NULL) {
685 start_environment_ = new HEnvironment(NULL, info->scope(), info->closure()); 661 start_environment_ = new HEnvironment(NULL, info->scope(), info->closure());
686 start_environment_->set_ast_id(info->function()->id()); 662 start_environment_->set_ast_id(info->function()->id());
687 } 663 }
688 664
689 665
666 bool HGraph::AllowCodeMotion() const {
667 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount;
668 }
669
670
690 Handle<Code> HGraph::Compile() { 671 Handle<Code> HGraph::Compile() {
691 int values = GetMaximumValueID(); 672 int values = GetMaximumValueID();
692 if (values > LAllocator::max_initial_value_ids()) { 673 if (values > LAllocator::max_initial_value_ids()) {
693 if (FLAG_trace_bailout) PrintF("Function is too big\n"); 674 if (FLAG_trace_bailout) PrintF("Function is too big\n");
694 return Handle<Code>::null(); 675 return Handle<Code>::null();
695 } 676 }
696 677
697 LAllocator allocator(values, this); 678 LAllocator allocator(values, this);
698 LChunkBuilder builder(this, &allocator); 679 LChunkBuilder builder(this, &allocator);
699 LChunk* chunk = builder.Build(); 680 LChunk* chunk = builder.Build();
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
861 } 842 }
862 } 843 }
863 // Replace the uses and add phis modified to the work list. 844 // Replace the uses and add phis modified to the work list.
864 for (int i = 0; i < uses_to_replace.length(); ++i) { 845 for (int i = 0; i < uses_to_replace.length(); ++i) {
865 HValue* use = uses_to_replace[i]; 846 HValue* use = uses_to_replace[i];
866 phi->ReplaceAtUse(use, value); 847 phi->ReplaceAtUse(use, value);
867 if (use->IsPhi()) worklist.Add(HPhi::cast(use)); 848 if (use->IsPhi()) worklist.Add(HPhi::cast(use));
868 } 849 }
869 uses_to_replace.Rewind(0); 850 uses_to_replace.Rewind(0);
870 block->RemovePhi(phi); 851 block->RemovePhi(phi);
871 } else if (phi->HasNoUses() && 852 } else if (FLAG_eliminate_dead_phis && phi->HasNoUses() &&
872 !phi->HasReceiverOperand() && 853 !phi->IsReceiver()) {
873 FLAG_eliminate_dead_phis) { 854 // We can't eliminate phis in the receiver position in the environment
874 // We can't eliminate phis that have the receiver as an operand 855 // because in case of throwing an error we need this value to
875 // because in case of throwing an error we need the correct 856 // construct a stack trace.
876 // receiver value in the environment to construct a corrent
877 // stack trace.
878 block->RemovePhi(phi); 857 block->RemovePhi(phi);
879 block->RecordDeletedPhi(phi->merged_index()); 858 block->RecordDeletedPhi(phi->merged_index());
880 } 859 }
881 } 860 }
882 } 861 }
883 862
884 863
885 bool HGraph::CollectPhis() { 864 bool HGraph::CollectPhis() {
886 const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); 865 const ZoneList<HBasicBlock*>* blocks = graph_->blocks();
887 phi_list_ = new ZoneList<HPhi*>(blocks->length()); 866 phi_list_ = new ZoneList<HPhi*>(blocks->length());
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
922 901
923 class HRangeAnalysis BASE_EMBEDDED { 902 class HRangeAnalysis BASE_EMBEDDED {
924 public: 903 public:
925 explicit HRangeAnalysis(HGraph* graph) : graph_(graph), changed_ranges_(16) {} 904 explicit HRangeAnalysis(HGraph* graph) : graph_(graph), changed_ranges_(16) {}
926 905
927 void Analyze(); 906 void Analyze();
928 907
929 private: 908 private:
930 void TraceRange(const char* msg, ...); 909 void TraceRange(const char* msg, ...);
931 void Analyze(HBasicBlock* block); 910 void Analyze(HBasicBlock* block);
932 void InferControlFlowRange(HBranch* branch, HBasicBlock* dest); 911 void InferControlFlowRange(HTest* test, HBasicBlock* dest);
933 void InferControlFlowRange(Token::Value op, HValue* value, HValue* other); 912 void InferControlFlowRange(Token::Value op, HValue* value, HValue* other);
934 void InferPhiRange(HPhi* phi); 913 void InferPhiRange(HPhi* phi);
935 void InferRange(HValue* value); 914 void InferRange(HValue* value);
936 void RollBackTo(int index); 915 void RollBackTo(int index);
937 void AddRange(HValue* value, Range* range); 916 void AddRange(HValue* value, Range* range);
938 917
939 HGraph* graph_; 918 HGraph* graph_;
940 ZoneList<HValue*> changed_ranges_; 919 ZoneList<HValue*> changed_ranges_;
941 }; 920 };
942 921
(...skipping 15 matching lines...) Expand all
958 937
959 938
960 void HRangeAnalysis::Analyze(HBasicBlock* block) { 939 void HRangeAnalysis::Analyze(HBasicBlock* block) {
961 TraceRange("Analyzing block B%d\n", block->block_id()); 940 TraceRange("Analyzing block B%d\n", block->block_id());
962 941
963 int last_changed_range = changed_ranges_.length() - 1; 942 int last_changed_range = changed_ranges_.length() - 1;
964 943
965 // Infer range based on control flow. 944 // Infer range based on control flow.
966 if (block->predecessors()->length() == 1) { 945 if (block->predecessors()->length() == 1) {
967 HBasicBlock* pred = block->predecessors()->first(); 946 HBasicBlock* pred = block->predecessors()->first();
968 if (pred->end()->IsBranch()) { 947 if (pred->end()->IsTest()) {
969 InferControlFlowRange(HBranch::cast(pred->end()), block); 948 InferControlFlowRange(HTest::cast(pred->end()), block);
970 } 949 }
971 } 950 }
972 951
973 // Process phi instructions. 952 // Process phi instructions.
974 for (int i = 0; i < block->phis()->length(); ++i) { 953 for (int i = 0; i < block->phis()->length(); ++i) {
975 HPhi* phi = block->phis()->at(i); 954 HPhi* phi = block->phis()->at(i);
976 InferPhiRange(phi); 955 InferPhiRange(phi);
977 } 956 }
978 957
979 // Go through all instructions of the current block. 958 // Go through all instructions of the current block.
980 HInstruction* instr = block->first(); 959 HInstruction* instr = block->first();
981 while (instr != block->end()) { 960 while (instr != block->end()) {
982 InferRange(instr); 961 InferRange(instr);
983 instr = instr->next(); 962 instr = instr->next();
984 } 963 }
985 964
986 // Continue analysis in all dominated blocks. 965 // Continue analysis in all dominated blocks.
987 for (int i = 0; i < block->dominated_blocks()->length(); ++i) { 966 for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
988 Analyze(block->dominated_blocks()->at(i)); 967 Analyze(block->dominated_blocks()->at(i));
989 } 968 }
990 969
991 RollBackTo(last_changed_range); 970 RollBackTo(last_changed_range);
992 } 971 }
993 972
994 973
995 void HRangeAnalysis::InferControlFlowRange(HBranch* branch, HBasicBlock* dest) { 974 void HRangeAnalysis::InferControlFlowRange(HTest* test, HBasicBlock* dest) {
996 ASSERT(branch->FirstSuccessor() == dest || branch->SecondSuccessor() == dest); 975 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest));
997 ASSERT(branch->FirstSuccessor() != dest || branch->SecondSuccessor() != dest); 976 if (test->value()->IsCompare()) {
998 977 HCompare* compare = HCompare::cast(test->value());
999 if (branch->value()->IsCompare()) {
1000 HCompare* compare = HCompare::cast(branch->value());
1001 Token::Value op = compare->token(); 978 Token::Value op = compare->token();
1002 if (branch->SecondSuccessor() == dest) { 979 if (test->SecondSuccessor() == dest) {
1003 op = Token::NegateCompareOp(op); 980 op = Token::NegateCompareOp(op);
1004 } 981 }
1005 Token::Value inverted_op = Token::InvertCompareOp(op); 982 Token::Value inverted_op = Token::InvertCompareOp(op);
1006 InferControlFlowRange(op, compare->left(), compare->right()); 983 InferControlFlowRange(op, compare->left(), compare->right());
1007 InferControlFlowRange(inverted_op, compare->right(), compare->left()); 984 InferControlFlowRange(inverted_op, compare->right(), compare->left());
1008 } 985 }
1009 } 986 }
1010 987
1011 988
1012 // We know that value [op] other. Use this information to update the range on 989 // We know that value [op] other. Use this information to update the range on
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after
1439 TraceGVN("Found loop invariant instruction %d\n", instr->id()); 1416 TraceGVN("Found loop invariant instruction %d\n", instr->id());
1440 // Move the instruction out of the loop. 1417 // Move the instruction out of the loop.
1441 instr->Unlink(); 1418 instr->Unlink();
1442 instr->InsertBefore(pre_header->end()); 1419 instr->InsertBefore(pre_header->end());
1443 } 1420 }
1444 } 1421 }
1445 instr = next; 1422 instr = next;
1446 } 1423 }
1447 } 1424 }
1448 1425
1449 // Only move instructions that postdominate the loop header (i.e. are 1426
1450 // always executed inside the loop). This is to avoid unnecessary
1451 // deoptimizations assuming the loop is executed at least once.
1452 // TODO(fschneider): Better type feedback should give us information
1453 // about code that was never executed.
1454 bool HGlobalValueNumberer::ShouldMove(HInstruction* instr, 1427 bool HGlobalValueNumberer::ShouldMove(HInstruction* instr,
1455 HBasicBlock* loop_header) { 1428 HBasicBlock* loop_header) {
1456 if (!instr->IsChange() && 1429 // If we've disabled code motion, don't move any instructions.
1457 FLAG_aggressive_loop_invariant_motion) return true; 1430 if (!graph_->AllowCodeMotion()) return false;
1431
1432 // If --aggressive-loop-invariant-motion, move everything except change
1433 // instructions.
1434 if (FLAG_aggressive_loop_invariant_motion && !instr->IsChange()) {
1435 return true;
1436 }
1437
1438 // Otherwise only move instructions that postdominate the loop header
1439 // (i.e. are always executed inside the loop). This is to avoid
1440 // unnecessary deoptimizations assuming the loop is executed at least
1441 // once. TODO(fschneider): Better type feedback should give us
1442 // information about code that was never executed.
1458 HBasicBlock* block = instr->block(); 1443 HBasicBlock* block = instr->block();
1459 bool result = true; 1444 bool result = true;
1460 if (block != loop_header) { 1445 if (block != loop_header) {
1461 for (int i = 1; i < loop_header->predecessors()->length(); ++i) { 1446 for (int i = 1; i < loop_header->predecessors()->length(); ++i) {
1462 bool found = false; 1447 bool found = false;
1463 HBasicBlock* pred = loop_header->predecessors()->at(i); 1448 HBasicBlock* pred = loop_header->predecessors()->at(i);
1464 while (pred != loop_header) { 1449 while (pred != loop_header) {
1465 if (pred == block) found = true; 1450 if (pred == block) found = true;
1466 pred = pred->dominator(); 1451 pred = pred->dominator();
1467 } 1452 }
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
1798 1783
1799 current = current->EnsureAndPropagateNotMinusZero(visited); 1784 current = current->EnsureAndPropagateNotMinusZero(visited);
1800 } 1785 }
1801 } 1786 }
1802 1787
1803 1788
1804 void HGraph::InsertRepresentationChangeForUse(HValue* value, 1789 void HGraph::InsertRepresentationChangeForUse(HValue* value,
1805 HValue* use, 1790 HValue* use,
1806 Representation to, 1791 Representation to,
1807 bool is_truncating) { 1792 bool is_truncating) {
1808 // Propagate flags for negative zero checks upwards from conversions
1809 // int32-to-tagged and int32-to-double.
1810 Representation from = value->representation();
1811 if (from.IsInteger32()) {
1812 ASSERT(to.IsTagged() || to.IsDouble());
1813 BitVector visited(GetMaximumValueID());
1814 PropagateMinusZeroChecks(value, &visited);
1815 }
1816
1817 // Insert the representation change right before its use. For phi-uses we 1793 // Insert the representation change right before its use. For phi-uses we
1818 // insert at the end of the corresponding predecessor. 1794 // insert at the end of the corresponding predecessor.
1819 HBasicBlock* insert_block = use->block(); 1795 HInstruction* next = NULL;
1820 if (use->IsPhi()) { 1796 if (use->IsPhi()) {
1821 int index = 0; 1797 int index = 0;
1822 while (use->OperandAt(index) != value) ++index; 1798 while (use->OperandAt(index) != value) ++index;
1823 insert_block = insert_block->predecessors()->at(index); 1799 next = use->block()->predecessors()->at(index)->end();
1800 } else {
1801 next = HInstruction::cast(use);
1824 } 1802 }
1825 1803
1826 HInstruction* next = (insert_block == use->block())
1827 ? HInstruction::cast(use)
1828 : insert_block->end();
1829
1830 // For constants we try to make the representation change at compile 1804 // For constants we try to make the representation change at compile
1831 // time. When a representation change is not possible without loss of 1805 // time. When a representation change is not possible without loss of
1832 // information we treat constants like normal instructions and insert the 1806 // information we treat constants like normal instructions and insert the
1833 // change instructions for them. 1807 // change instructions for them.
1834 HInstruction* new_value = NULL; 1808 HInstruction* new_value = NULL;
1835 if (value->IsConstant()) { 1809 if (value->IsConstant()) {
1836 HConstant* constant = HConstant::cast(value); 1810 HConstant* constant = HConstant::cast(value);
1837 // Try to create a new copy of the constant with the new representation. 1811 // Try to create a new copy of the constant with the new representation.
1838 new_value = is_truncating 1812 new_value = is_truncating
1839 ? constant->CopyToTruncatedInt32() 1813 ? constant->CopyToTruncatedInt32()
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1969 // Process normal instructions. 1943 // Process normal instructions.
1970 HInstruction* current = blocks_[i]->first(); 1944 HInstruction* current = blocks_[i]->first();
1971 while (current != NULL) { 1945 while (current != NULL) {
1972 InsertRepresentationChanges(current); 1946 InsertRepresentationChanges(current);
1973 current = current->next(); 1947 current = current->next();
1974 } 1948 }
1975 } 1949 }
1976 } 1950 }
1977 1951
1978 1952
1953 void HGraph::ComputeMinusZeroChecks() {
1954 BitVector visited(GetMaximumValueID());
1955 for (int i = 0; i < blocks_.length(); ++i) {
1956 for (HInstruction* current = blocks_[i]->first();
1957 current != NULL;
1958 current = current->next()) {
1959 if (current->IsChange()) {
1960 HChange* change = HChange::cast(current);
1961 // Propagate flags for negative zero checks upwards from conversions
1962 // int32-to-tagged and int32-to-double.
1963 Representation from = change->value()->representation();
1964 ASSERT(from.Equals(change->from()));
1965 if (from.IsInteger32()) {
1966 ASSERT(change->to().IsTagged() || change->to().IsDouble());
1967 ASSERT(visited.IsEmpty());
1968 PropagateMinusZeroChecks(change->value(), &visited);
1969 visited.Clear();
1970 }
1971 }
1972 }
1973 }
1974 }
1975
1976
1979 // Implementation of utility classes to represent an expression's context in 1977 // Implementation of utility classes to represent an expression's context in
1980 // the AST. 1978 // the AST.
1981 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) 1979 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind)
1982 : owner_(owner), kind_(kind), outer_(owner->ast_context()) { 1980 : owner_(owner), kind_(kind), outer_(owner->ast_context()) {
1983 owner->set_ast_context(this); // Push. 1981 owner->set_ast_context(this); // Push.
1984 #ifdef DEBUG 1982 #ifdef DEBUG
1985 original_length_ = owner->environment()->length(); 1983 original_length_ = owner->environment()->length();
1986 #endif 1984 #endif
1987 } 1985 }
1988 1986
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2051 2049
2052 2050
2053 void TestContext::BuildBranch(HValue* value) { 2051 void TestContext::BuildBranch(HValue* value) {
2054 // We expect the graph to be in edge-split form: there is no edge that 2052 // We expect the graph to be in edge-split form: there is no edge that
2055 // connects a branch node to a join node. We conservatively ensure that 2053 // connects a branch node to a join node. We conservatively ensure that
2056 // property by always adding an empty block on the outgoing edges of this 2054 // property by always adding an empty block on the outgoing edges of this
2057 // branch. 2055 // branch.
2058 HGraphBuilder* builder = owner(); 2056 HGraphBuilder* builder = owner();
2059 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); 2057 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
2060 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); 2058 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
2061 HBranch* branch = new HBranch(empty_true, empty_false, value); 2059 HTest* test = new HTest(value, empty_true, empty_false);
2062 builder->CurrentBlock()->Finish(branch); 2060 builder->CurrentBlock()->Finish(test);
2063 2061
2064 HValue* const no_return_value = NULL; 2062 HValue* const no_return_value = NULL;
2065 HBasicBlock* true_target = if_true(); 2063 HBasicBlock* true_target = if_true();
2066 if (true_target->IsInlineReturnTarget()) { 2064 if (true_target->IsInlineReturnTarget()) {
2067 empty_true->AddLeaveInlined(no_return_value, true_target); 2065 empty_true->AddLeaveInlined(no_return_value, true_target);
2068 } else { 2066 } else {
2069 empty_true->Goto(true_target); 2067 empty_true->Goto(true_target);
2070 } 2068 }
2071 2069
2072 HBasicBlock* false_target = if_false(); 2070 HBasicBlock* false_target = if_false();
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
2167 2165
2168 2166
2169 void HGraphBuilder::VisitForControl(Expression* expr, 2167 void HGraphBuilder::VisitForControl(Expression* expr,
2170 HBasicBlock* true_block, 2168 HBasicBlock* true_block,
2171 HBasicBlock* false_block) { 2169 HBasicBlock* false_block) {
2172 TestContext for_test(this, true_block, false_block); 2170 TestContext for_test(this, true_block, false_block);
2173 Visit(expr); 2171 Visit(expr);
2174 } 2172 }
2175 2173
2176 2174
2177 HValue* HGraphBuilder::VisitArgument(Expression* expr) { 2175 void HGraphBuilder::VisitArgument(Expression* expr) {
2178 VisitForValue(expr); 2176 VisitForValue(expr);
2179 if (HasStackOverflow() || !subgraph()->HasExit()) return NULL;
2180 return environment()->Top();
2181 } 2177 }
2182 2178
2183 2179
2184 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { 2180 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) {
2185 for (int i = 0; i < arguments->length(); i++) { 2181 for (int i = 0; i < arguments->length(); i++) {
2186 VisitArgument(arguments->at(i)); 2182 VisitArgument(arguments->at(i));
2187 if (HasStackOverflow() || !current_subgraph_->HasExit()) return; 2183 if (HasStackOverflow() || !current_subgraph_->HasExit()) return;
2188 } 2184 }
2189 } 2185 }
2190 2186
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2228 rep.Analyze(); 2224 rep.Analyze();
2229 2225
2230 if (FLAG_use_range) { 2226 if (FLAG_use_range) {
2231 HRangeAnalysis rangeAnalysis(graph_); 2227 HRangeAnalysis rangeAnalysis(graph_);
2232 rangeAnalysis.Analyze(); 2228 rangeAnalysis.Analyze();
2233 } 2229 }
2234 2230
2235 graph_->InitializeInferredTypes(); 2231 graph_->InitializeInferredTypes();
2236 graph_->Canonicalize(); 2232 graph_->Canonicalize();
2237 graph_->InsertRepresentationChanges(); 2233 graph_->InsertRepresentationChanges();
2234 graph_->ComputeMinusZeroChecks();
2238 2235
2239 // Eliminate redundant stack checks on backwards branches. 2236 // Eliminate redundant stack checks on backwards branches.
2240 HStackCheckEliminator sce(graph_); 2237 HStackCheckEliminator sce(graph_);
2241 sce.Process(); 2238 sce.Process();
2242 2239
2243 // Perform common subexpression elimination and loop-invariant code motion. 2240 // Perform common subexpression elimination and loop-invariant code motion.
2244 if (FLAG_use_gvn) { 2241 if (FLAG_use_gvn) {
2245 HPhase phase("Global value numbering", graph_); 2242 HPhase phase("Global value numbering", graph_);
2246 HGlobalValueNumberer gvn(graph_); 2243 HGlobalValueNumberer gvn(graph_);
2247 gvn.Analyze(); 2244 gvn.Analyze();
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2288 current_subgraph_->exit_block()->AddPhi(instr); 2285 current_subgraph_->exit_block()->AddPhi(instr);
2289 } 2286 }
2290 2287
2291 2288
2292 void HGraphBuilder::PushAndAdd(HInstruction* instr) { 2289 void HGraphBuilder::PushAndAdd(HInstruction* instr) {
2293 Push(instr); 2290 Push(instr);
2294 AddInstruction(instr); 2291 AddInstruction(instr);
2295 } 2292 }
2296 2293
2297 2294
2298 void HGraphBuilder::PushArgumentsForStubCall(int argument_count) { 2295 void HGraphBuilder::PreProcessCall(HCall* call) {
2299 const int kMaxStubArguments = 4; 2296 int count = call->argument_count();
2300 ASSERT_GE(kMaxStubArguments, argument_count); 2297 ZoneList<HValue*> arguments(count);
2301 // Push the arguments on the stack. 2298 for (int i = 0; i < count; ++i) {
2302 HValue* arguments[kMaxStubArguments]; 2299 arguments.Add(Pop());
2303 for (int i = argument_count - 1; i >= 0; i--) {
2304 arguments[i] = Pop();
2305 } 2300 }
2306 for (int i = 0; i < argument_count; i++) { 2301
2307 AddInstruction(new HPushArgument(arguments[i])); 2302 while (!arguments.is_empty()) {
2303 AddInstruction(new HPushArgument(arguments.RemoveLast()));
2308 } 2304 }
2309 } 2305 }
2310 2306
2311 2307
2312 void HGraphBuilder::ProcessCall(HCall* call) {
2313 for (int i = call->argument_count() - 1; i >= 0; --i) {
2314 HValue* value = Pop();
2315 HPushArgument* push = new HPushArgument(value);
2316 call->SetArgumentAt(i, push);
2317 }
2318
2319 for (int i = 0; i < call->argument_count(); ++i) {
2320 AddInstruction(call->PushArgumentAt(i));
2321 }
2322 }
2323
2324
2325 void HGraphBuilder::SetupScope(Scope* scope) { 2308 void HGraphBuilder::SetupScope(Scope* scope) {
2326 // We don't yet handle the function name for named function expressions. 2309 // We don't yet handle the function name for named function expressions.
2327 if (scope->function() != NULL) BAILOUT("named function expression"); 2310 if (scope->function() != NULL) BAILOUT("named function expression");
2328 2311
2329 // We can't handle heap-allocated locals. 2312 // We can't handle heap-allocated locals.
2330 if (scope->num_heap_slots() > 0) BAILOUT("heap allocated locals"); 2313 if (scope->num_heap_slots() > 0) BAILOUT("heap allocated locals");
2331 2314
2332 HConstant* undefined_constant = 2315 HConstant* undefined_constant =
2333 new HConstant(Factory::undefined_value(), Representation::Tagged()); 2316 new HConstant(Factory::undefined_value(), Representation::Tagged());
2334 AddInstruction(undefined_constant); 2317 AddInstruction(undefined_constant);
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
2580 CaseClause* clause = clauses->at(i); 2563 CaseClause* clause = clauses->at(i);
2581 if (clause->is_default()) continue; 2564 if (clause->is_default()) continue;
2582 2565
2583 // Finish the previous graph by connecting it to the current. 2566 // Finish the previous graph by connecting it to the current.
2584 HSubgraph* subgraph = compare_graphs.at(i); 2567 HSubgraph* subgraph = compare_graphs.at(i);
2585 if (prev_compare_inst == NULL) { 2568 if (prev_compare_inst == NULL) {
2586 ASSERT(prev_graph == current_subgraph_); 2569 ASSERT(prev_graph == current_subgraph_);
2587 prev_graph->exit_block()->Finish(new HGoto(subgraph->entry_block())); 2570 prev_graph->exit_block()->Finish(new HGoto(subgraph->entry_block()));
2588 } else { 2571 } else {
2589 HBasicBlock* empty = graph()->CreateBasicBlock(); 2572 HBasicBlock* empty = graph()->CreateBasicBlock();
2590 prev_graph->exit_block()->Finish(new HBranch(empty, 2573 prev_graph->exit_block()->Finish(new HTest(prev_compare_inst,
2591 subgraph->entry_block(), 2574 empty,
2592 prev_compare_inst)); 2575 subgraph->entry_block()));
2593 } 2576 }
2594 2577
2595 // Build instructions for current subgraph. 2578 // Build instructions for current subgraph.
2596 ASSERT(clause->IsSmiCompare()); 2579 ASSERT(clause->IsSmiCompare());
2597 prev_compare_inst = BuildSwitchCompare(subgraph, switch_value, clause); 2580 prev_compare_inst = BuildSwitchCompare(subgraph, switch_value, clause);
2598 if (HasStackOverflow()) return; 2581 if (HasStackOverflow()) return;
2599 2582
2600 prev_graph = subgraph; 2583 prev_graph = subgraph;
2601 } 2584 }
2602 2585
2603 // Finish last comparison if there was at least one comparison. 2586 // Finish last comparison if there was at least one comparison.
2604 // last_false_block is the (empty) false-block of the last comparison. If 2587 // last_false_block is the (empty) false-block of the last comparison. If
2605 // there are no comparisons at all (a single default clause), it is just 2588 // there are no comparisons at all (a single default clause), it is just
2606 // the last block of the current subgraph. 2589 // the last block of the current subgraph.
2607 HBasicBlock* last_false_block = current_subgraph_->exit_block(); 2590 HBasicBlock* last_false_block = current_subgraph_->exit_block();
2608 if (prev_graph != current_subgraph_) { 2591 if (prev_graph != current_subgraph_) {
2609 last_false_block = graph()->CreateBasicBlock(); 2592 last_false_block = graph()->CreateBasicBlock();
2610 HBasicBlock* empty = graph()->CreateBasicBlock(); 2593 HBasicBlock* empty = graph()->CreateBasicBlock();
2611 prev_graph->exit_block()->Finish(new HBranch(empty, 2594 prev_graph->exit_block()->Finish(new HTest(prev_compare_inst,
2612 last_false_block, 2595 empty,
2613 prev_compare_inst)); 2596 last_false_block));
2614 } 2597 }
2615 2598
2616 // If we have a non-smi compare clause, we deoptimize after trying 2599 // If we have a non-smi compare clause, we deoptimize after trying
2617 // all the previous compares. 2600 // all the previous compares.
2618 if (num_smi_clauses < num_clauses) { 2601 if (num_smi_clauses < num_clauses) {
2619 last_false_block->Finish(new HDeoptimize); 2602 last_false_block->Finish(new HDeoptimize);
2620 } 2603 }
2621 2604
2622 // Build statement blocks, connect them to their comparison block and 2605 // Build statement blocks, connect them to their comparison block and
2623 // to the previous statement block, if there is a fall-through. 2606 // to the previous statement block, if there is a fall-through.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2686 return statement->OsrEntryId() == info()->osr_ast_id(); 2669 return statement->OsrEntryId() == info()->osr_ast_id();
2687 } 2670 }
2688 2671
2689 2672
2690 void HSubgraph::PreProcessOsrEntry(IterationStatement* statement) { 2673 void HSubgraph::PreProcessOsrEntry(IterationStatement* statement) {
2691 if (!graph()->HasOsrEntryAt(statement)) return; 2674 if (!graph()->HasOsrEntryAt(statement)) return;
2692 2675
2693 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); 2676 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock();
2694 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); 2677 HBasicBlock* osr_entry = graph()->CreateBasicBlock();
2695 HValue* true_value = graph()->GetConstantTrue(); 2678 HValue* true_value = graph()->GetConstantTrue();
2696 HBranch* branch = new HBranch(non_osr_entry, osr_entry, true_value); 2679 HTest* test = new HTest(true_value, non_osr_entry, osr_entry);
2697 exit_block()->Finish(branch); 2680 exit_block()->Finish(test);
2698 2681
2699 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); 2682 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock();
2700 non_osr_entry->Goto(loop_predecessor); 2683 non_osr_entry->Goto(loop_predecessor);
2701 2684
2702 int osr_entry_id = statement->OsrEntryId(); 2685 int osr_entry_id = statement->OsrEntryId();
2703 // We want the correct environment at the OsrEntry instruction. Build 2686 // We want the correct environment at the OsrEntry instruction. Build
2704 // it explicitly. The expression stack should be empty. 2687 // it explicitly. The expression stack should be empty.
2705 int count = osr_entry->last_environment()->length(); 2688 int count = osr_entry->last_environment()->length();
2706 ASSERT(count == (osr_entry->last_environment()->parameter_count() + 2689 ASSERT(count == (osr_entry->last_environment()->parameter_count() +
2707 osr_entry->last_environment()->local_count())); 2690 osr_entry->last_environment()->local_count()));
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
2921 global->Lookup(*var->name(), lookup); 2904 global->Lookup(*var->name(), lookup);
2922 if (!lookup->IsProperty()) { 2905 if (!lookup->IsProperty()) {
2923 BAILOUT("global variable cell not yet introduced"); 2906 BAILOUT("global variable cell not yet introduced");
2924 } 2907 }
2925 if (lookup->type() != NORMAL) { 2908 if (lookup->type() != NORMAL) {
2926 BAILOUT("global variable has accessors"); 2909 BAILOUT("global variable has accessors");
2927 } 2910 }
2928 if (is_store && lookup->IsReadOnly()) { 2911 if (is_store && lookup->IsReadOnly()) {
2929 BAILOUT("read-only global variable"); 2912 BAILOUT("read-only global variable");
2930 } 2913 }
2914 if (lookup->holder() != *global) {
2915 BAILOUT("global property on prototype of global object");
2916 }
2917 }
2918
2919
2920 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) {
2921 ASSERT(var->IsContextSlot());
2922 HInstruction* context = new HContext;
2923 AddInstruction(context);
2924 int length = graph()->info()->scope()->ContextChainLength(var->scope());
2925 while (length-- > 0) {
2926 context = new HOuterContext(context);
2927 AddInstruction(context);
2928 }
2929 return context;
2931 } 2930 }
2932 2931
2933 2932
2934 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { 2933 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
2935 Variable* variable = expr->AsVariable(); 2934 Variable* variable = expr->AsVariable();
2936 if (variable == NULL) { 2935 if (variable == NULL) {
2937 BAILOUT("reference to rewritten variable"); 2936 BAILOUT("reference to rewritten variable");
2938 } else if (variable->IsStackAllocated()) { 2937 } else if (variable->IsStackAllocated()) {
2939 if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { 2938 if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) {
2940 BAILOUT("unsupported context for arguments object"); 2939 BAILOUT("unsupported context for arguments object");
2941 } 2940 }
2942 ast_context()->ReturnValue(environment()->Lookup(variable)); 2941 ast_context()->ReturnValue(environment()->Lookup(variable));
2942 } else if (variable->IsContextSlot()) {
2943 if (variable->mode() == Variable::CONST) {
2944 BAILOUT("reference to const context slot");
2945 }
2946 HValue* context = BuildContextChainWalk(variable);
2947 int index = variable->AsSlot()->index();
2948 HLoadContextSlot* instr = new HLoadContextSlot(context, index);
2949 ast_context()->ReturnInstruction(instr, expr->id());
2943 } else if (variable->is_global()) { 2950 } else if (variable->is_global()) {
2944 LookupResult lookup; 2951 LookupResult lookup;
2945 LookupGlobalPropertyCell(variable, &lookup, false); 2952 LookupGlobalPropertyCell(variable, &lookup, false);
2946 CHECK_BAILOUT; 2953 CHECK_BAILOUT;
2947 2954
2948 Handle<GlobalObject> global(graph()->info()->global_object()); 2955 Handle<GlobalObject> global(graph()->info()->global_object());
2949 // TODO(3039103): Handle global property load through an IC call when access 2956 // TODO(3039103): Handle global property load through an IC call when access
2950 // checks are enabled. 2957 // checks are enabled.
2951 if (global->IsAccessCheckNeeded()) { 2958 if (global->IsAccessCheckNeeded()) {
2952 BAILOUT("global object requires access check"); 2959 BAILOUT("global object requires access check");
2953 } 2960 }
2954 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 2961 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
2955 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); 2962 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
2956 HLoadGlobal* instr = new HLoadGlobal(cell, check_hole); 2963 HLoadGlobal* instr = new HLoadGlobal(cell, check_hole);
2957 ast_context()->ReturnInstruction(instr, expr->id()); 2964 ast_context()->ReturnInstruction(instr, expr->id());
2958 } else { 2965 } else {
2959 BAILOUT("reference to non-stack-allocated/non-global variable"); 2966 BAILOUT("reference to a variable which requires dynamic lookup");
2960 } 2967 }
2961 } 2968 }
2962 2969
2963 2970
2964 void HGraphBuilder::VisitLiteral(Literal* expr) { 2971 void HGraphBuilder::VisitLiteral(Literal* expr) {
2965 HConstant* instr = new HConstant(expr->handle(), Representation::Tagged()); 2972 HConstant* instr = new HConstant(expr->handle(), Representation::Tagged());
2966 ast_context()->ReturnInstruction(instr, expr->id()); 2973 ast_context()->ReturnInstruction(instr, expr->id());
2967 } 2974 }
2968 2975
2969 2976
2970 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { 2977 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
2971 HRegExpLiteral* instr = new HRegExpLiteral(expr->pattern(), 2978 HRegExpLiteral* instr = new HRegExpLiteral(expr->pattern(),
2972 expr->flags(), 2979 expr->flags(),
2973 expr->literal_index()); 2980 expr->literal_index());
2974 ast_context()->ReturnInstruction(instr, expr->id()); 2981 ast_context()->ReturnInstruction(instr, expr->id());
2975 } 2982 }
2976 2983
2977 2984
2978 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { 2985 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
2979 HObjectLiteral* literal = (new HObjectLiteral(expr->constant_properties(), 2986 HContext* context = new HContext;
2987 AddInstruction(context);
2988 HObjectLiteral* literal = (new HObjectLiteral(context,
2989 expr->constant_properties(),
2980 expr->fast_elements(), 2990 expr->fast_elements(),
2981 expr->literal_index(), 2991 expr->literal_index(),
2982 expr->depth())); 2992 expr->depth()));
2983 // The object is expected in the bailout environment during computation 2993 // The object is expected in the bailout environment during computation
2984 // of the property values and is the value of the entire expression. 2994 // of the property values and is the value of the entire expression.
2985 PushAndAdd(literal); 2995 PushAndAdd(literal);
2986 2996
2987 expr->CalculateEmitStore(); 2997 expr->CalculateEmitStore();
2988 2998
2989 for (int i = 0; i < expr->properties()->length(); i++) { 2999 for (int i = 0; i < expr->properties()->length(); i++) {
2990 ObjectLiteral::Property* property = expr->properties()->at(i); 3000 ObjectLiteral::Property* property = expr->properties()->at(i);
2991 if (property->IsCompileTimeValue()) continue; 3001 if (property->IsCompileTimeValue()) continue;
2992 3002
2993 Literal* key = property->key(); 3003 Literal* key = property->key();
2994 Expression* value = property->value(); 3004 Expression* value = property->value();
2995 3005
2996 switch (property->kind()) { 3006 switch (property->kind()) {
2997 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 3007 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
2998 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 3008 ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
2999 // Fall through. 3009 // Fall through.
3000 case ObjectLiteral::Property::COMPUTED: 3010 case ObjectLiteral::Property::COMPUTED:
3001 if (key->handle()->IsSymbol()) { 3011 if (key->handle()->IsSymbol()) {
3002 if (property->emit_store()) { 3012 if (property->emit_store()) {
3003 VISIT_FOR_VALUE(value); 3013 VISIT_FOR_VALUE(value);
3004 HValue* value = Pop(); 3014 HValue* value = Pop();
3005 Handle<String> name = Handle<String>::cast(key->handle()); 3015 Handle<String> name = Handle<String>::cast(key->handle());
3006 AddInstruction(new HStoreNamedGeneric(literal, name, value)); 3016 HStoreNamedGeneric* store =
3017 new HStoreNamedGeneric(context, literal, name, value);
3018 AddInstruction(store);
3007 AddSimulate(key->id()); 3019 AddSimulate(key->id());
3008 } else { 3020 } else {
3009 VISIT_FOR_EFFECT(value); 3021 VISIT_FOR_EFFECT(value);
3010 } 3022 }
3011 break; 3023 break;
3012 } 3024 }
3013 // Fall through. 3025 // Fall through.
3014 case ObjectLiteral::Property::PROTOTYPE: 3026 case ObjectLiteral::Property::PROTOTYPE:
3015 case ObjectLiteral::Property::SETTER: 3027 case ObjectLiteral::Property::SETTER:
3016 case ObjectLiteral::Property::GETTER: 3028 case ObjectLiteral::Property::GETTER:
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
3059 } 3071 }
3060 ast_context()->ReturnValue(Pop()); 3072 ast_context()->ReturnValue(Pop());
3061 } 3073 }
3062 3074
3063 3075
3064 void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { 3076 void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
3065 BAILOUT("CatchExtensionObject"); 3077 BAILOUT("CatchExtensionObject");
3066 } 3078 }
3067 3079
3068 3080
3069 HBasicBlock* HGraphBuilder::BuildTypeSwitch(ZoneMapList* maps, 3081 HBasicBlock* HGraphBuilder::BuildTypeSwitch(HValue* receiver,
3070 ZoneList<HSubgraph*>* subgraphs, 3082 ZoneMapList* maps,
3071 HValue* receiver, 3083 ZoneList<HSubgraph*>* body_graphs,
3084 HSubgraph* default_graph,
3072 int join_id) { 3085 int join_id) {
3073 ASSERT(subgraphs->length() == (maps->length() + 1)); 3086 ASSERT(maps->length() == body_graphs->length());
3087 HBasicBlock* join_block = graph()->CreateBasicBlock();
3088 AddInstruction(new HCheckNonSmi(receiver));
3074 3089
3075 // Build map compare subgraphs for all but the first map. 3090 for (int i = 0; i < maps->length(); ++i) {
3076 ZoneList<HSubgraph*> map_compare_subgraphs(maps->length() - 1); 3091 // Build the branches, connect all the target subgraphs to the join
3077 for (int i = maps->length() - 1; i > 0; --i) { 3092 // block. Use the default as a target of the last branch.
3078 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3093 HSubgraph* if_true = body_graphs->at(i);
3079 SubgraphScope scope(this, subgraph); 3094 HSubgraph* if_false = (i == maps->length() - 1)
3080 HSubgraph* else_subgraph = 3095 ? default_graph
3081 (i == (maps->length() - 1)) 3096 : CreateBranchSubgraph(environment());
3082 ? subgraphs->last() 3097 HCompareMap* compare =
3083 : map_compare_subgraphs.last(); 3098 new HCompareMap(receiver,
3084 current_subgraph_->exit_block()->Finish( 3099 maps->at(i),
3085 new HCompareMapAndBranch(receiver, 3100 if_true->entry_block(),
3086 maps->at(i), 3101 if_false->entry_block());
3087 subgraphs->at(i)->entry_block(), 3102 subgraph()->exit_block()->Finish(compare);
3088 else_subgraph->entry_block())); 3103
3089 map_compare_subgraphs.Add(subgraph); 3104 if (if_true->HasExit()) {
3105 // In an effect context the value of the type switch is not needed.
3106 // There is no need to merge it at the join block only to discard it.
3107 if (ast_context()->IsEffect()) {
3108 if_true->exit_block()->last_environment()->Drop(1);
3109 }
3110 if_true->exit_block()->Goto(join_block);
3111 }
3112
3113 subgraph()->set_exit_block(if_false->exit_block());
3090 } 3114 }
3091 3115
3092 // Generate first map check to end the current block. 3116 // Connect the default if necessary.
3093 AddInstruction(new HCheckNonSmi(receiver)); 3117 if (subgraph()->HasExit()) {
3094 HSubgraph* else_subgraph = 3118 if (ast_context()->IsEffect()) {
3095 (maps->length() == 1) ? subgraphs->at(1) : map_compare_subgraphs.last(); 3119 environment()->Drop(1);
3096 current_subgraph_->exit_block()->Finish(
3097 new HCompareMapAndBranch(receiver,
3098 Handle<Map>(maps->first()),
3099 subgraphs->first()->entry_block(),
3100 else_subgraph->entry_block()));
3101
3102 // Join all the call subgraphs in a new basic block and make
3103 // this basic block the current basic block.
3104 HBasicBlock* join_block = graph_->CreateBasicBlock();
3105 for (int i = 0; i < subgraphs->length(); ++i) {
3106 if (subgraphs->at(i)->HasExit()) {
3107 subgraphs->at(i)->exit_block()->Goto(join_block);
3108 } 3120 }
3121 subgraph()->exit_block()->Goto(join_block);
3109 } 3122 }
3110 3123
3111 if (join_block->predecessors()->is_empty()) return NULL; 3124 if (join_block->predecessors()->is_empty()) return NULL;
3112 join_block->SetJoinId(join_id); 3125 join_block->SetJoinId(join_id);
3113 return join_block; 3126 return join_block;
3114 } 3127 }
3115 3128
3116 3129
3117 // Sets the lookup result and returns true if the store can be inlined. 3130 // Sets the lookup result and returns true if the store can be inlined.
3118 static bool ComputeStoredField(Handle<Map> type, 3131 static bool ComputeStoredField(Handle<Map> type,
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
3169 // enable elimination of redundant checks after the transition store. 3182 // enable elimination of redundant checks after the transition store.
3170 instr->SetFlag(HValue::kChangesMaps); 3183 instr->SetFlag(HValue::kChangesMaps);
3171 } 3184 }
3172 return instr; 3185 return instr;
3173 } 3186 }
3174 3187
3175 3188
3176 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, 3189 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object,
3177 Handle<String> name, 3190 Handle<String> name,
3178 HValue* value) { 3191 HValue* value) {
3179 return new HStoreNamedGeneric(object, name, value); 3192 HContext* context = new HContext;
3193 AddInstruction(context);
3194 return new HStoreNamedGeneric(context, object, name, value);
3180 } 3195 }
3181 3196
3182 3197
3183 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, 3198 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
3184 HValue* value, 3199 HValue* value,
3185 Expression* expr) { 3200 Expression* expr) {
3186 Property* prop = (expr->AsProperty() != NULL) 3201 Property* prop = (expr->AsProperty() != NULL)
3187 ? expr->AsProperty() 3202 ? expr->AsProperty()
3188 : expr->AsAssignment()->target()->AsProperty(); 3203 : expr->AsAssignment()->target()->AsProperty();
3189 Literal* key = prop->key()->AsLiteral(); 3204 Literal* key = prop->key()->AsLiteral();
(...skipping 12 matching lines...) Expand all
3202 } 3217 }
3203 3218
3204 3219
3205 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, 3220 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
3206 HValue* object, 3221 HValue* object,
3207 HValue* value, 3222 HValue* value,
3208 ZoneMapList* types, 3223 ZoneMapList* types,
3209 Handle<String> name) { 3224 Handle<String> name) {
3210 int number_of_types = Min(types->length(), kMaxStorePolymorphism); 3225 int number_of_types = Min(types->length(), kMaxStorePolymorphism);
3211 ZoneMapList maps(number_of_types); 3226 ZoneMapList maps(number_of_types);
3212 ZoneList<HSubgraph*> subgraphs(number_of_types + 1); 3227 ZoneList<HSubgraph*> subgraphs(number_of_types);
3213 bool needs_generic = (types->length() > kMaxStorePolymorphism); 3228 bool needs_generic = (types->length() > kMaxStorePolymorphism);
3214 3229
3215 // Build subgraphs for each of the specific maps. 3230 // Build subgraphs for each of the specific maps.
3216 // 3231 //
3217 // TODO(ager): We should recognize when the prototype chains for 3232 // TODO(ager): We should recognize when the prototype chains for
3218 // different maps are identical. In that case we can avoid 3233 // different maps are identical. In that case we can avoid
3219 // repeatedly generating the same prototype map checks. 3234 // repeatedly generating the same prototype map checks.
3220 for (int i = 0; i < number_of_types; ++i) { 3235 for (int i = 0; i < number_of_types; ++i) {
3221 Handle<Map> map = types->at(i); 3236 Handle<Map> map = types->at(i);
3222 LookupResult lookup; 3237 LookupResult lookup;
3223 if (ComputeStoredField(map, name, &lookup)) { 3238 if (ComputeStoredField(map, name, &lookup)) {
3224 maps.Add(map);
3225 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3239 HSubgraph* subgraph = CreateBranchSubgraph(environment());
3226 SubgraphScope scope(this, subgraph); 3240 SubgraphScope scope(this, subgraph);
3227 HInstruction* instr = 3241 HInstruction* instr =
3228 BuildStoreNamedField(object, name, value, map, &lookup, false); 3242 BuildStoreNamedField(object, name, value, map, &lookup, false);
3229 Push(value); 3243 Push(value);
3230 instr->set_position(expr->position()); 3244 instr->set_position(expr->position());
3231 AddInstruction(instr); 3245 AddInstruction(instr);
3246 maps.Add(map);
3232 subgraphs.Add(subgraph); 3247 subgraphs.Add(subgraph);
3233 } else { 3248 } else {
3234 needs_generic = true; 3249 needs_generic = true;
3235 } 3250 }
3236 } 3251 }
3237 3252
3238 // If none of the properties were named fields we generate a 3253 // If none of the properties were named fields we generate a
3239 // generic store. 3254 // generic store.
3240 if (maps.length() == 0) { 3255 if (maps.length() == 0) {
3241 HInstruction* instr = new HStoreNamedGeneric(object, name, value); 3256 HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
3242 Push(value); 3257 Push(value);
3243 instr->set_position(expr->position()); 3258 instr->set_position(expr->position());
3244 AddInstruction(instr); 3259 AddInstruction(instr);
3245 if (instr->HasSideEffects()) AddSimulate(expr->id()); 3260 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3261 ast_context()->ReturnValue(Pop());
3246 } else { 3262 } else {
3247 // Build subgraph for generic store through IC. 3263 // Build subgraph for generic store through IC.
3248 { 3264 HSubgraph* default_graph = CreateBranchSubgraph(environment());
3249 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3265 { SubgraphScope scope(this, default_graph);
3250 SubgraphScope scope(this, subgraph);
3251 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { 3266 if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3252 subgraph->FinishExit(new HDeoptimize()); 3267 default_graph->FinishExit(new HDeoptimize());
3253 } else { 3268 } else {
3254 HInstruction* instr = new HStoreNamedGeneric(object, name, value); 3269 HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
3255 Push(value); 3270 Push(value);
3256 instr->set_position(expr->position()); 3271 instr->set_position(expr->position());
3257 AddInstruction(instr); 3272 AddInstruction(instr);
3258 } 3273 }
3259 subgraphs.Add(subgraph);
3260 } 3274 }
3261 3275
3262 HBasicBlock* new_exit_block = 3276 HBasicBlock* new_exit_block =
3263 BuildTypeSwitch(&maps, &subgraphs, object, expr->AssignmentId()); 3277 BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id());
3264 subgraph()->set_exit_block(new_exit_block); 3278 subgraph()->set_exit_block(new_exit_block);
3279 // In an effect context, we did not materialized the value in the
3280 // predecessor environments so there's no need to handle it here.
3281 if (subgraph()->HasExit() && !ast_context()->IsEffect()) {
3282 ast_context()->ReturnValue(Pop());
3283 }
3265 } 3284 }
3266
3267 if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop());
3268 } 3285 }
3269 3286
3270 3287
3271 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { 3288 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
3272 Property* prop = expr->target()->AsProperty(); 3289 Property* prop = expr->target()->AsProperty();
3273 ASSERT(prop != NULL); 3290 ASSERT(prop != NULL);
3274 expr->RecordTypeFeedback(oracle()); 3291 expr->RecordTypeFeedback(oracle());
3275 VISIT_FOR_VALUE(prop->obj()); 3292 VISIT_FOR_VALUE(prop->obj());
3276 3293
3277 HValue* value = NULL; 3294 HValue* value = NULL;
(...skipping 13 matching lines...) Expand all
3291 LookupResult lookup; 3308 LookupResult lookup;
3292 3309
3293 if (expr->IsMonomorphic()) { 3310 if (expr->IsMonomorphic()) {
3294 instr = BuildStoreNamed(object, value, expr); 3311 instr = BuildStoreNamed(object, value, expr);
3295 3312
3296 } else if (types != NULL && types->length() > 1) { 3313 } else if (types != NULL && types->length() > 1) {
3297 HandlePolymorphicStoreNamedField(expr, object, value, types, name); 3314 HandlePolymorphicStoreNamedField(expr, object, value, types, name);
3298 return; 3315 return;
3299 3316
3300 } else { 3317 } else {
3301 instr = new HStoreNamedGeneric(object, name, value); 3318 instr = BuildStoreNamedGeneric(object, name, value);
3302 } 3319 }
3303 3320
3304 } else { 3321 } else {
3305 // Keyed store. 3322 // Keyed store.
3306 VISIT_FOR_VALUE(prop->key()); 3323 VISIT_FOR_VALUE(prop->key());
3307 VISIT_FOR_VALUE(expr->value()); 3324 VISIT_FOR_VALUE(expr->value());
3308 value = Pop(); 3325 value = Pop();
3309 HValue* key = Pop(); 3326 HValue* key = Pop();
3310 HValue* object = Pop(); 3327 HValue* object = Pop();
3311 3328
(...skipping 17 matching lines...) Expand all
3329 // superclass of Assignment and CountOperation, we cannot just pass the 3346 // superclass of Assignment and CountOperation, we cannot just pass the
3330 // owning expression instead of position and ast_id separately. 3347 // owning expression instead of position and ast_id separately.
3331 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, 3348 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
3332 HValue* value, 3349 HValue* value,
3333 int position, 3350 int position,
3334 int ast_id) { 3351 int ast_id) {
3335 LookupResult lookup; 3352 LookupResult lookup;
3336 LookupGlobalPropertyCell(var, &lookup, true); 3353 LookupGlobalPropertyCell(var, &lookup, true);
3337 CHECK_BAILOUT; 3354 CHECK_BAILOUT;
3338 3355
3356 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
3339 Handle<GlobalObject> global(graph()->info()->global_object()); 3357 Handle<GlobalObject> global(graph()->info()->global_object());
3340 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 3358 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
3341 HInstruction* instr = new HStoreGlobal(value, cell); 3359 HInstruction* instr = new HStoreGlobal(value, cell, check_hole);
3342 instr->set_position(position); 3360 instr->set_position(position);
3343 AddInstruction(instr); 3361 AddInstruction(instr);
3344 if (instr->HasSideEffects()) AddSimulate(ast_id); 3362 if (instr->HasSideEffects()) AddSimulate(ast_id);
3345 } 3363 }
3346 3364
3347 3365
3348 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { 3366 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
3349 Expression* target = expr->target(); 3367 Expression* target = expr->target();
3350 VariableProxy* proxy = target->AsVariableProxy(); 3368 VariableProxy* proxy = target->AsVariableProxy();
3351 Variable* var = proxy->AsVariable(); 3369 Variable* var = proxy->AsVariable();
3352 Property* prop = target->AsProperty(); 3370 Property* prop = target->AsProperty();
3353 ASSERT(var == NULL || prop == NULL); 3371 ASSERT(var == NULL || prop == NULL);
3354 3372
3355 // We have a second position recorded in the FullCodeGenerator to have 3373 // We have a second position recorded in the FullCodeGenerator to have
3356 // type feedback for the binary operation. 3374 // type feedback for the binary operation.
3357 BinaryOperation* operation = expr->binary_operation(); 3375 BinaryOperation* operation = expr->binary_operation();
3358 operation->RecordTypeFeedback(oracle());
3359 3376
3360 if (var != NULL) { 3377 if (var != NULL) {
3361 if (!var->is_global() && !var->IsStackAllocated()) {
3362 BAILOUT("non-stack/non-global in compound assignment");
3363 }
3364
3365 VISIT_FOR_VALUE(operation); 3378 VISIT_FOR_VALUE(operation);
3366 3379
3367 if (var->is_global()) { 3380 if (var->is_global()) {
3368 HandleGlobalVariableAssignment(var, 3381 HandleGlobalVariableAssignment(var,
3369 Top(), 3382 Top(),
3370 expr->position(), 3383 expr->position(),
3371 expr->AssignmentId()); 3384 expr->AssignmentId());
3385 } else if (var->IsStackAllocated()) {
3386 Bind(var, Top());
3387 } else if (var->IsContextSlot()) {
3388 HValue* context = BuildContextChainWalk(var);
3389 int index = var->AsSlot()->index();
3390 HStoreContextSlot* instr = new HStoreContextSlot(context, index, Top());
3391 AddInstruction(instr);
3392 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3372 } else { 3393 } else {
3373 Bind(var, Top()); 3394 BAILOUT("compound assignment to lookup slot");
3374 } 3395 }
3375 ast_context()->ReturnValue(Pop()); 3396 ast_context()->ReturnValue(Pop());
3376 3397
3377 } else if (prop != NULL) { 3398 } else if (prop != NULL) {
3378 prop->RecordTypeFeedback(oracle()); 3399 prop->RecordTypeFeedback(oracle());
3379 3400
3380 if (prop->key()->IsPropertyName()) { 3401 if (prop->key()->IsPropertyName()) {
3381 // Named property. 3402 // Named property.
3382 VISIT_FOR_VALUE(prop->obj()); 3403 VISIT_FOR_VALUE(prop->obj());
3383 HValue* obj = Top(); 3404 HValue* obj = Top();
(...skipping 27 matching lines...) Expand all
3411 3432
3412 } else { 3433 } else {
3413 // Keyed property. 3434 // Keyed property.
3414 VISIT_FOR_VALUE(prop->obj()); 3435 VISIT_FOR_VALUE(prop->obj());
3415 VISIT_FOR_VALUE(prop->key()); 3436 VISIT_FOR_VALUE(prop->key());
3416 HValue* obj = environment()->ExpressionStackAt(1); 3437 HValue* obj = environment()->ExpressionStackAt(1);
3417 HValue* key = environment()->ExpressionStackAt(0); 3438 HValue* key = environment()->ExpressionStackAt(0);
3418 3439
3419 bool is_fast_elements = prop->IsMonomorphic() && 3440 bool is_fast_elements = prop->IsMonomorphic() &&
3420 prop->GetMonomorphicReceiverType()->has_fast_elements(); 3441 prop->GetMonomorphicReceiverType()->has_fast_elements();
3421
3422 HInstruction* load = is_fast_elements 3442 HInstruction* load = is_fast_elements
3423 ? BuildLoadKeyedFastElement(obj, key, prop) 3443 ? BuildLoadKeyedFastElement(obj, key, prop)
3424 : BuildLoadKeyedGeneric(obj, key); 3444 : BuildLoadKeyedGeneric(obj, key);
3425 PushAndAdd(load); 3445 PushAndAdd(load);
3426 if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); 3446 if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId());
3427 3447
3428 VISIT_FOR_VALUE(expr->value()); 3448 VISIT_FOR_VALUE(expr->value());
3429 HValue* right = Pop(); 3449 HValue* right = Pop();
3430 HValue* left = Pop(); 3450 HValue* left = Pop();
3431 3451
(...skipping 26 matching lines...) Expand all
3458 3478
3459 if (expr->is_compound()) { 3479 if (expr->is_compound()) {
3460 HandleCompoundAssignment(expr); 3480 HandleCompoundAssignment(expr);
3461 return; 3481 return;
3462 } 3482 }
3463 3483
3464 if (var != NULL) { 3484 if (var != NULL) {
3465 if (proxy->IsArguments()) BAILOUT("assignment to arguments"); 3485 if (proxy->IsArguments()) BAILOUT("assignment to arguments");
3466 3486
3467 // Handle the assignment. 3487 // Handle the assignment.
3468 if (var->is_global()) { 3488 if (var->IsStackAllocated()) {
3489 HValue* value = NULL;
3490 // Handle stack-allocated variables on the right-hand side directly.
3491 // We do not allow the arguments object to occur in a context where it
3492 // may escape, but assignments to stack-allocated locals are
3493 // permitted. Handling such assignments here bypasses the check for
3494 // the arguments object in VisitVariableProxy.
3495 Variable* rhs_var = expr->value()->AsVariableProxy()->AsVariable();
3496 if (rhs_var != NULL && rhs_var->IsStackAllocated()) {
3497 value = environment()->Lookup(rhs_var);
3498 } else {
3499 VISIT_FOR_VALUE(expr->value());
3500 value = Pop();
3501 }
3502 Bind(var, value);
3503 ast_context()->ReturnValue(value);
3504
3505 } else if (var->IsContextSlot() && var->mode() != Variable::CONST) {
3506 VISIT_FOR_VALUE(expr->value());
3507 HValue* context = BuildContextChainWalk(var);
3508 int index = var->AsSlot()->index();
3509 HStoreContextSlot* instr = new HStoreContextSlot(context, index, Top());
3510 AddInstruction(instr);
3511 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3512 ast_context()->ReturnValue(Pop());
3513
3514 } else if (var->is_global()) {
3469 VISIT_FOR_VALUE(expr->value()); 3515 VISIT_FOR_VALUE(expr->value());
3470 HandleGlobalVariableAssignment(var, 3516 HandleGlobalVariableAssignment(var,
3471 Top(), 3517 Top(),
3472 expr->position(), 3518 expr->position(),
3473 expr->AssignmentId()); 3519 expr->AssignmentId());
3520 ast_context()->ReturnValue(Pop());
3521
3474 } else { 3522 } else {
3475 // We allow reference to the arguments object only in assignemtns 3523 BAILOUT("assignment to LOOKUP or const CONTEXT variable");
3476 // to local variables to make sure that the arguments object does
3477 // not escape and is not modified.
3478 VariableProxy* rhs = expr->value()->AsVariableProxy();
3479 if (rhs != NULL &&
3480 rhs->var()->IsStackAllocated() &&
3481 environment()->Lookup(rhs->var())->CheckFlag(HValue::kIsArguments)) {
3482 Push(environment()->Lookup(rhs->var()));
3483 } else {
3484 VISIT_FOR_VALUE(expr->value());
3485 }
3486 Bind(proxy->var(), Top());
3487 } 3524 }
3488 // Return the value.
3489 ast_context()->ReturnValue(Pop());
3490 3525
3491 } else if (prop != NULL) { 3526 } else if (prop != NULL) {
3492 HandlePropertyAssignment(expr); 3527 HandlePropertyAssignment(expr);
3493 } else { 3528 } else {
3494 BAILOUT("unsupported invalid lhs"); 3529 BAILOUT("invalid left-hand side in assignment");
3495 } 3530 }
3496 } 3531 }
3497 3532
3498 3533
3499 void HGraphBuilder::VisitThrow(Throw* expr) { 3534 void HGraphBuilder::VisitThrow(Throw* expr) {
3500 // We don't optimize functions with invalid left-hand sides in 3535 // We don't optimize functions with invalid left-hand sides in
3501 // assignments, count operations, or for-in. Consequently throw can 3536 // assignments, count operations, or for-in. Consequently throw can
3502 // currently only occur in an effect context. 3537 // currently only occur in an effect context.
3503 ASSERT(ast_context()->IsEffect()); 3538 ASSERT(ast_context()->IsEffect());
3504 VISIT_FOR_VALUE(expr->exception()); 3539 VISIT_FOR_VALUE(expr->exception());
3505 3540
3506 HValue* value = environment()->Pop(); 3541 HValue* value = environment()->Pop();
3507 HControlInstruction* instr = new HThrow(value); 3542 HThrow* instr = new HThrow(value);
3508 instr->set_position(expr->position()); 3543 instr->set_position(expr->position());
3509 current_subgraph_->FinishExit(instr); 3544 AddInstruction(instr);
3545 AddSimulate(expr->id());
3546 current_subgraph_->FinishExit(new HAbnormalExit);
3510 } 3547 }
3511 3548
3512 3549
3513 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, 3550 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
3514 HValue* object, 3551 HValue* object,
3515 ZoneMapList* types, 3552 ZoneMapList* types,
3516 Handle<String> name) { 3553 Handle<String> name) {
3517 int number_of_types = Min(types->length(), kMaxLoadPolymorphism); 3554 int number_of_types = Min(types->length(), kMaxLoadPolymorphism);
3518 ZoneMapList maps(number_of_types); 3555 ZoneMapList maps(number_of_types);
3519 ZoneList<HSubgraph*> subgraphs(number_of_types + 1); 3556 ZoneList<HSubgraph*> subgraphs(number_of_types);
3520 bool needs_generic = (types->length() > kMaxLoadPolymorphism); 3557 bool needs_generic = (types->length() > kMaxLoadPolymorphism);
3521 3558
3522 // Build subgraphs for each of the specific maps. 3559 // Build subgraphs for each of the specific maps.
3523 // 3560 //
3524 // TODO(ager): We should recognize when the prototype chains for 3561 // TODO(ager): We should recognize when the prototype chains for
3525 // different maps are identical. In that case we can avoid 3562 // different maps are identical. In that case we can avoid
3526 // repeatedly generating the same prototype map checks. 3563 // repeatedly generating the same prototype map checks.
3527 for (int i = 0; i < number_of_types; ++i) { 3564 for (int i = 0; i < number_of_types; ++i) {
3528 Handle<Map> map = types->at(i); 3565 Handle<Map> map = types->at(i);
3529 LookupResult lookup; 3566 LookupResult lookup;
3530 map->LookupInDescriptors(NULL, *name, &lookup); 3567 map->LookupInDescriptors(NULL, *name, &lookup);
3531 if (lookup.IsProperty() && lookup.type() == FIELD) { 3568 if (lookup.IsProperty() && lookup.type() == FIELD) {
3532 maps.Add(map);
3533 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3569 HSubgraph* subgraph = CreateBranchSubgraph(environment());
3534 SubgraphScope scope(this, subgraph); 3570 SubgraphScope scope(this, subgraph);
3535 HLoadNamedField* instr = 3571 HLoadNamedField* instr =
3536 BuildLoadNamedField(object, expr, map, &lookup, false); 3572 BuildLoadNamedField(object, expr, map, &lookup, false);
3537 instr->set_position(expr->position()); 3573 instr->set_position(expr->position());
3538 instr->ClearFlag(HValue::kUseGVN); // Don't do GVN on polymorphic loads. 3574 instr->ClearFlag(HValue::kUseGVN); // Don't do GVN on polymorphic loads.
3539 PushAndAdd(instr); 3575 PushAndAdd(instr);
3576 maps.Add(map);
3540 subgraphs.Add(subgraph); 3577 subgraphs.Add(subgraph);
3541 } else { 3578 } else {
3542 needs_generic = true; 3579 needs_generic = true;
3543 } 3580 }
3544 } 3581 }
3545 3582
3546 // If none of the properties were named fields we generate a 3583 // If none of the properties were named fields we generate a
3547 // generic load. 3584 // generic load.
3548 if (maps.length() == 0) { 3585 if (maps.length() == 0) {
3549 HInstruction* instr = BuildLoadNamedGeneric(object, expr); 3586 HInstruction* instr = BuildLoadNamedGeneric(object, expr);
3550 instr->set_position(expr->position()); 3587 instr->set_position(expr->position());
3551 PushAndAdd(instr); 3588 ast_context()->ReturnInstruction(instr, expr->id());
3552 if (instr->HasSideEffects()) AddSimulate(expr->id());
3553 } else { 3589 } else {
3554 // Build subgraph for generic load through IC. 3590 // Build subgraph for generic load through IC.
3555 { 3591 HSubgraph* default_graph = CreateBranchSubgraph(environment());
3556 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3592 { SubgraphScope scope(this, default_graph);
3557 SubgraphScope scope(this, subgraph);
3558 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { 3593 if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3559 subgraph->FinishExit(new HDeoptimize()); 3594 default_graph->FinishExit(new HDeoptimize());
3560 } else { 3595 } else {
3561 HInstruction* instr = BuildLoadNamedGeneric(object, expr); 3596 HInstruction* instr = BuildLoadNamedGeneric(object, expr);
3562 instr->set_position(expr->position()); 3597 instr->set_position(expr->position());
3563 PushAndAdd(instr); 3598 PushAndAdd(instr);
3564 } 3599 }
3565 subgraphs.Add(subgraph);
3566 } 3600 }
3567 3601
3568 HBasicBlock* new_exit_block = 3602 HBasicBlock* new_exit_block =
3569 BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); 3603 BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id());
3570 subgraph()->set_exit_block(new_exit_block); 3604 subgraph()->set_exit_block(new_exit_block);
3605 // In an effect context, we did not materialized the value in the
3606 // predecessor environments so there's no need to handle it here.
3607 if (subgraph()->HasExit() && !ast_context()->IsEffect()) {
3608 ast_context()->ReturnValue(Pop());
3609 }
3571 } 3610 }
3572
3573 if (subgraph()->HasExit()) ast_context()->ReturnValue(Pop());
3574 } 3611 }
3575 3612
3576 3613
3577 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, 3614 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
3578 Property* expr, 3615 Property* expr,
3579 Handle<Map> type, 3616 Handle<Map> type,
3580 LookupResult* lookup, 3617 LookupResult* lookup,
3581 bool smi_and_map_check) { 3618 bool smi_and_map_check) {
3582 if (smi_and_map_check) { 3619 if (smi_and_map_check) {
3583 AddInstruction(new HCheckNonSmi(object)); 3620 AddInstruction(new HCheckNonSmi(object));
(...skipping 11 matching lines...) Expand all
3595 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; 3632 int offset = (index * kPointerSize) + FixedArray::kHeaderSize;
3596 return new HLoadNamedField(object, false, offset); 3633 return new HLoadNamedField(object, false, offset);
3597 } 3634 }
3598 } 3635 }
3599 3636
3600 3637
3601 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj, 3638 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj,
3602 Property* expr) { 3639 Property* expr) {
3603 ASSERT(expr->key()->IsPropertyName()); 3640 ASSERT(expr->key()->IsPropertyName());
3604 Handle<Object> name = expr->key()->AsLiteral()->handle(); 3641 Handle<Object> name = expr->key()->AsLiteral()->handle();
3605 return new HLoadNamedGeneric(obj, name); 3642 HContext* context = new HContext;
3643 AddInstruction(context);
3644 return new HLoadNamedGeneric(context, obj, name);
3606 } 3645 }
3607 3646
3608 3647
3609 HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj, 3648 HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj,
3610 Property* expr, 3649 Property* expr,
3611 Handle<Map> map, 3650 Handle<Map> map,
3612 Handle<String> name) { 3651 Handle<String> name) {
3613 LookupResult lookup; 3652 LookupResult lookup;
3614 map->LookupInDescriptors(NULL, *name, &lookup); 3653 map->LookupInDescriptors(NULL, *name, &lookup);
3615 if (lookup.IsProperty() && lookup.type() == FIELD) { 3654 if (lookup.IsProperty() && lookup.type() == FIELD) {
3616 return BuildLoadNamedField(obj, 3655 return BuildLoadNamedField(obj,
3617 expr, 3656 expr,
3618 map, 3657 map,
3619 &lookup, 3658 &lookup,
3620 true); 3659 true);
3621 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) { 3660 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) {
3622 AddInstruction(new HCheckNonSmi(obj)); 3661 AddInstruction(new HCheckNonSmi(obj));
3623 AddInstruction(new HCheckMap(obj, map)); 3662 AddInstruction(new HCheckMap(obj, map));
3624 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); 3663 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map));
3625 return new HConstant(function, Representation::Tagged()); 3664 return new HConstant(function, Representation::Tagged());
3626 } else { 3665 } else {
3627 return BuildLoadNamedGeneric(obj, expr); 3666 return BuildLoadNamedGeneric(obj, expr);
3628 } 3667 }
3629 } 3668 }
3630 3669
3631 3670
3632 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 3671 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
3633 HValue* key) { 3672 HValue* key) {
3634 return new HLoadKeyedGeneric(object, key); 3673 HContext* context = new HContext;
3674 AddInstruction(context);
3675 return new HLoadKeyedGeneric(context, object, key);
3635 } 3676 }
3636 3677
3637 3678
3638 HInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object, 3679 HInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object,
3639 HValue* key, 3680 HValue* key,
3640 Property* expr) { 3681 Property* expr) {
3641 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); 3682 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic());
3642 AddInstruction(new HCheckNonSmi(object)); 3683 AddInstruction(new HCheckNonSmi(object));
3643 Handle<Map> map = expr->GetMonomorphicReceiverType(); 3684 Handle<Map> map = expr->GetMonomorphicReceiverType();
3644 ASSERT(map->has_fast_elements()); 3685 ASSERT(map->has_fast_elements());
3645 AddInstruction(new HCheckMap(object, map)); 3686 AddInstruction(new HCheckMap(object, map));
3646 bool is_array = (map->instance_type() == JS_ARRAY_TYPE); 3687 bool is_array = (map->instance_type() == JS_ARRAY_TYPE);
3647 HLoadElements* elements = new HLoadElements(object); 3688 HLoadElements* elements = new HLoadElements(object);
3648 HInstruction* length = NULL; 3689 HInstruction* length = NULL;
3649 if (is_array) { 3690 if (is_array) {
3650 length = AddInstruction(new HJSArrayLength(object)); 3691 length = AddInstruction(new HJSArrayLength(object));
3651 AddInstruction(new HBoundsCheck(key, length)); 3692 AddInstruction(new HBoundsCheck(key, length));
3652 AddInstruction(elements); 3693 AddInstruction(elements);
3653 } else { 3694 } else {
3654 AddInstruction(elements); 3695 AddInstruction(elements);
3655 length = AddInstruction(new HFixedArrayLength(elements)); 3696 length = AddInstruction(new HFixedArrayLength(elements));
3656 AddInstruction(new HBoundsCheck(key, length)); 3697 AddInstruction(new HBoundsCheck(key, length));
3657 } 3698 }
3658 return new HLoadKeyedFastElement(elements, key); 3699 return new HLoadKeyedFastElement(elements, key);
3659 } 3700 }
3660 3701
3661 3702
3703 HInstruction* HGraphBuilder::BuildLoadKeyedPixelArrayElement(HValue* object,
3704 HValue* key,
3705 Property* expr) {
3706 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic());
3707 AddInstruction(new HCheckNonSmi(object));
3708 Handle<Map> map = expr->GetMonomorphicReceiverType();
3709 ASSERT(!map->has_fast_elements());
3710 ASSERT(map->has_pixel_array_elements());
3711 AddInstruction(new HCheckMap(object, map));
3712 HLoadElements* elements = new HLoadElements(object);
3713 AddInstruction(elements);
3714 HInstruction* length = AddInstruction(new HPixelArrayLength(elements));
3715 AddInstruction(new HBoundsCheck(key, length));
3716 HLoadPixelArrayExternalPointer* external_elements =
3717 new HLoadPixelArrayExternalPointer(elements);
3718 AddInstruction(external_elements);
3719 HLoadPixelArrayElement* pixel_array_value =
3720 new HLoadPixelArrayElement(external_elements, key);
3721 return pixel_array_value;
3722 }
3723
3724
3662 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object, 3725 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object,
3663 HValue* key, 3726 HValue* key,
3664 HValue* value) { 3727 HValue* value) {
3665 return new HStoreKeyedGeneric(object, key, value); 3728 HContext* context = new HContext;
3729 AddInstruction(context);
3730 return new HStoreKeyedGeneric(context, object, key, value);
3666 } 3731 }
3667 3732
3668 3733
3669 HInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object, 3734 HInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object,
3670 HValue* key, 3735 HValue* key,
3671 HValue* val, 3736 HValue* val,
3672 Expression* expr) { 3737 Expression* expr) {
3673 ASSERT(expr->IsMonomorphic()); 3738 ASSERT(expr->IsMonomorphic());
3674 AddInstruction(new HCheckNonSmi(object)); 3739 AddInstruction(new HCheckNonSmi(object));
3675 Handle<Map> map = expr->GetMonomorphicReceiverType(); 3740 Handle<Map> map = expr->GetMonomorphicReceiverType();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
3725 3790
3726 VISIT_FOR_VALUE(expr->obj()); 3791 VISIT_FOR_VALUE(expr->obj());
3727 3792
3728 HInstruction* instr = NULL; 3793 HInstruction* instr = NULL;
3729 if (expr->IsArrayLength()) { 3794 if (expr->IsArrayLength()) {
3730 HValue* array = Pop(); 3795 HValue* array = Pop();
3731 AddInstruction(new HCheckNonSmi(array)); 3796 AddInstruction(new HCheckNonSmi(array));
3732 AddInstruction(new HCheckInstanceType(array, JS_ARRAY_TYPE, JS_ARRAY_TYPE)); 3797 AddInstruction(new HCheckInstanceType(array, JS_ARRAY_TYPE, JS_ARRAY_TYPE));
3733 instr = new HJSArrayLength(array); 3798 instr = new HJSArrayLength(array);
3734 3799
3800 } else if (expr->IsStringLength()) {
3801 HValue* string = Pop();
3802 AddInstruction(new HCheckNonSmi(string));
3803 AddInstruction(new HCheckInstanceType(string,
3804 FIRST_STRING_TYPE,
3805 LAST_STRING_TYPE));
3806 instr = new HStringLength(string);
3807
3735 } else if (expr->IsFunctionPrototype()) { 3808 } else if (expr->IsFunctionPrototype()) {
3736 HValue* function = Pop(); 3809 HValue* function = Pop();
3737 AddInstruction(new HCheckNonSmi(function)); 3810 AddInstruction(new HCheckNonSmi(function));
3738 instr = new HLoadFunctionPrototype(function); 3811 instr = new HLoadFunctionPrototype(function);
3739 3812
3740 } else if (expr->key()->IsPropertyName()) { 3813 } else if (expr->key()->IsPropertyName()) {
3741 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 3814 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
3742 ZoneMapList* types = expr->GetReceiverTypes(); 3815 ZoneMapList* types = expr->GetReceiverTypes();
3743 3816
3744 HValue* obj = Pop(); 3817 HValue* obj = Pop();
3745 if (expr->IsMonomorphic()) { 3818 if (expr->IsMonomorphic()) {
3746 instr = BuildLoadNamed(obj, expr, types->first(), name); 3819 instr = BuildLoadNamed(obj, expr, types->first(), name);
3747 } else if (types != NULL && types->length() > 1) { 3820 } else if (types != NULL && types->length() > 1) {
3748 HandlePolymorphicLoadNamedField(expr, obj, types, name); 3821 HandlePolymorphicLoadNamedField(expr, obj, types, name);
3749 return; 3822 return;
3750 3823
3751 } else { 3824 } else {
3752 instr = BuildLoadNamedGeneric(obj, expr); 3825 instr = BuildLoadNamedGeneric(obj, expr);
3753 } 3826 }
3754 3827
3755 } else { 3828 } else {
3756 VISIT_FOR_VALUE(expr->key()); 3829 VISIT_FOR_VALUE(expr->key());
3757 3830
3758 HValue* key = Pop(); 3831 HValue* key = Pop();
3759 HValue* obj = Pop(); 3832 HValue* obj = Pop();
3760 3833
3761 bool is_fast_elements = expr->IsMonomorphic() && 3834 if (expr->IsMonomorphic()) {
3762 expr->GetMonomorphicReceiverType()->has_fast_elements(); 3835 Handle<Map> receiver_type(expr->GetMonomorphicReceiverType());
3763 3836 // An object has either fast elements or pixel array elements, but never
3764 instr = is_fast_elements 3837 // both. Pixel array maps that are assigned to pixel array elements are
3765 ? BuildLoadKeyedFastElement(obj, key, expr) 3838 // always created with the fast elements flag cleared.
3766 : BuildLoadKeyedGeneric(obj, key); 3839 if (receiver_type->has_pixel_array_elements()) {
3840 instr = BuildLoadKeyedPixelArrayElement(obj, key, expr);
3841 } else if (receiver_type->has_fast_elements()) {
3842 instr = BuildLoadKeyedFastElement(obj, key, expr);
3843 }
3844 }
3845 if (instr == NULL) {
3846 instr = BuildLoadKeyedGeneric(obj, key);
3847 }
3767 } 3848 }
3768 instr->set_position(expr->position()); 3849 instr->set_position(expr->position());
3769 ast_context()->ReturnInstruction(instr, expr->id()); 3850 ast_context()->ReturnInstruction(instr, expr->id());
3770 } 3851 }
3771 3852
3772 3853
3773 void HGraphBuilder::AddCheckConstantFunction(Call* expr, 3854 void HGraphBuilder::AddCheckConstantFunction(Call* expr,
3774 HValue* receiver, 3855 HValue* receiver,
3775 Handle<Map> receiver_map, 3856 Handle<Map> receiver_map,
3776 bool smi_and_map_check) { 3857 bool smi_and_map_check) {
3777 // Constant functions have the nice property that the map will change if they 3858 // Constant functions have the nice property that the map will change if they
3778 // are overwritten. Therefore it is enough to check the map of the holder and 3859 // are overwritten. Therefore it is enough to check the map of the holder and
3779 // its prototypes. 3860 // its prototypes.
3780 if (smi_and_map_check) { 3861 if (smi_and_map_check) {
3781 AddInstruction(new HCheckNonSmi(receiver)); 3862 AddInstruction(new HCheckNonSmi(receiver));
3782 AddInstruction(new HCheckMap(receiver, receiver_map)); 3863 AddInstruction(new HCheckMap(receiver, receiver_map));
3783 } 3864 }
3784 if (!expr->holder().is_null()) { 3865 if (!expr->holder().is_null()) {
3785 AddInstruction(new HCheckPrototypeMaps(receiver, 3866 AddInstruction(new HCheckPrototypeMaps(
3786 expr->holder(), 3867 Handle<JSObject>(JSObject::cast(receiver_map->prototype())),
3787 receiver_map)); 3868 expr->holder()));
3788 } 3869 }
3789 } 3870 }
3790 3871
3791 3872
3792 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, 3873 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
3793 HValue* receiver, 3874 HValue* receiver,
3794 ZoneMapList* types, 3875 ZoneMapList* types,
3795 Handle<String> name) { 3876 Handle<String> name) {
3796 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 3877 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
3797 int number_of_types = Min(types->length(), kMaxCallPolymorphism); 3878 int number_of_types = Min(types->length(), kMaxCallPolymorphism);
3798 ZoneMapList maps(number_of_types); 3879 ZoneMapList maps(number_of_types);
3799 ZoneList<HSubgraph*> subgraphs(number_of_types + 1); 3880 ZoneList<HSubgraph*> subgraphs(number_of_types);
3800 bool needs_generic = (types->length() > kMaxCallPolymorphism); 3881 bool needs_generic = (types->length() > kMaxCallPolymorphism);
3801 3882
3802 // Build subgraphs for each of the specific maps. 3883 // Build subgraphs for each of the specific maps.
3803 // 3884 //
3804 // TODO(ager): We should recognize when the prototype chains for different 3885 // TODO(ager): We should recognize when the prototype chains for different
3805 // maps are identical. In that case we can avoid repeatedly generating the 3886 // maps are identical. In that case we can avoid repeatedly generating the
3806 // same prototype map checks. 3887 // same prototype map checks.
3807 for (int i = 0; i < number_of_types; ++i) { 3888 for (int i = 0; i < number_of_types; ++i) {
3808 Handle<Map> map = types->at(i); 3889 Handle<Map> map = types->at(i);
3809 if (expr->ComputeTarget(map, name)) { 3890 if (expr->ComputeTarget(map, name)) {
3810 maps.Add(map);
3811 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3891 HSubgraph* subgraph = CreateBranchSubgraph(environment());
3812 SubgraphScope scope(this, subgraph); 3892 SubgraphScope scope(this, subgraph);
3813 AddCheckConstantFunction(expr, receiver, map, false); 3893 AddCheckConstantFunction(expr, receiver, map, false);
3814 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { 3894 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) {
3815 PrintF("Trying to inline the polymorphic call to %s\n", 3895 PrintF("Trying to inline the polymorphic call to %s\n",
3816 *name->ToCString()); 3896 *name->ToCString());
3817 } 3897 }
3818 if (!FLAG_polymorphic_inlining || !TryInline(expr)) { 3898 if (!FLAG_polymorphic_inlining || !TryInline(expr)) {
3819 // Check for bailout, as trying to inline might fail due to bailout 3899 // Check for bailout, as trying to inline might fail due to bailout
3820 // during hydrogen processing. 3900 // during hydrogen processing.
3821 CHECK_BAILOUT; 3901 CHECK_BAILOUT;
3822 HCall* call = new HCallConstantFunction(expr->target(), argument_count); 3902 HCall* call = new HCallConstantFunction(expr->target(), argument_count);
3823 call->set_position(expr->position()); 3903 call->set_position(expr->position());
3824 ProcessCall(call); 3904 PreProcessCall(call);
3825 PushAndAdd(call); 3905 PushAndAdd(call);
3826 } 3906 }
3907 maps.Add(map);
3827 subgraphs.Add(subgraph); 3908 subgraphs.Add(subgraph);
3828 } else { 3909 } else {
3829 needs_generic = true; 3910 needs_generic = true;
3830 } 3911 }
3831 } 3912 }
3832 3913
3833 // If we couldn't compute the target for any of the maps just perform an 3914 // If we couldn't compute the target for any of the maps just perform an
3834 // IC call. 3915 // IC call.
3835 if (maps.length() == 0) { 3916 if (maps.length() == 0) {
3836 HCall* call = new HCallNamed(name, argument_count); 3917 HContext* context = new HContext;
3918 AddInstruction(context);
3919 HCall* call = new HCallNamed(context, name, argument_count);
3837 call->set_position(expr->position()); 3920 call->set_position(expr->position());
3838 ProcessCall(call); 3921 PreProcessCall(call);
3839 ast_context()->ReturnInstruction(call, expr->id()); 3922 ast_context()->ReturnInstruction(call, expr->id());
3840 } else { 3923 } else {
3841 // Build subgraph for generic call through IC. 3924 // Build subgraph for generic call through IC.
3842 { 3925 HSubgraph* default_graph = CreateBranchSubgraph(environment());
3843 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3926 { SubgraphScope scope(this, default_graph);
3844 SubgraphScope scope(this, subgraph);
3845 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { 3927 if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3846 subgraph->FinishExit(new HDeoptimize()); 3928 default_graph->FinishExit(new HDeoptimize());
3847 } else { 3929 } else {
3848 HCall* call = new HCallNamed(name, argument_count); 3930 HContext* context = new HContext;
3931 AddInstruction(context);
3932 HCall* call = new HCallNamed(context, name, argument_count);
3849 call->set_position(expr->position()); 3933 call->set_position(expr->position());
3850 ProcessCall(call); 3934 PreProcessCall(call);
3851 PushAndAdd(call); 3935 PushAndAdd(call);
3852 } 3936 }
3853 subgraphs.Add(subgraph);
3854 } 3937 }
3855 3938
3856 HBasicBlock* new_exit_block = 3939 HBasicBlock* new_exit_block =
3857 BuildTypeSwitch(&maps, &subgraphs, receiver, expr->id()); 3940 BuildTypeSwitch(receiver, &maps, &subgraphs, default_graph, expr->id());
3858 subgraph()->set_exit_block(new_exit_block); 3941 subgraph()->set_exit_block(new_exit_block);
3859 if (new_exit_block != NULL) ast_context()->ReturnValue(Pop()); 3942 // In an effect context, we did not materialized the value in the
3943 // predecessor environments so there's no need to handle it here.
3944 if (new_exit_block != NULL && !ast_context()->IsEffect()) {
3945 ast_context()->ReturnValue(Pop());
3946 }
3860 } 3947 }
3861 } 3948 }
3862 3949
3863 3950
3864 void HGraphBuilder::TraceInline(Handle<JSFunction> target, bool result) { 3951 void HGraphBuilder::TraceInline(Handle<JSFunction> target, bool result) {
3865 SmartPointer<char> callee = target->shared()->DebugName()->ToCString(); 3952 SmartPointer<char> callee = target->shared()->DebugName()->ToCString();
3866 SmartPointer<char> caller = 3953 SmartPointer<char> caller =
3867 graph()->info()->function()->debug_name()->ToCString(); 3954 graph()->info()->function()->debug_name()->ToCString();
3868 if (result) { 3955 if (result) {
3869 PrintF("Inlined %s called from %s.\n", *callee, *caller); 3956 PrintF("Inlined %s called from %s.\n", *callee, *caller);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
3907 3994
3908 // We don't want to add more than a certain number of nodes from inlining. 3995 // We don't want to add more than a certain number of nodes from inlining.
3909 if (FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) { 3996 if (FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) {
3910 if (FLAG_trace_inlining) TraceInline(target, false); 3997 if (FLAG_trace_inlining) TraceInline(target, false);
3911 return false; 3998 return false;
3912 } 3999 }
3913 4000
3914 int count_before = AstNode::Count(); 4001 int count_before = AstNode::Count();
3915 4002
3916 // Parse and allocate variables. 4003 // Parse and allocate variables.
3917 Handle<SharedFunctionInfo> shared(target->shared()); 4004 CompilationInfo inner_info(target);
3918 CompilationInfo inner_info(shared);
3919 if (!ParserApi::Parse(&inner_info) || 4005 if (!ParserApi::Parse(&inner_info) ||
3920 !Scope::Analyze(&inner_info)) { 4006 !Scope::Analyze(&inner_info)) {
4007 if (Top::has_pending_exception()) {
4008 SetStackOverflow();
4009 }
3921 return false; 4010 return false;
3922 } 4011 }
3923 FunctionLiteral* function = inner_info.function(); 4012 FunctionLiteral* function = inner_info.function();
3924 4013
3925 // Count the number of AST nodes added by inlining this call. 4014 // Count the number of AST nodes added by inlining this call.
3926 int nodes_added = AstNode::Count() - count_before; 4015 int nodes_added = AstNode::Count() - count_before;
3927 if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) { 4016 if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) {
3928 if (FLAG_trace_inlining) TraceInline(target, false); 4017 if (FLAG_trace_inlining) TraceInline(target, false);
3929 return false; 4018 return false;
3930 } 4019 }
3931 4020
3932 // Check if we can handle all declarations in the inlined functions. 4021 // Check if we can handle all declarations in the inlined functions.
3933 VisitDeclarations(inner_info.scope()->declarations()); 4022 VisitDeclarations(inner_info.scope()->declarations());
3934 if (HasStackOverflow()) { 4023 if (HasStackOverflow()) {
3935 ClearStackOverflow(); 4024 ClearStackOverflow();
3936 return false; 4025 return false;
3937 } 4026 }
3938 4027
3939 // Don't inline functions that uses the arguments object or that 4028 // Don't inline functions that uses the arguments object or that
3940 // have a mismatching number of parameters. 4029 // have a mismatching number of parameters.
4030 Handle<SharedFunctionInfo> shared(target->shared());
3941 int arity = expr->arguments()->length(); 4031 int arity = expr->arguments()->length();
3942 if (function->scope()->arguments() != NULL || 4032 if (function->scope()->arguments() != NULL ||
3943 arity != target->shared()->formal_parameter_count()) { 4033 arity != shared->formal_parameter_count()) {
3944 return false; 4034 return false;
3945 } 4035 }
3946 4036
3947 // All statements in the body must be inlineable. 4037 // All statements in the body must be inlineable.
3948 for (int i = 0, count = function->body()->length(); i < count; ++i) { 4038 for (int i = 0, count = function->body()->length(); i < count; ++i) {
3949 if (!function->body()->at(i)->IsInlineable()) return false; 4039 if (!function->body()->at(i)->IsInlineable()) return false;
3950 } 4040 }
3951 4041
3952 // Generate the deoptimization data for the unoptimized version of 4042 // Generate the deoptimization data for the unoptimized version of
3953 // the target function if we don't already have it. 4043 // the target function if we don't already have it.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
3985 if_false->MarkAsInlineReturnTarget(); 4075 if_false->MarkAsInlineReturnTarget();
3986 // AstContext constructor pushes on the context stack. 4076 // AstContext constructor pushes on the context stack.
3987 test_context = new TestContext(this, if_true, if_false); 4077 test_context = new TestContext(this, if_true, if_false);
3988 function_return_ = NULL; 4078 function_return_ = NULL;
3989 } else { 4079 } else {
3990 // Inlined body is treated as if it occurs in the original call context. 4080 // Inlined body is treated as if it occurs in the original call context.
3991 function_return_ = graph()->CreateBasicBlock(); 4081 function_return_ = graph()->CreateBasicBlock();
3992 function_return_->MarkAsInlineReturnTarget(); 4082 function_return_->MarkAsInlineReturnTarget();
3993 } 4083 }
3994 call_context_ = ast_context(); 4084 call_context_ = ast_context();
3995 TypeFeedbackOracle new_oracle(Handle<Code>(shared->code())); 4085 TypeFeedbackOracle new_oracle(
4086 Handle<Code>(shared->code()),
4087 Handle<Context>(target->context()->global_context()));
3996 oracle_ = &new_oracle; 4088 oracle_ = &new_oracle;
3997 graph()->info()->SetOsrAstId(AstNode::kNoNumber); 4089 graph()->info()->SetOsrAstId(AstNode::kNoNumber);
3998 4090
3999 HSubgraph* body = CreateInlinedSubgraph(env, target, function); 4091 HSubgraph* body = CreateInlinedSubgraph(env, target, function);
4000 body->exit_block()->AddInstruction(new HEnterInlined(target, function)); 4092 body->exit_block()->AddInstruction(new HEnterInlined(target, function));
4001 AddToSubgraph(body, function->body()); 4093 AddToSubgraph(body, function->body());
4002 if (HasStackOverflow()) { 4094 if (HasStackOverflow()) {
4003 // Bail out if the inline function did, as we cannot residualize a call 4095 // Bail out if the inline function did, as we cannot residualize a call
4004 // instead. 4096 // instead.
4005 delete test_context; 4097 delete test_context;
(...skipping 17 matching lines...) Expand all
4023 ASSERT(function_return_ != NULL); 4115 ASSERT(function_return_ != NULL);
4024 body->exit_block()->AddLeaveInlined(return_value, function_return_); 4116 body->exit_block()->AddLeaveInlined(return_value, function_return_);
4025 } else { 4117 } else {
4026 // The graph builder assumes control can reach both branches of a 4118 // The graph builder assumes control can reach both branches of a
4027 // test, so we materialize the undefined value and test it rather than 4119 // test, so we materialize the undefined value and test it rather than
4028 // simply jumping to the false target. 4120 // simply jumping to the false target.
4029 // 4121 //
4030 // TODO(3168478): refactor to avoid this. 4122 // TODO(3168478): refactor to avoid this.
4031 HBasicBlock* empty_true = graph()->CreateBasicBlock(); 4123 HBasicBlock* empty_true = graph()->CreateBasicBlock();
4032 HBasicBlock* empty_false = graph()->CreateBasicBlock(); 4124 HBasicBlock* empty_false = graph()->CreateBasicBlock();
4033 HBranch* branch = 4125 HTest* test = new HTest(return_value, empty_true, empty_false);
4034 new HBranch(empty_true, empty_false, return_value); 4126 body->exit_block()->Finish(test);
4035 body->exit_block()->Finish(branch);
4036 4127
4037 HValue* const no_return_value = NULL; 4128 HValue* const no_return_value = NULL;
4038 empty_true->AddLeaveInlined(no_return_value, test_context->if_true()); 4129 empty_true->AddLeaveInlined(no_return_value, test_context->if_true());
4039 empty_false->AddLeaveInlined(no_return_value, test_context->if_false()); 4130 empty_false->AddLeaveInlined(no_return_value, test_context->if_false());
4040 } 4131 }
4041 body->set_exit_block(NULL); 4132 body->set_exit_block(NULL);
4042 } 4133 }
4043 4134
4044 // Record the environment at the inlined function call. 4135 // Record the environment at the inlined function call.
4045 AddSimulate(expr->ReturnId()); 4136 AddSimulate(expr->ReturnId());
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
4094 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { 4185 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) {
4095 ASSERT(target->IsInlineReturnTarget()); 4186 ASSERT(target->IsInlineReturnTarget());
4096 AddInstruction(new HLeaveInlined); 4187 AddInstruction(new HLeaveInlined);
4097 HEnvironment* outer = last_environment()->outer(); 4188 HEnvironment* outer = last_environment()->outer();
4098 if (return_value != NULL) outer->Push(return_value); 4189 if (return_value != NULL) outer->Push(return_value);
4099 UpdateEnvironment(outer); 4190 UpdateEnvironment(outer);
4100 Goto(target); 4191 Goto(target);
4101 } 4192 }
4102 4193
4103 4194
4104 bool HGraphBuilder::TryMathFunctionInline(Call* expr) { 4195 bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr,
4196 HValue* receiver,
4197 Handle<Map> receiver_map,
4198 CheckType check_type) {
4199 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null());
4105 // Try to inline calls like Math.* as operations in the calling function. 4200 // Try to inline calls like Math.* as operations in the calling function.
4106 if (!expr->target()->shared()->IsBuiltinMathFunction()) return false; 4201 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
4107 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 4202 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
4108 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4203 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
4109 switch (id) { 4204 switch (id) {
4205 case kStringCharCodeAt:
4206 if (argument_count == 2 && check_type == STRING_CHECK) {
4207 HValue* index = Pop();
4208 HValue* string = Pop();
4209 ASSERT(!expr->holder().is_null());
4210 AddInstruction(new HCheckPrototypeMaps(
4211 oracle()->GetPrototypeForPrimitiveCheck(STRING_CHECK),
4212 expr->holder()));
4213 HStringCharCodeAt* result = BuildStringCharCodeAt(string, index);
4214 ast_context()->ReturnInstruction(result, expr->id());
4215 return true;
4216 }
4217 break;
4110 case kMathRound: 4218 case kMathRound:
4111 case kMathFloor: 4219 case kMathFloor:
4112 case kMathAbs: 4220 case kMathAbs:
4113 case kMathSqrt: 4221 case kMathSqrt:
4114 case kMathLog: 4222 case kMathLog:
4115 case kMathSin: 4223 case kMathSin:
4116 case kMathCos: 4224 case kMathCos:
4117 if (argument_count == 2) { 4225 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) {
4226 AddCheckConstantFunction(expr, receiver, receiver_map, true);
4118 HValue* argument = Pop(); 4227 HValue* argument = Pop();
4119 Drop(1); // Receiver. 4228 Drop(1); // Receiver.
4120 HUnaryMathOperation* op = new HUnaryMathOperation(argument, id); 4229 HUnaryMathOperation* op = new HUnaryMathOperation(argument, id);
4121 op->set_position(expr->position()); 4230 op->set_position(expr->position());
4122 ast_context()->ReturnInstruction(op, expr->id()); 4231 ast_context()->ReturnInstruction(op, expr->id());
4123 return true; 4232 return true;
4124 } 4233 }
4125 break; 4234 break;
4126 case kMathPow: 4235 case kMathPow:
4127 if (argument_count == 3) { 4236 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
4237 AddCheckConstantFunction(expr, receiver, receiver_map, true);
4128 HValue* right = Pop(); 4238 HValue* right = Pop();
4129 HValue* left = Pop(); 4239 HValue* left = Pop();
4130 Pop(); // Pop receiver. 4240 Pop(); // Pop receiver.
4131 HInstruction* result = NULL; 4241 HInstruction* result = NULL;
4132 // Use sqrt() if exponent is 0.5 or -0.5. 4242 // Use sqrt() if exponent is 0.5 or -0.5.
4133 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { 4243 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
4134 double exponent = HConstant::cast(right)->DoubleValue(); 4244 double exponent = HConstant::cast(right)->DoubleValue();
4135 if (exponent == 0.5) { 4245 if (exponent == 0.5) {
4136 result = new HUnaryMathOperation(left, kMathPowHalf); 4246 result = new HUnaryMathOperation(left, kMathPowHalf);
4137 ast_context()->ReturnInstruction(result, expr->id());
4138 return true;
4139 } else if (exponent == -0.5) { 4247 } else if (exponent == -0.5) {
4140 HConstant* double_one = 4248 HConstant* double_one =
4141 new HConstant(Handle<Object>(Smi::FromInt(1)), 4249 new HConstant(Handle<Object>(Smi::FromInt(1)),
4142 Representation::Double()); 4250 Representation::Double());
4143 AddInstruction(double_one); 4251 AddInstruction(double_one);
4144 HUnaryMathOperation* square_root = 4252 HUnaryMathOperation* square_root =
4145 new HUnaryMathOperation(left, kMathPowHalf); 4253 new HUnaryMathOperation(left, kMathPowHalf);
4146 AddInstruction(square_root); 4254 AddInstruction(square_root);
4147 // MathPowHalf doesn't have side effects so there's no need for 4255 // MathPowHalf doesn't have side effects so there's no need for
4148 // an environment simulation here. 4256 // an environment simulation here.
4149 ASSERT(!square_root->HasSideEffects()); 4257 ASSERT(!square_root->HasSideEffects());
4150 result = new HDiv(double_one, square_root); 4258 result = new HDiv(double_one, square_root);
4151 ast_context()->ReturnInstruction(result, expr->id());
4152 return true;
4153 } else if (exponent == 2.0) { 4259 } else if (exponent == 2.0) {
4154 result = new HMul(left, left); 4260 result = new HMul(left, left);
4155 ast_context()->ReturnInstruction(result, expr->id());
4156 return true;
4157 } 4261 }
4158 } else if (right->IsConstant() && 4262 } else if (right->IsConstant() &&
4159 HConstant::cast(right)->HasInteger32Value() && 4263 HConstant::cast(right)->HasInteger32Value() &&
4160 HConstant::cast(right)->Integer32Value() == 2) { 4264 HConstant::cast(right)->Integer32Value() == 2) {
4161 result = new HMul(left, left); 4265 result = new HMul(left, left);
4162 ast_context()->ReturnInstruction(result, expr->id());
4163 return true;
4164 } 4266 }
4165 4267
4166 result = new HPower(left, right); 4268 if (result == NULL) {
4269 result = new HPower(left, right);
4270 }
4167 ast_context()->ReturnInstruction(result, expr->id()); 4271 ast_context()->ReturnInstruction(result, expr->id());
4168 return true; 4272 return true;
4169 } 4273 }
4170 break; 4274 break;
4171 default: 4275 default:
4172 // Not yet supported for inlining. 4276 // Not yet supported for inlining.
4173 break; 4277 break;
4174 } 4278 }
4175 return false; 4279 return false;
4176 } 4280 }
(...skipping 10 matching lines...) Expand all
4187 if (!name->IsEqualTo(CStrVector("apply"))) return false; 4291 if (!name->IsEqualTo(CStrVector("apply"))) return false;
4188 4292
4189 ZoneList<Expression*>* args = expr->arguments(); 4293 ZoneList<Expression*>* args = expr->arguments();
4190 if (args->length() != 2) return false; 4294 if (args->length() != 2) return false;
4191 4295
4192 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); 4296 VariableProxy* arg_two = args->at(1)->AsVariableProxy();
4193 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; 4297 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
4194 HValue* arg_two_value = environment()->Lookup(arg_two->var()); 4298 HValue* arg_two_value = environment()->Lookup(arg_two->var());
4195 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; 4299 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
4196 4300
4197 if (!expr->IsMonomorphic()) return false; 4301 if (!expr->IsMonomorphic() ||
4302 expr->check_type() != RECEIVER_MAP_CHECK) return false;
4198 4303
4199 // Found pattern f.apply(receiver, arguments). 4304 // Found pattern f.apply(receiver, arguments).
4200 VisitForValue(prop->obj()); 4305 VisitForValue(prop->obj());
4201 if (HasStackOverflow()) return false; 4306 if (HasStackOverflow()) return false;
4202 HValue* function = Pop(); 4307 HValue* function = Pop();
4203 VisitForValue(args->at(0)); 4308 VisitForValue(args->at(0));
4204 if (HasStackOverflow()) return false; 4309 if (HasStackOverflow()) return false;
4205 HValue* receiver = Pop(); 4310 HValue* receiver = Pop();
4206 HInstruction* elements = AddInstruction(new HArgumentsElements); 4311 HInstruction* elements = AddInstruction(new HArgumentsElements);
4207 HInstruction* length = AddInstruction(new HArgumentsLength(elements)); 4312 HInstruction* length = AddInstruction(new HArgumentsLength(elements));
4208 AddCheckConstantFunction(expr, 4313 AddCheckConstantFunction(expr,
4209 function, 4314 function,
4210 expr->GetReceiverTypes()->first(), 4315 expr->GetReceiverTypes()->first(),
4211 true); 4316 true);
4212 HInstruction* result = 4317 HInstruction* result =
4213 new HApplyArguments(function, receiver, length, elements); 4318 new HApplyArguments(function, receiver, length, elements);
4214 result->set_position(expr->position()); 4319 result->set_position(expr->position());
4215 ast_context()->ReturnInstruction(result, expr->id()); 4320 ast_context()->ReturnInstruction(result, expr->id());
4216 return true; 4321 return true;
4217 } 4322 }
4218 4323
4219 4324
4325 static bool HasCustomCallGenerator(Handle<JSFunction> function) {
4326 SharedFunctionInfo* info = function->shared();
4327 return info->HasBuiltinFunctionId() &&
4328 CallStubCompiler::HasCustomCallGenerator(info->builtin_function_id());
4329 }
4330
4331
4220 void HGraphBuilder::VisitCall(Call* expr) { 4332 void HGraphBuilder::VisitCall(Call* expr) {
4221 Expression* callee = expr->expression(); 4333 Expression* callee = expr->expression();
4222 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4334 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
4223 HCall* call = NULL; 4335 HCall* call = NULL;
4224 4336
4225 Property* prop = callee->AsProperty(); 4337 Property* prop = callee->AsProperty();
4226 if (prop != NULL) { 4338 if (prop != NULL) {
4227 if (!prop->key()->IsPropertyName()) { 4339 if (!prop->key()->IsPropertyName()) {
4228 // Keyed function call. 4340 // Keyed function call.
4229 VisitArgument(prop->obj()); 4341 VisitArgument(prop->obj());
4230 CHECK_BAILOUT; 4342 CHECK_BAILOUT;
4231 4343
4232 VISIT_FOR_VALUE(prop->key()); 4344 VISIT_FOR_VALUE(prop->key());
4233 // Push receiver and key like the non-optimized code generator expects it. 4345 // Push receiver and key like the non-optimized code generator expects it.
4234 HValue* key = Pop(); 4346 HValue* key = Pop();
4235 HValue* receiver = Pop(); 4347 HValue* receiver = Pop();
4236 Push(key); 4348 Push(key);
4237 Push(receiver); 4349 Push(receiver);
4238 4350
4239 VisitArgumentList(expr->arguments()); 4351 VisitArgumentList(expr->arguments());
4240 CHECK_BAILOUT; 4352 CHECK_BAILOUT;
4241 4353
4242 call = new HCallKeyed(key, argument_count); 4354 HContext* context = new HContext;
4355 AddInstruction(context);
4356 call = new HCallKeyed(context, key, argument_count);
4243 call->set_position(expr->position()); 4357 call->set_position(expr->position());
4244 ProcessCall(call); 4358 PreProcessCall(call);
4245 Drop(1); // Key. 4359 Drop(1); // Key.
4246 ast_context()->ReturnInstruction(call, expr->id()); 4360 ast_context()->ReturnInstruction(call, expr->id());
4247 return; 4361 return;
4248 } 4362 }
4249 4363
4250 // Named function call. 4364 // Named function call.
4251 expr->RecordTypeFeedback(oracle()); 4365 expr->RecordTypeFeedback(oracle());
4252 4366
4253 if (TryCallApply(expr)) return; 4367 if (TryCallApply(expr)) return;
4254 CHECK_BAILOUT; 4368 CHECK_BAILOUT;
4255 4369
4256 HValue* receiver = VisitArgument(prop->obj()); 4370 VisitArgument(prop->obj());
4257 CHECK_BAILOUT; 4371 CHECK_BAILOUT;
4258 VisitArgumentList(expr->arguments()); 4372 VisitArgumentList(expr->arguments());
4259 CHECK_BAILOUT; 4373 CHECK_BAILOUT;
4260 4374
4261 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4375 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4262 4376
4263 expr->RecordTypeFeedback(oracle()); 4377 expr->RecordTypeFeedback(oracle());
4264 ZoneMapList* types = expr->GetReceiverTypes(); 4378 ZoneMapList* types = expr->GetReceiverTypes();
4265 4379
4380 HValue* receiver =
4381 environment()->ExpressionStackAt(expr->arguments()->length());
4266 if (expr->IsMonomorphic()) { 4382 if (expr->IsMonomorphic()) {
4267 AddCheckConstantFunction(expr, receiver, types->first(), true); 4383 Handle<Map> receiver_map =
4268 4384 (types == NULL) ? Handle<Map>::null() : types->first();
4269 if (TryMathFunctionInline(expr)) { 4385 if (TryInlineBuiltinFunction(expr,
4386 receiver,
4387 receiver_map,
4388 expr->check_type())) {
4270 return; 4389 return;
4271 } else if (TryInline(expr)) {
4272 if (subgraph()->HasExit()) {
4273 HValue* return_value = Pop();
4274 // If we inlined a function in a test context then we need to emit
4275 // a simulate here to shadow the ones at the end of the
4276 // predecessor blocks. Those environments contain the return
4277 // value on top and do not correspond to any actual state of the
4278 // unoptimized code.
4279 if (ast_context()->IsEffect()) AddSimulate(expr->id());
4280 ast_context()->ReturnValue(return_value);
4281 }
4282 return;
4283 } else {
4284 // Check for bailout, as the TryInline call in the if condition above
4285 // might return false due to bailout during hydrogen processing.
4286 CHECK_BAILOUT;
4287 call = new HCallConstantFunction(expr->target(), argument_count);
4288 } 4390 }
4289 4391
4392 if (HasCustomCallGenerator(expr->target()) ||
4393 expr->check_type() != RECEIVER_MAP_CHECK) {
4394 // When the target has a custom call IC generator, use the IC,
4395 // because it is likely to generate better code. Also use the
4396 // IC when a primitive receiver check is required.
4397 HContext* context = new HContext;
4398 AddInstruction(context);
4399 call = new HCallNamed(context, name, argument_count);
4400 } else {
4401 AddCheckConstantFunction(expr, receiver, receiver_map, true);
4402
4403 if (TryInline(expr)) {
4404 if (subgraph()->HasExit()) {
4405 HValue* return_value = Pop();
4406 // If we inlined a function in a test context then we need to emit
4407 // a simulate here to shadow the ones at the end of the
4408 // predecessor blocks. Those environments contain the return
4409 // value on top and do not correspond to any actual state of the
4410 // unoptimized code.
4411 if (ast_context()->IsEffect()) AddSimulate(expr->id());
4412 ast_context()->ReturnValue(return_value);
4413 }
4414 return;
4415 } else {
4416 // Check for bailout, as the TryInline call in the if condition above
4417 // might return false due to bailout during hydrogen processing.
4418 CHECK_BAILOUT;
4419 call = new HCallConstantFunction(expr->target(), argument_count);
4420 }
4421 }
4290 } else if (types != NULL && types->length() > 1) { 4422 } else if (types != NULL && types->length() > 1) {
4423 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK);
4291 HandlePolymorphicCallNamed(expr, receiver, types, name); 4424 HandlePolymorphicCallNamed(expr, receiver, types, name);
4292 return; 4425 return;
4293 4426
4294 } else { 4427 } else {
4295 call = new HCallNamed(name, argument_count); 4428 HContext* context = new HContext;
4429 AddInstruction(context);
4430 call = new HCallNamed(context, name, argument_count);
4296 } 4431 }
4297 4432
4298 } else { 4433 } else {
4299 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 4434 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
4300 bool global_call = (var != NULL) && var->is_global() && !var->is_this(); 4435 bool global_call = (var != NULL) && var->is_global() && !var->is_this();
4301 4436
4302 if (!global_call) { 4437 if (!global_call) {
4303 ++argument_count; 4438 ++argument_count;
4304 VisitArgument(expr->expression()); 4439 VisitArgument(expr->expression());
4305 CHECK_BAILOUT; 4440 CHECK_BAILOUT;
4306 } 4441 }
4307 4442
4308 if (global_call) { 4443 if (global_call) {
4309 // If there is a global property cell for the name at compile time and 4444 // If there is a global property cell for the name at compile time and
4310 // access check is not enabled we assume that the function will not change 4445 // access check is not enabled we assume that the function will not change
4311 // and generate optimized code for calling the function. 4446 // and generate optimized code for calling the function.
4312 CompilationInfo* info = graph()->info(); 4447 CompilationInfo* info = graph()->info();
4313 bool known_global_function = info->has_global_object() && 4448 bool known_global_function = info->has_global_object() &&
4314 !info->global_object()->IsAccessCheckNeeded() && 4449 !info->global_object()->IsAccessCheckNeeded() &&
4315 expr->ComputeGlobalTarget(Handle<GlobalObject>(info->global_object()), 4450 expr->ComputeGlobalTarget(Handle<GlobalObject>(info->global_object()),
4316 var->name()); 4451 var->name());
4317 if (known_global_function) { 4452 if (known_global_function) {
4318 // Push the global object instead of the global receiver because 4453 // Push the global object instead of the global receiver because
4319 // code generated by the full code generator expects it. 4454 // code generated by the full code generator expects it.
4320 PushAndAdd(new HGlobalObject); 4455 HContext* context = new HContext;
4456 HGlobalObject* global_object = new HGlobalObject(context);
4457 AddInstruction(context);
4458 PushAndAdd(global_object);
4321 VisitArgumentList(expr->arguments()); 4459 VisitArgumentList(expr->arguments());
4322 CHECK_BAILOUT; 4460 CHECK_BAILOUT;
4323 4461
4324 VISIT_FOR_VALUE(expr->expression()); 4462 VISIT_FOR_VALUE(expr->expression());
4325 HValue* function = Pop(); 4463 HValue* function = Pop();
4326 AddInstruction(new HCheckFunction(function, expr->target())); 4464 AddInstruction(new HCheckFunction(function, expr->target()));
4327 4465
4328 // Replace the global object with the global receiver. 4466 // Replace the global object with the global receiver.
4329 HGlobalReceiver* global_receiver = new HGlobalReceiver; 4467 HGlobalReceiver* global_receiver = new HGlobalReceiver(global_object);
4330 // Index of the receiver from the top of the expression stack. 4468 // Index of the receiver from the top of the expression stack.
4331 const int receiver_index = argument_count - 1; 4469 const int receiver_index = argument_count - 1;
4332 AddInstruction(global_receiver); 4470 AddInstruction(global_receiver);
4333 ASSERT(environment()->ExpressionStackAt(receiver_index)-> 4471 ASSERT(environment()->ExpressionStackAt(receiver_index)->
4334 IsGlobalObject()); 4472 IsGlobalObject());
4335 environment()->SetExpressionStackAt(receiver_index, global_receiver); 4473 environment()->SetExpressionStackAt(receiver_index, global_receiver);
4336 4474
4337 if (TryInline(expr)) { 4475 if (TryInline(expr)) {
4338 if (subgraph()->HasExit()) { 4476 if (subgraph()->HasExit()) {
4339 HValue* return_value = Pop(); 4477 HValue* return_value = Pop();
4340 // If we inlined a function in a test context then we need to 4478 // If we inlined a function in a test context then we need to
4341 // emit a simulate here to shadow the ones at the end of the 4479 // emit a simulate here to shadow the ones at the end of the
4342 // predecessor blocks. Those environments contain the return 4480 // predecessor blocks. Those environments contain the return
4343 // value on top and do not correspond to any actual state of the 4481 // value on top and do not correspond to any actual state of the
4344 // unoptimized code. 4482 // unoptimized code.
4345 if (ast_context()->IsEffect()) AddSimulate(expr->id()); 4483 if (ast_context()->IsEffect()) AddSimulate(expr->id());
4346 ast_context()->ReturnValue(return_value); 4484 ast_context()->ReturnValue(return_value);
4347 } 4485 }
4348 return; 4486 return;
4349 } 4487 }
4350 // Check for bailout, as trying to inline might fail due to bailout 4488 // Check for bailout, as trying to inline might fail due to bailout
4351 // during hydrogen processing. 4489 // during hydrogen processing.
4352 CHECK_BAILOUT; 4490 CHECK_BAILOUT;
4353 4491
4354 call = new HCallKnownGlobal(expr->target(), argument_count); 4492 call = new HCallKnownGlobal(expr->target(), argument_count);
4355 } else { 4493 } else {
4356 PushAndAdd(new HGlobalObject); 4494 HContext* context = new HContext;
4495 AddInstruction(context);
4496 PushAndAdd(new HGlobalObject(context));
4357 VisitArgumentList(expr->arguments()); 4497 VisitArgumentList(expr->arguments());
4358 CHECK_BAILOUT; 4498 CHECK_BAILOUT;
4359 4499
4360 call = new HCallGlobal(var->name(), argument_count); 4500 call = new HCallGlobal(context, var->name(), argument_count);
4361 } 4501 }
4362 4502
4363 } else { 4503 } else {
4364 PushAndAdd(new HGlobalReceiver); 4504 HContext* context = new HContext;
4505 HGlobalObject* global_object = new HGlobalObject(context);
4506 AddInstruction(context);
4507 AddInstruction(global_object);
4508 PushAndAdd(new HGlobalReceiver(global_object));
4365 VisitArgumentList(expr->arguments()); 4509 VisitArgumentList(expr->arguments());
4366 CHECK_BAILOUT; 4510 CHECK_BAILOUT;
4367 4511
4368 call = new HCallFunction(argument_count); 4512 call = new HCallFunction(context, argument_count);
4369 } 4513 }
4370 } 4514 }
4371 4515
4372 call->set_position(expr->position()); 4516 call->set_position(expr->position());
4373 ProcessCall(call); 4517 PreProcessCall(call);
4374 ast_context()->ReturnInstruction(call, expr->id()); 4518 ast_context()->ReturnInstruction(call, expr->id());
4375 } 4519 }
4376 4520
4377 4521
4378 void HGraphBuilder::VisitCallNew(CallNew* expr) { 4522 void HGraphBuilder::VisitCallNew(CallNew* expr) {
4379 // The constructor function is also used as the receiver argument to the 4523 // The constructor function is also used as the receiver argument to the
4380 // JS construct call builtin. 4524 // JS construct call builtin.
4381 VisitArgument(expr->expression()); 4525 VisitArgument(expr->expression());
4382 CHECK_BAILOUT; 4526 CHECK_BAILOUT;
4383 VisitArgumentList(expr->arguments()); 4527 VisitArgumentList(expr->arguments());
4384 CHECK_BAILOUT; 4528 CHECK_BAILOUT;
4385 4529
4386 int argument_count = expr->arguments()->length() + 1; // Plus constructor. 4530 HContext* context = new HContext;
4387 HCall* call = new HCallNew(argument_count); 4531 AddInstruction(context);
4532
4533 // The constructor is both an operand to the instruction and an argument
4534 // to the construct call.
4535 int arg_count = expr->arguments()->length() + 1; // Plus constructor.
4536 HValue* constructor = environment()->ExpressionStackAt(arg_count - 1);
4537 HCall* call = new HCallNew(context, constructor, arg_count);
4388 call->set_position(expr->position()); 4538 call->set_position(expr->position());
4389 ProcessCall(call); 4539 PreProcessCall(call);
4390 ast_context()->ReturnInstruction(call, expr->id()); 4540 ast_context()->ReturnInstruction(call, expr->id());
4391 } 4541 }
4392 4542
4393 4543
4394 // Support for generating inlined runtime functions. 4544 // Support for generating inlined runtime functions.
4395 4545
4396 // Lookup table for generators for runtime calls that are generated inline. 4546 // Lookup table for generators for runtime calls that are generated inline.
4397 // Elements of the table are member pointers to functions of HGraphBuilder. 4547 // Elements of the table are member pointers to functions of HGraphBuilder.
4398 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ 4548 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
4399 &HGraphBuilder::Generate##Name, 4549 &HGraphBuilder::Generate##Name,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
4433 ASSERT(static_cast<size_t>(lookup_index) < 4583 ASSERT(static_cast<size_t>(lookup_index) <
4434 ARRAY_SIZE(kInlineFunctionGenerators)); 4584 ARRAY_SIZE(kInlineFunctionGenerators));
4435 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; 4585 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
4436 4586
4437 // Call the inline code generator using the pointer-to-member. 4587 // Call the inline code generator using the pointer-to-member.
4438 (this->*generator)(argument_count, expr->id()); 4588 (this->*generator)(argument_count, expr->id());
4439 } else { 4589 } else {
4440 ASSERT(function->intrinsic_type == Runtime::RUNTIME); 4590 ASSERT(function->intrinsic_type == Runtime::RUNTIME);
4441 HCall* call = new HCallRuntime(name, expr->function(), argument_count); 4591 HCall* call = new HCallRuntime(name, expr->function(), argument_count);
4442 call->set_position(RelocInfo::kNoPosition); 4592 call->set_position(RelocInfo::kNoPosition);
4443 ProcessCall(call); 4593 PreProcessCall(call);
4444 ast_context()->ReturnInstruction(call, expr->id()); 4594 ast_context()->ReturnInstruction(call, expr->id());
4445 } 4595 }
4446 } 4596 }
4447 4597
4448 4598
4449 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { 4599 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
4450 Token::Value op = expr->op(); 4600 Token::Value op = expr->op();
4451 if (op == Token::VOID) { 4601 if (op == Token::VOID) {
4452 VISIT_FOR_EFFECT(expr->expression()); 4602 VISIT_FOR_EFFECT(expr->expression());
4453 ast_context()->ReturnValue(graph()->GetConstantUndefined()); 4603 ast_context()->ReturnValue(graph()->GetConstantUndefined());
4454 } else if (op == Token::DELETE) { 4604 } else if (op == Token::DELETE) {
4455 Property* prop = expr->expression()->AsProperty(); 4605 Property* prop = expr->expression()->AsProperty();
4456 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 4606 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
4457 if (prop == NULL && var == NULL) { 4607 if (prop == NULL && var == NULL) {
4458 // Result of deleting non-property, non-variable reference is true. 4608 // Result of deleting non-property, non-variable reference is true.
4459 // Evaluate the subexpression for side effects. 4609 // Evaluate the subexpression for side effects.
4460 VISIT_FOR_EFFECT(expr->expression()); 4610 VISIT_FOR_EFFECT(expr->expression());
4461 ast_context()->ReturnValue(graph()->GetConstantTrue()); 4611 ast_context()->ReturnValue(graph()->GetConstantTrue());
4462 } else if (var != NULL && 4612 } else if (var != NULL &&
4463 !var->is_global() && 4613 !var->is_global() &&
4464 var->AsSlot() != NULL && 4614 var->AsSlot() != NULL &&
4465 var->AsSlot()->type() != Slot::LOOKUP) { 4615 var->AsSlot()->type() != Slot::LOOKUP) {
4466 // Result of deleting non-global, non-dynamic variables is false. 4616 // Result of deleting non-global, non-dynamic variables is false.
4467 // The subexpression does not have side effects. 4617 // The subexpression does not have side effects.
4468 ast_context()->ReturnValue(graph()->GetConstantFalse()); 4618 ast_context()->ReturnValue(graph()->GetConstantFalse());
4469 } else if (prop != NULL) { 4619 } else if (prop != NULL) {
4470 VISIT_FOR_VALUE(prop->obj()); 4620 if (prop->is_synthetic()) {
4471 VISIT_FOR_VALUE(prop->key()); 4621 // Result of deleting parameters is false, even when they rewrite
4472 HValue* key = Pop(); 4622 // to accesses on the arguments object.
4473 HValue* obj = Pop(); 4623 ast_context()->ReturnValue(graph()->GetConstantFalse());
4474 ast_context()->ReturnInstruction(new HDeleteProperty(obj, key), 4624 } else {
4475 expr->id()); 4625 VISIT_FOR_VALUE(prop->obj());
4626 VISIT_FOR_VALUE(prop->key());
4627 HValue* key = Pop();
4628 HValue* obj = Pop();
4629 HDeleteProperty* instr = new HDeleteProperty(obj, key);
4630 ast_context()->ReturnInstruction(instr, expr->id());
4631 }
4476 } else if (var->is_global()) { 4632 } else if (var->is_global()) {
4477 BAILOUT("delete with global variable"); 4633 BAILOUT("delete with global variable");
4478 } else { 4634 } else {
4479 BAILOUT("delete with non-global variable"); 4635 BAILOUT("delete with non-global variable");
4480 } 4636 }
4481 } else if (op == Token::NOT) { 4637 } else if (op == Token::NOT) {
4482 if (ast_context()->IsTest()) { 4638 if (ast_context()->IsTest()) {
4483 TestContext* context = TestContext::cast(ast_context()); 4639 TestContext* context = TestContext::cast(ast_context());
4484 VisitForControl(expr->expression(), 4640 VisitForControl(expr->expression(),
4485 context->if_false(), 4641 context->if_false(),
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
4545 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { 4701 void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
4546 IncrementOperation* increment = expr->increment(); 4702 IncrementOperation* increment = expr->increment();
4547 Expression* target = increment->expression(); 4703 Expression* target = increment->expression();
4548 VariableProxy* proxy = target->AsVariableProxy(); 4704 VariableProxy* proxy = target->AsVariableProxy();
4549 Variable* var = proxy->AsVariable(); 4705 Variable* var = proxy->AsVariable();
4550 Property* prop = target->AsProperty(); 4706 Property* prop = target->AsProperty();
4551 ASSERT(var == NULL || prop == NULL); 4707 ASSERT(var == NULL || prop == NULL);
4552 bool inc = expr->op() == Token::INC; 4708 bool inc = expr->op() == Token::INC;
4553 4709
4554 if (var != NULL) { 4710 if (var != NULL) {
4555 if (!var->is_global() && !var->IsStackAllocated()) {
4556 BAILOUT("non-stack/non-global variable in count operation");
4557 }
4558
4559 VISIT_FOR_VALUE(target); 4711 VISIT_FOR_VALUE(target);
4560 4712
4561 // Match the full code generator stack by simulating an extra stack 4713 // Match the full code generator stack by simulating an extra stack
4562 // element for postfix operations in a non-effect context. 4714 // element for postfix operations in a non-effect context.
4563 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); 4715 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect();
4564 HValue* before = has_extra ? Top() : Pop(); 4716 HValue* before = has_extra ? Top() : Pop();
4565 HInstruction* after = BuildIncrement(before, inc); 4717 HInstruction* after = BuildIncrement(before, inc);
4566 AddInstruction(after); 4718 AddInstruction(after);
4567 Push(after); 4719 Push(after);
4568 4720
4569 if (var->is_global()) { 4721 if (var->is_global()) {
4570 HandleGlobalVariableAssignment(var, 4722 HandleGlobalVariableAssignment(var,
4571 after, 4723 after,
4572 expr->position(), 4724 expr->position(),
4573 expr->AssignmentId()); 4725 expr->AssignmentId());
4726 } else if (var->IsStackAllocated()) {
4727 Bind(var, after);
4728 } else if (var->IsContextSlot()) {
4729 HValue* context = BuildContextChainWalk(var);
4730 int index = var->AsSlot()->index();
4731 HStoreContextSlot* instr = new HStoreContextSlot(context, index, after);
4732 AddInstruction(instr);
4733 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
4574 } else { 4734 } else {
4575 ASSERT(var->IsStackAllocated()); 4735 BAILOUT("lookup variable in count operation");
4576 Bind(var, after);
4577 } 4736 }
4578 Drop(has_extra ? 2 : 1); 4737 Drop(has_extra ? 2 : 1);
4579 ast_context()->ReturnValue(expr->is_postfix() ? before : after); 4738 ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4580 4739
4581 } else if (prop != NULL) { 4740 } else if (prop != NULL) {
4582 prop->RecordTypeFeedback(oracle()); 4741 prop->RecordTypeFeedback(oracle());
4583 4742
4584 if (prop->key()->IsPropertyName()) { 4743 if (prop->key()->IsPropertyName()) {
4585 // Named property. 4744 // Named property.
4586 4745
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
4645 if (load->HasSideEffects()) AddSimulate(increment->id()); 4804 if (load->HasSideEffects()) AddSimulate(increment->id());
4646 4805
4647 HValue* before = Pop(); 4806 HValue* before = Pop();
4648 // There is no deoptimization to after the increment, so we don't need 4807 // There is no deoptimization to after the increment, so we don't need
4649 // to simulate the expression stack after this instruction. 4808 // to simulate the expression stack after this instruction.
4650 HInstruction* after = BuildIncrement(before, inc); 4809 HInstruction* after = BuildIncrement(before, inc);
4651 AddInstruction(after); 4810 AddInstruction(after);
4652 4811
4653 HInstruction* store = is_fast_elements 4812 HInstruction* store = is_fast_elements
4654 ? BuildStoreKeyedFastElement(obj, key, after, prop) 4813 ? BuildStoreKeyedFastElement(obj, key, after, prop)
4655 : new HStoreKeyedGeneric(obj, key, after); 4814 : BuildStoreKeyedGeneric(obj, key, after);
4656 AddInstruction(store); 4815 AddInstruction(store);
4657 4816
4658 // Drop the key from the bailout environment. Overwrite the receiver 4817 // Drop the key from the bailout environment. Overwrite the receiver
4659 // with the result of the operation, and the placeholder with the 4818 // with the result of the operation, and the placeholder with the
4660 // original value if necessary. 4819 // original value if necessary.
4661 Drop(1); 4820 Drop(1);
4662 environment()->SetExpressionStackAt(0, after); 4821 environment()->SetExpressionStackAt(0, after);
4663 if (has_extra) environment()->SetExpressionStackAt(1, before); 4822 if (has_extra) environment()->SetExpressionStackAt(1, before);
4664 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 4823 if (store->HasSideEffects()) AddSimulate(expr->AssignmentId());
4665 Drop(has_extra ? 2 : 1); 4824 Drop(has_extra ? 2 : 1);
4666 4825
4667 ast_context()->ReturnValue(expr->is_postfix() ? before : after); 4826 ast_context()->ReturnValue(expr->is_postfix() ? before : after);
4668 } 4827 }
4669 4828
4670 } else { 4829 } else {
4671 BAILOUT("invalid lhs in count operation"); 4830 BAILOUT("invalid lhs in count operation");
4672 } 4831 }
4673 } 4832 }
4674 4833
4675 4834
4835 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* string,
4836 HValue* index) {
4837 AddInstruction(new HCheckNonSmi(string));
4838 AddInstruction(new HCheckInstanceType(
4839 string, FIRST_STRING_TYPE, LAST_STRING_TYPE));
4840 HStringLength* length = new HStringLength(string);
4841 AddInstruction(length);
4842 AddInstruction(new HBoundsCheck(index, length));
4843 return new HStringCharCodeAt(string, index);
4844 }
4845
4846
4676 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, 4847 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
4677 HValue* left, 4848 HValue* left,
4678 HValue* right) { 4849 HValue* right) {
4679 HInstruction* instr = NULL; 4850 HInstruction* instr = NULL;
4680 switch (expr->op()) { 4851 switch (expr->op()) {
4681 case Token::ADD: 4852 case Token::ADD:
4682 instr = new HAdd(left, right); 4853 instr = new HAdd(left, right);
4683 break; 4854 break;
4684 case Token::SUB: 4855 case Token::SUB:
4685 instr = new HSub(left, right); 4856 instr = new HSub(left, right);
(...skipping 21 matching lines...) Expand all
4707 break; 4878 break;
4708 case Token::SHR: 4879 case Token::SHR:
4709 instr = new HShr(left, right); 4880 instr = new HShr(left, right);
4710 break; 4881 break;
4711 case Token::SHL: 4882 case Token::SHL:
4712 instr = new HShl(left, right); 4883 instr = new HShl(left, right);
4713 break; 4884 break;
4714 default: 4885 default:
4715 UNREACHABLE(); 4886 UNREACHABLE();
4716 } 4887 }
4717 TypeInfo info = oracle()->BinaryType(expr, TypeFeedbackOracle::RESULT); 4888 TypeInfo info = oracle()->BinaryType(expr);
4718 // If we hit an uninitialized binary op stub we will get type info 4889 // If we hit an uninitialized binary op stub we will get type info
4719 // for a smi operation. If one of the operands is a constant string 4890 // for a smi operation. If one of the operands is a constant string
4720 // do not generate code assuming it is a smi operation. 4891 // do not generate code assuming it is a smi operation.
4721 if (info.IsSmi() && 4892 if (info.IsSmi() &&
4722 ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) || 4893 ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) ||
4723 (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) { 4894 (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) {
4724 return instr; 4895 return instr;
4725 } 4896 }
4726 if (FLAG_trace_representation) { 4897 if (FLAG_trace_representation) {
4727 PrintF("Info: %s/%s\n", info.ToString(), ToRepresentation(info).Mnemonic()); 4898 PrintF("Info: %s/%s\n", info.ToString(), ToRepresentation(info).Mnemonic());
4728 } 4899 }
4729 AssumeRepresentation(instr, ToRepresentation(info)); 4900 Representation rep = ToRepresentation(info);
4901 // We only generate either int32 or generic tagged bitwise operations.
4902 if (instr->IsBitwiseBinaryOperation() && rep.IsDouble()) {
4903 rep = Representation::Integer32();
4904 }
4905 AssumeRepresentation(instr, rep);
4730 return instr; 4906 return instr;
4731 } 4907 }
4732 4908
4733 4909
4734 // Check for the form (%_ClassOf(foo) === 'BarClass'). 4910 // Check for the form (%_ClassOf(foo) === 'BarClass').
4735 static bool IsClassOfTest(CompareOperation* expr) { 4911 static bool IsClassOfTest(CompareOperation* expr) {
4736 if (expr->op() != Token::EQ_STRICT) return false; 4912 if (expr->op() != Token::EQ_STRICT) return false;
4737 CallRuntime* call = expr->left()->AsCallRuntime(); 4913 CallRuntime* call = expr->left()->AsCallRuntime();
4738 if (call == NULL) return false; 4914 if (call == NULL) return false;
4739 Literal* literal = expr->right()->AsLiteral(); 4915 Literal* literal = expr->right()->AsLiteral();
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
4800 4976
4801 void HGraphBuilder::AssumeRepresentation(HValue* value, Representation r) { 4977 void HGraphBuilder::AssumeRepresentation(HValue* value, Representation r) {
4802 if (value->CheckFlag(HValue::kFlexibleRepresentation)) { 4978 if (value->CheckFlag(HValue::kFlexibleRepresentation)) {
4803 if (FLAG_trace_representation) { 4979 if (FLAG_trace_representation) {
4804 PrintF("Assume representation for %s to be %s (%d)\n", 4980 PrintF("Assume representation for %s to be %s (%d)\n",
4805 value->Mnemonic(), 4981 value->Mnemonic(),
4806 r.Mnemonic(), 4982 r.Mnemonic(),
4807 graph_->GetMaximumValueID()); 4983 graph_->GetMaximumValueID());
4808 } 4984 }
4809 value->ChangeRepresentation(r); 4985 value->ChangeRepresentation(r);
4810 // The representation of the value is dictated by type feedback. 4986 // The representation of the value is dictated by type feedback and
4987 // will not be changed later.
4811 value->ClearFlag(HValue::kFlexibleRepresentation); 4988 value->ClearFlag(HValue::kFlexibleRepresentation);
4812 } else if (FLAG_trace_representation) { 4989 } else if (FLAG_trace_representation) {
4813 PrintF("No representation assumed\n"); 4990 PrintF("No representation assumed\n");
4814 } 4991 }
4815 } 4992 }
4816 4993
4817 4994
4818 Representation HGraphBuilder::ToRepresentation(TypeInfo info) { 4995 Representation HGraphBuilder::ToRepresentation(TypeInfo info) {
4819 if (info.IsSmi()) return Representation::Integer32(); 4996 if (info.IsSmi()) return Representation::Integer32();
4820 if (info.IsInteger32()) return Representation::Integer32(); 4997 if (info.IsInteger32()) return Representation::Integer32();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4852 return; 5029 return;
4853 } 5030 }
4854 5031
4855 VISIT_FOR_VALUE(expr->left()); 5032 VISIT_FOR_VALUE(expr->left());
4856 VISIT_FOR_VALUE(expr->right()); 5033 VISIT_FOR_VALUE(expr->right());
4857 5034
4858 HValue* right = Pop(); 5035 HValue* right = Pop();
4859 HValue* left = Pop(); 5036 HValue* left = Pop();
4860 Token::Value op = expr->op(); 5037 Token::Value op = expr->op();
4861 5038
4862 TypeInfo info = oracle()->CompareType(expr, TypeFeedbackOracle::RESULT); 5039 TypeInfo info = oracle()->CompareType(expr);
4863 HInstruction* instr = NULL; 5040 HInstruction* instr = NULL;
4864 if (op == Token::INSTANCEOF) { 5041 if (op == Token::INSTANCEOF) {
4865 instr = new HInstanceOf(left, right); 5042 // Check to see if the rhs of the instanceof is a global function not
5043 // residing in new space. If it is we assume that the function will stay the
5044 // same.
5045 Handle<JSFunction> target = Handle<JSFunction>::null();
5046 Variable* var = expr->right()->AsVariableProxy()->AsVariable();
5047 bool global_function = (var != NULL) && var->is_global() && !var->is_this();
5048 CompilationInfo* info = graph()->info();
5049 if (global_function &&
5050 info->has_global_object() &&
5051 !info->global_object()->IsAccessCheckNeeded()) {
5052 Handle<String> name = var->name();
5053 Handle<GlobalObject> global(info->global_object());
5054 LookupResult lookup;
5055 global->Lookup(*name, &lookup);
5056 if (lookup.IsProperty() &&
5057 lookup.type() == NORMAL &&
5058 lookup.GetValue()->IsJSFunction()) {
5059 Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue()));
5060 // If the function is in new space we assume it's more likely to
5061 // change and thus prefer the general IC code.
5062 if (!Heap::InNewSpace(*candidate)) {
5063 target = candidate;
5064 }
5065 }
5066 }
5067
5068 // If the target is not null we have found a known global function that is
5069 // assumed to stay the same for this instanceof.
5070 if (target.is_null()) {
5071 HContext* context = new HContext;
5072 AddInstruction(context);
5073 instr = new HInstanceOf(context, left, right);
5074 } else {
5075 AddInstruction(new HCheckFunction(right, target));
5076 instr = new HInstanceOfKnownGlobal(left, target);
5077 }
4866 } else if (op == Token::IN) { 5078 } else if (op == Token::IN) {
4867 BAILOUT("Unsupported comparison: in"); 5079 BAILOUT("Unsupported comparison: in");
4868 } else if (info.IsNonPrimitive()) { 5080 } else if (info.IsNonPrimitive()) {
4869 switch (op) { 5081 switch (op) {
4870 case Token::EQ: 5082 case Token::EQ:
4871 case Token::EQ_STRICT: { 5083 case Token::EQ_STRICT: {
4872 AddInstruction(new HCheckNonSmi(left)); 5084 AddInstruction(new HCheckNonSmi(left));
4873 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left)); 5085 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left));
4874 AddInstruction(new HCheckNonSmi(right)); 5086 AddInstruction(new HCheckNonSmi(right));
4875 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right)); 5087 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right));
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
4994 } 5206 }
4995 5207
4996 5208
4997 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( 5209 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
4998 int argument_count, 5210 int argument_count,
4999 int ast_id) { 5211 int ast_id) {
5000 BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); 5212 BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf");
5001 } 5213 }
5002 5214
5003 5215
5004 // Support for construct call checks. 5216 // Support for construct call checks.
5005 void HGraphBuilder::GenerateIsConstructCall(int argument_count, int ast_id) { 5217 void HGraphBuilder::GenerateIsConstructCall(int argument_count, int ast_id) {
5006 BAILOUT("inlined runtime function: IsConstructCall"); 5218 ASSERT(argument_count == 0);
5219 ast_context()->ReturnInstruction(new HIsConstructCall, ast_id);
5007 } 5220 }
5008 5221
5009 5222
5010 // Support for arguments.length and arguments[?]. 5223 // Support for arguments.length and arguments[?].
5011 void HGraphBuilder::GenerateArgumentsLength(int argument_count, int ast_id) { 5224 void HGraphBuilder::GenerateArgumentsLength(int argument_count, int ast_id) {
5012 ASSERT(argument_count == 0); 5225 ASSERT(argument_count == 0);
5013 HInstruction* elements = AddInstruction(new HArgumentsElements); 5226 HInstruction* elements = AddInstruction(new HArgumentsElements);
5014 HArgumentsLength* result = new HArgumentsLength(elements); 5227 HArgumentsLength* result = new HArgumentsLength(elements);
5015 ast_context()->ReturnInstruction(result, ast_id); 5228 ast_context()->ReturnInstruction(result, ast_id);
5016 } 5229 }
(...skipping 25 matching lines...) Expand all
5042 } 5255 }
5043 5256
5044 5257
5045 void HGraphBuilder::GenerateSetValueOf(int argument_count, int ast_id) { 5258 void HGraphBuilder::GenerateSetValueOf(int argument_count, int ast_id) {
5046 BAILOUT("inlined runtime function: SetValueOf"); 5259 BAILOUT("inlined runtime function: SetValueOf");
5047 } 5260 }
5048 5261
5049 5262
5050 // Fast support for charCodeAt(n). 5263 // Fast support for charCodeAt(n).
5051 void HGraphBuilder::GenerateStringCharCodeAt(int argument_count, int ast_id) { 5264 void HGraphBuilder::GenerateStringCharCodeAt(int argument_count, int ast_id) {
5052 BAILOUT("inlined runtime function: StringCharCodeAt"); 5265 ASSERT(argument_count == 2);
5266 HValue* index = Pop();
5267 HValue* string = Pop();
5268 HStringCharCodeAt* result = BuildStringCharCodeAt(string, index);
5269 ast_context()->ReturnInstruction(result, ast_id);
5053 } 5270 }
5054 5271
5055 5272
5056 // Fast support for string.charAt(n) and string[n]. 5273 // Fast support for string.charAt(n) and string[n].
5057 void HGraphBuilder::GenerateStringCharFromCode(int argument_count, 5274 void HGraphBuilder::GenerateStringCharFromCode(int argument_count,
5058 int ast_id) { 5275 int ast_id) {
5059 BAILOUT("inlined runtime function: StringCharFromCode"); 5276 BAILOUT("inlined runtime function: StringCharFromCode");
5060 } 5277 }
5061 5278
5062 5279
5063 // Fast support for string.charAt(n) and string[n]. 5280 // Fast support for string.charAt(n) and string[n].
5064 void HGraphBuilder::GenerateStringCharAt(int argument_count, int ast_id) { 5281 void HGraphBuilder::GenerateStringCharAt(int argument_count, int ast_id) {
5065 ASSERT_EQ(2, argument_count); 5282 ASSERT_EQ(2, argument_count);
5066 PushArgumentsForStubCall(argument_count); 5283 HContext* context = new HContext;
5067 HCallStub* result = new HCallStub(CodeStub::StringCharAt, argument_count); 5284 AddInstruction(context);
5285 HCallStub* result =
5286 new HCallStub(context, CodeStub::StringCharAt, argument_count);
5287 PreProcessCall(result);
5068 ast_context()->ReturnInstruction(result, ast_id); 5288 ast_context()->ReturnInstruction(result, ast_id);
5069 } 5289 }
5070 5290
5071 5291
5072 // Fast support for object equality testing. 5292 // Fast support for object equality testing.
5073 void HGraphBuilder::GenerateObjectEquals(int argument_count, int ast_id) { 5293 void HGraphBuilder::GenerateObjectEquals(int argument_count, int ast_id) {
5074 ASSERT(argument_count == 2); 5294 ASSERT(argument_count == 2);
5075 HValue* right = Pop(); 5295 HValue* right = Pop();
5076 HValue* left = Pop(); 5296 HValue* left = Pop();
5077 HCompareJSObjectEq* result = new HCompareJSObjectEq(left, right); 5297 HCompareJSObjectEq* result = new HCompareJSObjectEq(left, right);
5078 ast_context()->ReturnInstruction(result, ast_id); 5298 ast_context()->ReturnInstruction(result, ast_id);
5079 } 5299 }
5080 5300
5081 5301
5082 void HGraphBuilder::GenerateLog(int argument_count, int ast_id) { 5302 void HGraphBuilder::GenerateLog(int argument_count, int ast_id) {
5083 UNREACHABLE(); // We caught this in VisitCallRuntime. 5303 UNREACHABLE(); // We caught this in VisitCallRuntime.
5084 } 5304 }
5085 5305
5086 5306
5087 // Fast support for Math.random(). 5307 // Fast support for Math.random().
5088 void HGraphBuilder::GenerateRandomHeapNumber(int argument_count, int ast_id) { 5308 void HGraphBuilder::GenerateRandomHeapNumber(int argument_count, int ast_id) {
5089 BAILOUT("inlined runtime function: RandomHeapNumber"); 5309 BAILOUT("inlined runtime function: RandomHeapNumber");
5090 } 5310 }
5091 5311
5092 5312
5093 // Fast support for StringAdd. 5313 // Fast support for StringAdd.
5094 void HGraphBuilder::GenerateStringAdd(int argument_count, int ast_id) { 5314 void HGraphBuilder::GenerateStringAdd(int argument_count, int ast_id) {
5095 ASSERT_EQ(2, argument_count); 5315 ASSERT_EQ(2, argument_count);
5096 PushArgumentsForStubCall(argument_count); 5316 HContext* context = new HContext;
5097 HCallStub* result = new HCallStub(CodeStub::StringAdd, argument_count); 5317 AddInstruction(context);
5318 HCallStub* result =
5319 new HCallStub(context, CodeStub::StringAdd, argument_count);
5320 PreProcessCall(result);
5098 ast_context()->ReturnInstruction(result, ast_id); 5321 ast_context()->ReturnInstruction(result, ast_id);
5099 } 5322 }
5100 5323
5101 5324
5102 // Fast support for SubString. 5325 // Fast support for SubString.
5103 void HGraphBuilder::GenerateSubString(int argument_count, int ast_id) { 5326 void HGraphBuilder::GenerateSubString(int argument_count, int ast_id) {
5104 ASSERT_EQ(3, argument_count); 5327 ASSERT_EQ(3, argument_count);
5105 PushArgumentsForStubCall(argument_count); 5328 HContext* context = new HContext;
5106 HCallStub* result = new HCallStub(CodeStub::SubString, argument_count); 5329 AddInstruction(context);
5330 HCallStub* result =
5331 new HCallStub(context, CodeStub::SubString, argument_count);
5332 PreProcessCall(result);
5107 ast_context()->ReturnInstruction(result, ast_id); 5333 ast_context()->ReturnInstruction(result, ast_id);
5108 } 5334 }
5109 5335
5110 5336
5111 // Fast support for StringCompare. 5337 // Fast support for StringCompare.
5112 void HGraphBuilder::GenerateStringCompare(int argument_count, int ast_id) { 5338 void HGraphBuilder::GenerateStringCompare(int argument_count, int ast_id) {
5113 ASSERT_EQ(2, argument_count); 5339 ASSERT_EQ(2, argument_count);
5114 PushArgumentsForStubCall(argument_count); 5340 HContext* context = new HContext;
5115 HCallStub* result = new HCallStub(CodeStub::StringCompare, argument_count); 5341 AddInstruction(context);
5342 HCallStub* result =
5343 new HCallStub(context, CodeStub::StringCompare, argument_count);
5344 PreProcessCall(result);
5116 ast_context()->ReturnInstruction(result, ast_id); 5345 ast_context()->ReturnInstruction(result, ast_id);
5117 } 5346 }
5118 5347
5119 5348
5120 // Support for direct calls from JavaScript to native RegExp code. 5349 // Support for direct calls from JavaScript to native RegExp code.
5121 void HGraphBuilder::GenerateRegExpExec(int argument_count, int ast_id) { 5350 void HGraphBuilder::GenerateRegExpExec(int argument_count, int ast_id) {
5122 ASSERT_EQ(4, argument_count); 5351 ASSERT_EQ(4, argument_count);
5123 PushArgumentsForStubCall(argument_count); 5352 HContext* context = new HContext;
5124 HCallStub* result = new HCallStub(CodeStub::RegExpExec, argument_count); 5353 AddInstruction(context);
5354 HCallStub* result =
5355 new HCallStub(context, CodeStub::RegExpExec, argument_count);
5356 PreProcessCall(result);
5125 ast_context()->ReturnInstruction(result, ast_id); 5357 ast_context()->ReturnInstruction(result, ast_id);
5126 } 5358 }
5127 5359
5128 5360
5129 // Construct a RegExp exec result with two in-object properties. 5361 // Construct a RegExp exec result with two in-object properties.
5130 void HGraphBuilder::GenerateRegExpConstructResult(int argument_count, 5362 void HGraphBuilder::GenerateRegExpConstructResult(int argument_count,
5131 int ast_id) { 5363 int ast_id) {
5132 ASSERT_EQ(3, argument_count); 5364 ASSERT_EQ(3, argument_count);
5133 PushArgumentsForStubCall(argument_count); 5365 HContext* context = new HContext;
5366 AddInstruction(context);
5134 HCallStub* result = 5367 HCallStub* result =
5135 new HCallStub(CodeStub::RegExpConstructResult, argument_count); 5368 new HCallStub(context, CodeStub::RegExpConstructResult, argument_count);
5369 PreProcessCall(result);
5136 ast_context()->ReturnInstruction(result, ast_id); 5370 ast_context()->ReturnInstruction(result, ast_id);
5137 } 5371 }
5138 5372
5139 5373
5140 // Support for fast native caches. 5374 // Support for fast native caches.
5141 void HGraphBuilder::GenerateGetFromCache(int argument_count, int ast_id) { 5375 void HGraphBuilder::GenerateGetFromCache(int argument_count, int ast_id) {
5142 BAILOUT("inlined runtime function: GetFromCache"); 5376 BAILOUT("inlined runtime function: GetFromCache");
5143 } 5377 }
5144 5378
5145 5379
5146 // Fast support for number to string. 5380 // Fast support for number to string.
5147 void HGraphBuilder::GenerateNumberToString(int argument_count, int ast_id) { 5381 void HGraphBuilder::GenerateNumberToString(int argument_count, int ast_id) {
5148 ASSERT_EQ(1, argument_count); 5382 ASSERT_EQ(1, argument_count);
5149 PushArgumentsForStubCall(argument_count); 5383 HContext* context = new HContext;
5150 HCallStub* result = new HCallStub(CodeStub::NumberToString, argument_count); 5384 AddInstruction(context);
5385 HCallStub* result =
5386 new HCallStub(context, CodeStub::NumberToString, argument_count);
5387 PreProcessCall(result);
5151 ast_context()->ReturnInstruction(result, ast_id); 5388 ast_context()->ReturnInstruction(result, ast_id);
5152 } 5389 }
5153 5390
5154 5391
5155 // Fast swapping of elements. Takes three expressions, the object and two 5392 // Fast swapping of elements. Takes three expressions, the object and two
5156 // indices. This should only be used if the indices are known to be 5393 // indices. This should only be used if the indices are known to be
5157 // non-negative and within bounds of the elements array at the call site. 5394 // non-negative and within bounds of the elements array at the call site.
5158 void HGraphBuilder::GenerateSwapElements(int argument_count, int ast_id) { 5395 void HGraphBuilder::GenerateSwapElements(int argument_count, int ast_id) {
5159 BAILOUT("inlined runtime function: SwapElements"); 5396 BAILOUT("inlined runtime function: SwapElements");
5160 } 5397 }
(...skipping 10 matching lines...) Expand all
5171 ASSERT_EQ(2, argument_count); 5408 ASSERT_EQ(2, argument_count);
5172 HValue* right = Pop(); 5409 HValue* right = Pop();
5173 HValue* left = Pop(); 5410 HValue* left = Pop();
5174 HPower* result = new HPower(left, right); 5411 HPower* result = new HPower(left, right);
5175 ast_context()->ReturnInstruction(result, ast_id); 5412 ast_context()->ReturnInstruction(result, ast_id);
5176 } 5413 }
5177 5414
5178 5415
5179 void HGraphBuilder::GenerateMathSin(int argument_count, int ast_id) { 5416 void HGraphBuilder::GenerateMathSin(int argument_count, int ast_id) {
5180 ASSERT_EQ(1, argument_count); 5417 ASSERT_EQ(1, argument_count);
5181 PushArgumentsForStubCall(argument_count); 5418 HContext* context = new HContext;
5419 AddInstruction(context);
5182 HCallStub* result = 5420 HCallStub* result =
5183 new HCallStub(CodeStub::TranscendentalCache, argument_count); 5421 new HCallStub(context, CodeStub::TranscendentalCache, argument_count);
5184 result->set_transcendental_type(TranscendentalCache::SIN); 5422 result->set_transcendental_type(TranscendentalCache::SIN);
5423 PreProcessCall(result);
5185 ast_context()->ReturnInstruction(result, ast_id); 5424 ast_context()->ReturnInstruction(result, ast_id);
5186 } 5425 }
5187 5426
5188 5427
5189 void HGraphBuilder::GenerateMathCos(int argument_count, int ast_id) { 5428 void HGraphBuilder::GenerateMathCos(int argument_count, int ast_id) {
5190 ASSERT_EQ(1, argument_count); 5429 ASSERT_EQ(1, argument_count);
5191 PushArgumentsForStubCall(argument_count); 5430 HContext* context = new HContext;
5431 AddInstruction(context);
5192 HCallStub* result = 5432 HCallStub* result =
5193 new HCallStub(CodeStub::TranscendentalCache, argument_count); 5433 new HCallStub(context, CodeStub::TranscendentalCache, argument_count);
5194 result->set_transcendental_type(TranscendentalCache::COS); 5434 result->set_transcendental_type(TranscendentalCache::COS);
5435 PreProcessCall(result);
5195 ast_context()->ReturnInstruction(result, ast_id); 5436 ast_context()->ReturnInstruction(result, ast_id);
5196 } 5437 }
5197 5438
5198 5439
5199 void HGraphBuilder::GenerateMathLog(int argument_count, int ast_id) { 5440 void HGraphBuilder::GenerateMathLog(int argument_count, int ast_id) {
5200 ASSERT_EQ(1, argument_count); 5441 ASSERT_EQ(1, argument_count);
5201 PushArgumentsForStubCall(argument_count); 5442 HContext* context = new HContext;
5443 AddInstruction(context);
5202 HCallStub* result = 5444 HCallStub* result =
5203 new HCallStub(CodeStub::TranscendentalCache, argument_count); 5445 new HCallStub(context, CodeStub::TranscendentalCache, argument_count);
5204 result->set_transcendental_type(TranscendentalCache::LOG); 5446 result->set_transcendental_type(TranscendentalCache::LOG);
5447 PreProcessCall(result);
5205 ast_context()->ReturnInstruction(result, ast_id); 5448 ast_context()->ReturnInstruction(result, ast_id);
5206 } 5449 }
5207 5450
5208 5451
5209 void HGraphBuilder::GenerateMathSqrt(int argument_count, int ast_id) { 5452 void HGraphBuilder::GenerateMathSqrt(int argument_count, int ast_id) {
5210 BAILOUT("inlined runtime function: MathSqrt"); 5453 BAILOUT("inlined runtime function: MathSqrt");
5211 } 5454 }
5212 5455
5213 5456
5214 // Check whether two RegExps are equivalent 5457 // Check whether two RegExps are equivalent
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
5656 PrintF("Timing results:\n"); 5899 PrintF("Timing results:\n");
5657 int64_t sum = 0; 5900 int64_t sum = 0;
5658 for (int i = 0; i < timing_.length(); ++i) { 5901 for (int i = 0; i < timing_.length(); ++i) {
5659 sum += timing_[i]; 5902 sum += timing_[i];
5660 } 5903 }
5661 5904
5662 for (int i = 0; i < names_.length(); ++i) { 5905 for (int i = 0; i < names_.length(); ++i) {
5663 PrintF("%30s", names_[i]); 5906 PrintF("%30s", names_[i]);
5664 double ms = static_cast<double>(timing_[i]) / 1000; 5907 double ms = static_cast<double>(timing_[i]) / 1000;
5665 double percent = static_cast<double>(timing_[i]) * 100 / sum; 5908 double percent = static_cast<double>(timing_[i]) * 100 / sum;
5666 PrintF(" - %0.3f ms / %0.3f %% \n", ms, percent); 5909 PrintF(" - %7.3f ms / %4.1f %% ", ms, percent);
5910
5911 unsigned size = sizes_[i];
5912 double size_percent = static_cast<double>(size) * 100 / total_size_;
5913 PrintF(" %8u bytes / %4.1f %%\n", size, size_percent);
5667 } 5914 }
5668 PrintF("%30s - %0.3f ms \n", "Sum", static_cast<double>(sum) / 1000); 5915 PrintF("%30s - %7.3f ms %8u bytes\n", "Sum",
5916 static_cast<double>(sum) / 1000,
5917 total_size_);
5669 PrintF("---------------------------------------------------------------\n"); 5918 PrintF("---------------------------------------------------------------\n");
5670 PrintF("%30s - %0.3f ms (%0.1f times slower than full code gen)\n", 5919 PrintF("%30s - %7.3f ms (%.1f times slower than full code gen)\n",
5671 "Total", 5920 "Total",
5672 static_cast<double>(total_) / 1000, 5921 static_cast<double>(total_) / 1000,
5673 static_cast<double>(total_) / full_code_gen_); 5922 static_cast<double>(total_) / full_code_gen_);
5674 } 5923 }
5675 5924
5676 5925
5677 void HStatistics::SaveTiming(const char* name, int64_t ticks) { 5926 void HStatistics::SaveTiming(const char* name, int64_t ticks, unsigned size) {
5678 if (name == HPhase::kFullCodeGen) { 5927 if (name == HPhase::kFullCodeGen) {
5679 full_code_gen_ += ticks; 5928 full_code_gen_ += ticks;
5680 } else if (name == HPhase::kTotal) { 5929 } else if (name == HPhase::kTotal) {
5681 total_ += ticks; 5930 total_ += ticks;
5682 } else { 5931 } else {
5932 total_size_ += size;
5683 for (int i = 0; i < names_.length(); ++i) { 5933 for (int i = 0; i < names_.length(); ++i) {
5684 if (names_[i] == name) { 5934 if (names_[i] == name) {
5685 timing_[i] += ticks; 5935 timing_[i] += ticks;
5936 sizes_[i] += size;
5686 return; 5937 return;
5687 } 5938 }
5688 } 5939 }
5689 names_.Add(name); 5940 names_.Add(name);
5690 timing_.Add(ticks); 5941 timing_.Add(ticks);
5942 sizes_.Add(size);
5691 } 5943 }
5692 } 5944 }
5693 5945
5694 5946
5695 const char* const HPhase::kFullCodeGen = "Full code generator"; 5947 const char* const HPhase::kFullCodeGen = "Full code generator";
5696 const char* const HPhase::kTotal = "Total"; 5948 const char* const HPhase::kTotal = "Total";
5697 5949
5698 5950
5699 void HPhase::Begin(const char* name, 5951 void HPhase::Begin(const char* name,
5700 HGraph* graph, 5952 HGraph* graph,
5701 LChunk* chunk, 5953 LChunk* chunk,
5702 LAllocator* allocator) { 5954 LAllocator* allocator) {
5703 name_ = name; 5955 name_ = name;
5704 graph_ = graph; 5956 graph_ = graph;
5705 chunk_ = chunk; 5957 chunk_ = chunk;
5706 allocator_ = allocator; 5958 allocator_ = allocator;
5707 if (allocator != NULL && chunk_ == NULL) { 5959 if (allocator != NULL && chunk_ == NULL) {
5708 chunk_ = allocator->chunk(); 5960 chunk_ = allocator->chunk();
5709 } 5961 }
5710 if (FLAG_time_hydrogen) start_ = OS::Ticks(); 5962 if (FLAG_time_hydrogen) start_ = OS::Ticks();
5963 start_allocation_size_ = Zone::allocation_size_;
5711 } 5964 }
5712 5965
5713 5966
5714 void HPhase::End() const { 5967 void HPhase::End() const {
5715 if (FLAG_time_hydrogen) { 5968 if (FLAG_time_hydrogen) {
5716 int64_t end = OS::Ticks(); 5969 int64_t end = OS::Ticks();
5717 HStatistics::Instance()->SaveTiming(name_, end - start_); 5970 unsigned size = Zone::allocation_size_ - start_allocation_size_;
5971 HStatistics::Instance()->SaveTiming(name_, end - start_, size);
5718 } 5972 }
5719 5973
5720 if (FLAG_trace_hydrogen) { 5974 if (FLAG_trace_hydrogen) {
5721 if (graph_ != NULL) HTracer::Instance()->TraceHydrogen(name_, graph_); 5975 if (graph_ != NULL) HTracer::Instance()->TraceHydrogen(name_, graph_);
5722 if (chunk_ != NULL) HTracer::Instance()->TraceLithium(name_, chunk_); 5976 if (chunk_ != NULL) HTracer::Instance()->TraceLithium(name_, chunk_);
5723 if (allocator_ != NULL) { 5977 if (allocator_ != NULL) {
5724 HTracer::Instance()->TraceLiveRanges(name_, allocator_); 5978 HTracer::Instance()->TraceLiveRanges(name_, allocator_);
5725 } 5979 }
5726 } 5980 }
5727 5981
5728 #ifdef DEBUG 5982 #ifdef DEBUG
5729 if (graph_ != NULL) graph_->Verify(); 5983 if (graph_ != NULL) graph_->Verify();
5730 if (chunk_ != NULL) chunk_->Verify();
5731 if (allocator_ != NULL) allocator_->Verify(); 5984 if (allocator_ != NULL) allocator_->Verify();
5732 #endif 5985 #endif
5733 } 5986 }
5734 5987
5735 } } // namespace v8::internal 5988 } } // 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