Move IC code into a subdir and move ic-compilation related code from stub-cache into...
[platform/upstream/v8.git] / src / hydrogen.cc
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/hydrogen.h"
6
7 #include <algorithm>
8
9 #include "src/v8.h"
10
11 #include "src/allocation-site-scopes.h"
12 #include "src/codegen.h"
13 #include "src/full-codegen.h"
14 #include "src/hashmap.h"
15 #include "src/hydrogen-bce.h"
16 #include "src/hydrogen-bch.h"
17 #include "src/hydrogen-canonicalize.h"
18 #include "src/hydrogen-check-elimination.h"
19 #include "src/hydrogen-dce.h"
20 #include "src/hydrogen-dehoist.h"
21 #include "src/hydrogen-environment-liveness.h"
22 #include "src/hydrogen-escape-analysis.h"
23 #include "src/hydrogen-gvn.h"
24 #include "src/hydrogen-infer-representation.h"
25 #include "src/hydrogen-infer-types.h"
26 #include "src/hydrogen-load-elimination.h"
27 #include "src/hydrogen-mark-deoptimize.h"
28 #include "src/hydrogen-mark-unreachable.h"
29 #include "src/hydrogen-osr.h"
30 #include "src/hydrogen-range-analysis.h"
31 #include "src/hydrogen-redundant-phi.h"
32 #include "src/hydrogen-removable-simulates.h"
33 #include "src/hydrogen-representation-changes.h"
34 #include "src/hydrogen-sce.h"
35 #include "src/hydrogen-store-elimination.h"
36 #include "src/hydrogen-uint32-analysis.h"
37 #include "src/lithium-allocator.h"
38 #include "src/parser.h"
39 #include "src/runtime.h"
40 #include "src/scopeinfo.h"
41 #include "src/scopes.h"
42 #include "src/typing.h"
43 // CallOptimization
44 #include "src/ic/ic-compiler.h"
45 // GetRootConstructor
46 #include "src/ic/ic-inl.h"
47
48 #if V8_TARGET_ARCH_IA32
49 #include "src/ia32/lithium-codegen-ia32.h"  // NOLINT
50 #elif V8_TARGET_ARCH_X64
51 #include "src/x64/lithium-codegen-x64.h"  // NOLINT
52 #elif V8_TARGET_ARCH_ARM64
53 #include "src/arm64/lithium-codegen-arm64.h"  // NOLINT
54 #elif V8_TARGET_ARCH_ARM
55 #include "src/arm/lithium-codegen-arm.h"  // NOLINT
56 #elif V8_TARGET_ARCH_MIPS
57 #include "src/mips/lithium-codegen-mips.h"  // NOLINT
58 #elif V8_TARGET_ARCH_MIPS64
59 #include "src/mips64/lithium-codegen-mips64.h"  // NOLINT
60 #elif V8_TARGET_ARCH_X87
61 #include "src/x87/lithium-codegen-x87.h"  // NOLINT
62 #else
63 #error Unsupported target architecture.
64 #endif
65
66 namespace v8 {
67 namespace internal {
68
69 HBasicBlock::HBasicBlock(HGraph* graph)
70     : block_id_(graph->GetNextBlockID()),
71       graph_(graph),
72       phis_(4, graph->zone()),
73       first_(NULL),
74       last_(NULL),
75       end_(NULL),
76       loop_information_(NULL),
77       predecessors_(2, graph->zone()),
78       dominator_(NULL),
79       dominated_blocks_(4, graph->zone()),
80       last_environment_(NULL),
81       argument_count_(-1),
82       first_instruction_index_(-1),
83       last_instruction_index_(-1),
84       deleted_phis_(4, graph->zone()),
85       parent_loop_header_(NULL),
86       inlined_entry_block_(NULL),
87       is_inline_return_target_(false),
88       is_reachable_(true),
89       dominates_loop_successors_(false),
90       is_osr_entry_(false),
91       is_ordered_(false) { }
92
93
94 Isolate* HBasicBlock::isolate() const {
95   return graph_->isolate();
96 }
97
98
99 void HBasicBlock::MarkUnreachable() {
100   is_reachable_ = false;
101 }
102
103
104 void HBasicBlock::AttachLoopInformation() {
105   DCHECK(!IsLoopHeader());
106   loop_information_ = new(zone()) HLoopInformation(this, zone());
107 }
108
109
110 void HBasicBlock::DetachLoopInformation() {
111   DCHECK(IsLoopHeader());
112   loop_information_ = NULL;
113 }
114
115
116 void HBasicBlock::AddPhi(HPhi* phi) {
117   DCHECK(!IsStartBlock());
118   phis_.Add(phi, zone());
119   phi->SetBlock(this);
120 }
121
122
123 void HBasicBlock::RemovePhi(HPhi* phi) {
124   DCHECK(phi->block() == this);
125   DCHECK(phis_.Contains(phi));
126   phi->Kill();
127   phis_.RemoveElement(phi);
128   phi->SetBlock(NULL);
129 }
130
131
132 void HBasicBlock::AddInstruction(HInstruction* instr,
133                                  HSourcePosition position) {
134   DCHECK(!IsStartBlock() || !IsFinished());
135   DCHECK(!instr->IsLinked());
136   DCHECK(!IsFinished());
137
138   if (!position.IsUnknown()) {
139     instr->set_position(position);
140   }
141   if (first_ == NULL) {
142     DCHECK(last_environment() != NULL);
143     DCHECK(!last_environment()->ast_id().IsNone());
144     HBlockEntry* entry = new(zone()) HBlockEntry();
145     entry->InitializeAsFirst(this);
146     if (!position.IsUnknown()) {
147       entry->set_position(position);
148     } else {
149       DCHECK(!FLAG_hydrogen_track_positions ||
150              !graph()->info()->IsOptimizing());
151     }
152     first_ = last_ = entry;
153   }
154   instr->InsertAfter(last_);
155 }
156
157
158 HPhi* HBasicBlock::AddNewPhi(int merged_index) {
159   if (graph()->IsInsideNoSideEffectsScope()) {
160     merged_index = HPhi::kInvalidMergedIndex;
161   }
162   HPhi* phi = new(zone()) HPhi(merged_index, zone());
163   AddPhi(phi);
164   return phi;
165 }
166
167
168 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id,
169                                        RemovableSimulate removable) {
170   DCHECK(HasEnvironment());
171   HEnvironment* environment = last_environment();
172   DCHECK(ast_id.IsNone() ||
173          ast_id == BailoutId::StubEntry() ||
174          environment->closure()->shared()->VerifyBailoutId(ast_id));
175
176   int push_count = environment->push_count();
177   int pop_count = environment->pop_count();
178
179   HSimulate* instr =
180       new(zone()) HSimulate(ast_id, pop_count, zone(), removable);
181 #ifdef DEBUG
182   instr->set_closure(environment->closure());
183 #endif
184   // Order of pushed values: newest (top of stack) first. This allows
185   // HSimulate::MergeWith() to easily append additional pushed values
186   // that are older (from further down the stack).
187   for (int i = 0; i < push_count; ++i) {
188     instr->AddPushedValue(environment->ExpressionStackAt(i));
189   }
190   for (GrowableBitVector::Iterator it(environment->assigned_variables(),
191                                       zone());
192        !it.Done();
193        it.Advance()) {
194     int index = it.Current();
195     instr->AddAssignedValue(index, environment->Lookup(index));
196   }
197   environment->ClearHistory();
198   return instr;
199 }
200
201
202 void HBasicBlock::Finish(HControlInstruction* end, HSourcePosition position) {
203   DCHECK(!IsFinished());
204   AddInstruction(end, position);
205   end_ = end;
206   for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
207     it.Current()->RegisterPredecessor(this);
208   }
209 }
210
211
212 void HBasicBlock::Goto(HBasicBlock* block,
213                        HSourcePosition position,
214                        FunctionState* state,
215                        bool add_simulate) {
216   bool drop_extra = state != NULL &&
217       state->inlining_kind() == NORMAL_RETURN;
218
219   if (block->IsInlineReturnTarget()) {
220     HEnvironment* env = last_environment();
221     int argument_count = env->arguments_environment()->parameter_count();
222     AddInstruction(new(zone())
223                    HLeaveInlined(state->entry(), argument_count),
224                    position);
225     UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
226   }
227
228   if (add_simulate) AddNewSimulate(BailoutId::None(), position);
229   HGoto* instr = new(zone()) HGoto(block);
230   Finish(instr, position);
231 }
232
233
234 void HBasicBlock::AddLeaveInlined(HValue* return_value,
235                                   FunctionState* state,
236                                   HSourcePosition position) {
237   HBasicBlock* target = state->function_return();
238   bool drop_extra = state->inlining_kind() == NORMAL_RETURN;
239
240   DCHECK(target->IsInlineReturnTarget());
241   DCHECK(return_value != NULL);
242   HEnvironment* env = last_environment();
243   int argument_count = env->arguments_environment()->parameter_count();
244   AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count),
245                  position);
246   UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
247   last_environment()->Push(return_value);
248   AddNewSimulate(BailoutId::None(), position);
249   HGoto* instr = new(zone()) HGoto(target);
250   Finish(instr, position);
251 }
252
253
254 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
255   DCHECK(!HasEnvironment());
256   DCHECK(first() == NULL);
257   UpdateEnvironment(env);
258 }
259
260
261 void HBasicBlock::UpdateEnvironment(HEnvironment* env) {
262   last_environment_ = env;
263   graph()->update_maximum_environment_size(env->first_expression_index());
264 }
265
266
267 void HBasicBlock::SetJoinId(BailoutId ast_id) {
268   int length = predecessors_.length();
269   DCHECK(length > 0);
270   for (int i = 0; i < length; i++) {
271     HBasicBlock* predecessor = predecessors_[i];
272     DCHECK(predecessor->end()->IsGoto());
273     HSimulate* simulate = HSimulate::cast(predecessor->end()->previous());
274     DCHECK(i != 0 ||
275            (predecessor->last_environment()->closure().is_null() ||
276             predecessor->last_environment()->closure()->shared()
277               ->VerifyBailoutId(ast_id)));
278     simulate->set_ast_id(ast_id);
279     predecessor->last_environment()->set_ast_id(ast_id);
280   }
281 }
282
283
284 bool HBasicBlock::Dominates(HBasicBlock* other) const {
285   HBasicBlock* current = other->dominator();
286   while (current != NULL) {
287     if (current == this) return true;
288     current = current->dominator();
289   }
290   return false;
291 }
292
293
294 bool HBasicBlock::EqualToOrDominates(HBasicBlock* other) const {
295   if (this == other) return true;
296   return Dominates(other);
297 }
298
299
300 int HBasicBlock::LoopNestingDepth() const {
301   const HBasicBlock* current = this;
302   int result  = (current->IsLoopHeader()) ? 1 : 0;
303   while (current->parent_loop_header() != NULL) {
304     current = current->parent_loop_header();
305     result++;
306   }
307   return result;
308 }
309
310
311 void HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) {
312   DCHECK(IsLoopHeader());
313
314   SetJoinId(stmt->EntryId());
315   if (predecessors()->length() == 1) {
316     // This is a degenerated loop.
317     DetachLoopInformation();
318     return;
319   }
320
321   // Only the first entry into the loop is from outside the loop. All other
322   // entries must be back edges.
323   for (int i = 1; i < predecessors()->length(); ++i) {
324     loop_information()->RegisterBackEdge(predecessors()->at(i));
325   }
326 }
327
328
329 void HBasicBlock::MarkSuccEdgeUnreachable(int succ) {
330   DCHECK(IsFinished());
331   HBasicBlock* succ_block = end()->SuccessorAt(succ);
332
333   DCHECK(succ_block->predecessors()->length() == 1);
334   succ_block->MarkUnreachable();
335 }
336
337
338 void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
339   if (HasPredecessor()) {
340     // Only loop header blocks can have a predecessor added after
341     // instructions have been added to the block (they have phis for all
342     // values in the environment, these phis may be eliminated later).
343     DCHECK(IsLoopHeader() || first_ == NULL);
344     HEnvironment* incoming_env = pred->last_environment();
345     if (IsLoopHeader()) {
346       DCHECK(phis()->length() == incoming_env->length());
347       for (int i = 0; i < phis_.length(); ++i) {
348         phis_[i]->AddInput(incoming_env->values()->at(i));
349       }
350     } else {
351       last_environment()->AddIncomingEdge(this, pred->last_environment());
352     }
353   } else if (!HasEnvironment() && !IsFinished()) {
354     DCHECK(!IsLoopHeader());
355     SetInitialEnvironment(pred->last_environment()->Copy());
356   }
357
358   predecessors_.Add(pred, zone());
359 }
360
361
362 void HBasicBlock::AddDominatedBlock(HBasicBlock* block) {
363   DCHECK(!dominated_blocks_.Contains(block));
364   // Keep the list of dominated blocks sorted such that if there is two
365   // succeeding block in this list, the predecessor is before the successor.
366   int index = 0;
367   while (index < dominated_blocks_.length() &&
368          dominated_blocks_[index]->block_id() < block->block_id()) {
369     ++index;
370   }
371   dominated_blocks_.InsertAt(index, block, zone());
372 }
373
374
375 void HBasicBlock::AssignCommonDominator(HBasicBlock* other) {
376   if (dominator_ == NULL) {
377     dominator_ = other;
378     other->AddDominatedBlock(this);
379   } else if (other->dominator() != NULL) {
380     HBasicBlock* first = dominator_;
381     HBasicBlock* second = other;
382
383     while (first != second) {
384       if (first->block_id() > second->block_id()) {
385         first = first->dominator();
386       } else {
387         second = second->dominator();
388       }
389       DCHECK(first != NULL && second != NULL);
390     }
391
392     if (dominator_ != first) {
393       DCHECK(dominator_->dominated_blocks_.Contains(this));
394       dominator_->dominated_blocks_.RemoveElement(this);
395       dominator_ = first;
396       first->AddDominatedBlock(this);
397     }
398   }
399 }
400
401
402 void HBasicBlock::AssignLoopSuccessorDominators() {
403   // Mark blocks that dominate all subsequent reachable blocks inside their
404   // loop. Exploit the fact that blocks are sorted in reverse post order. When
405   // the loop is visited in increasing block id order, if the number of
406   // non-loop-exiting successor edges at the dominator_candidate block doesn't
407   // exceed the number of previously encountered predecessor edges, there is no
408   // path from the loop header to any block with higher id that doesn't go
409   // through the dominator_candidate block. In this case, the
410   // dominator_candidate block is guaranteed to dominate all blocks reachable
411   // from it with higher ids.
412   HBasicBlock* last = loop_information()->GetLastBackEdge();
413   int outstanding_successors = 1;  // one edge from the pre-header
414   // Header always dominates everything.
415   MarkAsLoopSuccessorDominator();
416   for (int j = block_id(); j <= last->block_id(); ++j) {
417     HBasicBlock* dominator_candidate = graph_->blocks()->at(j);
418     for (HPredecessorIterator it(dominator_candidate); !it.Done();
419          it.Advance()) {
420       HBasicBlock* predecessor = it.Current();
421       // Don't count back edges.
422       if (predecessor->block_id() < dominator_candidate->block_id()) {
423         outstanding_successors--;
424       }
425     }
426
427     // If more successors than predecessors have been seen in the loop up to
428     // now, it's not possible to guarantee that the current block dominates
429     // all of the blocks with higher IDs. In this case, assume conservatively
430     // that those paths through loop that don't go through the current block
431     // contain all of the loop's dependencies. Also be careful to record
432     // dominator information about the current loop that's being processed,
433     // and not nested loops, which will be processed when
434     // AssignLoopSuccessorDominators gets called on their header.
435     DCHECK(outstanding_successors >= 0);
436     HBasicBlock* parent_loop_header = dominator_candidate->parent_loop_header();
437     if (outstanding_successors == 0 &&
438         (parent_loop_header == this && !dominator_candidate->IsLoopHeader())) {
439       dominator_candidate->MarkAsLoopSuccessorDominator();
440     }
441     HControlInstruction* end = dominator_candidate->end();
442     for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
443       HBasicBlock* successor = it.Current();
444       // Only count successors that remain inside the loop and don't loop back
445       // to a loop header.
446       if (successor->block_id() > dominator_candidate->block_id() &&
447           successor->block_id() <= last->block_id()) {
448         // Backwards edges must land on loop headers.
449         DCHECK(successor->block_id() > dominator_candidate->block_id() ||
450                successor->IsLoopHeader());
451         outstanding_successors++;
452       }
453     }
454   }
455 }
456
457
458 int HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const {
459   for (int i = 0; i < predecessors_.length(); ++i) {
460     if (predecessors_[i] == predecessor) return i;
461   }
462   UNREACHABLE();
463   return -1;
464 }
465
466
467 #ifdef DEBUG
468 void HBasicBlock::Verify() {
469   // Check that every block is finished.
470   DCHECK(IsFinished());
471   DCHECK(block_id() >= 0);
472
473   // Check that the incoming edges are in edge split form.
474   if (predecessors_.length() > 1) {
475     for (int i = 0; i < predecessors_.length(); ++i) {
476       DCHECK(predecessors_[i]->end()->SecondSuccessor() == NULL);
477     }
478   }
479 }
480 #endif
481
482
483 void HLoopInformation::RegisterBackEdge(HBasicBlock* block) {
484   this->back_edges_.Add(block, block->zone());
485   AddBlock(block);
486 }
487
488
489 HBasicBlock* HLoopInformation::GetLastBackEdge() const {
490   int max_id = -1;
491   HBasicBlock* result = NULL;
492   for (int i = 0; i < back_edges_.length(); ++i) {
493     HBasicBlock* cur = back_edges_[i];
494     if (cur->block_id() > max_id) {
495       max_id = cur->block_id();
496       result = cur;
497     }
498   }
499   return result;
500 }
501
502
503 void HLoopInformation::AddBlock(HBasicBlock* block) {
504   if (block == loop_header()) return;
505   if (block->parent_loop_header() == loop_header()) return;
506   if (block->parent_loop_header() != NULL) {
507     AddBlock(block->parent_loop_header());
508   } else {
509     block->set_parent_loop_header(loop_header());
510     blocks_.Add(block, block->zone());
511     for (int i = 0; i < block->predecessors()->length(); ++i) {
512       AddBlock(block->predecessors()->at(i));
513     }
514   }
515 }
516
517
518 #ifdef DEBUG
519
520 // Checks reachability of the blocks in this graph and stores a bit in
521 // the BitVector "reachable()" for every block that can be reached
522 // from the start block of the graph. If "dont_visit" is non-null, the given
523 // block is treated as if it would not be part of the graph. "visited_count()"
524 // returns the number of reachable blocks.
525 class ReachabilityAnalyzer BASE_EMBEDDED {
526  public:
527   ReachabilityAnalyzer(HBasicBlock* entry_block,
528                        int block_count,
529                        HBasicBlock* dont_visit)
530       : visited_count_(0),
531         stack_(16, entry_block->zone()),
532         reachable_(block_count, entry_block->zone()),
533         dont_visit_(dont_visit) {
534     PushBlock(entry_block);
535     Analyze();
536   }
537
538   int visited_count() const { return visited_count_; }
539   const BitVector* reachable() const { return &reachable_; }
540
541  private:
542   void PushBlock(HBasicBlock* block) {
543     if (block != NULL && block != dont_visit_ &&
544         !reachable_.Contains(block->block_id())) {
545       reachable_.Add(block->block_id());
546       stack_.Add(block, block->zone());
547       visited_count_++;
548     }
549   }
550
551   void Analyze() {
552     while (!stack_.is_empty()) {
553       HControlInstruction* end = stack_.RemoveLast()->end();
554       for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
555         PushBlock(it.Current());
556       }
557     }
558   }
559
560   int visited_count_;
561   ZoneList<HBasicBlock*> stack_;
562   BitVector reachable_;
563   HBasicBlock* dont_visit_;
564 };
565
566
567 void HGraph::Verify(bool do_full_verify) const {
568   Heap::RelocationLock relocation_lock(isolate()->heap());
569   AllowHandleDereference allow_deref;
570   AllowDeferredHandleDereference allow_deferred_deref;
571   for (int i = 0; i < blocks_.length(); i++) {
572     HBasicBlock* block = blocks_.at(i);
573
574     block->Verify();
575
576     // Check that every block contains at least one node and that only the last
577     // node is a control instruction.
578     HInstruction* current = block->first();
579     DCHECK(current != NULL && current->IsBlockEntry());
580     while (current != NULL) {
581       DCHECK((current->next() == NULL) == current->IsControlInstruction());
582       DCHECK(current->block() == block);
583       current->Verify();
584       current = current->next();
585     }
586
587     // Check that successors are correctly set.
588     HBasicBlock* first = block->end()->FirstSuccessor();
589     HBasicBlock* second = block->end()->SecondSuccessor();
590     DCHECK(second == NULL || first != NULL);
591
592     // Check that the predecessor array is correct.
593     if (first != NULL) {
594       DCHECK(first->predecessors()->Contains(block));
595       if (second != NULL) {
596         DCHECK(second->predecessors()->Contains(block));
597       }
598     }
599
600     // Check that phis have correct arguments.
601     for (int j = 0; j < block->phis()->length(); j++) {
602       HPhi* phi = block->phis()->at(j);
603       phi->Verify();
604     }
605
606     // Check that all join blocks have predecessors that end with an
607     // unconditional goto and agree on their environment node id.
608     if (block->predecessors()->length() >= 2) {
609       BailoutId id =
610           block->predecessors()->first()->last_environment()->ast_id();
611       for (int k = 0; k < block->predecessors()->length(); k++) {
612         HBasicBlock* predecessor = block->predecessors()->at(k);
613         DCHECK(predecessor->end()->IsGoto() ||
614                predecessor->end()->IsDeoptimize());
615         DCHECK(predecessor->last_environment()->ast_id() == id);
616       }
617     }
618   }
619
620   // Check special property of first block to have no predecessors.
621   DCHECK(blocks_.at(0)->predecessors()->is_empty());
622
623   if (do_full_verify) {
624     // Check that the graph is fully connected.
625     ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL);
626     DCHECK(analyzer.visited_count() == blocks_.length());
627
628     // Check that entry block dominator is NULL.
629     DCHECK(entry_block_->dominator() == NULL);
630
631     // Check dominators.
632     for (int i = 0; i < blocks_.length(); ++i) {
633       HBasicBlock* block = blocks_.at(i);
634       if (block->dominator() == NULL) {
635         // Only start block may have no dominator assigned to.
636         DCHECK(i == 0);
637       } else {
638         // Assert that block is unreachable if dominator must not be visited.
639         ReachabilityAnalyzer dominator_analyzer(entry_block_,
640                                                 blocks_.length(),
641                                                 block->dominator());
642         DCHECK(!dominator_analyzer.reachable()->Contains(block->block_id()));
643       }
644     }
645   }
646 }
647
648 #endif
649
650
651 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
652                                int32_t value) {
653   if (!pointer->is_set()) {
654     // Can't pass GetInvalidContext() to HConstant::New, because that will
655     // recursively call GetConstant
656     HConstant* constant = HConstant::New(zone(), NULL, value);
657     constant->InsertAfter(entry_block()->first());
658     pointer->set(constant);
659     return constant;
660   }
661   return ReinsertConstantIfNecessary(pointer->get());
662 }
663
664
665 HConstant* HGraph::ReinsertConstantIfNecessary(HConstant* constant) {
666   if (!constant->IsLinked()) {
667     // The constant was removed from the graph. Reinsert.
668     constant->ClearFlag(HValue::kIsDead);
669     constant->InsertAfter(entry_block()->first());
670   }
671   return constant;
672 }
673
674
675 HConstant* HGraph::GetConstant0() {
676   return GetConstant(&constant_0_, 0);
677 }
678
679
680 HConstant* HGraph::GetConstant1() {
681   return GetConstant(&constant_1_, 1);
682 }
683
684
685 HConstant* HGraph::GetConstantMinus1() {
686   return GetConstant(&constant_minus1_, -1);
687 }
688
689
690 #define DEFINE_GET_CONSTANT(Name, name, type, htype, boolean_value)            \
691 HConstant* HGraph::GetConstant##Name() {                                       \
692   if (!constant_##name##_.is_set()) {                                          \
693     HConstant* constant = new(zone()) HConstant(                               \
694         Unique<Object>::CreateImmovable(isolate()->factory()->name##_value()), \
695         Unique<Map>::CreateImmovable(isolate()->factory()->type##_map()),      \
696         false,                                                                 \
697         Representation::Tagged(),                                              \
698         htype,                                                                 \
699         true,                                                                  \
700         boolean_value,                                                         \
701         false,                                                                 \
702         ODDBALL_TYPE);                                                         \
703     constant->InsertAfter(entry_block()->first());                             \
704     constant_##name##_.set(constant);                                          \
705   }                                                                            \
706   return ReinsertConstantIfNecessary(constant_##name##_.get());                \
707 }
708
709
710 DEFINE_GET_CONSTANT(Undefined, undefined, undefined, HType::Undefined(), false)
711 DEFINE_GET_CONSTANT(True, true, boolean, HType::Boolean(), true)
712 DEFINE_GET_CONSTANT(False, false, boolean, HType::Boolean(), false)
713 DEFINE_GET_CONSTANT(Hole, the_hole, the_hole, HType::None(), false)
714 DEFINE_GET_CONSTANT(Null, null, null, HType::Null(), false)
715
716
717 #undef DEFINE_GET_CONSTANT
718
719 #define DEFINE_IS_CONSTANT(Name, name)                                         \
720 bool HGraph::IsConstant##Name(HConstant* constant) {                           \
721   return constant_##name##_.is_set() && constant == constant_##name##_.get();  \
722 }
723 DEFINE_IS_CONSTANT(Undefined, undefined)
724 DEFINE_IS_CONSTANT(0, 0)
725 DEFINE_IS_CONSTANT(1, 1)
726 DEFINE_IS_CONSTANT(Minus1, minus1)
727 DEFINE_IS_CONSTANT(True, true)
728 DEFINE_IS_CONSTANT(False, false)
729 DEFINE_IS_CONSTANT(Hole, the_hole)
730 DEFINE_IS_CONSTANT(Null, null)
731
732 #undef DEFINE_IS_CONSTANT
733
734
735 HConstant* HGraph::GetInvalidContext() {
736   return GetConstant(&constant_invalid_context_, 0xFFFFC0C7);
737 }
738
739
740 bool HGraph::IsStandardConstant(HConstant* constant) {
741   if (IsConstantUndefined(constant)) return true;
742   if (IsConstant0(constant)) return true;
743   if (IsConstant1(constant)) return true;
744   if (IsConstantMinus1(constant)) return true;
745   if (IsConstantTrue(constant)) return true;
746   if (IsConstantFalse(constant)) return true;
747   if (IsConstantHole(constant)) return true;
748   if (IsConstantNull(constant)) return true;
749   return false;
750 }
751
752
753 HGraphBuilder::IfBuilder::IfBuilder() : builder_(NULL), needs_compare_(true) {}
754
755
756 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder)
757     : needs_compare_(true) {
758   Initialize(builder);
759 }
760
761
762 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder,
763                                     HIfContinuation* continuation)
764     : needs_compare_(false), first_true_block_(NULL), first_false_block_(NULL) {
765   InitializeDontCreateBlocks(builder);
766   continuation->Continue(&first_true_block_, &first_false_block_);
767 }
768
769
770 void HGraphBuilder::IfBuilder::InitializeDontCreateBlocks(
771     HGraphBuilder* builder) {
772   builder_ = builder;
773   finished_ = false;
774   did_then_ = false;
775   did_else_ = false;
776   did_else_if_ = false;
777   did_and_ = false;
778   did_or_ = false;
779   captured_ = false;
780   pending_merge_block_ = false;
781   split_edge_merge_block_ = NULL;
782   merge_at_join_blocks_ = NULL;
783   normal_merge_at_join_block_count_ = 0;
784   deopt_merge_at_join_block_count_ = 0;
785 }
786
787
788 void HGraphBuilder::IfBuilder::Initialize(HGraphBuilder* builder) {
789   InitializeDontCreateBlocks(builder);
790   HEnvironment* env = builder->environment();
791   first_true_block_ = builder->CreateBasicBlock(env->Copy());
792   first_false_block_ = builder->CreateBasicBlock(env->Copy());
793 }
794
795
796 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare(
797     HControlInstruction* compare) {
798   DCHECK(did_then_ == did_else_);
799   if (did_else_) {
800     // Handle if-then-elseif
801     did_else_if_ = true;
802     did_else_ = false;
803     did_then_ = false;
804     did_and_ = false;
805     did_or_ = false;
806     pending_merge_block_ = false;
807     split_edge_merge_block_ = NULL;
808     HEnvironment* env = builder()->environment();
809     first_true_block_ = builder()->CreateBasicBlock(env->Copy());
810     first_false_block_ = builder()->CreateBasicBlock(env->Copy());
811   }
812   if (split_edge_merge_block_ != NULL) {
813     HEnvironment* env = first_false_block_->last_environment();
814     HBasicBlock* split_edge = builder()->CreateBasicBlock(env->Copy());
815     if (did_or_) {
816       compare->SetSuccessorAt(0, split_edge);
817       compare->SetSuccessorAt(1, first_false_block_);
818     } else {
819       compare->SetSuccessorAt(0, first_true_block_);
820       compare->SetSuccessorAt(1, split_edge);
821     }
822     builder()->GotoNoSimulate(split_edge, split_edge_merge_block_);
823   } else {
824     compare->SetSuccessorAt(0, first_true_block_);
825     compare->SetSuccessorAt(1, first_false_block_);
826   }
827   builder()->FinishCurrentBlock(compare);
828   needs_compare_ = false;
829   return compare;
830 }
831
832
833 void HGraphBuilder::IfBuilder::Or() {
834   DCHECK(!needs_compare_);
835   DCHECK(!did_and_);
836   did_or_ = true;
837   HEnvironment* env = first_false_block_->last_environment();
838   if (split_edge_merge_block_ == NULL) {
839     split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
840     builder()->GotoNoSimulate(first_true_block_, split_edge_merge_block_);
841     first_true_block_ = split_edge_merge_block_;
842   }
843   builder()->set_current_block(first_false_block_);
844   first_false_block_ = builder()->CreateBasicBlock(env->Copy());
845 }
846
847
848 void HGraphBuilder::IfBuilder::And() {
849   DCHECK(!needs_compare_);
850   DCHECK(!did_or_);
851   did_and_ = true;
852   HEnvironment* env = first_false_block_->last_environment();
853   if (split_edge_merge_block_ == NULL) {
854     split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
855     builder()->GotoNoSimulate(first_false_block_, split_edge_merge_block_);
856     first_false_block_ = split_edge_merge_block_;
857   }
858   builder()->set_current_block(first_true_block_);
859   first_true_block_ = builder()->CreateBasicBlock(env->Copy());
860 }
861
862
863 void HGraphBuilder::IfBuilder::CaptureContinuation(
864     HIfContinuation* continuation) {
865   DCHECK(!did_else_if_);
866   DCHECK(!finished_);
867   DCHECK(!captured_);
868
869   HBasicBlock* true_block = NULL;
870   HBasicBlock* false_block = NULL;
871   Finish(&true_block, &false_block);
872   DCHECK(true_block != NULL);
873   DCHECK(false_block != NULL);
874   continuation->Capture(true_block, false_block);
875   captured_ = true;
876   builder()->set_current_block(NULL);
877   End();
878 }
879
880
881 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) {
882   DCHECK(!did_else_if_);
883   DCHECK(!finished_);
884   DCHECK(!captured_);
885   HBasicBlock* true_block = NULL;
886   HBasicBlock* false_block = NULL;
887   Finish(&true_block, &false_block);
888   merge_at_join_blocks_ = NULL;
889   if (true_block != NULL && !true_block->IsFinished()) {
890     DCHECK(continuation->IsTrueReachable());
891     builder()->GotoNoSimulate(true_block, continuation->true_branch());
892   }
893   if (false_block != NULL && !false_block->IsFinished()) {
894     DCHECK(continuation->IsFalseReachable());
895     builder()->GotoNoSimulate(false_block, continuation->false_branch());
896   }
897   captured_ = true;
898   End();
899 }
900
901
902 void HGraphBuilder::IfBuilder::Then() {
903   DCHECK(!captured_);
904   DCHECK(!finished_);
905   did_then_ = true;
906   if (needs_compare_) {
907     // Handle if's without any expressions, they jump directly to the "else"
908     // branch. However, we must pretend that the "then" branch is reachable,
909     // so that the graph builder visits it and sees any live range extending
910     // constructs within it.
911     HConstant* constant_false = builder()->graph()->GetConstantFalse();
912     ToBooleanStub::Types boolean_type = ToBooleanStub::Types();
913     boolean_type.Add(ToBooleanStub::BOOLEAN);
914     HBranch* branch = builder()->New<HBranch>(
915         constant_false, boolean_type, first_true_block_, first_false_block_);
916     builder()->FinishCurrentBlock(branch);
917   }
918   builder()->set_current_block(first_true_block_);
919   pending_merge_block_ = true;
920 }
921
922
923 void HGraphBuilder::IfBuilder::Else() {
924   DCHECK(did_then_);
925   DCHECK(!captured_);
926   DCHECK(!finished_);
927   AddMergeAtJoinBlock(false);
928   builder()->set_current_block(first_false_block_);
929   pending_merge_block_ = true;
930   did_else_ = true;
931 }
932
933
934 void HGraphBuilder::IfBuilder::Deopt(const char* reason) {
935   DCHECK(did_then_);
936   builder()->Add<HDeoptimize>(reason, Deoptimizer::EAGER);
937   AddMergeAtJoinBlock(true);
938 }
939
940
941 void HGraphBuilder::IfBuilder::Return(HValue* value) {
942   HValue* parameter_count = builder()->graph()->GetConstantMinus1();
943   builder()->FinishExitCurrentBlock(
944       builder()->New<HReturn>(value, parameter_count));
945   AddMergeAtJoinBlock(false);
946 }
947
948
949 void HGraphBuilder::IfBuilder::AddMergeAtJoinBlock(bool deopt) {
950   if (!pending_merge_block_) return;
951   HBasicBlock* block = builder()->current_block();
952   DCHECK(block == NULL || !block->IsFinished());
953   MergeAtJoinBlock* record = new (builder()->zone())
954       MergeAtJoinBlock(block, deopt, merge_at_join_blocks_);
955   merge_at_join_blocks_ = record;
956   if (block != NULL) {
957     DCHECK(block->end() == NULL);
958     if (deopt) {
959       normal_merge_at_join_block_count_++;
960     } else {
961       deopt_merge_at_join_block_count_++;
962     }
963   }
964   builder()->set_current_block(NULL);
965   pending_merge_block_ = false;
966 }
967
968
969 void HGraphBuilder::IfBuilder::Finish() {
970   DCHECK(!finished_);
971   if (!did_then_) {
972     Then();
973   }
974   AddMergeAtJoinBlock(false);
975   if (!did_else_) {
976     Else();
977     AddMergeAtJoinBlock(false);
978   }
979   finished_ = true;
980 }
981
982
983 void HGraphBuilder::IfBuilder::Finish(HBasicBlock** then_continuation,
984                                       HBasicBlock** else_continuation) {
985   Finish();
986
987   MergeAtJoinBlock* else_record = merge_at_join_blocks_;
988   if (else_continuation != NULL) {
989     *else_continuation = else_record->block_;
990   }
991   MergeAtJoinBlock* then_record = else_record->next_;
992   if (then_continuation != NULL) {
993     *then_continuation = then_record->block_;
994   }
995   DCHECK(then_record->next_ == NULL);
996 }
997
998
999 void HGraphBuilder::IfBuilder::End() {
1000   if (captured_) return;
1001   Finish();
1002
1003   int total_merged_blocks = normal_merge_at_join_block_count_ +
1004     deopt_merge_at_join_block_count_;
1005   DCHECK(total_merged_blocks >= 1);
1006   HBasicBlock* merge_block =
1007       total_merged_blocks == 1 ? NULL : builder()->graph()->CreateBasicBlock();
1008
1009   // Merge non-deopt blocks first to ensure environment has right size for
1010   // padding.
1011   MergeAtJoinBlock* current = merge_at_join_blocks_;
1012   while (current != NULL) {
1013     if (!current->deopt_ && current->block_ != NULL) {
1014       // If there is only one block that makes it through to the end of the
1015       // if, then just set it as the current block and continue rather then
1016       // creating an unnecessary merge block.
1017       if (total_merged_blocks == 1) {
1018         builder()->set_current_block(current->block_);
1019         return;
1020       }
1021       builder()->GotoNoSimulate(current->block_, merge_block);
1022     }
1023     current = current->next_;
1024   }
1025
1026   // Merge deopt blocks, padding when necessary.
1027   current = merge_at_join_blocks_;
1028   while (current != NULL) {
1029     if (current->deopt_ && current->block_ != NULL) {
1030       current->block_->FinishExit(HAbnormalExit::New(builder()->zone(), NULL),
1031                                   HSourcePosition::Unknown());
1032     }
1033     current = current->next_;
1034   }
1035   builder()->set_current_block(merge_block);
1036 }
1037
1038
1039 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder) {
1040   Initialize(builder, NULL, kWhileTrue, NULL);
1041 }
1042
1043
1044 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
1045                                         LoopBuilder::Direction direction) {
1046   Initialize(builder, context, direction, builder->graph()->GetConstant1());
1047 }
1048
1049
1050 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
1051                                         LoopBuilder::Direction direction,
1052                                         HValue* increment_amount) {
1053   Initialize(builder, context, direction, increment_amount);
1054   increment_amount_ = increment_amount;
1055 }
1056
1057
1058 void HGraphBuilder::LoopBuilder::Initialize(HGraphBuilder* builder,
1059                                             HValue* context,
1060                                             Direction direction,
1061                                             HValue* increment_amount) {
1062   builder_ = builder;
1063   context_ = context;
1064   direction_ = direction;
1065   increment_amount_ = increment_amount;
1066
1067   finished_ = false;
1068   header_block_ = builder->CreateLoopHeaderBlock();
1069   body_block_ = NULL;
1070   exit_block_ = NULL;
1071   exit_trampoline_block_ = NULL;
1072 }
1073
1074
1075 HValue* HGraphBuilder::LoopBuilder::BeginBody(
1076     HValue* initial,
1077     HValue* terminating,
1078     Token::Value token) {
1079   DCHECK(direction_ != kWhileTrue);
1080   HEnvironment* env = builder_->environment();
1081   phi_ = header_block_->AddNewPhi(env->values()->length());
1082   phi_->AddInput(initial);
1083   env->Push(initial);
1084   builder_->GotoNoSimulate(header_block_);
1085
1086   HEnvironment* body_env = env->Copy();
1087   HEnvironment* exit_env = env->Copy();
1088   // Remove the phi from the expression stack
1089   body_env->Pop();
1090   exit_env->Pop();
1091   body_block_ = builder_->CreateBasicBlock(body_env);
1092   exit_block_ = builder_->CreateBasicBlock(exit_env);
1093
1094   builder_->set_current_block(header_block_);
1095   env->Pop();
1096   builder_->FinishCurrentBlock(builder_->New<HCompareNumericAndBranch>(
1097           phi_, terminating, token, body_block_, exit_block_));
1098
1099   builder_->set_current_block(body_block_);
1100   if (direction_ == kPreIncrement || direction_ == kPreDecrement) {
1101     HValue* one = builder_->graph()->GetConstant1();
1102     if (direction_ == kPreIncrement) {
1103       increment_ = HAdd::New(zone(), context_, phi_, one);
1104     } else {
1105       increment_ = HSub::New(zone(), context_, phi_, one);
1106     }
1107     increment_->ClearFlag(HValue::kCanOverflow);
1108     builder_->AddInstruction(increment_);
1109     return increment_;
1110   } else {
1111     return phi_;
1112   }
1113 }
1114
1115
1116 void HGraphBuilder::LoopBuilder::BeginBody(int drop_count) {
1117   DCHECK(direction_ == kWhileTrue);
1118   HEnvironment* env = builder_->environment();
1119   builder_->GotoNoSimulate(header_block_);
1120   builder_->set_current_block(header_block_);
1121   env->Drop(drop_count);
1122 }
1123
1124
1125 void HGraphBuilder::LoopBuilder::Break() {
1126   if (exit_trampoline_block_ == NULL) {
1127     // Its the first time we saw a break.
1128     if (direction_ == kWhileTrue) {
1129       HEnvironment* env = builder_->environment()->Copy();
1130       exit_trampoline_block_ = builder_->CreateBasicBlock(env);
1131     } else {
1132       HEnvironment* env = exit_block_->last_environment()->Copy();
1133       exit_trampoline_block_ = builder_->CreateBasicBlock(env);
1134       builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_);
1135     }
1136   }
1137
1138   builder_->GotoNoSimulate(exit_trampoline_block_);
1139   builder_->set_current_block(NULL);
1140 }
1141
1142
1143 void HGraphBuilder::LoopBuilder::EndBody() {
1144   DCHECK(!finished_);
1145
1146   if (direction_ == kPostIncrement || direction_ == kPostDecrement) {
1147     if (direction_ == kPostIncrement) {
1148       increment_ = HAdd::New(zone(), context_, phi_, increment_amount_);
1149     } else {
1150       increment_ = HSub::New(zone(), context_, phi_, increment_amount_);
1151     }
1152     increment_->ClearFlag(HValue::kCanOverflow);
1153     builder_->AddInstruction(increment_);
1154   }
1155
1156   if (direction_ != kWhileTrue) {
1157     // Push the new increment value on the expression stack to merge into
1158     // the phi.
1159     builder_->environment()->Push(increment_);
1160   }
1161   HBasicBlock* last_block = builder_->current_block();
1162   builder_->GotoNoSimulate(last_block, header_block_);
1163   header_block_->loop_information()->RegisterBackEdge(last_block);
1164
1165   if (exit_trampoline_block_ != NULL) {
1166     builder_->set_current_block(exit_trampoline_block_);
1167   } else {
1168     builder_->set_current_block(exit_block_);
1169   }
1170   finished_ = true;
1171 }
1172
1173
1174 HGraph* HGraphBuilder::CreateGraph() {
1175   graph_ = new(zone()) HGraph(info_);
1176   if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_);
1177   CompilationPhase phase("H_Block building", info_);
1178   set_current_block(graph()->entry_block());
1179   if (!BuildGraph()) return NULL;
1180   graph()->FinalizeUniqueness();
1181   return graph_;
1182 }
1183
1184
1185 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
1186   DCHECK(current_block() != NULL);
1187   DCHECK(!FLAG_hydrogen_track_positions ||
1188          !position_.IsUnknown() ||
1189          !info_->IsOptimizing());
1190   current_block()->AddInstruction(instr, source_position());
1191   if (graph()->IsInsideNoSideEffectsScope()) {
1192     instr->SetFlag(HValue::kHasNoObservableSideEffects);
1193   }
1194   return instr;
1195 }
1196
1197
1198 void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) {
1199   DCHECK(!FLAG_hydrogen_track_positions ||
1200          !info_->IsOptimizing() ||
1201          !position_.IsUnknown());
1202   current_block()->Finish(last, source_position());
1203   if (last->IsReturn() || last->IsAbnormalExit()) {
1204     set_current_block(NULL);
1205   }
1206 }
1207
1208
1209 void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) {
1210   DCHECK(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() ||
1211          !position_.IsUnknown());
1212   current_block()->FinishExit(instruction, source_position());
1213   if (instruction->IsReturn() || instruction->IsAbnormalExit()) {
1214     set_current_block(NULL);
1215   }
1216 }
1217
1218
1219 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) {
1220   if (FLAG_native_code_counters && counter->Enabled()) {
1221     HValue* reference = Add<HConstant>(ExternalReference(counter));
1222     HValue* old_value = Add<HLoadNamedField>(
1223         reference, static_cast<HValue*>(NULL), HObjectAccess::ForCounter());
1224     HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1());
1225     new_value->ClearFlag(HValue::kCanOverflow);  // Ignore counter overflow
1226     Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(),
1227                           new_value, STORE_TO_INITIALIZED_ENTRY);
1228   }
1229 }
1230
1231
1232 void HGraphBuilder::AddSimulate(BailoutId id,
1233                                 RemovableSimulate removable) {
1234   DCHECK(current_block() != NULL);
1235   DCHECK(!graph()->IsInsideNoSideEffectsScope());
1236   current_block()->AddNewSimulate(id, source_position(), removable);
1237 }
1238
1239
1240 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
1241   HBasicBlock* b = graph()->CreateBasicBlock();
1242   b->SetInitialEnvironment(env);
1243   return b;
1244 }
1245
1246
1247 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
1248   HBasicBlock* header = graph()->CreateBasicBlock();
1249   HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
1250   header->SetInitialEnvironment(entry_env);
1251   header->AttachLoopInformation();
1252   return header;
1253 }
1254
1255
1256 HValue* HGraphBuilder::BuildGetElementsKind(HValue* object) {
1257   HValue* map = Add<HLoadNamedField>(object, static_cast<HValue*>(NULL),
1258                                      HObjectAccess::ForMap());
1259
1260   HValue* bit_field2 = Add<HLoadNamedField>(map, static_cast<HValue*>(NULL),
1261                                             HObjectAccess::ForMapBitField2());
1262   return BuildDecodeField<Map::ElementsKindBits>(bit_field2);
1263 }
1264
1265
1266 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) {
1267   if (obj->type().IsHeapObject()) return obj;
1268   return Add<HCheckHeapObject>(obj);
1269 }
1270
1271
1272 void HGraphBuilder::FinishExitWithHardDeoptimization(const char* reason) {
1273   Add<HDeoptimize>(reason, Deoptimizer::EAGER);
1274   FinishExitCurrentBlock(New<HAbnormalExit>());
1275 }
1276
1277
1278 HValue* HGraphBuilder::BuildCheckString(HValue* string) {
1279   if (!string->type().IsString()) {
1280     DCHECK(!string->IsConstant() ||
1281            !HConstant::cast(string)->HasStringValue());
1282     BuildCheckHeapObject(string);
1283     return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
1284   }
1285   return string;
1286 }
1287
1288
1289 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) {
1290   if (object->type().IsJSObject()) return object;
1291   if (function->IsConstant() &&
1292       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
1293     Handle<JSFunction> f = Handle<JSFunction>::cast(
1294         HConstant::cast(function)->handle(isolate()));
1295     SharedFunctionInfo* shared = f->shared();
1296     if (shared->strict_mode() == STRICT || shared->native()) return object;
1297   }
1298   return Add<HWrapReceiver>(object, function);
1299 }
1300
1301
1302 HValue* HGraphBuilder::BuildCheckForCapacityGrow(
1303     HValue* object,
1304     HValue* elements,
1305     ElementsKind kind,
1306     HValue* length,
1307     HValue* key,
1308     bool is_js_array,
1309     PropertyAccessType access_type) {
1310   IfBuilder length_checker(this);
1311
1312   Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
1313   length_checker.If<HCompareNumericAndBranch>(key, length, token);
1314
1315   length_checker.Then();
1316
1317   HValue* current_capacity = AddLoadFixedArrayLength(elements);
1318
1319   IfBuilder capacity_checker(this);
1320
1321   capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity,
1322                                                 Token::GTE);
1323   capacity_checker.Then();
1324
1325   HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
1326   HValue* max_capacity = AddUncasted<HAdd>(current_capacity, max_gap);
1327
1328   Add<HBoundsCheck>(key, max_capacity);
1329
1330   HValue* new_capacity = BuildNewElementsCapacity(key);
1331   HValue* new_elements = BuildGrowElementsCapacity(object, elements,
1332                                                    kind, kind, length,
1333                                                    new_capacity);
1334
1335   environment()->Push(new_elements);
1336   capacity_checker.Else();
1337
1338   environment()->Push(elements);
1339   capacity_checker.End();
1340
1341   if (is_js_array) {
1342     HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1());
1343     new_length->ClearFlag(HValue::kCanOverflow);
1344
1345     Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind),
1346                           new_length);
1347   }
1348
1349   if (access_type == STORE && kind == FAST_SMI_ELEMENTS) {
1350     HValue* checked_elements = environment()->Top();
1351
1352     // Write zero to ensure that the new element is initialized with some smi.
1353     Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), kind);
1354   }
1355
1356   length_checker.Else();
1357   Add<HBoundsCheck>(key, length);
1358
1359   environment()->Push(elements);
1360   length_checker.End();
1361
1362   return environment()->Pop();
1363 }
1364
1365
1366 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
1367                                                 HValue* elements,
1368                                                 ElementsKind kind,
1369                                                 HValue* length) {
1370   Factory* factory = isolate()->factory();
1371
1372   IfBuilder cow_checker(this);
1373
1374   cow_checker.If<HCompareMap>(elements, factory->fixed_cow_array_map());
1375   cow_checker.Then();
1376
1377   HValue* capacity = AddLoadFixedArrayLength(elements);
1378
1379   HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind,
1380                                                    kind, length, capacity);
1381
1382   environment()->Push(new_elements);
1383
1384   cow_checker.Else();
1385
1386   environment()->Push(elements);
1387
1388   cow_checker.End();
1389
1390   return environment()->Pop();
1391 }
1392
1393
1394 void HGraphBuilder::BuildTransitionElementsKind(HValue* object,
1395                                                 HValue* map,
1396                                                 ElementsKind from_kind,
1397                                                 ElementsKind to_kind,
1398                                                 bool is_jsarray) {
1399   DCHECK(!IsFastHoleyElementsKind(from_kind) ||
1400          IsFastHoleyElementsKind(to_kind));
1401
1402   if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) {
1403     Add<HTrapAllocationMemento>(object);
1404   }
1405
1406   if (!IsSimpleMapChangeTransition(from_kind, to_kind)) {
1407     HInstruction* elements = AddLoadElements(object);
1408
1409     HInstruction* empty_fixed_array = Add<HConstant>(
1410         isolate()->factory()->empty_fixed_array());
1411
1412     IfBuilder if_builder(this);
1413
1414     if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array);
1415
1416     if_builder.Then();
1417
1418     HInstruction* elements_length = AddLoadFixedArrayLength(elements);
1419
1420     HInstruction* array_length = is_jsarray
1421         ? Add<HLoadNamedField>(object, static_cast<HValue*>(NULL),
1422                                HObjectAccess::ForArrayLength(from_kind))
1423         : elements_length;
1424
1425     BuildGrowElementsCapacity(object, elements, from_kind, to_kind,
1426                               array_length, elements_length);
1427
1428     if_builder.End();
1429   }
1430
1431   Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map);
1432 }
1433
1434
1435 void HGraphBuilder::BuildJSObjectCheck(HValue* receiver,
1436                                        int bit_field_mask) {
1437   // Check that the object isn't a smi.
1438   Add<HCheckHeapObject>(receiver);
1439
1440   // Get the map of the receiver.
1441   HValue* map = Add<HLoadNamedField>(receiver, static_cast<HValue*>(NULL),
1442                                      HObjectAccess::ForMap());
1443
1444   // Check the instance type and if an access check is needed, this can be
1445   // done with a single load, since both bytes are adjacent in the map.
1446   HObjectAccess access(HObjectAccess::ForMapInstanceTypeAndBitField());
1447   HValue* instance_type_and_bit_field =
1448       Add<HLoadNamedField>(map, static_cast<HValue*>(NULL), access);
1449
1450   HValue* mask = Add<HConstant>(0x00FF | (bit_field_mask << 8));
1451   HValue* and_result = AddUncasted<HBitwise>(Token::BIT_AND,
1452                                              instance_type_and_bit_field,
1453                                              mask);
1454   HValue* sub_result = AddUncasted<HSub>(and_result,
1455                                          Add<HConstant>(JS_OBJECT_TYPE));
1456   Add<HBoundsCheck>(sub_result,
1457                     Add<HConstant>(LAST_JS_OBJECT_TYPE + 1 - JS_OBJECT_TYPE));
1458 }
1459
1460
1461 void HGraphBuilder::BuildKeyedIndexCheck(HValue* key,
1462                                          HIfContinuation* join_continuation) {
1463   // The sometimes unintuitively backward ordering of the ifs below is
1464   // convoluted, but necessary.  All of the paths must guarantee that the
1465   // if-true of the continuation returns a smi element index and the if-false of
1466   // the continuation returns either a symbol or a unique string key. All other
1467   // object types cause a deopt to fall back to the runtime.
1468
1469   IfBuilder key_smi_if(this);
1470   key_smi_if.If<HIsSmiAndBranch>(key);
1471   key_smi_if.Then();
1472   {
1473     Push(key);  // Nothing to do, just continue to true of continuation.
1474   }
1475   key_smi_if.Else();
1476   {
1477     HValue* map = Add<HLoadNamedField>(key, static_cast<HValue*>(NULL),
1478                                        HObjectAccess::ForMap());
1479     HValue* instance_type =
1480         Add<HLoadNamedField>(map, static_cast<HValue*>(NULL),
1481                              HObjectAccess::ForMapInstanceType());
1482
1483     // Non-unique string, check for a string with a hash code that is actually
1484     // an index.
1485     STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE);
1486     IfBuilder not_string_or_name_if(this);
1487     not_string_or_name_if.If<HCompareNumericAndBranch>(
1488         instance_type,
1489         Add<HConstant>(LAST_UNIQUE_NAME_TYPE),
1490         Token::GT);
1491
1492     not_string_or_name_if.Then();
1493     {
1494       // Non-smi, non-Name, non-String: Try to convert to smi in case of
1495       // HeapNumber.
1496       // TODO(danno): This could call some variant of ToString
1497       Push(AddUncasted<HForceRepresentation>(key, Representation::Smi()));
1498     }
1499     not_string_or_name_if.Else();
1500     {
1501       // String or Name: check explicitly for Name, they can short-circuit
1502       // directly to unique non-index key path.
1503       IfBuilder not_symbol_if(this);
1504       not_symbol_if.If<HCompareNumericAndBranch>(
1505           instance_type,
1506           Add<HConstant>(SYMBOL_TYPE),
1507           Token::NE);
1508
1509       not_symbol_if.Then();
1510       {
1511         // String: check whether the String is a String of an index. If it is,
1512         // extract the index value from the hash.
1513         HValue* hash =
1514             Add<HLoadNamedField>(key, static_cast<HValue*>(NULL),
1515                                  HObjectAccess::ForNameHashField());
1516         HValue* not_index_mask = Add<HConstant>(static_cast<int>(
1517             String::kContainsCachedArrayIndexMask));
1518
1519         HValue* not_index_test = AddUncasted<HBitwise>(
1520             Token::BIT_AND, hash, not_index_mask);
1521
1522         IfBuilder string_index_if(this);
1523         string_index_if.If<HCompareNumericAndBranch>(not_index_test,
1524                                                      graph()->GetConstant0(),
1525                                                      Token::EQ);
1526         string_index_if.Then();
1527         {
1528           // String with index in hash: extract string and merge to index path.
1529           Push(BuildDecodeField<String::ArrayIndexValueBits>(hash));
1530         }
1531         string_index_if.Else();
1532         {
1533           // Key is a non-index String, check for uniqueness/internalization.
1534           // If it's not internalized yet, internalize it now.
1535           HValue* not_internalized_bit = AddUncasted<HBitwise>(
1536               Token::BIT_AND,
1537               instance_type,
1538               Add<HConstant>(static_cast<int>(kIsNotInternalizedMask)));
1539
1540           IfBuilder internalized(this);
1541           internalized.If<HCompareNumericAndBranch>(not_internalized_bit,
1542                                                     graph()->GetConstant0(),
1543                                                     Token::EQ);
1544           internalized.Then();
1545           Push(key);
1546
1547           internalized.Else();
1548           Add<HPushArguments>(key);
1549           HValue* intern_key = Add<HCallRuntime>(
1550               isolate()->factory()->empty_string(),
1551               Runtime::FunctionForId(Runtime::kInternalizeString), 1);
1552           Push(intern_key);
1553
1554           internalized.End();
1555           // Key guaranteed to be a unique string
1556         }
1557         string_index_if.JoinContinuation(join_continuation);
1558       }
1559       not_symbol_if.Else();
1560       {
1561         Push(key);  // Key is symbol
1562       }
1563       not_symbol_if.JoinContinuation(join_continuation);
1564     }
1565     not_string_or_name_if.JoinContinuation(join_continuation);
1566   }
1567   key_smi_if.JoinContinuation(join_continuation);
1568 }
1569
1570
1571 void HGraphBuilder::BuildNonGlobalObjectCheck(HValue* receiver) {
1572   // Get the the instance type of the receiver, and make sure that it is
1573   // not one of the global object types.
1574   HValue* map = Add<HLoadNamedField>(receiver, static_cast<HValue*>(NULL),
1575                                      HObjectAccess::ForMap());
1576   HValue* instance_type =
1577     Add<HLoadNamedField>(map, static_cast<HValue*>(NULL),
1578                          HObjectAccess::ForMapInstanceType());
1579   STATIC_ASSERT(JS_BUILTINS_OBJECT_TYPE == JS_GLOBAL_OBJECT_TYPE + 1);
1580   HValue* min_global_type = Add<HConstant>(JS_GLOBAL_OBJECT_TYPE);
1581   HValue* max_global_type = Add<HConstant>(JS_BUILTINS_OBJECT_TYPE);
1582
1583   IfBuilder if_global_object(this);
1584   if_global_object.If<HCompareNumericAndBranch>(instance_type,
1585                                                 max_global_type,
1586                                                 Token::LTE);
1587   if_global_object.And();
1588   if_global_object.If<HCompareNumericAndBranch>(instance_type,
1589                                                 min_global_type,
1590                                                 Token::GTE);
1591   if_global_object.ThenDeopt("receiver was a global object");
1592   if_global_object.End();
1593 }
1594
1595
1596 void HGraphBuilder::BuildTestForDictionaryProperties(
1597     HValue* object,
1598     HIfContinuation* continuation) {
1599   HValue* properties = Add<HLoadNamedField>(
1600       object, static_cast<HValue*>(NULL),
1601       HObjectAccess::ForPropertiesPointer());
1602   HValue* properties_map =
1603       Add<HLoadNamedField>(properties, static_cast<HValue*>(NULL),
1604                            HObjectAccess::ForMap());
1605   HValue* hash_map = Add<HLoadRoot>(Heap::kHashTableMapRootIndex);
1606   IfBuilder builder(this);
1607   builder.If<HCompareObjectEqAndBranch>(properties_map, hash_map);
1608   builder.CaptureContinuation(continuation);
1609 }
1610
1611
1612 HValue* HGraphBuilder::BuildKeyedLookupCacheHash(HValue* object,
1613                                                  HValue* key) {
1614   // Load the map of the receiver, compute the keyed lookup cache hash
1615   // based on 32 bits of the map pointer and the string hash.
1616   HValue* object_map =
1617       Add<HLoadNamedField>(object, static_cast<HValue*>(NULL),
1618                            HObjectAccess::ForMapAsInteger32());
1619   HValue* shifted_map = AddUncasted<HShr>(
1620       object_map, Add<HConstant>(KeyedLookupCache::kMapHashShift));
1621   HValue* string_hash =
1622       Add<HLoadNamedField>(key, static_cast<HValue*>(NULL),
1623                            HObjectAccess::ForStringHashField());
1624   HValue* shifted_hash = AddUncasted<HShr>(
1625       string_hash, Add<HConstant>(String::kHashShift));
1626   HValue* xor_result = AddUncasted<HBitwise>(Token::BIT_XOR, shifted_map,
1627                                              shifted_hash);
1628   int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
1629   return AddUncasted<HBitwise>(Token::BIT_AND, xor_result,
1630                                Add<HConstant>(mask));
1631 }
1632
1633
1634 HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) {
1635   int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed());
1636   HValue* seed = Add<HConstant>(seed_value);
1637   HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, index, seed);
1638
1639   // hash = ~hash + (hash << 15);
1640   HValue* shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(15));
1641   HValue* not_hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash,
1642                                            graph()->GetConstantMinus1());
1643   hash = AddUncasted<HAdd>(shifted_hash, not_hash);
1644
1645   // hash = hash ^ (hash >> 12);
1646   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(12));
1647   hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
1648
1649   // hash = hash + (hash << 2);
1650   shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(2));
1651   hash = AddUncasted<HAdd>(hash, shifted_hash);
1652
1653   // hash = hash ^ (hash >> 4);
1654   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(4));
1655   hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
1656
1657   // hash = hash * 2057;
1658   hash = AddUncasted<HMul>(hash, Add<HConstant>(2057));
1659   hash->ClearFlag(HValue::kCanOverflow);
1660
1661   // hash = hash ^ (hash >> 16);
1662   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(16));
1663   return AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
1664 }
1665
1666
1667 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver,
1668                                                            HValue* elements,
1669                                                            HValue* key,
1670                                                            HValue* hash) {
1671   HValue* capacity = Add<HLoadKeyed>(
1672       elements,
1673       Add<HConstant>(NameDictionary::kCapacityIndex),
1674       static_cast<HValue*>(NULL),
1675       FAST_ELEMENTS);
1676
1677   HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1());
1678   mask->ChangeRepresentation(Representation::Integer32());
1679   mask->ClearFlag(HValue::kCanOverflow);
1680
1681   HValue* entry = hash;
1682   HValue* count = graph()->GetConstant1();
1683   Push(entry);
1684   Push(count);
1685
1686   HIfContinuation return_or_loop_continuation(graph()->CreateBasicBlock(),
1687                                               graph()->CreateBasicBlock());
1688   HIfContinuation found_key_match_continuation(graph()->CreateBasicBlock(),
1689                                                graph()->CreateBasicBlock());
1690   LoopBuilder probe_loop(this);
1691   probe_loop.BeginBody(2);  // Drop entry, count from last environment to
1692                             // appease live range building without simulates.
1693
1694   count = Pop();
1695   entry = Pop();
1696   entry = AddUncasted<HBitwise>(Token::BIT_AND, entry, mask);
1697   int entry_size = SeededNumberDictionary::kEntrySize;
1698   HValue* base_index = AddUncasted<HMul>(entry, Add<HConstant>(entry_size));
1699   base_index->ClearFlag(HValue::kCanOverflow);
1700   int start_offset = SeededNumberDictionary::kElementsStartIndex;
1701   HValue* key_index =
1702       AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset));
1703   key_index->ClearFlag(HValue::kCanOverflow);
1704
1705   HValue* candidate_key = Add<HLoadKeyed>(
1706       elements, key_index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
1707   IfBuilder if_undefined(this);
1708   if_undefined.If<HCompareObjectEqAndBranch>(candidate_key,
1709                                              graph()->GetConstantUndefined());
1710   if_undefined.Then();
1711   {
1712     // element == undefined means "not found". Call the runtime.
1713     // TODO(jkummerow): walk the prototype chain instead.
1714     Add<HPushArguments>(receiver, key);
1715     Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
1716                            Runtime::FunctionForId(Runtime::kKeyedGetProperty),
1717                            2));
1718   }
1719   if_undefined.Else();
1720   {
1721     IfBuilder if_match(this);
1722     if_match.If<HCompareObjectEqAndBranch>(candidate_key, key);
1723     if_match.Then();
1724     if_match.Else();
1725
1726     // Update non-internalized string in the dictionary with internalized key?
1727     IfBuilder if_update_with_internalized(this);
1728     HValue* smi_check =
1729         if_update_with_internalized.IfNot<HIsSmiAndBranch>(candidate_key);
1730     if_update_with_internalized.And();
1731     HValue* map = AddLoadMap(candidate_key, smi_check);
1732     HValue* instance_type = Add<HLoadNamedField>(
1733         map, static_cast<HValue*>(NULL), HObjectAccess::ForMapInstanceType());
1734     HValue* not_internalized_bit = AddUncasted<HBitwise>(
1735         Token::BIT_AND, instance_type,
1736         Add<HConstant>(static_cast<int>(kIsNotInternalizedMask)));
1737     if_update_with_internalized.If<HCompareNumericAndBranch>(
1738         not_internalized_bit, graph()->GetConstant0(), Token::NE);
1739     if_update_with_internalized.And();
1740     if_update_with_internalized.IfNot<HCompareObjectEqAndBranch>(
1741         candidate_key, graph()->GetConstantHole());
1742     if_update_with_internalized.AndIf<HStringCompareAndBranch>(candidate_key,
1743                                                                key, Token::EQ);
1744     if_update_with_internalized.Then();
1745     // Replace a key that is a non-internalized string by the equivalent
1746     // internalized string for faster further lookups.
1747     Add<HStoreKeyed>(elements, key_index, key, FAST_ELEMENTS);
1748     if_update_with_internalized.Else();
1749
1750     if_update_with_internalized.JoinContinuation(&found_key_match_continuation);
1751     if_match.JoinContinuation(&found_key_match_continuation);
1752
1753     IfBuilder found_key_match(this, &found_key_match_continuation);
1754     found_key_match.Then();
1755     // Key at current probe matches. Relevant bits in the |details| field must
1756     // be zero, otherwise the dictionary element requires special handling.
1757     HValue* details_index =
1758         AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 2));
1759     details_index->ClearFlag(HValue::kCanOverflow);
1760     HValue* details = Add<HLoadKeyed>(
1761         elements, details_index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
1762     int details_mask = PropertyDetails::TypeField::kMask |
1763                        PropertyDetails::DeletedField::kMask;
1764     details = AddUncasted<HBitwise>(Token::BIT_AND, details,
1765                                     Add<HConstant>(details_mask));
1766     IfBuilder details_compare(this);
1767     details_compare.If<HCompareNumericAndBranch>(
1768         details, graph()->GetConstant0(), Token::EQ);
1769     details_compare.Then();
1770     HValue* result_index =
1771         AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 1));
1772     result_index->ClearFlag(HValue::kCanOverflow);
1773     Push(Add<HLoadKeyed>(elements, result_index, static_cast<HValue*>(NULL),
1774                          FAST_ELEMENTS));
1775     details_compare.Else();
1776     Add<HPushArguments>(receiver, key);
1777     Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
1778                            Runtime::FunctionForId(Runtime::kKeyedGetProperty),
1779                            2));
1780     details_compare.End();
1781
1782     found_key_match.Else();
1783     found_key_match.JoinContinuation(&return_or_loop_continuation);
1784   }
1785   if_undefined.JoinContinuation(&return_or_loop_continuation);
1786
1787   IfBuilder return_or_loop(this, &return_or_loop_continuation);
1788   return_or_loop.Then();
1789   probe_loop.Break();
1790
1791   return_or_loop.Else();
1792   entry = AddUncasted<HAdd>(entry, count);
1793   entry->ClearFlag(HValue::kCanOverflow);
1794   count = AddUncasted<HAdd>(count, graph()->GetConstant1());
1795   count->ClearFlag(HValue::kCanOverflow);
1796   Push(entry);
1797   Push(count);
1798
1799   probe_loop.EndBody();
1800
1801   return_or_loop.End();
1802
1803   return Pop();
1804 }
1805
1806
1807 HValue* HGraphBuilder::BuildRegExpConstructResult(HValue* length,
1808                                                   HValue* index,
1809                                                   HValue* input) {
1810   NoObservableSideEffectsScope scope(this);
1811   HConstant* max_length = Add<HConstant>(JSObject::kInitialMaxFastElementArray);
1812   Add<HBoundsCheck>(length, max_length);
1813
1814   // Generate size calculation code here in order to make it dominate
1815   // the JSRegExpResult allocation.
1816   ElementsKind elements_kind = FAST_ELEMENTS;
1817   HValue* size = BuildCalculateElementsSize(elements_kind, length);
1818
1819   // Allocate the JSRegExpResult and the FixedArray in one step.
1820   HValue* result = Add<HAllocate>(
1821       Add<HConstant>(JSRegExpResult::kSize), HType::JSArray(),
1822       NOT_TENURED, JS_ARRAY_TYPE);
1823
1824   // Initialize the JSRegExpResult header.
1825   HValue* global_object = Add<HLoadNamedField>(
1826       context(), static_cast<HValue*>(NULL),
1827       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
1828   HValue* native_context = Add<HLoadNamedField>(
1829       global_object, static_cast<HValue*>(NULL),
1830       HObjectAccess::ForGlobalObjectNativeContext());
1831   Add<HStoreNamedField>(
1832       result, HObjectAccess::ForMap(),
1833       Add<HLoadNamedField>(
1834           native_context, static_cast<HValue*>(NULL),
1835           HObjectAccess::ForContextSlot(Context::REGEXP_RESULT_MAP_INDEX)));
1836   HConstant* empty_fixed_array =
1837       Add<HConstant>(isolate()->factory()->empty_fixed_array());
1838   Add<HStoreNamedField>(
1839       result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset),
1840       empty_fixed_array);
1841   Add<HStoreNamedField>(
1842       result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
1843       empty_fixed_array);
1844   Add<HStoreNamedField>(
1845       result, HObjectAccess::ForJSArrayOffset(JSArray::kLengthOffset), length);
1846
1847   // Initialize the additional fields.
1848   Add<HStoreNamedField>(
1849       result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kIndexOffset),
1850       index);
1851   Add<HStoreNamedField>(
1852       result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kInputOffset),
1853       input);
1854
1855   // Allocate and initialize the elements header.
1856   HAllocate* elements = BuildAllocateElements(elements_kind, size);
1857   BuildInitializeElementsHeader(elements, elements_kind, length);
1858
1859   HConstant* size_in_bytes_upper_bound = EstablishElementsAllocationSize(
1860       elements_kind, max_length->Integer32Value());
1861   elements->set_size_upper_bound(size_in_bytes_upper_bound);
1862
1863   Add<HStoreNamedField>(
1864       result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
1865       elements);
1866
1867   // Initialize the elements contents with undefined.
1868   BuildFillElementsWithValue(
1869       elements, elements_kind, graph()->GetConstant0(), length,
1870       graph()->GetConstantUndefined());
1871
1872   return result;
1873 }
1874
1875
1876 HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) {
1877   NoObservableSideEffectsScope scope(this);
1878
1879   // Convert constant numbers at compile time.
1880   if (object->IsConstant() && HConstant::cast(object)->HasNumberValue()) {
1881     Handle<Object> number = HConstant::cast(object)->handle(isolate());
1882     Handle<String> result = isolate()->factory()->NumberToString(number);
1883     return Add<HConstant>(result);
1884   }
1885
1886   // Create a joinable continuation.
1887   HIfContinuation found(graph()->CreateBasicBlock(),
1888                         graph()->CreateBasicBlock());
1889
1890   // Load the number string cache.
1891   HValue* number_string_cache =
1892       Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex);
1893
1894   // Make the hash mask from the length of the number string cache. It
1895   // contains two elements (number and string) for each cache entry.
1896   HValue* mask = AddLoadFixedArrayLength(number_string_cache);
1897   mask->set_type(HType::Smi());
1898   mask = AddUncasted<HSar>(mask, graph()->GetConstant1());
1899   mask = AddUncasted<HSub>(mask, graph()->GetConstant1());
1900
1901   // Check whether object is a smi.
1902   IfBuilder if_objectissmi(this);
1903   if_objectissmi.If<HIsSmiAndBranch>(object);
1904   if_objectissmi.Then();
1905   {
1906     // Compute hash for smi similar to smi_get_hash().
1907     HValue* hash = AddUncasted<HBitwise>(Token::BIT_AND, object, mask);
1908
1909     // Load the key.
1910     HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
1911     HValue* key = Add<HLoadKeyed>(number_string_cache, key_index,
1912                                   static_cast<HValue*>(NULL),
1913                                   FAST_ELEMENTS, ALLOW_RETURN_HOLE);
1914
1915     // Check if object == key.
1916     IfBuilder if_objectiskey(this);
1917     if_objectiskey.If<HCompareObjectEqAndBranch>(object, key);
1918     if_objectiskey.Then();
1919     {
1920       // Make the key_index available.
1921       Push(key_index);
1922     }
1923     if_objectiskey.JoinContinuation(&found);
1924   }
1925   if_objectissmi.Else();
1926   {
1927     if (type->Is(Type::SignedSmall())) {
1928       if_objectissmi.Deopt("Expected smi");
1929     } else {
1930       // Check if the object is a heap number.
1931       IfBuilder if_objectisnumber(this);
1932       HValue* objectisnumber = if_objectisnumber.If<HCompareMap>(
1933           object, isolate()->factory()->heap_number_map());
1934       if_objectisnumber.Then();
1935       {
1936         // Compute hash for heap number similar to double_get_hash().
1937         HValue* low = Add<HLoadNamedField>(
1938             object, objectisnumber,
1939             HObjectAccess::ForHeapNumberValueLowestBits());
1940         HValue* high = Add<HLoadNamedField>(
1941             object, objectisnumber,
1942             HObjectAccess::ForHeapNumberValueHighestBits());
1943         HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, low, high);
1944         hash = AddUncasted<HBitwise>(Token::BIT_AND, hash, mask);
1945
1946         // Load the key.
1947         HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
1948         HValue* key = Add<HLoadKeyed>(number_string_cache, key_index,
1949                                       static_cast<HValue*>(NULL),
1950                                       FAST_ELEMENTS, ALLOW_RETURN_HOLE);
1951
1952         // Check if the key is a heap number and compare it with the object.
1953         IfBuilder if_keyisnotsmi(this);
1954         HValue* keyisnotsmi = if_keyisnotsmi.IfNot<HIsSmiAndBranch>(key);
1955         if_keyisnotsmi.Then();
1956         {
1957           IfBuilder if_keyisheapnumber(this);
1958           if_keyisheapnumber.If<HCompareMap>(
1959               key, isolate()->factory()->heap_number_map());
1960           if_keyisheapnumber.Then();
1961           {
1962             // Check if values of key and object match.
1963             IfBuilder if_keyeqobject(this);
1964             if_keyeqobject.If<HCompareNumericAndBranch>(
1965                 Add<HLoadNamedField>(key, keyisnotsmi,
1966                                      HObjectAccess::ForHeapNumberValue()),
1967                 Add<HLoadNamedField>(object, objectisnumber,
1968                                      HObjectAccess::ForHeapNumberValue()),
1969                 Token::EQ);
1970             if_keyeqobject.Then();
1971             {
1972               // Make the key_index available.
1973               Push(key_index);
1974             }
1975             if_keyeqobject.JoinContinuation(&found);
1976           }
1977           if_keyisheapnumber.JoinContinuation(&found);
1978         }
1979         if_keyisnotsmi.JoinContinuation(&found);
1980       }
1981       if_objectisnumber.Else();
1982       {
1983         if (type->Is(Type::Number())) {
1984           if_objectisnumber.Deopt("Expected heap number");
1985         }
1986       }
1987       if_objectisnumber.JoinContinuation(&found);
1988     }
1989   }
1990   if_objectissmi.JoinContinuation(&found);
1991
1992   // Check for cache hit.
1993   IfBuilder if_found(this, &found);
1994   if_found.Then();
1995   {
1996     // Count number to string operation in native code.
1997     AddIncrementCounter(isolate()->counters()->number_to_string_native());
1998
1999     // Load the value in case of cache hit.
2000     HValue* key_index = Pop();
2001     HValue* value_index = AddUncasted<HAdd>(key_index, graph()->GetConstant1());
2002     Push(Add<HLoadKeyed>(number_string_cache, value_index,
2003                          static_cast<HValue*>(NULL),
2004                          FAST_ELEMENTS, ALLOW_RETURN_HOLE));
2005   }
2006   if_found.Else();
2007   {
2008     // Cache miss, fallback to runtime.
2009     Add<HPushArguments>(object);
2010     Push(Add<HCallRuntime>(
2011             isolate()->factory()->empty_string(),
2012             Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
2013             1));
2014   }
2015   if_found.End();
2016
2017   return Pop();
2018 }
2019
2020
2021 HAllocate* HGraphBuilder::BuildAllocate(
2022     HValue* object_size,
2023     HType type,
2024     InstanceType instance_type,
2025     HAllocationMode allocation_mode) {
2026   // Compute the effective allocation size.
2027   HValue* size = object_size;
2028   if (allocation_mode.CreateAllocationMementos()) {
2029     size = AddUncasted<HAdd>(size, Add<HConstant>(AllocationMemento::kSize));
2030     size->ClearFlag(HValue::kCanOverflow);
2031   }
2032
2033   // Perform the actual allocation.
2034   HAllocate* object = Add<HAllocate>(
2035       size, type, allocation_mode.GetPretenureMode(),
2036       instance_type, allocation_mode.feedback_site());
2037
2038   // Setup the allocation memento.
2039   if (allocation_mode.CreateAllocationMementos()) {
2040     BuildCreateAllocationMemento(
2041         object, object_size, allocation_mode.current_site());
2042   }
2043
2044   return object;
2045 }
2046
2047
2048 HValue* HGraphBuilder::BuildAddStringLengths(HValue* left_length,
2049                                              HValue* right_length) {
2050   // Compute the combined string length and check against max string length.
2051   HValue* length = AddUncasted<HAdd>(left_length, right_length);
2052   // Check that length <= kMaxLength <=> length < MaxLength + 1.
2053   HValue* max_length = Add<HConstant>(String::kMaxLength + 1);
2054   Add<HBoundsCheck>(length, max_length);
2055   return length;
2056 }
2057
2058
2059 HValue* HGraphBuilder::BuildCreateConsString(
2060     HValue* length,
2061     HValue* left,
2062     HValue* right,
2063     HAllocationMode allocation_mode) {
2064   // Determine the string instance types.
2065   HInstruction* left_instance_type = AddLoadStringInstanceType(left);
2066   HInstruction* right_instance_type = AddLoadStringInstanceType(right);
2067
2068   // Allocate the cons string object. HAllocate does not care whether we
2069   // pass CONS_STRING_TYPE or CONS_ASCII_STRING_TYPE here, so we just use
2070   // CONS_STRING_TYPE here. Below we decide whether the cons string is
2071   // one-byte or two-byte and set the appropriate map.
2072   DCHECK(HAllocate::CompatibleInstanceTypes(CONS_STRING_TYPE,
2073                                             CONS_ASCII_STRING_TYPE));
2074   HAllocate* result = BuildAllocate(Add<HConstant>(ConsString::kSize),
2075                                     HType::String(), CONS_STRING_TYPE,
2076                                     allocation_mode);
2077
2078   // Compute intersection and difference of instance types.
2079   HValue* anded_instance_types = AddUncasted<HBitwise>(
2080       Token::BIT_AND, left_instance_type, right_instance_type);
2081   HValue* xored_instance_types = AddUncasted<HBitwise>(
2082       Token::BIT_XOR, left_instance_type, right_instance_type);
2083
2084   // We create a one-byte cons string if
2085   // 1. both strings are one-byte, or
2086   // 2. at least one of the strings is two-byte, but happens to contain only
2087   //    one-byte characters.
2088   // To do this, we check
2089   // 1. if both strings are one-byte, or if the one-byte data hint is set in
2090   //    both strings, or
2091   // 2. if one of the strings has the one-byte data hint set and the other
2092   //    string is one-byte.
2093   IfBuilder if_onebyte(this);
2094   STATIC_ASSERT(kOneByteStringTag != 0);
2095   STATIC_ASSERT(kOneByteDataHintMask != 0);
2096   if_onebyte.If<HCompareNumericAndBranch>(
2097       AddUncasted<HBitwise>(
2098           Token::BIT_AND, anded_instance_types,
2099           Add<HConstant>(static_cast<int32_t>(
2100                   kStringEncodingMask | kOneByteDataHintMask))),
2101       graph()->GetConstant0(), Token::NE);
2102   if_onebyte.Or();
2103   STATIC_ASSERT(kOneByteStringTag != 0 &&
2104                 kOneByteDataHintTag != 0 &&
2105                 kOneByteDataHintTag != kOneByteStringTag);
2106   if_onebyte.If<HCompareNumericAndBranch>(
2107       AddUncasted<HBitwise>(
2108           Token::BIT_AND, xored_instance_types,
2109           Add<HConstant>(static_cast<int32_t>(
2110                   kOneByteStringTag | kOneByteDataHintTag))),
2111       Add<HConstant>(static_cast<int32_t>(
2112               kOneByteStringTag | kOneByteDataHintTag)), Token::EQ);
2113   if_onebyte.Then();
2114   {
2115     // We can safely skip the write barrier for storing the map here.
2116     Add<HStoreNamedField>(
2117         result, HObjectAccess::ForMap(),
2118         Add<HConstant>(isolate()->factory()->cons_ascii_string_map()));
2119   }
2120   if_onebyte.Else();
2121   {
2122     // We can safely skip the write barrier for storing the map here.
2123     Add<HStoreNamedField>(
2124         result, HObjectAccess::ForMap(),
2125         Add<HConstant>(isolate()->factory()->cons_string_map()));
2126   }
2127   if_onebyte.End();
2128
2129   // Initialize the cons string fields.
2130   Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
2131                         Add<HConstant>(String::kEmptyHashField));
2132   Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
2133   Add<HStoreNamedField>(result, HObjectAccess::ForConsStringFirst(), left);
2134   Add<HStoreNamedField>(result, HObjectAccess::ForConsStringSecond(), right);
2135
2136   // Count the native string addition.
2137   AddIncrementCounter(isolate()->counters()->string_add_native());
2138
2139   return result;
2140 }
2141
2142
2143 void HGraphBuilder::BuildCopySeqStringChars(HValue* src,
2144                                             HValue* src_offset,
2145                                             String::Encoding src_encoding,
2146                                             HValue* dst,
2147                                             HValue* dst_offset,
2148                                             String::Encoding dst_encoding,
2149                                             HValue* length) {
2150   DCHECK(dst_encoding != String::ONE_BYTE_ENCODING ||
2151          src_encoding == String::ONE_BYTE_ENCODING);
2152   LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
2153   HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT);
2154   {
2155     HValue* src_index = AddUncasted<HAdd>(src_offset, index);
2156     HValue* value =
2157         AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index);
2158     HValue* dst_index = AddUncasted<HAdd>(dst_offset, index);
2159     Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value);
2160   }
2161   loop.EndBody();
2162 }
2163
2164
2165 HValue* HGraphBuilder::BuildObjectSizeAlignment(
2166     HValue* unaligned_size, int header_size) {
2167   DCHECK((header_size & kObjectAlignmentMask) == 0);
2168   HValue* size = AddUncasted<HAdd>(
2169       unaligned_size, Add<HConstant>(static_cast<int32_t>(
2170           header_size + kObjectAlignmentMask)));
2171   size->ClearFlag(HValue::kCanOverflow);
2172   return AddUncasted<HBitwise>(
2173       Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>(
2174           ~kObjectAlignmentMask)));
2175 }
2176
2177
2178 HValue* HGraphBuilder::BuildUncheckedStringAdd(
2179     HValue* left,
2180     HValue* right,
2181     HAllocationMode allocation_mode) {
2182   // Determine the string lengths.
2183   HValue* left_length = AddLoadStringLength(left);
2184   HValue* right_length = AddLoadStringLength(right);
2185
2186   // Compute the combined string length.
2187   HValue* length = BuildAddStringLengths(left_length, right_length);
2188
2189   // Do some manual constant folding here.
2190   if (left_length->IsConstant()) {
2191     HConstant* c_left_length = HConstant::cast(left_length);
2192     DCHECK_NE(0, c_left_length->Integer32Value());
2193     if (c_left_length->Integer32Value() + 1 >= ConsString::kMinLength) {
2194       // The right string contains at least one character.
2195       return BuildCreateConsString(length, left, right, allocation_mode);
2196     }
2197   } else if (right_length->IsConstant()) {
2198     HConstant* c_right_length = HConstant::cast(right_length);
2199     DCHECK_NE(0, c_right_length->Integer32Value());
2200     if (c_right_length->Integer32Value() + 1 >= ConsString::kMinLength) {
2201       // The left string contains at least one character.
2202       return BuildCreateConsString(length, left, right, allocation_mode);
2203     }
2204   }
2205
2206   // Check if we should create a cons string.
2207   IfBuilder if_createcons(this);
2208   if_createcons.If<HCompareNumericAndBranch>(
2209       length, Add<HConstant>(ConsString::kMinLength), Token::GTE);
2210   if_createcons.Then();
2211   {
2212     // Create a cons string.
2213     Push(BuildCreateConsString(length, left, right, allocation_mode));
2214   }
2215   if_createcons.Else();
2216   {
2217     // Determine the string instance types.
2218     HValue* left_instance_type = AddLoadStringInstanceType(left);
2219     HValue* right_instance_type = AddLoadStringInstanceType(right);
2220
2221     // Compute union and difference of instance types.
2222     HValue* ored_instance_types = AddUncasted<HBitwise>(
2223         Token::BIT_OR, left_instance_type, right_instance_type);
2224     HValue* xored_instance_types = AddUncasted<HBitwise>(
2225         Token::BIT_XOR, left_instance_type, right_instance_type);
2226
2227     // Check if both strings have the same encoding and both are
2228     // sequential.
2229     IfBuilder if_sameencodingandsequential(this);
2230     if_sameencodingandsequential.If<HCompareNumericAndBranch>(
2231         AddUncasted<HBitwise>(
2232             Token::BIT_AND, xored_instance_types,
2233             Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
2234         graph()->GetConstant0(), Token::EQ);
2235     if_sameencodingandsequential.And();
2236     STATIC_ASSERT(kSeqStringTag == 0);
2237     if_sameencodingandsequential.If<HCompareNumericAndBranch>(
2238         AddUncasted<HBitwise>(
2239             Token::BIT_AND, ored_instance_types,
2240             Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))),
2241         graph()->GetConstant0(), Token::EQ);
2242     if_sameencodingandsequential.Then();
2243     {
2244       HConstant* string_map =
2245           Add<HConstant>(isolate()->factory()->string_map());
2246       HConstant* ascii_string_map =
2247           Add<HConstant>(isolate()->factory()->ascii_string_map());
2248
2249       // Determine map and size depending on whether result is one-byte string.
2250       IfBuilder if_onebyte(this);
2251       STATIC_ASSERT(kOneByteStringTag != 0);
2252       if_onebyte.If<HCompareNumericAndBranch>(
2253           AddUncasted<HBitwise>(
2254               Token::BIT_AND, ored_instance_types,
2255               Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
2256           graph()->GetConstant0(), Token::NE);
2257       if_onebyte.Then();
2258       {
2259         // Allocate sequential one-byte string object.
2260         Push(length);
2261         Push(ascii_string_map);
2262       }
2263       if_onebyte.Else();
2264       {
2265         // Allocate sequential two-byte string object.
2266         HValue* size = AddUncasted<HShl>(length, graph()->GetConstant1());
2267         size->ClearFlag(HValue::kCanOverflow);
2268         size->SetFlag(HValue::kUint32);
2269         Push(size);
2270         Push(string_map);
2271       }
2272       if_onebyte.End();
2273       HValue* map = Pop();
2274
2275       // Calculate the number of bytes needed for the characters in the
2276       // string while observing object alignment.
2277       STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0);
2278       HValue* size = BuildObjectSizeAlignment(Pop(), SeqString::kHeaderSize);
2279
2280       // Allocate the string object. HAllocate does not care whether we pass
2281       // STRING_TYPE or ASCII_STRING_TYPE here, so we just use STRING_TYPE here.
2282       HAllocate* result = BuildAllocate(
2283           size, HType::String(), STRING_TYPE, allocation_mode);
2284       Add<HStoreNamedField>(result, HObjectAccess::ForMap(), map);
2285
2286       // Initialize the string fields.
2287       Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
2288                             Add<HConstant>(String::kEmptyHashField));
2289       Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
2290
2291       // Copy characters to the result string.
2292       IfBuilder if_twobyte(this);
2293       if_twobyte.If<HCompareObjectEqAndBranch>(map, string_map);
2294       if_twobyte.Then();
2295       {
2296         // Copy characters from the left string.
2297         BuildCopySeqStringChars(
2298             left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
2299             result, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
2300             left_length);
2301
2302         // Copy characters from the right string.
2303         BuildCopySeqStringChars(
2304             right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
2305             result, left_length, String::TWO_BYTE_ENCODING,
2306             right_length);
2307       }
2308       if_twobyte.Else();
2309       {
2310         // Copy characters from the left string.
2311         BuildCopySeqStringChars(
2312             left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
2313             result, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
2314             left_length);
2315
2316         // Copy characters from the right string.
2317         BuildCopySeqStringChars(
2318             right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
2319             result, left_length, String::ONE_BYTE_ENCODING,
2320             right_length);
2321       }
2322       if_twobyte.End();
2323
2324       // Count the native string addition.
2325       AddIncrementCounter(isolate()->counters()->string_add_native());
2326
2327       // Return the sequential string.
2328       Push(result);
2329     }
2330     if_sameencodingandsequential.Else();
2331     {
2332       // Fallback to the runtime to add the two strings.
2333       Add<HPushArguments>(left, right);
2334       Push(Add<HCallRuntime>(
2335             isolate()->factory()->empty_string(),
2336             Runtime::FunctionForId(Runtime::kStringAdd),
2337             2));
2338     }
2339     if_sameencodingandsequential.End();
2340   }
2341   if_createcons.End();
2342
2343   return Pop();
2344 }
2345
2346
2347 HValue* HGraphBuilder::BuildStringAdd(
2348     HValue* left,
2349     HValue* right,
2350     HAllocationMode allocation_mode) {
2351   NoObservableSideEffectsScope no_effects(this);
2352
2353   // Determine string lengths.
2354   HValue* left_length = AddLoadStringLength(left);
2355   HValue* right_length = AddLoadStringLength(right);
2356
2357   // Check if left string is empty.
2358   IfBuilder if_leftempty(this);
2359   if_leftempty.If<HCompareNumericAndBranch>(
2360       left_length, graph()->GetConstant0(), Token::EQ);
2361   if_leftempty.Then();
2362   {
2363     // Count the native string addition.
2364     AddIncrementCounter(isolate()->counters()->string_add_native());
2365
2366     // Just return the right string.
2367     Push(right);
2368   }
2369   if_leftempty.Else();
2370   {
2371     // Check if right string is empty.
2372     IfBuilder if_rightempty(this);
2373     if_rightempty.If<HCompareNumericAndBranch>(
2374         right_length, graph()->GetConstant0(), Token::EQ);
2375     if_rightempty.Then();
2376     {
2377       // Count the native string addition.
2378       AddIncrementCounter(isolate()->counters()->string_add_native());
2379
2380       // Just return the left string.
2381       Push(left);
2382     }
2383     if_rightempty.Else();
2384     {
2385       // Add the two non-empty strings.
2386       Push(BuildUncheckedStringAdd(left, right, allocation_mode));
2387     }
2388     if_rightempty.End();
2389   }
2390   if_leftempty.End();
2391
2392   return Pop();
2393 }
2394
2395
2396 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
2397     HValue* checked_object,
2398     HValue* key,
2399     HValue* val,
2400     bool is_js_array,
2401     ElementsKind elements_kind,
2402     PropertyAccessType access_type,
2403     LoadKeyedHoleMode load_mode,
2404     KeyedAccessStoreMode store_mode) {
2405   DCHECK((!IsExternalArrayElementsKind(elements_kind) &&
2406               !IsFixedTypedArrayElementsKind(elements_kind)) ||
2407          !is_js_array);
2408   // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
2409   // on a HElementsTransition instruction. The flag can also be removed if the
2410   // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
2411   // ElementsKind transitions. Finally, the dependency can be removed for stores
2412   // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
2413   // generated store code.
2414   if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
2415       (elements_kind == FAST_ELEMENTS && access_type == STORE)) {
2416     checked_object->ClearDependsOnFlag(kElementsKind);
2417   }
2418
2419   bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
2420   bool fast_elements = IsFastObjectElementsKind(elements_kind);
2421   HValue* elements = AddLoadElements(checked_object);
2422   if (access_type == STORE && (fast_elements || fast_smi_only_elements) &&
2423       store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
2424     HCheckMaps* check_cow_map = Add<HCheckMaps>(
2425         elements, isolate()->factory()->fixed_array_map());
2426     check_cow_map->ClearDependsOnFlag(kElementsKind);
2427   }
2428   HInstruction* length = NULL;
2429   if (is_js_array) {
2430     length = Add<HLoadNamedField>(
2431         checked_object->ActualValue(), checked_object,
2432         HObjectAccess::ForArrayLength(elements_kind));
2433   } else {
2434     length = AddLoadFixedArrayLength(elements);
2435   }
2436   length->set_type(HType::Smi());
2437   HValue* checked_key = NULL;
2438   if (IsExternalArrayElementsKind(elements_kind) ||
2439       IsFixedTypedArrayElementsKind(elements_kind)) {
2440     HValue* backing_store;
2441     if (IsExternalArrayElementsKind(elements_kind)) {
2442       backing_store = Add<HLoadNamedField>(
2443           elements, static_cast<HValue*>(NULL),
2444           HObjectAccess::ForExternalArrayExternalPointer());
2445     } else {
2446       backing_store = elements;
2447     }
2448     if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
2449       NoObservableSideEffectsScope no_effects(this);
2450       IfBuilder length_checker(this);
2451       length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
2452       length_checker.Then();
2453       IfBuilder negative_checker(this);
2454       HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
2455           key, graph()->GetConstant0(), Token::GTE);
2456       negative_checker.Then();
2457       HInstruction* result = AddElementAccess(
2458           backing_store, key, val, bounds_check, elements_kind, access_type);
2459       negative_checker.ElseDeopt("Negative key encountered");
2460       negative_checker.End();
2461       length_checker.End();
2462       return result;
2463     } else {
2464       DCHECK(store_mode == STANDARD_STORE);
2465       checked_key = Add<HBoundsCheck>(key, length);
2466       return AddElementAccess(
2467           backing_store, checked_key, val,
2468           checked_object, elements_kind, access_type);
2469     }
2470   }
2471   DCHECK(fast_smi_only_elements ||
2472          fast_elements ||
2473          IsFastDoubleElementsKind(elements_kind));
2474
2475   // In case val is stored into a fast smi array, assure that the value is a smi
2476   // before manipulating the backing store. Otherwise the actual store may
2477   // deopt, leaving the backing store in an invalid state.
2478   if (access_type == STORE && IsFastSmiElementsKind(elements_kind) &&
2479       !val->type().IsSmi()) {
2480     val = AddUncasted<HForceRepresentation>(val, Representation::Smi());
2481   }
2482
2483   if (IsGrowStoreMode(store_mode)) {
2484     NoObservableSideEffectsScope no_effects(this);
2485     Representation representation = HStoreKeyed::RequiredValueRepresentation(
2486         elements_kind, STORE_TO_INITIALIZED_ENTRY);
2487     val = AddUncasted<HForceRepresentation>(val, representation);
2488     elements = BuildCheckForCapacityGrow(checked_object, elements,
2489                                          elements_kind, length, key,
2490                                          is_js_array, access_type);
2491     checked_key = key;
2492   } else {
2493     checked_key = Add<HBoundsCheck>(key, length);
2494
2495     if (access_type == STORE && (fast_elements || fast_smi_only_elements)) {
2496       if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
2497         NoObservableSideEffectsScope no_effects(this);
2498         elements = BuildCopyElementsOnWrite(checked_object, elements,
2499                                             elements_kind, length);
2500       } else {
2501         HCheckMaps* check_cow_map = Add<HCheckMaps>(
2502             elements, isolate()->factory()->fixed_array_map());
2503         check_cow_map->ClearDependsOnFlag(kElementsKind);
2504       }
2505     }
2506   }
2507   return AddElementAccess(elements, checked_key, val, checked_object,
2508                           elements_kind, access_type, load_mode);
2509 }
2510
2511
2512 HValue* HGraphBuilder::BuildAllocateArrayFromLength(
2513     JSArrayBuilder* array_builder,
2514     HValue* length_argument) {
2515   if (length_argument->IsConstant() &&
2516       HConstant::cast(length_argument)->HasSmiValue()) {
2517     int array_length = HConstant::cast(length_argument)->Integer32Value();
2518     if (array_length == 0) {
2519       return array_builder->AllocateEmptyArray();
2520     } else {
2521       return array_builder->AllocateArray(length_argument,
2522                                           array_length,
2523                                           length_argument);
2524     }
2525   }
2526
2527   HValue* constant_zero = graph()->GetConstant0();
2528   HConstant* max_alloc_length =
2529       Add<HConstant>(JSObject::kInitialMaxFastElementArray);
2530   HInstruction* checked_length = Add<HBoundsCheck>(length_argument,
2531                                                    max_alloc_length);
2532   IfBuilder if_builder(this);
2533   if_builder.If<HCompareNumericAndBranch>(checked_length, constant_zero,
2534                                           Token::EQ);
2535   if_builder.Then();
2536   const int initial_capacity = JSArray::kPreallocatedArrayElements;
2537   HConstant* initial_capacity_node = Add<HConstant>(initial_capacity);
2538   Push(initial_capacity_node);  // capacity
2539   Push(constant_zero);          // length
2540   if_builder.Else();
2541   if (!(top_info()->IsStub()) &&
2542       IsFastPackedElementsKind(array_builder->kind())) {
2543     // We'll come back later with better (holey) feedback.
2544     if_builder.Deopt("Holey array despite packed elements_kind feedback");
2545   } else {
2546     Push(checked_length);         // capacity
2547     Push(checked_length);         // length
2548   }
2549   if_builder.End();
2550
2551   // Figure out total size
2552   HValue* length = Pop();
2553   HValue* capacity = Pop();
2554   return array_builder->AllocateArray(capacity, max_alloc_length, length);
2555 }
2556
2557
2558 HValue* HGraphBuilder::BuildCalculateElementsSize(ElementsKind kind,
2559                                                   HValue* capacity) {
2560   int elements_size = IsFastDoubleElementsKind(kind)
2561       ? kDoubleSize
2562       : kPointerSize;
2563
2564   HConstant* elements_size_value = Add<HConstant>(elements_size);
2565   HInstruction* mul = HMul::NewImul(zone(), context(),
2566                                     capacity->ActualValue(),
2567                                     elements_size_value);
2568   AddInstruction(mul);
2569   mul->ClearFlag(HValue::kCanOverflow);
2570
2571   STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize);
2572
2573   HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize);
2574   HValue* total_size = AddUncasted<HAdd>(mul, header_size);
2575   total_size->ClearFlag(HValue::kCanOverflow);
2576   return total_size;
2577 }
2578
2579
2580 HAllocate* HGraphBuilder::AllocateJSArrayObject(AllocationSiteMode mode) {
2581   int base_size = JSArray::kSize;
2582   if (mode == TRACK_ALLOCATION_SITE) {
2583     base_size += AllocationMemento::kSize;
2584   }
2585   HConstant* size_in_bytes = Add<HConstant>(base_size);
2586   return Add<HAllocate>(
2587       size_in_bytes, HType::JSArray(), NOT_TENURED, JS_OBJECT_TYPE);
2588 }
2589
2590
2591 HConstant* HGraphBuilder::EstablishElementsAllocationSize(
2592     ElementsKind kind,
2593     int capacity) {
2594   int base_size = IsFastDoubleElementsKind(kind)
2595       ? FixedDoubleArray::SizeFor(capacity)
2596       : FixedArray::SizeFor(capacity);
2597
2598   return Add<HConstant>(base_size);
2599 }
2600
2601
2602 HAllocate* HGraphBuilder::BuildAllocateElements(ElementsKind kind,
2603                                                 HValue* size_in_bytes) {
2604   InstanceType instance_type = IsFastDoubleElementsKind(kind)
2605       ? FIXED_DOUBLE_ARRAY_TYPE
2606       : FIXED_ARRAY_TYPE;
2607
2608   return Add<HAllocate>(size_in_bytes, HType::HeapObject(), NOT_TENURED,
2609                         instance_type);
2610 }
2611
2612
2613 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements,
2614                                                   ElementsKind kind,
2615                                                   HValue* capacity) {
2616   Factory* factory = isolate()->factory();
2617   Handle<Map> map = IsFastDoubleElementsKind(kind)
2618       ? factory->fixed_double_array_map()
2619       : factory->fixed_array_map();
2620
2621   Add<HStoreNamedField>(elements, HObjectAccess::ForMap(), Add<HConstant>(map));
2622   Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(),
2623                         capacity);
2624 }
2625
2626
2627 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader(
2628     ElementsKind kind,
2629     HValue* capacity) {
2630   // The HForceRepresentation is to prevent possible deopt on int-smi
2631   // conversion after allocation but before the new object fields are set.
2632   capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi());
2633   HValue* size_in_bytes = BuildCalculateElementsSize(kind, capacity);
2634   HValue* new_elements = BuildAllocateElements(kind, size_in_bytes);
2635   BuildInitializeElementsHeader(new_elements, kind, capacity);
2636   return new_elements;
2637 }
2638
2639
2640 void HGraphBuilder::BuildJSArrayHeader(HValue* array,
2641                                        HValue* array_map,
2642                                        HValue* elements,
2643                                        AllocationSiteMode mode,
2644                                        ElementsKind elements_kind,
2645                                        HValue* allocation_site_payload,
2646                                        HValue* length_field) {
2647   Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map);
2648
2649   HConstant* empty_fixed_array =
2650     Add<HConstant>(isolate()->factory()->empty_fixed_array());
2651
2652   Add<HStoreNamedField>(
2653       array, HObjectAccess::ForPropertiesPointer(), empty_fixed_array);
2654
2655   Add<HStoreNamedField>(
2656       array, HObjectAccess::ForElementsPointer(),
2657       elements != NULL ? elements : empty_fixed_array);
2658
2659   Add<HStoreNamedField>(
2660       array, HObjectAccess::ForArrayLength(elements_kind), length_field);
2661
2662   if (mode == TRACK_ALLOCATION_SITE) {
2663     BuildCreateAllocationMemento(
2664         array, Add<HConstant>(JSArray::kSize), allocation_site_payload);
2665   }
2666 }
2667
2668
2669 HInstruction* HGraphBuilder::AddElementAccess(
2670     HValue* elements,
2671     HValue* checked_key,
2672     HValue* val,
2673     HValue* dependency,
2674     ElementsKind elements_kind,
2675     PropertyAccessType access_type,
2676     LoadKeyedHoleMode load_mode) {
2677   if (access_type == STORE) {
2678     DCHECK(val != NULL);
2679     if (elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS ||
2680         elements_kind == UINT8_CLAMPED_ELEMENTS) {
2681       val = Add<HClampToUint8>(val);
2682     }
2683     return Add<HStoreKeyed>(elements, checked_key, val, elements_kind,
2684                             STORE_TO_INITIALIZED_ENTRY);
2685   }
2686
2687   DCHECK(access_type == LOAD);
2688   DCHECK(val == NULL);
2689   HLoadKeyed* load = Add<HLoadKeyed>(
2690       elements, checked_key, dependency, elements_kind, load_mode);
2691   if (FLAG_opt_safe_uint32_operations &&
2692       (elements_kind == EXTERNAL_UINT32_ELEMENTS ||
2693        elements_kind == UINT32_ELEMENTS)) {
2694     graph()->RecordUint32Instruction(load);
2695   }
2696   return load;
2697 }
2698
2699
2700 HLoadNamedField* HGraphBuilder::AddLoadMap(HValue* object,
2701                                            HValue* dependency) {
2702   return Add<HLoadNamedField>(object, dependency, HObjectAccess::ForMap());
2703 }
2704
2705
2706 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object,
2707                                                 HValue* dependency) {
2708   return Add<HLoadNamedField>(
2709       object, dependency, HObjectAccess::ForElementsPointer());
2710 }
2711
2712
2713 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(
2714     HValue* array,
2715     HValue* dependency) {
2716   return Add<HLoadNamedField>(
2717       array, dependency, HObjectAccess::ForFixedArrayLength());
2718 }
2719
2720
2721 HLoadNamedField* HGraphBuilder::AddLoadArrayLength(HValue* array,
2722                                                    ElementsKind kind,
2723                                                    HValue* dependency) {
2724   return Add<HLoadNamedField>(
2725       array, dependency, HObjectAccess::ForArrayLength(kind));
2726 }
2727
2728
2729 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) {
2730   HValue* half_old_capacity = AddUncasted<HShr>(old_capacity,
2731                                                 graph_->GetConstant1());
2732
2733   HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity);
2734   new_capacity->ClearFlag(HValue::kCanOverflow);
2735
2736   HValue* min_growth = Add<HConstant>(16);
2737
2738   new_capacity = AddUncasted<HAdd>(new_capacity, min_growth);
2739   new_capacity->ClearFlag(HValue::kCanOverflow);
2740
2741   return new_capacity;
2742 }
2743
2744
2745 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
2746                                                  HValue* elements,
2747                                                  ElementsKind kind,
2748                                                  ElementsKind new_kind,
2749                                                  HValue* length,
2750                                                  HValue* new_capacity) {
2751   Add<HBoundsCheck>(new_capacity, Add<HConstant>(
2752           (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >>
2753           ElementsKindToShiftSize(new_kind)));
2754
2755   HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader(
2756       new_kind, new_capacity);
2757
2758   BuildCopyElements(elements, kind, new_elements,
2759                     new_kind, length, new_capacity);
2760
2761   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
2762                         new_elements);
2763
2764   return new_elements;
2765 }
2766
2767
2768 void HGraphBuilder::BuildFillElementsWithValue(HValue* elements,
2769                                                ElementsKind elements_kind,
2770                                                HValue* from,
2771                                                HValue* to,
2772                                                HValue* value) {
2773   if (to == NULL) {
2774     to = AddLoadFixedArrayLength(elements);
2775   }
2776
2777   // Special loop unfolding case
2778   STATIC_ASSERT(JSArray::kPreallocatedArrayElements <=
2779                 kElementLoopUnrollThreshold);
2780   int initial_capacity = -1;
2781   if (from->IsInteger32Constant() && to->IsInteger32Constant()) {
2782     int constant_from = from->GetInteger32Constant();
2783     int constant_to = to->GetInteger32Constant();
2784
2785     if (constant_from == 0 && constant_to <= kElementLoopUnrollThreshold) {
2786       initial_capacity = constant_to;
2787     }
2788   }
2789
2790   // Since we're about to store a hole value, the store instruction below must
2791   // assume an elements kind that supports heap object values.
2792   if (IsFastSmiOrObjectElementsKind(elements_kind)) {
2793     elements_kind = FAST_HOLEY_ELEMENTS;
2794   }
2795
2796   if (initial_capacity >= 0) {
2797     for (int i = 0; i < initial_capacity; i++) {
2798       HInstruction* key = Add<HConstant>(i);
2799       Add<HStoreKeyed>(elements, key, value, elements_kind);
2800     }
2801   } else {
2802     // Carefully loop backwards so that the "from" remains live through the loop
2803     // rather than the to. This often corresponds to keeping length live rather
2804     // then capacity, which helps register allocation, since length is used more
2805     // other than capacity after filling with holes.
2806     LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
2807
2808     HValue* key = builder.BeginBody(to, from, Token::GT);
2809
2810     HValue* adjusted_key = AddUncasted<HSub>(key, graph()->GetConstant1());
2811     adjusted_key->ClearFlag(HValue::kCanOverflow);
2812
2813     Add<HStoreKeyed>(elements, adjusted_key, value, elements_kind);
2814
2815     builder.EndBody();
2816   }
2817 }
2818
2819
2820 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements,
2821                                               ElementsKind elements_kind,
2822                                               HValue* from,
2823                                               HValue* to) {
2824   // Fast elements kinds need to be initialized in case statements below cause a
2825   // garbage collection.
2826   Factory* factory = isolate()->factory();
2827
2828   double nan_double = FixedDoubleArray::hole_nan_as_double();
2829   HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
2830       ? Add<HConstant>(factory->the_hole_value())
2831       : Add<HConstant>(nan_double);
2832
2833   BuildFillElementsWithValue(elements, elements_kind, from, to, hole);
2834 }
2835
2836
2837 void HGraphBuilder::BuildCopyElements(HValue* from_elements,
2838                                       ElementsKind from_elements_kind,
2839                                       HValue* to_elements,
2840                                       ElementsKind to_elements_kind,
2841                                       HValue* length,
2842                                       HValue* capacity) {
2843   int constant_capacity = -1;
2844   if (capacity != NULL &&
2845       capacity->IsConstant() &&
2846       HConstant::cast(capacity)->HasInteger32Value()) {
2847     int constant_candidate = HConstant::cast(capacity)->Integer32Value();
2848     if (constant_candidate <= kElementLoopUnrollThreshold) {
2849       constant_capacity = constant_candidate;
2850     }
2851   }
2852
2853   bool pre_fill_with_holes =
2854     IsFastDoubleElementsKind(from_elements_kind) &&
2855     IsFastObjectElementsKind(to_elements_kind);
2856   if (pre_fill_with_holes) {
2857     // If the copy might trigger a GC, make sure that the FixedArray is
2858     // pre-initialized with holes to make sure that it's always in a
2859     // consistent state.
2860     BuildFillElementsWithHole(to_elements, to_elements_kind,
2861                               graph()->GetConstant0(), NULL);
2862   }
2863
2864   if (constant_capacity != -1) {
2865     // Unroll the loop for small elements kinds.
2866     for (int i = 0; i < constant_capacity; i++) {
2867       HValue* key_constant = Add<HConstant>(i);
2868       HInstruction* value = Add<HLoadKeyed>(from_elements, key_constant,
2869                                             static_cast<HValue*>(NULL),
2870                                             from_elements_kind);
2871       Add<HStoreKeyed>(to_elements, key_constant, value, to_elements_kind);
2872     }
2873   } else {
2874     if (!pre_fill_with_holes &&
2875         (capacity == NULL || !length->Equals(capacity))) {
2876       BuildFillElementsWithHole(to_elements, to_elements_kind,
2877                                 length, NULL);
2878     }
2879
2880     if (capacity == NULL) {
2881       capacity = AddLoadFixedArrayLength(to_elements);
2882     }
2883
2884     LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
2885
2886     HValue* key = builder.BeginBody(length, graph()->GetConstant0(),
2887                                     Token::GT);
2888
2889     key = AddUncasted<HSub>(key, graph()->GetConstant1());
2890     key->ClearFlag(HValue::kCanOverflow);
2891
2892     HValue* element = Add<HLoadKeyed>(from_elements, key,
2893                                       static_cast<HValue*>(NULL),
2894                                       from_elements_kind,
2895                                       ALLOW_RETURN_HOLE);
2896
2897     ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) &&
2898                          IsFastSmiElementsKind(to_elements_kind))
2899       ? FAST_HOLEY_ELEMENTS : to_elements_kind;
2900
2901     if (IsHoleyElementsKind(from_elements_kind) &&
2902         from_elements_kind != to_elements_kind) {
2903       IfBuilder if_hole(this);
2904       if_hole.If<HCompareHoleAndBranch>(element);
2905       if_hole.Then();
2906       HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind)
2907         ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double())
2908         : graph()->GetConstantHole();
2909       Add<HStoreKeyed>(to_elements, key, hole_constant, kind);
2910       if_hole.Else();
2911       HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind);
2912       store->SetFlag(HValue::kAllowUndefinedAsNaN);
2913       if_hole.End();
2914     } else {
2915       HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind);
2916       store->SetFlag(HValue::kAllowUndefinedAsNaN);
2917     }
2918
2919     builder.EndBody();
2920   }
2921
2922   Counters* counters = isolate()->counters();
2923   AddIncrementCounter(counters->inlined_copied_elements());
2924 }
2925
2926
2927 HValue* HGraphBuilder::BuildCloneShallowArrayCow(HValue* boilerplate,
2928                                                  HValue* allocation_site,
2929                                                  AllocationSiteMode mode,
2930                                                  ElementsKind kind) {
2931   HAllocate* array = AllocateJSArrayObject(mode);
2932
2933   HValue* map = AddLoadMap(boilerplate);
2934   HValue* elements = AddLoadElements(boilerplate);
2935   HValue* length = AddLoadArrayLength(boilerplate, kind);
2936
2937   BuildJSArrayHeader(array,
2938                      map,
2939                      elements,
2940                      mode,
2941                      FAST_ELEMENTS,
2942                      allocation_site,
2943                      length);
2944   return array;
2945 }
2946
2947
2948 HValue* HGraphBuilder::BuildCloneShallowArrayEmpty(HValue* boilerplate,
2949                                                    HValue* allocation_site,
2950                                                    AllocationSiteMode mode) {
2951   HAllocate* array = AllocateJSArrayObject(mode);
2952
2953   HValue* map = AddLoadMap(boilerplate);
2954
2955   BuildJSArrayHeader(array,
2956                      map,
2957                      NULL,  // set elements to empty fixed array
2958                      mode,
2959                      FAST_ELEMENTS,
2960                      allocation_site,
2961                      graph()->GetConstant0());
2962   return array;
2963 }
2964
2965
2966 HValue* HGraphBuilder::BuildCloneShallowArrayNonEmpty(HValue* boilerplate,
2967                                                       HValue* allocation_site,
2968                                                       AllocationSiteMode mode,
2969                                                       ElementsKind kind) {
2970   HValue* boilerplate_elements = AddLoadElements(boilerplate);
2971   HValue* capacity = AddLoadFixedArrayLength(boilerplate_elements);
2972
2973   // Generate size calculation code here in order to make it dominate
2974   // the JSArray allocation.
2975   HValue* elements_size = BuildCalculateElementsSize(kind, capacity);
2976
2977   // Create empty JSArray object for now, store elimination should remove
2978   // redundant initialization of elements and length fields and at the same
2979   // time the object will be fully prepared for GC if it happens during
2980   // elements allocation.
2981   HValue* result = BuildCloneShallowArrayEmpty(
2982       boilerplate, allocation_site, mode);
2983
2984   HAllocate* elements = BuildAllocateElements(kind, elements_size);
2985
2986   // This function implicitly relies on the fact that the
2987   // FastCloneShallowArrayStub is called only for literals shorter than
2988   // JSObject::kInitialMaxFastElementArray.
2989   // Can't add HBoundsCheck here because otherwise the stub will eager a frame.
2990   HConstant* size_upper_bound = EstablishElementsAllocationSize(
2991       kind, JSObject::kInitialMaxFastElementArray);
2992   elements->set_size_upper_bound(size_upper_bound);
2993
2994   Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(), elements);
2995
2996   // The allocation for the cloned array above causes register pressure on
2997   // machines with low register counts. Force a reload of the boilerplate
2998   // elements here to free up a register for the allocation to avoid unnecessary
2999   // spillage.
3000   boilerplate_elements = AddLoadElements(boilerplate);
3001   boilerplate_elements->SetFlag(HValue::kCantBeReplaced);
3002
3003   // Copy the elements array header.
3004   for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) {
3005     HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i);
3006     Add<HStoreNamedField>(elements, access,
3007         Add<HLoadNamedField>(boilerplate_elements,
3008                              static_cast<HValue*>(NULL), access));
3009   }
3010
3011   // And the result of the length
3012   HValue* length = AddLoadArrayLength(boilerplate, kind);
3013   Add<HStoreNamedField>(result, HObjectAccess::ForArrayLength(kind), length);
3014
3015   BuildCopyElements(boilerplate_elements, kind, elements,
3016                     kind, length, NULL);
3017   return result;
3018 }
3019
3020
3021 void HGraphBuilder::BuildCompareNil(
3022     HValue* value,
3023     Type* type,
3024     HIfContinuation* continuation) {
3025   IfBuilder if_nil(this);
3026   bool some_case_handled = false;
3027   bool some_case_missing = false;
3028
3029   if (type->Maybe(Type::Null())) {
3030     if (some_case_handled) if_nil.Or();
3031     if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull());
3032     some_case_handled = true;
3033   } else {
3034     some_case_missing = true;
3035   }
3036
3037   if (type->Maybe(Type::Undefined())) {
3038     if (some_case_handled) if_nil.Or();
3039     if_nil.If<HCompareObjectEqAndBranch>(value,
3040                                          graph()->GetConstantUndefined());
3041     some_case_handled = true;
3042   } else {
3043     some_case_missing = true;
3044   }
3045
3046   if (type->Maybe(Type::Undetectable())) {
3047     if (some_case_handled) if_nil.Or();
3048     if_nil.If<HIsUndetectableAndBranch>(value);
3049     some_case_handled = true;
3050   } else {
3051     some_case_missing = true;
3052   }
3053
3054   if (some_case_missing) {
3055     if_nil.Then();
3056     if_nil.Else();
3057     if (type->NumClasses() == 1) {
3058       BuildCheckHeapObject(value);
3059       // For ICs, the map checked below is a sentinel map that gets replaced by
3060       // the monomorphic map when the code is used as a template to generate a
3061       // new IC. For optimized functions, there is no sentinel map, the map
3062       // emitted below is the actual monomorphic map.
3063       Add<HCheckMaps>(value, type->Classes().Current());
3064     } else {
3065       if_nil.Deopt("Too many undetectable types");
3066     }
3067   }
3068
3069   if_nil.CaptureContinuation(continuation);
3070 }
3071
3072
3073 void HGraphBuilder::BuildCreateAllocationMemento(
3074     HValue* previous_object,
3075     HValue* previous_object_size,
3076     HValue* allocation_site) {
3077   DCHECK(allocation_site != NULL);
3078   HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>(
3079       previous_object, previous_object_size, HType::HeapObject());
3080   AddStoreMapConstant(
3081       allocation_memento, isolate()->factory()->allocation_memento_map());
3082   Add<HStoreNamedField>(
3083       allocation_memento,
3084       HObjectAccess::ForAllocationMementoSite(),
3085       allocation_site);
3086   if (FLAG_allocation_site_pretenuring) {
3087     HValue* memento_create_count = Add<HLoadNamedField>(
3088         allocation_site, static_cast<HValue*>(NULL),
3089         HObjectAccess::ForAllocationSiteOffset(
3090             AllocationSite::kPretenureCreateCountOffset));
3091     memento_create_count = AddUncasted<HAdd>(
3092         memento_create_count, graph()->GetConstant1());
3093     // This smi value is reset to zero after every gc, overflow isn't a problem
3094     // since the counter is bounded by the new space size.
3095     memento_create_count->ClearFlag(HValue::kCanOverflow);
3096     Add<HStoreNamedField>(
3097         allocation_site, HObjectAccess::ForAllocationSiteOffset(
3098             AllocationSite::kPretenureCreateCountOffset), memento_create_count);
3099   }
3100 }
3101
3102
3103 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* closure) {
3104   // Get the global context, then the native context
3105   HInstruction* context =
3106       Add<HLoadNamedField>(closure, static_cast<HValue*>(NULL),
3107                            HObjectAccess::ForFunctionContextPointer());
3108   HInstruction* global_object = Add<HLoadNamedField>(
3109       context, static_cast<HValue*>(NULL),
3110       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
3111   HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
3112       GlobalObject::kNativeContextOffset);
3113   return Add<HLoadNamedField>(
3114       global_object, static_cast<HValue*>(NULL), access);
3115 }
3116
3117
3118 HInstruction* HGraphBuilder::BuildGetNativeContext() {
3119   // Get the global context, then the native context
3120   HValue* global_object = Add<HLoadNamedField>(
3121       context(), static_cast<HValue*>(NULL),
3122       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
3123   return Add<HLoadNamedField>(
3124       global_object, static_cast<HValue*>(NULL),
3125       HObjectAccess::ForObservableJSObjectOffset(
3126           GlobalObject::kNativeContextOffset));
3127 }
3128
3129
3130 HInstruction* HGraphBuilder::BuildGetArrayFunction() {
3131   HInstruction* native_context = BuildGetNativeContext();
3132   HInstruction* index =
3133       Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX));
3134   return Add<HLoadKeyed>(
3135       native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
3136 }
3137
3138
3139 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
3140     ElementsKind kind,
3141     HValue* allocation_site_payload,
3142     HValue* constructor_function,
3143     AllocationSiteOverrideMode override_mode) :
3144         builder_(builder),
3145         kind_(kind),
3146         allocation_site_payload_(allocation_site_payload),
3147         constructor_function_(constructor_function) {
3148   DCHECK(!allocation_site_payload->IsConstant() ||
3149          HConstant::cast(allocation_site_payload)->handle(
3150              builder_->isolate())->IsAllocationSite());
3151   mode_ = override_mode == DISABLE_ALLOCATION_SITES
3152       ? DONT_TRACK_ALLOCATION_SITE
3153       : AllocationSite::GetMode(kind);
3154 }
3155
3156
3157 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
3158                                               ElementsKind kind,
3159                                               HValue* constructor_function) :
3160     builder_(builder),
3161     kind_(kind),
3162     mode_(DONT_TRACK_ALLOCATION_SITE),
3163     allocation_site_payload_(NULL),
3164     constructor_function_(constructor_function) {
3165 }
3166
3167
3168 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
3169   if (!builder()->top_info()->IsStub()) {
3170     // A constant map is fine.
3171     Handle<Map> map(builder()->isolate()->get_initial_js_array_map(kind_),
3172                     builder()->isolate());
3173     return builder()->Add<HConstant>(map);
3174   }
3175
3176   if (constructor_function_ != NULL && kind_ == GetInitialFastElementsKind()) {
3177     // No need for a context lookup if the kind_ matches the initial
3178     // map, because we can just load the map in that case.
3179     HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
3180     return builder()->Add<HLoadNamedField>(
3181         constructor_function_, static_cast<HValue*>(NULL), access);
3182   }
3183
3184   // TODO(mvstanton): we should always have a constructor function if we
3185   // are creating a stub.
3186   HInstruction* native_context = constructor_function_ != NULL
3187       ? builder()->BuildGetNativeContext(constructor_function_)
3188       : builder()->BuildGetNativeContext();
3189
3190   HInstruction* index = builder()->Add<HConstant>(
3191       static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX));
3192
3193   HInstruction* map_array = builder()->Add<HLoadKeyed>(
3194       native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
3195
3196   HInstruction* kind_index = builder()->Add<HConstant>(kind_);
3197
3198   return builder()->Add<HLoadKeyed>(
3199       map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
3200 }
3201
3202
3203 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
3204   // Find the map near the constructor function
3205   HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
3206   return builder()->Add<HLoadNamedField>(
3207       constructor_function_, static_cast<HValue*>(NULL), access);
3208 }
3209
3210
3211 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() {
3212   HConstant* capacity = builder()->Add<HConstant>(initial_capacity());
3213   return AllocateArray(capacity,
3214                        capacity,
3215                        builder()->graph()->GetConstant0());
3216 }
3217
3218
3219 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
3220     HValue* capacity,
3221     HConstant* capacity_upper_bound,
3222     HValue* length_field,
3223     FillMode fill_mode) {
3224   return AllocateArray(capacity,
3225                        capacity_upper_bound->GetInteger32Constant(),
3226                        length_field,
3227                        fill_mode);
3228 }
3229
3230
3231 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
3232     HValue* capacity,
3233     int capacity_upper_bound,
3234     HValue* length_field,
3235     FillMode fill_mode) {
3236   HConstant* elememts_size_upper_bound = capacity->IsInteger32Constant()
3237       ? HConstant::cast(capacity)
3238       : builder()->EstablishElementsAllocationSize(kind_, capacity_upper_bound);
3239
3240   HAllocate* array = AllocateArray(capacity, length_field, fill_mode);
3241   if (!elements_location_->has_size_upper_bound()) {
3242     elements_location_->set_size_upper_bound(elememts_size_upper_bound);
3243   }
3244   return array;
3245 }
3246
3247
3248 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
3249     HValue* capacity,
3250     HValue* length_field,
3251     FillMode fill_mode) {
3252   // These HForceRepresentations are because we store these as fields in the
3253   // objects we construct, and an int32-to-smi HChange could deopt. Accept
3254   // the deopt possibility now, before allocation occurs.
3255   capacity =
3256       builder()->AddUncasted<HForceRepresentation>(capacity,
3257                                                    Representation::Smi());
3258   length_field =
3259       builder()->AddUncasted<HForceRepresentation>(length_field,
3260                                                    Representation::Smi());
3261
3262   // Generate size calculation code here in order to make it dominate
3263   // the JSArray allocation.
3264   HValue* elements_size =
3265       builder()->BuildCalculateElementsSize(kind_, capacity);
3266
3267   // Allocate (dealing with failure appropriately)
3268   HAllocate* array_object = builder()->AllocateJSArrayObject(mode_);
3269
3270   // Fill in the fields: map, properties, length
3271   HValue* map;
3272   if (allocation_site_payload_ == NULL) {
3273     map = EmitInternalMapCode();
3274   } else {
3275     map = EmitMapCode();
3276   }
3277
3278   builder()->BuildJSArrayHeader(array_object,
3279                                 map,
3280                                 NULL,  // set elements to empty fixed array
3281                                 mode_,
3282                                 kind_,
3283                                 allocation_site_payload_,
3284                                 length_field);
3285
3286   // Allocate and initialize the elements
3287   elements_location_ = builder()->BuildAllocateElements(kind_, elements_size);
3288
3289   builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity);
3290
3291   // Set the elements
3292   builder()->Add<HStoreNamedField>(
3293       array_object, HObjectAccess::ForElementsPointer(), elements_location_);
3294
3295   if (fill_mode == FILL_WITH_HOLE) {
3296     builder()->BuildFillElementsWithHole(elements_location_, kind_,
3297                                          graph()->GetConstant0(), capacity);
3298   }
3299
3300   return array_object;
3301 }
3302
3303
3304 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin) {
3305   HValue* global_object = Add<HLoadNamedField>(
3306       context(), static_cast<HValue*>(NULL),
3307       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
3308   HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
3309       GlobalObject::kBuiltinsOffset);
3310   HValue* builtins = Add<HLoadNamedField>(
3311       global_object, static_cast<HValue*>(NULL), access);
3312   HObjectAccess function_access = HObjectAccess::ForObservableJSObjectOffset(
3313           JSBuiltinsObject::OffsetOfFunctionWithId(builtin));
3314   return Add<HLoadNamedField>(
3315       builtins, static_cast<HValue*>(NULL), function_access);
3316 }
3317
3318
3319 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
3320     : HGraphBuilder(info),
3321       function_state_(NULL),
3322       initial_function_state_(this, info, NORMAL_RETURN, 0),
3323       ast_context_(NULL),
3324       break_scope_(NULL),
3325       inlined_count_(0),
3326       globals_(10, info->zone()),
3327       inline_bailout_(false),
3328       osr_(new(info->zone()) HOsrBuilder(this)) {
3329   // This is not initialized in the initializer list because the
3330   // constructor for the initial state relies on function_state_ == NULL
3331   // to know it's the initial state.
3332   function_state_= &initial_function_state_;
3333   InitializeAstVisitor(info->zone());
3334   if (FLAG_hydrogen_track_positions) {
3335     SetSourcePosition(info->shared_info()->start_position());
3336   }
3337 }
3338
3339
3340 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first,
3341                                                 HBasicBlock* second,
3342                                                 BailoutId join_id) {
3343   if (first == NULL) {
3344     return second;
3345   } else if (second == NULL) {
3346     return first;
3347   } else {
3348     HBasicBlock* join_block = graph()->CreateBasicBlock();
3349     Goto(first, join_block);
3350     Goto(second, join_block);
3351     join_block->SetJoinId(join_id);
3352     return join_block;
3353   }
3354 }
3355
3356
3357 HBasicBlock* HOptimizedGraphBuilder::JoinContinue(IterationStatement* statement,
3358                                                   HBasicBlock* exit_block,
3359                                                   HBasicBlock* continue_block) {
3360   if (continue_block != NULL) {
3361     if (exit_block != NULL) Goto(exit_block, continue_block);
3362     continue_block->SetJoinId(statement->ContinueId());
3363     return continue_block;
3364   }
3365   return exit_block;
3366 }
3367
3368
3369 HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement,
3370                                                 HBasicBlock* loop_entry,
3371                                                 HBasicBlock* body_exit,
3372                                                 HBasicBlock* loop_successor,
3373                                                 HBasicBlock* break_block) {
3374   if (body_exit != NULL) Goto(body_exit, loop_entry);
3375   loop_entry->PostProcessLoopHeader(statement);
3376   if (break_block != NULL) {
3377     if (loop_successor != NULL) Goto(loop_successor, break_block);
3378     break_block->SetJoinId(statement->ExitId());
3379     return break_block;
3380   }
3381   return loop_successor;
3382 }
3383
3384
3385 // Build a new loop header block and set it as the current block.
3386 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() {
3387   HBasicBlock* loop_entry = CreateLoopHeaderBlock();
3388   Goto(loop_entry);
3389   set_current_block(loop_entry);
3390   return loop_entry;
3391 }
3392
3393
3394 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry(
3395     IterationStatement* statement) {
3396   HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement)
3397       ? osr()->BuildOsrLoopEntry(statement)
3398       : BuildLoopEntry();
3399   return loop_entry;
3400 }
3401
3402
3403 void HBasicBlock::FinishExit(HControlInstruction* instruction,
3404                              HSourcePosition position) {
3405   Finish(instruction, position);
3406   ClearEnvironment();
3407 }
3408
3409
3410 OStream& operator<<(OStream& os, const HBasicBlock& b) {
3411   return os << "B" << b.block_id();
3412 }
3413
3414
3415 HGraph::HGraph(CompilationInfo* info)
3416     : isolate_(info->isolate()),
3417       next_block_id_(0),
3418       entry_block_(NULL),
3419       blocks_(8, info->zone()),
3420       values_(16, info->zone()),
3421       phi_list_(NULL),
3422       uint32_instructions_(NULL),
3423       osr_(NULL),
3424       info_(info),
3425       zone_(info->zone()),
3426       is_recursive_(false),
3427       use_optimistic_licm_(false),
3428       depends_on_empty_array_proto_elements_(false),
3429       type_change_checksum_(0),
3430       maximum_environment_size_(0),
3431       no_side_effects_scope_count_(0),
3432       disallow_adding_new_values_(false),
3433       next_inline_id_(0),
3434       inlined_functions_(5, info->zone()) {
3435   if (info->IsStub()) {
3436     HydrogenCodeStub* stub = info->code_stub();
3437     CodeStubInterfaceDescriptor* descriptor = stub->GetInterfaceDescriptor();
3438     start_environment_ = new(zone_) HEnvironment(
3439         zone_, descriptor->GetEnvironmentParameterCount());
3440   } else {
3441     TraceInlinedFunction(info->shared_info(), HSourcePosition::Unknown());
3442     start_environment_ =
3443         new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
3444   }
3445   start_environment_->set_ast_id(BailoutId::FunctionEntry());
3446   entry_block_ = CreateBasicBlock();
3447   entry_block_->SetInitialEnvironment(start_environment_);
3448 }
3449
3450
3451 HBasicBlock* HGraph::CreateBasicBlock() {
3452   HBasicBlock* result = new(zone()) HBasicBlock(this);
3453   blocks_.Add(result, zone());
3454   return result;
3455 }
3456
3457
3458 void HGraph::FinalizeUniqueness() {
3459   DisallowHeapAllocation no_gc;
3460   DCHECK(!OptimizingCompilerThread::IsOptimizerThread(isolate()));
3461   for (int i = 0; i < blocks()->length(); ++i) {
3462     for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
3463       it.Current()->FinalizeUniqueness();
3464     }
3465   }
3466 }
3467
3468
3469 int HGraph::TraceInlinedFunction(
3470     Handle<SharedFunctionInfo> shared,
3471     HSourcePosition position) {
3472   if (!FLAG_hydrogen_track_positions) {
3473     return 0;
3474   }
3475
3476   int id = 0;
3477   for (; id < inlined_functions_.length(); id++) {
3478     if (inlined_functions_[id].shared().is_identical_to(shared)) {
3479       break;
3480     }
3481   }
3482
3483   if (id == inlined_functions_.length()) {
3484     inlined_functions_.Add(InlinedFunctionInfo(shared), zone());
3485
3486     if (!shared->script()->IsUndefined()) {
3487       Handle<Script> script(Script::cast(shared->script()));
3488       if (!script->source()->IsUndefined()) {
3489         CodeTracer::Scope tracing_scopex(isolate()->GetCodeTracer());
3490         OFStream os(tracing_scopex.file());
3491         os << "--- FUNCTION SOURCE (" << shared->DebugName()->ToCString().get()
3492            << ") id{" << info()->optimization_id() << "," << id << "} ---\n";
3493         {
3494           ConsStringIteratorOp op;
3495           StringCharacterStream stream(String::cast(script->source()),
3496                                        &op,
3497                                        shared->start_position());
3498           // fun->end_position() points to the last character in the stream. We
3499           // need to compensate by adding one to calculate the length.
3500           int source_len =
3501               shared->end_position() - shared->start_position() + 1;
3502           for (int i = 0; i < source_len; i++) {
3503             if (stream.HasMore()) {
3504               os << AsUC16(stream.GetNext());
3505             }
3506           }
3507         }
3508
3509         os << "\n--- END ---\n";
3510       }
3511     }
3512   }
3513
3514   int inline_id = next_inline_id_++;
3515
3516   if (inline_id != 0) {
3517     CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
3518     OFStream os(tracing_scope.file());
3519     os << "INLINE (" << shared->DebugName()->ToCString().get() << ") id{"
3520        << info()->optimization_id() << "," << id << "} AS " << inline_id
3521        << " AT " << position << endl;
3522   }
3523
3524   return inline_id;
3525 }
3526
3527
3528 int HGraph::SourcePositionToScriptPosition(HSourcePosition pos) {
3529   if (!FLAG_hydrogen_track_positions || pos.IsUnknown()) {
3530     return pos.raw();
3531   }
3532
3533   return inlined_functions_[pos.inlining_id()].start_position() +
3534       pos.position();
3535 }
3536
3537
3538 // Block ordering was implemented with two mutually recursive methods,
3539 // HGraph::Postorder and HGraph::PostorderLoopBlocks.
3540 // The recursion could lead to stack overflow so the algorithm has been
3541 // implemented iteratively.
3542 // At a high level the algorithm looks like this:
3543 //
3544 // Postorder(block, loop_header) : {
3545 //   if (block has already been visited or is of another loop) return;
3546 //   mark block as visited;
3547 //   if (block is a loop header) {
3548 //     VisitLoopMembers(block, loop_header);
3549 //     VisitSuccessorsOfLoopHeader(block);
3550 //   } else {
3551 //     VisitSuccessors(block)
3552 //   }
3553 //   put block in result list;
3554 // }
3555 //
3556 // VisitLoopMembers(block, outer_loop_header) {
3557 //   foreach (block b in block loop members) {
3558 //     VisitSuccessorsOfLoopMember(b, outer_loop_header);
3559 //     if (b is loop header) VisitLoopMembers(b);
3560 //   }
3561 // }
3562 //
3563 // VisitSuccessorsOfLoopMember(block, outer_loop_header) {
3564 //   foreach (block b in block successors) Postorder(b, outer_loop_header)
3565 // }
3566 //
3567 // VisitSuccessorsOfLoopHeader(block) {
3568 //   foreach (block b in block successors) Postorder(b, block)
3569 // }
3570 //
3571 // VisitSuccessors(block, loop_header) {
3572 //   foreach (block b in block successors) Postorder(b, loop_header)
3573 // }
3574 //
3575 // The ordering is started calling Postorder(entry, NULL).
3576 //
3577 // Each instance of PostorderProcessor represents the "stack frame" of the
3578 // recursion, and particularly keeps the state of the loop (iteration) of the
3579 // "Visit..." function it represents.
3580 // To recycle memory we keep all the frames in a double linked list but
3581 // this means that we cannot use constructors to initialize the frames.
3582 //
3583 class PostorderProcessor : public ZoneObject {
3584  public:
3585   // Back link (towards the stack bottom).
3586   PostorderProcessor* parent() {return father_; }
3587   // Forward link (towards the stack top).
3588   PostorderProcessor* child() {return child_; }
3589   HBasicBlock* block() { return block_; }
3590   HLoopInformation* loop() { return loop_; }
3591   HBasicBlock* loop_header() { return loop_header_; }
3592
3593   static PostorderProcessor* CreateEntryProcessor(Zone* zone,
3594                                                   HBasicBlock* block) {
3595     PostorderProcessor* result = new(zone) PostorderProcessor(NULL);
3596     return result->SetupSuccessors(zone, block, NULL);
3597   }
3598
3599   PostorderProcessor* PerformStep(Zone* zone,
3600                                   ZoneList<HBasicBlock*>* order) {
3601     PostorderProcessor* next =
3602         PerformNonBacktrackingStep(zone, order);
3603     if (next != NULL) {
3604       return next;
3605     } else {
3606       return Backtrack(zone, order);
3607     }
3608   }
3609
3610  private:
3611   explicit PostorderProcessor(PostorderProcessor* father)
3612       : father_(father), child_(NULL), successor_iterator(NULL) { }
3613
3614   // Each enum value states the cycle whose state is kept by this instance.
3615   enum LoopKind {
3616     NONE,
3617     SUCCESSORS,
3618     SUCCESSORS_OF_LOOP_HEADER,
3619     LOOP_MEMBERS,
3620     SUCCESSORS_OF_LOOP_MEMBER
3621   };
3622
3623   // Each "Setup..." method is like a constructor for a cycle state.
3624   PostorderProcessor* SetupSuccessors(Zone* zone,
3625                                       HBasicBlock* block,
3626                                       HBasicBlock* loop_header) {
3627     if (block == NULL || block->IsOrdered() ||
3628         block->parent_loop_header() != loop_header) {
3629       kind_ = NONE;
3630       block_ = NULL;
3631       loop_ = NULL;
3632       loop_header_ = NULL;
3633       return this;
3634     } else {
3635       block_ = block;
3636       loop_ = NULL;
3637       block->MarkAsOrdered();
3638
3639       if (block->IsLoopHeader()) {
3640         kind_ = SUCCESSORS_OF_LOOP_HEADER;
3641         loop_header_ = block;
3642         InitializeSuccessors();
3643         PostorderProcessor* result = Push(zone);
3644         return result->SetupLoopMembers(zone, block, block->loop_information(),
3645                                         loop_header);
3646       } else {
3647         DCHECK(block->IsFinished());
3648         kind_ = SUCCESSORS;
3649         loop_header_ = loop_header;
3650         InitializeSuccessors();
3651         return this;
3652       }
3653     }
3654   }
3655
3656   PostorderProcessor* SetupLoopMembers(Zone* zone,
3657                                        HBasicBlock* block,
3658                                        HLoopInformation* loop,
3659                                        HBasicBlock* loop_header) {
3660     kind_ = LOOP_MEMBERS;
3661     block_ = block;
3662     loop_ = loop;
3663     loop_header_ = loop_header;
3664     InitializeLoopMembers();
3665     return this;
3666   }
3667
3668   PostorderProcessor* SetupSuccessorsOfLoopMember(
3669       HBasicBlock* block,
3670       HLoopInformation* loop,
3671       HBasicBlock* loop_header) {
3672     kind_ = SUCCESSORS_OF_LOOP_MEMBER;
3673     block_ = block;
3674     loop_ = loop;
3675     loop_header_ = loop_header;
3676     InitializeSuccessors();
3677     return this;
3678   }
3679
3680   // This method "allocates" a new stack frame.
3681   PostorderProcessor* Push(Zone* zone) {
3682     if (child_ == NULL) {
3683       child_ = new(zone) PostorderProcessor(this);
3684     }
3685     return child_;
3686   }
3687
3688   void ClosePostorder(ZoneList<HBasicBlock*>* order, Zone* zone) {
3689     DCHECK(block_->end()->FirstSuccessor() == NULL ||
3690            order->Contains(block_->end()->FirstSuccessor()) ||
3691            block_->end()->FirstSuccessor()->IsLoopHeader());
3692     DCHECK(block_->end()->SecondSuccessor() == NULL ||
3693            order->Contains(block_->end()->SecondSuccessor()) ||
3694            block_->end()->SecondSuccessor()->IsLoopHeader());
3695     order->Add(block_, zone);
3696   }
3697
3698   // This method is the basic block to walk up the stack.
3699   PostorderProcessor* Pop(Zone* zone,
3700                           ZoneList<HBasicBlock*>* order) {
3701     switch (kind_) {
3702       case SUCCESSORS:
3703       case SUCCESSORS_OF_LOOP_HEADER:
3704         ClosePostorder(order, zone);
3705         return father_;
3706       case LOOP_MEMBERS:
3707         return father_;
3708       case SUCCESSORS_OF_LOOP_MEMBER:
3709         if (block()->IsLoopHeader() && block() != loop_->loop_header()) {
3710           // In this case we need to perform a LOOP_MEMBERS cycle so we
3711           // initialize it and return this instead of father.
3712           return SetupLoopMembers(zone, block(),
3713                                   block()->loop_information(), loop_header_);
3714         } else {
3715           return father_;
3716         }
3717       case NONE:
3718         return father_;
3719     }
3720     UNREACHABLE();
3721     return NULL;
3722   }
3723
3724   // Walks up the stack.
3725   PostorderProcessor* Backtrack(Zone* zone,
3726                                 ZoneList<HBasicBlock*>* order) {
3727     PostorderProcessor* parent = Pop(zone, order);
3728     while (parent != NULL) {
3729       PostorderProcessor* next =
3730           parent->PerformNonBacktrackingStep(zone, order);
3731       if (next != NULL) {
3732         return next;
3733       } else {
3734         parent = parent->Pop(zone, order);
3735       }
3736     }
3737     return NULL;
3738   }
3739
3740   PostorderProcessor* PerformNonBacktrackingStep(
3741       Zone* zone,
3742       ZoneList<HBasicBlock*>* order) {
3743     HBasicBlock* next_block;
3744     switch (kind_) {
3745       case SUCCESSORS:
3746         next_block = AdvanceSuccessors();
3747         if (next_block != NULL) {
3748           PostorderProcessor* result = Push(zone);
3749           return result->SetupSuccessors(zone, next_block, loop_header_);
3750         }
3751         break;
3752       case SUCCESSORS_OF_LOOP_HEADER:
3753         next_block = AdvanceSuccessors();
3754         if (next_block != NULL) {
3755           PostorderProcessor* result = Push(zone);
3756           return result->SetupSuccessors(zone, next_block, block());
3757         }
3758         break;
3759       case LOOP_MEMBERS:
3760         next_block = AdvanceLoopMembers();
3761         if (next_block != NULL) {
3762           PostorderProcessor* result = Push(zone);
3763           return result->SetupSuccessorsOfLoopMember(next_block,
3764                                                      loop_, loop_header_);
3765         }
3766         break;
3767       case SUCCESSORS_OF_LOOP_MEMBER:
3768         next_block = AdvanceSuccessors();
3769         if (next_block != NULL) {
3770           PostorderProcessor* result = Push(zone);
3771           return result->SetupSuccessors(zone, next_block, loop_header_);
3772         }
3773         break;
3774       case NONE:
3775         return NULL;
3776     }
3777     return NULL;
3778   }
3779
3780   // The following two methods implement a "foreach b in successors" cycle.
3781   void InitializeSuccessors() {
3782     loop_index = 0;
3783     loop_length = 0;
3784     successor_iterator = HSuccessorIterator(block_->end());
3785   }
3786
3787   HBasicBlock* AdvanceSuccessors() {
3788     if (!successor_iterator.Done()) {
3789       HBasicBlock* result = successor_iterator.Current();
3790       successor_iterator.Advance();
3791       return result;
3792     }
3793     return NULL;
3794   }
3795
3796   // The following two methods implement a "foreach b in loop members" cycle.
3797   void InitializeLoopMembers() {
3798     loop_index = 0;
3799     loop_length = loop_->blocks()->length();
3800   }
3801
3802   HBasicBlock* AdvanceLoopMembers() {
3803     if (loop_index < loop_length) {
3804       HBasicBlock* result = loop_->blocks()->at(loop_index);
3805       loop_index++;
3806       return result;
3807     } else {
3808       return NULL;
3809     }
3810   }
3811
3812   LoopKind kind_;
3813   PostorderProcessor* father_;
3814   PostorderProcessor* child_;
3815   HLoopInformation* loop_;
3816   HBasicBlock* block_;
3817   HBasicBlock* loop_header_;
3818   int loop_index;
3819   int loop_length;
3820   HSuccessorIterator successor_iterator;
3821 };
3822
3823
3824 void HGraph::OrderBlocks() {
3825   CompilationPhase phase("H_Block ordering", info());
3826
3827 #ifdef DEBUG
3828   // Initially the blocks must not be ordered.
3829   for (int i = 0; i < blocks_.length(); ++i) {
3830     DCHECK(!blocks_[i]->IsOrdered());
3831   }
3832 #endif
3833
3834   PostorderProcessor* postorder =
3835       PostorderProcessor::CreateEntryProcessor(zone(), blocks_[0]);
3836   blocks_.Rewind(0);
3837   while (postorder) {
3838     postorder = postorder->PerformStep(zone(), &blocks_);
3839   }
3840
3841 #ifdef DEBUG
3842   // Now all blocks must be marked as ordered.
3843   for (int i = 0; i < blocks_.length(); ++i) {
3844     DCHECK(blocks_[i]->IsOrdered());
3845   }
3846 #endif
3847
3848   // Reverse block list and assign block IDs.
3849   for (int i = 0, j = blocks_.length(); --j >= i; ++i) {
3850     HBasicBlock* bi = blocks_[i];
3851     HBasicBlock* bj = blocks_[j];
3852     bi->set_block_id(j);
3853     bj->set_block_id(i);
3854     blocks_[i] = bj;
3855     blocks_[j] = bi;
3856   }
3857 }
3858
3859
3860 void HGraph::AssignDominators() {
3861   HPhase phase("H_Assign dominators", this);
3862   for (int i = 0; i < blocks_.length(); ++i) {
3863     HBasicBlock* block = blocks_[i];
3864     if (block->IsLoopHeader()) {
3865       // Only the first predecessor of a loop header is from outside the loop.
3866       // All others are back edges, and thus cannot dominate the loop header.
3867       block->AssignCommonDominator(block->predecessors()->first());
3868       block->AssignLoopSuccessorDominators();
3869     } else {
3870       for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) {
3871         blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
3872       }
3873     }
3874   }
3875 }
3876
3877
3878 bool HGraph::CheckArgumentsPhiUses() {
3879   int block_count = blocks_.length();
3880   for (int i = 0; i < block_count; ++i) {
3881     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
3882       HPhi* phi = blocks_[i]->phis()->at(j);
3883       // We don't support phi uses of arguments for now.
3884       if (phi->CheckFlag(HValue::kIsArguments)) return false;
3885     }
3886   }
3887   return true;
3888 }
3889
3890
3891 bool HGraph::CheckConstPhiUses() {
3892   int block_count = blocks_.length();
3893   for (int i = 0; i < block_count; ++i) {
3894     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
3895       HPhi* phi = blocks_[i]->phis()->at(j);
3896       // Check for the hole value (from an uninitialized const).
3897       for (int k = 0; k < phi->OperandCount(); k++) {
3898         if (phi->OperandAt(k) == GetConstantHole()) return false;
3899       }
3900     }
3901   }
3902   return true;
3903 }
3904
3905
3906 void HGraph::CollectPhis() {
3907   int block_count = blocks_.length();
3908   phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone());
3909   for (int i = 0; i < block_count; ++i) {
3910     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
3911       HPhi* phi = blocks_[i]->phis()->at(j);
3912       phi_list_->Add(phi, zone());
3913     }
3914   }
3915 }
3916
3917
3918 // Implementation of utility class to encapsulate the translation state for
3919 // a (possibly inlined) function.
3920 FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
3921                              CompilationInfo* info,
3922                              InliningKind inlining_kind,
3923                              int inlining_id)
3924     : owner_(owner),
3925       compilation_info_(info),
3926       call_context_(NULL),
3927       inlining_kind_(inlining_kind),
3928       function_return_(NULL),
3929       test_context_(NULL),
3930       entry_(NULL),
3931       arguments_object_(NULL),
3932       arguments_elements_(NULL),
3933       inlining_id_(inlining_id),
3934       outer_source_position_(HSourcePosition::Unknown()),
3935       outer_(owner->function_state()) {
3936   if (outer_ != NULL) {
3937     // State for an inline function.
3938     if (owner->ast_context()->IsTest()) {
3939       HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
3940       HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
3941       if_true->MarkAsInlineReturnTarget(owner->current_block());
3942       if_false->MarkAsInlineReturnTarget(owner->current_block());
3943       TestContext* outer_test_context = TestContext::cast(owner->ast_context());
3944       Expression* cond = outer_test_context->condition();
3945       // The AstContext constructor pushed on the context stack.  This newed
3946       // instance is the reason that AstContext can't be BASE_EMBEDDED.
3947       test_context_ = new TestContext(owner, cond, if_true, if_false);
3948     } else {
3949       function_return_ = owner->graph()->CreateBasicBlock();
3950       function_return()->MarkAsInlineReturnTarget(owner->current_block());
3951     }
3952     // Set this after possibly allocating a new TestContext above.
3953     call_context_ = owner->ast_context();
3954   }
3955
3956   // Push on the state stack.
3957   owner->set_function_state(this);
3958
3959   if (FLAG_hydrogen_track_positions) {
3960     outer_source_position_ = owner->source_position();
3961     owner->EnterInlinedSource(
3962       info->shared_info()->start_position(),
3963       inlining_id);
3964     owner->SetSourcePosition(info->shared_info()->start_position());
3965   }
3966 }
3967
3968
3969 FunctionState::~FunctionState() {
3970   delete test_context_;
3971   owner_->set_function_state(outer_);
3972
3973   if (FLAG_hydrogen_track_positions) {
3974     owner_->set_source_position(outer_source_position_);
3975     owner_->EnterInlinedSource(
3976       outer_->compilation_info()->shared_info()->start_position(),
3977       outer_->inlining_id());
3978   }
3979 }
3980
3981
3982 // Implementation of utility classes to represent an expression's context in
3983 // the AST.
3984 AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind)
3985     : owner_(owner),
3986       kind_(kind),
3987       outer_(owner->ast_context()),
3988       for_typeof_(false) {
3989   owner->set_ast_context(this);  // Push.
3990 #ifdef DEBUG
3991   DCHECK(owner->environment()->frame_type() == JS_FUNCTION);
3992   original_length_ = owner->environment()->length();
3993 #endif
3994 }
3995
3996
3997 AstContext::~AstContext() {
3998   owner_->set_ast_context(outer_);  // Pop.
3999 }
4000
4001
4002 EffectContext::~EffectContext() {
4003   DCHECK(owner()->HasStackOverflow() ||
4004          owner()->current_block() == NULL ||
4005          (owner()->environment()->length() == original_length_ &&
4006           owner()->environment()->frame_type() == JS_FUNCTION));
4007 }
4008
4009
4010 ValueContext::~ValueContext() {
4011   DCHECK(owner()->HasStackOverflow() ||
4012          owner()->current_block() == NULL ||
4013          (owner()->environment()->length() == original_length_ + 1 &&
4014           owner()->environment()->frame_type() == JS_FUNCTION));
4015 }
4016
4017
4018 void EffectContext::ReturnValue(HValue* value) {
4019   // The value is simply ignored.
4020 }
4021
4022
4023 void ValueContext::ReturnValue(HValue* value) {
4024   // The value is tracked in the bailout environment, and communicated
4025   // through the environment as the result of the expression.
4026   if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) {
4027     owner()->Bailout(kBadValueContextForArgumentsValue);
4028   }
4029   owner()->Push(value);
4030 }
4031
4032
4033 void TestContext::ReturnValue(HValue* value) {
4034   BuildBranch(value);
4035 }
4036
4037
4038 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
4039   DCHECK(!instr->IsControlInstruction());
4040   owner()->AddInstruction(instr);
4041   if (instr->HasObservableSideEffects()) {
4042     owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
4043   }
4044 }
4045
4046
4047 void EffectContext::ReturnControl(HControlInstruction* instr,
4048                                   BailoutId ast_id) {
4049   DCHECK(!instr->HasObservableSideEffects());
4050   HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
4051   HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
4052   instr->SetSuccessorAt(0, empty_true);
4053   instr->SetSuccessorAt(1, empty_false);
4054   owner()->FinishCurrentBlock(instr);
4055   HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id);
4056   owner()->set_current_block(join);
4057 }
4058
4059
4060 void EffectContext::ReturnContinuation(HIfContinuation* continuation,
4061                                        BailoutId ast_id) {
4062   HBasicBlock* true_branch = NULL;
4063   HBasicBlock* false_branch = NULL;
4064   continuation->Continue(&true_branch, &false_branch);
4065   if (!continuation->IsTrueReachable()) {
4066     owner()->set_current_block(false_branch);
4067   } else if (!continuation->IsFalseReachable()) {
4068     owner()->set_current_block(true_branch);
4069   } else {
4070     HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id);
4071     owner()->set_current_block(join);
4072   }
4073 }
4074
4075
4076 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
4077   DCHECK(!instr->IsControlInstruction());
4078   if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
4079     return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
4080   }
4081   owner()->AddInstruction(instr);
4082   owner()->Push(instr);
4083   if (instr->HasObservableSideEffects()) {
4084     owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
4085   }
4086 }
4087
4088
4089 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
4090   DCHECK(!instr->HasObservableSideEffects());
4091   if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
4092     return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
4093   }
4094   HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
4095   HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
4096   instr->SetSuccessorAt(0, materialize_true);
4097   instr->SetSuccessorAt(1, materialize_false);
4098   owner()->FinishCurrentBlock(instr);
4099   owner()->set_current_block(materialize_true);
4100   owner()->Push(owner()->graph()->GetConstantTrue());
4101   owner()->set_current_block(materialize_false);
4102   owner()->Push(owner()->graph()->GetConstantFalse());
4103   HBasicBlock* join =
4104     owner()->CreateJoin(materialize_true, materialize_false, ast_id);
4105   owner()->set_current_block(join);
4106 }
4107
4108
4109 void ValueContext::ReturnContinuation(HIfContinuation* continuation,
4110                                       BailoutId ast_id) {
4111   HBasicBlock* materialize_true = NULL;
4112   HBasicBlock* materialize_false = NULL;
4113   continuation->Continue(&materialize_true, &materialize_false);
4114   if (continuation->IsTrueReachable()) {
4115     owner()->set_current_block(materialize_true);
4116     owner()->Push(owner()->graph()->GetConstantTrue());
4117     owner()->set_current_block(materialize_true);
4118   }
4119   if (continuation->IsFalseReachable()) {
4120     owner()->set_current_block(materialize_false);
4121     owner()->Push(owner()->graph()->GetConstantFalse());
4122     owner()->set_current_block(materialize_false);
4123   }
4124   if (continuation->TrueAndFalseReachable()) {
4125     HBasicBlock* join =
4126         owner()->CreateJoin(materialize_true, materialize_false, ast_id);
4127     owner()->set_current_block(join);
4128   }
4129 }
4130
4131
4132 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
4133   DCHECK(!instr->IsControlInstruction());
4134   HOptimizedGraphBuilder* builder = owner();
4135   builder->AddInstruction(instr);
4136   // We expect a simulate after every expression with side effects, though
4137   // this one isn't actually needed (and wouldn't work if it were targeted).
4138   if (instr->HasObservableSideEffects()) {
4139     builder->Push(instr);
4140     builder->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
4141     builder->Pop();
4142   }
4143   BuildBranch(instr);
4144 }
4145
4146
4147 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
4148   DCHECK(!instr->HasObservableSideEffects());
4149   HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
4150   HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
4151   instr->SetSuccessorAt(0, empty_true);
4152   instr->SetSuccessorAt(1, empty_false);
4153   owner()->FinishCurrentBlock(instr);
4154   owner()->Goto(empty_true, if_true(), owner()->function_state());
4155   owner()->Goto(empty_false, if_false(), owner()->function_state());
4156   owner()->set_current_block(NULL);
4157 }
4158
4159
4160 void TestContext::ReturnContinuation(HIfContinuation* continuation,
4161                                      BailoutId ast_id) {
4162   HBasicBlock* true_branch = NULL;
4163   HBasicBlock* false_branch = NULL;
4164   continuation->Continue(&true_branch, &false_branch);
4165   if (continuation->IsTrueReachable()) {
4166     owner()->Goto(true_branch, if_true(), owner()->function_state());
4167   }
4168   if (continuation->IsFalseReachable()) {
4169     owner()->Goto(false_branch, if_false(), owner()->function_state());
4170   }
4171   owner()->set_current_block(NULL);
4172 }
4173
4174
4175 void TestContext::BuildBranch(HValue* value) {
4176   // We expect the graph to be in edge-split form: there is no edge that
4177   // connects a branch node to a join node.  We conservatively ensure that
4178   // property by always adding an empty block on the outgoing edges of this
4179   // branch.
4180   HOptimizedGraphBuilder* builder = owner();
4181   if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
4182     builder->Bailout(kArgumentsObjectValueInATestContext);
4183   }
4184   ToBooleanStub::Types expected(condition()->to_boolean_types());
4185   ReturnControl(owner()->New<HBranch>(value, expected), BailoutId::None());
4186 }
4187
4188
4189 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts.
4190 #define CHECK_BAILOUT(call)                     \
4191   do {                                          \
4192     call;                                       \
4193     if (HasStackOverflow()) return;             \
4194   } while (false)
4195
4196
4197 #define CHECK_ALIVE(call)                                       \
4198   do {                                                          \
4199     call;                                                       \
4200     if (HasStackOverflow() || current_block() == NULL) return;  \
4201   } while (false)
4202
4203
4204 #define CHECK_ALIVE_OR_RETURN(call, value)                            \
4205   do {                                                                \
4206     call;                                                             \
4207     if (HasStackOverflow() || current_block() == NULL) return value;  \
4208   } while (false)
4209
4210
4211 void HOptimizedGraphBuilder::Bailout(BailoutReason reason) {
4212   current_info()->set_bailout_reason(reason);
4213   SetStackOverflow();
4214 }
4215
4216
4217 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) {
4218   EffectContext for_effect(this);
4219   Visit(expr);
4220 }
4221
4222
4223 void HOptimizedGraphBuilder::VisitForValue(Expression* expr,
4224                                            ArgumentsAllowedFlag flag) {
4225   ValueContext for_value(this, flag);
4226   Visit(expr);
4227 }
4228
4229
4230 void HOptimizedGraphBuilder::VisitForTypeOf(Expression* expr) {
4231   ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
4232   for_value.set_for_typeof(true);
4233   Visit(expr);
4234 }
4235
4236
4237 void HOptimizedGraphBuilder::VisitForControl(Expression* expr,
4238                                              HBasicBlock* true_block,
4239                                              HBasicBlock* false_block) {
4240   TestContext for_test(this, expr, true_block, false_block);
4241   Visit(expr);
4242 }
4243
4244
4245 void HOptimizedGraphBuilder::VisitExpressions(
4246     ZoneList<Expression*>* exprs) {
4247   for (int i = 0; i < exprs->length(); ++i) {
4248     CHECK_ALIVE(VisitForValue(exprs->at(i)));
4249   }
4250 }
4251
4252
4253 bool HOptimizedGraphBuilder::BuildGraph() {
4254   if (current_info()->function()->is_generator()) {
4255     Bailout(kFunctionIsAGenerator);
4256     return false;
4257   }
4258   Scope* scope = current_info()->scope();
4259   if (scope->HasIllegalRedeclaration()) {
4260     Bailout(kFunctionWithIllegalRedeclaration);
4261     return false;
4262   }
4263   if (scope->calls_eval()) {
4264     Bailout(kFunctionCallsEval);
4265     return false;
4266   }
4267   SetUpScope(scope);
4268
4269   // Add an edge to the body entry.  This is warty: the graph's start
4270   // environment will be used by the Lithium translation as the initial
4271   // environment on graph entry, but it has now been mutated by the
4272   // Hydrogen translation of the instructions in the start block.  This
4273   // environment uses values which have not been defined yet.  These
4274   // Hydrogen instructions will then be replayed by the Lithium
4275   // translation, so they cannot have an environment effect.  The edge to
4276   // the body's entry block (along with some special logic for the start
4277   // block in HInstruction::InsertAfter) seals the start block from
4278   // getting unwanted instructions inserted.
4279   //
4280   // TODO(kmillikin): Fix this.  Stop mutating the initial environment.
4281   // Make the Hydrogen instructions in the initial block into Hydrogen
4282   // values (but not instructions), present in the initial environment and
4283   // not replayed by the Lithium translation.
4284   HEnvironment* initial_env = environment()->CopyWithoutHistory();
4285   HBasicBlock* body_entry = CreateBasicBlock(initial_env);
4286   Goto(body_entry);
4287   body_entry->SetJoinId(BailoutId::FunctionEntry());
4288   set_current_block(body_entry);
4289
4290   // Handle implicit declaration of the function name in named function
4291   // expressions before other declarations.
4292   if (scope->is_function_scope() && scope->function() != NULL) {
4293     VisitVariableDeclaration(scope->function());
4294   }
4295   VisitDeclarations(scope->declarations());
4296   Add<HSimulate>(BailoutId::Declarations());
4297
4298   Add<HStackCheck>(HStackCheck::kFunctionEntry);
4299
4300   VisitStatements(current_info()->function()->body());
4301   if (HasStackOverflow()) return false;
4302
4303   if (current_block() != NULL) {
4304     Add<HReturn>(graph()->GetConstantUndefined());
4305     set_current_block(NULL);
4306   }
4307
4308   // If the checksum of the number of type info changes is the same as the
4309   // last time this function was compiled, then this recompile is likely not
4310   // due to missing/inadequate type feedback, but rather too aggressive
4311   // optimization. Disable optimistic LICM in that case.
4312   Handle<Code> unoptimized_code(current_info()->shared_info()->code());
4313   DCHECK(unoptimized_code->kind() == Code::FUNCTION);
4314   Handle<TypeFeedbackInfo> type_info(
4315       TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
4316   int checksum = type_info->own_type_change_checksum();
4317   int composite_checksum = graph()->update_type_change_checksum(checksum);
4318   graph()->set_use_optimistic_licm(
4319       !type_info->matches_inlined_type_change_checksum(composite_checksum));
4320   type_info->set_inlined_type_change_checksum(composite_checksum);
4321
4322   // Perform any necessary OSR-specific cleanups or changes to the graph.
4323   osr()->FinishGraph();
4324
4325   return true;
4326 }
4327
4328
4329 bool HGraph::Optimize(BailoutReason* bailout_reason) {
4330   OrderBlocks();
4331   AssignDominators();
4332
4333   // We need to create a HConstant "zero" now so that GVN will fold every
4334   // zero-valued constant in the graph together.
4335   // The constant is needed to make idef-based bounds check work: the pass
4336   // evaluates relations with "zero" and that zero cannot be created after GVN.
4337   GetConstant0();
4338
4339 #ifdef DEBUG
4340   // Do a full verify after building the graph and computing dominators.
4341   Verify(true);
4342 #endif
4343
4344   if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) {
4345     Run<HEnvironmentLivenessAnalysisPhase>();
4346   }
4347
4348   if (!CheckConstPhiUses()) {
4349     *bailout_reason = kUnsupportedPhiUseOfConstVariable;
4350     return false;
4351   }
4352   Run<HRedundantPhiEliminationPhase>();
4353   if (!CheckArgumentsPhiUses()) {
4354     *bailout_reason = kUnsupportedPhiUseOfArguments;
4355     return false;
4356   }
4357
4358   // Find and mark unreachable code to simplify optimizations, especially gvn,
4359   // where unreachable code could unnecessarily defeat LICM.
4360   Run<HMarkUnreachableBlocksPhase>();
4361
4362   if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
4363   if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
4364
4365   if (FLAG_load_elimination) Run<HLoadEliminationPhase>();
4366
4367   CollectPhis();
4368
4369   if (has_osr()) osr()->FinishOsrValues();
4370
4371   Run<HInferRepresentationPhase>();
4372
4373   // Remove HSimulate instructions that have turned out not to be needed
4374   // after all by folding them into the following HSimulate.
4375   // This must happen after inferring representations.
4376   Run<HMergeRemovableSimulatesPhase>();
4377
4378   Run<HMarkDeoptimizeOnUndefinedPhase>();
4379   Run<HRepresentationChangesPhase>();
4380
4381   Run<HInferTypesPhase>();
4382
4383   // Must be performed before canonicalization to ensure that Canonicalize
4384   // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with
4385   // zero.
4386   if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>();
4387
4388   if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>();
4389
4390   if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>();
4391
4392   if (FLAG_check_elimination) Run<HCheckEliminationPhase>();
4393
4394   if (FLAG_store_elimination) Run<HStoreEliminationPhase>();
4395
4396   Run<HRangeAnalysisPhase>();
4397
4398   Run<HComputeChangeUndefinedToNaN>();
4399
4400   // Eliminate redundant stack checks on backwards branches.
4401   Run<HStackCheckEliminationPhase>();
4402
4403   if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>();
4404   if (FLAG_array_bounds_checks_hoisting) Run<HBoundsCheckHoistingPhase>();
4405   if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
4406   if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
4407
4408   RestoreActualValues();
4409
4410   // Find unreachable code a second time, GVN and other optimizations may have
4411   // made blocks unreachable that were previously reachable.
4412   Run<HMarkUnreachableBlocksPhase>();
4413
4414   return true;
4415 }
4416
4417
4418 void HGraph::RestoreActualValues() {
4419   HPhase phase("H_Restore actual values", this);
4420
4421   for (int block_index = 0; block_index < blocks()->length(); block_index++) {
4422     HBasicBlock* block = blocks()->at(block_index);
4423
4424 #ifdef DEBUG
4425     for (int i = 0; i < block->phis()->length(); i++) {
4426       HPhi* phi = block->phis()->at(i);
4427       DCHECK(phi->ActualValue() == phi);
4428     }
4429 #endif
4430
4431     for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
4432       HInstruction* instruction = it.Current();
4433       if (instruction->ActualValue() == instruction) continue;
4434       if (instruction->CheckFlag(HValue::kIsDead)) {
4435         // The instruction was marked as deleted but left in the graph
4436         // as a control flow dependency point for subsequent
4437         // instructions.
4438         instruction->DeleteAndReplaceWith(instruction->ActualValue());
4439       } else {
4440         DCHECK(instruction->IsInformativeDefinition());
4441         if (instruction->IsPurelyInformativeDefinition()) {
4442           instruction->DeleteAndReplaceWith(instruction->RedefinedOperand());
4443         } else {
4444           instruction->ReplaceAllUsesWith(instruction->ActualValue());
4445         }
4446       }
4447     }
4448   }
4449 }
4450
4451
4452 void HOptimizedGraphBuilder::PushArgumentsFromEnvironment(int count) {
4453   ZoneList<HValue*> arguments(count, zone());
4454   for (int i = 0; i < count; ++i) {
4455     arguments.Add(Pop(), zone());
4456   }
4457
4458   HPushArguments* push_args = New<HPushArguments>();
4459   while (!arguments.is_empty()) {
4460     push_args->AddInput(arguments.RemoveLast());
4461   }
4462   AddInstruction(push_args);
4463 }
4464
4465
4466 template <class Instruction>
4467 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
4468   PushArgumentsFromEnvironment(call->argument_count());
4469   return call;
4470 }
4471
4472
4473 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) {
4474   // First special is HContext.
4475   HInstruction* context = Add<HContext>();
4476   environment()->BindContext(context);
4477
4478   // Create an arguments object containing the initial parameters.  Set the
4479   // initial values of parameters including "this" having parameter index 0.
4480   DCHECK_EQ(scope->num_parameters() + 1, environment()->parameter_count());
4481   HArgumentsObject* arguments_object =
4482       New<HArgumentsObject>(environment()->parameter_count());
4483   for (int i = 0; i < environment()->parameter_count(); ++i) {
4484     HInstruction* parameter = Add<HParameter>(i);
4485     arguments_object->AddArgument(parameter, zone());
4486     environment()->Bind(i, parameter);
4487   }
4488   AddInstruction(arguments_object);
4489   graph()->SetArgumentsObject(arguments_object);
4490
4491   HConstant* undefined_constant = graph()->GetConstantUndefined();
4492   // Initialize specials and locals to undefined.
4493   for (int i = environment()->parameter_count() + 1;
4494        i < environment()->length();
4495        ++i) {
4496     environment()->Bind(i, undefined_constant);
4497   }
4498
4499   // Handle the arguments and arguments shadow variables specially (they do
4500   // not have declarations).
4501   if (scope->arguments() != NULL) {
4502     if (!scope->arguments()->IsStackAllocated()) {
4503       return Bailout(kContextAllocatedArguments);
4504     }
4505
4506     environment()->Bind(scope->arguments(),
4507                         graph()->GetArgumentsObject());
4508   }
4509 }
4510
4511
4512 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
4513   for (int i = 0; i < statements->length(); i++) {
4514     Statement* stmt = statements->at(i);
4515     CHECK_ALIVE(Visit(stmt));
4516     if (stmt->IsJump()) break;
4517   }
4518 }
4519
4520
4521 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
4522   DCHECK(!HasStackOverflow());
4523   DCHECK(current_block() != NULL);
4524   DCHECK(current_block()->HasPredecessor());
4525
4526   Scope* outer_scope = scope();
4527   Scope* scope = stmt->scope();
4528   BreakAndContinueInfo break_info(stmt, outer_scope);
4529
4530   { BreakAndContinueScope push(&break_info, this);
4531     if (scope != NULL) {
4532       // Load the function object.
4533       Scope* declaration_scope = scope->DeclarationScope();
4534       HInstruction* function;
4535       HValue* outer_context = environment()->context();
4536       if (declaration_scope->is_global_scope() ||
4537           declaration_scope->is_eval_scope()) {
4538         function = new(zone()) HLoadContextSlot(
4539             outer_context, Context::CLOSURE_INDEX, HLoadContextSlot::kNoCheck);
4540       } else {
4541         function = New<HThisFunction>();
4542       }
4543       AddInstruction(function);
4544       // Allocate a block context and store it to the stack frame.
4545       HInstruction* inner_context = Add<HAllocateBlockContext>(
4546           outer_context, function, scope->GetScopeInfo());
4547       HInstruction* instr = Add<HStoreFrameContext>(inner_context);
4548       if (instr->HasObservableSideEffects()) {
4549         AddSimulate(stmt->EntryId(), REMOVABLE_SIMULATE);
4550       }
4551       set_scope(scope);
4552       environment()->BindContext(inner_context);
4553       VisitDeclarations(scope->declarations());
4554       AddSimulate(stmt->DeclsId(), REMOVABLE_SIMULATE);
4555     }
4556     CHECK_BAILOUT(VisitStatements(stmt->statements()));
4557   }
4558   set_scope(outer_scope);
4559   if (scope != NULL && current_block() != NULL) {
4560     HValue* inner_context = environment()->context();
4561     HValue* outer_context = Add<HLoadNamedField>(
4562         inner_context, static_cast<HValue*>(NULL),
4563         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
4564
4565     HInstruction* instr = Add<HStoreFrameContext>(outer_context);
4566     if (instr->HasObservableSideEffects()) {
4567       AddSimulate(stmt->ExitId(), REMOVABLE_SIMULATE);
4568     }
4569     environment()->BindContext(outer_context);
4570   }
4571   HBasicBlock* break_block = break_info.break_block();
4572   if (break_block != NULL) {
4573     if (current_block() != NULL) Goto(break_block);
4574     break_block->SetJoinId(stmt->ExitId());
4575     set_current_block(break_block);
4576   }
4577 }
4578
4579
4580 void HOptimizedGraphBuilder::VisitExpressionStatement(
4581     ExpressionStatement* stmt) {
4582   DCHECK(!HasStackOverflow());
4583   DCHECK(current_block() != NULL);
4584   DCHECK(current_block()->HasPredecessor());
4585   VisitForEffect(stmt->expression());
4586 }
4587
4588
4589 void HOptimizedGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
4590   DCHECK(!HasStackOverflow());
4591   DCHECK(current_block() != NULL);
4592   DCHECK(current_block()->HasPredecessor());
4593 }
4594
4595
4596 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) {
4597   DCHECK(!HasStackOverflow());
4598   DCHECK(current_block() != NULL);
4599   DCHECK(current_block()->HasPredecessor());
4600   if (stmt->condition()->ToBooleanIsTrue()) {
4601     Add<HSimulate>(stmt->ThenId());
4602     Visit(stmt->then_statement());
4603   } else if (stmt->condition()->ToBooleanIsFalse()) {
4604     Add<HSimulate>(stmt->ElseId());
4605     Visit(stmt->else_statement());
4606   } else {
4607     HBasicBlock* cond_true = graph()->CreateBasicBlock();
4608     HBasicBlock* cond_false = graph()->CreateBasicBlock();
4609     CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false));
4610
4611     if (cond_true->HasPredecessor()) {
4612       cond_true->SetJoinId(stmt->ThenId());
4613       set_current_block(cond_true);
4614       CHECK_BAILOUT(Visit(stmt->then_statement()));
4615       cond_true = current_block();
4616     } else {
4617       cond_true = NULL;
4618     }
4619
4620     if (cond_false->HasPredecessor()) {
4621       cond_false->SetJoinId(stmt->ElseId());
4622       set_current_block(cond_false);
4623       CHECK_BAILOUT(Visit(stmt->else_statement()));
4624       cond_false = current_block();
4625     } else {
4626       cond_false = NULL;
4627     }
4628
4629     HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId());
4630     set_current_block(join);
4631   }
4632 }
4633
4634
4635 HBasicBlock* HOptimizedGraphBuilder::BreakAndContinueScope::Get(
4636     BreakableStatement* stmt,
4637     BreakType type,
4638     Scope** scope,
4639     int* drop_extra) {
4640   *drop_extra = 0;
4641   BreakAndContinueScope* current = this;
4642   while (current != NULL && current->info()->target() != stmt) {
4643     *drop_extra += current->info()->drop_extra();
4644     current = current->next();
4645   }
4646   DCHECK(current != NULL);  // Always found (unless stack is malformed).
4647   *scope = current->info()->scope();
4648
4649   if (type == BREAK) {
4650     *drop_extra += current->info()->drop_extra();
4651   }
4652
4653   HBasicBlock* block = NULL;
4654   switch (type) {
4655     case BREAK:
4656       block = current->info()->break_block();
4657       if (block == NULL) {
4658         block = current->owner()->graph()->CreateBasicBlock();
4659         current->info()->set_break_block(block);
4660       }
4661       break;
4662
4663     case CONTINUE:
4664       block = current->info()->continue_block();
4665       if (block == NULL) {
4666         block = current->owner()->graph()->CreateBasicBlock();
4667         current->info()->set_continue_block(block);
4668       }
4669       break;
4670   }
4671
4672   return block;
4673 }
4674
4675
4676 void HOptimizedGraphBuilder::VisitContinueStatement(
4677     ContinueStatement* stmt) {
4678   DCHECK(!HasStackOverflow());
4679   DCHECK(current_block() != NULL);
4680   DCHECK(current_block()->HasPredecessor());
4681   Scope* outer_scope = NULL;
4682   Scope* inner_scope = scope();
4683   int drop_extra = 0;
4684   HBasicBlock* continue_block = break_scope()->Get(
4685       stmt->target(), BreakAndContinueScope::CONTINUE,
4686       &outer_scope, &drop_extra);
4687   HValue* context = environment()->context();
4688   Drop(drop_extra);
4689   int context_pop_count = inner_scope->ContextChainLength(outer_scope);
4690   if (context_pop_count > 0) {
4691     while (context_pop_count-- > 0) {
4692       HInstruction* context_instruction = Add<HLoadNamedField>(
4693           context, static_cast<HValue*>(NULL),
4694           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
4695       context = context_instruction;
4696     }
4697     HInstruction* instr = Add<HStoreFrameContext>(context);
4698     if (instr->HasObservableSideEffects()) {
4699       AddSimulate(stmt->target()->EntryId(), REMOVABLE_SIMULATE);
4700     }
4701     environment()->BindContext(context);
4702   }
4703
4704   Goto(continue_block);
4705   set_current_block(NULL);
4706 }
4707
4708
4709 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
4710   DCHECK(!HasStackOverflow());
4711   DCHECK(current_block() != NULL);
4712   DCHECK(current_block()->HasPredecessor());
4713   Scope* outer_scope = NULL;
4714   Scope* inner_scope = scope();
4715   int drop_extra = 0;
4716   HBasicBlock* break_block = break_scope()->Get(
4717       stmt->target(), BreakAndContinueScope::BREAK,
4718       &outer_scope, &drop_extra);
4719   HValue* context = environment()->context();
4720   Drop(drop_extra);
4721   int context_pop_count = inner_scope->ContextChainLength(outer_scope);
4722   if (context_pop_count > 0) {
4723     while (context_pop_count-- > 0) {
4724       HInstruction* context_instruction = Add<HLoadNamedField>(
4725           context, static_cast<HValue*>(NULL),
4726           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
4727       context = context_instruction;
4728     }
4729     HInstruction* instr = Add<HStoreFrameContext>(context);
4730     if (instr->HasObservableSideEffects()) {
4731       AddSimulate(stmt->target()->ExitId(), REMOVABLE_SIMULATE);
4732     }
4733     environment()->BindContext(context);
4734   }
4735   Goto(break_block);
4736   set_current_block(NULL);
4737 }
4738
4739
4740 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
4741   DCHECK(!HasStackOverflow());
4742   DCHECK(current_block() != NULL);
4743   DCHECK(current_block()->HasPredecessor());
4744   FunctionState* state = function_state();
4745   AstContext* context = call_context();
4746   if (context == NULL) {
4747     // Not an inlined return, so an actual one.
4748     CHECK_ALIVE(VisitForValue(stmt->expression()));
4749     HValue* result = environment()->Pop();
4750     Add<HReturn>(result);
4751   } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
4752     // Return from an inlined construct call. In a test context the return value
4753     // will always evaluate to true, in a value context the return value needs
4754     // to be a JSObject.
4755     if (context->IsTest()) {
4756       TestContext* test = TestContext::cast(context);
4757       CHECK_ALIVE(VisitForEffect(stmt->expression()));
4758       Goto(test->if_true(), state);
4759     } else if (context->IsEffect()) {
4760       CHECK_ALIVE(VisitForEffect(stmt->expression()));
4761       Goto(function_return(), state);
4762     } else {
4763       DCHECK(context->IsValue());
4764       CHECK_ALIVE(VisitForValue(stmt->expression()));
4765       HValue* return_value = Pop();
4766       HValue* receiver = environment()->arguments_environment()->Lookup(0);
4767       HHasInstanceTypeAndBranch* typecheck =
4768           New<HHasInstanceTypeAndBranch>(return_value,
4769                                          FIRST_SPEC_OBJECT_TYPE,
4770                                          LAST_SPEC_OBJECT_TYPE);
4771       HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
4772       HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
4773       typecheck->SetSuccessorAt(0, if_spec_object);
4774       typecheck->SetSuccessorAt(1, not_spec_object);
4775       FinishCurrentBlock(typecheck);
4776       AddLeaveInlined(if_spec_object, return_value, state);
4777       AddLeaveInlined(not_spec_object, receiver, state);
4778     }
4779   } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
4780     // Return from an inlined setter call. The returned value is never used, the
4781     // value of an assignment is always the value of the RHS of the assignment.
4782     CHECK_ALIVE(VisitForEffect(stmt->expression()));
4783     if (context->IsTest()) {
4784       HValue* rhs = environment()->arguments_environment()->Lookup(1);
4785       context->ReturnValue(rhs);
4786     } else if (context->IsEffect()) {
4787       Goto(function_return(), state);
4788     } else {
4789       DCHECK(context->IsValue());
4790       HValue* rhs = environment()->arguments_environment()->Lookup(1);
4791       AddLeaveInlined(rhs, state);
4792     }
4793   } else {
4794     // Return from a normal inlined function. Visit the subexpression in the
4795     // expression context of the call.
4796     if (context->IsTest()) {
4797       TestContext* test = TestContext::cast(context);
4798       VisitForControl(stmt->expression(), test->if_true(), test->if_false());
4799     } else if (context->IsEffect()) {
4800       // Visit in value context and ignore the result. This is needed to keep
4801       // environment in sync with full-codegen since some visitors (e.g.
4802       // VisitCountOperation) use the operand stack differently depending on
4803       // context.
4804       CHECK_ALIVE(VisitForValue(stmt->expression()));
4805       Pop();
4806       Goto(function_return(), state);
4807     } else {
4808       DCHECK(context->IsValue());
4809       CHECK_ALIVE(VisitForValue(stmt->expression()));
4810       AddLeaveInlined(Pop(), state);
4811     }
4812   }
4813   set_current_block(NULL);
4814 }
4815
4816
4817 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) {
4818   DCHECK(!HasStackOverflow());
4819   DCHECK(current_block() != NULL);
4820   DCHECK(current_block()->HasPredecessor());
4821   return Bailout(kWithStatement);
4822 }
4823
4824
4825 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
4826   DCHECK(!HasStackOverflow());
4827   DCHECK(current_block() != NULL);
4828   DCHECK(current_block()->HasPredecessor());
4829
4830   // We only optimize switch statements with a bounded number of clauses.
4831   const int kCaseClauseLimit = 128;
4832   ZoneList<CaseClause*>* clauses = stmt->cases();
4833   int clause_count = clauses->length();
4834   ZoneList<HBasicBlock*> body_blocks(clause_count, zone());
4835   if (clause_count > kCaseClauseLimit) {
4836     return Bailout(kSwitchStatementTooManyClauses);
4837   }
4838
4839   CHECK_ALIVE(VisitForValue(stmt->tag()));
4840   Add<HSimulate>(stmt->EntryId());
4841   HValue* tag_value = Top();
4842   Type* tag_type = stmt->tag()->bounds().lower;
4843
4844   // 1. Build all the tests, with dangling true branches
4845   BailoutId default_id = BailoutId::None();
4846   for (int i = 0; i < clause_count; ++i) {
4847     CaseClause* clause = clauses->at(i);
4848     if (clause->is_default()) {
4849       body_blocks.Add(NULL, zone());
4850       if (default_id.IsNone()) default_id = clause->EntryId();
4851       continue;
4852     }
4853
4854     // Generate a compare and branch.
4855     CHECK_ALIVE(VisitForValue(clause->label()));
4856     HValue* label_value = Pop();
4857
4858     Type* label_type = clause->label()->bounds().lower;
4859     Type* combined_type = clause->compare_type();
4860     HControlInstruction* compare = BuildCompareInstruction(
4861         Token::EQ_STRICT, tag_value, label_value, tag_type, label_type,
4862         combined_type,
4863         ScriptPositionToSourcePosition(stmt->tag()->position()),
4864         ScriptPositionToSourcePosition(clause->label()->position()),
4865         PUSH_BEFORE_SIMULATE, clause->id());
4866
4867     HBasicBlock* next_test_block = graph()->CreateBasicBlock();
4868     HBasicBlock* body_block = graph()->CreateBasicBlock();
4869     body_blocks.Add(body_block, zone());
4870     compare->SetSuccessorAt(0, body_block);
4871     compare->SetSuccessorAt(1, next_test_block);
4872     FinishCurrentBlock(compare);
4873
4874     set_current_block(body_block);
4875     Drop(1);  // tag_value
4876
4877     set_current_block(next_test_block);
4878   }
4879
4880   // Save the current block to use for the default or to join with the
4881   // exit.
4882   HBasicBlock* last_block = current_block();
4883   Drop(1);  // tag_value
4884
4885   // 2. Loop over the clauses and the linked list of tests in lockstep,
4886   // translating the clause bodies.
4887   HBasicBlock* fall_through_block = NULL;
4888
4889   BreakAndContinueInfo break_info(stmt, scope());
4890   { BreakAndContinueScope push(&break_info, this);
4891     for (int i = 0; i < clause_count; ++i) {
4892       CaseClause* clause = clauses->at(i);
4893
4894       // Identify the block where normal (non-fall-through) control flow
4895       // goes to.
4896       HBasicBlock* normal_block = NULL;
4897       if (clause->is_default()) {
4898         if (last_block == NULL) continue;
4899         normal_block = last_block;
4900         last_block = NULL;  // Cleared to indicate we've handled it.
4901       } else {
4902         normal_block = body_blocks[i];
4903       }
4904
4905       if (fall_through_block == NULL) {
4906         set_current_block(normal_block);
4907       } else {
4908         HBasicBlock* join = CreateJoin(fall_through_block,
4909                                        normal_block,
4910                                        clause->EntryId());
4911         set_current_block(join);
4912       }
4913
4914       CHECK_BAILOUT(VisitStatements(clause->statements()));
4915       fall_through_block = current_block();
4916     }
4917   }
4918
4919   // Create an up-to-3-way join.  Use the break block if it exists since
4920   // it's already a join block.
4921   HBasicBlock* break_block = break_info.break_block();
4922   if (break_block == NULL) {
4923     set_current_block(CreateJoin(fall_through_block,
4924                                  last_block,
4925                                  stmt->ExitId()));
4926   } else {
4927     if (fall_through_block != NULL) Goto(fall_through_block, break_block);
4928     if (last_block != NULL) Goto(last_block, break_block);
4929     break_block->SetJoinId(stmt->ExitId());
4930     set_current_block(break_block);
4931   }
4932 }
4933
4934
4935 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt,
4936                                            HBasicBlock* loop_entry) {
4937   Add<HSimulate>(stmt->StackCheckId());
4938   HStackCheck* stack_check =
4939       HStackCheck::cast(Add<HStackCheck>(HStackCheck::kBackwardsBranch));
4940   DCHECK(loop_entry->IsLoopHeader());
4941   loop_entry->loop_information()->set_stack_check(stack_check);
4942   CHECK_BAILOUT(Visit(stmt->body()));
4943 }
4944
4945
4946 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
4947   DCHECK(!HasStackOverflow());
4948   DCHECK(current_block() != NULL);
4949   DCHECK(current_block()->HasPredecessor());
4950   DCHECK(current_block() != NULL);
4951   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
4952
4953   BreakAndContinueInfo break_info(stmt, scope());
4954   {
4955     BreakAndContinueScope push(&break_info, this);
4956     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
4957   }
4958   HBasicBlock* body_exit =
4959       JoinContinue(stmt, current_block(), break_info.continue_block());
4960   HBasicBlock* loop_successor = NULL;
4961   if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) {
4962     set_current_block(body_exit);
4963     loop_successor = graph()->CreateBasicBlock();
4964     if (stmt->cond()->ToBooleanIsFalse()) {
4965       loop_entry->loop_information()->stack_check()->Eliminate();
4966       Goto(loop_successor);
4967       body_exit = NULL;
4968     } else {
4969       // The block for a true condition, the actual predecessor block of the
4970       // back edge.
4971       body_exit = graph()->CreateBasicBlock();
4972       CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor));
4973     }
4974     if (body_exit != NULL && body_exit->HasPredecessor()) {
4975       body_exit->SetJoinId(stmt->BackEdgeId());
4976     } else {
4977       body_exit = NULL;
4978     }
4979     if (loop_successor->HasPredecessor()) {
4980       loop_successor->SetJoinId(stmt->ExitId());
4981     } else {
4982       loop_successor = NULL;
4983     }
4984   }
4985   HBasicBlock* loop_exit = CreateLoop(stmt,
4986                                       loop_entry,
4987                                       body_exit,
4988                                       loop_successor,
4989                                       break_info.break_block());
4990   set_current_block(loop_exit);
4991 }
4992
4993
4994 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
4995   DCHECK(!HasStackOverflow());
4996   DCHECK(current_block() != NULL);
4997   DCHECK(current_block()->HasPredecessor());
4998   DCHECK(current_block() != NULL);
4999   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
5000
5001   // If the condition is constant true, do not generate a branch.
5002   HBasicBlock* loop_successor = NULL;
5003   if (!stmt->cond()->ToBooleanIsTrue()) {
5004     HBasicBlock* body_entry = graph()->CreateBasicBlock();
5005     loop_successor = graph()->CreateBasicBlock();
5006     CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
5007     if (body_entry->HasPredecessor()) {
5008       body_entry->SetJoinId(stmt->BodyId());
5009       set_current_block(body_entry);
5010     }
5011     if (loop_successor->HasPredecessor()) {
5012       loop_successor->SetJoinId(stmt->ExitId());
5013     } else {
5014       loop_successor = NULL;
5015     }
5016   }
5017
5018   BreakAndContinueInfo break_info(stmt, scope());
5019   if (current_block() != NULL) {
5020     BreakAndContinueScope push(&break_info, this);
5021     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
5022   }
5023   HBasicBlock* body_exit =
5024       JoinContinue(stmt, current_block(), break_info.continue_block());
5025   HBasicBlock* loop_exit = CreateLoop(stmt,
5026                                       loop_entry,
5027                                       body_exit,
5028                                       loop_successor,
5029                                       break_info.break_block());
5030   set_current_block(loop_exit);
5031 }
5032
5033
5034 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) {
5035   DCHECK(!HasStackOverflow());
5036   DCHECK(current_block() != NULL);
5037   DCHECK(current_block()->HasPredecessor());
5038   if (stmt->init() != NULL) {
5039     CHECK_ALIVE(Visit(stmt->init()));
5040   }
5041   DCHECK(current_block() != NULL);
5042   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
5043
5044   HBasicBlock* loop_successor = NULL;
5045   if (stmt->cond() != NULL) {
5046     HBasicBlock* body_entry = graph()->CreateBasicBlock();
5047     loop_successor = graph()->CreateBasicBlock();
5048     CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
5049     if (body_entry->HasPredecessor()) {
5050       body_entry->SetJoinId(stmt->BodyId());
5051       set_current_block(body_entry);
5052     }
5053     if (loop_successor->HasPredecessor()) {
5054       loop_successor->SetJoinId(stmt->ExitId());
5055     } else {
5056       loop_successor = NULL;
5057     }
5058   }
5059
5060   BreakAndContinueInfo break_info(stmt, scope());
5061   if (current_block() != NULL) {
5062     BreakAndContinueScope push(&break_info, this);
5063     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
5064   }
5065   HBasicBlock* body_exit =
5066       JoinContinue(stmt, current_block(), break_info.continue_block());
5067
5068   if (stmt->next() != NULL && body_exit != NULL) {
5069     set_current_block(body_exit);
5070     CHECK_BAILOUT(Visit(stmt->next()));
5071     body_exit = current_block();
5072   }
5073
5074   HBasicBlock* loop_exit = CreateLoop(stmt,
5075                                       loop_entry,
5076                                       body_exit,
5077                                       loop_successor,
5078                                       break_info.break_block());
5079   set_current_block(loop_exit);
5080 }
5081
5082
5083 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
5084   DCHECK(!HasStackOverflow());
5085   DCHECK(current_block() != NULL);
5086   DCHECK(current_block()->HasPredecessor());
5087
5088   if (!FLAG_optimize_for_in) {
5089     return Bailout(kForInStatementOptimizationIsDisabled);
5090   }
5091
5092   if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) {
5093     return Bailout(kForInStatementIsNotFastCase);
5094   }
5095
5096   if (!stmt->each()->IsVariableProxy() ||
5097       !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
5098     return Bailout(kForInStatementWithNonLocalEachVariable);
5099   }
5100
5101   Variable* each_var = stmt->each()->AsVariableProxy()->var();
5102
5103   CHECK_ALIVE(VisitForValue(stmt->enumerable()));
5104   HValue* enumerable = Top();  // Leave enumerable at the top.
5105
5106   HInstruction* map = Add<HForInPrepareMap>(enumerable);
5107   Add<HSimulate>(stmt->PrepareId());
5108
5109   HInstruction* array = Add<HForInCacheArray>(
5110       enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex);
5111
5112   HInstruction* enum_length = Add<HMapEnumLength>(map);
5113
5114   HInstruction* start_index = Add<HConstant>(0);
5115
5116   Push(map);
5117   Push(array);
5118   Push(enum_length);
5119   Push(start_index);
5120
5121   HInstruction* index_cache = Add<HForInCacheArray>(
5122       enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex);
5123   HForInCacheArray::cast(array)->set_index_cache(
5124       HForInCacheArray::cast(index_cache));
5125
5126   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
5127
5128   HValue* index = environment()->ExpressionStackAt(0);
5129   HValue* limit = environment()->ExpressionStackAt(1);
5130
5131   // Check that we still have more keys.
5132   HCompareNumericAndBranch* compare_index =
5133       New<HCompareNumericAndBranch>(index, limit, Token::LT);
5134   compare_index->set_observed_input_representation(
5135       Representation::Smi(), Representation::Smi());
5136
5137   HBasicBlock* loop_body = graph()->CreateBasicBlock();
5138   HBasicBlock* loop_successor = graph()->CreateBasicBlock();
5139
5140   compare_index->SetSuccessorAt(0, loop_body);
5141   compare_index->SetSuccessorAt(1, loop_successor);
5142   FinishCurrentBlock(compare_index);
5143
5144   set_current_block(loop_successor);
5145   Drop(5);
5146
5147   set_current_block(loop_body);
5148
5149   HValue* key = Add<HLoadKeyed>(
5150       environment()->ExpressionStackAt(2),  // Enum cache.
5151       environment()->ExpressionStackAt(0),  // Iteration index.
5152       environment()->ExpressionStackAt(0),
5153       FAST_ELEMENTS);
5154
5155   // Check if the expected map still matches that of the enumerable.
5156   // If not just deoptimize.
5157   Add<HCheckMapValue>(environment()->ExpressionStackAt(4),
5158                       environment()->ExpressionStackAt(3));
5159
5160   Bind(each_var, key);
5161
5162   BreakAndContinueInfo break_info(stmt, scope(), 5);
5163   {
5164     BreakAndContinueScope push(&break_info, this);
5165     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
5166   }
5167
5168   HBasicBlock* body_exit =
5169       JoinContinue(stmt, current_block(), break_info.continue_block());
5170
5171   if (body_exit != NULL) {
5172     set_current_block(body_exit);
5173
5174     HValue* current_index = Pop();
5175     Push(AddUncasted<HAdd>(current_index, graph()->GetConstant1()));
5176     body_exit = current_block();
5177   }
5178
5179   HBasicBlock* loop_exit = CreateLoop(stmt,
5180                                       loop_entry,
5181                                       body_exit,
5182                                       loop_successor,
5183                                       break_info.break_block());
5184
5185   set_current_block(loop_exit);
5186 }
5187
5188
5189 void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
5190   DCHECK(!HasStackOverflow());
5191   DCHECK(current_block() != NULL);
5192   DCHECK(current_block()->HasPredecessor());
5193   return Bailout(kForOfStatement);
5194 }
5195
5196
5197 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
5198   DCHECK(!HasStackOverflow());
5199   DCHECK(current_block() != NULL);
5200   DCHECK(current_block()->HasPredecessor());
5201   return Bailout(kTryCatchStatement);
5202 }
5203
5204
5205 void HOptimizedGraphBuilder::VisitTryFinallyStatement(
5206     TryFinallyStatement* stmt) {
5207   DCHECK(!HasStackOverflow());
5208   DCHECK(current_block() != NULL);
5209   DCHECK(current_block()->HasPredecessor());
5210   return Bailout(kTryFinallyStatement);
5211 }
5212
5213
5214 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
5215   DCHECK(!HasStackOverflow());
5216   DCHECK(current_block() != NULL);
5217   DCHECK(current_block()->HasPredecessor());
5218   return Bailout(kDebuggerStatement);
5219 }
5220
5221
5222 void HOptimizedGraphBuilder::VisitCaseClause(CaseClause* clause) {
5223   UNREACHABLE();
5224 }
5225
5226
5227 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
5228   DCHECK(!HasStackOverflow());
5229   DCHECK(current_block() != NULL);
5230   DCHECK(current_block()->HasPredecessor());
5231   Handle<SharedFunctionInfo> shared_info = expr->shared_info();
5232   if (shared_info.is_null()) {
5233     shared_info =
5234         Compiler::BuildFunctionInfo(expr, current_info()->script(), top_info());
5235   }
5236   // We also have a stack overflow if the recursive compilation did.
5237   if (HasStackOverflow()) return;
5238   HFunctionLiteral* instr =
5239       New<HFunctionLiteral>(shared_info, expr->pretenure());
5240   return ast_context()->ReturnInstruction(instr, expr->id());
5241 }
5242
5243
5244 void HOptimizedGraphBuilder::VisitNativeFunctionLiteral(
5245     NativeFunctionLiteral* expr) {
5246   DCHECK(!HasStackOverflow());
5247   DCHECK(current_block() != NULL);
5248   DCHECK(current_block()->HasPredecessor());
5249   return Bailout(kNativeFunctionLiteral);
5250 }
5251
5252
5253 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) {
5254   DCHECK(!HasStackOverflow());
5255   DCHECK(current_block() != NULL);
5256   DCHECK(current_block()->HasPredecessor());
5257   HBasicBlock* cond_true = graph()->CreateBasicBlock();
5258   HBasicBlock* cond_false = graph()->CreateBasicBlock();
5259   CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false));
5260
5261   // Visit the true and false subexpressions in the same AST context as the
5262   // whole expression.
5263   if (cond_true->HasPredecessor()) {
5264     cond_true->SetJoinId(expr->ThenId());
5265     set_current_block(cond_true);
5266     CHECK_BAILOUT(Visit(expr->then_expression()));
5267     cond_true = current_block();
5268   } else {
5269     cond_true = NULL;
5270   }
5271
5272   if (cond_false->HasPredecessor()) {
5273     cond_false->SetJoinId(expr->ElseId());
5274     set_current_block(cond_false);
5275     CHECK_BAILOUT(Visit(expr->else_expression()));
5276     cond_false = current_block();
5277   } else {
5278     cond_false = NULL;
5279   }
5280
5281   if (!ast_context()->IsTest()) {
5282     HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id());
5283     set_current_block(join);
5284     if (join != NULL && !ast_context()->IsEffect()) {
5285       return ast_context()->ReturnValue(Pop());
5286     }
5287   }
5288 }
5289
5290
5291 HOptimizedGraphBuilder::GlobalPropertyAccess
5292 HOptimizedGraphBuilder::LookupGlobalProperty(Variable* var, LookupIterator* it,
5293                                              PropertyAccessType access_type) {
5294   DCHECK_EQ(*var->name(), *it->name());
5295   if (var->is_this() || !current_info()->has_global_object()) {
5296     return kUseGeneric;
5297   }
5298   if (!it->HasProperty() || it->property_kind() != LookupIterator::DATA ||
5299       (access_type == STORE && it->IsReadOnly())) {
5300     return kUseGeneric;
5301   }
5302
5303   return kUseCell;
5304 }
5305
5306
5307 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
5308   DCHECK(var->IsContextSlot());
5309   HValue* context = environment()->context();
5310   int length = scope()->ContextChainLength(var->scope());
5311   while (length-- > 0) {
5312     context = Add<HLoadNamedField>(
5313         context, static_cast<HValue*>(NULL),
5314         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
5315   }
5316   return context;
5317 }
5318
5319
5320 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
5321   if (expr->is_this()) {
5322     current_info()->set_this_has_uses(true);
5323   }
5324
5325   DCHECK(!HasStackOverflow());
5326   DCHECK(current_block() != NULL);
5327   DCHECK(current_block()->HasPredecessor());
5328   Variable* variable = expr->var();
5329   switch (variable->location()) {
5330     case Variable::UNALLOCATED: {
5331       if (IsLexicalVariableMode(variable->mode())) {
5332         // TODO(rossberg): should this be an DCHECK?
5333         return Bailout(kReferenceToGlobalLexicalVariable);
5334       }
5335       // Handle known global constants like 'undefined' specially to avoid a
5336       // load from a global cell for them.
5337       Handle<Object> constant_value =
5338           isolate()->factory()->GlobalConstantFor(variable->name());
5339       if (!constant_value.is_null()) {
5340         HConstant* instr = New<HConstant>(constant_value);
5341         return ast_context()->ReturnInstruction(instr, expr->id());
5342       }
5343
5344       Handle<GlobalObject> global(current_info()->global_object());
5345       LookupIterator it(global, variable->name(),
5346                         LookupIterator::CHECK_PROPERTY);
5347       GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD);
5348
5349       if (type == kUseCell &&
5350           current_info()->global_object()->IsAccessCheckNeeded()) {
5351         type = kUseGeneric;
5352       }
5353
5354       if (type == kUseCell) {
5355         Handle<PropertyCell> cell = it.GetPropertyCell();
5356         if (cell->type()->IsConstant()) {
5357           PropertyCell::AddDependentCompilationInfo(cell, top_info());
5358           Handle<Object> constant_object = cell->type()->AsConstant()->Value();
5359           if (constant_object->IsConsString()) {
5360             constant_object =
5361                 String::Flatten(Handle<String>::cast(constant_object));
5362           }
5363           HConstant* constant = New<HConstant>(constant_object);
5364           return ast_context()->ReturnInstruction(constant, expr->id());
5365         } else {
5366           HLoadGlobalCell* instr =
5367               New<HLoadGlobalCell>(cell, it.property_details());
5368           return ast_context()->ReturnInstruction(instr, expr->id());
5369         }
5370       } else {
5371         HValue* global_object = Add<HLoadNamedField>(
5372             context(), static_cast<HValue*>(NULL),
5373             HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
5374         HLoadGlobalGeneric* instr =
5375             New<HLoadGlobalGeneric>(global_object,
5376                                     variable->name(),
5377                                     ast_context()->is_for_typeof());
5378         if (FLAG_vector_ics) {
5379           Handle<SharedFunctionInfo> current_shared =
5380               function_state()->compilation_info()->shared_info();
5381           instr->SetVectorAndSlot(
5382               handle(current_shared->feedback_vector(), isolate()),
5383               expr->VariableFeedbackSlot());
5384         }
5385         return ast_context()->ReturnInstruction(instr, expr->id());
5386       }
5387     }
5388
5389     case Variable::PARAMETER:
5390     case Variable::LOCAL: {
5391       HValue* value = LookupAndMakeLive(variable);
5392       if (value == graph()->GetConstantHole()) {
5393         DCHECK(IsDeclaredVariableMode(variable->mode()) &&
5394                variable->mode() != VAR);
5395         return Bailout(kReferenceToUninitializedVariable);
5396       }
5397       return ast_context()->ReturnValue(value);
5398     }
5399
5400     case Variable::CONTEXT: {
5401       HValue* context = BuildContextChainWalk(variable);
5402       HLoadContextSlot::Mode mode;
5403       switch (variable->mode()) {
5404         case LET:
5405         case CONST:
5406           mode = HLoadContextSlot::kCheckDeoptimize;
5407           break;
5408         case CONST_LEGACY:
5409           mode = HLoadContextSlot::kCheckReturnUndefined;
5410           break;
5411         default:
5412           mode = HLoadContextSlot::kNoCheck;
5413           break;
5414       }
5415       HLoadContextSlot* instr =
5416           new(zone()) HLoadContextSlot(context, variable->index(), mode);
5417       return ast_context()->ReturnInstruction(instr, expr->id());
5418     }
5419
5420     case Variable::LOOKUP:
5421       return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup);
5422   }
5423 }
5424
5425
5426 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) {
5427   DCHECK(!HasStackOverflow());
5428   DCHECK(current_block() != NULL);
5429   DCHECK(current_block()->HasPredecessor());
5430   HConstant* instr = New<HConstant>(expr->value());
5431   return ast_context()->ReturnInstruction(instr, expr->id());
5432 }
5433
5434
5435 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
5436   DCHECK(!HasStackOverflow());
5437   DCHECK(current_block() != NULL);
5438   DCHECK(current_block()->HasPredecessor());
5439   Handle<JSFunction> closure = function_state()->compilation_info()->closure();
5440   Handle<FixedArray> literals(closure->literals());
5441   HRegExpLiteral* instr = New<HRegExpLiteral>(literals,
5442                                               expr->pattern(),
5443                                               expr->flags(),
5444                                               expr->literal_index());
5445   return ast_context()->ReturnInstruction(instr, expr->id());
5446 }
5447
5448
5449 static bool CanInlinePropertyAccess(Type* type) {
5450   if (type->Is(Type::NumberOrString())) return true;
5451   if (!type->IsClass()) return false;
5452   Handle<Map> map = type->AsClass()->Map();
5453   return map->IsJSObjectMap() &&
5454       !map->is_dictionary_map() &&
5455       !map->has_named_interceptor();
5456 }
5457
5458
5459 // Determines whether the given array or object literal boilerplate satisfies
5460 // all limits to be considered for fast deep-copying and computes the total
5461 // size of all objects that are part of the graph.
5462 static bool IsFastLiteral(Handle<JSObject> boilerplate,
5463                           int max_depth,
5464                           int* max_properties) {
5465   if (boilerplate->map()->is_deprecated() &&
5466       !JSObject::TryMigrateInstance(boilerplate)) {
5467     return false;
5468   }
5469
5470   DCHECK(max_depth >= 0 && *max_properties >= 0);
5471   if (max_depth == 0) return false;
5472
5473   Isolate* isolate = boilerplate->GetIsolate();
5474   Handle<FixedArrayBase> elements(boilerplate->elements());
5475   if (elements->length() > 0 &&
5476       elements->map() != isolate->heap()->fixed_cow_array_map()) {
5477     if (boilerplate->HasFastObjectElements()) {
5478       Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
5479       int length = elements->length();
5480       for (int i = 0; i < length; i++) {
5481         if ((*max_properties)-- == 0) return false;
5482         Handle<Object> value(fast_elements->get(i), isolate);
5483         if (value->IsJSObject()) {
5484           Handle<JSObject> value_object = Handle<JSObject>::cast(value);
5485           if (!IsFastLiteral(value_object,
5486                              max_depth - 1,
5487                              max_properties)) {
5488             return false;
5489           }
5490         }
5491       }
5492     } else if (!boilerplate->HasFastDoubleElements()) {
5493       return false;
5494     }
5495   }
5496
5497   Handle<FixedArray> properties(boilerplate->properties());
5498   if (properties->length() > 0) {
5499     return false;
5500   } else {
5501     Handle<DescriptorArray> descriptors(
5502         boilerplate->map()->instance_descriptors());
5503     int limit = boilerplate->map()->NumberOfOwnDescriptors();
5504     for (int i = 0; i < limit; i++) {
5505       PropertyDetails details = descriptors->GetDetails(i);
5506       if (details.type() != FIELD) continue;
5507       int index = descriptors->GetFieldIndex(i);
5508       if ((*max_properties)-- == 0) return false;
5509       Handle<Object> value(boilerplate->InObjectPropertyAt(index), isolate);
5510       if (value->IsJSObject()) {
5511         Handle<JSObject> value_object = Handle<JSObject>::cast(value);
5512         if (!IsFastLiteral(value_object,
5513                            max_depth - 1,
5514                            max_properties)) {
5515           return false;
5516         }
5517       }
5518     }
5519   }
5520   return true;
5521 }
5522
5523
5524 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
5525   DCHECK(!HasStackOverflow());
5526   DCHECK(current_block() != NULL);
5527   DCHECK(current_block()->HasPredecessor());
5528   expr->BuildConstantProperties(isolate());
5529   Handle<JSFunction> closure = function_state()->compilation_info()->closure();
5530   HInstruction* literal;
5531
5532   // Check whether to use fast or slow deep-copying for boilerplate.
5533   int max_properties = kMaxFastLiteralProperties;
5534   Handle<Object> literals_cell(closure->literals()->get(expr->literal_index()),
5535                                isolate());
5536   Handle<AllocationSite> site;
5537   Handle<JSObject> boilerplate;
5538   if (!literals_cell->IsUndefined()) {
5539     // Retrieve the boilerplate
5540     site = Handle<AllocationSite>::cast(literals_cell);
5541     boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()),
5542                                    isolate());
5543   }
5544
5545   if (!boilerplate.is_null() &&
5546       IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
5547     AllocationSiteUsageContext usage_context(isolate(), site, false);
5548     usage_context.EnterNewScope();
5549     literal = BuildFastLiteral(boilerplate, &usage_context);
5550     usage_context.ExitScope(site, boilerplate);
5551   } else {
5552     NoObservableSideEffectsScope no_effects(this);
5553     Handle<FixedArray> closure_literals(closure->literals(), isolate());
5554     Handle<FixedArray> constant_properties = expr->constant_properties();
5555     int literal_index = expr->literal_index();
5556     int flags = expr->fast_elements()
5557         ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags;
5558     flags |= expr->has_function()
5559         ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags;
5560
5561     Add<HPushArguments>(Add<HConstant>(closure_literals),
5562                         Add<HConstant>(literal_index),
5563                         Add<HConstant>(constant_properties),
5564                         Add<HConstant>(flags));
5565
5566     // TODO(mvstanton): Add a flag to turn off creation of any
5567     // AllocationMementos for this call: we are in crankshaft and should have
5568     // learned enough about transition behavior to stop emitting mementos.
5569     Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral;
5570     literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
5571                                 Runtime::FunctionForId(function_id),
5572                                 4);
5573   }
5574
5575   // The object is expected in the bailout environment during computation
5576   // of the property values and is the value of the entire expression.
5577   Push(literal);
5578
5579   expr->CalculateEmitStore(zone());
5580
5581   for (int i = 0; i < expr->properties()->length(); i++) {
5582     ObjectLiteral::Property* property = expr->properties()->at(i);
5583     if (property->IsCompileTimeValue()) continue;
5584
5585     Literal* key = property->key();
5586     Expression* value = property->value();
5587
5588     switch (property->kind()) {
5589       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
5590         DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
5591         // Fall through.
5592       case ObjectLiteral::Property::COMPUTED:
5593         if (key->value()->IsInternalizedString()) {
5594           if (property->emit_store()) {
5595             CHECK_ALIVE(VisitForValue(value));
5596             HValue* value = Pop();
5597             Handle<Map> map = property->GetReceiverType();
5598             Handle<String> name = property->key()->AsPropertyName();
5599             HInstruction* store;
5600             if (map.is_null()) {
5601               // If we don't know the monomorphic type, do a generic store.
5602               CHECK_ALIVE(store = BuildNamedGeneric(
5603                   STORE, NULL, literal, name, value));
5604             } else {
5605               PropertyAccessInfo info(this, STORE, ToType(map), name);
5606               if (info.CanAccessMonomorphic()) {
5607                 HValue* checked_literal = Add<HCheckMaps>(literal, map);
5608                 DCHECK(!info.IsAccessor());
5609                 store = BuildMonomorphicAccess(
5610                     &info, literal, checked_literal, value,
5611                     BailoutId::None(), BailoutId::None());
5612               } else {
5613                 CHECK_ALIVE(store = BuildNamedGeneric(
5614                     STORE, NULL, literal, name, value));
5615               }
5616             }
5617             AddInstruction(store);
5618             if (store->HasObservableSideEffects()) {
5619               Add<HSimulate>(key->id(), REMOVABLE_SIMULATE);
5620             }
5621           } else {
5622             CHECK_ALIVE(VisitForEffect(value));
5623           }
5624           break;
5625         }
5626         // Fall through.
5627       case ObjectLiteral::Property::PROTOTYPE:
5628       case ObjectLiteral::Property::SETTER:
5629       case ObjectLiteral::Property::GETTER:
5630         return Bailout(kObjectLiteralWithComplexProperty);
5631       default: UNREACHABLE();
5632     }
5633   }
5634
5635   if (expr->has_function()) {
5636     // Return the result of the transformation to fast properties
5637     // instead of the original since this operation changes the map
5638     // of the object. This makes sure that the original object won't
5639     // be used by other optimized code before it is transformed
5640     // (e.g. because of code motion).
5641     HToFastProperties* result = Add<HToFastProperties>(Pop());
5642     return ast_context()->ReturnValue(result);
5643   } else {
5644     return ast_context()->ReturnValue(Pop());
5645   }
5646 }
5647
5648
5649 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
5650   DCHECK(!HasStackOverflow());
5651   DCHECK(current_block() != NULL);
5652   DCHECK(current_block()->HasPredecessor());
5653   expr->BuildConstantElements(isolate());
5654   ZoneList<Expression*>* subexprs = expr->values();
5655   int length = subexprs->length();
5656   HInstruction* literal;
5657
5658   Handle<AllocationSite> site;
5659   Handle<FixedArray> literals(environment()->closure()->literals(), isolate());
5660   bool uninitialized = false;
5661   Handle<Object> literals_cell(literals->get(expr->literal_index()),
5662                                isolate());
5663   Handle<JSObject> boilerplate_object;
5664   if (literals_cell->IsUndefined()) {
5665     uninitialized = true;
5666     Handle<Object> raw_boilerplate;
5667     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5668         isolate(), raw_boilerplate,
5669         Runtime::CreateArrayLiteralBoilerplate(
5670             isolate(), literals, expr->constant_elements()),
5671         Bailout(kArrayBoilerplateCreationFailed));
5672
5673     boilerplate_object = Handle<JSObject>::cast(raw_boilerplate);
5674     AllocationSiteCreationContext creation_context(isolate());
5675     site = creation_context.EnterNewScope();
5676     if (JSObject::DeepWalk(boilerplate_object, &creation_context).is_null()) {
5677       return Bailout(kArrayBoilerplateCreationFailed);
5678     }
5679     creation_context.ExitScope(site, boilerplate_object);
5680     literals->set(expr->literal_index(), *site);
5681
5682     if (boilerplate_object->elements()->map() ==
5683         isolate()->heap()->fixed_cow_array_map()) {
5684       isolate()->counters()->cow_arrays_created_runtime()->Increment();
5685     }
5686   } else {
5687     DCHECK(literals_cell->IsAllocationSite());
5688     site = Handle<AllocationSite>::cast(literals_cell);
5689     boilerplate_object = Handle<JSObject>(
5690         JSObject::cast(site->transition_info()), isolate());
5691   }
5692
5693   DCHECK(!boilerplate_object.is_null());
5694   DCHECK(site->SitePointsToLiteral());
5695
5696   ElementsKind boilerplate_elements_kind =
5697       boilerplate_object->GetElementsKind();
5698
5699   // Check whether to use fast or slow deep-copying for boilerplate.
5700   int max_properties = kMaxFastLiteralProperties;
5701   if (IsFastLiteral(boilerplate_object,
5702                     kMaxFastLiteralDepth,
5703                     &max_properties)) {
5704     AllocationSiteUsageContext usage_context(isolate(), site, false);
5705     usage_context.EnterNewScope();
5706     literal = BuildFastLiteral(boilerplate_object, &usage_context);
5707     usage_context.ExitScope(site, boilerplate_object);
5708   } else {
5709     NoObservableSideEffectsScope no_effects(this);
5710     // Boilerplate already exists and constant elements are never accessed,
5711     // pass an empty fixed array to the runtime function instead.
5712     Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array();
5713     int literal_index = expr->literal_index();
5714     int flags = expr->depth() == 1
5715         ? ArrayLiteral::kShallowElements
5716         : ArrayLiteral::kNoFlags;
5717     flags |= ArrayLiteral::kDisableMementos;
5718
5719     Add<HPushArguments>(Add<HConstant>(literals),
5720                         Add<HConstant>(literal_index),
5721                         Add<HConstant>(constants),
5722                         Add<HConstant>(flags));
5723
5724     // TODO(mvstanton): Consider a flag to turn off creation of any
5725     // AllocationMementos for this call: we are in crankshaft and should have
5726     // learned enough about transition behavior to stop emitting mementos.
5727     Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral;
5728     literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
5729                                 Runtime::FunctionForId(function_id),
5730                                 4);
5731
5732     // De-opt if elements kind changed from boilerplate_elements_kind.
5733     Handle<Map> map = Handle<Map>(boilerplate_object->map(), isolate());
5734     literal = Add<HCheckMaps>(literal, map);
5735   }
5736
5737   // The array is expected in the bailout environment during computation
5738   // of the property values and is the value of the entire expression.
5739   Push(literal);
5740   // The literal index is on the stack, too.
5741   Push(Add<HConstant>(expr->literal_index()));
5742
5743   HInstruction* elements = NULL;
5744
5745   for (int i = 0; i < length; i++) {
5746     Expression* subexpr = subexprs->at(i);
5747     // If the subexpression is a literal or a simple materialized literal it
5748     // is already set in the cloned array.
5749     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
5750
5751     CHECK_ALIVE(VisitForValue(subexpr));
5752     HValue* value = Pop();
5753     if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral);
5754
5755     elements = AddLoadElements(literal);
5756
5757     HValue* key = Add<HConstant>(i);
5758
5759     switch (boilerplate_elements_kind) {
5760       case FAST_SMI_ELEMENTS:
5761       case FAST_HOLEY_SMI_ELEMENTS:
5762       case FAST_ELEMENTS:
5763       case FAST_HOLEY_ELEMENTS:
5764       case FAST_DOUBLE_ELEMENTS:
5765       case FAST_HOLEY_DOUBLE_ELEMENTS: {
5766         HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value,
5767                                               boilerplate_elements_kind);
5768         instr->SetUninitialized(uninitialized);
5769         break;
5770       }
5771       default:
5772         UNREACHABLE();
5773         break;
5774     }
5775
5776     Add<HSimulate>(expr->GetIdForElement(i));
5777   }
5778
5779   Drop(1);  // array literal index
5780   return ast_context()->ReturnValue(Pop());
5781 }
5782
5783
5784 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object,
5785                                                 Handle<Map> map) {
5786   BuildCheckHeapObject(object);
5787   return Add<HCheckMaps>(object, map);
5788 }
5789
5790
5791 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField(
5792     PropertyAccessInfo* info,
5793     HValue* checked_object) {
5794   // See if this is a load for an immutable property
5795   if (checked_object->ActualValue()->IsConstant() && info->IsCacheable() &&
5796       info->IsReadOnly() && !info->IsConfigurable()) {
5797     Handle<Object> object(
5798         HConstant::cast(checked_object->ActualValue())->handle(isolate()));
5799
5800     if (object->IsJSObject()) {
5801       LookupIterator it(object, info->name(), LookupIterator::CHECK_PROPERTY);
5802       Handle<Object> value = JSObject::GetDataProperty(&it);
5803       CHECK(it.IsFound());
5804       return New<HConstant>(value);
5805     }
5806   }
5807
5808   HObjectAccess access = info->access();
5809   if (access.representation().IsDouble()) {
5810     // Load the heap number.
5811     checked_object = Add<HLoadNamedField>(
5812         checked_object, static_cast<HValue*>(NULL),
5813         access.WithRepresentation(Representation::Tagged()));
5814     // Load the double value from it.
5815     access = HObjectAccess::ForHeapNumberValue();
5816   }
5817
5818   SmallMapList* map_list = info->field_maps();
5819   if (map_list->length() == 0) {
5820     return New<HLoadNamedField>(checked_object, checked_object, access);
5821   }
5822
5823   UniqueSet<Map>* maps = new(zone()) UniqueSet<Map>(map_list->length(), zone());
5824   for (int i = 0; i < map_list->length(); ++i) {
5825     maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone());
5826   }
5827   return New<HLoadNamedField>(
5828       checked_object, checked_object, access, maps, info->field_type());
5829 }
5830
5831
5832 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
5833     PropertyAccessInfo* info,
5834     HValue* checked_object,
5835     HValue* value) {
5836   bool transition_to_field = info->IsTransition();
5837   // TODO(verwaest): Move this logic into PropertyAccessInfo.
5838   HObjectAccess field_access = info->access();
5839
5840   HStoreNamedField *instr;
5841   if (field_access.representation().IsDouble()) {
5842     HObjectAccess heap_number_access =
5843         field_access.WithRepresentation(Representation::Tagged());
5844     if (transition_to_field) {
5845       // The store requires a mutable HeapNumber to be allocated.
5846       NoObservableSideEffectsScope no_side_effects(this);
5847       HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
5848
5849       // TODO(hpayer): Allocation site pretenuring support.
5850       HInstruction* heap_number = Add<HAllocate>(heap_number_size,
5851           HType::HeapObject(),
5852           NOT_TENURED,
5853           MUTABLE_HEAP_NUMBER_TYPE);
5854       AddStoreMapConstant(
5855           heap_number, isolate()->factory()->mutable_heap_number_map());
5856       Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
5857                             value);
5858       instr = New<HStoreNamedField>(checked_object->ActualValue(),
5859                                     heap_number_access,
5860                                     heap_number);
5861     } else {
5862       // Already holds a HeapNumber; load the box and write its value field.
5863       HInstruction* heap_number = Add<HLoadNamedField>(
5864           checked_object, static_cast<HValue*>(NULL), heap_number_access);
5865       instr = New<HStoreNamedField>(heap_number,
5866                                     HObjectAccess::ForHeapNumberValue(),
5867                                     value, STORE_TO_INITIALIZED_ENTRY);
5868     }
5869   } else {
5870     if (field_access.representation().IsHeapObject()) {
5871       BuildCheckHeapObject(value);
5872     }
5873
5874     if (!info->field_maps()->is_empty()) {
5875       DCHECK(field_access.representation().IsHeapObject());
5876       value = Add<HCheckMaps>(value, info->field_maps());
5877     }
5878
5879     // This is a normal store.
5880     instr = New<HStoreNamedField>(
5881         checked_object->ActualValue(), field_access, value,
5882         transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY);
5883   }
5884
5885   if (transition_to_field) {
5886     Handle<Map> transition(info->transition());
5887     DCHECK(!transition->is_deprecated());
5888     instr->SetTransition(Add<HConstant>(transition));
5889   }
5890   return instr;
5891 }
5892
5893
5894 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible(
5895     PropertyAccessInfo* info) {
5896   if (!CanInlinePropertyAccess(type_)) return false;
5897
5898   // Currently only handle Type::Number as a polymorphic case.
5899   // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
5900   // instruction.
5901   if (type_->Is(Type::Number())) return false;
5902
5903   // Values are only compatible for monomorphic load if they all behave the same
5904   // regarding value wrappers.
5905   if (type_->Is(Type::NumberOrString())) {
5906     if (!info->type_->Is(Type::NumberOrString())) return false;
5907   } else {
5908     if (info->type_->Is(Type::NumberOrString())) return false;
5909   }
5910
5911   if (!LookupDescriptor()) return false;
5912
5913   if (!IsFound()) {
5914     return (!info->IsFound() || info->has_holder()) &&
5915            map()->prototype() == info->map()->prototype();
5916   }
5917
5918   // Mismatch if the other access info found the property in the prototype
5919   // chain.
5920   if (info->has_holder()) return false;
5921
5922   if (IsAccessor()) {
5923     return accessor_.is_identical_to(info->accessor_) &&
5924         api_holder_.is_identical_to(info->api_holder_);
5925   }
5926
5927   if (IsConstant()) {
5928     return constant_.is_identical_to(info->constant_);
5929   }
5930
5931   DCHECK(IsField());
5932   if (!info->IsField()) return false;
5933
5934   Representation r = access_.representation();
5935   if (IsLoad()) {
5936     if (!info->access_.representation().IsCompatibleForLoad(r)) return false;
5937   } else {
5938     if (!info->access_.representation().IsCompatibleForStore(r)) return false;
5939   }
5940   if (info->access_.offset() != access_.offset()) return false;
5941   if (info->access_.IsInobject() != access_.IsInobject()) return false;
5942   if (IsLoad()) {
5943     if (field_maps_.is_empty()) {
5944       info->field_maps_.Clear();
5945     } else if (!info->field_maps_.is_empty()) {
5946       for (int i = 0; i < field_maps_.length(); ++i) {
5947         info->field_maps_.AddMapIfMissing(field_maps_.at(i), info->zone());
5948       }
5949       info->field_maps_.Sort();
5950     }
5951   } else {
5952     // We can only merge stores that agree on their field maps. The comparison
5953     // below is safe, since we keep the field maps sorted.
5954     if (field_maps_.length() != info->field_maps_.length()) return false;
5955     for (int i = 0; i < field_maps_.length(); ++i) {
5956       if (!field_maps_.at(i).is_identical_to(info->field_maps_.at(i))) {
5957         return false;
5958       }
5959     }
5960   }
5961   info->GeneralizeRepresentation(r);
5962   info->field_type_ = info->field_type_.Combine(field_type_);
5963   return true;
5964 }
5965
5966
5967 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() {
5968   if (!type_->IsClass()) return true;
5969   map()->LookupDescriptor(NULL, *name_, &lookup_);
5970   return LoadResult(map());
5971 }
5972
5973
5974 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
5975   if (!IsLoad() && IsProperty() && (IsReadOnly() || !IsCacheable())) {
5976     return false;
5977   }
5978
5979   if (IsField()) {
5980     // Construct the object field access.
5981     int index = GetLocalFieldIndexFromMap(map);
5982     access_ = HObjectAccess::ForField(map, index, representation(), name_);
5983
5984     // Load field map for heap objects.
5985     LoadFieldMaps(map);
5986   } else if (IsAccessor()) {
5987     Handle<Object> accessors = GetAccessorsFromMap(map);
5988     if (!accessors->IsAccessorPair()) return false;
5989     Object* raw_accessor =
5990         IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter()
5991                  : Handle<AccessorPair>::cast(accessors)->setter();
5992     if (!raw_accessor->IsJSFunction()) return false;
5993     Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor));
5994     if (accessor->shared()->IsApiFunction()) {
5995       CallOptimization call_optimization(accessor);
5996       if (call_optimization.is_simple_api_call()) {
5997         CallOptimization::HolderLookup holder_lookup;
5998         Handle<Map> receiver_map = this->map();
5999         api_holder_ = call_optimization.LookupHolderOfExpectedType(
6000             receiver_map, &holder_lookup);
6001       }
6002     }
6003     accessor_ = accessor;
6004   } else if (IsConstant()) {
6005     constant_ = GetConstantFromMap(map);
6006   }
6007
6008   return true;
6009 }
6010
6011
6012 void HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps(
6013     Handle<Map> map) {
6014   // Clear any previously collected field maps/type.
6015   field_maps_.Clear();
6016   field_type_ = HType::Tagged();
6017
6018   // Figure out the field type from the accessor map.
6019   Handle<HeapType> field_type = GetFieldTypeFromMap(map);
6020
6021   // Collect the (stable) maps from the field type.
6022   int num_field_maps = field_type->NumClasses();
6023   if (num_field_maps == 0) return;
6024   DCHECK(access_.representation().IsHeapObject());
6025   field_maps_.Reserve(num_field_maps, zone());
6026   HeapType::Iterator<Map> it = field_type->Classes();
6027   while (!it.Done()) {
6028     Handle<Map> field_map = it.Current();
6029     if (!field_map->is_stable()) {
6030       field_maps_.Clear();
6031       return;
6032     }
6033     field_maps_.Add(field_map, zone());
6034     it.Advance();
6035   }
6036   field_maps_.Sort();
6037   DCHECK_EQ(num_field_maps, field_maps_.length());
6038
6039   // Determine field HType from field HeapType.
6040   field_type_ = HType::FromType<HeapType>(field_type);
6041   DCHECK(field_type_.IsHeapObject());
6042
6043   // Add dependency on the map that introduced the field.
6044   Map::AddDependentCompilationInfo(GetFieldOwnerFromMap(map),
6045                                    DependentCode::kFieldTypeGroup, top_info());
6046 }
6047
6048
6049 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
6050   Handle<Map> map = this->map();
6051
6052   while (map->prototype()->IsJSObject()) {
6053     holder_ = handle(JSObject::cast(map->prototype()));
6054     if (holder_->map()->is_deprecated()) {
6055       JSObject::TryMigrateInstance(holder_);
6056     }
6057     map = Handle<Map>(holder_->map());
6058     if (!CanInlinePropertyAccess(ToType(map))) {
6059       lookup_.NotFound();
6060       return false;
6061     }
6062     map->LookupDescriptor(*holder_, *name_, &lookup_);
6063     if (IsFound()) return LoadResult(map);
6064   }
6065   lookup_.NotFound();
6066   return true;
6067 }
6068
6069
6070 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
6071   if (!CanInlinePropertyAccess(type_)) return false;
6072   if (IsJSObjectFieldAccessor()) return IsLoad();
6073   if (this->map()->function_with_prototype() &&
6074       !this->map()->has_non_instance_prototype() &&
6075       name_.is_identical_to(isolate()->factory()->prototype_string())) {
6076     return IsLoad();
6077   }
6078   if (!LookupDescriptor()) return false;
6079   if (IsFound()) {
6080     if (IsLoad()) return true;
6081     return !IsReadOnly() && IsCacheable();
6082   }
6083   if (!LookupInPrototypes()) return false;
6084   if (IsLoad()) return true;
6085
6086   if (IsAccessor()) return true;
6087   Handle<Map> map = this->map();
6088   map->LookupTransition(NULL, *name_, &lookup_);
6089   if (lookup_.IsTransitionToField() && map->unused_property_fields() > 0) {
6090     // Construct the object field access.
6091     int descriptor = transition()->LastAdded();
6092     int index =
6093         transition()->instance_descriptors()->GetFieldIndex(descriptor) -
6094         map->inobject_properties();
6095     PropertyDetails details =
6096         transition()->instance_descriptors()->GetDetails(descriptor);
6097     Representation representation = details.representation();
6098     access_ = HObjectAccess::ForField(map, index, representation, name_);
6099
6100     // Load field map for heap objects.
6101     LoadFieldMaps(transition());
6102     return true;
6103   }
6104   return false;
6105 }
6106
6107
6108 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic(
6109     SmallMapList* types) {
6110   DCHECK(type_->Is(ToType(types->first())));
6111   if (!CanAccessMonomorphic()) return false;
6112   STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
6113   if (types->length() > kMaxLoadPolymorphism) return false;
6114
6115   HObjectAccess access = HObjectAccess::ForMap();  // bogus default
6116   if (GetJSObjectFieldAccess(&access)) {
6117     for (int i = 1; i < types->length(); ++i) {
6118       PropertyAccessInfo test_info(
6119           builder_, access_type_, ToType(types->at(i)), name_);
6120       HObjectAccess test_access = HObjectAccess::ForMap();  // bogus default
6121       if (!test_info.GetJSObjectFieldAccess(&test_access)) return false;
6122       if (!access.Equals(test_access)) return false;
6123     }
6124     return true;
6125   }
6126
6127   // Currently only handle Type::Number as a polymorphic case.
6128   // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
6129   // instruction.
6130   if (type_->Is(Type::Number())) return false;
6131
6132   // Multiple maps cannot transition to the same target map.
6133   DCHECK(!IsLoad() || !IsTransition());
6134   if (IsTransition() && types->length() > 1) return false;
6135
6136   for (int i = 1; i < types->length(); ++i) {
6137     PropertyAccessInfo test_info(
6138         builder_, access_type_, ToType(types->at(i)), name_);
6139     if (!test_info.IsCompatible(this)) return false;
6140   }
6141
6142   return true;
6143 }
6144
6145
6146 Handle<Map> HOptimizedGraphBuilder::PropertyAccessInfo::map() {
6147   JSFunction* ctor = IC::GetRootConstructor(
6148       type_, current_info()->closure()->context()->native_context());
6149   if (ctor != NULL) return handle(ctor->initial_map());
6150   return type_->AsClass()->Map();
6151 }
6152
6153
6154 static bool NeedsWrappingFor(Type* type, Handle<JSFunction> target) {
6155   return type->Is(Type::NumberOrString()) &&
6156       target->shared()->strict_mode() == SLOPPY &&
6157       !target->shared()->native();
6158 }
6159
6160
6161 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess(
6162     PropertyAccessInfo* info,
6163     HValue* object,
6164     HValue* checked_object,
6165     HValue* value,
6166     BailoutId ast_id,
6167     BailoutId return_id,
6168     bool can_inline_accessor) {
6169
6170   HObjectAccess access = HObjectAccess::ForMap();  // bogus default
6171   if (info->GetJSObjectFieldAccess(&access)) {
6172     DCHECK(info->IsLoad());
6173     return New<HLoadNamedField>(object, checked_object, access);
6174   }
6175
6176   if (info->name().is_identical_to(isolate()->factory()->prototype_string()) &&
6177       info->map()->function_with_prototype()) {
6178     DCHECK(!info->map()->has_non_instance_prototype());
6179     return New<HLoadFunctionPrototype>(checked_object);
6180   }
6181
6182   HValue* checked_holder = checked_object;
6183   if (info->has_holder()) {
6184     Handle<JSObject> prototype(JSObject::cast(info->map()->prototype()));
6185     checked_holder = BuildCheckPrototypeMaps(prototype, info->holder());
6186   }
6187
6188   if (!info->IsFound()) {
6189     DCHECK(info->IsLoad());
6190     return graph()->GetConstantUndefined();
6191   }
6192
6193   if (info->IsField()) {
6194     if (info->IsLoad()) {
6195       return BuildLoadNamedField(info, checked_holder);
6196     } else {
6197       return BuildStoreNamedField(info, checked_object, value);
6198     }
6199   }
6200
6201   if (info->IsTransition()) {
6202     DCHECK(!info->IsLoad());
6203     return BuildStoreNamedField(info, checked_object, value);
6204   }
6205
6206   if (info->IsAccessor()) {
6207     Push(checked_object);
6208     int argument_count = 1;
6209     if (!info->IsLoad()) {
6210       argument_count = 2;
6211       Push(value);
6212     }
6213
6214     if (NeedsWrappingFor(info->type(), info->accessor())) {
6215       HValue* function = Add<HConstant>(info->accessor());
6216       PushArgumentsFromEnvironment(argument_count);
6217       return New<HCallFunction>(function, argument_count, WRAP_AND_CALL);
6218     } else if (FLAG_inline_accessors && can_inline_accessor) {
6219       bool success = info->IsLoad()
6220           ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id)
6221           : TryInlineSetter(
6222               info->accessor(), info->map(), ast_id, return_id, value);
6223       if (success || HasStackOverflow()) return NULL;
6224     }
6225
6226     PushArgumentsFromEnvironment(argument_count);
6227     return BuildCallConstantFunction(info->accessor(), argument_count);
6228   }
6229
6230   DCHECK(info->IsConstant());
6231   if (info->IsLoad()) {
6232     return New<HConstant>(info->constant());
6233   } else {
6234     return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant()));
6235   }
6236 }
6237
6238
6239 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
6240     PropertyAccessType access_type,
6241     Expression* expr,
6242     BailoutId ast_id,
6243     BailoutId return_id,
6244     HValue* object,
6245     HValue* value,
6246     SmallMapList* types,
6247     Handle<String> name) {
6248   // Something did not match; must use a polymorphic load.
6249   int count = 0;
6250   HBasicBlock* join = NULL;
6251   HBasicBlock* number_block = NULL;
6252   bool handled_string = false;
6253
6254   bool handle_smi = false;
6255   STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
6256   for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
6257     PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name);
6258     if (info.type()->Is(Type::String())) {
6259       if (handled_string) continue;
6260       handled_string = true;
6261     }
6262     if (info.CanAccessMonomorphic()) {
6263       count++;
6264       if (info.type()->Is(Type::Number())) {
6265         handle_smi = true;
6266         break;
6267       }
6268     }
6269   }
6270
6271   count = 0;
6272   HControlInstruction* smi_check = NULL;
6273   handled_string = false;
6274
6275   for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
6276     PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name);
6277     if (info.type()->Is(Type::String())) {
6278       if (handled_string) continue;
6279       handled_string = true;
6280     }
6281     if (!info.CanAccessMonomorphic()) continue;
6282
6283     if (count == 0) {
6284       join = graph()->CreateBasicBlock();
6285       if (handle_smi) {
6286         HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
6287         HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
6288         number_block = graph()->CreateBasicBlock();
6289         smi_check = New<HIsSmiAndBranch>(
6290             object, empty_smi_block, not_smi_block);
6291         FinishCurrentBlock(smi_check);
6292         GotoNoSimulate(empty_smi_block, number_block);
6293         set_current_block(not_smi_block);
6294       } else {
6295         BuildCheckHeapObject(object);
6296       }
6297     }
6298     ++count;
6299     HBasicBlock* if_true = graph()->CreateBasicBlock();
6300     HBasicBlock* if_false = graph()->CreateBasicBlock();
6301     HUnaryControlInstruction* compare;
6302
6303     HValue* dependency;
6304     if (info.type()->Is(Type::Number())) {
6305       Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
6306       compare = New<HCompareMap>(object, heap_number_map, if_true, if_false);
6307       dependency = smi_check;
6308     } else if (info.type()->Is(Type::String())) {
6309       compare = New<HIsStringAndBranch>(object, if_true, if_false);
6310       dependency = compare;
6311     } else {
6312       compare = New<HCompareMap>(object, info.map(), if_true, if_false);
6313       dependency = compare;
6314     }
6315     FinishCurrentBlock(compare);
6316
6317     if (info.type()->Is(Type::Number())) {
6318       GotoNoSimulate(if_true, number_block);
6319       if_true = number_block;
6320     }
6321
6322     set_current_block(if_true);
6323
6324     HInstruction* access = BuildMonomorphicAccess(
6325         &info, object, dependency, value, ast_id,
6326         return_id, FLAG_polymorphic_inlining);
6327
6328     HValue* result = NULL;
6329     switch (access_type) {
6330       case LOAD:
6331         result = access;
6332         break;
6333       case STORE:
6334         result = value;
6335         break;
6336     }
6337
6338     if (access == NULL) {
6339       if (HasStackOverflow()) return;
6340     } else {
6341       if (!access->IsLinked()) AddInstruction(access);
6342       if (!ast_context()->IsEffect()) Push(result);
6343     }
6344
6345     if (current_block() != NULL) Goto(join);
6346     set_current_block(if_false);
6347   }
6348
6349   // Finish up.  Unconditionally deoptimize if we've handled all the maps we
6350   // know about and do not want to handle ones we've never seen.  Otherwise
6351   // use a generic IC.
6352   if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
6353     FinishExitWithHardDeoptimization("Uknown map in polymorphic access");
6354   } else {
6355     HInstruction* instr = BuildNamedGeneric(access_type, expr, object, name,
6356                                             value);
6357     AddInstruction(instr);
6358     if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value);
6359
6360     if (join != NULL) {
6361       Goto(join);
6362     } else {
6363       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6364       if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
6365       return;
6366     }
6367   }
6368
6369   DCHECK(join != NULL);
6370   if (join->HasPredecessor()) {
6371     join->SetJoinId(ast_id);
6372     set_current_block(join);
6373     if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
6374   } else {
6375     set_current_block(NULL);
6376   }
6377 }
6378
6379
6380 static bool ComputeReceiverTypes(Expression* expr,
6381                                  HValue* receiver,
6382                                  SmallMapList** t,
6383                                  Zone* zone) {
6384   SmallMapList* types = expr->GetReceiverTypes();
6385   *t = types;
6386   bool monomorphic = expr->IsMonomorphic();
6387   if (types != NULL && receiver->HasMonomorphicJSObjectType()) {
6388     Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
6389     types->FilterForPossibleTransitions(root_map);
6390     monomorphic = types->length() == 1;
6391   }
6392   return monomorphic && CanInlinePropertyAccess(
6393       IC::MapToType<Type>(types->first(), zone));
6394 }
6395
6396
6397 static bool AreStringTypes(SmallMapList* types) {
6398   for (int i = 0; i < types->length(); i++) {
6399     if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
6400   }
6401   return true;
6402 }
6403
6404
6405 void HOptimizedGraphBuilder::BuildStore(Expression* expr,
6406                                         Property* prop,
6407                                         BailoutId ast_id,
6408                                         BailoutId return_id,
6409                                         bool is_uninitialized) {
6410   if (!prop->key()->IsPropertyName()) {
6411     // Keyed store.
6412     HValue* value = environment()->ExpressionStackAt(0);
6413     HValue* key = environment()->ExpressionStackAt(1);
6414     HValue* object = environment()->ExpressionStackAt(2);
6415     bool has_side_effects = false;
6416     HandleKeyedElementAccess(object, key, value, expr,
6417                              STORE, &has_side_effects);
6418     Drop(3);
6419     Push(value);
6420     Add<HSimulate>(return_id, REMOVABLE_SIMULATE);
6421     return ast_context()->ReturnValue(Pop());
6422   }
6423
6424   // Named store.
6425   HValue* value = Pop();
6426   HValue* object = Pop();
6427
6428   Literal* key = prop->key()->AsLiteral();
6429   Handle<String> name = Handle<String>::cast(key->value());
6430   DCHECK(!name.is_null());
6431
6432   HInstruction* instr = BuildNamedAccess(STORE, ast_id, return_id, expr,
6433                                          object, name, value, is_uninitialized);
6434   if (instr == NULL) return;
6435
6436   if (!ast_context()->IsEffect()) Push(value);
6437   AddInstruction(instr);
6438   if (instr->HasObservableSideEffects()) {
6439     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6440   }
6441   if (!ast_context()->IsEffect()) Drop(1);
6442   return ast_context()->ReturnValue(value);
6443 }
6444
6445
6446 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
6447   Property* prop = expr->target()->AsProperty();
6448   DCHECK(prop != NULL);
6449   CHECK_ALIVE(VisitForValue(prop->obj()));
6450   if (!prop->key()->IsPropertyName()) {
6451     CHECK_ALIVE(VisitForValue(prop->key()));
6452   }
6453   CHECK_ALIVE(VisitForValue(expr->value()));
6454   BuildStore(expr, prop, expr->id(),
6455              expr->AssignmentId(), expr->IsUninitialized());
6456 }
6457
6458
6459 // Because not every expression has a position and there is not common
6460 // superclass of Assignment and CountOperation, we cannot just pass the
6461 // owning expression instead of position and ast_id separately.
6462 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
6463     Variable* var,
6464     HValue* value,
6465     BailoutId ast_id) {
6466   Handle<GlobalObject> global(current_info()->global_object());
6467   LookupIterator it(global, var->name(), LookupIterator::CHECK_PROPERTY);
6468   GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE);
6469   if (type == kUseCell) {
6470     Handle<PropertyCell> cell = it.GetPropertyCell();
6471     if (cell->type()->IsConstant()) {
6472       Handle<Object> constant = cell->type()->AsConstant()->Value();
6473       if (value->IsConstant()) {
6474         HConstant* c_value = HConstant::cast(value);
6475         if (!constant.is_identical_to(c_value->handle(isolate()))) {
6476           Add<HDeoptimize>("Constant global variable assignment",
6477                            Deoptimizer::EAGER);
6478         }
6479       } else {
6480         HValue* c_constant = Add<HConstant>(constant);
6481         IfBuilder builder(this);
6482         if (constant->IsNumber()) {
6483           builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ);
6484         } else {
6485           builder.If<HCompareObjectEqAndBranch>(value, c_constant);
6486         }
6487         builder.Then();
6488         builder.Else();
6489         Add<HDeoptimize>("Constant global variable assignment",
6490                          Deoptimizer::EAGER);
6491         builder.End();
6492       }
6493     }
6494     HInstruction* instr =
6495         Add<HStoreGlobalCell>(value, cell, it.property_details());
6496     if (instr->HasObservableSideEffects()) {
6497       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6498     }
6499   } else {
6500     HValue* global_object = Add<HLoadNamedField>(
6501         context(), static_cast<HValue*>(NULL),
6502         HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
6503     HStoreNamedGeneric* instr =
6504         Add<HStoreNamedGeneric>(global_object, var->name(),
6505                                  value, function_strict_mode());
6506     USE(instr);
6507     DCHECK(instr->HasObservableSideEffects());
6508     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6509   }
6510 }
6511
6512
6513 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
6514   Expression* target = expr->target();
6515   VariableProxy* proxy = target->AsVariableProxy();
6516   Property* prop = target->AsProperty();
6517   DCHECK(proxy == NULL || prop == NULL);
6518
6519   // We have a second position recorded in the FullCodeGenerator to have
6520   // type feedback for the binary operation.
6521   BinaryOperation* operation = expr->binary_operation();
6522
6523   if (proxy != NULL) {
6524     Variable* var = proxy->var();
6525     if (var->mode() == LET)  {
6526       return Bailout(kUnsupportedLetCompoundAssignment);
6527     }
6528
6529     CHECK_ALIVE(VisitForValue(operation));
6530
6531     switch (var->location()) {
6532       case Variable::UNALLOCATED:
6533         HandleGlobalVariableAssignment(var,
6534                                        Top(),
6535                                        expr->AssignmentId());
6536         break;
6537
6538       case Variable::PARAMETER:
6539       case Variable::LOCAL:
6540         if (var->mode() == CONST_LEGACY)  {
6541           return Bailout(kUnsupportedConstCompoundAssignment);
6542         }
6543         BindIfLive(var, Top());
6544         break;
6545
6546       case Variable::CONTEXT: {
6547         // Bail out if we try to mutate a parameter value in a function
6548         // using the arguments object.  We do not (yet) correctly handle the
6549         // arguments property of the function.
6550         if (current_info()->scope()->arguments() != NULL) {
6551           // Parameters will be allocated to context slots.  We have no
6552           // direct way to detect that the variable is a parameter so we do
6553           // a linear search of the parameter variables.
6554           int count = current_info()->scope()->num_parameters();
6555           for (int i = 0; i < count; ++i) {
6556             if (var == current_info()->scope()->parameter(i)) {
6557               Bailout(kAssignmentToParameterFunctionUsesArgumentsObject);
6558             }
6559           }
6560         }
6561
6562         HStoreContextSlot::Mode mode;
6563
6564         switch (var->mode()) {
6565           case LET:
6566             mode = HStoreContextSlot::kCheckDeoptimize;
6567             break;
6568           case CONST:
6569             // This case is checked statically so no need to
6570             // perform checks here
6571             UNREACHABLE();
6572           case CONST_LEGACY:
6573             return ast_context()->ReturnValue(Pop());
6574           default:
6575             mode = HStoreContextSlot::kNoCheck;
6576         }
6577
6578         HValue* context = BuildContextChainWalk(var);
6579         HStoreContextSlot* instr = Add<HStoreContextSlot>(
6580             context, var->index(), mode, Top());
6581         if (instr->HasObservableSideEffects()) {
6582           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
6583         }
6584         break;
6585       }
6586
6587       case Variable::LOOKUP:
6588         return Bailout(kCompoundAssignmentToLookupSlot);
6589     }
6590     return ast_context()->ReturnValue(Pop());
6591
6592   } else if (prop != NULL) {
6593     CHECK_ALIVE(VisitForValue(prop->obj()));
6594     HValue* object = Top();
6595     HValue* key = NULL;
6596     if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
6597       CHECK_ALIVE(VisitForValue(prop->key()));
6598       key = Top();
6599     }
6600
6601     CHECK_ALIVE(PushLoad(prop, object, key));
6602
6603     CHECK_ALIVE(VisitForValue(expr->value()));
6604     HValue* right = Pop();
6605     HValue* left = Pop();
6606
6607     Push(BuildBinaryOperation(operation, left, right, PUSH_BEFORE_SIMULATE));
6608
6609     BuildStore(expr, prop, expr->id(),
6610                expr->AssignmentId(), expr->IsUninitialized());
6611   } else {
6612     return Bailout(kInvalidLhsInCompoundAssignment);
6613   }
6614 }
6615
6616
6617 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
6618   DCHECK(!HasStackOverflow());
6619   DCHECK(current_block() != NULL);
6620   DCHECK(current_block()->HasPredecessor());
6621   VariableProxy* proxy = expr->target()->AsVariableProxy();
6622   Property* prop = expr->target()->AsProperty();
6623   DCHECK(proxy == NULL || prop == NULL);
6624
6625   if (expr->is_compound()) {
6626     HandleCompoundAssignment(expr);
6627     return;
6628   }
6629
6630   if (prop != NULL) {
6631     HandlePropertyAssignment(expr);
6632   } else if (proxy != NULL) {
6633     Variable* var = proxy->var();
6634
6635     if (var->mode() == CONST) {
6636       if (expr->op() != Token::INIT_CONST) {
6637         return Bailout(kNonInitializerAssignmentToConst);
6638       }
6639     } else if (var->mode() == CONST_LEGACY) {
6640       if (expr->op() != Token::INIT_CONST_LEGACY) {
6641         CHECK_ALIVE(VisitForValue(expr->value()));
6642         return ast_context()->ReturnValue(Pop());
6643       }
6644
6645       if (var->IsStackAllocated()) {
6646         // We insert a use of the old value to detect unsupported uses of const
6647         // variables (e.g. initialization inside a loop).
6648         HValue* old_value = environment()->Lookup(var);
6649         Add<HUseConst>(old_value);
6650       }
6651     }
6652
6653     if (proxy->IsArguments()) return Bailout(kAssignmentToArguments);
6654
6655     // Handle the assignment.
6656     switch (var->location()) {
6657       case Variable::UNALLOCATED:
6658         CHECK_ALIVE(VisitForValue(expr->value()));
6659         HandleGlobalVariableAssignment(var,
6660                                        Top(),
6661                                        expr->AssignmentId());
6662         return ast_context()->ReturnValue(Pop());
6663
6664       case Variable::PARAMETER:
6665       case Variable::LOCAL: {
6666         // Perform an initialization check for let declared variables
6667         // or parameters.
6668         if (var->mode() == LET && expr->op() == Token::ASSIGN) {
6669           HValue* env_value = environment()->Lookup(var);
6670           if (env_value == graph()->GetConstantHole()) {
6671             return Bailout(kAssignmentToLetVariableBeforeInitialization);
6672           }
6673         }
6674         // We do not allow the arguments object to occur in a context where it
6675         // may escape, but assignments to stack-allocated locals are
6676         // permitted.
6677         CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
6678         HValue* value = Pop();
6679         BindIfLive(var, value);
6680         return ast_context()->ReturnValue(value);
6681       }
6682
6683       case Variable::CONTEXT: {
6684         // Bail out if we try to mutate a parameter value in a function using
6685         // the arguments object.  We do not (yet) correctly handle the
6686         // arguments property of the function.
6687         if (current_info()->scope()->arguments() != NULL) {
6688           // Parameters will rewrite to context slots.  We have no direct way
6689           // to detect that the variable is a parameter.
6690           int count = current_info()->scope()->num_parameters();
6691           for (int i = 0; i < count; ++i) {
6692             if (var == current_info()->scope()->parameter(i)) {
6693               return Bailout(kAssignmentToParameterInArgumentsObject);
6694             }
6695           }
6696         }
6697
6698         CHECK_ALIVE(VisitForValue(expr->value()));
6699         HStoreContextSlot::Mode mode;
6700         if (expr->op() == Token::ASSIGN) {
6701           switch (var->mode()) {
6702             case LET:
6703               mode = HStoreContextSlot::kCheckDeoptimize;
6704               break;
6705             case CONST:
6706               // This case is checked statically so no need to
6707               // perform checks here
6708               UNREACHABLE();
6709             case CONST_LEGACY:
6710               return ast_context()->ReturnValue(Pop());
6711             default:
6712               mode = HStoreContextSlot::kNoCheck;
6713           }
6714         } else if (expr->op() == Token::INIT_VAR ||
6715                    expr->op() == Token::INIT_LET ||
6716                    expr->op() == Token::INIT_CONST) {
6717           mode = HStoreContextSlot::kNoCheck;
6718         } else {
6719           DCHECK(expr->op() == Token::INIT_CONST_LEGACY);
6720
6721           mode = HStoreContextSlot::kCheckIgnoreAssignment;
6722         }
6723
6724         HValue* context = BuildContextChainWalk(var);
6725         HStoreContextSlot* instr = Add<HStoreContextSlot>(
6726             context, var->index(), mode, Top());
6727         if (instr->HasObservableSideEffects()) {
6728           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
6729         }
6730         return ast_context()->ReturnValue(Pop());
6731       }
6732
6733       case Variable::LOOKUP:
6734         return Bailout(kAssignmentToLOOKUPVariable);
6735     }
6736   } else {
6737     return Bailout(kInvalidLeftHandSideInAssignment);
6738   }
6739 }
6740
6741
6742 void HOptimizedGraphBuilder::VisitYield(Yield* expr) {
6743   // Generators are not optimized, so we should never get here.
6744   UNREACHABLE();
6745 }
6746
6747
6748 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
6749   DCHECK(!HasStackOverflow());
6750   DCHECK(current_block() != NULL);
6751   DCHECK(current_block()->HasPredecessor());
6752   // We don't optimize functions with invalid left-hand sides in
6753   // assignments, count operations, or for-in.  Consequently throw can
6754   // currently only occur in an effect context.
6755   DCHECK(ast_context()->IsEffect());
6756   CHECK_ALIVE(VisitForValue(expr->exception()));
6757
6758   HValue* value = environment()->Pop();
6759   if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
6760   Add<HPushArguments>(value);
6761   Add<HCallRuntime>(isolate()->factory()->empty_string(),
6762                     Runtime::FunctionForId(Runtime::kThrow), 1);
6763   Add<HSimulate>(expr->id());
6764
6765   // If the throw definitely exits the function, we can finish with a dummy
6766   // control flow at this point.  This is not the case if the throw is inside
6767   // an inlined function which may be replaced.
6768   if (call_context() == NULL) {
6769     FinishExitCurrentBlock(New<HAbnormalExit>());
6770   }
6771 }
6772
6773
6774 HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) {
6775   if (string->IsConstant()) {
6776     HConstant* c_string = HConstant::cast(string);
6777     if (c_string->HasStringValue()) {
6778       return Add<HConstant>(c_string->StringValue()->map()->instance_type());
6779     }
6780   }
6781   return Add<HLoadNamedField>(
6782       Add<HLoadNamedField>(string, static_cast<HValue*>(NULL),
6783                            HObjectAccess::ForMap()),
6784       static_cast<HValue*>(NULL), HObjectAccess::ForMapInstanceType());
6785 }
6786
6787
6788 HInstruction* HGraphBuilder::AddLoadStringLength(HValue* string) {
6789   if (string->IsConstant()) {
6790     HConstant* c_string = HConstant::cast(string);
6791     if (c_string->HasStringValue()) {
6792       return Add<HConstant>(c_string->StringValue()->length());
6793     }
6794   }
6795   return Add<HLoadNamedField>(string, static_cast<HValue*>(NULL),
6796                               HObjectAccess::ForStringLength());
6797 }
6798
6799
6800 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric(
6801     PropertyAccessType access_type,
6802     Expression* expr,
6803     HValue* object,
6804     Handle<String> name,
6805     HValue* value,
6806     bool is_uninitialized) {
6807   if (is_uninitialized) {
6808     Add<HDeoptimize>("Insufficient type feedback for generic named access",
6809                      Deoptimizer::SOFT);
6810   }
6811   if (access_type == LOAD) {
6812     HLoadNamedGeneric* result = New<HLoadNamedGeneric>(object, name);
6813     if (FLAG_vector_ics) {
6814       Handle<SharedFunctionInfo> current_shared =
6815           function_state()->compilation_info()->shared_info();
6816       result->SetVectorAndSlot(
6817           handle(current_shared->feedback_vector(), isolate()),
6818           expr->AsProperty()->PropertyFeedbackSlot());
6819     }
6820     return result;
6821   } else {
6822     return New<HStoreNamedGeneric>(object, name, value, function_strict_mode());
6823   }
6824 }
6825
6826
6827
6828 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric(
6829     PropertyAccessType access_type,
6830     Expression* expr,
6831     HValue* object,
6832     HValue* key,
6833     HValue* value) {
6834   if (access_type == LOAD) {
6835     HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(object, key);
6836     if (FLAG_vector_ics) {
6837       Handle<SharedFunctionInfo> current_shared =
6838           function_state()->compilation_info()->shared_info();
6839       result->SetVectorAndSlot(
6840           handle(current_shared->feedback_vector(), isolate()),
6841           expr->AsProperty()->PropertyFeedbackSlot());
6842     }
6843     return result;
6844   } else {
6845     return New<HStoreKeyedGeneric>(object, key, value, function_strict_mode());
6846   }
6847 }
6848
6849
6850 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) {
6851   // Loads from a "stock" fast holey double arrays can elide the hole check.
6852   LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
6853   if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) &&
6854       isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
6855     Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
6856     Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
6857     BuildCheckPrototypeMaps(prototype, object_prototype);
6858     load_mode = ALLOW_RETURN_HOLE;
6859     graph()->MarkDependsOnEmptyArrayProtoElements();
6860   }
6861
6862   return load_mode;
6863 }
6864
6865
6866 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
6867     HValue* object,
6868     HValue* key,
6869     HValue* val,
6870     HValue* dependency,
6871     Handle<Map> map,
6872     PropertyAccessType access_type,
6873     KeyedAccessStoreMode store_mode) {
6874   HCheckMaps* checked_object = Add<HCheckMaps>(object, map, dependency);
6875   if (dependency) {
6876     checked_object->ClearDependsOnFlag(kElementsKind);
6877   }
6878
6879   if (access_type == STORE && map->prototype()->IsJSObject()) {
6880     // monomorphic stores need a prototype chain check because shape
6881     // changes could allow callbacks on elements in the chain that
6882     // aren't compatible with monomorphic keyed stores.
6883     PrototypeIterator iter(map);
6884     JSObject* holder = NULL;
6885     while (!iter.IsAtEnd()) {
6886       holder = JSObject::cast(*PrototypeIterator::GetCurrent(iter));
6887       iter.Advance();
6888     }
6889     DCHECK(holder && holder->IsJSObject());
6890
6891     BuildCheckPrototypeMaps(handle(JSObject::cast(map->prototype())),
6892                             Handle<JSObject>(holder));
6893   }
6894
6895   LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
6896   return BuildUncheckedMonomorphicElementAccess(
6897       checked_object, key, val,
6898       map->instance_type() == JS_ARRAY_TYPE,
6899       map->elements_kind(), access_type,
6900       load_mode, store_mode);
6901 }
6902
6903
6904 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
6905     HValue* object,
6906     HValue* key,
6907     HValue* val,
6908     SmallMapList* maps) {
6909   // For polymorphic loads of similar elements kinds (i.e. all tagged or all
6910   // double), always use the "worst case" code without a transition.  This is
6911   // much faster than transitioning the elements to the worst case, trading a
6912   // HTransitionElements for a HCheckMaps, and avoiding mutation of the array.
6913   bool has_double_maps = false;
6914   bool has_smi_or_object_maps = false;
6915   bool has_js_array_access = false;
6916   bool has_non_js_array_access = false;
6917   bool has_seen_holey_elements = false;
6918   Handle<Map> most_general_consolidated_map;
6919   for (int i = 0; i < maps->length(); ++i) {
6920     Handle<Map> map = maps->at(i);
6921     if (!map->IsJSObjectMap()) return NULL;
6922     // Don't allow mixing of JSArrays with JSObjects.
6923     if (map->instance_type() == JS_ARRAY_TYPE) {
6924       if (has_non_js_array_access) return NULL;
6925       has_js_array_access = true;
6926     } else if (has_js_array_access) {
6927       return NULL;
6928     } else {
6929       has_non_js_array_access = true;
6930     }
6931     // Don't allow mixed, incompatible elements kinds.
6932     if (map->has_fast_double_elements()) {
6933       if (has_smi_or_object_maps) return NULL;
6934       has_double_maps = true;
6935     } else if (map->has_fast_smi_or_object_elements()) {
6936       if (has_double_maps) return NULL;
6937       has_smi_or_object_maps = true;
6938     } else {
6939       return NULL;
6940     }
6941     // Remember if we've ever seen holey elements.
6942     if (IsHoleyElementsKind(map->elements_kind())) {
6943       has_seen_holey_elements = true;
6944     }
6945     // Remember the most general elements kind, the code for its load will
6946     // properly handle all of the more specific cases.
6947     if ((i == 0) || IsMoreGeneralElementsKindTransition(
6948             most_general_consolidated_map->elements_kind(),
6949             map->elements_kind())) {
6950       most_general_consolidated_map = map;
6951     }
6952   }
6953   if (!has_double_maps && !has_smi_or_object_maps) return NULL;
6954
6955   HCheckMaps* checked_object = Add<HCheckMaps>(object, maps);
6956   // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS.
6957   // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS.
6958   ElementsKind consolidated_elements_kind = has_seen_holey_elements
6959       ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind())
6960       : most_general_consolidated_map->elements_kind();
6961   HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
6962       checked_object, key, val,
6963       most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
6964       consolidated_elements_kind,
6965       LOAD, NEVER_RETURN_HOLE, STANDARD_STORE);
6966   return instr;
6967 }
6968
6969
6970 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
6971     Expression* expr,
6972     HValue* object,
6973     HValue* key,
6974     HValue* val,
6975     SmallMapList* maps,
6976     PropertyAccessType access_type,
6977     KeyedAccessStoreMode store_mode,
6978     bool* has_side_effects) {
6979   *has_side_effects = false;
6980   BuildCheckHeapObject(object);
6981
6982   if (access_type == LOAD) {
6983     HInstruction* consolidated_load =
6984         TryBuildConsolidatedElementLoad(object, key, val, maps);
6985     if (consolidated_load != NULL) {
6986       *has_side_effects |= consolidated_load->HasObservableSideEffects();
6987       return consolidated_load;
6988     }
6989   }
6990
6991   // Elements_kind transition support.
6992   MapHandleList transition_target(maps->length());
6993   // Collect possible transition targets.
6994   MapHandleList possible_transitioned_maps(maps->length());
6995   for (int i = 0; i < maps->length(); ++i) {
6996     Handle<Map> map = maps->at(i);
6997     ElementsKind elements_kind = map->elements_kind();
6998     if (IsFastElementsKind(elements_kind) &&
6999         elements_kind != GetInitialFastElementsKind()) {
7000       possible_transitioned_maps.Add(map);
7001     }
7002     if (elements_kind == SLOPPY_ARGUMENTS_ELEMENTS) {
7003       HInstruction* result = BuildKeyedGeneric(access_type, expr, object, key,
7004                                                val);
7005       *has_side_effects = result->HasObservableSideEffects();
7006       return AddInstruction(result);
7007     }
7008   }
7009   // Get transition target for each map (NULL == no transition).
7010   for (int i = 0; i < maps->length(); ++i) {
7011     Handle<Map> map = maps->at(i);
7012     Handle<Map> transitioned_map =
7013         map->FindTransitionedMap(&possible_transitioned_maps);
7014     transition_target.Add(transitioned_map);
7015   }
7016
7017   MapHandleList untransitionable_maps(maps->length());
7018   HTransitionElementsKind* transition = NULL;
7019   for (int i = 0; i < maps->length(); ++i) {
7020     Handle<Map> map = maps->at(i);
7021     DCHECK(map->IsMap());
7022     if (!transition_target.at(i).is_null()) {
7023       DCHECK(Map::IsValidElementsTransition(
7024           map->elements_kind(),
7025           transition_target.at(i)->elements_kind()));
7026       transition = Add<HTransitionElementsKind>(object, map,
7027                                                 transition_target.at(i));
7028     } else {
7029       untransitionable_maps.Add(map);
7030     }
7031   }
7032
7033   // If only one map is left after transitioning, handle this case
7034   // monomorphically.
7035   DCHECK(untransitionable_maps.length() >= 1);
7036   if (untransitionable_maps.length() == 1) {
7037     Handle<Map> untransitionable_map = untransitionable_maps[0];
7038     HInstruction* instr = NULL;
7039     if (untransitionable_map->has_slow_elements_kind() ||
7040         !untransitionable_map->IsJSObjectMap()) {
7041       instr = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key,
7042                                                val));
7043     } else {
7044       instr = BuildMonomorphicElementAccess(
7045           object, key, val, transition, untransitionable_map, access_type,
7046           store_mode);
7047     }
7048     *has_side_effects |= instr->HasObservableSideEffects();
7049     return access_type == STORE ? NULL : instr;
7050   }
7051
7052   HBasicBlock* join = graph()->CreateBasicBlock();
7053
7054   for (int i = 0; i < untransitionable_maps.length(); ++i) {
7055     Handle<Map> map = untransitionable_maps[i];
7056     if (!map->IsJSObjectMap()) continue;
7057     ElementsKind elements_kind = map->elements_kind();
7058     HBasicBlock* this_map = graph()->CreateBasicBlock();
7059     HBasicBlock* other_map = graph()->CreateBasicBlock();
7060     HCompareMap* mapcompare =
7061         New<HCompareMap>(object, map, this_map, other_map);
7062     FinishCurrentBlock(mapcompare);
7063
7064     set_current_block(this_map);
7065     HInstruction* access = NULL;
7066     if (IsDictionaryElementsKind(elements_kind)) {
7067       access = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key,
7068                                                 val));
7069     } else {
7070       DCHECK(IsFastElementsKind(elements_kind) ||
7071              IsExternalArrayElementsKind(elements_kind) ||
7072              IsFixedTypedArrayElementsKind(elements_kind));
7073       LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
7074       // Happily, mapcompare is a checked object.
7075       access = BuildUncheckedMonomorphicElementAccess(
7076           mapcompare, key, val,
7077           map->instance_type() == JS_ARRAY_TYPE,
7078           elements_kind, access_type,
7079           load_mode,
7080           store_mode);
7081     }
7082     *has_side_effects |= access->HasObservableSideEffects();
7083     // The caller will use has_side_effects and add a correct Simulate.
7084     access->SetFlag(HValue::kHasNoObservableSideEffects);
7085     if (access_type == LOAD) {
7086       Push(access);
7087     }
7088     NoObservableSideEffectsScope scope(this);
7089     GotoNoSimulate(join);
7090     set_current_block(other_map);
7091   }
7092
7093   // Ensure that we visited at least one map above that goes to join. This is
7094   // necessary because FinishExitWithHardDeoptimization does an AbnormalExit
7095   // rather than joining the join block. If this becomes an issue, insert a
7096   // generic access in the case length() == 0.
7097   DCHECK(join->predecessors()->length() > 0);
7098   // Deopt if none of the cases matched.
7099   NoObservableSideEffectsScope scope(this);
7100   FinishExitWithHardDeoptimization("Unknown map in polymorphic element access");
7101   set_current_block(join);
7102   return access_type == STORE ? NULL : Pop();
7103 }
7104
7105
7106 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
7107     HValue* obj,
7108     HValue* key,
7109     HValue* val,
7110     Expression* expr,
7111     PropertyAccessType access_type,
7112     bool* has_side_effects) {
7113   DCHECK(!expr->IsPropertyName());
7114   HInstruction* instr = NULL;
7115
7116   SmallMapList* types;
7117   bool monomorphic = ComputeReceiverTypes(expr, obj, &types, zone());
7118
7119   bool force_generic = false;
7120   if (access_type == STORE &&
7121       (monomorphic || (types != NULL && !types->is_empty()))) {
7122     // Stores can't be mono/polymorphic if their prototype chain has dictionary
7123     // elements. However a receiver map that has dictionary elements itself
7124     // should be left to normal mono/poly behavior (the other maps may benefit
7125     // from highly optimized stores).
7126     for (int i = 0; i < types->length(); i++) {
7127       Handle<Map> current_map = types->at(i);
7128       if (current_map->DictionaryElementsInPrototypeChainOnly()) {
7129         force_generic = true;
7130         monomorphic = false;
7131         break;
7132       }
7133     }
7134   }
7135
7136   if (monomorphic) {
7137     Handle<Map> map = types->first();
7138     if (map->has_slow_elements_kind() || !map->IsJSObjectMap()) {
7139       instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key,
7140                                                val));
7141     } else {
7142       BuildCheckHeapObject(obj);
7143       instr = BuildMonomorphicElementAccess(
7144           obj, key, val, NULL, map, access_type, expr->GetStoreMode());
7145     }
7146   } else if (!force_generic && (types != NULL && !types->is_empty())) {
7147     return HandlePolymorphicElementAccess(
7148         expr, obj, key, val, types, access_type,
7149         expr->GetStoreMode(), has_side_effects);
7150   } else {
7151     if (access_type == STORE) {
7152       if (expr->IsAssignment() &&
7153           expr->AsAssignment()->HasNoTypeInformation()) {
7154         Add<HDeoptimize>("Insufficient type feedback for keyed store",
7155                          Deoptimizer::SOFT);
7156       }
7157     } else {
7158       if (expr->AsProperty()->HasNoTypeInformation()) {
7159         Add<HDeoptimize>("Insufficient type feedback for keyed load",
7160                          Deoptimizer::SOFT);
7161       }
7162     }
7163     instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key, val));
7164   }
7165   *has_side_effects = instr->HasObservableSideEffects();
7166   return instr;
7167 }
7168
7169
7170 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() {
7171   // Outermost function already has arguments on the stack.
7172   if (function_state()->outer() == NULL) return;
7173
7174   if (function_state()->arguments_pushed()) return;
7175
7176   // Push arguments when entering inlined function.
7177   HEnterInlined* entry = function_state()->entry();
7178   entry->set_arguments_pushed();
7179
7180   HArgumentsObject* arguments = entry->arguments_object();
7181   const ZoneList<HValue*>* arguments_values = arguments->arguments_values();
7182
7183   HInstruction* insert_after = entry;
7184   for (int i = 0; i < arguments_values->length(); i++) {
7185     HValue* argument = arguments_values->at(i);
7186     HInstruction* push_argument = New<HPushArguments>(argument);
7187     push_argument->InsertAfter(insert_after);
7188     insert_after = push_argument;
7189   }
7190
7191   HArgumentsElements* arguments_elements = New<HArgumentsElements>(true);
7192   arguments_elements->ClearFlag(HValue::kUseGVN);
7193   arguments_elements->InsertAfter(insert_after);
7194   function_state()->set_arguments_elements(arguments_elements);
7195 }
7196
7197
7198 bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) {
7199   VariableProxy* proxy = expr->obj()->AsVariableProxy();
7200   if (proxy == NULL) return false;
7201   if (!proxy->var()->IsStackAllocated()) return false;
7202   if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
7203     return false;
7204   }
7205
7206   HInstruction* result = NULL;
7207   if (expr->key()->IsPropertyName()) {
7208     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
7209     if (!String::Equals(name, isolate()->factory()->length_string())) {
7210       return false;
7211     }
7212
7213     if (function_state()->outer() == NULL) {
7214       HInstruction* elements = Add<HArgumentsElements>(false);
7215       result = New<HArgumentsLength>(elements);
7216     } else {
7217       // Number of arguments without receiver.
7218       int argument_count = environment()->
7219           arguments_environment()->parameter_count() - 1;
7220       result = New<HConstant>(argument_count);
7221     }
7222   } else {
7223     Push(graph()->GetArgumentsObject());
7224     CHECK_ALIVE_OR_RETURN(VisitForValue(expr->key()), true);
7225     HValue* key = Pop();
7226     Drop(1);  // Arguments object.
7227     if (function_state()->outer() == NULL) {
7228       HInstruction* elements = Add<HArgumentsElements>(false);
7229       HInstruction* length = Add<HArgumentsLength>(elements);
7230       HInstruction* checked_key = Add<HBoundsCheck>(key, length);
7231       result = New<HAccessArgumentsAt>(elements, length, checked_key);
7232     } else {
7233       EnsureArgumentsArePushedForAccess();
7234
7235       // Number of arguments without receiver.
7236       HInstruction* elements = function_state()->arguments_elements();
7237       int argument_count = environment()->
7238           arguments_environment()->parameter_count() - 1;
7239       HInstruction* length = Add<HConstant>(argument_count);
7240       HInstruction* checked_key = Add<HBoundsCheck>(key, length);
7241       result = New<HAccessArgumentsAt>(elements, length, checked_key);
7242     }
7243   }
7244   ast_context()->ReturnInstruction(result, expr->id());
7245   return true;
7246 }
7247
7248
7249 HInstruction* HOptimizedGraphBuilder::BuildNamedAccess(
7250     PropertyAccessType access,
7251     BailoutId ast_id,
7252     BailoutId return_id,
7253     Expression* expr,
7254     HValue* object,
7255     Handle<String> name,
7256     HValue* value,
7257     bool is_uninitialized) {
7258   SmallMapList* types;
7259   ComputeReceiverTypes(expr, object, &types, zone());
7260   DCHECK(types != NULL);
7261
7262   if (types->length() > 0) {
7263     PropertyAccessInfo info(this, access, ToType(types->first()), name);
7264     if (!info.CanAccessAsMonomorphic(types)) {
7265       HandlePolymorphicNamedFieldAccess(
7266           access, expr, ast_id, return_id, object, value, types, name);
7267       return NULL;
7268     }
7269
7270     HValue* checked_object;
7271     // Type::Number() is only supported by polymorphic load/call handling.
7272     DCHECK(!info.type()->Is(Type::Number()));
7273     BuildCheckHeapObject(object);
7274     if (AreStringTypes(types)) {
7275       checked_object =
7276           Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
7277     } else {
7278       checked_object = Add<HCheckMaps>(object, types);
7279     }
7280     return BuildMonomorphicAccess(
7281         &info, object, checked_object, value, ast_id, return_id);
7282   }
7283
7284   return BuildNamedGeneric(access, expr, object, name, value, is_uninitialized);
7285 }
7286
7287
7288 void HOptimizedGraphBuilder::PushLoad(Property* expr,
7289                                       HValue* object,
7290                                       HValue* key) {
7291   ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
7292   Push(object);
7293   if (key != NULL) Push(key);
7294   BuildLoad(expr, expr->LoadId());
7295 }
7296
7297
7298 void HOptimizedGraphBuilder::BuildLoad(Property* expr,
7299                                        BailoutId ast_id) {
7300   HInstruction* instr = NULL;
7301   if (expr->IsStringAccess()) {
7302     HValue* index = Pop();
7303     HValue* string = Pop();
7304     HInstruction* char_code = BuildStringCharCodeAt(string, index);
7305     AddInstruction(char_code);
7306     instr = NewUncasted<HStringCharFromCode>(char_code);
7307
7308   } else if (expr->key()->IsPropertyName()) {
7309     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
7310     HValue* object = Pop();
7311
7312     instr = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr,
7313                              object, name, NULL, expr->IsUninitialized());
7314     if (instr == NULL) return;
7315     if (instr->IsLinked()) return ast_context()->ReturnValue(instr);
7316
7317   } else {
7318     HValue* key = Pop();
7319     HValue* obj = Pop();
7320
7321     bool has_side_effects = false;
7322     HValue* load = HandleKeyedElementAccess(
7323         obj, key, NULL, expr, LOAD, &has_side_effects);
7324     if (has_side_effects) {
7325       if (ast_context()->IsEffect()) {
7326         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
7327       } else {
7328         Push(load);
7329         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
7330         Drop(1);
7331       }
7332     }
7333     return ast_context()->ReturnValue(load);
7334   }
7335   return ast_context()->ReturnInstruction(instr, ast_id);
7336 }
7337
7338
7339 void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
7340   DCHECK(!HasStackOverflow());
7341   DCHECK(current_block() != NULL);
7342   DCHECK(current_block()->HasPredecessor());
7343
7344   if (TryArgumentsAccess(expr)) return;
7345
7346   CHECK_ALIVE(VisitForValue(expr->obj()));
7347   if (!expr->key()->IsPropertyName() || expr->IsStringAccess()) {
7348     CHECK_ALIVE(VisitForValue(expr->key()));
7349   }
7350
7351   BuildLoad(expr, expr->id());
7352 }
7353
7354
7355 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant) {
7356   HCheckMaps* check = Add<HCheckMaps>(
7357       Add<HConstant>(constant), handle(constant->map()));
7358   check->ClearDependsOnFlag(kElementsKind);
7359   return check;
7360 }
7361
7362
7363 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
7364                                                      Handle<JSObject> holder) {
7365   PrototypeIterator iter(isolate(), prototype,
7366                          PrototypeIterator::START_AT_RECEIVER);
7367   while (holder.is_null() ||
7368          !PrototypeIterator::GetCurrent(iter).is_identical_to(holder)) {
7369     BuildConstantMapCheck(
7370         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
7371     iter.Advance();
7372     if (iter.IsAtEnd()) {
7373       return NULL;
7374     }
7375   }
7376   return BuildConstantMapCheck(
7377       Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
7378 }
7379
7380
7381 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
7382                                                    Handle<Map> receiver_map) {
7383   if (!holder.is_null()) {
7384     Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
7385     BuildCheckPrototypeMaps(prototype, holder);
7386   }
7387 }
7388
7389
7390 HInstruction* HOptimizedGraphBuilder::NewPlainFunctionCall(
7391     HValue* fun, int argument_count, bool pass_argument_count) {
7392   return New<HCallJSFunction>(
7393       fun, argument_count, pass_argument_count);
7394 }
7395
7396
7397 HInstruction* HOptimizedGraphBuilder::NewArgumentAdaptorCall(
7398     HValue* fun, HValue* context,
7399     int argument_count, HValue* expected_param_count) {
7400   CallInterfaceDescriptor* descriptor =
7401       isolate()->call_descriptor(Isolate::ArgumentAdaptorCall);
7402
7403   HValue* arity = Add<HConstant>(argument_count - 1);
7404
7405   HValue* op_vals[] = { context, fun, arity, expected_param_count };
7406
7407   Handle<Code> adaptor =
7408       isolate()->builtins()->ArgumentsAdaptorTrampoline();
7409   HConstant* adaptor_value = Add<HConstant>(adaptor);
7410
7411   return New<HCallWithDescriptor>(
7412       adaptor_value, argument_count, descriptor,
7413       Vector<HValue*>(op_vals, descriptor->GetEnvironmentLength()));
7414 }
7415
7416
7417 HInstruction* HOptimizedGraphBuilder::BuildCallConstantFunction(
7418     Handle<JSFunction> jsfun, int argument_count) {
7419   HValue* target = Add<HConstant>(jsfun);
7420   // For constant functions, we try to avoid calling the
7421   // argument adaptor and instead call the function directly
7422   int formal_parameter_count = jsfun->shared()->formal_parameter_count();
7423   bool dont_adapt_arguments =
7424       (formal_parameter_count ==
7425        SharedFunctionInfo::kDontAdaptArgumentsSentinel);
7426   int arity = argument_count - 1;
7427   bool can_invoke_directly =
7428       dont_adapt_arguments || formal_parameter_count == arity;
7429   if (can_invoke_directly) {
7430     if (jsfun.is_identical_to(current_info()->closure())) {
7431       graph()->MarkRecursive();
7432     }
7433     return NewPlainFunctionCall(target, argument_count, dont_adapt_arguments);
7434   } else {
7435     HValue* param_count_value = Add<HConstant>(formal_parameter_count);
7436     HValue* context = Add<HLoadNamedField>(
7437         target, static_cast<HValue*>(NULL),
7438         HObjectAccess::ForFunctionContextPointer());
7439     return NewArgumentAdaptorCall(target, context,
7440         argument_count, param_count_value);
7441   }
7442   UNREACHABLE();
7443   return NULL;
7444 }
7445
7446
7447 class FunctionSorter {
7448  public:
7449   explicit FunctionSorter(int index = 0, int ticks = 0, int size = 0)
7450       : index_(index), ticks_(ticks), size_(size) {}
7451
7452   int index() const { return index_; }
7453   int ticks() const { return ticks_; }
7454   int size() const { return size_; }
7455
7456  private:
7457   int index_;
7458   int ticks_;
7459   int size_;
7460 };
7461
7462
7463 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) {
7464   int diff = lhs.ticks() - rhs.ticks();
7465   if (diff != 0) return diff > 0;
7466   return lhs.size() < rhs.size();
7467 }
7468
7469
7470 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
7471     Call* expr,
7472     HValue* receiver,
7473     SmallMapList* types,
7474     Handle<String> name) {
7475   int argument_count = expr->arguments()->length() + 1;  // Includes receiver.
7476   FunctionSorter order[kMaxCallPolymorphism];
7477
7478   bool handle_smi = false;
7479   bool handled_string = false;
7480   int ordered_functions = 0;
7481
7482   for (int i = 0;
7483        i < types->length() && ordered_functions < kMaxCallPolymorphism;
7484        ++i) {
7485     PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
7486     if (info.CanAccessMonomorphic() && info.IsConstant() &&
7487         info.constant()->IsJSFunction()) {
7488       if (info.type()->Is(Type::String())) {
7489         if (handled_string) continue;
7490         handled_string = true;
7491       }
7492       Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
7493       if (info.type()->Is(Type::Number())) {
7494         handle_smi = true;
7495       }
7496       expr->set_target(target);
7497       order[ordered_functions++] = FunctionSorter(
7498           i, target->shared()->profiler_ticks(), InliningAstSize(target));
7499     }
7500   }
7501
7502   std::sort(order, order + ordered_functions);
7503
7504   HBasicBlock* number_block = NULL;
7505   HBasicBlock* join = NULL;
7506   handled_string = false;
7507   int count = 0;
7508
7509   for (int fn = 0; fn < ordered_functions; ++fn) {
7510     int i = order[fn].index();
7511     PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
7512     if (info.type()->Is(Type::String())) {
7513       if (handled_string) continue;
7514       handled_string = true;
7515     }
7516     // Reloads the target.
7517     info.CanAccessMonomorphic();
7518     Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
7519
7520     expr->set_target(target);
7521     if (count == 0) {
7522       // Only needed once.
7523       join = graph()->CreateBasicBlock();
7524       if (handle_smi) {
7525         HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
7526         HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
7527         number_block = graph()->CreateBasicBlock();
7528         FinishCurrentBlock(New<HIsSmiAndBranch>(
7529                 receiver, empty_smi_block, not_smi_block));
7530         GotoNoSimulate(empty_smi_block, number_block);
7531         set_current_block(not_smi_block);
7532       } else {
7533         BuildCheckHeapObject(receiver);
7534       }
7535     }
7536     ++count;
7537     HBasicBlock* if_true = graph()->CreateBasicBlock();
7538     HBasicBlock* if_false = graph()->CreateBasicBlock();
7539     HUnaryControlInstruction* compare;
7540
7541     Handle<Map> map = info.map();
7542     if (info.type()->Is(Type::Number())) {
7543       Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
7544       compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
7545     } else if (info.type()->Is(Type::String())) {
7546       compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
7547     } else {
7548       compare = New<HCompareMap>(receiver, map, if_true, if_false);
7549     }
7550     FinishCurrentBlock(compare);
7551
7552     if (info.type()->Is(Type::Number())) {
7553       GotoNoSimulate(if_true, number_block);
7554       if_true = number_block;
7555     }
7556
7557     set_current_block(if_true);
7558
7559     AddCheckPrototypeMaps(info.holder(), map);
7560
7561     HValue* function = Add<HConstant>(expr->target());
7562     environment()->SetExpressionStackAt(0, function);
7563     Push(receiver);
7564     CHECK_ALIVE(VisitExpressions(expr->arguments()));
7565     bool needs_wrapping = NeedsWrappingFor(info.type(), target);
7566     bool try_inline = FLAG_polymorphic_inlining && !needs_wrapping;
7567     if (FLAG_trace_inlining && try_inline) {
7568       Handle<JSFunction> caller = current_info()->closure();
7569       SmartArrayPointer<char> caller_name =
7570           caller->shared()->DebugName()->ToCString();
7571       PrintF("Trying to inline the polymorphic call to %s from %s\n",
7572              name->ToCString().get(),
7573              caller_name.get());
7574     }
7575     if (try_inline && TryInlineCall(expr)) {
7576       // Trying to inline will signal that we should bailout from the
7577       // entire compilation by setting stack overflow on the visitor.
7578       if (HasStackOverflow()) return;
7579     } else {
7580       // Since HWrapReceiver currently cannot actually wrap numbers and strings,
7581       // use the regular CallFunctionStub for method calls to wrap the receiver.
7582       // TODO(verwaest): Support creation of value wrappers directly in
7583       // HWrapReceiver.
7584       HInstruction* call = needs_wrapping
7585           ? NewUncasted<HCallFunction>(
7586               function, argument_count, WRAP_AND_CALL)
7587           : BuildCallConstantFunction(target, argument_count);
7588       PushArgumentsFromEnvironment(argument_count);
7589       AddInstruction(call);
7590       Drop(1);  // Drop the function.
7591       if (!ast_context()->IsEffect()) Push(call);
7592     }
7593
7594     if (current_block() != NULL) Goto(join);
7595     set_current_block(if_false);
7596   }
7597
7598   // Finish up.  Unconditionally deoptimize if we've handled all the maps we
7599   // know about and do not want to handle ones we've never seen.  Otherwise
7600   // use a generic IC.
7601   if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
7602     FinishExitWithHardDeoptimization("Unknown map in polymorphic call");
7603   } else {
7604     Property* prop = expr->expression()->AsProperty();
7605     HInstruction* function = BuildNamedGeneric(
7606         LOAD, prop, receiver, name, NULL, prop->IsUninitialized());
7607     AddInstruction(function);
7608     Push(function);
7609     AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
7610
7611     environment()->SetExpressionStackAt(1, function);
7612     environment()->SetExpressionStackAt(0, receiver);
7613     CHECK_ALIVE(VisitExpressions(expr->arguments()));
7614
7615     CallFunctionFlags flags = receiver->type().IsJSObject()
7616         ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD;
7617     HInstruction* call = New<HCallFunction>(
7618         function, argument_count, flags);
7619
7620     PushArgumentsFromEnvironment(argument_count);
7621
7622     Drop(1);  // Function.
7623
7624     if (join != NULL) {
7625       AddInstruction(call);
7626       if (!ast_context()->IsEffect()) Push(call);
7627       Goto(join);
7628     } else {
7629       return ast_context()->ReturnInstruction(call, expr->id());
7630     }
7631   }
7632
7633   // We assume that control flow is always live after an expression.  So
7634   // even without predecessors to the join block, we set it as the exit
7635   // block and continue by adding instructions there.
7636   DCHECK(join != NULL);
7637   if (join->HasPredecessor()) {
7638     set_current_block(join);
7639     join->SetJoinId(expr->id());
7640     if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
7641   } else {
7642     set_current_block(NULL);
7643   }
7644 }
7645
7646
7647 void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target,
7648                                          Handle<JSFunction> caller,
7649                                          const char* reason) {
7650   if (FLAG_trace_inlining) {
7651     SmartArrayPointer<char> target_name =
7652         target->shared()->DebugName()->ToCString();
7653     SmartArrayPointer<char> caller_name =
7654         caller->shared()->DebugName()->ToCString();
7655     if (reason == NULL) {
7656       PrintF("Inlined %s called from %s.\n", target_name.get(),
7657              caller_name.get());
7658     } else {
7659       PrintF("Did not inline %s called from %s (%s).\n",
7660              target_name.get(), caller_name.get(), reason);
7661     }
7662   }
7663 }
7664
7665
7666 static const int kNotInlinable = 1000000000;
7667
7668
7669 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) {
7670   if (!FLAG_use_inlining) return kNotInlinable;
7671
7672   // Precondition: call is monomorphic and we have found a target with the
7673   // appropriate arity.
7674   Handle<JSFunction> caller = current_info()->closure();
7675   Handle<SharedFunctionInfo> target_shared(target->shared());
7676
7677   // Always inline builtins marked for inlining.
7678   if (target->IsBuiltin()) {
7679     return target_shared->inline_builtin() ? 0 : kNotInlinable;
7680   }
7681
7682   if (target_shared->IsApiFunction()) {
7683     TraceInline(target, caller, "target is api function");
7684     return kNotInlinable;
7685   }
7686
7687   // Do a quick check on source code length to avoid parsing large
7688   // inlining candidates.
7689   if (target_shared->SourceSize() >
7690       Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) {
7691     TraceInline(target, caller, "target text too big");
7692     return kNotInlinable;
7693   }
7694
7695   // Target must be inlineable.
7696   if (!target_shared->IsInlineable()) {
7697     TraceInline(target, caller, "target not inlineable");
7698     return kNotInlinable;
7699   }
7700   if (target_shared->DisableOptimizationReason() != kNoReason) {
7701     TraceInline(target, caller, "target contains unsupported syntax [early]");
7702     return kNotInlinable;
7703   }
7704
7705   int nodes_added = target_shared->ast_node_count();
7706   return nodes_added;
7707 }
7708
7709
7710 bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
7711                                        int arguments_count,
7712                                        HValue* implicit_return_value,
7713                                        BailoutId ast_id,
7714                                        BailoutId return_id,
7715                                        InliningKind inlining_kind,
7716                                        HSourcePosition position) {
7717   int nodes_added = InliningAstSize(target);
7718   if (nodes_added == kNotInlinable) return false;
7719
7720   Handle<JSFunction> caller = current_info()->closure();
7721
7722   if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
7723     TraceInline(target, caller, "target AST is too large [early]");
7724     return false;
7725   }
7726
7727   // Don't inline deeper than the maximum number of inlining levels.
7728   HEnvironment* env = environment();
7729   int current_level = 1;
7730   while (env->outer() != NULL) {
7731     if (current_level == FLAG_max_inlining_levels) {
7732       TraceInline(target, caller, "inline depth limit reached");
7733       return false;
7734     }
7735     if (env->outer()->frame_type() == JS_FUNCTION) {
7736       current_level++;
7737     }
7738     env = env->outer();
7739   }
7740
7741   // Don't inline recursive functions.
7742   for (FunctionState* state = function_state();
7743        state != NULL;
7744        state = state->outer()) {
7745     if (*state->compilation_info()->closure() == *target) {
7746       TraceInline(target, caller, "target is recursive");
7747       return false;
7748     }
7749   }
7750
7751   // We don't want to add more than a certain number of nodes from inlining.
7752   if (inlined_count_ > Min(FLAG_max_inlined_nodes_cumulative,
7753                            kUnlimitedMaxInlinedNodesCumulative)) {
7754     TraceInline(target, caller, "cumulative AST node limit reached");
7755     return false;
7756   }
7757
7758   // Parse and allocate variables.
7759   CompilationInfo target_info(target, zone());
7760   // Use the same AstValueFactory for creating strings in the sub-compilation
7761   // step, but don't transfer ownership to target_info.
7762   target_info.SetAstValueFactory(top_info()->ast_value_factory(), false);
7763   Handle<SharedFunctionInfo> target_shared(target->shared());
7764   if (!Parser::Parse(&target_info) || !Scope::Analyze(&target_info)) {
7765     if (target_info.isolate()->has_pending_exception()) {
7766       // Parse or scope error, never optimize this function.
7767       SetStackOverflow();
7768       target_shared->DisableOptimization(kParseScopeError);
7769     }
7770     TraceInline(target, caller, "parse failure");
7771     return false;
7772   }
7773
7774   if (target_info.scope()->num_heap_slots() > 0) {
7775     TraceInline(target, caller, "target has context-allocated variables");
7776     return false;
7777   }
7778   FunctionLiteral* function = target_info.function();
7779
7780   // The following conditions must be checked again after re-parsing, because
7781   // earlier the information might not have been complete due to lazy parsing.
7782   nodes_added = function->ast_node_count();
7783   if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
7784     TraceInline(target, caller, "target AST is too large [late]");
7785     return false;
7786   }
7787   if (function->dont_optimize()) {
7788     TraceInline(target, caller, "target contains unsupported syntax [late]");
7789     return false;
7790   }
7791
7792   // If the function uses the arguments object check that inlining of functions
7793   // with arguments object is enabled and the arguments-variable is
7794   // stack allocated.
7795   if (function->scope()->arguments() != NULL) {
7796     if (!FLAG_inline_arguments) {
7797       TraceInline(target, caller, "target uses arguments object");
7798       return false;
7799     }
7800
7801     if (!function->scope()->arguments()->IsStackAllocated()) {
7802       TraceInline(target,
7803                   caller,
7804                   "target uses non-stackallocated arguments object");
7805       return false;
7806     }
7807   }
7808
7809   // All declarations must be inlineable.
7810   ZoneList<Declaration*>* decls = target_info.scope()->declarations();
7811   int decl_count = decls->length();
7812   for (int i = 0; i < decl_count; ++i) {
7813     if (!decls->at(i)->IsInlineable()) {
7814       TraceInline(target, caller, "target has non-trivial declaration");
7815       return false;
7816     }
7817   }
7818
7819   // Generate the deoptimization data for the unoptimized version of
7820   // the target function if we don't already have it.
7821   if (!target_shared->has_deoptimization_support()) {
7822     // Note that we compile here using the same AST that we will use for
7823     // generating the optimized inline code.
7824     target_info.EnableDeoptimizationSupport();
7825     if (!FullCodeGenerator::MakeCode(&target_info)) {
7826       TraceInline(target, caller, "could not generate deoptimization info");
7827       return false;
7828     }
7829     if (target_shared->scope_info() == ScopeInfo::Empty(isolate())) {
7830       // The scope info might not have been set if a lazily compiled
7831       // function is inlined before being called for the first time.
7832       Handle<ScopeInfo> target_scope_info =
7833           ScopeInfo::Create(target_info.scope(), zone());
7834       target_shared->set_scope_info(*target_scope_info);
7835     }
7836     target_shared->EnableDeoptimizationSupport(*target_info.code());
7837     target_shared->set_feedback_vector(*target_info.feedback_vector());
7838     Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG,
7839                                         &target_info,
7840                                         target_shared);
7841   }
7842
7843   // ----------------------------------------------------------------
7844   // After this point, we've made a decision to inline this function (so
7845   // TryInline should always return true).
7846
7847   // Type-check the inlined function.
7848   DCHECK(target_shared->has_deoptimization_support());
7849   AstTyper::Run(&target_info);
7850
7851   int function_id = graph()->TraceInlinedFunction(target_shared, position);
7852
7853   // Save the pending call context. Set up new one for the inlined function.
7854   // The function state is new-allocated because we need to delete it
7855   // in two different places.
7856   FunctionState* target_state = new FunctionState(
7857       this, &target_info, inlining_kind, function_id);
7858
7859   HConstant* undefined = graph()->GetConstantUndefined();
7860
7861   HEnvironment* inner_env =
7862       environment()->CopyForInlining(target,
7863                                      arguments_count,
7864                                      function,
7865                                      undefined,
7866                                      function_state()->inlining_kind());
7867
7868   HConstant* context = Add<HConstant>(Handle<Context>(target->context()));
7869   inner_env->BindContext(context);
7870
7871   // Create a dematerialized arguments object for the function, also copy the
7872   // current arguments values to use them for materialization.
7873   HEnvironment* arguments_env = inner_env->arguments_environment();
7874   int parameter_count = arguments_env->parameter_count();
7875   HArgumentsObject* arguments_object = Add<HArgumentsObject>(parameter_count);
7876   for (int i = 0; i < parameter_count; i++) {
7877     arguments_object->AddArgument(arguments_env->Lookup(i), zone());
7878   }
7879
7880   // If the function uses arguments object then bind bind one.
7881   if (function->scope()->arguments() != NULL) {
7882     DCHECK(function->scope()->arguments()->IsStackAllocated());
7883     inner_env->Bind(function->scope()->arguments(), arguments_object);
7884   }
7885
7886   // Capture the state before invoking the inlined function for deopt in the
7887   // inlined function. This simulate has no bailout-id since it's not directly
7888   // reachable for deopt, and is only used to capture the state. If the simulate
7889   // becomes reachable by merging, the ast id of the simulate merged into it is
7890   // adopted.
7891   Add<HSimulate>(BailoutId::None());
7892
7893   current_block()->UpdateEnvironment(inner_env);
7894   Scope* saved_scope = scope();
7895   set_scope(target_info.scope());
7896   HEnterInlined* enter_inlined =
7897       Add<HEnterInlined>(return_id, target, arguments_count, function,
7898                          function_state()->inlining_kind(),
7899                          function->scope()->arguments(),
7900                          arguments_object);
7901   function_state()->set_entry(enter_inlined);
7902
7903   VisitDeclarations(target_info.scope()->declarations());
7904   VisitStatements(function->body());
7905   set_scope(saved_scope);
7906   if (HasStackOverflow()) {
7907     // Bail out if the inline function did, as we cannot residualize a call
7908     // instead.
7909     TraceInline(target, caller, "inline graph construction failed");
7910     target_shared->DisableOptimization(kInliningBailedOut);
7911     inline_bailout_ = true;
7912     delete target_state;
7913     return true;
7914   }
7915
7916   // Update inlined nodes count.
7917   inlined_count_ += nodes_added;
7918
7919   Handle<Code> unoptimized_code(target_shared->code());
7920   DCHECK(unoptimized_code->kind() == Code::FUNCTION);
7921   Handle<TypeFeedbackInfo> type_info(
7922       TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
7923   graph()->update_type_change_checksum(type_info->own_type_change_checksum());
7924
7925   TraceInline(target, caller, NULL);
7926
7927   if (current_block() != NULL) {
7928     FunctionState* state = function_state();
7929     if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
7930       // Falling off the end of an inlined construct call. In a test context the
7931       // return value will always evaluate to true, in a value context the
7932       // return value is the newly allocated receiver.
7933       if (call_context()->IsTest()) {
7934         Goto(inlined_test_context()->if_true(), state);
7935       } else if (call_context()->IsEffect()) {
7936         Goto(function_return(), state);
7937       } else {
7938         DCHECK(call_context()->IsValue());
7939         AddLeaveInlined(implicit_return_value, state);
7940       }
7941     } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
7942       // Falling off the end of an inlined setter call. The returned value is
7943       // never used, the value of an assignment is always the value of the RHS
7944       // of the assignment.
7945       if (call_context()->IsTest()) {
7946         inlined_test_context()->ReturnValue(implicit_return_value);
7947       } else if (call_context()->IsEffect()) {
7948         Goto(function_return(), state);
7949       } else {
7950         DCHECK(call_context()->IsValue());
7951         AddLeaveInlined(implicit_return_value, state);
7952       }
7953     } else {
7954       // Falling off the end of a normal inlined function. This basically means
7955       // returning undefined.
7956       if (call_context()->IsTest()) {
7957         Goto(inlined_test_context()->if_false(), state);
7958       } else if (call_context()->IsEffect()) {
7959         Goto(function_return(), state);
7960       } else {
7961         DCHECK(call_context()->IsValue());
7962         AddLeaveInlined(undefined, state);
7963       }
7964     }
7965   }
7966
7967   // Fix up the function exits.
7968   if (inlined_test_context() != NULL) {
7969     HBasicBlock* if_true = inlined_test_context()->if_true();
7970     HBasicBlock* if_false = inlined_test_context()->if_false();
7971
7972     HEnterInlined* entry = function_state()->entry();
7973
7974     // Pop the return test context from the expression context stack.
7975     DCHECK(ast_context() == inlined_test_context());
7976     ClearInlinedTestContext();
7977     delete target_state;
7978
7979     // Forward to the real test context.
7980     if (if_true->HasPredecessor()) {
7981       entry->RegisterReturnTarget(if_true, zone());
7982       if_true->SetJoinId(ast_id);
7983       HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
7984       Goto(if_true, true_target, function_state());
7985     }
7986     if (if_false->HasPredecessor()) {
7987       entry->RegisterReturnTarget(if_false, zone());
7988       if_false->SetJoinId(ast_id);
7989       HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
7990       Goto(if_false, false_target, function_state());
7991     }
7992     set_current_block(NULL);
7993     return true;
7994
7995   } else if (function_return()->HasPredecessor()) {
7996     function_state()->entry()->RegisterReturnTarget(function_return(), zone());
7997     function_return()->SetJoinId(ast_id);
7998     set_current_block(function_return());
7999   } else {
8000     set_current_block(NULL);
8001   }
8002   delete target_state;
8003   return true;
8004 }
8005
8006
8007 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) {
8008   return TryInline(expr->target(),
8009                    expr->arguments()->length(),
8010                    NULL,
8011                    expr->id(),
8012                    expr->ReturnId(),
8013                    NORMAL_RETURN,
8014                    ScriptPositionToSourcePosition(expr->position()));
8015 }
8016
8017
8018 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr,
8019                                                 HValue* implicit_return_value) {
8020   return TryInline(expr->target(),
8021                    expr->arguments()->length(),
8022                    implicit_return_value,
8023                    expr->id(),
8024                    expr->ReturnId(),
8025                    CONSTRUCT_CALL_RETURN,
8026                    ScriptPositionToSourcePosition(expr->position()));
8027 }
8028
8029
8030 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
8031                                              Handle<Map> receiver_map,
8032                                              BailoutId ast_id,
8033                                              BailoutId return_id) {
8034   if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true;
8035   return TryInline(getter,
8036                    0,
8037                    NULL,
8038                    ast_id,
8039                    return_id,
8040                    GETTER_CALL_RETURN,
8041                    source_position());
8042 }
8043
8044
8045 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
8046                                              Handle<Map> receiver_map,
8047                                              BailoutId id,
8048                                              BailoutId assignment_id,
8049                                              HValue* implicit_return_value) {
8050   if (TryInlineApiSetter(setter, receiver_map, id)) return true;
8051   return TryInline(setter,
8052                    1,
8053                    implicit_return_value,
8054                    id, assignment_id,
8055                    SETTER_CALL_RETURN,
8056                    source_position());
8057 }
8058
8059
8060 bool HOptimizedGraphBuilder::TryInlineApply(Handle<JSFunction> function,
8061                                             Call* expr,
8062                                             int arguments_count) {
8063   return TryInline(function,
8064                    arguments_count,
8065                    NULL,
8066                    expr->id(),
8067                    expr->ReturnId(),
8068                    NORMAL_RETURN,
8069                    ScriptPositionToSourcePosition(expr->position()));
8070 }
8071
8072
8073 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) {
8074   if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
8075   BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
8076   switch (id) {
8077     case kMathExp:
8078       if (!FLAG_fast_math) break;
8079       // Fall through if FLAG_fast_math.
8080     case kMathRound:
8081     case kMathFround:
8082     case kMathFloor:
8083     case kMathAbs:
8084     case kMathSqrt:
8085     case kMathLog:
8086     case kMathClz32:
8087       if (expr->arguments()->length() == 1) {
8088         HValue* argument = Pop();
8089         Drop(2);  // Receiver and function.
8090         HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
8091         ast_context()->ReturnInstruction(op, expr->id());
8092         return true;
8093       }
8094       break;
8095     case kMathImul:
8096       if (expr->arguments()->length() == 2) {
8097         HValue* right = Pop();
8098         HValue* left = Pop();
8099         Drop(2);  // Receiver and function.
8100         HInstruction* op = HMul::NewImul(zone(), context(), left, right);
8101         ast_context()->ReturnInstruction(op, expr->id());
8102         return true;
8103       }
8104       break;
8105     default:
8106       // Not supported for inlining yet.
8107       break;
8108   }
8109   return false;
8110 }
8111
8112
8113 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
8114     Call* expr,
8115     HValue* receiver,
8116     Handle<Map> receiver_map) {
8117   // Try to inline calls like Math.* as operations in the calling function.
8118   if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
8119   BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
8120   int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
8121   switch (id) {
8122     case kStringCharCodeAt:
8123     case kStringCharAt:
8124       if (argument_count == 2) {
8125         HValue* index = Pop();
8126         HValue* string = Pop();
8127         Drop(1);  // Function.
8128         HInstruction* char_code =
8129             BuildStringCharCodeAt(string, index);
8130         if (id == kStringCharCodeAt) {
8131           ast_context()->ReturnInstruction(char_code, expr->id());
8132           return true;
8133         }
8134         AddInstruction(char_code);
8135         HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
8136         ast_context()->ReturnInstruction(result, expr->id());
8137         return true;
8138       }
8139       break;
8140     case kStringFromCharCode:
8141       if (argument_count == 2) {
8142         HValue* argument = Pop();
8143         Drop(2);  // Receiver and function.
8144         HInstruction* result = NewUncasted<HStringCharFromCode>(argument);
8145         ast_context()->ReturnInstruction(result, expr->id());
8146         return true;
8147       }
8148       break;
8149     case kMathExp:
8150       if (!FLAG_fast_math) break;
8151       // Fall through if FLAG_fast_math.
8152     case kMathRound:
8153     case kMathFround:
8154     case kMathFloor:
8155     case kMathAbs:
8156     case kMathSqrt:
8157     case kMathLog:
8158     case kMathClz32:
8159       if (argument_count == 2) {
8160         HValue* argument = Pop();
8161         Drop(2);  // Receiver and function.
8162         HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
8163         ast_context()->ReturnInstruction(op, expr->id());
8164         return true;
8165       }
8166       break;
8167     case kMathPow:
8168       if (argument_count == 3) {
8169         HValue* right = Pop();
8170         HValue* left = Pop();
8171         Drop(2);  // Receiver and function.
8172         HInstruction* result = NULL;
8173         // Use sqrt() if exponent is 0.5 or -0.5.
8174         if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
8175           double exponent = HConstant::cast(right)->DoubleValue();
8176           if (exponent == 0.5) {
8177             result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf);
8178           } else if (exponent == -0.5) {
8179             HValue* one = graph()->GetConstant1();
8180             HInstruction* sqrt = AddUncasted<HUnaryMathOperation>(
8181                 left, kMathPowHalf);
8182             // MathPowHalf doesn't have side effects so there's no need for
8183             // an environment simulation here.
8184             DCHECK(!sqrt->HasObservableSideEffects());
8185             result = NewUncasted<HDiv>(one, sqrt);
8186           } else if (exponent == 2.0) {
8187             result = NewUncasted<HMul>(left, left);
8188           }
8189         }
8190
8191         if (result == NULL) {
8192           result = NewUncasted<HPower>(left, right);
8193         }
8194         ast_context()->ReturnInstruction(result, expr->id());
8195         return true;
8196       }
8197       break;
8198     case kMathMax:
8199     case kMathMin:
8200       if (argument_count == 3) {
8201         HValue* right = Pop();
8202         HValue* left = Pop();
8203         Drop(2);  // Receiver and function.
8204         HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
8205                                                      : HMathMinMax::kMathMax;
8206         HInstruction* result = NewUncasted<HMathMinMax>(left, right, op);
8207         ast_context()->ReturnInstruction(result, expr->id());
8208         return true;
8209       }
8210       break;
8211     case kMathImul:
8212       if (argument_count == 3) {
8213         HValue* right = Pop();
8214         HValue* left = Pop();
8215         Drop(2);  // Receiver and function.
8216         HInstruction* result = HMul::NewImul(zone(), context(), left, right);
8217         ast_context()->ReturnInstruction(result, expr->id());
8218         return true;
8219       }
8220       break;
8221     case kArrayPop: {
8222       if (receiver_map.is_null()) return false;
8223       if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
8224       ElementsKind elements_kind = receiver_map->elements_kind();
8225       if (!IsFastElementsKind(elements_kind)) return false;
8226       if (receiver_map->is_observed()) return false;
8227       DCHECK(receiver_map->is_extensible());
8228
8229       Drop(expr->arguments()->length());
8230       HValue* result;
8231       HValue* reduced_length;
8232       HValue* receiver = Pop();
8233
8234       HValue* checked_object = AddCheckMap(receiver, receiver_map);
8235       HValue* length = Add<HLoadNamedField>(
8236           checked_object, static_cast<HValue*>(NULL),
8237           HObjectAccess::ForArrayLength(elements_kind));
8238
8239       Drop(1);  // Function.
8240
8241       { NoObservableSideEffectsScope scope(this);
8242         IfBuilder length_checker(this);
8243
8244         HValue* bounds_check = length_checker.If<HCompareNumericAndBranch>(
8245             length, graph()->GetConstant0(), Token::EQ);
8246         length_checker.Then();
8247
8248         if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
8249
8250         length_checker.Else();
8251         HValue* elements = AddLoadElements(checked_object);
8252         // Ensure that we aren't popping from a copy-on-write array.
8253         if (IsFastSmiOrObjectElementsKind(elements_kind)) {
8254           elements = BuildCopyElementsOnWrite(checked_object, elements,
8255                                               elements_kind, length);
8256         }
8257         reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1());
8258         result = AddElementAccess(elements, reduced_length, NULL,
8259                                   bounds_check, elements_kind, LOAD);
8260         Factory* factory = isolate()->factory();
8261         double nan_double = FixedDoubleArray::hole_nan_as_double();
8262         HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
8263             ? Add<HConstant>(factory->the_hole_value())
8264             : Add<HConstant>(nan_double);
8265         if (IsFastSmiOrObjectElementsKind(elements_kind)) {
8266           elements_kind = FAST_HOLEY_ELEMENTS;
8267         }
8268         AddElementAccess(
8269             elements, reduced_length, hole, bounds_check, elements_kind, STORE);
8270         Add<HStoreNamedField>(
8271             checked_object, HObjectAccess::ForArrayLength(elements_kind),
8272             reduced_length, STORE_TO_INITIALIZED_ENTRY);
8273
8274         if (!ast_context()->IsEffect()) Push(result);
8275
8276         length_checker.End();
8277       }
8278       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
8279       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8280       if (!ast_context()->IsEffect()) Drop(1);
8281
8282       ast_context()->ReturnValue(result);
8283       return true;
8284     }
8285     case kArrayPush: {
8286       if (receiver_map.is_null()) return false;
8287       if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
8288       ElementsKind elements_kind = receiver_map->elements_kind();
8289       if (!IsFastElementsKind(elements_kind)) return false;
8290       if (receiver_map->is_observed()) return false;
8291       if (JSArray::IsReadOnlyLengthDescriptor(receiver_map)) return false;
8292       DCHECK(receiver_map->is_extensible());
8293
8294       // If there may be elements accessors in the prototype chain, the fast
8295       // inlined version can't be used.
8296       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
8297       // If there currently can be no elements accessors on the prototype chain,
8298       // it doesn't mean that there won't be any later. Install a full prototype
8299       // chain check to trap element accessors being installed on the prototype
8300       // chain, which would cause elements to go to dictionary mode and result
8301       // in a map change.
8302       Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
8303       BuildCheckPrototypeMaps(prototype, Handle<JSObject>());
8304
8305       const int argc = expr->arguments()->length();
8306       if (argc != 1) return false;
8307
8308       HValue* value_to_push = Pop();
8309       HValue* array = Pop();
8310       Drop(1);  // Drop function.
8311
8312       HInstruction* new_size = NULL;
8313       HValue* length = NULL;
8314
8315       {
8316         NoObservableSideEffectsScope scope(this);
8317
8318         length = Add<HLoadNamedField>(array, static_cast<HValue*>(NULL),
8319           HObjectAccess::ForArrayLength(elements_kind));
8320
8321         new_size = AddUncasted<HAdd>(length, graph()->GetConstant1());
8322
8323         bool is_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
8324         BuildUncheckedMonomorphicElementAccess(array, length,
8325                                                value_to_push, is_array,
8326                                                elements_kind, STORE,
8327                                                NEVER_RETURN_HOLE,
8328                                                STORE_AND_GROW_NO_TRANSITION);
8329
8330         if (!ast_context()->IsEffect()) Push(new_size);
8331         Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8332         if (!ast_context()->IsEffect()) Drop(1);
8333       }
8334
8335       ast_context()->ReturnValue(new_size);
8336       return true;
8337     }
8338     case kArrayShift: {
8339       if (receiver_map.is_null()) return false;
8340       if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
8341       ElementsKind kind = receiver_map->elements_kind();
8342       if (!IsFastElementsKind(kind)) return false;
8343       if (receiver_map->is_observed()) return false;
8344       if (!receiver_map->is_extensible()) return false;
8345
8346       // If there may be elements accessors in the prototype chain, the fast
8347       // inlined version can't be used.
8348       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
8349
8350       // If there currently can be no elements accessors on the prototype chain,
8351       // it doesn't mean that there won't be any later. Install a full prototype
8352       // chain check to trap element accessors being installed on the prototype
8353       // chain, which would cause elements to go to dictionary mode and result
8354       // in a map change.
8355       BuildCheckPrototypeMaps(
8356           handle(JSObject::cast(receiver_map->prototype()), isolate()),
8357           Handle<JSObject>::null());
8358
8359       // Threshold for fast inlined Array.shift().
8360       HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16));
8361
8362       Drop(expr->arguments()->length());
8363       HValue* receiver = Pop();
8364       HValue* function = Pop();
8365       HValue* result;
8366
8367       {
8368         NoObservableSideEffectsScope scope(this);
8369
8370         HValue* length = Add<HLoadNamedField>(
8371             receiver, static_cast<HValue*>(NULL),
8372             HObjectAccess::ForArrayLength(kind));
8373
8374         IfBuilder if_lengthiszero(this);
8375         HValue* lengthiszero = if_lengthiszero.If<HCompareNumericAndBranch>(
8376             length, graph()->GetConstant0(), Token::EQ);
8377         if_lengthiszero.Then();
8378         {
8379           if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
8380         }
8381         if_lengthiszero.Else();
8382         {
8383           HValue* elements = AddLoadElements(receiver);
8384
8385           // Check if we can use the fast inlined Array.shift().
8386           IfBuilder if_inline(this);
8387           if_inline.If<HCompareNumericAndBranch>(
8388               length, inline_threshold, Token::LTE);
8389           if (IsFastSmiOrObjectElementsKind(kind)) {
8390             // We cannot handle copy-on-write backing stores here.
8391             if_inline.AndIf<HCompareMap>(
8392                 elements, isolate()->factory()->fixed_array_map());
8393           }
8394           if_inline.Then();
8395           {
8396             // Remember the result.
8397             if (!ast_context()->IsEffect()) {
8398               Push(AddElementAccess(elements, graph()->GetConstant0(), NULL,
8399                                     lengthiszero, kind, LOAD));
8400             }
8401
8402             // Compute the new length.
8403             HValue* new_length = AddUncasted<HSub>(
8404                 length, graph()->GetConstant1());
8405             new_length->ClearFlag(HValue::kCanOverflow);
8406
8407             // Copy the remaining elements.
8408             LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
8409             {
8410               HValue* new_key = loop.BeginBody(
8411                   graph()->GetConstant0(), new_length, Token::LT);
8412               HValue* key = AddUncasted<HAdd>(new_key, graph()->GetConstant1());
8413               key->ClearFlag(HValue::kCanOverflow);
8414               HValue* element = AddUncasted<HLoadKeyed>(
8415                   elements, key, lengthiszero, kind, ALLOW_RETURN_HOLE);
8416               HStoreKeyed* store = Add<HStoreKeyed>(
8417                   elements, new_key, element, kind);
8418               store->SetFlag(HValue::kAllowUndefinedAsNaN);
8419             }
8420             loop.EndBody();
8421
8422             // Put a hole at the end.
8423             HValue* hole = IsFastSmiOrObjectElementsKind(kind)
8424                 ? Add<HConstant>(isolate()->factory()->the_hole_value())
8425                 : Add<HConstant>(FixedDoubleArray::hole_nan_as_double());
8426             if (IsFastSmiOrObjectElementsKind(kind)) kind = FAST_HOLEY_ELEMENTS;
8427             Add<HStoreKeyed>(
8428                 elements, new_length, hole, kind, INITIALIZING_STORE);
8429
8430             // Remember new length.
8431             Add<HStoreNamedField>(
8432                 receiver, HObjectAccess::ForArrayLength(kind),
8433                 new_length, STORE_TO_INITIALIZED_ENTRY);
8434           }
8435           if_inline.Else();
8436           {
8437             Add<HPushArguments>(receiver);
8438             result = Add<HCallJSFunction>(function, 1, true);
8439             if (!ast_context()->IsEffect()) Push(result);
8440           }
8441           if_inline.End();
8442         }
8443         if_lengthiszero.End();
8444       }
8445       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
8446       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8447       if (!ast_context()->IsEffect()) Drop(1);
8448       ast_context()->ReturnValue(result);
8449       return true;
8450     }
8451     case kArrayIndexOf:
8452     case kArrayLastIndexOf: {
8453       if (receiver_map.is_null()) return false;
8454       if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
8455       ElementsKind kind = receiver_map->elements_kind();
8456       if (!IsFastElementsKind(kind)) return false;
8457       if (receiver_map->is_observed()) return false;
8458       if (argument_count != 2) return false;
8459       DCHECK(receiver_map->is_extensible());
8460
8461       // If there may be elements accessors in the prototype chain, the fast
8462       // inlined version can't be used.
8463       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
8464
8465       // If there currently can be no elements accessors on the prototype chain,
8466       // it doesn't mean that there won't be any later. Install a full prototype
8467       // chain check to trap element accessors being installed on the prototype
8468       // chain, which would cause elements to go to dictionary mode and result
8469       // in a map change.
8470       BuildCheckPrototypeMaps(
8471           handle(JSObject::cast(receiver_map->prototype()), isolate()),
8472           Handle<JSObject>::null());
8473
8474       HValue* search_element = Pop();
8475       HValue* receiver = Pop();
8476       Drop(1);  // Drop function.
8477
8478       ArrayIndexOfMode mode = (id == kArrayIndexOf)
8479           ? kFirstIndexOf : kLastIndexOf;
8480       HValue* index = BuildArrayIndexOf(receiver, search_element, kind, mode);
8481
8482       if (!ast_context()->IsEffect()) Push(index);
8483       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8484       if (!ast_context()->IsEffect()) Drop(1);
8485       ast_context()->ReturnValue(index);
8486       return true;
8487     }
8488     default:
8489       // Not yet supported for inlining.
8490       break;
8491   }
8492   return false;
8493 }
8494
8495
8496 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr,
8497                                                       HValue* receiver) {
8498   Handle<JSFunction> function = expr->target();
8499   int argc = expr->arguments()->length();
8500   SmallMapList receiver_maps;
8501   return TryInlineApiCall(function,
8502                           receiver,
8503                           &receiver_maps,
8504                           argc,
8505                           expr->id(),
8506                           kCallApiFunction);
8507 }
8508
8509
8510 bool HOptimizedGraphBuilder::TryInlineApiMethodCall(
8511     Call* expr,
8512     HValue* receiver,
8513     SmallMapList* receiver_maps) {
8514   Handle<JSFunction> function = expr->target();
8515   int argc = expr->arguments()->length();
8516   return TryInlineApiCall(function,
8517                           receiver,
8518                           receiver_maps,
8519                           argc,
8520                           expr->id(),
8521                           kCallApiMethod);
8522 }
8523
8524
8525 bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<JSFunction> function,
8526                                                 Handle<Map> receiver_map,
8527                                                 BailoutId ast_id) {
8528   SmallMapList receiver_maps(1, zone());
8529   receiver_maps.Add(receiver_map, zone());
8530   return TryInlineApiCall(function,
8531                           NULL,  // Receiver is on expression stack.
8532                           &receiver_maps,
8533                           0,
8534                           ast_id,
8535                           kCallApiGetter);
8536 }
8537
8538
8539 bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<JSFunction> function,
8540                                                 Handle<Map> receiver_map,
8541                                                 BailoutId ast_id) {
8542   SmallMapList receiver_maps(1, zone());
8543   receiver_maps.Add(receiver_map, zone());
8544   return TryInlineApiCall(function,
8545                           NULL,  // Receiver is on expression stack.
8546                           &receiver_maps,
8547                           1,
8548                           ast_id,
8549                           kCallApiSetter);
8550 }
8551
8552
8553 bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function,
8554                                                HValue* receiver,
8555                                                SmallMapList* receiver_maps,
8556                                                int argc,
8557                                                BailoutId ast_id,
8558                                                ApiCallType call_type) {
8559   CallOptimization optimization(function);
8560   if (!optimization.is_simple_api_call()) return false;
8561   Handle<Map> holder_map;
8562   if (call_type == kCallApiFunction) {
8563     // Cannot embed a direct reference to the global proxy map
8564     // as it maybe dropped on deserialization.
8565     CHECK(!isolate()->serializer_enabled());
8566     DCHECK_EQ(0, receiver_maps->length());
8567     receiver_maps->Add(handle(function->global_proxy()->map()), zone());
8568   }
8569   CallOptimization::HolderLookup holder_lookup =
8570       CallOptimization::kHolderNotFound;
8571   Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
8572       receiver_maps->first(), &holder_lookup);
8573   if (holder_lookup == CallOptimization::kHolderNotFound) return false;
8574
8575   if (FLAG_trace_inlining) {
8576     PrintF("Inlining api function ");
8577     function->ShortPrint();
8578     PrintF("\n");
8579   }
8580
8581   bool drop_extra = false;
8582   bool is_store = false;
8583   switch (call_type) {
8584     case kCallApiFunction:
8585     case kCallApiMethod:
8586       // Need to check that none of the receiver maps could have changed.
8587       Add<HCheckMaps>(receiver, receiver_maps);
8588       // Need to ensure the chain between receiver and api_holder is intact.
8589       if (holder_lookup == CallOptimization::kHolderFound) {
8590         AddCheckPrototypeMaps(api_holder, receiver_maps->first());
8591       } else {
8592         DCHECK_EQ(holder_lookup, CallOptimization::kHolderIsReceiver);
8593       }
8594       // Includes receiver.
8595       PushArgumentsFromEnvironment(argc + 1);
8596       // Drop function after call.
8597       drop_extra = true;
8598       break;
8599     case kCallApiGetter:
8600       // Receiver and prototype chain cannot have changed.
8601       DCHECK_EQ(0, argc);
8602       DCHECK_EQ(NULL, receiver);
8603       // Receiver is on expression stack.
8604       receiver = Pop();
8605       Add<HPushArguments>(receiver);
8606       break;
8607     case kCallApiSetter:
8608       {
8609         is_store = true;
8610         // Receiver and prototype chain cannot have changed.
8611         DCHECK_EQ(1, argc);
8612         DCHECK_EQ(NULL, receiver);
8613         // Receiver and value are on expression stack.
8614         HValue* value = Pop();
8615         receiver = Pop();
8616         Add<HPushArguments>(receiver, value);
8617         break;
8618      }
8619   }
8620
8621   HValue* holder = NULL;
8622   switch (holder_lookup) {
8623     case CallOptimization::kHolderFound:
8624       holder = Add<HConstant>(api_holder);
8625       break;
8626     case CallOptimization::kHolderIsReceiver:
8627       holder = receiver;
8628       break;
8629     case CallOptimization::kHolderNotFound:
8630       UNREACHABLE();
8631       break;
8632   }
8633   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
8634   Handle<Object> call_data_obj(api_call_info->data(), isolate());
8635   bool call_data_is_undefined = call_data_obj->IsUndefined();
8636   HValue* call_data = Add<HConstant>(call_data_obj);
8637   ApiFunction fun(v8::ToCData<Address>(api_call_info->callback()));
8638   ExternalReference ref = ExternalReference(&fun,
8639                                             ExternalReference::DIRECT_API_CALL,
8640                                             isolate());
8641   HValue* api_function_address = Add<HConstant>(ExternalReference(ref));
8642
8643   HValue* op_vals[] = {
8644     context(),
8645     Add<HConstant>(function),
8646     call_data,
8647     holder,
8648     api_function_address
8649   };
8650
8651   CallInterfaceDescriptor* descriptor =
8652       isolate()->call_descriptor(Isolate::ApiFunctionCall);
8653
8654   CallApiFunctionStub stub(isolate(), is_store, call_data_is_undefined, argc);
8655   Handle<Code> code = stub.GetCode();
8656   HConstant* code_value = Add<HConstant>(code);
8657
8658   DCHECK((sizeof(op_vals) / kPointerSize) ==
8659          descriptor->GetEnvironmentLength());
8660
8661   HInstruction* call = New<HCallWithDescriptor>(
8662       code_value, argc + 1, descriptor,
8663       Vector<HValue*>(op_vals, descriptor->GetEnvironmentLength()));
8664
8665   if (drop_extra) Drop(1);  // Drop function.
8666   ast_context()->ReturnInstruction(call, ast_id);
8667   return true;
8668 }
8669
8670
8671 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) {
8672   DCHECK(expr->expression()->IsProperty());
8673
8674   if (!expr->IsMonomorphic()) {
8675     return false;
8676   }
8677   Handle<Map> function_map = expr->GetReceiverTypes()->first();
8678   if (function_map->instance_type() != JS_FUNCTION_TYPE ||
8679       !expr->target()->shared()->HasBuiltinFunctionId() ||
8680       expr->target()->shared()->builtin_function_id() != kFunctionApply) {
8681     return false;
8682   }
8683
8684   if (current_info()->scope()->arguments() == NULL) return false;
8685
8686   ZoneList<Expression*>* args = expr->arguments();
8687   if (args->length() != 2) return false;
8688
8689   VariableProxy* arg_two = args->at(1)->AsVariableProxy();
8690   if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
8691   HValue* arg_two_value = LookupAndMakeLive(arg_two->var());
8692   if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
8693
8694   // Found pattern f.apply(receiver, arguments).
8695   CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true);
8696   HValue* receiver = Pop();  // receiver
8697   HValue* function = Pop();  // f
8698   Drop(1);  // apply
8699
8700   HValue* checked_function = AddCheckMap(function, function_map);
8701
8702   if (function_state()->outer() == NULL) {
8703     HInstruction* elements = Add<HArgumentsElements>(false);
8704     HInstruction* length = Add<HArgumentsLength>(elements);
8705     HValue* wrapped_receiver = BuildWrapReceiver(receiver, checked_function);
8706     HInstruction* result = New<HApplyArguments>(function,
8707                                                 wrapped_receiver,
8708                                                 length,
8709                                                 elements);
8710     ast_context()->ReturnInstruction(result, expr->id());
8711     return true;
8712   } else {
8713     // We are inside inlined function and we know exactly what is inside
8714     // arguments object. But we need to be able to materialize at deopt.
8715     DCHECK_EQ(environment()->arguments_environment()->parameter_count(),
8716               function_state()->entry()->arguments_object()->arguments_count());
8717     HArgumentsObject* args = function_state()->entry()->arguments_object();
8718     const ZoneList<HValue*>* arguments_values = args->arguments_values();
8719     int arguments_count = arguments_values->length();
8720     Push(function);
8721     Push(BuildWrapReceiver(receiver, checked_function));
8722     for (int i = 1; i < arguments_count; i++) {
8723       Push(arguments_values->at(i));
8724     }
8725
8726     Handle<JSFunction> known_function;
8727     if (function->IsConstant() &&
8728         HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
8729       known_function = Handle<JSFunction>::cast(
8730           HConstant::cast(function)->handle(isolate()));
8731       int args_count = arguments_count - 1;  // Excluding receiver.
8732       if (TryInlineApply(known_function, expr, args_count)) return true;
8733     }
8734
8735     PushArgumentsFromEnvironment(arguments_count);
8736     HInvokeFunction* call = New<HInvokeFunction>(
8737         function, known_function, arguments_count);
8738     Drop(1);  // Function.
8739     ast_context()->ReturnInstruction(call, expr->id());
8740     return true;
8741   }
8742 }
8743
8744
8745 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function,
8746                                                     Handle<JSFunction> target) {
8747   SharedFunctionInfo* shared = target->shared();
8748   if (shared->strict_mode() == SLOPPY && !shared->native()) {
8749     // Cannot embed a direct reference to the global proxy
8750     // as is it dropped on deserialization.
8751     CHECK(!isolate()->serializer_enabled());
8752     Handle<JSObject> global_proxy(target->context()->global_proxy());
8753     return Add<HConstant>(global_proxy);
8754   }
8755   return graph()->GetConstantUndefined();
8756 }
8757
8758
8759 void HOptimizedGraphBuilder::BuildArrayCall(Expression* expression,
8760                                             int arguments_count,
8761                                             HValue* function,
8762                                             Handle<AllocationSite> site) {
8763   Add<HCheckValue>(function, array_function());
8764
8765   if (IsCallArrayInlineable(arguments_count, site)) {
8766     BuildInlinedCallArray(expression, arguments_count, site);
8767     return;
8768   }
8769
8770   HInstruction* call = PreProcessCall(New<HCallNewArray>(
8771       function, arguments_count + 1, site->GetElementsKind()));
8772   if (expression->IsCall()) {
8773     Drop(1);
8774   }
8775   ast_context()->ReturnInstruction(call, expression->id());
8776 }
8777
8778
8779 HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver,
8780                                                   HValue* search_element,
8781                                                   ElementsKind kind,
8782                                                   ArrayIndexOfMode mode) {
8783   DCHECK(IsFastElementsKind(kind));
8784
8785   NoObservableSideEffectsScope no_effects(this);
8786
8787   HValue* elements = AddLoadElements(receiver);
8788   HValue* length = AddLoadArrayLength(receiver, kind);
8789
8790   HValue* initial;
8791   HValue* terminating;
8792   Token::Value token;
8793   LoopBuilder::Direction direction;
8794   if (mode == kFirstIndexOf) {
8795     initial = graph()->GetConstant0();
8796     terminating = length;
8797     token = Token::LT;
8798     direction = LoopBuilder::kPostIncrement;
8799   } else {
8800     DCHECK_EQ(kLastIndexOf, mode);
8801     initial = length;
8802     terminating = graph()->GetConstant0();
8803     token = Token::GT;
8804     direction = LoopBuilder::kPreDecrement;
8805   }
8806
8807   Push(graph()->GetConstantMinus1());
8808   if (IsFastDoubleElementsKind(kind) || IsFastSmiElementsKind(kind)) {
8809     LoopBuilder loop(this, context(), direction);
8810     {
8811       HValue* index = loop.BeginBody(initial, terminating, token);
8812       HValue* element = AddUncasted<HLoadKeyed>(
8813           elements, index, static_cast<HValue*>(NULL),
8814           kind, ALLOW_RETURN_HOLE);
8815       IfBuilder if_issame(this);
8816       if (IsFastDoubleElementsKind(kind)) {
8817         if_issame.If<HCompareNumericAndBranch>(
8818             element, search_element, Token::EQ_STRICT);
8819       } else {
8820         if_issame.If<HCompareObjectEqAndBranch>(element, search_element);
8821       }
8822       if_issame.Then();
8823       {
8824         Drop(1);
8825         Push(index);
8826         loop.Break();
8827       }
8828       if_issame.End();
8829     }
8830     loop.EndBody();
8831   } else {
8832     IfBuilder if_isstring(this);
8833     if_isstring.If<HIsStringAndBranch>(search_element);
8834     if_isstring.Then();
8835     {
8836       LoopBuilder loop(this, context(), direction);
8837       {
8838         HValue* index = loop.BeginBody(initial, terminating, token);
8839         HValue* element = AddUncasted<HLoadKeyed>(
8840             elements, index, static_cast<HValue*>(NULL),
8841             kind, ALLOW_RETURN_HOLE);
8842         IfBuilder if_issame(this);
8843         if_issame.If<HIsStringAndBranch>(element);
8844         if_issame.AndIf<HStringCompareAndBranch>(
8845             element, search_element, Token::EQ_STRICT);
8846         if_issame.Then();
8847         {
8848           Drop(1);
8849           Push(index);
8850           loop.Break();
8851         }
8852         if_issame.End();
8853       }
8854       loop.EndBody();
8855     }
8856     if_isstring.Else();
8857     {
8858       IfBuilder if_isnumber(this);
8859       if_isnumber.If<HIsSmiAndBranch>(search_element);
8860       if_isnumber.OrIf<HCompareMap>(
8861           search_element, isolate()->factory()->heap_number_map());
8862       if_isnumber.Then();
8863       {
8864         HValue* search_number =
8865             AddUncasted<HForceRepresentation>(search_element,
8866                                               Representation::Double());
8867         LoopBuilder loop(this, context(), direction);
8868         {
8869           HValue* index = loop.BeginBody(initial, terminating, token);
8870           HValue* element = AddUncasted<HLoadKeyed>(
8871               elements, index, static_cast<HValue*>(NULL),
8872               kind, ALLOW_RETURN_HOLE);
8873
8874           IfBuilder if_element_isnumber(this);
8875           if_element_isnumber.If<HIsSmiAndBranch>(element);
8876           if_element_isnumber.OrIf<HCompareMap>(
8877               element, isolate()->factory()->heap_number_map());
8878           if_element_isnumber.Then();
8879           {
8880             HValue* number =
8881                 AddUncasted<HForceRepresentation>(element,
8882                                                   Representation::Double());
8883             IfBuilder if_issame(this);
8884             if_issame.If<HCompareNumericAndBranch>(
8885                 number, search_number, Token::EQ_STRICT);
8886             if_issame.Then();
8887             {
8888               Drop(1);
8889               Push(index);
8890               loop.Break();
8891             }
8892             if_issame.End();
8893           }
8894           if_element_isnumber.End();
8895         }
8896         loop.EndBody();
8897       }
8898       if_isnumber.Else();
8899       {
8900         LoopBuilder loop(this, context(), direction);
8901         {
8902           HValue* index = loop.BeginBody(initial, terminating, token);
8903           HValue* element = AddUncasted<HLoadKeyed>(
8904               elements, index, static_cast<HValue*>(NULL),
8905               kind, ALLOW_RETURN_HOLE);
8906           IfBuilder if_issame(this);
8907           if_issame.If<HCompareObjectEqAndBranch>(
8908               element, search_element);
8909           if_issame.Then();
8910           {
8911             Drop(1);
8912             Push(index);
8913             loop.Break();
8914           }
8915           if_issame.End();
8916         }
8917         loop.EndBody();
8918       }
8919       if_isnumber.End();
8920     }
8921     if_isstring.End();
8922   }
8923
8924   return Pop();
8925 }
8926
8927
8928 bool HOptimizedGraphBuilder::TryHandleArrayCall(Call* expr, HValue* function) {
8929   if (!array_function().is_identical_to(expr->target())) {
8930     return false;
8931   }
8932
8933   Handle<AllocationSite> site = expr->allocation_site();
8934   if (site.is_null()) return false;
8935
8936   BuildArrayCall(expr,
8937                  expr->arguments()->length(),
8938                  function,
8939                  site);
8940   return true;
8941 }
8942
8943
8944 bool HOptimizedGraphBuilder::TryHandleArrayCallNew(CallNew* expr,
8945                                                    HValue* function) {
8946   if (!array_function().is_identical_to(expr->target())) {
8947     return false;
8948   }
8949
8950   BuildArrayCall(expr,
8951                  expr->arguments()->length(),
8952                  function,
8953                  expr->allocation_site());
8954   return true;
8955 }
8956
8957
8958 void HOptimizedGraphBuilder::VisitCall(Call* expr) {
8959   DCHECK(!HasStackOverflow());
8960   DCHECK(current_block() != NULL);
8961   DCHECK(current_block()->HasPredecessor());
8962   Expression* callee = expr->expression();
8963   int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
8964   HInstruction* call = NULL;
8965
8966   Property* prop = callee->AsProperty();
8967   if (prop != NULL) {
8968     CHECK_ALIVE(VisitForValue(prop->obj()));
8969     HValue* receiver = Top();
8970
8971     SmallMapList* types;
8972     ComputeReceiverTypes(expr, receiver, &types, zone());
8973
8974     if (prop->key()->IsPropertyName() && types->length() > 0) {
8975       Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
8976       PropertyAccessInfo info(this, LOAD, ToType(types->first()), name);
8977       if (!info.CanAccessAsMonomorphic(types)) {
8978         HandlePolymorphicCallNamed(expr, receiver, types, name);
8979         return;
8980       }
8981     }
8982
8983     HValue* key = NULL;
8984     if (!prop->key()->IsPropertyName()) {
8985       CHECK_ALIVE(VisitForValue(prop->key()));
8986       key = Pop();
8987     }
8988
8989     CHECK_ALIVE(PushLoad(prop, receiver, key));
8990     HValue* function = Pop();
8991
8992     if (FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
8993
8994     // Push the function under the receiver.
8995     environment()->SetExpressionStackAt(0, function);
8996
8997     Push(receiver);
8998
8999     if (function->IsConstant() &&
9000         HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
9001       Handle<JSFunction> known_function = Handle<JSFunction>::cast(
9002           HConstant::cast(function)->handle(isolate()));
9003       expr->set_target(known_function);
9004
9005       if (TryCallApply(expr)) return;
9006       CHECK_ALIVE(VisitExpressions(expr->arguments()));
9007
9008       Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>();
9009       if (TryInlineBuiltinMethodCall(expr, receiver, map)) {
9010         if (FLAG_trace_inlining) {
9011           PrintF("Inlining builtin ");
9012           known_function->ShortPrint();
9013           PrintF("\n");
9014         }
9015         return;
9016       }
9017       if (TryInlineApiMethodCall(expr, receiver, types)) return;
9018
9019       // Wrap the receiver if necessary.
9020       if (NeedsWrappingFor(ToType(types->first()), known_function)) {
9021         // Since HWrapReceiver currently cannot actually wrap numbers and
9022         // strings, use the regular CallFunctionStub for method calls to wrap
9023         // the receiver.
9024         // TODO(verwaest): Support creation of value wrappers directly in
9025         // HWrapReceiver.
9026         call = New<HCallFunction>(
9027             function, argument_count, WRAP_AND_CALL);
9028       } else if (TryInlineCall(expr)) {
9029         return;
9030       } else {
9031         call = BuildCallConstantFunction(known_function, argument_count);
9032       }
9033
9034     } else {
9035       CHECK_ALIVE(VisitExpressions(expr->arguments()));
9036       CallFunctionFlags flags = receiver->type().IsJSObject()
9037           ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD;
9038       call = New<HCallFunction>(function, argument_count, flags);
9039     }
9040     PushArgumentsFromEnvironment(argument_count);
9041
9042   } else {
9043     VariableProxy* proxy = expr->expression()->AsVariableProxy();
9044     if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
9045       return Bailout(kPossibleDirectCallToEval);
9046     }
9047
9048     // The function is on the stack in the unoptimized code during
9049     // evaluation of the arguments.
9050     CHECK_ALIVE(VisitForValue(expr->expression()));
9051     HValue* function = Top();
9052     if (expr->global_call()) {
9053       Variable* var = proxy->var();
9054       bool known_global_function = false;
9055       // If there is a global property cell for the name at compile time and
9056       // access check is not enabled we assume that the function will not change
9057       // and generate optimized code for calling the function.
9058       Handle<GlobalObject> global(current_info()->global_object());
9059       LookupIterator it(global, var->name(), LookupIterator::CHECK_PROPERTY);
9060       GlobalPropertyAccess type = LookupGlobalProperty(var, &it, LOAD);
9061       if (type == kUseCell &&
9062           !current_info()->global_object()->IsAccessCheckNeeded()) {
9063         Handle<GlobalObject> global(current_info()->global_object());
9064         known_global_function = expr->ComputeGlobalTarget(global, &it);
9065       }
9066       if (known_global_function) {
9067         Add<HCheckValue>(function, expr->target());
9068
9069         // Placeholder for the receiver.
9070         Push(graph()->GetConstantUndefined());
9071         CHECK_ALIVE(VisitExpressions(expr->arguments()));
9072
9073         // Patch the global object on the stack by the expected receiver.
9074         HValue* receiver = ImplicitReceiverFor(function, expr->target());
9075         const int receiver_index = argument_count - 1;
9076         environment()->SetExpressionStackAt(receiver_index, receiver);
9077
9078         if (TryInlineBuiltinFunctionCall(expr)) {
9079           if (FLAG_trace_inlining) {
9080             PrintF("Inlining builtin ");
9081             expr->target()->ShortPrint();
9082             PrintF("\n");
9083           }
9084           return;
9085         }
9086         if (TryInlineApiFunctionCall(expr, receiver)) return;
9087         if (TryHandleArrayCall(expr, function)) return;
9088         if (TryInlineCall(expr)) return;
9089
9090         PushArgumentsFromEnvironment(argument_count);
9091         call = BuildCallConstantFunction(expr->target(), argument_count);
9092       } else {
9093         Push(graph()->GetConstantUndefined());
9094         CHECK_ALIVE(VisitExpressions(expr->arguments()));
9095         PushArgumentsFromEnvironment(argument_count);
9096         call = New<HCallFunction>(function, argument_count);
9097       }
9098
9099     } else if (expr->IsMonomorphic()) {
9100       Add<HCheckValue>(function, expr->target());
9101
9102       Push(graph()->GetConstantUndefined());
9103       CHECK_ALIVE(VisitExpressions(expr->arguments()));
9104
9105       HValue* receiver = ImplicitReceiverFor(function, expr->target());
9106       const int receiver_index = argument_count - 1;
9107       environment()->SetExpressionStackAt(receiver_index, receiver);
9108
9109       if (TryInlineBuiltinFunctionCall(expr)) {
9110         if (FLAG_trace_inlining) {
9111           PrintF("Inlining builtin ");
9112           expr->target()->ShortPrint();
9113           PrintF("\n");
9114         }
9115         return;
9116       }
9117       if (TryInlineApiFunctionCall(expr, receiver)) return;
9118
9119       if (TryInlineCall(expr)) return;
9120
9121       call = PreProcessCall(New<HInvokeFunction>(
9122           function, expr->target(), argument_count));
9123
9124     } else {
9125       Push(graph()->GetConstantUndefined());
9126       CHECK_ALIVE(VisitExpressions(expr->arguments()));
9127       PushArgumentsFromEnvironment(argument_count);
9128       call = New<HCallFunction>(function, argument_count);
9129     }
9130   }
9131
9132   Drop(1);  // Drop the function.
9133   return ast_context()->ReturnInstruction(call, expr->id());
9134 }
9135
9136
9137 void HOptimizedGraphBuilder::BuildInlinedCallArray(
9138     Expression* expression,
9139     int argument_count,
9140     Handle<AllocationSite> site) {
9141   DCHECK(!site.is_null());
9142   DCHECK(argument_count >= 0 && argument_count <= 1);
9143   NoObservableSideEffectsScope no_effects(this);
9144
9145   // We should at least have the constructor on the expression stack.
9146   HValue* constructor = environment()->ExpressionStackAt(argument_count);
9147
9148   // Register on the site for deoptimization if the transition feedback changes.
9149   AllocationSite::AddDependentCompilationInfo(
9150       site, AllocationSite::TRANSITIONS, top_info());
9151   ElementsKind kind = site->GetElementsKind();
9152   HInstruction* site_instruction = Add<HConstant>(site);
9153
9154   // In the single constant argument case, we may have to adjust elements kind
9155   // to avoid creating a packed non-empty array.
9156   if (argument_count == 1 && !IsHoleyElementsKind(kind)) {
9157     HValue* argument = environment()->Top();
9158     if (argument->IsConstant()) {
9159       HConstant* constant_argument = HConstant::cast(argument);
9160       DCHECK(constant_argument->HasSmiValue());
9161       int constant_array_size = constant_argument->Integer32Value();
9162       if (constant_array_size != 0) {
9163         kind = GetHoleyElementsKind(kind);
9164       }
9165     }
9166   }
9167
9168   // Build the array.
9169   JSArrayBuilder array_builder(this,
9170                                kind,
9171                                site_instruction,
9172                                constructor,
9173                                DISABLE_ALLOCATION_SITES);
9174   HValue* new_object = argument_count == 0
9175       ? array_builder.AllocateEmptyArray()
9176       : BuildAllocateArrayFromLength(&array_builder, Top());
9177
9178   int args_to_drop = argument_count + (expression->IsCall() ? 2 : 1);
9179   Drop(args_to_drop);
9180   ast_context()->ReturnValue(new_object);
9181 }
9182
9183
9184 // Checks whether allocation using the given constructor can be inlined.
9185 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
9186   return constructor->has_initial_map() &&
9187       constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
9188       constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize &&
9189       constructor->initial_map()->InitialPropertiesLength() == 0;
9190 }
9191
9192
9193 bool HOptimizedGraphBuilder::IsCallArrayInlineable(
9194     int argument_count,
9195     Handle<AllocationSite> site) {
9196   Handle<JSFunction> caller = current_info()->closure();
9197   Handle<JSFunction> target = array_function();
9198   // We should have the function plus array arguments on the environment stack.
9199   DCHECK(environment()->length() >= (argument_count + 1));
9200   DCHECK(!site.is_null());
9201
9202   bool inline_ok = false;
9203   if (site->CanInlineCall()) {
9204     // We also want to avoid inlining in certain 1 argument scenarios.
9205     if (argument_count == 1) {
9206       HValue* argument = Top();
9207       if (argument->IsConstant()) {
9208         // Do not inline if the constant length argument is not a smi or
9209         // outside the valid range for unrolled loop initialization.
9210         HConstant* constant_argument = HConstant::cast(argument);
9211         if (constant_argument->HasSmiValue()) {
9212           int value = constant_argument->Integer32Value();
9213           inline_ok = value >= 0 && value <= kElementLoopUnrollThreshold;
9214           if (!inline_ok) {
9215             TraceInline(target, caller,
9216                         "Constant length outside of valid inlining range.");
9217           }
9218         }
9219       } else {
9220         TraceInline(target, caller,
9221                     "Dont inline [new] Array(n) where n isn't constant.");
9222       }
9223     } else if (argument_count == 0) {
9224       inline_ok = true;
9225     } else {
9226       TraceInline(target, caller, "Too many arguments to inline.");
9227     }
9228   } else {
9229     TraceInline(target, caller, "AllocationSite requested no inlining.");
9230   }
9231
9232   if (inline_ok) {
9233     TraceInline(target, caller, NULL);
9234   }
9235   return inline_ok;
9236 }
9237
9238
9239 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
9240   DCHECK(!HasStackOverflow());
9241   DCHECK(current_block() != NULL);
9242   DCHECK(current_block()->HasPredecessor());
9243   if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
9244   int argument_count = expr->arguments()->length() + 1;  // Plus constructor.
9245   Factory* factory = isolate()->factory();
9246
9247   // The constructor function is on the stack in the unoptimized code
9248   // during evaluation of the arguments.
9249   CHECK_ALIVE(VisitForValue(expr->expression()));
9250   HValue* function = Top();
9251   CHECK_ALIVE(VisitExpressions(expr->arguments()));
9252
9253   if (FLAG_inline_construct &&
9254       expr->IsMonomorphic() &&
9255       IsAllocationInlineable(expr->target())) {
9256     Handle<JSFunction> constructor = expr->target();
9257     HValue* check = Add<HCheckValue>(function, constructor);
9258
9259     // Force completion of inobject slack tracking before generating
9260     // allocation code to finalize instance size.
9261     if (constructor->IsInobjectSlackTrackingInProgress()) {
9262       constructor->CompleteInobjectSlackTracking();
9263     }
9264
9265     // Calculate instance size from initial map of constructor.
9266     DCHECK(constructor->has_initial_map());
9267     Handle<Map> initial_map(constructor->initial_map());
9268     int instance_size = initial_map->instance_size();
9269     DCHECK(initial_map->InitialPropertiesLength() == 0);
9270
9271     // Allocate an instance of the implicit receiver object.
9272     HValue* size_in_bytes = Add<HConstant>(instance_size);
9273     HAllocationMode allocation_mode;
9274     if (FLAG_pretenuring_call_new) {
9275       if (FLAG_allocation_site_pretenuring) {
9276         // Try to use pretenuring feedback.
9277         Handle<AllocationSite> allocation_site = expr->allocation_site();
9278         allocation_mode = HAllocationMode(allocation_site);
9279         // Take a dependency on allocation site.
9280         AllocationSite::AddDependentCompilationInfo(allocation_site,
9281                                                     AllocationSite::TENURING,
9282                                                     top_info());
9283       }
9284     }
9285
9286     HAllocate* receiver = BuildAllocate(
9287         size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode);
9288     receiver->set_known_initial_map(initial_map);
9289
9290     // Initialize map and fields of the newly allocated object.
9291     { NoObservableSideEffectsScope no_effects(this);
9292       DCHECK(initial_map->instance_type() == JS_OBJECT_TYPE);
9293       Add<HStoreNamedField>(receiver,
9294           HObjectAccess::ForMapAndOffset(initial_map, JSObject::kMapOffset),
9295           Add<HConstant>(initial_map));
9296       HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array());
9297       Add<HStoreNamedField>(receiver,
9298           HObjectAccess::ForMapAndOffset(initial_map,
9299                                          JSObject::kPropertiesOffset),
9300           empty_fixed_array);
9301       Add<HStoreNamedField>(receiver,
9302           HObjectAccess::ForMapAndOffset(initial_map,
9303                                          JSObject::kElementsOffset),
9304           empty_fixed_array);
9305       if (initial_map->inobject_properties() != 0) {
9306         HConstant* undefined = graph()->GetConstantUndefined();
9307         for (int i = 0; i < initial_map->inobject_properties(); i++) {
9308           int property_offset = initial_map->GetInObjectPropertyOffset(i);
9309           Add<HStoreNamedField>(receiver,
9310               HObjectAccess::ForMapAndOffset(initial_map, property_offset),
9311               undefined);
9312         }
9313       }
9314     }
9315
9316     // Replace the constructor function with a newly allocated receiver using
9317     // the index of the receiver from the top of the expression stack.
9318     const int receiver_index = argument_count - 1;
9319     DCHECK(environment()->ExpressionStackAt(receiver_index) == function);
9320     environment()->SetExpressionStackAt(receiver_index, receiver);
9321
9322     if (TryInlineConstruct(expr, receiver)) {
9323       // Inlining worked, add a dependency on the initial map to make sure that
9324       // this code is deoptimized whenever the initial map of the constructor
9325       // changes.
9326       Map::AddDependentCompilationInfo(
9327           initial_map, DependentCode::kInitialMapChangedGroup, top_info());
9328       return;
9329     }
9330
9331     // TODO(mstarzinger): For now we remove the previous HAllocate and all
9332     // corresponding instructions and instead add HPushArguments for the
9333     // arguments in case inlining failed.  What we actually should do is for
9334     // inlining to try to build a subgraph without mutating the parent graph.
9335     HInstruction* instr = current_block()->last();
9336     do {
9337       HInstruction* prev_instr = instr->previous();
9338       instr->DeleteAndReplaceWith(NULL);
9339       instr = prev_instr;
9340     } while (instr != check);
9341     environment()->SetExpressionStackAt(receiver_index, function);
9342     HInstruction* call =
9343       PreProcessCall(New<HCallNew>(function, argument_count));
9344     return ast_context()->ReturnInstruction(call, expr->id());
9345   } else {
9346     // The constructor function is both an operand to the instruction and an
9347     // argument to the construct call.
9348     if (TryHandleArrayCallNew(expr, function)) return;
9349
9350     HInstruction* call =
9351         PreProcessCall(New<HCallNew>(function, argument_count));
9352     return ast_context()->ReturnInstruction(call, expr->id());
9353   }
9354 }
9355
9356
9357 // Support for generating inlined runtime functions.
9358
9359 // Lookup table for generators for runtime calls that are generated inline.
9360 // Elements of the table are member pointers to functions of
9361 // HOptimizedGraphBuilder.
9362 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize)  \
9363     &HOptimizedGraphBuilder::Generate##Name,
9364
9365 const HOptimizedGraphBuilder::InlineFunctionGenerator
9366     HOptimizedGraphBuilder::kInlineFunctionGenerators[] = {
9367         INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
9368         INLINE_OPTIMIZED_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
9369 };
9370 #undef INLINE_FUNCTION_GENERATOR_ADDRESS
9371
9372
9373 template <class ViewClass>
9374 void HGraphBuilder::BuildArrayBufferViewInitialization(
9375     HValue* obj,
9376     HValue* buffer,
9377     HValue* byte_offset,
9378     HValue* byte_length) {
9379
9380   for (int offset = ViewClass::kSize;
9381        offset < ViewClass::kSizeWithInternalFields;
9382        offset += kPointerSize) {
9383     Add<HStoreNamedField>(obj,
9384         HObjectAccess::ForObservableJSObjectOffset(offset),
9385         graph()->GetConstant0());
9386   }
9387
9388   Add<HStoreNamedField>(
9389       obj,
9390       HObjectAccess::ForJSArrayBufferViewByteOffset(),
9391       byte_offset);
9392   Add<HStoreNamedField>(
9393       obj,
9394       HObjectAccess::ForJSArrayBufferViewByteLength(),
9395       byte_length);
9396
9397   if (buffer != NULL) {
9398     Add<HStoreNamedField>(
9399         obj,
9400         HObjectAccess::ForJSArrayBufferViewBuffer(), buffer);
9401     HObjectAccess weak_first_view_access =
9402         HObjectAccess::ForJSArrayBufferWeakFirstView();
9403     Add<HStoreNamedField>(obj,
9404         HObjectAccess::ForJSArrayBufferViewWeakNext(),
9405         Add<HLoadNamedField>(buffer,
9406                              static_cast<HValue*>(NULL),
9407                              weak_first_view_access));
9408     Add<HStoreNamedField>(buffer, weak_first_view_access, obj);
9409   } else {
9410     Add<HStoreNamedField>(
9411         obj,
9412         HObjectAccess::ForJSArrayBufferViewBuffer(),
9413         Add<HConstant>(static_cast<int32_t>(0)));
9414     Add<HStoreNamedField>(obj,
9415         HObjectAccess::ForJSArrayBufferViewWeakNext(),
9416         graph()->GetConstantUndefined());
9417   }
9418 }
9419
9420
9421 void HOptimizedGraphBuilder::GenerateDataViewInitialize(
9422     CallRuntime* expr) {
9423   ZoneList<Expression*>* arguments = expr->arguments();
9424
9425   DCHECK(arguments->length()== 4);
9426   CHECK_ALIVE(VisitForValue(arguments->at(0)));
9427   HValue* obj = Pop();
9428
9429   CHECK_ALIVE(VisitForValue(arguments->at(1)));
9430   HValue* buffer = Pop();
9431
9432   CHECK_ALIVE(VisitForValue(arguments->at(2)));
9433   HValue* byte_offset = Pop();
9434
9435   CHECK_ALIVE(VisitForValue(arguments->at(3)));
9436   HValue* byte_length = Pop();
9437
9438   {
9439     NoObservableSideEffectsScope scope(this);
9440     BuildArrayBufferViewInitialization<JSDataView>(
9441         obj, buffer, byte_offset, byte_length);
9442   }
9443 }
9444
9445
9446 static Handle<Map> TypedArrayMap(Isolate* isolate,
9447                                  ExternalArrayType array_type,
9448                                  ElementsKind target_kind) {
9449   Handle<Context> native_context = isolate->native_context();
9450   Handle<JSFunction> fun;
9451   switch (array_type) {
9452 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
9453     case kExternal##Type##Array:                                              \
9454       fun = Handle<JSFunction>(native_context->type##_array_fun());           \
9455       break;
9456
9457     TYPED_ARRAYS(TYPED_ARRAY_CASE)
9458 #undef TYPED_ARRAY_CASE
9459   }
9460   Handle<Map> map(fun->initial_map());
9461   return Map::AsElementsKind(map, target_kind);
9462 }
9463
9464
9465 HValue* HOptimizedGraphBuilder::BuildAllocateExternalElements(
9466     ExternalArrayType array_type,
9467     bool is_zero_byte_offset,
9468     HValue* buffer, HValue* byte_offset, HValue* length) {
9469   Handle<Map> external_array_map(
9470       isolate()->heap()->MapForExternalArrayType(array_type));
9471
9472   // The HForceRepresentation is to prevent possible deopt on int-smi
9473   // conversion after allocation but before the new object fields are set.
9474   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
9475   HValue* elements =
9476       Add<HAllocate>(
9477           Add<HConstant>(ExternalArray::kAlignedSize),
9478           HType::HeapObject(),
9479           NOT_TENURED,
9480           external_array_map->instance_type());
9481
9482   AddStoreMapConstant(elements, external_array_map);
9483   Add<HStoreNamedField>(elements,
9484       HObjectAccess::ForFixedArrayLength(), length);
9485
9486   HValue* backing_store = Add<HLoadNamedField>(
9487       buffer, static_cast<HValue*>(NULL),
9488       HObjectAccess::ForJSArrayBufferBackingStore());
9489
9490   HValue* typed_array_start;
9491   if (is_zero_byte_offset) {
9492     typed_array_start = backing_store;
9493   } else {
9494     HInstruction* external_pointer =
9495         AddUncasted<HAdd>(backing_store, byte_offset);
9496     // Arguments are checked prior to call to TypedArrayInitialize,
9497     // including byte_offset.
9498     external_pointer->ClearFlag(HValue::kCanOverflow);
9499     typed_array_start = external_pointer;
9500   }
9501
9502   Add<HStoreNamedField>(elements,
9503       HObjectAccess::ForExternalArrayExternalPointer(),
9504       typed_array_start);
9505
9506   return elements;
9507 }
9508
9509
9510 HValue* HOptimizedGraphBuilder::BuildAllocateFixedTypedArray(
9511     ExternalArrayType array_type, size_t element_size,
9512     ElementsKind fixed_elements_kind,
9513     HValue* byte_length, HValue* length) {
9514   STATIC_ASSERT(
9515       (FixedTypedArrayBase::kHeaderSize & kObjectAlignmentMask) == 0);
9516   HValue* total_size;
9517
9518   // if fixed array's elements are not aligned to object's alignment,
9519   // we need to align the whole array to object alignment.
9520   if (element_size % kObjectAlignment != 0) {
9521     total_size = BuildObjectSizeAlignment(
9522         byte_length, FixedTypedArrayBase::kHeaderSize);
9523   } else {
9524     total_size = AddUncasted<HAdd>(byte_length,
9525         Add<HConstant>(FixedTypedArrayBase::kHeaderSize));
9526     total_size->ClearFlag(HValue::kCanOverflow);
9527   }
9528
9529   // The HForceRepresentation is to prevent possible deopt on int-smi
9530   // conversion after allocation but before the new object fields are set.
9531   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
9532   Handle<Map> fixed_typed_array_map(
9533       isolate()->heap()->MapForFixedTypedArray(array_type));
9534   HValue* elements =
9535       Add<HAllocate>(total_size, HType::HeapObject(),
9536                      NOT_TENURED, fixed_typed_array_map->instance_type());
9537   AddStoreMapConstant(elements, fixed_typed_array_map);
9538
9539   Add<HStoreNamedField>(elements,
9540       HObjectAccess::ForFixedArrayLength(),
9541       length);
9542
9543   HValue* filler = Add<HConstant>(static_cast<int32_t>(0));
9544
9545   {
9546     LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
9547
9548     HValue* key = builder.BeginBody(
9549         Add<HConstant>(static_cast<int32_t>(0)),
9550         length, Token::LT);
9551     Add<HStoreKeyed>(elements, key, filler, fixed_elements_kind);
9552
9553     builder.EndBody();
9554   }
9555   return elements;
9556 }
9557
9558
9559 void HOptimizedGraphBuilder::GenerateTypedArrayInitialize(
9560     CallRuntime* expr) {
9561   ZoneList<Expression*>* arguments = expr->arguments();
9562
9563   static const int kObjectArg = 0;
9564   static const int kArrayIdArg = 1;
9565   static const int kBufferArg = 2;
9566   static const int kByteOffsetArg = 3;
9567   static const int kByteLengthArg = 4;
9568   static const int kArgsLength = 5;
9569   DCHECK(arguments->length() == kArgsLength);
9570
9571
9572   CHECK_ALIVE(VisitForValue(arguments->at(kObjectArg)));
9573   HValue* obj = Pop();
9574
9575   if (arguments->at(kArrayIdArg)->IsLiteral()) {
9576     // This should never happen in real use, but can happen when fuzzing.
9577     // Just bail out.
9578     Bailout(kNeedSmiLiteral);
9579     return;
9580   }
9581   Handle<Object> value =
9582       static_cast<Literal*>(arguments->at(kArrayIdArg))->value();
9583   if (!value->IsSmi()) {
9584     // This should never happen in real use, but can happen when fuzzing.
9585     // Just bail out.
9586     Bailout(kNeedSmiLiteral);
9587     return;
9588   }
9589   int array_id = Smi::cast(*value)->value();
9590
9591   HValue* buffer;
9592   if (!arguments->at(kBufferArg)->IsNullLiteral()) {
9593     CHECK_ALIVE(VisitForValue(arguments->at(kBufferArg)));
9594     buffer = Pop();
9595   } else {
9596     buffer = NULL;
9597   }
9598
9599   HValue* byte_offset;
9600   bool is_zero_byte_offset;
9601
9602   if (arguments->at(kByteOffsetArg)->IsLiteral()
9603       && Smi::FromInt(0) ==
9604       *static_cast<Literal*>(arguments->at(kByteOffsetArg))->value()) {
9605     byte_offset = Add<HConstant>(static_cast<int32_t>(0));
9606     is_zero_byte_offset = true;
9607   } else {
9608     CHECK_ALIVE(VisitForValue(arguments->at(kByteOffsetArg)));
9609     byte_offset = Pop();
9610     is_zero_byte_offset = false;
9611     DCHECK(buffer != NULL);
9612   }
9613
9614   CHECK_ALIVE(VisitForValue(arguments->at(kByteLengthArg)));
9615   HValue* byte_length = Pop();
9616
9617   NoObservableSideEffectsScope scope(this);
9618   IfBuilder byte_offset_smi(this);
9619
9620   if (!is_zero_byte_offset) {
9621     byte_offset_smi.If<HIsSmiAndBranch>(byte_offset);
9622     byte_offset_smi.Then();
9623   }
9624
9625   ExternalArrayType array_type =
9626       kExternalInt8Array;  // Bogus initialization.
9627   size_t element_size = 1;  // Bogus initialization.
9628   ElementsKind external_elements_kind =  // Bogus initialization.
9629       EXTERNAL_INT8_ELEMENTS;
9630   ElementsKind fixed_elements_kind =  // Bogus initialization.
9631       INT8_ELEMENTS;
9632   Runtime::ArrayIdToTypeAndSize(array_id,
9633       &array_type,
9634       &external_elements_kind,
9635       &fixed_elements_kind,
9636       &element_size);
9637
9638
9639   { //  byte_offset is Smi.
9640     BuildArrayBufferViewInitialization<JSTypedArray>(
9641         obj, buffer, byte_offset, byte_length);
9642
9643
9644     HInstruction* length = AddUncasted<HDiv>(byte_length,
9645         Add<HConstant>(static_cast<int32_t>(element_size)));
9646
9647     Add<HStoreNamedField>(obj,
9648         HObjectAccess::ForJSTypedArrayLength(),
9649         length);
9650
9651     HValue* elements;
9652     if (buffer != NULL) {
9653       elements = BuildAllocateExternalElements(
9654           array_type, is_zero_byte_offset, buffer, byte_offset, length);
9655       Handle<Map> obj_map = TypedArrayMap(
9656           isolate(), array_type, external_elements_kind);
9657       AddStoreMapConstant(obj, obj_map);
9658     } else {
9659       DCHECK(is_zero_byte_offset);
9660       elements = BuildAllocateFixedTypedArray(
9661           array_type, element_size, fixed_elements_kind,
9662           byte_length, length);
9663     }
9664     Add<HStoreNamedField>(
9665         obj, HObjectAccess::ForElementsPointer(), elements);
9666   }
9667
9668   if (!is_zero_byte_offset) {
9669     byte_offset_smi.Else();
9670     { //  byte_offset is not Smi.
9671       Push(obj);
9672       CHECK_ALIVE(VisitForValue(arguments->at(kArrayIdArg)));
9673       Push(buffer);
9674       Push(byte_offset);
9675       Push(byte_length);
9676       PushArgumentsFromEnvironment(kArgsLength);
9677       Add<HCallRuntime>(expr->name(), expr->function(), kArgsLength);
9678     }
9679   }
9680   byte_offset_smi.End();
9681 }
9682
9683
9684 void HOptimizedGraphBuilder::GenerateMaxSmi(CallRuntime* expr) {
9685   DCHECK(expr->arguments()->length() == 0);
9686   HConstant* max_smi = New<HConstant>(static_cast<int32_t>(Smi::kMaxValue));
9687   return ast_context()->ReturnInstruction(max_smi, expr->id());
9688 }
9689
9690
9691 void HOptimizedGraphBuilder::GenerateTypedArrayMaxSizeInHeap(
9692     CallRuntime* expr) {
9693   DCHECK(expr->arguments()->length() == 0);
9694   HConstant* result = New<HConstant>(static_cast<int32_t>(
9695         FLAG_typed_array_max_size_in_heap));
9696   return ast_context()->ReturnInstruction(result, expr->id());
9697 }
9698
9699
9700 void HOptimizedGraphBuilder::GenerateArrayBufferGetByteLength(
9701     CallRuntime* expr) {
9702   DCHECK(expr->arguments()->length() == 1);
9703   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
9704   HValue* buffer = Pop();
9705   HInstruction* result = New<HLoadNamedField>(
9706     buffer,
9707     static_cast<HValue*>(NULL),
9708     HObjectAccess::ForJSArrayBufferByteLength());
9709   return ast_context()->ReturnInstruction(result, expr->id());
9710 }
9711
9712
9713 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength(
9714     CallRuntime* expr) {
9715   DCHECK(expr->arguments()->length() == 1);
9716   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
9717   HValue* buffer = Pop();
9718   HInstruction* result = New<HLoadNamedField>(
9719     buffer,
9720     static_cast<HValue*>(NULL),
9721     HObjectAccess::ForJSArrayBufferViewByteLength());
9722   return ast_context()->ReturnInstruction(result, expr->id());
9723 }
9724
9725
9726 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset(
9727     CallRuntime* expr) {
9728   DCHECK(expr->arguments()->length() == 1);
9729   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
9730   HValue* buffer = Pop();
9731   HInstruction* result = New<HLoadNamedField>(
9732     buffer,
9733     static_cast<HValue*>(NULL),
9734     HObjectAccess::ForJSArrayBufferViewByteOffset());
9735   return ast_context()->ReturnInstruction(result, expr->id());
9736 }
9737
9738
9739 void HOptimizedGraphBuilder::GenerateTypedArrayGetLength(
9740     CallRuntime* expr) {
9741   DCHECK(expr->arguments()->length() == 1);
9742   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
9743   HValue* buffer = Pop();
9744   HInstruction* result = New<HLoadNamedField>(
9745     buffer,
9746     static_cast<HValue*>(NULL),
9747     HObjectAccess::ForJSTypedArrayLength());
9748   return ast_context()->ReturnInstruction(result, expr->id());
9749 }
9750
9751
9752 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
9753   DCHECK(!HasStackOverflow());
9754   DCHECK(current_block() != NULL);
9755   DCHECK(current_block()->HasPredecessor());
9756   if (expr->is_jsruntime()) {
9757     return Bailout(kCallToAJavaScriptRuntimeFunction);
9758   }
9759
9760   const Runtime::Function* function = expr->function();
9761   DCHECK(function != NULL);
9762
9763   if (function->intrinsic_type == Runtime::INLINE ||
9764       function->intrinsic_type == Runtime::INLINE_OPTIMIZED) {
9765     DCHECK(expr->name()->length() > 0);
9766     DCHECK(expr->name()->Get(0) == '_');
9767     // Call to an inline function.
9768     int lookup_index = static_cast<int>(function->function_id) -
9769         static_cast<int>(Runtime::kFirstInlineFunction);
9770     DCHECK(lookup_index >= 0);
9771     DCHECK(static_cast<size_t>(lookup_index) <
9772            ARRAY_SIZE(kInlineFunctionGenerators));
9773     InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
9774
9775     // Call the inline code generator using the pointer-to-member.
9776     (this->*generator)(expr);
9777   } else {
9778     DCHECK(function->intrinsic_type == Runtime::RUNTIME);
9779     Handle<String> name = expr->name();
9780     int argument_count = expr->arguments()->length();
9781     CHECK_ALIVE(VisitExpressions(expr->arguments()));
9782     PushArgumentsFromEnvironment(argument_count);
9783     HCallRuntime* call = New<HCallRuntime>(name, function,
9784                                            argument_count);
9785     return ast_context()->ReturnInstruction(call, expr->id());
9786   }
9787 }
9788
9789
9790 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
9791   DCHECK(!HasStackOverflow());
9792   DCHECK(current_block() != NULL);
9793   DCHECK(current_block()->HasPredecessor());
9794   switch (expr->op()) {
9795     case Token::DELETE: return VisitDelete(expr);
9796     case Token::VOID: return VisitVoid(expr);
9797     case Token::TYPEOF: return VisitTypeof(expr);
9798     case Token::NOT: return VisitNot(expr);
9799     default: UNREACHABLE();
9800   }
9801 }
9802
9803
9804 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
9805   Property* prop = expr->expression()->AsProperty();
9806   VariableProxy* proxy = expr->expression()->AsVariableProxy();
9807   if (prop != NULL) {
9808     CHECK_ALIVE(VisitForValue(prop->obj()));
9809     CHECK_ALIVE(VisitForValue(prop->key()));
9810     HValue* key = Pop();
9811     HValue* obj = Pop();
9812     HValue* function = AddLoadJSBuiltin(Builtins::DELETE);
9813     Add<HPushArguments>(obj, key, Add<HConstant>(function_strict_mode()));
9814     // TODO(olivf) InvokeFunction produces a check for the parameter count,
9815     // even though we are certain to pass the correct number of arguments here.
9816     HInstruction* instr = New<HInvokeFunction>(function, 3);
9817     return ast_context()->ReturnInstruction(instr, expr->id());
9818   } else if (proxy != NULL) {
9819     Variable* var = proxy->var();
9820     if (var->IsUnallocated()) {
9821       Bailout(kDeleteWithGlobalVariable);
9822     } else if (var->IsStackAllocated() || var->IsContextSlot()) {
9823       // Result of deleting non-global variables is false.  'this' is not
9824       // really a variable, though we implement it as one.  The
9825       // subexpression does not have side effects.
9826       HValue* value = var->is_this()
9827           ? graph()->GetConstantTrue()
9828           : graph()->GetConstantFalse();
9829       return ast_context()->ReturnValue(value);
9830     } else {
9831       Bailout(kDeleteWithNonGlobalVariable);
9832     }
9833   } else {
9834     // Result of deleting non-property, non-variable reference is true.
9835     // Evaluate the subexpression for side effects.
9836     CHECK_ALIVE(VisitForEffect(expr->expression()));
9837     return ast_context()->ReturnValue(graph()->GetConstantTrue());
9838   }
9839 }
9840
9841
9842 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) {
9843   CHECK_ALIVE(VisitForEffect(expr->expression()));
9844   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
9845 }
9846
9847
9848 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
9849   CHECK_ALIVE(VisitForTypeOf(expr->expression()));
9850   HValue* value = Pop();
9851   HInstruction* instr = New<HTypeof>(value);
9852   return ast_context()->ReturnInstruction(instr, expr->id());
9853 }
9854
9855
9856 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) {
9857   if (ast_context()->IsTest()) {
9858     TestContext* context = TestContext::cast(ast_context());
9859     VisitForControl(expr->expression(),
9860                     context->if_false(),
9861                     context->if_true());
9862     return;
9863   }
9864
9865   if (ast_context()->IsEffect()) {
9866     VisitForEffect(expr->expression());
9867     return;
9868   }
9869
9870   DCHECK(ast_context()->IsValue());
9871   HBasicBlock* materialize_false = graph()->CreateBasicBlock();
9872   HBasicBlock* materialize_true = graph()->CreateBasicBlock();
9873   CHECK_BAILOUT(VisitForControl(expr->expression(),
9874                                 materialize_false,
9875                                 materialize_true));
9876
9877   if (materialize_false->HasPredecessor()) {
9878     materialize_false->SetJoinId(expr->MaterializeFalseId());
9879     set_current_block(materialize_false);
9880     Push(graph()->GetConstantFalse());
9881   } else {
9882     materialize_false = NULL;
9883   }
9884
9885   if (materialize_true->HasPredecessor()) {
9886     materialize_true->SetJoinId(expr->MaterializeTrueId());
9887     set_current_block(materialize_true);
9888     Push(graph()->GetConstantTrue());
9889   } else {
9890     materialize_true = NULL;
9891   }
9892
9893   HBasicBlock* join =
9894     CreateJoin(materialize_false, materialize_true, expr->id());
9895   set_current_block(join);
9896   if (join != NULL) return ast_context()->ReturnValue(Pop());
9897 }
9898
9899
9900 HInstruction* HOptimizedGraphBuilder::BuildIncrement(
9901     bool returns_original_input,
9902     CountOperation* expr) {
9903   // The input to the count operation is on top of the expression stack.
9904   Representation rep = Representation::FromType(expr->type());
9905   if (rep.IsNone() || rep.IsTagged()) {
9906     rep = Representation::Smi();
9907   }
9908
9909   if (returns_original_input) {
9910     // We need an explicit HValue representing ToNumber(input).  The
9911     // actual HChange instruction we need is (sometimes) added in a later
9912     // phase, so it is not available now to be used as an input to HAdd and
9913     // as the return value.
9914     HInstruction* number_input = AddUncasted<HForceRepresentation>(Pop(), rep);
9915     if (!rep.IsDouble()) {
9916       number_input->SetFlag(HInstruction::kFlexibleRepresentation);
9917       number_input->SetFlag(HInstruction::kCannotBeTagged);
9918     }
9919     Push(number_input);
9920   }
9921
9922   // The addition has no side effects, so we do not need
9923   // to simulate the expression stack after this instruction.
9924   // Any later failures deopt to the load of the input or earlier.
9925   HConstant* delta = (expr->op() == Token::INC)
9926       ? graph()->GetConstant1()
9927       : graph()->GetConstantMinus1();
9928   HInstruction* instr = AddUncasted<HAdd>(Top(), delta);
9929   if (instr->IsAdd()) {
9930     HAdd* add = HAdd::cast(instr);
9931     add->set_observed_input_representation(1, rep);
9932     add->set_observed_input_representation(2, Representation::Smi());
9933   }
9934   instr->SetFlag(HInstruction::kCannotBeTagged);
9935   instr->ClearAllSideEffects();
9936   return instr;
9937 }
9938
9939
9940 void HOptimizedGraphBuilder::BuildStoreForEffect(Expression* expr,
9941                                                  Property* prop,
9942                                                  BailoutId ast_id,
9943                                                  BailoutId return_id,
9944                                                  HValue* object,
9945                                                  HValue* key,
9946                                                  HValue* value) {
9947   EffectContext for_effect(this);
9948   Push(object);
9949   if (key != NULL) Push(key);
9950   Push(value);
9951   BuildStore(expr, prop, ast_id, return_id);
9952 }
9953
9954
9955 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
9956   DCHECK(!HasStackOverflow());
9957   DCHECK(current_block() != NULL);
9958   DCHECK(current_block()->HasPredecessor());
9959   if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
9960   Expression* target = expr->expression();
9961   VariableProxy* proxy = target->AsVariableProxy();
9962   Property* prop = target->AsProperty();
9963   if (proxy == NULL && prop == NULL) {
9964     return Bailout(kInvalidLhsInCountOperation);
9965   }
9966
9967   // Match the full code generator stack by simulating an extra stack
9968   // element for postfix operations in a non-effect context.  The return
9969   // value is ToNumber(input).
9970   bool returns_original_input =
9971       expr->is_postfix() && !ast_context()->IsEffect();
9972   HValue* input = NULL;  // ToNumber(original_input).
9973   HValue* after = NULL;  // The result after incrementing or decrementing.
9974
9975   if (proxy != NULL) {
9976     Variable* var = proxy->var();
9977     if (var->mode() == CONST_LEGACY)  {
9978       return Bailout(kUnsupportedCountOperationWithConst);
9979     }
9980     // Argument of the count operation is a variable, not a property.
9981     DCHECK(prop == NULL);
9982     CHECK_ALIVE(VisitForValue(target));
9983
9984     after = BuildIncrement(returns_original_input, expr);
9985     input = returns_original_input ? Top() : Pop();
9986     Push(after);
9987
9988     switch (var->location()) {
9989       case Variable::UNALLOCATED:
9990         HandleGlobalVariableAssignment(var,
9991                                        after,
9992                                        expr->AssignmentId());
9993         break;
9994
9995       case Variable::PARAMETER:
9996       case Variable::LOCAL:
9997         BindIfLive(var, after);
9998         break;
9999
10000       case Variable::CONTEXT: {
10001         // Bail out if we try to mutate a parameter value in a function
10002         // using the arguments object.  We do not (yet) correctly handle the
10003         // arguments property of the function.
10004         if (current_info()->scope()->arguments() != NULL) {
10005           // Parameters will rewrite to context slots.  We have no direct
10006           // way to detect that the variable is a parameter so we use a
10007           // linear search of the parameter list.
10008           int count = current_info()->scope()->num_parameters();
10009           for (int i = 0; i < count; ++i) {
10010             if (var == current_info()->scope()->parameter(i)) {
10011               return Bailout(kAssignmentToParameterInArgumentsObject);
10012             }
10013           }
10014         }
10015
10016         HValue* context = BuildContextChainWalk(var);
10017         HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode())
10018             ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck;
10019         HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
10020                                                           mode, after);
10021         if (instr->HasObservableSideEffects()) {
10022           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
10023         }
10024         break;
10025       }
10026
10027       case Variable::LOOKUP:
10028         return Bailout(kLookupVariableInCountOperation);
10029     }
10030
10031     Drop(returns_original_input ? 2 : 1);
10032     return ast_context()->ReturnValue(expr->is_postfix() ? input : after);
10033   }
10034
10035   // Argument of the count operation is a property.
10036   DCHECK(prop != NULL);
10037   if (returns_original_input) Push(graph()->GetConstantUndefined());
10038
10039   CHECK_ALIVE(VisitForValue(prop->obj()));
10040   HValue* object = Top();
10041
10042   HValue* key = NULL;
10043   if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
10044     CHECK_ALIVE(VisitForValue(prop->key()));
10045     key = Top();
10046   }
10047
10048   CHECK_ALIVE(PushLoad(prop, object, key));
10049
10050   after = BuildIncrement(returns_original_input, expr);
10051
10052   if (returns_original_input) {
10053     input = Pop();
10054     // Drop object and key to push it again in the effect context below.
10055     Drop(key == NULL ? 1 : 2);
10056     environment()->SetExpressionStackAt(0, input);
10057     CHECK_ALIVE(BuildStoreForEffect(
10058         expr, prop, expr->id(), expr->AssignmentId(), object, key, after));
10059     return ast_context()->ReturnValue(Pop());
10060   }
10061
10062   environment()->SetExpressionStackAt(0, after);
10063   return BuildStore(expr, prop, expr->id(), expr->AssignmentId());
10064 }
10065
10066
10067 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt(
10068     HValue* string,
10069     HValue* index) {
10070   if (string->IsConstant() && index->IsConstant()) {
10071     HConstant* c_string = HConstant::cast(string);
10072     HConstant* c_index = HConstant::cast(index);
10073     if (c_string->HasStringValue() && c_index->HasNumberValue()) {
10074       int32_t i = c_index->NumberValueAsInteger32();
10075       Handle<String> s = c_string->StringValue();
10076       if (i < 0 || i >= s->length()) {
10077         return New<HConstant>(base::OS::nan_value());
10078       }
10079       return New<HConstant>(s->Get(i));
10080     }
10081   }
10082   string = BuildCheckString(string);
10083   index = Add<HBoundsCheck>(index, AddLoadStringLength(string));
10084   return New<HStringCharCodeAt>(string, index);
10085 }
10086
10087
10088 // Checks if the given shift amounts have following forms:
10089 // (N1) and (N2) with N1 + N2 = 32; (sa) and (32 - sa).
10090 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa,
10091                                              HValue* const32_minus_sa) {
10092   if (sa->IsConstant() && const32_minus_sa->IsConstant()) {
10093     const HConstant* c1 = HConstant::cast(sa);
10094     const HConstant* c2 = HConstant::cast(const32_minus_sa);
10095     return c1->HasInteger32Value() && c2->HasInteger32Value() &&
10096         (c1->Integer32Value() + c2->Integer32Value() == 32);
10097   }
10098   if (!const32_minus_sa->IsSub()) return false;
10099   HSub* sub = HSub::cast(const32_minus_sa);
10100   return sub->left()->EqualsInteger32Constant(32) && sub->right() == sa;
10101 }
10102
10103
10104 // Checks if the left and the right are shift instructions with the oposite
10105 // directions that can be replaced by one rotate right instruction or not.
10106 // Returns the operand and the shift amount for the rotate instruction in the
10107 // former case.
10108 bool HGraphBuilder::MatchRotateRight(HValue* left,
10109                                      HValue* right,
10110                                      HValue** operand,
10111                                      HValue** shift_amount) {
10112   HShl* shl;
10113   HShr* shr;
10114   if (left->IsShl() && right->IsShr()) {
10115     shl = HShl::cast(left);
10116     shr = HShr::cast(right);
10117   } else if (left->IsShr() && right->IsShl()) {
10118     shl = HShl::cast(right);
10119     shr = HShr::cast(left);
10120   } else {
10121     return false;
10122   }
10123   if (shl->left() != shr->left()) return false;
10124
10125   if (!ShiftAmountsAllowReplaceByRotate(shl->right(), shr->right()) &&
10126       !ShiftAmountsAllowReplaceByRotate(shr->right(), shl->right())) {
10127     return false;
10128   }
10129   *operand= shr->left();
10130   *shift_amount = shr->right();
10131   return true;
10132 }
10133
10134
10135 bool CanBeZero(HValue* right) {
10136   if (right->IsConstant()) {
10137     HConstant* right_const = HConstant::cast(right);
10138     if (right_const->HasInteger32Value() &&
10139        (right_const->Integer32Value() & 0x1f) != 0) {
10140       return false;
10141     }
10142   }
10143   return true;
10144 }
10145
10146
10147 HValue* HGraphBuilder::EnforceNumberType(HValue* number,
10148                                          Type* expected) {
10149   if (expected->Is(Type::SignedSmall())) {
10150     return AddUncasted<HForceRepresentation>(number, Representation::Smi());
10151   }
10152   if (expected->Is(Type::Signed32())) {
10153     return AddUncasted<HForceRepresentation>(number,
10154                                              Representation::Integer32());
10155   }
10156   return number;
10157 }
10158
10159
10160 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Type** expected) {
10161   if (value->IsConstant()) {
10162     HConstant* constant = HConstant::cast(value);
10163     Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone());
10164     if (number.has_value) {
10165       *expected = Type::Number(zone());
10166       return AddInstruction(number.value);
10167     }
10168   }
10169
10170   // We put temporary values on the stack, which don't correspond to anything
10171   // in baseline code. Since nothing is observable we avoid recording those
10172   // pushes with a NoObservableSideEffectsScope.
10173   NoObservableSideEffectsScope no_effects(this);
10174
10175   Type* expected_type = *expected;
10176
10177   // Separate the number type from the rest.
10178   Type* expected_obj =
10179       Type::Intersect(expected_type, Type::NonNumber(zone()), zone());
10180   Type* expected_number =
10181       Type::Intersect(expected_type, Type::Number(zone()), zone());
10182
10183   // We expect to get a number.
10184   // (We need to check first, since Type::None->Is(Type::Any()) == true.
10185   if (expected_obj->Is(Type::None())) {
10186     DCHECK(!expected_number->Is(Type::None(zone())));
10187     return value;
10188   }
10189
10190   if (expected_obj->Is(Type::Undefined(zone()))) {
10191     // This is already done by HChange.
10192     *expected = Type::Union(expected_number, Type::Number(zone()), zone());
10193     return value;
10194   }
10195
10196   return value;
10197 }
10198
10199
10200 HValue* HOptimizedGraphBuilder::BuildBinaryOperation(
10201     BinaryOperation* expr,
10202     HValue* left,
10203     HValue* right,
10204     PushBeforeSimulateBehavior push_sim_result) {
10205   Type* left_type = expr->left()->bounds().lower;
10206   Type* right_type = expr->right()->bounds().lower;
10207   Type* result_type = expr->bounds().lower;
10208   Maybe<int> fixed_right_arg = expr->fixed_right_arg();
10209   Handle<AllocationSite> allocation_site = expr->allocation_site();
10210
10211   HAllocationMode allocation_mode;
10212   if (FLAG_allocation_site_pretenuring && !allocation_site.is_null()) {
10213     allocation_mode = HAllocationMode(allocation_site);
10214   }
10215
10216   HValue* result = HGraphBuilder::BuildBinaryOperation(
10217       expr->op(), left, right, left_type, right_type, result_type,
10218       fixed_right_arg, allocation_mode);
10219   // Add a simulate after instructions with observable side effects, and
10220   // after phis, which are the result of BuildBinaryOperation when we
10221   // inlined some complex subgraph.
10222   if (result->HasObservableSideEffects() || result->IsPhi()) {
10223     if (push_sim_result == PUSH_BEFORE_SIMULATE) {
10224       Push(result);
10225       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
10226       Drop(1);
10227     } else {
10228       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
10229     }
10230   }
10231   return result;
10232 }
10233
10234
10235 HValue* HGraphBuilder::BuildBinaryOperation(
10236     Token::Value op,
10237     HValue* left,
10238     HValue* right,
10239     Type* left_type,
10240     Type* right_type,
10241     Type* result_type,
10242     Maybe<int> fixed_right_arg,
10243     HAllocationMode allocation_mode) {
10244
10245   Representation left_rep = Representation::FromType(left_type);
10246   Representation right_rep = Representation::FromType(right_type);
10247
10248   bool maybe_string_add = op == Token::ADD &&
10249                           (left_type->Maybe(Type::String()) ||
10250                            left_type->Maybe(Type::Receiver()) ||
10251                            right_type->Maybe(Type::String()) ||
10252                            right_type->Maybe(Type::Receiver()));
10253
10254   if (left_type->Is(Type::None())) {
10255     Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation",
10256                      Deoptimizer::SOFT);
10257     // TODO(rossberg): we should be able to get rid of non-continuous
10258     // defaults.
10259     left_type = Type::Any(zone());
10260   } else {
10261     if (!maybe_string_add) left = TruncateToNumber(left, &left_type);
10262     left_rep = Representation::FromType(left_type);
10263   }
10264
10265   if (right_type->Is(Type::None())) {
10266     Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation",
10267                      Deoptimizer::SOFT);
10268     right_type = Type::Any(zone());
10269   } else {
10270     if (!maybe_string_add) right = TruncateToNumber(right, &right_type);
10271     right_rep = Representation::FromType(right_type);
10272   }
10273
10274   // Special case for string addition here.
10275   if (op == Token::ADD &&
10276       (left_type->Is(Type::String()) || right_type->Is(Type::String()))) {
10277     // Validate type feedback for left argument.
10278     if (left_type->Is(Type::String())) {
10279       left = BuildCheckString(left);
10280     }
10281
10282     // Validate type feedback for right argument.
10283     if (right_type->Is(Type::String())) {
10284       right = BuildCheckString(right);
10285     }
10286
10287     // Convert left argument as necessary.
10288     if (left_type->Is(Type::Number())) {
10289       DCHECK(right_type->Is(Type::String()));
10290       left = BuildNumberToString(left, left_type);
10291     } else if (!left_type->Is(Type::String())) {
10292       DCHECK(right_type->Is(Type::String()));
10293       HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_RIGHT);
10294       Add<HPushArguments>(left, right);
10295       return AddUncasted<HInvokeFunction>(function, 2);
10296     }
10297
10298     // Convert right argument as necessary.
10299     if (right_type->Is(Type::Number())) {
10300       DCHECK(left_type->Is(Type::String()));
10301       right = BuildNumberToString(right, right_type);
10302     } else if (!right_type->Is(Type::String())) {
10303       DCHECK(left_type->Is(Type::String()));
10304       HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT);
10305       Add<HPushArguments>(left, right);
10306       return AddUncasted<HInvokeFunction>(function, 2);
10307     }
10308
10309     // Fast path for empty constant strings.
10310     if (left->IsConstant() &&
10311         HConstant::cast(left)->HasStringValue() &&
10312         HConstant::cast(left)->StringValue()->length() == 0) {
10313       return right;
10314     }
10315     if (right->IsConstant() &&
10316         HConstant::cast(right)->HasStringValue() &&
10317         HConstant::cast(right)->StringValue()->length() == 0) {
10318       return left;
10319     }
10320
10321     // Register the dependent code with the allocation site.
10322     if (!allocation_mode.feedback_site().is_null()) {
10323       DCHECK(!graph()->info()->IsStub());
10324       Handle<AllocationSite> site(allocation_mode.feedback_site());
10325       AllocationSite::AddDependentCompilationInfo(
10326           site, AllocationSite::TENURING, top_info());
10327     }
10328
10329     // Inline the string addition into the stub when creating allocation
10330     // mementos to gather allocation site feedback, or if we can statically
10331     // infer that we're going to create a cons string.
10332     if ((graph()->info()->IsStub() &&
10333          allocation_mode.CreateAllocationMementos()) ||
10334         (left->IsConstant() &&
10335          HConstant::cast(left)->HasStringValue() &&
10336          HConstant::cast(left)->StringValue()->length() + 1 >=
10337            ConsString::kMinLength) ||
10338         (right->IsConstant() &&
10339          HConstant::cast(right)->HasStringValue() &&
10340          HConstant::cast(right)->StringValue()->length() + 1 >=
10341            ConsString::kMinLength)) {
10342       return BuildStringAdd(left, right, allocation_mode);
10343     }
10344
10345     // Fallback to using the string add stub.
10346     return AddUncasted<HStringAdd>(
10347         left, right, allocation_mode.GetPretenureMode(),
10348         STRING_ADD_CHECK_NONE, allocation_mode.feedback_site());
10349   }
10350
10351   if (graph()->info()->IsStub()) {
10352     left = EnforceNumberType(left, left_type);
10353     right = EnforceNumberType(right, right_type);
10354   }
10355
10356   Representation result_rep = Representation::FromType(result_type);
10357
10358   bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) ||
10359                           (right_rep.IsTagged() && !right_rep.IsSmi());
10360
10361   HInstruction* instr = NULL;
10362   // Only the stub is allowed to call into the runtime, since otherwise we would
10363   // inline several instructions (including the two pushes) for every tagged
10364   // operation in optimized code, which is more expensive, than a stub call.
10365   if (graph()->info()->IsStub() && is_non_primitive) {
10366     HValue* function = AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op));
10367     Add<HPushArguments>(left, right);
10368     instr = AddUncasted<HInvokeFunction>(function, 2);
10369   } else {
10370     switch (op) {
10371       case Token::ADD:
10372         instr = AddUncasted<HAdd>(left, right);
10373         break;
10374       case Token::SUB:
10375         instr = AddUncasted<HSub>(left, right);
10376         break;
10377       case Token::MUL:
10378         instr = AddUncasted<HMul>(left, right);
10379         break;
10380       case Token::MOD: {
10381         if (fixed_right_arg.has_value &&
10382             !right->EqualsInteger32Constant(fixed_right_arg.value)) {
10383           HConstant* fixed_right = Add<HConstant>(
10384               static_cast<int>(fixed_right_arg.value));
10385           IfBuilder if_same(this);
10386           if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ);
10387           if_same.Then();
10388           if_same.ElseDeopt("Unexpected RHS of binary operation");
10389           right = fixed_right;
10390         }
10391         instr = AddUncasted<HMod>(left, right);
10392         break;
10393       }
10394       case Token::DIV:
10395         instr = AddUncasted<HDiv>(left, right);
10396         break;
10397       case Token::BIT_XOR:
10398       case Token::BIT_AND:
10399         instr = AddUncasted<HBitwise>(op, left, right);
10400         break;
10401       case Token::BIT_OR: {
10402         HValue* operand, *shift_amount;
10403         if (left_type->Is(Type::Signed32()) &&
10404             right_type->Is(Type::Signed32()) &&
10405             MatchRotateRight(left, right, &operand, &shift_amount)) {
10406           instr = AddUncasted<HRor>(operand, shift_amount);
10407         } else {
10408           instr = AddUncasted<HBitwise>(op, left, right);
10409         }
10410         break;
10411       }
10412       case Token::SAR:
10413         instr = AddUncasted<HSar>(left, right);
10414         break;
10415       case Token::SHR:
10416         instr = AddUncasted<HShr>(left, right);
10417         if (FLAG_opt_safe_uint32_operations && instr->IsShr() &&
10418             CanBeZero(right)) {
10419           graph()->RecordUint32Instruction(instr);
10420         }
10421         break;
10422       case Token::SHL:
10423         instr = AddUncasted<HShl>(left, right);
10424         break;
10425       default:
10426         UNREACHABLE();
10427     }
10428   }
10429
10430   if (instr->IsBinaryOperation()) {
10431     HBinaryOperation* binop = HBinaryOperation::cast(instr);
10432     binop->set_observed_input_representation(1, left_rep);
10433     binop->set_observed_input_representation(2, right_rep);
10434     binop->initialize_output_representation(result_rep);
10435     if (graph()->info()->IsStub()) {
10436       // Stub should not call into stub.
10437       instr->SetFlag(HValue::kCannotBeTagged);
10438       // And should truncate on HForceRepresentation already.
10439       if (left->IsForceRepresentation()) {
10440         left->CopyFlag(HValue::kTruncatingToSmi, instr);
10441         left->CopyFlag(HValue::kTruncatingToInt32, instr);
10442       }
10443       if (right->IsForceRepresentation()) {
10444         right->CopyFlag(HValue::kTruncatingToSmi, instr);
10445         right->CopyFlag(HValue::kTruncatingToInt32, instr);
10446       }
10447     }
10448   }
10449   return instr;
10450 }
10451
10452
10453 // Check for the form (%_ClassOf(foo) === 'BarClass').
10454 static bool IsClassOfTest(CompareOperation* expr) {
10455   if (expr->op() != Token::EQ_STRICT) return false;
10456   CallRuntime* call = expr->left()->AsCallRuntime();
10457   if (call == NULL) return false;
10458   Literal* literal = expr->right()->AsLiteral();
10459   if (literal == NULL) return false;
10460   if (!literal->value()->IsString()) return false;
10461   if (!call->name()->IsOneByteEqualTo(STATIC_ASCII_VECTOR("_ClassOf"))) {
10462     return false;
10463   }
10464   DCHECK(call->arguments()->length() == 1);
10465   return true;
10466 }
10467
10468
10469 void HOptimizedGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
10470   DCHECK(!HasStackOverflow());
10471   DCHECK(current_block() != NULL);
10472   DCHECK(current_block()->HasPredecessor());
10473   switch (expr->op()) {
10474     case Token::COMMA:
10475       return VisitComma(expr);
10476     case Token::OR:
10477     case Token::AND:
10478       return VisitLogicalExpression(expr);
10479     default:
10480       return VisitArithmeticExpression(expr);
10481   }
10482 }
10483
10484
10485 void HOptimizedGraphBuilder::VisitComma(BinaryOperation* expr) {
10486   CHECK_ALIVE(VisitForEffect(expr->left()));
10487   // Visit the right subexpression in the same AST context as the entire
10488   // expression.
10489   Visit(expr->right());
10490 }
10491
10492
10493 void HOptimizedGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
10494   bool is_logical_and = expr->op() == Token::AND;
10495   if (ast_context()->IsTest()) {
10496     TestContext* context = TestContext::cast(ast_context());
10497     // Translate left subexpression.
10498     HBasicBlock* eval_right = graph()->CreateBasicBlock();
10499     if (is_logical_and) {
10500       CHECK_BAILOUT(VisitForControl(expr->left(),
10501                                     eval_right,
10502                                     context->if_false()));
10503     } else {
10504       CHECK_BAILOUT(VisitForControl(expr->left(),
10505                                     context->if_true(),
10506                                     eval_right));
10507     }
10508
10509     // Translate right subexpression by visiting it in the same AST
10510     // context as the entire expression.
10511     if (eval_right->HasPredecessor()) {
10512       eval_right->SetJoinId(expr->RightId());
10513       set_current_block(eval_right);
10514       Visit(expr->right());
10515     }
10516
10517   } else if (ast_context()->IsValue()) {
10518     CHECK_ALIVE(VisitForValue(expr->left()));
10519     DCHECK(current_block() != NULL);
10520     HValue* left_value = Top();
10521
10522     // Short-circuit left values that always evaluate to the same boolean value.
10523     if (expr->left()->ToBooleanIsTrue() || expr->left()->ToBooleanIsFalse()) {
10524       // l (evals true)  && r -> r
10525       // l (evals true)  || r -> l
10526       // l (evals false) && r -> l
10527       // l (evals false) || r -> r
10528       if (is_logical_and == expr->left()->ToBooleanIsTrue()) {
10529         Drop(1);
10530         CHECK_ALIVE(VisitForValue(expr->right()));
10531       }
10532       return ast_context()->ReturnValue(Pop());
10533     }
10534
10535     // We need an extra block to maintain edge-split form.
10536     HBasicBlock* empty_block = graph()->CreateBasicBlock();
10537     HBasicBlock* eval_right = graph()->CreateBasicBlock();
10538     ToBooleanStub::Types expected(expr->left()->to_boolean_types());
10539     HBranch* test = is_logical_and
10540         ? New<HBranch>(left_value, expected, eval_right, empty_block)
10541         : New<HBranch>(left_value, expected, empty_block, eval_right);
10542     FinishCurrentBlock(test);
10543
10544     set_current_block(eval_right);
10545     Drop(1);  // Value of the left subexpression.
10546     CHECK_BAILOUT(VisitForValue(expr->right()));
10547
10548     HBasicBlock* join_block =
10549       CreateJoin(empty_block, current_block(), expr->id());
10550     set_current_block(join_block);
10551     return ast_context()->ReturnValue(Pop());
10552
10553   } else {
10554     DCHECK(ast_context()->IsEffect());
10555     // In an effect context, we don't need the value of the left subexpression,
10556     // only its control flow and side effects.  We need an extra block to
10557     // maintain edge-split form.
10558     HBasicBlock* empty_block = graph()->CreateBasicBlock();
10559     HBasicBlock* right_block = graph()->CreateBasicBlock();
10560     if (is_logical_and) {
10561       CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
10562     } else {
10563       CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
10564     }
10565
10566     // TODO(kmillikin): Find a way to fix this.  It's ugly that there are
10567     // actually two empty blocks (one here and one inserted by
10568     // TestContext::BuildBranch, and that they both have an HSimulate though the
10569     // second one is not a merge node, and that we really have no good AST ID to
10570     // put on that first HSimulate.
10571
10572     if (empty_block->HasPredecessor()) {
10573       empty_block->SetJoinId(expr->id());
10574     } else {
10575       empty_block = NULL;
10576     }
10577
10578     if (right_block->HasPredecessor()) {
10579       right_block->SetJoinId(expr->RightId());
10580       set_current_block(right_block);
10581       CHECK_BAILOUT(VisitForEffect(expr->right()));
10582       right_block = current_block();
10583     } else {
10584       right_block = NULL;
10585     }
10586
10587     HBasicBlock* join_block =
10588       CreateJoin(empty_block, right_block, expr->id());
10589     set_current_block(join_block);
10590     // We did not materialize any value in the predecessor environments,
10591     // so there is no need to handle it here.
10592   }
10593 }
10594
10595
10596 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
10597   CHECK_ALIVE(VisitForValue(expr->left()));
10598   CHECK_ALIVE(VisitForValue(expr->right()));
10599   SetSourcePosition(expr->position());
10600   HValue* right = Pop();
10601   HValue* left = Pop();
10602   HValue* result =
10603       BuildBinaryOperation(expr, left, right,
10604           ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
10605                                     : PUSH_BEFORE_SIMULATE);
10606   if (FLAG_hydrogen_track_positions && result->IsBinaryOperation()) {
10607     HBinaryOperation::cast(result)->SetOperandPositions(
10608         zone(),
10609         ScriptPositionToSourcePosition(expr->left()->position()),
10610         ScriptPositionToSourcePosition(expr->right()->position()));
10611   }
10612   return ast_context()->ReturnValue(result);
10613 }
10614
10615
10616 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
10617                                                         Expression* sub_expr,
10618                                                         Handle<String> check) {
10619   CHECK_ALIVE(VisitForTypeOf(sub_expr));
10620   SetSourcePosition(expr->position());
10621   HValue* value = Pop();
10622   HTypeofIsAndBranch* instr = New<HTypeofIsAndBranch>(value, check);
10623   return ast_context()->ReturnControl(instr, expr->id());
10624 }
10625
10626
10627 static bool IsLiteralCompareBool(Isolate* isolate,
10628                                  HValue* left,
10629                                  Token::Value op,
10630                                  HValue* right) {
10631   return op == Token::EQ_STRICT &&
10632       ((left->IsConstant() &&
10633           HConstant::cast(left)->handle(isolate)->IsBoolean()) ||
10634        (right->IsConstant() &&
10635            HConstant::cast(right)->handle(isolate)->IsBoolean()));
10636 }
10637
10638
10639 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
10640   DCHECK(!HasStackOverflow());
10641   DCHECK(current_block() != NULL);
10642   DCHECK(current_block()->HasPredecessor());
10643
10644   if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
10645
10646   // Check for a few fast cases. The AST visiting behavior must be in sync
10647   // with the full codegen: We don't push both left and right values onto
10648   // the expression stack when one side is a special-case literal.
10649   Expression* sub_expr = NULL;
10650   Handle<String> check;
10651   if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
10652     return HandleLiteralCompareTypeof(expr, sub_expr, check);
10653   }
10654   if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) {
10655     return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
10656   }
10657   if (expr->IsLiteralCompareNull(&sub_expr)) {
10658     return HandleLiteralCompareNil(expr, sub_expr, kNullValue);
10659   }
10660
10661   if (IsClassOfTest(expr)) {
10662     CallRuntime* call = expr->left()->AsCallRuntime();
10663     DCHECK(call->arguments()->length() == 1);
10664     CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10665     HValue* value = Pop();
10666     Literal* literal = expr->right()->AsLiteral();
10667     Handle<String> rhs = Handle<String>::cast(literal->value());
10668     HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs);
10669     return ast_context()->ReturnControl(instr, expr->id());
10670   }
10671
10672   Type* left_type = expr->left()->bounds().lower;
10673   Type* right_type = expr->right()->bounds().lower;
10674   Type* combined_type = expr->combined_type();
10675
10676   CHECK_ALIVE(VisitForValue(expr->left()));
10677   CHECK_ALIVE(VisitForValue(expr->right()));
10678
10679   if (FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
10680
10681   HValue* right = Pop();
10682   HValue* left = Pop();
10683   Token::Value op = expr->op();
10684
10685   if (IsLiteralCompareBool(isolate(), left, op, right)) {
10686     HCompareObjectEqAndBranch* result =
10687         New<HCompareObjectEqAndBranch>(left, right);
10688     return ast_context()->ReturnControl(result, expr->id());
10689   }
10690
10691   if (op == Token::INSTANCEOF) {
10692     // Check to see if the rhs of the instanceof is a global function not
10693     // residing in new space. If it is we assume that the function will stay the
10694     // same.
10695     Handle<JSFunction> target = Handle<JSFunction>::null();
10696     VariableProxy* proxy = expr->right()->AsVariableProxy();
10697     bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated();
10698     if (global_function &&
10699         current_info()->has_global_object() &&
10700         !current_info()->global_object()->IsAccessCheckNeeded()) {
10701       Handle<String> name = proxy->name();
10702       Handle<GlobalObject> global(current_info()->global_object());
10703       LookupIterator it(global, name, LookupIterator::CHECK_PROPERTY);
10704       Handle<Object> value = JSObject::GetDataProperty(&it);
10705       if (it.IsFound() && value->IsJSFunction()) {
10706         Handle<JSFunction> candidate = Handle<JSFunction>::cast(value);
10707         // If the function is in new space we assume it's more likely to
10708         // change and thus prefer the general IC code.
10709         if (!isolate()->heap()->InNewSpace(*candidate)) {
10710           target = candidate;
10711         }
10712       }
10713     }
10714
10715     // If the target is not null we have found a known global function that is
10716     // assumed to stay the same for this instanceof.
10717     if (target.is_null()) {
10718       HInstanceOf* result = New<HInstanceOf>(left, right);
10719       return ast_context()->ReturnInstruction(result, expr->id());
10720     } else {
10721       Add<HCheckValue>(right, target);
10722       HInstanceOfKnownGlobal* result =
10723         New<HInstanceOfKnownGlobal>(left, target);
10724       return ast_context()->ReturnInstruction(result, expr->id());
10725     }
10726
10727     // Code below assumes that we don't fall through.
10728     UNREACHABLE();
10729   } else if (op == Token::IN) {
10730     HValue* function = AddLoadJSBuiltin(Builtins::IN);
10731     Add<HPushArguments>(left, right);
10732     // TODO(olivf) InvokeFunction produces a check for the parameter count,
10733     // even though we are certain to pass the correct number of arguments here.
10734     HInstruction* result = New<HInvokeFunction>(function, 2);
10735     return ast_context()->ReturnInstruction(result, expr->id());
10736   }
10737
10738   PushBeforeSimulateBehavior push_behavior =
10739     ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
10740                               : PUSH_BEFORE_SIMULATE;
10741   HControlInstruction* compare = BuildCompareInstruction(
10742       op, left, right, left_type, right_type, combined_type,
10743       ScriptPositionToSourcePosition(expr->left()->position()),
10744       ScriptPositionToSourcePosition(expr->right()->position()),
10745       push_behavior, expr->id());
10746   if (compare == NULL) return;  // Bailed out.
10747   return ast_context()->ReturnControl(compare, expr->id());
10748 }
10749
10750
10751 HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
10752     Token::Value op,
10753     HValue* left,
10754     HValue* right,
10755     Type* left_type,
10756     Type* right_type,
10757     Type* combined_type,
10758     HSourcePosition left_position,
10759     HSourcePosition right_position,
10760     PushBeforeSimulateBehavior push_sim_result,
10761     BailoutId bailout_id) {
10762   // Cases handled below depend on collected type feedback. They should
10763   // soft deoptimize when there is no type feedback.
10764   if (combined_type->Is(Type::None())) {
10765     Add<HDeoptimize>("Insufficient type feedback for combined type "
10766                      "of binary operation",
10767                      Deoptimizer::SOFT);
10768     combined_type = left_type = right_type = Type::Any(zone());
10769   }
10770
10771   Representation left_rep = Representation::FromType(left_type);
10772   Representation right_rep = Representation::FromType(right_type);
10773   Representation combined_rep = Representation::FromType(combined_type);
10774
10775   if (combined_type->Is(Type::Receiver())) {
10776     if (Token::IsEqualityOp(op)) {
10777       // HCompareObjectEqAndBranch can only deal with object, so
10778       // exclude numbers.
10779       if ((left->IsConstant() &&
10780            HConstant::cast(left)->HasNumberValue()) ||
10781           (right->IsConstant() &&
10782            HConstant::cast(right)->HasNumberValue())) {
10783         Add<HDeoptimize>("Type mismatch between feedback and constant",
10784                          Deoptimizer::SOFT);
10785         // The caller expects a branch instruction, so make it happy.
10786         return New<HBranch>(graph()->GetConstantTrue());
10787       }
10788       // Can we get away with map check and not instance type check?
10789       HValue* operand_to_check =
10790           left->block()->block_id() < right->block()->block_id() ? left : right;
10791       if (combined_type->IsClass()) {
10792         Handle<Map> map = combined_type->AsClass()->Map();
10793         AddCheckMap(operand_to_check, map);
10794         HCompareObjectEqAndBranch* result =
10795             New<HCompareObjectEqAndBranch>(left, right);
10796         if (FLAG_hydrogen_track_positions) {
10797           result->set_operand_position(zone(), 0, left_position);
10798           result->set_operand_position(zone(), 1, right_position);
10799         }
10800         return result;
10801       } else {
10802         BuildCheckHeapObject(operand_to_check);
10803         Add<HCheckInstanceType>(operand_to_check,
10804                                 HCheckInstanceType::IS_SPEC_OBJECT);
10805         HCompareObjectEqAndBranch* result =
10806             New<HCompareObjectEqAndBranch>(left, right);
10807         return result;
10808       }
10809     } else {
10810       Bailout(kUnsupportedNonPrimitiveCompare);
10811       return NULL;
10812     }
10813   } else if (combined_type->Is(Type::InternalizedString()) &&
10814              Token::IsEqualityOp(op)) {
10815     // If we have a constant argument, it should be consistent with the type
10816     // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch).
10817     if ((left->IsConstant() &&
10818          !HConstant::cast(left)->HasInternalizedStringValue()) ||
10819         (right->IsConstant() &&
10820          !HConstant::cast(right)->HasInternalizedStringValue())) {
10821       Add<HDeoptimize>("Type mismatch between feedback and constant",
10822                        Deoptimizer::SOFT);
10823       // The caller expects a branch instruction, so make it happy.
10824       return New<HBranch>(graph()->GetConstantTrue());
10825     }
10826     BuildCheckHeapObject(left);
10827     Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING);
10828     BuildCheckHeapObject(right);
10829     Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING);
10830     HCompareObjectEqAndBranch* result =
10831         New<HCompareObjectEqAndBranch>(left, right);
10832     return result;
10833   } else if (combined_type->Is(Type::String())) {
10834     BuildCheckHeapObject(left);
10835     Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING);
10836     BuildCheckHeapObject(right);
10837     Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING);
10838     HStringCompareAndBranch* result =
10839         New<HStringCompareAndBranch>(left, right, op);
10840     return result;
10841   } else {
10842     if (combined_rep.IsTagged() || combined_rep.IsNone()) {
10843       HCompareGeneric* result = Add<HCompareGeneric>(left, right, op);
10844       result->set_observed_input_representation(1, left_rep);
10845       result->set_observed_input_representation(2, right_rep);
10846       if (result->HasObservableSideEffects()) {
10847         if (push_sim_result == PUSH_BEFORE_SIMULATE) {
10848           Push(result);
10849           AddSimulate(bailout_id, REMOVABLE_SIMULATE);
10850           Drop(1);
10851         } else {
10852           AddSimulate(bailout_id, REMOVABLE_SIMULATE);
10853         }
10854       }
10855       // TODO(jkummerow): Can we make this more efficient?
10856       HBranch* branch = New<HBranch>(result);
10857       return branch;
10858     } else {
10859       HCompareNumericAndBranch* result =
10860           New<HCompareNumericAndBranch>(left, right, op);
10861       result->set_observed_input_representation(left_rep, right_rep);
10862       if (FLAG_hydrogen_track_positions) {
10863         result->SetOperandPositions(zone(), left_position, right_position);
10864       }
10865       return result;
10866     }
10867   }
10868 }
10869
10870
10871 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
10872                                                      Expression* sub_expr,
10873                                                      NilValue nil) {
10874   DCHECK(!HasStackOverflow());
10875   DCHECK(current_block() != NULL);
10876   DCHECK(current_block()->HasPredecessor());
10877   DCHECK(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
10878   if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
10879   CHECK_ALIVE(VisitForValue(sub_expr));
10880   HValue* value = Pop();
10881   if (expr->op() == Token::EQ_STRICT) {
10882     HConstant* nil_constant = nil == kNullValue
10883         ? graph()->GetConstantNull()
10884         : graph()->GetConstantUndefined();
10885     HCompareObjectEqAndBranch* instr =
10886         New<HCompareObjectEqAndBranch>(value, nil_constant);
10887     return ast_context()->ReturnControl(instr, expr->id());
10888   } else {
10889     DCHECK_EQ(Token::EQ, expr->op());
10890     Type* type = expr->combined_type()->Is(Type::None())
10891         ? Type::Any(zone()) : expr->combined_type();
10892     HIfContinuation continuation;
10893     BuildCompareNil(value, type, &continuation);
10894     return ast_context()->ReturnContinuation(&continuation, expr->id());
10895   }
10896 }
10897
10898
10899 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
10900   // If we share optimized code between different closures, the
10901   // this-function is not a constant, except inside an inlined body.
10902   if (function_state()->outer() != NULL) {
10903       return New<HConstant>(
10904           function_state()->compilation_info()->closure());
10905   } else {
10906       return New<HThisFunction>();
10907   }
10908 }
10909
10910
10911 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
10912     Handle<JSObject> boilerplate_object,
10913     AllocationSiteUsageContext* site_context) {
10914   NoObservableSideEffectsScope no_effects(this);
10915   InstanceType instance_type = boilerplate_object->map()->instance_type();
10916   DCHECK(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE);
10917
10918   HType type = instance_type == JS_ARRAY_TYPE
10919       ? HType::JSArray() : HType::JSObject();
10920   HValue* object_size_constant = Add<HConstant>(
10921       boilerplate_object->map()->instance_size());
10922
10923   PretenureFlag pretenure_flag = NOT_TENURED;
10924   if (FLAG_allocation_site_pretenuring) {
10925     pretenure_flag = site_context->current()->GetPretenureMode();
10926     Handle<AllocationSite> site(site_context->current());
10927     AllocationSite::AddDependentCompilationInfo(
10928         site, AllocationSite::TENURING, top_info());
10929   }
10930
10931   HInstruction* object = Add<HAllocate>(object_size_constant, type,
10932       pretenure_flag, instance_type, site_context->current());
10933
10934   // If allocation folding reaches Page::kMaxRegularHeapObjectSize the
10935   // elements array may not get folded into the object. Hence, we set the
10936   // elements pointer to empty fixed array and let store elimination remove
10937   // this store in the folding case.
10938   HConstant* empty_fixed_array = Add<HConstant>(
10939       isolate()->factory()->empty_fixed_array());
10940   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
10941       empty_fixed_array);
10942
10943   BuildEmitObjectHeader(boilerplate_object, object);
10944
10945   Handle<FixedArrayBase> elements(boilerplate_object->elements());
10946   int elements_size = (elements->length() > 0 &&
10947       elements->map() != isolate()->heap()->fixed_cow_array_map()) ?
10948           elements->Size() : 0;
10949
10950   if (pretenure_flag == TENURED &&
10951       elements->map() == isolate()->heap()->fixed_cow_array_map() &&
10952       isolate()->heap()->InNewSpace(*elements)) {
10953     // If we would like to pretenure a fixed cow array, we must ensure that the
10954     // array is already in old space, otherwise we'll create too many old-to-
10955     // new-space pointers (overflowing the store buffer).
10956     elements = Handle<FixedArrayBase>(
10957         isolate()->factory()->CopyAndTenureFixedCOWArray(
10958             Handle<FixedArray>::cast(elements)));
10959     boilerplate_object->set_elements(*elements);
10960   }
10961
10962   HInstruction* object_elements = NULL;
10963   if (elements_size > 0) {
10964     HValue* object_elements_size = Add<HConstant>(elements_size);
10965     InstanceType instance_type = boilerplate_object->HasFastDoubleElements()
10966         ? FIXED_DOUBLE_ARRAY_TYPE : FIXED_ARRAY_TYPE;
10967     object_elements = Add<HAllocate>(
10968         object_elements_size, HType::HeapObject(),
10969         pretenure_flag, instance_type, site_context->current());
10970   }
10971   BuildInitElementsInObjectHeader(boilerplate_object, object, object_elements);
10972
10973   // Copy object elements if non-COW.
10974   if (object_elements != NULL) {
10975     BuildEmitElements(boilerplate_object, elements, object_elements,
10976                       site_context);
10977   }
10978
10979   // Copy in-object properties.
10980   if (boilerplate_object->map()->NumberOfFields() != 0) {
10981     BuildEmitInObjectProperties(boilerplate_object, object, site_context,
10982                                 pretenure_flag);
10983   }
10984   return object;
10985 }
10986
10987
10988 void HOptimizedGraphBuilder::BuildEmitObjectHeader(
10989     Handle<JSObject> boilerplate_object,
10990     HInstruction* object) {
10991   DCHECK(boilerplate_object->properties()->length() == 0);
10992
10993   Handle<Map> boilerplate_object_map(boilerplate_object->map());
10994   AddStoreMapConstant(object, boilerplate_object_map);
10995
10996   Handle<Object> properties_field =
10997       Handle<Object>(boilerplate_object->properties(), isolate());
10998   DCHECK(*properties_field == isolate()->heap()->empty_fixed_array());
10999   HInstruction* properties = Add<HConstant>(properties_field);
11000   HObjectAccess access = HObjectAccess::ForPropertiesPointer();
11001   Add<HStoreNamedField>(object, access, properties);
11002
11003   if (boilerplate_object->IsJSArray()) {
11004     Handle<JSArray> boilerplate_array =
11005         Handle<JSArray>::cast(boilerplate_object);
11006     Handle<Object> length_field =
11007         Handle<Object>(boilerplate_array->length(), isolate());
11008     HInstruction* length = Add<HConstant>(length_field);
11009
11010     DCHECK(boilerplate_array->length()->IsSmi());
11011     Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(
11012         boilerplate_array->GetElementsKind()), length);
11013   }
11014 }
11015
11016
11017 void HOptimizedGraphBuilder::BuildInitElementsInObjectHeader(
11018     Handle<JSObject> boilerplate_object,
11019     HInstruction* object,
11020     HInstruction* object_elements) {
11021   DCHECK(boilerplate_object->properties()->length() == 0);
11022   if (object_elements == NULL) {
11023     Handle<Object> elements_field =
11024         Handle<Object>(boilerplate_object->elements(), isolate());
11025     object_elements = Add<HConstant>(elements_field);
11026   }
11027   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
11028       object_elements);
11029 }
11030
11031
11032 void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
11033     Handle<JSObject> boilerplate_object,
11034     HInstruction* object,
11035     AllocationSiteUsageContext* site_context,
11036     PretenureFlag pretenure_flag) {
11037   Handle<Map> boilerplate_map(boilerplate_object->map());
11038   Handle<DescriptorArray> descriptors(boilerplate_map->instance_descriptors());
11039   int limit = boilerplate_map->NumberOfOwnDescriptors();
11040
11041   int copied_fields = 0;
11042   for (int i = 0; i < limit; i++) {
11043     PropertyDetails details = descriptors->GetDetails(i);
11044     if (details.type() != FIELD) continue;
11045     copied_fields++;
11046     int index = descriptors->GetFieldIndex(i);
11047     int property_offset = boilerplate_object->GetInObjectPropertyOffset(index);
11048     Handle<Name> name(descriptors->GetKey(i));
11049     Handle<Object> value =
11050         Handle<Object>(boilerplate_object->InObjectPropertyAt(index),
11051         isolate());
11052
11053     // The access for the store depends on the type of the boilerplate.
11054     HObjectAccess access = boilerplate_object->IsJSArray() ?
11055         HObjectAccess::ForJSArrayOffset(property_offset) :
11056         HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
11057
11058     if (value->IsJSObject()) {
11059       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
11060       Handle<AllocationSite> current_site = site_context->EnterNewScope();
11061       HInstruction* result =
11062           BuildFastLiteral(value_object, site_context);
11063       site_context->ExitScope(current_site, value_object);
11064       Add<HStoreNamedField>(object, access, result);
11065     } else {
11066       Representation representation = details.representation();
11067       HInstruction* value_instruction;
11068
11069       if (representation.IsDouble()) {
11070         // Allocate a HeapNumber box and store the value into it.
11071         HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize);
11072         // This heap number alloc does not have a corresponding
11073         // AllocationSite. That is okay because
11074         // 1) it's a child object of another object with a valid allocation site
11075         // 2) we can just use the mode of the parent object for pretenuring
11076         HInstruction* double_box =
11077             Add<HAllocate>(heap_number_constant, HType::HeapObject(),
11078                 pretenure_flag, MUTABLE_HEAP_NUMBER_TYPE);
11079         AddStoreMapConstant(double_box,
11080             isolate()->factory()->mutable_heap_number_map());
11081         // Unwrap the mutable heap number from the boilerplate.
11082         HValue* double_value =
11083             Add<HConstant>(Handle<HeapNumber>::cast(value)->value());
11084         Add<HStoreNamedField>(
11085             double_box, HObjectAccess::ForHeapNumberValue(), double_value);
11086         value_instruction = double_box;
11087       } else if (representation.IsSmi()) {
11088         value_instruction = value->IsUninitialized()
11089             ? graph()->GetConstant0()
11090             : Add<HConstant>(value);
11091         // Ensure that value is stored as smi.
11092         access = access.WithRepresentation(representation);
11093       } else {
11094         value_instruction = Add<HConstant>(value);
11095       }
11096
11097       Add<HStoreNamedField>(object, access, value_instruction);
11098     }
11099   }
11100
11101   int inobject_properties = boilerplate_object->map()->inobject_properties();
11102   HInstruction* value_instruction =
11103       Add<HConstant>(isolate()->factory()->one_pointer_filler_map());
11104   for (int i = copied_fields; i < inobject_properties; i++) {
11105     DCHECK(boilerplate_object->IsJSObject());
11106     int property_offset = boilerplate_object->GetInObjectPropertyOffset(i);
11107     HObjectAccess access =
11108         HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
11109     Add<HStoreNamedField>(object, access, value_instruction);
11110   }
11111 }
11112
11113
11114 void HOptimizedGraphBuilder::BuildEmitElements(
11115     Handle<JSObject> boilerplate_object,
11116     Handle<FixedArrayBase> elements,
11117     HValue* object_elements,
11118     AllocationSiteUsageContext* site_context) {
11119   ElementsKind kind = boilerplate_object->map()->elements_kind();
11120   int elements_length = elements->length();
11121   HValue* object_elements_length = Add<HConstant>(elements_length);
11122   BuildInitializeElementsHeader(object_elements, kind, object_elements_length);
11123
11124   // Copy elements backing store content.
11125   if (elements->IsFixedDoubleArray()) {
11126     BuildEmitFixedDoubleArray(elements, kind, object_elements);
11127   } else if (elements->IsFixedArray()) {
11128     BuildEmitFixedArray(elements, kind, object_elements,
11129                         site_context);
11130   } else {
11131     UNREACHABLE();
11132   }
11133 }
11134
11135
11136 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray(
11137     Handle<FixedArrayBase> elements,
11138     ElementsKind kind,
11139     HValue* object_elements) {
11140   HInstruction* boilerplate_elements = Add<HConstant>(elements);
11141   int elements_length = elements->length();
11142   for (int i = 0; i < elements_length; i++) {
11143     HValue* key_constant = Add<HConstant>(i);
11144     HInstruction* value_instruction =
11145         Add<HLoadKeyed>(boilerplate_elements, key_constant,
11146                         static_cast<HValue*>(NULL), kind,
11147                         ALLOW_RETURN_HOLE);
11148     HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant,
11149                                            value_instruction, kind);
11150     store->SetFlag(HValue::kAllowUndefinedAsNaN);
11151   }
11152 }
11153
11154
11155 void HOptimizedGraphBuilder::BuildEmitFixedArray(
11156     Handle<FixedArrayBase> elements,
11157     ElementsKind kind,
11158     HValue* object_elements,
11159     AllocationSiteUsageContext* site_context) {
11160   HInstruction* boilerplate_elements = Add<HConstant>(elements);
11161   int elements_length = elements->length();
11162   Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
11163   for (int i = 0; i < elements_length; i++) {
11164     Handle<Object> value(fast_elements->get(i), isolate());
11165     HValue* key_constant = Add<HConstant>(i);
11166     if (value->IsJSObject()) {
11167       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
11168       Handle<AllocationSite> current_site = site_context->EnterNewScope();
11169       HInstruction* result =
11170           BuildFastLiteral(value_object, site_context);
11171       site_context->ExitScope(current_site, value_object);
11172       Add<HStoreKeyed>(object_elements, key_constant, result, kind);
11173     } else {
11174       HInstruction* value_instruction =
11175           Add<HLoadKeyed>(boilerplate_elements, key_constant,
11176                           static_cast<HValue*>(NULL), kind,
11177                           ALLOW_RETURN_HOLE);
11178       Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind);
11179     }
11180   }
11181 }
11182
11183
11184 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
11185   DCHECK(!HasStackOverflow());
11186   DCHECK(current_block() != NULL);
11187   DCHECK(current_block()->HasPredecessor());
11188   HInstruction* instr = BuildThisFunction();
11189   return ast_context()->ReturnInstruction(instr, expr->id());
11190 }
11191
11192
11193 void HOptimizedGraphBuilder::VisitSuperReference(SuperReference* expr) {
11194   UNREACHABLE();
11195 }
11196
11197
11198 void HOptimizedGraphBuilder::VisitDeclarations(
11199     ZoneList<Declaration*>* declarations) {
11200   DCHECK(globals_.is_empty());
11201   AstVisitor::VisitDeclarations(declarations);
11202   if (!globals_.is_empty()) {
11203     Handle<FixedArray> array =
11204        isolate()->factory()->NewFixedArray(globals_.length(), TENURED);
11205     for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i));
11206     int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) |
11207         DeclareGlobalsNativeFlag::encode(current_info()->is_native()) |
11208         DeclareGlobalsStrictMode::encode(current_info()->strict_mode());
11209     Add<HDeclareGlobals>(array, flags);
11210     globals_.Rewind(0);
11211   }
11212 }
11213
11214
11215 void HOptimizedGraphBuilder::VisitVariableDeclaration(
11216     VariableDeclaration* declaration) {
11217   VariableProxy* proxy = declaration->proxy();
11218   VariableMode mode = declaration->mode();
11219   Variable* variable = proxy->var();
11220   bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
11221   switch (variable->location()) {
11222     case Variable::UNALLOCATED:
11223       globals_.Add(variable->name(), zone());
11224       globals_.Add(variable->binding_needs_init()
11225                        ? isolate()->factory()->the_hole_value()
11226                        : isolate()->factory()->undefined_value(), zone());
11227       return;
11228     case Variable::PARAMETER:
11229     case Variable::LOCAL:
11230       if (hole_init) {
11231         HValue* value = graph()->GetConstantHole();
11232         environment()->Bind(variable, value);
11233       }
11234       break;
11235     case Variable::CONTEXT:
11236       if (hole_init) {
11237         HValue* value = graph()->GetConstantHole();
11238         HValue* context = environment()->context();
11239         HStoreContextSlot* store = Add<HStoreContextSlot>(
11240             context, variable->index(), HStoreContextSlot::kNoCheck, value);
11241         if (store->HasObservableSideEffects()) {
11242           Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
11243         }
11244       }
11245       break;
11246     case Variable::LOOKUP:
11247       return Bailout(kUnsupportedLookupSlotInDeclaration);
11248   }
11249 }
11250
11251
11252 void HOptimizedGraphBuilder::VisitFunctionDeclaration(
11253     FunctionDeclaration* declaration) {
11254   VariableProxy* proxy = declaration->proxy();
11255   Variable* variable = proxy->var();
11256   switch (variable->location()) {
11257     case Variable::UNALLOCATED: {
11258       globals_.Add(variable->name(), zone());
11259       Handle<SharedFunctionInfo> function = Compiler::BuildFunctionInfo(
11260           declaration->fun(), current_info()->script(), top_info());
11261       // Check for stack-overflow exception.
11262       if (function.is_null()) return SetStackOverflow();
11263       globals_.Add(function, zone());
11264       return;
11265     }
11266     case Variable::PARAMETER:
11267     case Variable::LOCAL: {
11268       CHECK_ALIVE(VisitForValue(declaration->fun()));
11269       HValue* value = Pop();
11270       BindIfLive(variable, value);
11271       break;
11272     }
11273     case Variable::CONTEXT: {
11274       CHECK_ALIVE(VisitForValue(declaration->fun()));
11275       HValue* value = Pop();
11276       HValue* context = environment()->context();
11277       HStoreContextSlot* store = Add<HStoreContextSlot>(
11278           context, variable->index(), HStoreContextSlot::kNoCheck, value);
11279       if (store->HasObservableSideEffects()) {
11280         Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
11281       }
11282       break;
11283     }
11284     case Variable::LOOKUP:
11285       return Bailout(kUnsupportedLookupSlotInDeclaration);
11286   }
11287 }
11288
11289
11290 void HOptimizedGraphBuilder::VisitModuleDeclaration(
11291     ModuleDeclaration* declaration) {
11292   UNREACHABLE();
11293 }
11294
11295
11296 void HOptimizedGraphBuilder::VisitImportDeclaration(
11297     ImportDeclaration* declaration) {
11298   UNREACHABLE();
11299 }
11300
11301
11302 void HOptimizedGraphBuilder::VisitExportDeclaration(
11303     ExportDeclaration* declaration) {
11304   UNREACHABLE();
11305 }
11306
11307
11308 void HOptimizedGraphBuilder::VisitModuleLiteral(ModuleLiteral* module) {
11309   UNREACHABLE();
11310 }
11311
11312
11313 void HOptimizedGraphBuilder::VisitModuleVariable(ModuleVariable* module) {
11314   UNREACHABLE();
11315 }
11316
11317
11318 void HOptimizedGraphBuilder::VisitModulePath(ModulePath* module) {
11319   UNREACHABLE();
11320 }
11321
11322
11323 void HOptimizedGraphBuilder::VisitModuleUrl(ModuleUrl* module) {
11324   UNREACHABLE();
11325 }
11326
11327
11328 void HOptimizedGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) {
11329   UNREACHABLE();
11330 }
11331
11332
11333 // Generators for inline runtime functions.
11334 // Support for types.
11335 void HOptimizedGraphBuilder::GenerateIsSmi(CallRuntime* call) {
11336   DCHECK(call->arguments()->length() == 1);
11337   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11338   HValue* value = Pop();
11339   HIsSmiAndBranch* result = New<HIsSmiAndBranch>(value);
11340   return ast_context()->ReturnControl(result, call->id());
11341 }
11342
11343
11344 void HOptimizedGraphBuilder::GenerateIsSpecObject(CallRuntime* call) {
11345   DCHECK(call->arguments()->length() == 1);
11346   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11347   HValue* value = Pop();
11348   HHasInstanceTypeAndBranch* result =
11349       New<HHasInstanceTypeAndBranch>(value,
11350                                      FIRST_SPEC_OBJECT_TYPE,
11351                                      LAST_SPEC_OBJECT_TYPE);
11352   return ast_context()->ReturnControl(result, call->id());
11353 }
11354
11355
11356 void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) {
11357   DCHECK(call->arguments()->length() == 1);
11358   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11359   HValue* value = Pop();
11360   HHasInstanceTypeAndBranch* result =
11361       New<HHasInstanceTypeAndBranch>(value, JS_FUNCTION_TYPE);
11362   return ast_context()->ReturnControl(result, call->id());
11363 }
11364
11365
11366 void HOptimizedGraphBuilder::GenerateIsMinusZero(CallRuntime* call) {
11367   DCHECK(call->arguments()->length() == 1);
11368   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11369   HValue* value = Pop();
11370   HCompareMinusZeroAndBranch* result = New<HCompareMinusZeroAndBranch>(value);
11371   return ast_context()->ReturnControl(result, call->id());
11372 }
11373
11374
11375 void HOptimizedGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
11376   DCHECK(call->arguments()->length() == 1);
11377   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11378   HValue* value = Pop();
11379   HHasCachedArrayIndexAndBranch* result =
11380       New<HHasCachedArrayIndexAndBranch>(value);
11381   return ast_context()->ReturnControl(result, call->id());
11382 }
11383
11384
11385 void HOptimizedGraphBuilder::GenerateIsArray(CallRuntime* call) {
11386   DCHECK(call->arguments()->length() == 1);
11387   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11388   HValue* value = Pop();
11389   HHasInstanceTypeAndBranch* result =
11390       New<HHasInstanceTypeAndBranch>(value, JS_ARRAY_TYPE);
11391   return ast_context()->ReturnControl(result, call->id());
11392 }
11393
11394
11395 void HOptimizedGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
11396   DCHECK(call->arguments()->length() == 1);
11397   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11398   HValue* value = Pop();
11399   HHasInstanceTypeAndBranch* result =
11400       New<HHasInstanceTypeAndBranch>(value, JS_REGEXP_TYPE);
11401   return ast_context()->ReturnControl(result, call->id());
11402 }
11403
11404
11405 void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) {
11406   DCHECK(call->arguments()->length() == 1);
11407   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11408   HValue* value = Pop();
11409   HIsObjectAndBranch* result = New<HIsObjectAndBranch>(value);
11410   return ast_context()->ReturnControl(result, call->id());
11411 }
11412
11413
11414 void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) {
11415   return Bailout(kInlinedRuntimeFunctionIsNonNegativeSmi);
11416 }
11417
11418
11419 void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
11420   DCHECK(call->arguments()->length() == 1);
11421   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11422   HValue* value = Pop();
11423   HIsUndetectableAndBranch* result = New<HIsUndetectableAndBranch>(value);
11424   return ast_context()->ReturnControl(result, call->id());
11425 }
11426
11427
11428 void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
11429     CallRuntime* call) {
11430   return Bailout(kInlinedRuntimeFunctionIsStringWrapperSafeForDefaultValueOf);
11431 }
11432
11433
11434 // Support for construct call checks.
11435 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
11436   DCHECK(call->arguments()->length() == 0);
11437   if (function_state()->outer() != NULL) {
11438     // We are generating graph for inlined function.
11439     HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN
11440         ? graph()->GetConstantTrue()
11441         : graph()->GetConstantFalse();
11442     return ast_context()->ReturnValue(value);
11443   } else {
11444     return ast_context()->ReturnControl(New<HIsConstructCallAndBranch>(),
11445                                         call->id());
11446   }
11447 }
11448
11449
11450 // Support for arguments.length and arguments[?].
11451 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
11452   DCHECK(call->arguments()->length() == 0);
11453   HInstruction* result = NULL;
11454   if (function_state()->outer() == NULL) {
11455     HInstruction* elements = Add<HArgumentsElements>(false);
11456     result = New<HArgumentsLength>(elements);
11457   } else {
11458     // Number of arguments without receiver.
11459     int argument_count = environment()->
11460         arguments_environment()->parameter_count() - 1;
11461     result = New<HConstant>(argument_count);
11462   }
11463   return ast_context()->ReturnInstruction(result, call->id());
11464 }
11465
11466
11467 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) {
11468   DCHECK(call->arguments()->length() == 1);
11469   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11470   HValue* index = Pop();
11471   HInstruction* result = NULL;
11472   if (function_state()->outer() == NULL) {
11473     HInstruction* elements = Add<HArgumentsElements>(false);
11474     HInstruction* length = Add<HArgumentsLength>(elements);
11475     HInstruction* checked_index = Add<HBoundsCheck>(index, length);
11476     result = New<HAccessArgumentsAt>(elements, length, checked_index);
11477   } else {
11478     EnsureArgumentsArePushedForAccess();
11479
11480     // Number of arguments without receiver.
11481     HInstruction* elements = function_state()->arguments_elements();
11482     int argument_count = environment()->
11483         arguments_environment()->parameter_count() - 1;
11484     HInstruction* length = Add<HConstant>(argument_count);
11485     HInstruction* checked_key = Add<HBoundsCheck>(index, length);
11486     result = New<HAccessArgumentsAt>(elements, length, checked_key);
11487   }
11488   return ast_context()->ReturnInstruction(result, call->id());
11489 }
11490
11491
11492 // Support for accessing the class and value fields of an object.
11493 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) {
11494   // The special form detected by IsClassOfTest is detected before we get here
11495   // and does not cause a bailout.
11496   return Bailout(kInlinedRuntimeFunctionClassOf);
11497 }
11498
11499
11500 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) {
11501   DCHECK(call->arguments()->length() == 1);
11502   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11503   HValue* object = Pop();
11504
11505   IfBuilder if_objectisvalue(this);
11506   HValue* objectisvalue = if_objectisvalue.If<HHasInstanceTypeAndBranch>(
11507       object, JS_VALUE_TYPE);
11508   if_objectisvalue.Then();
11509   {
11510     // Return the actual value.
11511     Push(Add<HLoadNamedField>(
11512             object, objectisvalue,
11513             HObjectAccess::ForObservableJSObjectOffset(
11514                 JSValue::kValueOffset)));
11515     Add<HSimulate>(call->id(), FIXED_SIMULATE);
11516   }
11517   if_objectisvalue.Else();
11518   {
11519     // If the object is not a value return the object.
11520     Push(object);
11521     Add<HSimulate>(call->id(), FIXED_SIMULATE);
11522   }
11523   if_objectisvalue.End();
11524   return ast_context()->ReturnValue(Pop());
11525 }
11526
11527
11528 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) {
11529   DCHECK(call->arguments()->length() == 2);
11530   DCHECK_NE(NULL, call->arguments()->at(1)->AsLiteral());
11531   Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->value()));
11532   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11533   HValue* date = Pop();
11534   HDateField* result = New<HDateField>(date, index);
11535   return ast_context()->ReturnInstruction(result, call->id());
11536 }
11537
11538
11539 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar(
11540     CallRuntime* call) {
11541   DCHECK(call->arguments()->length() == 3);
11542   // We need to follow the evaluation order of full codegen.
11543   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11544   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
11545   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11546   HValue* string = Pop();
11547   HValue* value = Pop();
11548   HValue* index = Pop();
11549   Add<HSeqStringSetChar>(String::ONE_BYTE_ENCODING, string,
11550                          index, value);
11551   Add<HSimulate>(call->id(), FIXED_SIMULATE);
11552   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
11553 }
11554
11555
11556 void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar(
11557     CallRuntime* call) {
11558   DCHECK(call->arguments()->length() == 3);
11559   // We need to follow the evaluation order of full codegen.
11560   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11561   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
11562   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11563   HValue* string = Pop();
11564   HValue* value = Pop();
11565   HValue* index = Pop();
11566   Add<HSeqStringSetChar>(String::TWO_BYTE_ENCODING, string,
11567                          index, value);
11568   Add<HSimulate>(call->id(), FIXED_SIMULATE);
11569   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
11570 }
11571
11572
11573 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
11574   DCHECK(call->arguments()->length() == 2);
11575   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11576   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11577   HValue* value = Pop();
11578   HValue* object = Pop();
11579
11580   // Check if object is a JSValue.
11581   IfBuilder if_objectisvalue(this);
11582   if_objectisvalue.If<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE);
11583   if_objectisvalue.Then();
11584   {
11585     // Create in-object property store to kValueOffset.
11586     Add<HStoreNamedField>(object,
11587         HObjectAccess::ForObservableJSObjectOffset(JSValue::kValueOffset),
11588         value);
11589     if (!ast_context()->IsEffect()) {
11590       Push(value);
11591     }
11592     Add<HSimulate>(call->id(), FIXED_SIMULATE);
11593   }
11594   if_objectisvalue.Else();
11595   {
11596     // Nothing to do in this case.
11597     if (!ast_context()->IsEffect()) {
11598       Push(value);
11599     }
11600     Add<HSimulate>(call->id(), FIXED_SIMULATE);
11601   }
11602   if_objectisvalue.End();
11603   if (!ast_context()->IsEffect()) {
11604     Drop(1);
11605   }
11606   return ast_context()->ReturnValue(value);
11607 }
11608
11609
11610 // Fast support for charCodeAt(n).
11611 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
11612   DCHECK(call->arguments()->length() == 2);
11613   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11614   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11615   HValue* index = Pop();
11616   HValue* string = Pop();
11617   HInstruction* result = BuildStringCharCodeAt(string, index);
11618   return ast_context()->ReturnInstruction(result, call->id());
11619 }
11620
11621
11622 // Fast support for string.charAt(n) and string[n].
11623 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
11624   DCHECK(call->arguments()->length() == 1);
11625   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11626   HValue* char_code = Pop();
11627   HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
11628   return ast_context()->ReturnInstruction(result, call->id());
11629 }
11630
11631
11632 // Fast support for string.charAt(n) and string[n].
11633 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
11634   DCHECK(call->arguments()->length() == 2);
11635   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11636   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11637   HValue* index = Pop();
11638   HValue* string = Pop();
11639   HInstruction* char_code = BuildStringCharCodeAt(string, index);
11640   AddInstruction(char_code);
11641   HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
11642   return ast_context()->ReturnInstruction(result, call->id());
11643 }
11644
11645
11646 // Fast support for object equality testing.
11647 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
11648   DCHECK(call->arguments()->length() == 2);
11649   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11650   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11651   HValue* right = Pop();
11652   HValue* left = Pop();
11653   HCompareObjectEqAndBranch* result =
11654       New<HCompareObjectEqAndBranch>(left, right);
11655   return ast_context()->ReturnControl(result, call->id());
11656 }
11657
11658
11659 // Fast support for StringAdd.
11660 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) {
11661   DCHECK_EQ(2, call->arguments()->length());
11662   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11663   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11664   HValue* right = Pop();
11665   HValue* left = Pop();
11666   HInstruction* result = NewUncasted<HStringAdd>(left, right);
11667   return ast_context()->ReturnInstruction(result, call->id());
11668 }
11669
11670
11671 // Fast support for SubString.
11672 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) {
11673   DCHECK_EQ(3, call->arguments()->length());
11674   CHECK_ALIVE(VisitExpressions(call->arguments()));
11675   PushArgumentsFromEnvironment(call->arguments()->length());
11676   HCallStub* result = New<HCallStub>(CodeStub::SubString, 3);
11677   return ast_context()->ReturnInstruction(result, call->id());
11678 }
11679
11680
11681 // Fast support for StringCompare.
11682 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) {
11683   DCHECK_EQ(2, call->arguments()->length());
11684   CHECK_ALIVE(VisitExpressions(call->arguments()));
11685   PushArgumentsFromEnvironment(call->arguments()->length());
11686   HCallStub* result = New<HCallStub>(CodeStub::StringCompare, 2);
11687   return ast_context()->ReturnInstruction(result, call->id());
11688 }
11689
11690
11691 // Support for direct calls from JavaScript to native RegExp code.
11692 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
11693   DCHECK_EQ(4, call->arguments()->length());
11694   CHECK_ALIVE(VisitExpressions(call->arguments()));
11695   PushArgumentsFromEnvironment(call->arguments()->length());
11696   HCallStub* result = New<HCallStub>(CodeStub::RegExpExec, 4);
11697   return ast_context()->ReturnInstruction(result, call->id());
11698 }
11699
11700
11701 void HOptimizedGraphBuilder::GenerateDoubleLo(CallRuntime* call) {
11702   DCHECK_EQ(1, call->arguments()->length());
11703   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11704   HValue* value = Pop();
11705   HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::LOW);
11706   return ast_context()->ReturnInstruction(result, call->id());
11707 }
11708
11709
11710 void HOptimizedGraphBuilder::GenerateDoubleHi(CallRuntime* call) {
11711   DCHECK_EQ(1, call->arguments()->length());
11712   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11713   HValue* value = Pop();
11714   HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::HIGH);
11715   return ast_context()->ReturnInstruction(result, call->id());
11716 }
11717
11718
11719 void HOptimizedGraphBuilder::GenerateConstructDouble(CallRuntime* call) {
11720   DCHECK_EQ(2, call->arguments()->length());
11721   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11722   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11723   HValue* lo = Pop();
11724   HValue* hi = Pop();
11725   HInstruction* result = NewUncasted<HConstructDouble>(hi, lo);
11726   return ast_context()->ReturnInstruction(result, call->id());
11727 }
11728
11729
11730 // Construct a RegExp exec result with two in-object properties.
11731 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
11732   DCHECK_EQ(3, call->arguments()->length());
11733   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11734   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11735   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
11736   HValue* input = Pop();
11737   HValue* index = Pop();
11738   HValue* length = Pop();
11739   HValue* result = BuildRegExpConstructResult(length, index, input);
11740   return ast_context()->ReturnValue(result);
11741 }
11742
11743
11744 // Support for fast native caches.
11745 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
11746   return Bailout(kInlinedRuntimeFunctionGetFromCache);
11747 }
11748
11749
11750 // Fast support for number to string.
11751 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) {
11752   DCHECK_EQ(1, call->arguments()->length());
11753   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11754   HValue* number = Pop();
11755   HValue* result = BuildNumberToString(number, Type::Any(zone()));
11756   return ast_context()->ReturnValue(result);
11757 }
11758
11759
11760 // Fast call for custom callbacks.
11761 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) {
11762   // 1 ~ The function to call is not itself an argument to the call.
11763   int arg_count = call->arguments()->length() - 1;
11764   DCHECK(arg_count >= 1);  // There's always at least a receiver.
11765
11766   CHECK_ALIVE(VisitExpressions(call->arguments()));
11767   // The function is the last argument
11768   HValue* function = Pop();
11769   // Push the arguments to the stack
11770   PushArgumentsFromEnvironment(arg_count);
11771
11772   IfBuilder if_is_jsfunction(this);
11773   if_is_jsfunction.If<HHasInstanceTypeAndBranch>(function, JS_FUNCTION_TYPE);
11774
11775   if_is_jsfunction.Then();
11776   {
11777     HInstruction* invoke_result =
11778         Add<HInvokeFunction>(function, arg_count);
11779     if (!ast_context()->IsEffect()) {
11780       Push(invoke_result);
11781     }
11782     Add<HSimulate>(call->id(), FIXED_SIMULATE);
11783   }
11784
11785   if_is_jsfunction.Else();
11786   {
11787     HInstruction* call_result =
11788         Add<HCallFunction>(function, arg_count);
11789     if (!ast_context()->IsEffect()) {
11790       Push(call_result);
11791     }
11792     Add<HSimulate>(call->id(), FIXED_SIMULATE);
11793   }
11794   if_is_jsfunction.End();
11795
11796   if (ast_context()->IsEffect()) {
11797     // EffectContext::ReturnValue ignores the value, so we can just pass
11798     // 'undefined' (as we do not have the call result anymore).
11799     return ast_context()->ReturnValue(graph()->GetConstantUndefined());
11800   } else {
11801     return ast_context()->ReturnValue(Pop());
11802   }
11803 }
11804
11805
11806 // Fast call to math functions.
11807 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) {
11808   DCHECK_EQ(2, call->arguments()->length());
11809   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11810   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11811   HValue* right = Pop();
11812   HValue* left = Pop();
11813   HInstruction* result = NewUncasted<HPower>(left, right);
11814   return ast_context()->ReturnInstruction(result, call->id());
11815 }
11816
11817
11818 void HOptimizedGraphBuilder::GenerateMathLogRT(CallRuntime* call) {
11819   DCHECK(call->arguments()->length() == 1);
11820   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11821   HValue* value = Pop();
11822   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathLog);
11823   return ast_context()->ReturnInstruction(result, call->id());
11824 }
11825
11826
11827 void HOptimizedGraphBuilder::GenerateMathSqrtRT(CallRuntime* call) {
11828   DCHECK(call->arguments()->length() == 1);
11829   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11830   HValue* value = Pop();
11831   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt);
11832   return ast_context()->ReturnInstruction(result, call->id());
11833 }
11834
11835
11836 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
11837   DCHECK(call->arguments()->length() == 1);
11838   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11839   HValue* value = Pop();
11840   HGetCachedArrayIndex* result = New<HGetCachedArrayIndex>(value);
11841   return ast_context()->ReturnInstruction(result, call->id());
11842 }
11843
11844
11845 void HOptimizedGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) {
11846   return Bailout(kInlinedRuntimeFunctionFastAsciiArrayJoin);
11847 }
11848
11849
11850 // Support for generators.
11851 void HOptimizedGraphBuilder::GenerateGeneratorNext(CallRuntime* call) {
11852   return Bailout(kInlinedRuntimeFunctionGeneratorNext);
11853 }
11854
11855
11856 void HOptimizedGraphBuilder::GenerateGeneratorThrow(CallRuntime* call) {
11857   return Bailout(kInlinedRuntimeFunctionGeneratorThrow);
11858 }
11859
11860
11861 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode(
11862     CallRuntime* call) {
11863   Add<HDebugBreak>();
11864   return ast_context()->ReturnValue(graph()->GetConstant0());
11865 }
11866
11867
11868 void HOptimizedGraphBuilder::GenerateDebugIsActive(CallRuntime* call) {
11869   DCHECK(call->arguments()->length() == 0);
11870   HValue* ref =
11871       Add<HConstant>(ExternalReference::debug_is_active_address(isolate()));
11872   HValue* value = Add<HLoadNamedField>(
11873       ref, static_cast<HValue*>(NULL), HObjectAccess::ForExternalUInteger8());
11874   return ast_context()->ReturnValue(value);
11875 }
11876
11877
11878 #undef CHECK_BAILOUT
11879 #undef CHECK_ALIVE
11880
11881
11882 HEnvironment::HEnvironment(HEnvironment* outer,
11883                            Scope* scope,
11884                            Handle<JSFunction> closure,
11885                            Zone* zone)
11886     : closure_(closure),
11887       values_(0, zone),
11888       frame_type_(JS_FUNCTION),
11889       parameter_count_(0),
11890       specials_count_(1),
11891       local_count_(0),
11892       outer_(outer),
11893       entry_(NULL),
11894       pop_count_(0),
11895       push_count_(0),
11896       ast_id_(BailoutId::None()),
11897       zone_(zone) {
11898   Scope* declaration_scope = scope->DeclarationScope();
11899   Initialize(declaration_scope->num_parameters() + 1,
11900              declaration_scope->num_stack_slots(), 0);
11901 }
11902
11903
11904 HEnvironment::HEnvironment(Zone* zone, int parameter_count)
11905     : values_(0, zone),
11906       frame_type_(STUB),
11907       parameter_count_(parameter_count),
11908       specials_count_(1),
11909       local_count_(0),
11910       outer_(NULL),
11911       entry_(NULL),
11912       pop_count_(0),
11913       push_count_(0),
11914       ast_id_(BailoutId::None()),
11915       zone_(zone) {
11916   Initialize(parameter_count, 0, 0);
11917 }
11918
11919
11920 HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone)
11921     : values_(0, zone),
11922       frame_type_(JS_FUNCTION),
11923       parameter_count_(0),
11924       specials_count_(0),
11925       local_count_(0),
11926       outer_(NULL),
11927       entry_(NULL),
11928       pop_count_(0),
11929       push_count_(0),
11930       ast_id_(other->ast_id()),
11931       zone_(zone) {
11932   Initialize(other);
11933 }
11934
11935
11936 HEnvironment::HEnvironment(HEnvironment* outer,
11937                            Handle<JSFunction> closure,
11938                            FrameType frame_type,
11939                            int arguments,
11940                            Zone* zone)
11941     : closure_(closure),
11942       values_(arguments, zone),
11943       frame_type_(frame_type),
11944       parameter_count_(arguments),
11945       specials_count_(0),
11946       local_count_(0),
11947       outer_(outer),
11948       entry_(NULL),
11949       pop_count_(0),
11950       push_count_(0),
11951       ast_id_(BailoutId::None()),
11952       zone_(zone) {
11953 }
11954
11955
11956 void HEnvironment::Initialize(int parameter_count,
11957                               int local_count,
11958                               int stack_height) {
11959   parameter_count_ = parameter_count;
11960   local_count_ = local_count;
11961
11962   // Avoid reallocating the temporaries' backing store on the first Push.
11963   int total = parameter_count + specials_count_ + local_count + stack_height;
11964   values_.Initialize(total + 4, zone());
11965   for (int i = 0; i < total; ++i) values_.Add(NULL, zone());
11966 }
11967
11968
11969 void HEnvironment::Initialize(const HEnvironment* other) {
11970   closure_ = other->closure();
11971   values_.AddAll(other->values_, zone());
11972   assigned_variables_.Union(other->assigned_variables_, zone());
11973   frame_type_ = other->frame_type_;
11974   parameter_count_ = other->parameter_count_;
11975   local_count_ = other->local_count_;
11976   if (other->outer_ != NULL) outer_ = other->outer_->Copy();  // Deep copy.
11977   entry_ = other->entry_;
11978   pop_count_ = other->pop_count_;
11979   push_count_ = other->push_count_;
11980   specials_count_ = other->specials_count_;
11981   ast_id_ = other->ast_id_;
11982 }
11983
11984
11985 void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
11986   DCHECK(!block->IsLoopHeader());
11987   DCHECK(values_.length() == other->values_.length());
11988
11989   int length = values_.length();
11990   for (int i = 0; i < length; ++i) {
11991     HValue* value = values_[i];
11992     if (value != NULL && value->IsPhi() && value->block() == block) {
11993       // There is already a phi for the i'th value.
11994       HPhi* phi = HPhi::cast(value);
11995       // Assert index is correct and that we haven't missed an incoming edge.
11996       DCHECK(phi->merged_index() == i || !phi->HasMergedIndex());
11997       DCHECK(phi->OperandCount() == block->predecessors()->length());
11998       phi->AddInput(other->values_[i]);
11999     } else if (values_[i] != other->values_[i]) {
12000       // There is a fresh value on the incoming edge, a phi is needed.
12001       DCHECK(values_[i] != NULL && other->values_[i] != NULL);
12002       HPhi* phi = block->AddNewPhi(i);
12003       HValue* old_value = values_[i];
12004       for (int j = 0; j < block->predecessors()->length(); j++) {
12005         phi->AddInput(old_value);
12006       }
12007       phi->AddInput(other->values_[i]);
12008       this->values_[i] = phi;
12009     }
12010   }
12011 }
12012
12013
12014 void HEnvironment::Bind(int index, HValue* value) {
12015   DCHECK(value != NULL);
12016   assigned_variables_.Add(index, zone());
12017   values_[index] = value;
12018 }
12019
12020
12021 bool HEnvironment::HasExpressionAt(int index) const {
12022   return index >= parameter_count_ + specials_count_ + local_count_;
12023 }
12024
12025
12026 bool HEnvironment::ExpressionStackIsEmpty() const {
12027   DCHECK(length() >= first_expression_index());
12028   return length() == first_expression_index();
12029 }
12030
12031
12032 void HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) {
12033   int count = index_from_top + 1;
12034   int index = values_.length() - count;
12035   DCHECK(HasExpressionAt(index));
12036   // The push count must include at least the element in question or else
12037   // the new value will not be included in this environment's history.
12038   if (push_count_ < count) {
12039     // This is the same effect as popping then re-pushing 'count' elements.
12040     pop_count_ += (count - push_count_);
12041     push_count_ = count;
12042   }
12043   values_[index] = value;
12044 }
12045
12046
12047 void HEnvironment::Drop(int count) {
12048   for (int i = 0; i < count; ++i) {
12049     Pop();
12050   }
12051 }
12052
12053
12054 HEnvironment* HEnvironment::Copy() const {
12055   return new(zone()) HEnvironment(this, zone());
12056 }
12057
12058
12059 HEnvironment* HEnvironment::CopyWithoutHistory() const {
12060   HEnvironment* result = Copy();
12061   result->ClearHistory();
12062   return result;
12063 }
12064
12065
12066 HEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const {
12067   HEnvironment* new_env = Copy();
12068   for (int i = 0; i < values_.length(); ++i) {
12069     HPhi* phi = loop_header->AddNewPhi(i);
12070     phi->AddInput(values_[i]);
12071     new_env->values_[i] = phi;
12072   }
12073   new_env->ClearHistory();
12074   return new_env;
12075 }
12076
12077
12078 HEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer,
12079                                                   Handle<JSFunction> target,
12080                                                   FrameType frame_type,
12081                                                   int arguments) const {
12082   HEnvironment* new_env =
12083       new(zone()) HEnvironment(outer, target, frame_type,
12084                                arguments + 1, zone());
12085   for (int i = 0; i <= arguments; ++i) {  // Include receiver.
12086     new_env->Push(ExpressionStackAt(arguments - i));
12087   }
12088   new_env->ClearHistory();
12089   return new_env;
12090 }
12091
12092
12093 HEnvironment* HEnvironment::CopyForInlining(
12094     Handle<JSFunction> target,
12095     int arguments,
12096     FunctionLiteral* function,
12097     HConstant* undefined,
12098     InliningKind inlining_kind) const {
12099   DCHECK(frame_type() == JS_FUNCTION);
12100
12101   // Outer environment is a copy of this one without the arguments.
12102   int arity = function->scope()->num_parameters();
12103
12104   HEnvironment* outer = Copy();
12105   outer->Drop(arguments + 1);  // Including receiver.
12106   outer->ClearHistory();
12107
12108   if (inlining_kind == CONSTRUCT_CALL_RETURN) {
12109     // Create artificial constructor stub environment.  The receiver should
12110     // actually be the constructor function, but we pass the newly allocated
12111     // object instead, DoComputeConstructStubFrame() relies on that.
12112     outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments);
12113   } else if (inlining_kind == GETTER_CALL_RETURN) {
12114     // We need an additional StackFrame::INTERNAL frame for restoring the
12115     // correct context.
12116     outer = CreateStubEnvironment(outer, target, JS_GETTER, arguments);
12117   } else if (inlining_kind == SETTER_CALL_RETURN) {
12118     // We need an additional StackFrame::INTERNAL frame for temporarily saving
12119     // the argument of the setter, see StoreStubCompiler::CompileStoreViaSetter.
12120     outer = CreateStubEnvironment(outer, target, JS_SETTER, arguments);
12121   }
12122
12123   if (arity != arguments) {
12124     // Create artificial arguments adaptation environment.
12125     outer = CreateStubEnvironment(outer, target, ARGUMENTS_ADAPTOR, arguments);
12126   }
12127
12128   HEnvironment* inner =
12129       new(zone()) HEnvironment(outer, function->scope(), target, zone());
12130   // Get the argument values from the original environment.
12131   for (int i = 0; i <= arity; ++i) {  // Include receiver.
12132     HValue* push = (i <= arguments) ?
12133         ExpressionStackAt(arguments - i) : undefined;
12134     inner->SetValueAt(i, push);
12135   }
12136   inner->SetValueAt(arity + 1, context());
12137   for (int i = arity + 2; i < inner->length(); ++i) {
12138     inner->SetValueAt(i, undefined);
12139   }
12140
12141   inner->set_ast_id(BailoutId::FunctionEntry());
12142   return inner;
12143 }
12144
12145
12146 OStream& operator<<(OStream& os, const HEnvironment& env) {
12147   for (int i = 0; i < env.length(); i++) {
12148     if (i == 0) os << "parameters\n";
12149     if (i == env.parameter_count()) os << "specials\n";
12150     if (i == env.parameter_count() + env.specials_count()) os << "locals\n";
12151     if (i == env.parameter_count() + env.specials_count() + env.local_count()) {
12152       os << "expressions\n";
12153     }
12154     HValue* val = env.values()->at(i);
12155     os << i << ": ";
12156     if (val != NULL) {
12157       os << val;
12158     } else {
12159       os << "NULL";
12160     }
12161     os << "\n";
12162   }
12163   return os << "\n";
12164 }
12165
12166
12167 void HTracer::TraceCompilation(CompilationInfo* info) {
12168   Tag tag(this, "compilation");
12169   if (info->IsOptimizing()) {
12170     Handle<String> name = info->function()->debug_name();
12171     PrintStringProperty("name", name->ToCString().get());
12172     PrintIndent();
12173     trace_.Add("method \"%s:%d\"\n",
12174                name->ToCString().get(),
12175                info->optimization_id());
12176   } else {
12177     CodeStub::Major major_key = info->code_stub()->MajorKey();
12178     PrintStringProperty("name", CodeStub::MajorName(major_key, false));
12179     PrintStringProperty("method", "stub");
12180   }
12181   PrintLongProperty("date",
12182                     static_cast<int64_t>(base::OS::TimeCurrentMillis()));
12183 }
12184
12185
12186 void HTracer::TraceLithium(const char* name, LChunk* chunk) {
12187   DCHECK(!chunk->isolate()->concurrent_recompilation_enabled());
12188   AllowHandleDereference allow_deref;
12189   AllowDeferredHandleDereference allow_deferred_deref;
12190   Trace(name, chunk->graph(), chunk);
12191 }
12192
12193
12194 void HTracer::TraceHydrogen(const char* name, HGraph* graph) {
12195   DCHECK(!graph->isolate()->concurrent_recompilation_enabled());
12196   AllowHandleDereference allow_deref;
12197   AllowDeferredHandleDereference allow_deferred_deref;
12198   Trace(name, graph, NULL);
12199 }
12200
12201
12202 void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
12203   Tag tag(this, "cfg");
12204   PrintStringProperty("name", name);
12205   const ZoneList<HBasicBlock*>* blocks = graph->blocks();
12206   for (int i = 0; i < blocks->length(); i++) {
12207     HBasicBlock* current = blocks->at(i);
12208     Tag block_tag(this, "block");
12209     PrintBlockProperty("name", current->block_id());
12210     PrintIntProperty("from_bci", -1);
12211     PrintIntProperty("to_bci", -1);
12212
12213     if (!current->predecessors()->is_empty()) {
12214       PrintIndent();
12215       trace_.Add("predecessors");
12216       for (int j = 0; j < current->predecessors()->length(); ++j) {
12217         trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id());
12218       }
12219       trace_.Add("\n");
12220     } else {
12221       PrintEmptyProperty("predecessors");
12222     }
12223
12224     if (current->end()->SuccessorCount() == 0) {
12225       PrintEmptyProperty("successors");
12226     } else  {
12227       PrintIndent();
12228       trace_.Add("successors");
12229       for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) {
12230         trace_.Add(" \"B%d\"", it.Current()->block_id());
12231       }
12232       trace_.Add("\n");
12233     }
12234
12235     PrintEmptyProperty("xhandlers");
12236
12237     {
12238       PrintIndent();
12239       trace_.Add("flags");
12240       if (current->IsLoopSuccessorDominator()) {
12241         trace_.Add(" \"dom-loop-succ\"");
12242       }
12243       if (current->IsUnreachable()) {
12244         trace_.Add(" \"dead\"");
12245       }
12246       if (current->is_osr_entry()) {
12247         trace_.Add(" \"osr\"");
12248       }
12249       trace_.Add("\n");
12250     }
12251
12252     if (current->dominator() != NULL) {
12253       PrintBlockProperty("dominator", current->dominator()->block_id());
12254     }
12255
12256     PrintIntProperty("loop_depth", current->LoopNestingDepth());
12257
12258     if (chunk != NULL) {
12259       int first_index = current->first_instruction_index();
12260       int last_index = current->last_instruction_index();
12261       PrintIntProperty(
12262           "first_lir_id",
12263           LifetimePosition::FromInstructionIndex(first_index).Value());
12264       PrintIntProperty(
12265           "last_lir_id",
12266           LifetimePosition::FromInstructionIndex(last_index).Value());
12267     }
12268
12269     {
12270       Tag states_tag(this, "states");
12271       Tag locals_tag(this, "locals");
12272       int total = current->phis()->length();
12273       PrintIntProperty("size", current->phis()->length());
12274       PrintStringProperty("method", "None");
12275       for (int j = 0; j < total; ++j) {
12276         HPhi* phi = current->phis()->at(j);
12277         PrintIndent();
12278         OStringStream os;
12279         os << phi->merged_index() << " " << NameOf(phi) << " " << *phi << "\n";
12280         trace_.Add(os.c_str());
12281       }
12282     }
12283
12284     {
12285       Tag HIR_tag(this, "HIR");
12286       for (HInstructionIterator it(current); !it.Done(); it.Advance()) {
12287         HInstruction* instruction = it.Current();
12288         int uses = instruction->UseCount();
12289         PrintIndent();
12290         OStringStream os;
12291         os << "0 " << uses << " " << NameOf(instruction) << " " << *instruction;
12292         if (FLAG_hydrogen_track_positions &&
12293             instruction->has_position() &&
12294             instruction->position().raw() != 0) {
12295           const HSourcePosition pos = instruction->position();
12296           os << " pos:";
12297           if (pos.inlining_id() != 0) os << pos.inlining_id() << "_";
12298           os << pos.position();
12299         }
12300         os << " <|@\n";
12301         trace_.Add(os.c_str());
12302       }
12303     }
12304
12305
12306     if (chunk != NULL) {
12307       Tag LIR_tag(this, "LIR");
12308       int first_index = current->first_instruction_index();
12309       int last_index = current->last_instruction_index();
12310       if (first_index != -1 && last_index != -1) {
12311         const ZoneList<LInstruction*>* instructions = chunk->instructions();
12312         for (int i = first_index; i <= last_index; ++i) {
12313           LInstruction* linstr = instructions->at(i);
12314           if (linstr != NULL) {
12315             PrintIndent();
12316             trace_.Add("%d ",
12317                        LifetimePosition::FromInstructionIndex(i).Value());
12318             linstr->PrintTo(&trace_);
12319             OStringStream os;
12320             os << " [hir:" << NameOf(linstr->hydrogen_value()) << "] <|@\n";
12321             trace_.Add(os.c_str());
12322           }
12323         }
12324       }
12325     }
12326   }
12327 }
12328
12329
12330 void HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) {
12331   Tag tag(this, "intervals");
12332   PrintStringProperty("name", name);
12333
12334   const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
12335   for (int i = 0; i < fixed_d->length(); ++i) {
12336     TraceLiveRange(fixed_d->at(i), "fixed", allocator->zone());
12337   }
12338
12339   const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges();
12340   for (int i = 0; i < fixed->length(); ++i) {
12341     TraceLiveRange(fixed->at(i), "fixed", allocator->zone());
12342   }
12343
12344   const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges();
12345   for (int i = 0; i < live_ranges->length(); ++i) {
12346     TraceLiveRange(live_ranges->at(i), "object", allocator->zone());
12347   }
12348 }
12349
12350
12351 void HTracer::TraceLiveRange(LiveRange* range, const char* type,
12352                              Zone* zone) {
12353   if (range != NULL && !range->IsEmpty()) {
12354     PrintIndent();
12355     trace_.Add("%d %s", range->id(), type);
12356     if (range->HasRegisterAssigned()) {
12357       LOperand* op = range->CreateAssignedOperand(zone);
12358       int assigned_reg = op->index();
12359       if (op->IsDoubleRegister()) {
12360         trace_.Add(" \"%s\"",
12361                    DoubleRegister::AllocationIndexToString(assigned_reg));
12362       } else {
12363         DCHECK(op->IsRegister());
12364         trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg));
12365       }
12366     } else if (range->IsSpilled()) {
12367       LOperand* op = range->TopLevel()->GetSpillOperand();
12368       if (op->IsDoubleStackSlot()) {
12369         trace_.Add(" \"double_stack:%d\"", op->index());
12370       } else {
12371         DCHECK(op->IsStackSlot());
12372         trace_.Add(" \"stack:%d\"", op->index());
12373       }
12374     }
12375     int parent_index = -1;
12376     if (range->IsChild()) {
12377       parent_index = range->parent()->id();
12378     } else {
12379       parent_index = range->id();
12380     }
12381     LOperand* op = range->FirstHint();
12382     int hint_index = -1;
12383     if (op != NULL && op->IsUnallocated()) {
12384       hint_index = LUnallocated::cast(op)->virtual_register();
12385     }
12386     trace_.Add(" %d %d", parent_index, hint_index);
12387     UseInterval* cur_interval = range->first_interval();
12388     while (cur_interval != NULL && range->Covers(cur_interval->start())) {
12389       trace_.Add(" [%d, %d[",
12390                  cur_interval->start().Value(),
12391                  cur_interval->end().Value());
12392       cur_interval = cur_interval->next();
12393     }
12394
12395     UsePosition* current_pos = range->first_pos();
12396     while (current_pos != NULL) {
12397       if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
12398         trace_.Add(" %d M", current_pos->pos().Value());
12399       }
12400       current_pos = current_pos->next();
12401     }
12402
12403     trace_.Add(" \"\"\n");
12404   }
12405 }
12406
12407
12408 void HTracer::FlushToFile() {
12409   AppendChars(filename_.start(), trace_.ToCString().get(), trace_.length(),
12410               false);
12411   trace_.Reset();
12412 }
12413
12414
12415 void HStatistics::Initialize(CompilationInfo* info) {
12416   if (info->shared_info().is_null()) return;
12417   source_size_ += info->shared_info()->SourceSize();
12418 }
12419
12420
12421 void HStatistics::Print(const char* stats_name) {
12422   PrintF(
12423       "\n"
12424       "----------------------------------------"
12425       "----------------------------------------\n"
12426       "--- %s timing results:\n"
12427       "----------------------------------------"
12428       "----------------------------------------\n",
12429       stats_name);
12430   base::TimeDelta sum;
12431   for (int i = 0; i < times_.length(); ++i) {
12432     sum += times_[i];
12433   }
12434
12435   for (int i = 0; i < names_.length(); ++i) {
12436     PrintF("%33s", names_[i]);
12437     double ms = times_[i].InMillisecondsF();
12438     double percent = times_[i].PercentOf(sum);
12439     PrintF(" %8.3f ms / %4.1f %% ", ms, percent);
12440
12441     unsigned size = sizes_[i];
12442     double size_percent = static_cast<double>(size) * 100 / total_size_;
12443     PrintF(" %9u bytes / %4.1f %%\n", size, size_percent);
12444   }
12445
12446   PrintF(
12447       "----------------------------------------"
12448       "----------------------------------------\n");
12449   base::TimeDelta total = create_graph_ + optimize_graph_ + generate_code_;
12450   PrintF("%33s %8.3f ms / %4.1f %% \n", "Create graph",
12451          create_graph_.InMillisecondsF(), create_graph_.PercentOf(total));
12452   PrintF("%33s %8.3f ms / %4.1f %% \n", "Optimize graph",
12453          optimize_graph_.InMillisecondsF(), optimize_graph_.PercentOf(total));
12454   PrintF("%33s %8.3f ms / %4.1f %% \n", "Generate and install code",
12455          generate_code_.InMillisecondsF(), generate_code_.PercentOf(total));
12456   PrintF(
12457       "----------------------------------------"
12458       "----------------------------------------\n");
12459   PrintF("%33s %8.3f ms           %9u bytes\n", "Total",
12460          total.InMillisecondsF(), total_size_);
12461   PrintF("%33s     (%.1f times slower than full code gen)\n", "",
12462          total.TimesOf(full_code_gen_));
12463
12464   double source_size_in_kb = static_cast<double>(source_size_) / 1024;
12465   double normalized_time =  source_size_in_kb > 0
12466       ? total.InMillisecondsF() / source_size_in_kb
12467       : 0;
12468   double normalized_size_in_kb = source_size_in_kb > 0
12469       ? total_size_ / 1024 / source_size_in_kb
12470       : 0;
12471   PrintF("%33s %8.3f ms           %7.3f kB allocated\n",
12472          "Average per kB source", normalized_time, normalized_size_in_kb);
12473 }
12474
12475
12476 void HStatistics::SaveTiming(const char* name, base::TimeDelta time,
12477                              unsigned size) {
12478   total_size_ += size;
12479   for (int i = 0; i < names_.length(); ++i) {
12480     if (strcmp(names_[i], name) == 0) {
12481       times_[i] += time;
12482       sizes_[i] += size;
12483       return;
12484     }
12485   }
12486   names_.Add(name);
12487   times_.Add(time);
12488   sizes_.Add(size);
12489 }
12490
12491
12492 HPhase::~HPhase() {
12493   if (ShouldProduceTraceOutput()) {
12494     isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
12495   }
12496
12497 #ifdef DEBUG
12498   graph_->Verify(false);  // No full verify.
12499 #endif
12500 }
12501
12502 } }  // namespace v8::internal