deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / 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 <sstream>
8
9 #include "src/v8.h"
10
11 #include "src/allocation-site-scopes.h"
12 #include "src/ast-numbering.h"
13 #include "src/full-codegen.h"
14 #include "src/hydrogen-bce.h"
15 #include "src/hydrogen-bch.h"
16 #include "src/hydrogen-canonicalize.h"
17 #include "src/hydrogen-check-elimination.h"
18 #include "src/hydrogen-dce.h"
19 #include "src/hydrogen-dehoist.h"
20 #include "src/hydrogen-environment-liveness.h"
21 #include "src/hydrogen-escape-analysis.h"
22 #include "src/hydrogen-gvn.h"
23 #include "src/hydrogen-infer-representation.h"
24 #include "src/hydrogen-infer-types.h"
25 #include "src/hydrogen-load-elimination.h"
26 #include "src/hydrogen-mark-deoptimize.h"
27 #include "src/hydrogen-mark-unreachable.h"
28 #include "src/hydrogen-osr.h"
29 #include "src/hydrogen-range-analysis.h"
30 #include "src/hydrogen-redundant-phi.h"
31 #include "src/hydrogen-removable-simulates.h"
32 #include "src/hydrogen-representation-changes.h"
33 #include "src/hydrogen-sce.h"
34 #include "src/hydrogen-store-elimination.h"
35 #include "src/hydrogen-uint32-analysis.h"
36 #include "src/ic/call-optimization.h"
37 #include "src/ic/ic.h"
38 // GetRootConstructor
39 #include "src/ic/ic-inl.h"
40 #include "src/lithium-allocator.h"
41 #include "src/parser.h"
42 #include "src/runtime/runtime.h"
43 #include "src/scopeinfo.h"
44 #include "src/typing.h"
45
46 #if V8_TARGET_ARCH_IA32
47 #include "src/ia32/lithium-codegen-ia32.h"  // NOLINT
48 #elif V8_TARGET_ARCH_X64
49 #include "src/x64/lithium-codegen-x64.h"  // NOLINT
50 #elif V8_TARGET_ARCH_ARM64
51 #include "src/arm64/lithium-codegen-arm64.h"  // NOLINT
52 #elif V8_TARGET_ARCH_ARM
53 #include "src/arm/lithium-codegen-arm.h"  // NOLINT
54 #elif V8_TARGET_ARCH_PPC
55 #include "src/ppc/lithium-codegen-ppc.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, SourcePosition position) {
133   DCHECK(!IsStartBlock() || !IsFinished());
134   DCHECK(!instr->IsLinked());
135   DCHECK(!IsFinished());
136
137   if (!position.IsUnknown()) {
138     instr->set_position(position);
139   }
140   if (first_ == NULL) {
141     DCHECK(last_environment() != NULL);
142     DCHECK(!last_environment()->ast_id().IsNone());
143     HBlockEntry* entry = new(zone()) HBlockEntry();
144     entry->InitializeAsFirst(this);
145     if (!position.IsUnknown()) {
146       entry->set_position(position);
147     } else {
148       DCHECK(!FLAG_hydrogen_track_positions ||
149              !graph()->info()->IsOptimizing() || instr->IsAbnormalExit());
150     }
151     first_ = last_ = entry;
152   }
153   instr->InsertAfter(last_);
154 }
155
156
157 HPhi* HBasicBlock::AddNewPhi(int merged_index) {
158   if (graph()->IsInsideNoSideEffectsScope()) {
159     merged_index = HPhi::kInvalidMergedIndex;
160   }
161   HPhi* phi = new(zone()) HPhi(merged_index, zone());
162   AddPhi(phi);
163   return phi;
164 }
165
166
167 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id,
168                                        RemovableSimulate removable) {
169   DCHECK(HasEnvironment());
170   HEnvironment* environment = last_environment();
171   DCHECK(ast_id.IsNone() ||
172          ast_id == BailoutId::StubEntry() ||
173          environment->closure()->shared()->VerifyBailoutId(ast_id));
174
175   int push_count = environment->push_count();
176   int pop_count = environment->pop_count();
177
178   HSimulate* instr =
179       new(zone()) HSimulate(ast_id, pop_count, zone(), removable);
180 #ifdef DEBUG
181   instr->set_closure(environment->closure());
182 #endif
183   // Order of pushed values: newest (top of stack) first. This allows
184   // HSimulate::MergeWith() to easily append additional pushed values
185   // that are older (from further down the stack).
186   for (int i = 0; i < push_count; ++i) {
187     instr->AddPushedValue(environment->ExpressionStackAt(i));
188   }
189   for (GrowableBitVector::Iterator it(environment->assigned_variables(),
190                                       zone());
191        !it.Done();
192        it.Advance()) {
193     int index = it.Current();
194     instr->AddAssignedValue(index, environment->Lookup(index));
195   }
196   environment->ClearHistory();
197   return instr;
198 }
199
200
201 void HBasicBlock::Finish(HControlInstruction* end, SourcePosition position) {
202   DCHECK(!IsFinished());
203   AddInstruction(end, position);
204   end_ = end;
205   for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
206     it.Current()->RegisterPredecessor(this);
207   }
208 }
209
210
211 void HBasicBlock::Goto(HBasicBlock* block, SourcePosition position,
212                        FunctionState* state, bool add_simulate) {
213   bool drop_extra = state != NULL &&
214       state->inlining_kind() == NORMAL_RETURN;
215
216   if (block->IsInlineReturnTarget()) {
217     HEnvironment* env = last_environment();
218     int argument_count = env->arguments_environment()->parameter_count();
219     AddInstruction(new(zone())
220                    HLeaveInlined(state->entry(), argument_count),
221                    position);
222     UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
223   }
224
225   if (add_simulate) AddNewSimulate(BailoutId::None(), position);
226   HGoto* instr = new(zone()) HGoto(block);
227   Finish(instr, position);
228 }
229
230
231 void HBasicBlock::AddLeaveInlined(HValue* return_value, FunctionState* state,
232                                   SourcePosition position) {
233   HBasicBlock* target = state->function_return();
234   bool drop_extra = state->inlining_kind() == NORMAL_RETURN;
235
236   DCHECK(target->IsInlineReturnTarget());
237   DCHECK(return_value != NULL);
238   HEnvironment* env = last_environment();
239   int argument_count = env->arguments_environment()->parameter_count();
240   AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count),
241                  position);
242   UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
243   last_environment()->Push(return_value);
244   AddNewSimulate(BailoutId::None(), position);
245   HGoto* instr = new(zone()) HGoto(target);
246   Finish(instr, position);
247 }
248
249
250 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
251   DCHECK(!HasEnvironment());
252   DCHECK(first() == NULL);
253   UpdateEnvironment(env);
254 }
255
256
257 void HBasicBlock::UpdateEnvironment(HEnvironment* env) {
258   last_environment_ = env;
259   graph()->update_maximum_environment_size(env->first_expression_index());
260 }
261
262
263 void HBasicBlock::SetJoinId(BailoutId ast_id) {
264   int length = predecessors_.length();
265   DCHECK(length > 0);
266   for (int i = 0; i < length; i++) {
267     HBasicBlock* predecessor = predecessors_[i];
268     DCHECK(predecessor->end()->IsGoto());
269     HSimulate* simulate = HSimulate::cast(predecessor->end()->previous());
270     DCHECK(i != 0 ||
271            (predecessor->last_environment()->closure().is_null() ||
272             predecessor->last_environment()->closure()->shared()
273               ->VerifyBailoutId(ast_id)));
274     simulate->set_ast_id(ast_id);
275     predecessor->last_environment()->set_ast_id(ast_id);
276   }
277 }
278
279
280 bool HBasicBlock::Dominates(HBasicBlock* other) const {
281   HBasicBlock* current = other->dominator();
282   while (current != NULL) {
283     if (current == this) return true;
284     current = current->dominator();
285   }
286   return false;
287 }
288
289
290 bool HBasicBlock::EqualToOrDominates(HBasicBlock* other) const {
291   if (this == other) return true;
292   return Dominates(other);
293 }
294
295
296 int HBasicBlock::LoopNestingDepth() const {
297   const HBasicBlock* current = this;
298   int result  = (current->IsLoopHeader()) ? 1 : 0;
299   while (current->parent_loop_header() != NULL) {
300     current = current->parent_loop_header();
301     result++;
302   }
303   return result;
304 }
305
306
307 void HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) {
308   DCHECK(IsLoopHeader());
309
310   SetJoinId(stmt->EntryId());
311   if (predecessors()->length() == 1) {
312     // This is a degenerated loop.
313     DetachLoopInformation();
314     return;
315   }
316
317   // Only the first entry into the loop is from outside the loop. All other
318   // entries must be back edges.
319   for (int i = 1; i < predecessors()->length(); ++i) {
320     loop_information()->RegisterBackEdge(predecessors()->at(i));
321   }
322 }
323
324
325 void HBasicBlock::MarkSuccEdgeUnreachable(int succ) {
326   DCHECK(IsFinished());
327   HBasicBlock* succ_block = end()->SuccessorAt(succ);
328
329   DCHECK(succ_block->predecessors()->length() == 1);
330   succ_block->MarkUnreachable();
331 }
332
333
334 void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
335   if (HasPredecessor()) {
336     // Only loop header blocks can have a predecessor added after
337     // instructions have been added to the block (they have phis for all
338     // values in the environment, these phis may be eliminated later).
339     DCHECK(IsLoopHeader() || first_ == NULL);
340     HEnvironment* incoming_env = pred->last_environment();
341     if (IsLoopHeader()) {
342       DCHECK(phis()->length() == incoming_env->length());
343       for (int i = 0; i < phis_.length(); ++i) {
344         phis_[i]->AddInput(incoming_env->values()->at(i));
345       }
346     } else {
347       last_environment()->AddIncomingEdge(this, pred->last_environment());
348     }
349   } else if (!HasEnvironment() && !IsFinished()) {
350     DCHECK(!IsLoopHeader());
351     SetInitialEnvironment(pred->last_environment()->Copy());
352   }
353
354   predecessors_.Add(pred, zone());
355 }
356
357
358 void HBasicBlock::AddDominatedBlock(HBasicBlock* block) {
359   DCHECK(!dominated_blocks_.Contains(block));
360   // Keep the list of dominated blocks sorted such that if there is two
361   // succeeding block in this list, the predecessor is before the successor.
362   int index = 0;
363   while (index < dominated_blocks_.length() &&
364          dominated_blocks_[index]->block_id() < block->block_id()) {
365     ++index;
366   }
367   dominated_blocks_.InsertAt(index, block, zone());
368 }
369
370
371 void HBasicBlock::AssignCommonDominator(HBasicBlock* other) {
372   if (dominator_ == NULL) {
373     dominator_ = other;
374     other->AddDominatedBlock(this);
375   } else if (other->dominator() != NULL) {
376     HBasicBlock* first = dominator_;
377     HBasicBlock* second = other;
378
379     while (first != second) {
380       if (first->block_id() > second->block_id()) {
381         first = first->dominator();
382       } else {
383         second = second->dominator();
384       }
385       DCHECK(first != NULL && second != NULL);
386     }
387
388     if (dominator_ != first) {
389       DCHECK(dominator_->dominated_blocks_.Contains(this));
390       dominator_->dominated_blocks_.RemoveElement(this);
391       dominator_ = first;
392       first->AddDominatedBlock(this);
393     }
394   }
395 }
396
397
398 void HBasicBlock::AssignLoopSuccessorDominators() {
399   // Mark blocks that dominate all subsequent reachable blocks inside their
400   // loop. Exploit the fact that blocks are sorted in reverse post order. When
401   // the loop is visited in increasing block id order, if the number of
402   // non-loop-exiting successor edges at the dominator_candidate block doesn't
403   // exceed the number of previously encountered predecessor edges, there is no
404   // path from the loop header to any block with higher id that doesn't go
405   // through the dominator_candidate block. In this case, the
406   // dominator_candidate block is guaranteed to dominate all blocks reachable
407   // from it with higher ids.
408   HBasicBlock* last = loop_information()->GetLastBackEdge();
409   int outstanding_successors = 1;  // one edge from the pre-header
410   // Header always dominates everything.
411   MarkAsLoopSuccessorDominator();
412   for (int j = block_id(); j <= last->block_id(); ++j) {
413     HBasicBlock* dominator_candidate = graph_->blocks()->at(j);
414     for (HPredecessorIterator it(dominator_candidate); !it.Done();
415          it.Advance()) {
416       HBasicBlock* predecessor = it.Current();
417       // Don't count back edges.
418       if (predecessor->block_id() < dominator_candidate->block_id()) {
419         outstanding_successors--;
420       }
421     }
422
423     // If more successors than predecessors have been seen in the loop up to
424     // now, it's not possible to guarantee that the current block dominates
425     // all of the blocks with higher IDs. In this case, assume conservatively
426     // that those paths through loop that don't go through the current block
427     // contain all of the loop's dependencies. Also be careful to record
428     // dominator information about the current loop that's being processed,
429     // and not nested loops, which will be processed when
430     // AssignLoopSuccessorDominators gets called on their header.
431     DCHECK(outstanding_successors >= 0);
432     HBasicBlock* parent_loop_header = dominator_candidate->parent_loop_header();
433     if (outstanding_successors == 0 &&
434         (parent_loop_header == this && !dominator_candidate->IsLoopHeader())) {
435       dominator_candidate->MarkAsLoopSuccessorDominator();
436     }
437     HControlInstruction* end = dominator_candidate->end();
438     for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
439       HBasicBlock* successor = it.Current();
440       // Only count successors that remain inside the loop and don't loop back
441       // to a loop header.
442       if (successor->block_id() > dominator_candidate->block_id() &&
443           successor->block_id() <= last->block_id()) {
444         // Backwards edges must land on loop headers.
445         DCHECK(successor->block_id() > dominator_candidate->block_id() ||
446                successor->IsLoopHeader());
447         outstanding_successors++;
448       }
449     }
450   }
451 }
452
453
454 int HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const {
455   for (int i = 0; i < predecessors_.length(); ++i) {
456     if (predecessors_[i] == predecessor) return i;
457   }
458   UNREACHABLE();
459   return -1;
460 }
461
462
463 #ifdef DEBUG
464 void HBasicBlock::Verify() {
465   // Check that every block is finished.
466   DCHECK(IsFinished());
467   DCHECK(block_id() >= 0);
468
469   // Check that the incoming edges are in edge split form.
470   if (predecessors_.length() > 1) {
471     for (int i = 0; i < predecessors_.length(); ++i) {
472       DCHECK(predecessors_[i]->end()->SecondSuccessor() == NULL);
473     }
474   }
475 }
476 #endif
477
478
479 void HLoopInformation::RegisterBackEdge(HBasicBlock* block) {
480   this->back_edges_.Add(block, block->zone());
481   AddBlock(block);
482 }
483
484
485 HBasicBlock* HLoopInformation::GetLastBackEdge() const {
486   int max_id = -1;
487   HBasicBlock* result = NULL;
488   for (int i = 0; i < back_edges_.length(); ++i) {
489     HBasicBlock* cur = back_edges_[i];
490     if (cur->block_id() > max_id) {
491       max_id = cur->block_id();
492       result = cur;
493     }
494   }
495   return result;
496 }
497
498
499 void HLoopInformation::AddBlock(HBasicBlock* block) {
500   if (block == loop_header()) return;
501   if (block->parent_loop_header() == loop_header()) return;
502   if (block->parent_loop_header() != NULL) {
503     AddBlock(block->parent_loop_header());
504   } else {
505     block->set_parent_loop_header(loop_header());
506     blocks_.Add(block, block->zone());
507     for (int i = 0; i < block->predecessors()->length(); ++i) {
508       AddBlock(block->predecessors()->at(i));
509     }
510   }
511 }
512
513
514 #ifdef DEBUG
515
516 // Checks reachability of the blocks in this graph and stores a bit in
517 // the BitVector "reachable()" for every block that can be reached
518 // from the start block of the graph. If "dont_visit" is non-null, the given
519 // block is treated as if it would not be part of the graph. "visited_count()"
520 // returns the number of reachable blocks.
521 class ReachabilityAnalyzer BASE_EMBEDDED {
522  public:
523   ReachabilityAnalyzer(HBasicBlock* entry_block,
524                        int block_count,
525                        HBasicBlock* dont_visit)
526       : visited_count_(0),
527         stack_(16, entry_block->zone()),
528         reachable_(block_count, entry_block->zone()),
529         dont_visit_(dont_visit) {
530     PushBlock(entry_block);
531     Analyze();
532   }
533
534   int visited_count() const { return visited_count_; }
535   const BitVector* reachable() const { return &reachable_; }
536
537  private:
538   void PushBlock(HBasicBlock* block) {
539     if (block != NULL && block != dont_visit_ &&
540         !reachable_.Contains(block->block_id())) {
541       reachable_.Add(block->block_id());
542       stack_.Add(block, block->zone());
543       visited_count_++;
544     }
545   }
546
547   void Analyze() {
548     while (!stack_.is_empty()) {
549       HControlInstruction* end = stack_.RemoveLast()->end();
550       for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
551         PushBlock(it.Current());
552       }
553     }
554   }
555
556   int visited_count_;
557   ZoneList<HBasicBlock*> stack_;
558   BitVector reachable_;
559   HBasicBlock* dont_visit_;
560 };
561
562
563 void HGraph::Verify(bool do_full_verify) const {
564   Heap::RelocationLock relocation_lock(isolate()->heap());
565   AllowHandleDereference allow_deref;
566   AllowDeferredHandleDereference allow_deferred_deref;
567   for (int i = 0; i < blocks_.length(); i++) {
568     HBasicBlock* block = blocks_.at(i);
569
570     block->Verify();
571
572     // Check that every block contains at least one node and that only the last
573     // node is a control instruction.
574     HInstruction* current = block->first();
575     DCHECK(current != NULL && current->IsBlockEntry());
576     while (current != NULL) {
577       DCHECK((current->next() == NULL) == current->IsControlInstruction());
578       DCHECK(current->block() == block);
579       current->Verify();
580       current = current->next();
581     }
582
583     // Check that successors are correctly set.
584     HBasicBlock* first = block->end()->FirstSuccessor();
585     HBasicBlock* second = block->end()->SecondSuccessor();
586     DCHECK(second == NULL || first != NULL);
587
588     // Check that the predecessor array is correct.
589     if (first != NULL) {
590       DCHECK(first->predecessors()->Contains(block));
591       if (second != NULL) {
592         DCHECK(second->predecessors()->Contains(block));
593       }
594     }
595
596     // Check that phis have correct arguments.
597     for (int j = 0; j < block->phis()->length(); j++) {
598       HPhi* phi = block->phis()->at(j);
599       phi->Verify();
600     }
601
602     // Check that all join blocks have predecessors that end with an
603     // unconditional goto and agree on their environment node id.
604     if (block->predecessors()->length() >= 2) {
605       BailoutId id =
606           block->predecessors()->first()->last_environment()->ast_id();
607       for (int k = 0; k < block->predecessors()->length(); k++) {
608         HBasicBlock* predecessor = block->predecessors()->at(k);
609         DCHECK(predecessor->end()->IsGoto() ||
610                predecessor->end()->IsDeoptimize());
611         DCHECK(predecessor->last_environment()->ast_id() == id);
612       }
613     }
614   }
615
616   // Check special property of first block to have no predecessors.
617   DCHECK(blocks_.at(0)->predecessors()->is_empty());
618
619   if (do_full_verify) {
620     // Check that the graph is fully connected.
621     ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL);
622     DCHECK(analyzer.visited_count() == blocks_.length());
623
624     // Check that entry block dominator is NULL.
625     DCHECK(entry_block_->dominator() == NULL);
626
627     // Check dominators.
628     for (int i = 0; i < blocks_.length(); ++i) {
629       HBasicBlock* block = blocks_.at(i);
630       if (block->dominator() == NULL) {
631         // Only start block may have no dominator assigned to.
632         DCHECK(i == 0);
633       } else {
634         // Assert that block is unreachable if dominator must not be visited.
635         ReachabilityAnalyzer dominator_analyzer(entry_block_,
636                                                 blocks_.length(),
637                                                 block->dominator());
638         DCHECK(!dominator_analyzer.reachable()->Contains(block->block_id()));
639       }
640     }
641   }
642 }
643
644 #endif
645
646
647 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
648                                int32_t value) {
649   if (!pointer->is_set()) {
650     // Can't pass GetInvalidContext() to HConstant::New, because that will
651     // recursively call GetConstant
652     HConstant* constant = HConstant::New(isolate(), zone(), NULL, value);
653     constant->InsertAfter(entry_block()->first());
654     pointer->set(constant);
655     return constant;
656   }
657   return ReinsertConstantIfNecessary(pointer->get());
658 }
659
660
661 HConstant* HGraph::ReinsertConstantIfNecessary(HConstant* constant) {
662   if (!constant->IsLinked()) {
663     // The constant was removed from the graph. Reinsert.
664     constant->ClearFlag(HValue::kIsDead);
665     constant->InsertAfter(entry_block()->first());
666   }
667   return constant;
668 }
669
670
671 HConstant* HGraph::GetConstant0() {
672   return GetConstant(&constant_0_, 0);
673 }
674
675
676 HConstant* HGraph::GetConstant1() {
677   return GetConstant(&constant_1_, 1);
678 }
679
680
681 HConstant* HGraph::GetConstantMinus1() {
682   return GetConstant(&constant_minus1_, -1);
683 }
684
685
686 #define DEFINE_GET_CONSTANT(Name, name, type, htype, boolean_value)            \
687 HConstant* HGraph::GetConstant##Name() {                                       \
688   if (!constant_##name##_.is_set()) {                                          \
689     HConstant* constant = new(zone()) HConstant(                               \
690         Unique<Object>::CreateImmovable(isolate()->factory()->name##_value()), \
691         Unique<Map>::CreateImmovable(isolate()->factory()->type##_map()),      \
692         false,                                                                 \
693         Representation::Tagged(),                                              \
694         htype,                                                                 \
695         true,                                                                  \
696         boolean_value,                                                         \
697         false,                                                                 \
698         ODDBALL_TYPE);                                                         \
699     constant->InsertAfter(entry_block()->first());                             \
700     constant_##name##_.set(constant);                                          \
701   }                                                                            \
702   return ReinsertConstantIfNecessary(constant_##name##_.get());                \
703 }
704
705
706 DEFINE_GET_CONSTANT(Undefined, undefined, undefined, HType::Undefined(), false)
707 DEFINE_GET_CONSTANT(True, true, boolean, HType::Boolean(), true)
708 DEFINE_GET_CONSTANT(False, false, boolean, HType::Boolean(), false)
709 DEFINE_GET_CONSTANT(Hole, the_hole, the_hole, HType::None(), false)
710 DEFINE_GET_CONSTANT(Null, null, null, HType::Null(), false)
711
712
713 #undef DEFINE_GET_CONSTANT
714
715 #define DEFINE_IS_CONSTANT(Name, name)                                         \
716 bool HGraph::IsConstant##Name(HConstant* constant) {                           \
717   return constant_##name##_.is_set() && constant == constant_##name##_.get();  \
718 }
719 DEFINE_IS_CONSTANT(Undefined, undefined)
720 DEFINE_IS_CONSTANT(0, 0)
721 DEFINE_IS_CONSTANT(1, 1)
722 DEFINE_IS_CONSTANT(Minus1, minus1)
723 DEFINE_IS_CONSTANT(True, true)
724 DEFINE_IS_CONSTANT(False, false)
725 DEFINE_IS_CONSTANT(Hole, the_hole)
726 DEFINE_IS_CONSTANT(Null, null)
727
728 #undef DEFINE_IS_CONSTANT
729
730
731 HConstant* HGraph::GetInvalidContext() {
732   return GetConstant(&constant_invalid_context_, 0xFFFFC0C7);
733 }
734
735
736 bool HGraph::IsStandardConstant(HConstant* constant) {
737   if (IsConstantUndefined(constant)) return true;
738   if (IsConstant0(constant)) return true;
739   if (IsConstant1(constant)) return true;
740   if (IsConstantMinus1(constant)) return true;
741   if (IsConstantTrue(constant)) return true;
742   if (IsConstantFalse(constant)) return true;
743   if (IsConstantHole(constant)) return true;
744   if (IsConstantNull(constant)) return true;
745   return false;
746 }
747
748
749 HGraphBuilder::IfBuilder::IfBuilder() : builder_(NULL), needs_compare_(true) {}
750
751
752 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder)
753     : needs_compare_(true) {
754   Initialize(builder);
755 }
756
757
758 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder,
759                                     HIfContinuation* continuation)
760     : needs_compare_(false), first_true_block_(NULL), first_false_block_(NULL) {
761   InitializeDontCreateBlocks(builder);
762   continuation->Continue(&first_true_block_, &first_false_block_);
763 }
764
765
766 void HGraphBuilder::IfBuilder::InitializeDontCreateBlocks(
767     HGraphBuilder* builder) {
768   builder_ = builder;
769   finished_ = false;
770   did_then_ = false;
771   did_else_ = false;
772   did_else_if_ = false;
773   did_and_ = false;
774   did_or_ = false;
775   captured_ = false;
776   pending_merge_block_ = false;
777   split_edge_merge_block_ = NULL;
778   merge_at_join_blocks_ = NULL;
779   normal_merge_at_join_block_count_ = 0;
780   deopt_merge_at_join_block_count_ = 0;
781 }
782
783
784 void HGraphBuilder::IfBuilder::Initialize(HGraphBuilder* builder) {
785   InitializeDontCreateBlocks(builder);
786   HEnvironment* env = builder->environment();
787   first_true_block_ = builder->CreateBasicBlock(env->Copy());
788   first_false_block_ = builder->CreateBasicBlock(env->Copy());
789 }
790
791
792 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare(
793     HControlInstruction* compare) {
794   DCHECK(did_then_ == did_else_);
795   if (did_else_) {
796     // Handle if-then-elseif
797     did_else_if_ = true;
798     did_else_ = false;
799     did_then_ = false;
800     did_and_ = false;
801     did_or_ = false;
802     pending_merge_block_ = false;
803     split_edge_merge_block_ = NULL;
804     HEnvironment* env = builder()->environment();
805     first_true_block_ = builder()->CreateBasicBlock(env->Copy());
806     first_false_block_ = builder()->CreateBasicBlock(env->Copy());
807   }
808   if (split_edge_merge_block_ != NULL) {
809     HEnvironment* env = first_false_block_->last_environment();
810     HBasicBlock* split_edge = builder()->CreateBasicBlock(env->Copy());
811     if (did_or_) {
812       compare->SetSuccessorAt(0, split_edge);
813       compare->SetSuccessorAt(1, first_false_block_);
814     } else {
815       compare->SetSuccessorAt(0, first_true_block_);
816       compare->SetSuccessorAt(1, split_edge);
817     }
818     builder()->GotoNoSimulate(split_edge, split_edge_merge_block_);
819   } else {
820     compare->SetSuccessorAt(0, first_true_block_);
821     compare->SetSuccessorAt(1, first_false_block_);
822   }
823   builder()->FinishCurrentBlock(compare);
824   needs_compare_ = false;
825   return compare;
826 }
827
828
829 void HGraphBuilder::IfBuilder::Or() {
830   DCHECK(!needs_compare_);
831   DCHECK(!did_and_);
832   did_or_ = true;
833   HEnvironment* env = first_false_block_->last_environment();
834   if (split_edge_merge_block_ == NULL) {
835     split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
836     builder()->GotoNoSimulate(first_true_block_, split_edge_merge_block_);
837     first_true_block_ = split_edge_merge_block_;
838   }
839   builder()->set_current_block(first_false_block_);
840   first_false_block_ = builder()->CreateBasicBlock(env->Copy());
841 }
842
843
844 void HGraphBuilder::IfBuilder::And() {
845   DCHECK(!needs_compare_);
846   DCHECK(!did_or_);
847   did_and_ = true;
848   HEnvironment* env = first_false_block_->last_environment();
849   if (split_edge_merge_block_ == NULL) {
850     split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
851     builder()->GotoNoSimulate(first_false_block_, split_edge_merge_block_);
852     first_false_block_ = split_edge_merge_block_;
853   }
854   builder()->set_current_block(first_true_block_);
855   first_true_block_ = builder()->CreateBasicBlock(env->Copy());
856 }
857
858
859 void HGraphBuilder::IfBuilder::CaptureContinuation(
860     HIfContinuation* continuation) {
861   DCHECK(!did_else_if_);
862   DCHECK(!finished_);
863   DCHECK(!captured_);
864
865   HBasicBlock* true_block = NULL;
866   HBasicBlock* false_block = NULL;
867   Finish(&true_block, &false_block);
868   DCHECK(true_block != NULL);
869   DCHECK(false_block != NULL);
870   continuation->Capture(true_block, false_block);
871   captured_ = true;
872   builder()->set_current_block(NULL);
873   End();
874 }
875
876
877 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) {
878   DCHECK(!did_else_if_);
879   DCHECK(!finished_);
880   DCHECK(!captured_);
881   HBasicBlock* true_block = NULL;
882   HBasicBlock* false_block = NULL;
883   Finish(&true_block, &false_block);
884   merge_at_join_blocks_ = NULL;
885   if (true_block != NULL && !true_block->IsFinished()) {
886     DCHECK(continuation->IsTrueReachable());
887     builder()->GotoNoSimulate(true_block, continuation->true_branch());
888   }
889   if (false_block != NULL && !false_block->IsFinished()) {
890     DCHECK(continuation->IsFalseReachable());
891     builder()->GotoNoSimulate(false_block, continuation->false_branch());
892   }
893   captured_ = true;
894   End();
895 }
896
897
898 void HGraphBuilder::IfBuilder::Then() {
899   DCHECK(!captured_);
900   DCHECK(!finished_);
901   did_then_ = true;
902   if (needs_compare_) {
903     // Handle if's without any expressions, they jump directly to the "else"
904     // branch. However, we must pretend that the "then" branch is reachable,
905     // so that the graph builder visits it and sees any live range extending
906     // constructs within it.
907     HConstant* constant_false = builder()->graph()->GetConstantFalse();
908     ToBooleanStub::Types boolean_type = ToBooleanStub::Types();
909     boolean_type.Add(ToBooleanStub::BOOLEAN);
910     HBranch* branch = builder()->New<HBranch>(
911         constant_false, boolean_type, first_true_block_, first_false_block_);
912     builder()->FinishCurrentBlock(branch);
913   }
914   builder()->set_current_block(first_true_block_);
915   pending_merge_block_ = true;
916 }
917
918
919 void HGraphBuilder::IfBuilder::Else() {
920   DCHECK(did_then_);
921   DCHECK(!captured_);
922   DCHECK(!finished_);
923   AddMergeAtJoinBlock(false);
924   builder()->set_current_block(first_false_block_);
925   pending_merge_block_ = true;
926   did_else_ = true;
927 }
928
929
930 void HGraphBuilder::IfBuilder::Deopt(Deoptimizer::DeoptReason reason) {
931   DCHECK(did_then_);
932   builder()->Add<HDeoptimize>(reason, Deoptimizer::EAGER);
933   AddMergeAtJoinBlock(true);
934 }
935
936
937 void HGraphBuilder::IfBuilder::Return(HValue* value) {
938   HValue* parameter_count = builder()->graph()->GetConstantMinus1();
939   builder()->FinishExitCurrentBlock(
940       builder()->New<HReturn>(value, parameter_count));
941   AddMergeAtJoinBlock(false);
942 }
943
944
945 void HGraphBuilder::IfBuilder::AddMergeAtJoinBlock(bool deopt) {
946   if (!pending_merge_block_) return;
947   HBasicBlock* block = builder()->current_block();
948   DCHECK(block == NULL || !block->IsFinished());
949   MergeAtJoinBlock* record = new (builder()->zone())
950       MergeAtJoinBlock(block, deopt, merge_at_join_blocks_);
951   merge_at_join_blocks_ = record;
952   if (block != NULL) {
953     DCHECK(block->end() == NULL);
954     if (deopt) {
955       normal_merge_at_join_block_count_++;
956     } else {
957       deopt_merge_at_join_block_count_++;
958     }
959   }
960   builder()->set_current_block(NULL);
961   pending_merge_block_ = false;
962 }
963
964
965 void HGraphBuilder::IfBuilder::Finish() {
966   DCHECK(!finished_);
967   if (!did_then_) {
968     Then();
969   }
970   AddMergeAtJoinBlock(false);
971   if (!did_else_) {
972     Else();
973     AddMergeAtJoinBlock(false);
974   }
975   finished_ = true;
976 }
977
978
979 void HGraphBuilder::IfBuilder::Finish(HBasicBlock** then_continuation,
980                                       HBasicBlock** else_continuation) {
981   Finish();
982
983   MergeAtJoinBlock* else_record = merge_at_join_blocks_;
984   if (else_continuation != NULL) {
985     *else_continuation = else_record->block_;
986   }
987   MergeAtJoinBlock* then_record = else_record->next_;
988   if (then_continuation != NULL) {
989     *then_continuation = then_record->block_;
990   }
991   DCHECK(then_record->next_ == NULL);
992 }
993
994
995 void HGraphBuilder::IfBuilder::End() {
996   if (captured_) return;
997   Finish();
998
999   int total_merged_blocks = normal_merge_at_join_block_count_ +
1000     deopt_merge_at_join_block_count_;
1001   DCHECK(total_merged_blocks >= 1);
1002   HBasicBlock* merge_block =
1003       total_merged_blocks == 1 ? NULL : builder()->graph()->CreateBasicBlock();
1004
1005   // Merge non-deopt blocks first to ensure environment has right size for
1006   // padding.
1007   MergeAtJoinBlock* current = merge_at_join_blocks_;
1008   while (current != NULL) {
1009     if (!current->deopt_ && current->block_ != NULL) {
1010       // If there is only one block that makes it through to the end of the
1011       // if, then just set it as the current block and continue rather then
1012       // creating an unnecessary merge block.
1013       if (total_merged_blocks == 1) {
1014         builder()->set_current_block(current->block_);
1015         return;
1016       }
1017       builder()->GotoNoSimulate(current->block_, merge_block);
1018     }
1019     current = current->next_;
1020   }
1021
1022   // Merge deopt blocks, padding when necessary.
1023   current = merge_at_join_blocks_;
1024   while (current != NULL) {
1025     if (current->deopt_ && current->block_ != NULL) {
1026       current->block_->FinishExit(
1027           HAbnormalExit::New(builder()->isolate(), builder()->zone(), NULL),
1028           SourcePosition::Unknown());
1029     }
1030     current = current->next_;
1031   }
1032   builder()->set_current_block(merge_block);
1033 }
1034
1035
1036 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder) {
1037   Initialize(builder, NULL, kWhileTrue, NULL);
1038 }
1039
1040
1041 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
1042                                         LoopBuilder::Direction direction) {
1043   Initialize(builder, context, direction, builder->graph()->GetConstant1());
1044 }
1045
1046
1047 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
1048                                         LoopBuilder::Direction direction,
1049                                         HValue* increment_amount) {
1050   Initialize(builder, context, direction, increment_amount);
1051   increment_amount_ = increment_amount;
1052 }
1053
1054
1055 void HGraphBuilder::LoopBuilder::Initialize(HGraphBuilder* builder,
1056                                             HValue* context,
1057                                             Direction direction,
1058                                             HValue* increment_amount) {
1059   builder_ = builder;
1060   context_ = context;
1061   direction_ = direction;
1062   increment_amount_ = increment_amount;
1063
1064   finished_ = false;
1065   header_block_ = builder->CreateLoopHeaderBlock();
1066   body_block_ = NULL;
1067   exit_block_ = NULL;
1068   exit_trampoline_block_ = NULL;
1069 }
1070
1071
1072 HValue* HGraphBuilder::LoopBuilder::BeginBody(
1073     HValue* initial,
1074     HValue* terminating,
1075     Token::Value token) {
1076   DCHECK(direction_ != kWhileTrue);
1077   HEnvironment* env = builder_->environment();
1078   phi_ = header_block_->AddNewPhi(env->values()->length());
1079   phi_->AddInput(initial);
1080   env->Push(initial);
1081   builder_->GotoNoSimulate(header_block_);
1082
1083   HEnvironment* body_env = env->Copy();
1084   HEnvironment* exit_env = env->Copy();
1085   // Remove the phi from the expression stack
1086   body_env->Pop();
1087   exit_env->Pop();
1088   body_block_ = builder_->CreateBasicBlock(body_env);
1089   exit_block_ = builder_->CreateBasicBlock(exit_env);
1090
1091   builder_->set_current_block(header_block_);
1092   env->Pop();
1093   builder_->FinishCurrentBlock(builder_->New<HCompareNumericAndBranch>(
1094           phi_, terminating, token, body_block_, exit_block_));
1095
1096   builder_->set_current_block(body_block_);
1097   if (direction_ == kPreIncrement || direction_ == kPreDecrement) {
1098     Isolate* isolate = builder_->isolate();
1099     HValue* one = builder_->graph()->GetConstant1();
1100     if (direction_ == kPreIncrement) {
1101       increment_ = HAdd::New(isolate, zone(), context_, phi_, one);
1102     } else {
1103       increment_ = HSub::New(isolate, zone(), context_, phi_, one);
1104     }
1105     increment_->ClearFlag(HValue::kCanOverflow);
1106     builder_->AddInstruction(increment_);
1107     return increment_;
1108   } else {
1109     return phi_;
1110   }
1111 }
1112
1113
1114 void HGraphBuilder::LoopBuilder::BeginBody(int drop_count) {
1115   DCHECK(direction_ == kWhileTrue);
1116   HEnvironment* env = builder_->environment();
1117   builder_->GotoNoSimulate(header_block_);
1118   builder_->set_current_block(header_block_);
1119   env->Drop(drop_count);
1120 }
1121
1122
1123 void HGraphBuilder::LoopBuilder::Break() {
1124   if (exit_trampoline_block_ == NULL) {
1125     // Its the first time we saw a break.
1126     if (direction_ == kWhileTrue) {
1127       HEnvironment* env = builder_->environment()->Copy();
1128       exit_trampoline_block_ = builder_->CreateBasicBlock(env);
1129     } else {
1130       HEnvironment* env = exit_block_->last_environment()->Copy();
1131       exit_trampoline_block_ = builder_->CreateBasicBlock(env);
1132       builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_);
1133     }
1134   }
1135
1136   builder_->GotoNoSimulate(exit_trampoline_block_);
1137   builder_->set_current_block(NULL);
1138 }
1139
1140
1141 void HGraphBuilder::LoopBuilder::EndBody() {
1142   DCHECK(!finished_);
1143
1144   if (direction_ == kPostIncrement || direction_ == kPostDecrement) {
1145     Isolate* isolate = builder_->isolate();
1146     if (direction_ == kPostIncrement) {
1147       increment_ =
1148           HAdd::New(isolate, zone(), context_, phi_, increment_amount_);
1149     } else {
1150       increment_ =
1151           HSub::New(isolate, zone(), context_, phi_, increment_amount_);
1152     }
1153     increment_->ClearFlag(HValue::kCanOverflow);
1154     builder_->AddInstruction(increment_);
1155   }
1156
1157   if (direction_ != kWhileTrue) {
1158     // Push the new increment value on the expression stack to merge into
1159     // the phi.
1160     builder_->environment()->Push(increment_);
1161   }
1162   HBasicBlock* last_block = builder_->current_block();
1163   builder_->GotoNoSimulate(last_block, header_block_);
1164   header_block_->loop_information()->RegisterBackEdge(last_block);
1165
1166   if (exit_trampoline_block_ != NULL) {
1167     builder_->set_current_block(exit_trampoline_block_);
1168   } else {
1169     builder_->set_current_block(exit_block_);
1170   }
1171   finished_ = true;
1172 }
1173
1174
1175 HGraph* HGraphBuilder::CreateGraph() {
1176   graph_ = new(zone()) HGraph(info_);
1177   if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_);
1178   CompilationPhase phase("H_Block building", info_);
1179   set_current_block(graph()->entry_block());
1180   if (!BuildGraph()) return NULL;
1181   graph()->FinalizeUniqueness();
1182   return graph_;
1183 }
1184
1185
1186 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
1187   DCHECK(current_block() != NULL);
1188   DCHECK(!FLAG_hydrogen_track_positions ||
1189          !position_.IsUnknown() ||
1190          !info_->IsOptimizing());
1191   current_block()->AddInstruction(instr, source_position());
1192   if (graph()->IsInsideNoSideEffectsScope()) {
1193     instr->SetFlag(HValue::kHasNoObservableSideEffects);
1194   }
1195   return instr;
1196 }
1197
1198
1199 void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) {
1200   DCHECK(!FLAG_hydrogen_track_positions ||
1201          !info_->IsOptimizing() ||
1202          !position_.IsUnknown());
1203   current_block()->Finish(last, source_position());
1204   if (last->IsReturn() || last->IsAbnormalExit()) {
1205     set_current_block(NULL);
1206   }
1207 }
1208
1209
1210 void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) {
1211   DCHECK(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() ||
1212          !position_.IsUnknown());
1213   current_block()->FinishExit(instruction, source_position());
1214   if (instruction->IsReturn() || instruction->IsAbnormalExit()) {
1215     set_current_block(NULL);
1216   }
1217 }
1218
1219
1220 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) {
1221   if (FLAG_native_code_counters && counter->Enabled()) {
1222     HValue* reference = Add<HConstant>(ExternalReference(counter));
1223     HValue* old_value =
1224         Add<HLoadNamedField>(reference, nullptr, HObjectAccess::ForCounter());
1225     HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1());
1226     new_value->ClearFlag(HValue::kCanOverflow);  // Ignore counter overflow
1227     Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(),
1228                           new_value, STORE_TO_INITIALIZED_ENTRY);
1229   }
1230 }
1231
1232
1233 void HGraphBuilder::AddSimulate(BailoutId id,
1234                                 RemovableSimulate removable) {
1235   DCHECK(current_block() != NULL);
1236   DCHECK(!graph()->IsInsideNoSideEffectsScope());
1237   current_block()->AddNewSimulate(id, source_position(), removable);
1238 }
1239
1240
1241 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
1242   HBasicBlock* b = graph()->CreateBasicBlock();
1243   b->SetInitialEnvironment(env);
1244   return b;
1245 }
1246
1247
1248 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
1249   HBasicBlock* header = graph()->CreateBasicBlock();
1250   HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
1251   header->SetInitialEnvironment(entry_env);
1252   header->AttachLoopInformation();
1253   return header;
1254 }
1255
1256
1257 HValue* HGraphBuilder::BuildGetElementsKind(HValue* object) {
1258   HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap());
1259
1260   HValue* bit_field2 =
1261       Add<HLoadNamedField>(map, nullptr, 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(
1273     Deoptimizer::DeoptReason reason) {
1274   Add<HDeoptimize>(reason, Deoptimizer::EAGER);
1275   FinishExitCurrentBlock(New<HAbnormalExit>());
1276 }
1277
1278
1279 HValue* HGraphBuilder::BuildCheckString(HValue* string) {
1280   if (!string->type().IsString()) {
1281     DCHECK(!string->IsConstant() ||
1282            !HConstant::cast(string)->HasStringValue());
1283     BuildCheckHeapObject(string);
1284     return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
1285   }
1286   return string;
1287 }
1288
1289
1290 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) {
1291   if (object->type().IsJSObject()) return object;
1292   if (function->IsConstant() &&
1293       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
1294     Handle<JSFunction> f = Handle<JSFunction>::cast(
1295         HConstant::cast(function)->handle(isolate()));
1296     SharedFunctionInfo* shared = f->shared();
1297     if (is_strict(shared->language_mode()) || shared->native()) return object;
1298   }
1299   return Add<HWrapReceiver>(object, function);
1300 }
1301
1302
1303 HValue* HGraphBuilder::BuildCheckForCapacityGrow(
1304     HValue* object,
1305     HValue* elements,
1306     ElementsKind kind,
1307     HValue* length,
1308     HValue* key,
1309     bool is_js_array,
1310     PropertyAccessType access_type) {
1311   IfBuilder length_checker(this);
1312
1313   Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
1314   length_checker.If<HCompareNumericAndBranch>(key, length, token);
1315
1316   length_checker.Then();
1317
1318   HValue* current_capacity = AddLoadFixedArrayLength(elements);
1319
1320   IfBuilder capacity_checker(this);
1321
1322   capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity,
1323                                                 Token::GTE);
1324   capacity_checker.Then();
1325
1326   HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
1327   HValue* max_capacity = AddUncasted<HAdd>(current_capacity, max_gap);
1328
1329   Add<HBoundsCheck>(key, max_capacity);
1330
1331   HValue* new_capacity = BuildNewElementsCapacity(key);
1332   HValue* new_elements = BuildGrowElementsCapacity(object, elements,
1333                                                    kind, kind, length,
1334                                                    new_capacity);
1335
1336   environment()->Push(new_elements);
1337   capacity_checker.Else();
1338
1339   environment()->Push(elements);
1340   capacity_checker.End();
1341
1342   if (is_js_array) {
1343     HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1());
1344     new_length->ClearFlag(HValue::kCanOverflow);
1345
1346     Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind),
1347                           new_length);
1348   }
1349
1350   if (access_type == STORE && kind == FAST_SMI_ELEMENTS) {
1351     HValue* checked_elements = environment()->Top();
1352
1353     // Write zero to ensure that the new element is initialized with some smi.
1354     Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), kind);
1355   }
1356
1357   length_checker.Else();
1358   Add<HBoundsCheck>(key, length);
1359
1360   environment()->Push(elements);
1361   length_checker.End();
1362
1363   return environment()->Pop();
1364 }
1365
1366
1367 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
1368                                                 HValue* elements,
1369                                                 ElementsKind kind,
1370                                                 HValue* length) {
1371   Factory* factory = isolate()->factory();
1372
1373   IfBuilder cow_checker(this);
1374
1375   cow_checker.If<HCompareMap>(elements, factory->fixed_cow_array_map());
1376   cow_checker.Then();
1377
1378   HValue* capacity = AddLoadFixedArrayLength(elements);
1379
1380   HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind,
1381                                                    kind, length, capacity);
1382
1383   environment()->Push(new_elements);
1384
1385   cow_checker.Else();
1386
1387   environment()->Push(elements);
1388
1389   cow_checker.End();
1390
1391   return environment()->Pop();
1392 }
1393
1394
1395 void HGraphBuilder::BuildTransitionElementsKind(HValue* object,
1396                                                 HValue* map,
1397                                                 ElementsKind from_kind,
1398                                                 ElementsKind to_kind,
1399                                                 bool is_jsarray) {
1400   DCHECK(!IsFastHoleyElementsKind(from_kind) ||
1401          IsFastHoleyElementsKind(to_kind));
1402
1403   if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) {
1404     Add<HTrapAllocationMemento>(object);
1405   }
1406
1407   if (!IsSimpleMapChangeTransition(from_kind, to_kind)) {
1408     HInstruction* elements = AddLoadElements(object);
1409
1410     HInstruction* empty_fixed_array = Add<HConstant>(
1411         isolate()->factory()->empty_fixed_array());
1412
1413     IfBuilder if_builder(this);
1414
1415     if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array);
1416
1417     if_builder.Then();
1418
1419     HInstruction* elements_length = AddLoadFixedArrayLength(elements);
1420
1421     HInstruction* array_length =
1422         is_jsarray
1423             ? Add<HLoadNamedField>(object, nullptr,
1424                                    HObjectAccess::ForArrayLength(from_kind))
1425             : elements_length;
1426
1427     BuildGrowElementsCapacity(object, elements, from_kind, to_kind,
1428                               array_length, elements_length);
1429
1430     if_builder.End();
1431   }
1432
1433   Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map);
1434 }
1435
1436
1437 void HGraphBuilder::BuildJSObjectCheck(HValue* receiver,
1438                                        int bit_field_mask) {
1439   // Check that the object isn't a smi.
1440   Add<HCheckHeapObject>(receiver);
1441
1442   // Get the map of the receiver.
1443   HValue* map =
1444       Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
1445
1446   // Check the instance type and if an access check is needed, this can be
1447   // done with a single load, since both bytes are adjacent in the map.
1448   HObjectAccess access(HObjectAccess::ForMapInstanceTypeAndBitField());
1449   HValue* instance_type_and_bit_field =
1450       Add<HLoadNamedField>(map, nullptr, access);
1451
1452   HValue* mask = Add<HConstant>(0x00FF | (bit_field_mask << 8));
1453   HValue* and_result = AddUncasted<HBitwise>(Token::BIT_AND,
1454                                              instance_type_and_bit_field,
1455                                              mask);
1456   HValue* sub_result = AddUncasted<HSub>(and_result,
1457                                          Add<HConstant>(JS_OBJECT_TYPE));
1458   Add<HBoundsCheck>(sub_result,
1459                     Add<HConstant>(LAST_JS_OBJECT_TYPE + 1 - JS_OBJECT_TYPE));
1460 }
1461
1462
1463 void HGraphBuilder::BuildKeyedIndexCheck(HValue* key,
1464                                          HIfContinuation* join_continuation) {
1465   // The sometimes unintuitively backward ordering of the ifs below is
1466   // convoluted, but necessary.  All of the paths must guarantee that the
1467   // if-true of the continuation returns a smi element index and the if-false of
1468   // the continuation returns either a symbol or a unique string key. All other
1469   // object types cause a deopt to fall back to the runtime.
1470
1471   IfBuilder key_smi_if(this);
1472   key_smi_if.If<HIsSmiAndBranch>(key);
1473   key_smi_if.Then();
1474   {
1475     Push(key);  // Nothing to do, just continue to true of continuation.
1476   }
1477   key_smi_if.Else();
1478   {
1479     HValue* map = Add<HLoadNamedField>(key, nullptr, HObjectAccess::ForMap());
1480     HValue* instance_type =
1481         Add<HLoadNamedField>(map, nullptr, 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 = Add<HLoadNamedField>(key, nullptr,
1514                                             HObjectAccess::ForNameHashField());
1515         HValue* not_index_mask = Add<HConstant>(static_cast<int>(
1516             String::kContainsCachedArrayIndexMask));
1517
1518         HValue* not_index_test = AddUncasted<HBitwise>(
1519             Token::BIT_AND, hash, not_index_mask);
1520
1521         IfBuilder string_index_if(this);
1522         string_index_if.If<HCompareNumericAndBranch>(not_index_test,
1523                                                      graph()->GetConstant0(),
1524                                                      Token::EQ);
1525         string_index_if.Then();
1526         {
1527           // String with index in hash: extract string and merge to index path.
1528           Push(BuildDecodeField<String::ArrayIndexValueBits>(hash));
1529         }
1530         string_index_if.Else();
1531         {
1532           // Key is a non-index String, check for uniqueness/internalization.
1533           // If it's not internalized yet, internalize it now.
1534           HValue* not_internalized_bit = AddUncasted<HBitwise>(
1535               Token::BIT_AND,
1536               instance_type,
1537               Add<HConstant>(static_cast<int>(kIsNotInternalizedMask)));
1538
1539           IfBuilder internalized(this);
1540           internalized.If<HCompareNumericAndBranch>(not_internalized_bit,
1541                                                     graph()->GetConstant0(),
1542                                                     Token::EQ);
1543           internalized.Then();
1544           Push(key);
1545
1546           internalized.Else();
1547           Add<HPushArguments>(key);
1548           HValue* intern_key = Add<HCallRuntime>(
1549               isolate()->factory()->empty_string(),
1550               Runtime::FunctionForId(Runtime::kInternalizeString), 1);
1551           Push(intern_key);
1552
1553           internalized.End();
1554           // Key guaranteed to be a unique string
1555         }
1556         string_index_if.JoinContinuation(join_continuation);
1557       }
1558       not_symbol_if.Else();
1559       {
1560         Push(key);  // Key is symbol
1561       }
1562       not_symbol_if.JoinContinuation(join_continuation);
1563     }
1564     not_string_or_name_if.JoinContinuation(join_continuation);
1565   }
1566   key_smi_if.JoinContinuation(join_continuation);
1567 }
1568
1569
1570 void HGraphBuilder::BuildNonGlobalObjectCheck(HValue* receiver) {
1571   // Get the the instance type of the receiver, and make sure that it is
1572   // not one of the global object types.
1573   HValue* map =
1574       Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
1575   HValue* instance_type =
1576       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
1577   STATIC_ASSERT(JS_BUILTINS_OBJECT_TYPE == JS_GLOBAL_OBJECT_TYPE + 1);
1578   HValue* min_global_type = Add<HConstant>(JS_GLOBAL_OBJECT_TYPE);
1579   HValue* max_global_type = Add<HConstant>(JS_BUILTINS_OBJECT_TYPE);
1580
1581   IfBuilder if_global_object(this);
1582   if_global_object.If<HCompareNumericAndBranch>(instance_type,
1583                                                 max_global_type,
1584                                                 Token::LTE);
1585   if_global_object.And();
1586   if_global_object.If<HCompareNumericAndBranch>(instance_type,
1587                                                 min_global_type,
1588                                                 Token::GTE);
1589   if_global_object.ThenDeopt(Deoptimizer::kReceiverWasAGlobalObject);
1590   if_global_object.End();
1591 }
1592
1593
1594 void HGraphBuilder::BuildTestForDictionaryProperties(
1595     HValue* object,
1596     HIfContinuation* continuation) {
1597   HValue* properties = Add<HLoadNamedField>(
1598       object, nullptr, HObjectAccess::ForPropertiesPointer());
1599   HValue* properties_map =
1600       Add<HLoadNamedField>(properties, nullptr, HObjectAccess::ForMap());
1601   HValue* hash_map = Add<HLoadRoot>(Heap::kHashTableMapRootIndex);
1602   IfBuilder builder(this);
1603   builder.If<HCompareObjectEqAndBranch>(properties_map, hash_map);
1604   builder.CaptureContinuation(continuation);
1605 }
1606
1607
1608 HValue* HGraphBuilder::BuildKeyedLookupCacheHash(HValue* object,
1609                                                  HValue* key) {
1610   // Load the map of the receiver, compute the keyed lookup cache hash
1611   // based on 32 bits of the map pointer and the string hash.
1612   HValue* object_map =
1613       Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMapAsInteger32());
1614   HValue* shifted_map = AddUncasted<HShr>(
1615       object_map, Add<HConstant>(KeyedLookupCache::kMapHashShift));
1616   HValue* string_hash =
1617       Add<HLoadNamedField>(key, nullptr, HObjectAccess::ForStringHashField());
1618   HValue* shifted_hash = AddUncasted<HShr>(
1619       string_hash, Add<HConstant>(String::kHashShift));
1620   HValue* xor_result = AddUncasted<HBitwise>(Token::BIT_XOR, shifted_map,
1621                                              shifted_hash);
1622   int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
1623   return AddUncasted<HBitwise>(Token::BIT_AND, xor_result,
1624                                Add<HConstant>(mask));
1625 }
1626
1627
1628 HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) {
1629   int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed());
1630   HValue* seed = Add<HConstant>(seed_value);
1631   HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, index, seed);
1632
1633   // hash = ~hash + (hash << 15);
1634   HValue* shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(15));
1635   HValue* not_hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash,
1636                                            graph()->GetConstantMinus1());
1637   hash = AddUncasted<HAdd>(shifted_hash, not_hash);
1638
1639   // hash = hash ^ (hash >> 12);
1640   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(12));
1641   hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
1642
1643   // hash = hash + (hash << 2);
1644   shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(2));
1645   hash = AddUncasted<HAdd>(hash, shifted_hash);
1646
1647   // hash = hash ^ (hash >> 4);
1648   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(4));
1649   hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
1650
1651   // hash = hash * 2057;
1652   hash = AddUncasted<HMul>(hash, Add<HConstant>(2057));
1653   hash->ClearFlag(HValue::kCanOverflow);
1654
1655   // hash = hash ^ (hash >> 16);
1656   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(16));
1657   return AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
1658 }
1659
1660
1661 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver,
1662                                                            HValue* elements,
1663                                                            HValue* key,
1664                                                            HValue* hash) {
1665   HValue* capacity =
1666       Add<HLoadKeyed>(elements, Add<HConstant>(NameDictionary::kCapacityIndex),
1667                       nullptr, FAST_ELEMENTS);
1668
1669   HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1());
1670   mask->ChangeRepresentation(Representation::Integer32());
1671   mask->ClearFlag(HValue::kCanOverflow);
1672
1673   HValue* entry = hash;
1674   HValue* count = graph()->GetConstant1();
1675   Push(entry);
1676   Push(count);
1677
1678   HIfContinuation return_or_loop_continuation(graph()->CreateBasicBlock(),
1679                                               graph()->CreateBasicBlock());
1680   HIfContinuation found_key_match_continuation(graph()->CreateBasicBlock(),
1681                                                graph()->CreateBasicBlock());
1682   LoopBuilder probe_loop(this);
1683   probe_loop.BeginBody(2);  // Drop entry, count from last environment to
1684                             // appease live range building without simulates.
1685
1686   count = Pop();
1687   entry = Pop();
1688   entry = AddUncasted<HBitwise>(Token::BIT_AND, entry, mask);
1689   int entry_size = SeededNumberDictionary::kEntrySize;
1690   HValue* base_index = AddUncasted<HMul>(entry, Add<HConstant>(entry_size));
1691   base_index->ClearFlag(HValue::kCanOverflow);
1692   int start_offset = SeededNumberDictionary::kElementsStartIndex;
1693   HValue* key_index =
1694       AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset));
1695   key_index->ClearFlag(HValue::kCanOverflow);
1696
1697   HValue* candidate_key =
1698       Add<HLoadKeyed>(elements, key_index, nullptr, FAST_ELEMENTS);
1699   IfBuilder if_undefined(this);
1700   if_undefined.If<HCompareObjectEqAndBranch>(candidate_key,
1701                                              graph()->GetConstantUndefined());
1702   if_undefined.Then();
1703   {
1704     // element == undefined means "not found". Call the runtime.
1705     // TODO(jkummerow): walk the prototype chain instead.
1706     Add<HPushArguments>(receiver, key);
1707     Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
1708                            Runtime::FunctionForId(Runtime::kKeyedGetProperty),
1709                            2));
1710   }
1711   if_undefined.Else();
1712   {
1713     IfBuilder if_match(this);
1714     if_match.If<HCompareObjectEqAndBranch>(candidate_key, key);
1715     if_match.Then();
1716     if_match.Else();
1717
1718     // Update non-internalized string in the dictionary with internalized key?
1719     IfBuilder if_update_with_internalized(this);
1720     HValue* smi_check =
1721         if_update_with_internalized.IfNot<HIsSmiAndBranch>(candidate_key);
1722     if_update_with_internalized.And();
1723     HValue* map = AddLoadMap(candidate_key, smi_check);
1724     HValue* instance_type =
1725         Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
1726     HValue* not_internalized_bit = AddUncasted<HBitwise>(
1727         Token::BIT_AND, instance_type,
1728         Add<HConstant>(static_cast<int>(kIsNotInternalizedMask)));
1729     if_update_with_internalized.If<HCompareNumericAndBranch>(
1730         not_internalized_bit, graph()->GetConstant0(), Token::NE);
1731     if_update_with_internalized.And();
1732     if_update_with_internalized.IfNot<HCompareObjectEqAndBranch>(
1733         candidate_key, graph()->GetConstantHole());
1734     if_update_with_internalized.AndIf<HStringCompareAndBranch>(candidate_key,
1735                                                                key, Token::EQ);
1736     if_update_with_internalized.Then();
1737     // Replace a key that is a non-internalized string by the equivalent
1738     // internalized string for faster further lookups.
1739     Add<HStoreKeyed>(elements, key_index, key, FAST_ELEMENTS);
1740     if_update_with_internalized.Else();
1741
1742     if_update_with_internalized.JoinContinuation(&found_key_match_continuation);
1743     if_match.JoinContinuation(&found_key_match_continuation);
1744
1745     IfBuilder found_key_match(this, &found_key_match_continuation);
1746     found_key_match.Then();
1747     // Key at current probe matches. Relevant bits in the |details| field must
1748     // be zero, otherwise the dictionary element requires special handling.
1749     HValue* details_index =
1750         AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 2));
1751     details_index->ClearFlag(HValue::kCanOverflow);
1752     HValue* details =
1753         Add<HLoadKeyed>(elements, details_index, nullptr, FAST_ELEMENTS);
1754     int details_mask = PropertyDetails::TypeField::kMask;
1755     details = AddUncasted<HBitwise>(Token::BIT_AND, details,
1756                                     Add<HConstant>(details_mask));
1757     IfBuilder details_compare(this);
1758     details_compare.If<HCompareNumericAndBranch>(
1759         details, graph()->GetConstant0(), Token::EQ);
1760     details_compare.Then();
1761     HValue* result_index =
1762         AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 1));
1763     result_index->ClearFlag(HValue::kCanOverflow);
1764     Push(Add<HLoadKeyed>(elements, result_index, nullptr, FAST_ELEMENTS));
1765     details_compare.Else();
1766     Add<HPushArguments>(receiver, key);
1767     Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
1768                            Runtime::FunctionForId(Runtime::kKeyedGetProperty),
1769                            2));
1770     details_compare.End();
1771
1772     found_key_match.Else();
1773     found_key_match.JoinContinuation(&return_or_loop_continuation);
1774   }
1775   if_undefined.JoinContinuation(&return_or_loop_continuation);
1776
1777   IfBuilder return_or_loop(this, &return_or_loop_continuation);
1778   return_or_loop.Then();
1779   probe_loop.Break();
1780
1781   return_or_loop.Else();
1782   entry = AddUncasted<HAdd>(entry, count);
1783   entry->ClearFlag(HValue::kCanOverflow);
1784   count = AddUncasted<HAdd>(count, graph()->GetConstant1());
1785   count->ClearFlag(HValue::kCanOverflow);
1786   Push(entry);
1787   Push(count);
1788
1789   probe_loop.EndBody();
1790
1791   return_or_loop.End();
1792
1793   return Pop();
1794 }
1795
1796
1797 HValue* HGraphBuilder::BuildRegExpConstructResult(HValue* length,
1798                                                   HValue* index,
1799                                                   HValue* input) {
1800   NoObservableSideEffectsScope scope(this);
1801   HConstant* max_length = Add<HConstant>(JSObject::kInitialMaxFastElementArray);
1802   Add<HBoundsCheck>(length, max_length);
1803
1804   // Generate size calculation code here in order to make it dominate
1805   // the JSRegExpResult allocation.
1806   ElementsKind elements_kind = FAST_ELEMENTS;
1807   HValue* size = BuildCalculateElementsSize(elements_kind, length);
1808
1809   // Allocate the JSRegExpResult and the FixedArray in one step.
1810   HValue* result = Add<HAllocate>(
1811       Add<HConstant>(JSRegExpResult::kSize), HType::JSArray(),
1812       NOT_TENURED, JS_ARRAY_TYPE);
1813
1814   // Initialize the JSRegExpResult header.
1815   HValue* global_object = Add<HLoadNamedField>(
1816       context(), nullptr,
1817       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
1818   HValue* native_context = Add<HLoadNamedField>(
1819       global_object, nullptr, HObjectAccess::ForGlobalObjectNativeContext());
1820   Add<HStoreNamedField>(
1821       result, HObjectAccess::ForMap(),
1822       Add<HLoadNamedField>(
1823           native_context, nullptr,
1824           HObjectAccess::ForContextSlot(Context::REGEXP_RESULT_MAP_INDEX)));
1825   HConstant* empty_fixed_array =
1826       Add<HConstant>(isolate()->factory()->empty_fixed_array());
1827   Add<HStoreNamedField>(
1828       result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset),
1829       empty_fixed_array);
1830   Add<HStoreNamedField>(
1831       result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
1832       empty_fixed_array);
1833   Add<HStoreNamedField>(
1834       result, HObjectAccess::ForJSArrayOffset(JSArray::kLengthOffset), length);
1835
1836   // Initialize the additional fields.
1837   Add<HStoreNamedField>(
1838       result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kIndexOffset),
1839       index);
1840   Add<HStoreNamedField>(
1841       result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kInputOffset),
1842       input);
1843
1844   // Allocate and initialize the elements header.
1845   HAllocate* elements = BuildAllocateElements(elements_kind, size);
1846   BuildInitializeElementsHeader(elements, elements_kind, length);
1847
1848   if (!elements->has_size_upper_bound()) {
1849     HConstant* size_in_bytes_upper_bound = EstablishElementsAllocationSize(
1850         elements_kind, max_length->Integer32Value());
1851     elements->set_size_upper_bound(size_in_bytes_upper_bound);
1852   }
1853
1854   Add<HStoreNamedField>(
1855       result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
1856       elements);
1857
1858   // Initialize the elements contents with undefined.
1859   BuildFillElementsWithValue(
1860       elements, elements_kind, graph()->GetConstant0(), length,
1861       graph()->GetConstantUndefined());
1862
1863   return result;
1864 }
1865
1866
1867 HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) {
1868   NoObservableSideEffectsScope scope(this);
1869
1870   // Convert constant numbers at compile time.
1871   if (object->IsConstant() && HConstant::cast(object)->HasNumberValue()) {
1872     Handle<Object> number = HConstant::cast(object)->handle(isolate());
1873     Handle<String> result = isolate()->factory()->NumberToString(number);
1874     return Add<HConstant>(result);
1875   }
1876
1877   // Create a joinable continuation.
1878   HIfContinuation found(graph()->CreateBasicBlock(),
1879                         graph()->CreateBasicBlock());
1880
1881   // Load the number string cache.
1882   HValue* number_string_cache =
1883       Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex);
1884
1885   // Make the hash mask from the length of the number string cache. It
1886   // contains two elements (number and string) for each cache entry.
1887   HValue* mask = AddLoadFixedArrayLength(number_string_cache);
1888   mask->set_type(HType::Smi());
1889   mask = AddUncasted<HSar>(mask, graph()->GetConstant1());
1890   mask = AddUncasted<HSub>(mask, graph()->GetConstant1());
1891
1892   // Check whether object is a smi.
1893   IfBuilder if_objectissmi(this);
1894   if_objectissmi.If<HIsSmiAndBranch>(object);
1895   if_objectissmi.Then();
1896   {
1897     // Compute hash for smi similar to smi_get_hash().
1898     HValue* hash = AddUncasted<HBitwise>(Token::BIT_AND, object, mask);
1899
1900     // Load the key.
1901     HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
1902     HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, nullptr,
1903                                   FAST_ELEMENTS, ALLOW_RETURN_HOLE);
1904
1905     // Check if object == key.
1906     IfBuilder if_objectiskey(this);
1907     if_objectiskey.If<HCompareObjectEqAndBranch>(object, key);
1908     if_objectiskey.Then();
1909     {
1910       // Make the key_index available.
1911       Push(key_index);
1912     }
1913     if_objectiskey.JoinContinuation(&found);
1914   }
1915   if_objectissmi.Else();
1916   {
1917     if (type->Is(Type::SignedSmall())) {
1918       if_objectissmi.Deopt(Deoptimizer::kExpectedSmi);
1919     } else {
1920       // Check if the object is a heap number.
1921       IfBuilder if_objectisnumber(this);
1922       HValue* objectisnumber = if_objectisnumber.If<HCompareMap>(
1923           object, isolate()->factory()->heap_number_map());
1924       if_objectisnumber.Then();
1925       {
1926         // Compute hash for heap number similar to double_get_hash().
1927         HValue* low = Add<HLoadNamedField>(
1928             object, objectisnumber,
1929             HObjectAccess::ForHeapNumberValueLowestBits());
1930         HValue* high = Add<HLoadNamedField>(
1931             object, objectisnumber,
1932             HObjectAccess::ForHeapNumberValueHighestBits());
1933         HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, low, high);
1934         hash = AddUncasted<HBitwise>(Token::BIT_AND, hash, mask);
1935
1936         // Load the key.
1937         HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
1938         HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, nullptr,
1939                                       FAST_ELEMENTS, ALLOW_RETURN_HOLE);
1940
1941         // Check if the key is a heap number and compare it with the object.
1942         IfBuilder if_keyisnotsmi(this);
1943         HValue* keyisnotsmi = if_keyisnotsmi.IfNot<HIsSmiAndBranch>(key);
1944         if_keyisnotsmi.Then();
1945         {
1946           IfBuilder if_keyisheapnumber(this);
1947           if_keyisheapnumber.If<HCompareMap>(
1948               key, isolate()->factory()->heap_number_map());
1949           if_keyisheapnumber.Then();
1950           {
1951             // Check if values of key and object match.
1952             IfBuilder if_keyeqobject(this);
1953             if_keyeqobject.If<HCompareNumericAndBranch>(
1954                 Add<HLoadNamedField>(key, keyisnotsmi,
1955                                      HObjectAccess::ForHeapNumberValue()),
1956                 Add<HLoadNamedField>(object, objectisnumber,
1957                                      HObjectAccess::ForHeapNumberValue()),
1958                 Token::EQ);
1959             if_keyeqobject.Then();
1960             {
1961               // Make the key_index available.
1962               Push(key_index);
1963             }
1964             if_keyeqobject.JoinContinuation(&found);
1965           }
1966           if_keyisheapnumber.JoinContinuation(&found);
1967         }
1968         if_keyisnotsmi.JoinContinuation(&found);
1969       }
1970       if_objectisnumber.Else();
1971       {
1972         if (type->Is(Type::Number())) {
1973           if_objectisnumber.Deopt(Deoptimizer::kExpectedHeapNumber);
1974         }
1975       }
1976       if_objectisnumber.JoinContinuation(&found);
1977     }
1978   }
1979   if_objectissmi.JoinContinuation(&found);
1980
1981   // Check for cache hit.
1982   IfBuilder if_found(this, &found);
1983   if_found.Then();
1984   {
1985     // Count number to string operation in native code.
1986     AddIncrementCounter(isolate()->counters()->number_to_string_native());
1987
1988     // Load the value in case of cache hit.
1989     HValue* key_index = Pop();
1990     HValue* value_index = AddUncasted<HAdd>(key_index, graph()->GetConstant1());
1991     Push(Add<HLoadKeyed>(number_string_cache, value_index, nullptr,
1992                          FAST_ELEMENTS, ALLOW_RETURN_HOLE));
1993   }
1994   if_found.Else();
1995   {
1996     // Cache miss, fallback to runtime.
1997     Add<HPushArguments>(object);
1998     Push(Add<HCallRuntime>(
1999             isolate()->factory()->empty_string(),
2000             Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
2001             1));
2002   }
2003   if_found.End();
2004
2005   return Pop();
2006 }
2007
2008
2009 HAllocate* HGraphBuilder::BuildAllocate(
2010     HValue* object_size,
2011     HType type,
2012     InstanceType instance_type,
2013     HAllocationMode allocation_mode) {
2014   // Compute the effective allocation size.
2015   HValue* size = object_size;
2016   if (allocation_mode.CreateAllocationMementos()) {
2017     size = AddUncasted<HAdd>(size, Add<HConstant>(AllocationMemento::kSize));
2018     size->ClearFlag(HValue::kCanOverflow);
2019   }
2020
2021   // Perform the actual allocation.
2022   HAllocate* object = Add<HAllocate>(
2023       size, type, allocation_mode.GetPretenureMode(),
2024       instance_type, allocation_mode.feedback_site());
2025
2026   // Setup the allocation memento.
2027   if (allocation_mode.CreateAllocationMementos()) {
2028     BuildCreateAllocationMemento(
2029         object, object_size, allocation_mode.current_site());
2030   }
2031
2032   return object;
2033 }
2034
2035
2036 HValue* HGraphBuilder::BuildAddStringLengths(HValue* left_length,
2037                                              HValue* right_length) {
2038   // Compute the combined string length and check against max string length.
2039   HValue* length = AddUncasted<HAdd>(left_length, right_length);
2040   // Check that length <= kMaxLength <=> length < MaxLength + 1.
2041   HValue* max_length = Add<HConstant>(String::kMaxLength + 1);
2042   Add<HBoundsCheck>(length, max_length);
2043   return length;
2044 }
2045
2046
2047 HValue* HGraphBuilder::BuildCreateConsString(
2048     HValue* length,
2049     HValue* left,
2050     HValue* right,
2051     HAllocationMode allocation_mode) {
2052   // Determine the string instance types.
2053   HInstruction* left_instance_type = AddLoadStringInstanceType(left);
2054   HInstruction* right_instance_type = AddLoadStringInstanceType(right);
2055
2056   // Allocate the cons string object. HAllocate does not care whether we
2057   // pass CONS_STRING_TYPE or CONS_ONE_BYTE_STRING_TYPE here, so we just use
2058   // CONS_STRING_TYPE here. Below we decide whether the cons string is
2059   // one-byte or two-byte and set the appropriate map.
2060   DCHECK(HAllocate::CompatibleInstanceTypes(CONS_STRING_TYPE,
2061                                             CONS_ONE_BYTE_STRING_TYPE));
2062   HAllocate* result = BuildAllocate(Add<HConstant>(ConsString::kSize),
2063                                     HType::String(), CONS_STRING_TYPE,
2064                                     allocation_mode);
2065
2066   // Compute intersection and difference of instance types.
2067   HValue* anded_instance_types = AddUncasted<HBitwise>(
2068       Token::BIT_AND, left_instance_type, right_instance_type);
2069   HValue* xored_instance_types = AddUncasted<HBitwise>(
2070       Token::BIT_XOR, left_instance_type, right_instance_type);
2071
2072   // We create a one-byte cons string if
2073   // 1. both strings are one-byte, or
2074   // 2. at least one of the strings is two-byte, but happens to contain only
2075   //    one-byte characters.
2076   // To do this, we check
2077   // 1. if both strings are one-byte, or if the one-byte data hint is set in
2078   //    both strings, or
2079   // 2. if one of the strings has the one-byte data hint set and the other
2080   //    string is one-byte.
2081   IfBuilder if_onebyte(this);
2082   STATIC_ASSERT(kOneByteStringTag != 0);
2083   STATIC_ASSERT(kOneByteDataHintMask != 0);
2084   if_onebyte.If<HCompareNumericAndBranch>(
2085       AddUncasted<HBitwise>(
2086           Token::BIT_AND, anded_instance_types,
2087           Add<HConstant>(static_cast<int32_t>(
2088                   kStringEncodingMask | kOneByteDataHintMask))),
2089       graph()->GetConstant0(), Token::NE);
2090   if_onebyte.Or();
2091   STATIC_ASSERT(kOneByteStringTag != 0 &&
2092                 kOneByteDataHintTag != 0 &&
2093                 kOneByteDataHintTag != kOneByteStringTag);
2094   if_onebyte.If<HCompareNumericAndBranch>(
2095       AddUncasted<HBitwise>(
2096           Token::BIT_AND, xored_instance_types,
2097           Add<HConstant>(static_cast<int32_t>(
2098                   kOneByteStringTag | kOneByteDataHintTag))),
2099       Add<HConstant>(static_cast<int32_t>(
2100               kOneByteStringTag | kOneByteDataHintTag)), Token::EQ);
2101   if_onebyte.Then();
2102   {
2103     // We can safely skip the write barrier for storing the map here.
2104     Add<HStoreNamedField>(
2105         result, HObjectAccess::ForMap(),
2106         Add<HConstant>(isolate()->factory()->cons_one_byte_string_map()));
2107   }
2108   if_onebyte.Else();
2109   {
2110     // We can safely skip the write barrier for storing the map here.
2111     Add<HStoreNamedField>(
2112         result, HObjectAccess::ForMap(),
2113         Add<HConstant>(isolate()->factory()->cons_string_map()));
2114   }
2115   if_onebyte.End();
2116
2117   // Initialize the cons string fields.
2118   Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
2119                         Add<HConstant>(String::kEmptyHashField));
2120   Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
2121   Add<HStoreNamedField>(result, HObjectAccess::ForConsStringFirst(), left);
2122   Add<HStoreNamedField>(result, HObjectAccess::ForConsStringSecond(), right);
2123
2124   // Count the native string addition.
2125   AddIncrementCounter(isolate()->counters()->string_add_native());
2126
2127   return result;
2128 }
2129
2130
2131 void HGraphBuilder::BuildCopySeqStringChars(HValue* src,
2132                                             HValue* src_offset,
2133                                             String::Encoding src_encoding,
2134                                             HValue* dst,
2135                                             HValue* dst_offset,
2136                                             String::Encoding dst_encoding,
2137                                             HValue* length) {
2138   DCHECK(dst_encoding != String::ONE_BYTE_ENCODING ||
2139          src_encoding == String::ONE_BYTE_ENCODING);
2140   LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
2141   HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT);
2142   {
2143     HValue* src_index = AddUncasted<HAdd>(src_offset, index);
2144     HValue* value =
2145         AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index);
2146     HValue* dst_index = AddUncasted<HAdd>(dst_offset, index);
2147     Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value);
2148   }
2149   loop.EndBody();
2150 }
2151
2152
2153 HValue* HGraphBuilder::BuildObjectSizeAlignment(
2154     HValue* unaligned_size, int header_size) {
2155   DCHECK((header_size & kObjectAlignmentMask) == 0);
2156   HValue* size = AddUncasted<HAdd>(
2157       unaligned_size, Add<HConstant>(static_cast<int32_t>(
2158           header_size + kObjectAlignmentMask)));
2159   size->ClearFlag(HValue::kCanOverflow);
2160   return AddUncasted<HBitwise>(
2161       Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>(
2162           ~kObjectAlignmentMask)));
2163 }
2164
2165
2166 HValue* HGraphBuilder::BuildUncheckedStringAdd(
2167     HValue* left,
2168     HValue* right,
2169     HAllocationMode allocation_mode) {
2170   // Determine the string lengths.
2171   HValue* left_length = AddLoadStringLength(left);
2172   HValue* right_length = AddLoadStringLength(right);
2173
2174   // Compute the combined string length.
2175   HValue* length = BuildAddStringLengths(left_length, right_length);
2176
2177   // Do some manual constant folding here.
2178   if (left_length->IsConstant()) {
2179     HConstant* c_left_length = HConstant::cast(left_length);
2180     DCHECK_NE(0, c_left_length->Integer32Value());
2181     if (c_left_length->Integer32Value() + 1 >= ConsString::kMinLength) {
2182       // The right string contains at least one character.
2183       return BuildCreateConsString(length, left, right, allocation_mode);
2184     }
2185   } else if (right_length->IsConstant()) {
2186     HConstant* c_right_length = HConstant::cast(right_length);
2187     DCHECK_NE(0, c_right_length->Integer32Value());
2188     if (c_right_length->Integer32Value() + 1 >= ConsString::kMinLength) {
2189       // The left string contains at least one character.
2190       return BuildCreateConsString(length, left, right, allocation_mode);
2191     }
2192   }
2193
2194   // Check if we should create a cons string.
2195   IfBuilder if_createcons(this);
2196   if_createcons.If<HCompareNumericAndBranch>(
2197       length, Add<HConstant>(ConsString::kMinLength), Token::GTE);
2198   if_createcons.Then();
2199   {
2200     // Create a cons string.
2201     Push(BuildCreateConsString(length, left, right, allocation_mode));
2202   }
2203   if_createcons.Else();
2204   {
2205     // Determine the string instance types.
2206     HValue* left_instance_type = AddLoadStringInstanceType(left);
2207     HValue* right_instance_type = AddLoadStringInstanceType(right);
2208
2209     // Compute union and difference of instance types.
2210     HValue* ored_instance_types = AddUncasted<HBitwise>(
2211         Token::BIT_OR, left_instance_type, right_instance_type);
2212     HValue* xored_instance_types = AddUncasted<HBitwise>(
2213         Token::BIT_XOR, left_instance_type, right_instance_type);
2214
2215     // Check if both strings have the same encoding and both are
2216     // sequential.
2217     IfBuilder if_sameencodingandsequential(this);
2218     if_sameencodingandsequential.If<HCompareNumericAndBranch>(
2219         AddUncasted<HBitwise>(
2220             Token::BIT_AND, xored_instance_types,
2221             Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
2222         graph()->GetConstant0(), Token::EQ);
2223     if_sameencodingandsequential.And();
2224     STATIC_ASSERT(kSeqStringTag == 0);
2225     if_sameencodingandsequential.If<HCompareNumericAndBranch>(
2226         AddUncasted<HBitwise>(
2227             Token::BIT_AND, ored_instance_types,
2228             Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))),
2229         graph()->GetConstant0(), Token::EQ);
2230     if_sameencodingandsequential.Then();
2231     {
2232       HConstant* string_map =
2233           Add<HConstant>(isolate()->factory()->string_map());
2234       HConstant* one_byte_string_map =
2235           Add<HConstant>(isolate()->factory()->one_byte_string_map());
2236
2237       // Determine map and size depending on whether result is one-byte string.
2238       IfBuilder if_onebyte(this);
2239       STATIC_ASSERT(kOneByteStringTag != 0);
2240       if_onebyte.If<HCompareNumericAndBranch>(
2241           AddUncasted<HBitwise>(
2242               Token::BIT_AND, ored_instance_types,
2243               Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
2244           graph()->GetConstant0(), Token::NE);
2245       if_onebyte.Then();
2246       {
2247         // Allocate sequential one-byte string object.
2248         Push(length);
2249         Push(one_byte_string_map);
2250       }
2251       if_onebyte.Else();
2252       {
2253         // Allocate sequential two-byte string object.
2254         HValue* size = AddUncasted<HShl>(length, graph()->GetConstant1());
2255         size->ClearFlag(HValue::kCanOverflow);
2256         size->SetFlag(HValue::kUint32);
2257         Push(size);
2258         Push(string_map);
2259       }
2260       if_onebyte.End();
2261       HValue* map = Pop();
2262
2263       // Calculate the number of bytes needed for the characters in the
2264       // string while observing object alignment.
2265       STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0);
2266       HValue* size = BuildObjectSizeAlignment(Pop(), SeqString::kHeaderSize);
2267
2268       // Allocate the string object. HAllocate does not care whether we pass
2269       // STRING_TYPE or ONE_BYTE_STRING_TYPE here, so we just use STRING_TYPE.
2270       HAllocate* result = BuildAllocate(
2271           size, HType::String(), STRING_TYPE, allocation_mode);
2272       Add<HStoreNamedField>(result, HObjectAccess::ForMap(), map);
2273
2274       // Initialize the string fields.
2275       Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
2276                             Add<HConstant>(String::kEmptyHashField));
2277       Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
2278
2279       // Copy characters to the result string.
2280       IfBuilder if_twobyte(this);
2281       if_twobyte.If<HCompareObjectEqAndBranch>(map, string_map);
2282       if_twobyte.Then();
2283       {
2284         // Copy characters from the left string.
2285         BuildCopySeqStringChars(
2286             left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
2287             result, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
2288             left_length);
2289
2290         // Copy characters from the right string.
2291         BuildCopySeqStringChars(
2292             right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
2293             result, left_length, String::TWO_BYTE_ENCODING,
2294             right_length);
2295       }
2296       if_twobyte.Else();
2297       {
2298         // Copy characters from the left string.
2299         BuildCopySeqStringChars(
2300             left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
2301             result, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
2302             left_length);
2303
2304         // Copy characters from the right string.
2305         BuildCopySeqStringChars(
2306             right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
2307             result, left_length, String::ONE_BYTE_ENCODING,
2308             right_length);
2309       }
2310       if_twobyte.End();
2311
2312       // Count the native string addition.
2313       AddIncrementCounter(isolate()->counters()->string_add_native());
2314
2315       // Return the sequential string.
2316       Push(result);
2317     }
2318     if_sameencodingandsequential.Else();
2319     {
2320       // Fallback to the runtime to add the two strings.
2321       Add<HPushArguments>(left, right);
2322       Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
2323                              Runtime::FunctionForId(Runtime::kStringAddRT), 2));
2324     }
2325     if_sameencodingandsequential.End();
2326   }
2327   if_createcons.End();
2328
2329   return Pop();
2330 }
2331
2332
2333 HValue* HGraphBuilder::BuildStringAdd(
2334     HValue* left,
2335     HValue* right,
2336     HAllocationMode allocation_mode) {
2337   NoObservableSideEffectsScope no_effects(this);
2338
2339   // Determine string lengths.
2340   HValue* left_length = AddLoadStringLength(left);
2341   HValue* right_length = AddLoadStringLength(right);
2342
2343   // Check if left string is empty.
2344   IfBuilder if_leftempty(this);
2345   if_leftempty.If<HCompareNumericAndBranch>(
2346       left_length, graph()->GetConstant0(), Token::EQ);
2347   if_leftempty.Then();
2348   {
2349     // Count the native string addition.
2350     AddIncrementCounter(isolate()->counters()->string_add_native());
2351
2352     // Just return the right string.
2353     Push(right);
2354   }
2355   if_leftempty.Else();
2356   {
2357     // Check if right string is empty.
2358     IfBuilder if_rightempty(this);
2359     if_rightempty.If<HCompareNumericAndBranch>(
2360         right_length, graph()->GetConstant0(), Token::EQ);
2361     if_rightempty.Then();
2362     {
2363       // Count the native string addition.
2364       AddIncrementCounter(isolate()->counters()->string_add_native());
2365
2366       // Just return the left string.
2367       Push(left);
2368     }
2369     if_rightempty.Else();
2370     {
2371       // Add the two non-empty strings.
2372       Push(BuildUncheckedStringAdd(left, right, allocation_mode));
2373     }
2374     if_rightempty.End();
2375   }
2376   if_leftempty.End();
2377
2378   return Pop();
2379 }
2380
2381
2382 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
2383     HValue* checked_object,
2384     HValue* key,
2385     HValue* val,
2386     bool is_js_array,
2387     ElementsKind elements_kind,
2388     PropertyAccessType access_type,
2389     LoadKeyedHoleMode load_mode,
2390     KeyedAccessStoreMode store_mode) {
2391   DCHECK(top_info()->IsStub() || checked_object->IsCompareMap() ||
2392          checked_object->IsCheckMaps());
2393   DCHECK((!IsExternalArrayElementsKind(elements_kind) &&
2394               !IsFixedTypedArrayElementsKind(elements_kind)) ||
2395          !is_js_array);
2396   // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
2397   // on a HElementsTransition instruction. The flag can also be removed if the
2398   // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
2399   // ElementsKind transitions. Finally, the dependency can be removed for stores
2400   // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
2401   // generated store code.
2402   if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
2403       (elements_kind == FAST_ELEMENTS && access_type == STORE)) {
2404     checked_object->ClearDependsOnFlag(kElementsKind);
2405   }
2406
2407   bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
2408   bool fast_elements = IsFastObjectElementsKind(elements_kind);
2409   HValue* elements = AddLoadElements(checked_object);
2410   if (access_type == STORE && (fast_elements || fast_smi_only_elements) &&
2411       store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
2412     HCheckMaps* check_cow_map = Add<HCheckMaps>(
2413         elements, isolate()->factory()->fixed_array_map());
2414     check_cow_map->ClearDependsOnFlag(kElementsKind);
2415   }
2416   HInstruction* length = NULL;
2417   if (is_js_array) {
2418     length = Add<HLoadNamedField>(
2419         checked_object->ActualValue(), checked_object,
2420         HObjectAccess::ForArrayLength(elements_kind));
2421   } else {
2422     length = AddLoadFixedArrayLength(elements);
2423   }
2424   length->set_type(HType::Smi());
2425   HValue* checked_key = NULL;
2426   if (IsExternalArrayElementsKind(elements_kind) ||
2427       IsFixedTypedArrayElementsKind(elements_kind)) {
2428     HValue* backing_store;
2429     if (IsExternalArrayElementsKind(elements_kind)) {
2430       backing_store = Add<HLoadNamedField>(
2431           elements, nullptr, HObjectAccess::ForExternalArrayExternalPointer());
2432     } else {
2433       backing_store = elements;
2434     }
2435     if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
2436       NoObservableSideEffectsScope no_effects(this);
2437       IfBuilder length_checker(this);
2438       length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
2439       length_checker.Then();
2440       IfBuilder negative_checker(this);
2441       HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
2442           key, graph()->GetConstant0(), Token::GTE);
2443       negative_checker.Then();
2444       HInstruction* result = AddElementAccess(
2445           backing_store, key, val, bounds_check, elements_kind, access_type);
2446       negative_checker.ElseDeopt(Deoptimizer::kNegativeKeyEncountered);
2447       negative_checker.End();
2448       length_checker.End();
2449       return result;
2450     } else {
2451       DCHECK(store_mode == STANDARD_STORE);
2452       checked_key = Add<HBoundsCheck>(key, length);
2453       return AddElementAccess(
2454           backing_store, checked_key, val,
2455           checked_object, elements_kind, access_type);
2456     }
2457   }
2458   DCHECK(fast_smi_only_elements ||
2459          fast_elements ||
2460          IsFastDoubleElementsKind(elements_kind));
2461
2462   // In case val is stored into a fast smi array, assure that the value is a smi
2463   // before manipulating the backing store. Otherwise the actual store may
2464   // deopt, leaving the backing store in an invalid state.
2465   if (access_type == STORE && IsFastSmiElementsKind(elements_kind) &&
2466       !val->type().IsSmi()) {
2467     val = AddUncasted<HForceRepresentation>(val, Representation::Smi());
2468   }
2469
2470   if (IsGrowStoreMode(store_mode)) {
2471     NoObservableSideEffectsScope no_effects(this);
2472     Representation representation = HStoreKeyed::RequiredValueRepresentation(
2473         elements_kind, STORE_TO_INITIALIZED_ENTRY);
2474     val = AddUncasted<HForceRepresentation>(val, representation);
2475     elements = BuildCheckForCapacityGrow(checked_object, elements,
2476                                          elements_kind, length, key,
2477                                          is_js_array, access_type);
2478     checked_key = key;
2479   } else {
2480     checked_key = Add<HBoundsCheck>(key, length);
2481
2482     if (access_type == STORE && (fast_elements || fast_smi_only_elements)) {
2483       if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
2484         NoObservableSideEffectsScope no_effects(this);
2485         elements = BuildCopyElementsOnWrite(checked_object, elements,
2486                                             elements_kind, length);
2487       } else {
2488         HCheckMaps* check_cow_map = Add<HCheckMaps>(
2489             elements, isolate()->factory()->fixed_array_map());
2490         check_cow_map->ClearDependsOnFlag(kElementsKind);
2491       }
2492     }
2493   }
2494   return AddElementAccess(elements, checked_key, val, checked_object,
2495                           elements_kind, access_type, load_mode);
2496 }
2497
2498
2499 HValue* HGraphBuilder::BuildAllocateArrayFromLength(
2500     JSArrayBuilder* array_builder,
2501     HValue* length_argument) {
2502   if (length_argument->IsConstant() &&
2503       HConstant::cast(length_argument)->HasSmiValue()) {
2504     int array_length = HConstant::cast(length_argument)->Integer32Value();
2505     if (array_length == 0) {
2506       return array_builder->AllocateEmptyArray();
2507     } else {
2508       return array_builder->AllocateArray(length_argument,
2509                                           array_length,
2510                                           length_argument);
2511     }
2512   }
2513
2514   HValue* constant_zero = graph()->GetConstant0();
2515   HConstant* max_alloc_length =
2516       Add<HConstant>(JSObject::kInitialMaxFastElementArray);
2517   HInstruction* checked_length = Add<HBoundsCheck>(length_argument,
2518                                                    max_alloc_length);
2519   IfBuilder if_builder(this);
2520   if_builder.If<HCompareNumericAndBranch>(checked_length, constant_zero,
2521                                           Token::EQ);
2522   if_builder.Then();
2523   const int initial_capacity = JSArray::kPreallocatedArrayElements;
2524   HConstant* initial_capacity_node = Add<HConstant>(initial_capacity);
2525   Push(initial_capacity_node);  // capacity
2526   Push(constant_zero);          // length
2527   if_builder.Else();
2528   if (!(top_info()->IsStub()) &&
2529       IsFastPackedElementsKind(array_builder->kind())) {
2530     // We'll come back later with better (holey) feedback.
2531     if_builder.Deopt(
2532         Deoptimizer::kHoleyArrayDespitePackedElements_kindFeedback);
2533   } else {
2534     Push(checked_length);         // capacity
2535     Push(checked_length);         // length
2536   }
2537   if_builder.End();
2538
2539   // Figure out total size
2540   HValue* length = Pop();
2541   HValue* capacity = Pop();
2542   return array_builder->AllocateArray(capacity, max_alloc_length, length);
2543 }
2544
2545
2546 HValue* HGraphBuilder::BuildCalculateElementsSize(ElementsKind kind,
2547                                                   HValue* capacity) {
2548   int elements_size = IsFastDoubleElementsKind(kind)
2549       ? kDoubleSize
2550       : kPointerSize;
2551
2552   HConstant* elements_size_value = Add<HConstant>(elements_size);
2553   HInstruction* mul =
2554       HMul::NewImul(isolate(), zone(), context(), capacity->ActualValue(),
2555                     elements_size_value);
2556   AddInstruction(mul);
2557   mul->ClearFlag(HValue::kCanOverflow);
2558
2559   STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize);
2560
2561   HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize);
2562   HValue* total_size = AddUncasted<HAdd>(mul, header_size);
2563   total_size->ClearFlag(HValue::kCanOverflow);
2564   return total_size;
2565 }
2566
2567
2568 HAllocate* HGraphBuilder::AllocateJSArrayObject(AllocationSiteMode mode) {
2569   int base_size = JSArray::kSize;
2570   if (mode == TRACK_ALLOCATION_SITE) {
2571     base_size += AllocationMemento::kSize;
2572   }
2573   HConstant* size_in_bytes = Add<HConstant>(base_size);
2574   return Add<HAllocate>(
2575       size_in_bytes, HType::JSArray(), NOT_TENURED, JS_OBJECT_TYPE);
2576 }
2577
2578
2579 HConstant* HGraphBuilder::EstablishElementsAllocationSize(
2580     ElementsKind kind,
2581     int capacity) {
2582   int base_size = IsFastDoubleElementsKind(kind)
2583       ? FixedDoubleArray::SizeFor(capacity)
2584       : FixedArray::SizeFor(capacity);
2585
2586   return Add<HConstant>(base_size);
2587 }
2588
2589
2590 HAllocate* HGraphBuilder::BuildAllocateElements(ElementsKind kind,
2591                                                 HValue* size_in_bytes) {
2592   InstanceType instance_type = IsFastDoubleElementsKind(kind)
2593       ? FIXED_DOUBLE_ARRAY_TYPE
2594       : FIXED_ARRAY_TYPE;
2595
2596   return Add<HAllocate>(size_in_bytes, HType::HeapObject(), NOT_TENURED,
2597                         instance_type);
2598 }
2599
2600
2601 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements,
2602                                                   ElementsKind kind,
2603                                                   HValue* capacity) {
2604   Factory* factory = isolate()->factory();
2605   Handle<Map> map = IsFastDoubleElementsKind(kind)
2606       ? factory->fixed_double_array_map()
2607       : factory->fixed_array_map();
2608
2609   Add<HStoreNamedField>(elements, HObjectAccess::ForMap(), Add<HConstant>(map));
2610   Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(),
2611                         capacity);
2612 }
2613
2614
2615 HValue* HGraphBuilder::BuildAllocateAndInitializeArray(ElementsKind kind,
2616                                                        HValue* capacity) {
2617   // The HForceRepresentation is to prevent possible deopt on int-smi
2618   // conversion after allocation but before the new object fields are set.
2619   capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi());
2620   HValue* size_in_bytes = BuildCalculateElementsSize(kind, capacity);
2621   HValue* new_array = BuildAllocateElements(kind, size_in_bytes);
2622   BuildInitializeElementsHeader(new_array, kind, capacity);
2623   return new_array;
2624 }
2625
2626
2627 void HGraphBuilder::BuildJSArrayHeader(HValue* array,
2628                                        HValue* array_map,
2629                                        HValue* elements,
2630                                        AllocationSiteMode mode,
2631                                        ElementsKind elements_kind,
2632                                        HValue* allocation_site_payload,
2633                                        HValue* length_field) {
2634   Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map);
2635
2636   HConstant* empty_fixed_array =
2637     Add<HConstant>(isolate()->factory()->empty_fixed_array());
2638
2639   Add<HStoreNamedField>(
2640       array, HObjectAccess::ForPropertiesPointer(), empty_fixed_array);
2641
2642   Add<HStoreNamedField>(
2643       array, HObjectAccess::ForElementsPointer(),
2644       elements != NULL ? elements : empty_fixed_array);
2645
2646   Add<HStoreNamedField>(
2647       array, HObjectAccess::ForArrayLength(elements_kind), length_field);
2648
2649   if (mode == TRACK_ALLOCATION_SITE) {
2650     BuildCreateAllocationMemento(
2651         array, Add<HConstant>(JSArray::kSize), allocation_site_payload);
2652   }
2653 }
2654
2655
2656 HInstruction* HGraphBuilder::AddElementAccess(
2657     HValue* elements,
2658     HValue* checked_key,
2659     HValue* val,
2660     HValue* dependency,
2661     ElementsKind elements_kind,
2662     PropertyAccessType access_type,
2663     LoadKeyedHoleMode load_mode) {
2664   if (access_type == STORE) {
2665     DCHECK(val != NULL);
2666     if (elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS ||
2667         elements_kind == UINT8_CLAMPED_ELEMENTS) {
2668       val = Add<HClampToUint8>(val);
2669     }
2670     return Add<HStoreKeyed>(elements, checked_key, val, elements_kind,
2671                             STORE_TO_INITIALIZED_ENTRY);
2672   }
2673
2674   DCHECK(access_type == LOAD);
2675   DCHECK(val == NULL);
2676   HLoadKeyed* load = Add<HLoadKeyed>(
2677       elements, checked_key, dependency, elements_kind, load_mode);
2678   if (elements_kind == EXTERNAL_UINT32_ELEMENTS ||
2679       elements_kind == UINT32_ELEMENTS) {
2680     graph()->RecordUint32Instruction(load);
2681   }
2682   return load;
2683 }
2684
2685
2686 HLoadNamedField* HGraphBuilder::AddLoadMap(HValue* object,
2687                                            HValue* dependency) {
2688   return Add<HLoadNamedField>(object, dependency, HObjectAccess::ForMap());
2689 }
2690
2691
2692 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object,
2693                                                 HValue* dependency) {
2694   return Add<HLoadNamedField>(
2695       object, dependency, HObjectAccess::ForElementsPointer());
2696 }
2697
2698
2699 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(
2700     HValue* array,
2701     HValue* dependency) {
2702   return Add<HLoadNamedField>(
2703       array, dependency, HObjectAccess::ForFixedArrayLength());
2704 }
2705
2706
2707 HLoadNamedField* HGraphBuilder::AddLoadArrayLength(HValue* array,
2708                                                    ElementsKind kind,
2709                                                    HValue* dependency) {
2710   return Add<HLoadNamedField>(
2711       array, dependency, HObjectAccess::ForArrayLength(kind));
2712 }
2713
2714
2715 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) {
2716   HValue* half_old_capacity = AddUncasted<HShr>(old_capacity,
2717                                                 graph_->GetConstant1());
2718
2719   HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity);
2720   new_capacity->ClearFlag(HValue::kCanOverflow);
2721
2722   HValue* min_growth = Add<HConstant>(16);
2723
2724   new_capacity = AddUncasted<HAdd>(new_capacity, min_growth);
2725   new_capacity->ClearFlag(HValue::kCanOverflow);
2726
2727   return new_capacity;
2728 }
2729
2730
2731 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
2732                                                  HValue* elements,
2733                                                  ElementsKind kind,
2734                                                  ElementsKind new_kind,
2735                                                  HValue* length,
2736                                                  HValue* new_capacity) {
2737   Add<HBoundsCheck>(new_capacity, Add<HConstant>(
2738           (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >>
2739           ElementsKindToShiftSize(new_kind)));
2740
2741   HValue* new_elements =
2742       BuildAllocateAndInitializeArray(new_kind, new_capacity);
2743
2744   BuildCopyElements(elements, kind, new_elements,
2745                     new_kind, length, new_capacity);
2746
2747   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
2748                         new_elements);
2749
2750   return new_elements;
2751 }
2752
2753
2754 void HGraphBuilder::BuildFillElementsWithValue(HValue* elements,
2755                                                ElementsKind elements_kind,
2756                                                HValue* from,
2757                                                HValue* to,
2758                                                HValue* value) {
2759   if (to == NULL) {
2760     to = AddLoadFixedArrayLength(elements);
2761   }
2762
2763   // Special loop unfolding case
2764   STATIC_ASSERT(JSArray::kPreallocatedArrayElements <=
2765                 kElementLoopUnrollThreshold);
2766   int initial_capacity = -1;
2767   if (from->IsInteger32Constant() && to->IsInteger32Constant()) {
2768     int constant_from = from->GetInteger32Constant();
2769     int constant_to = to->GetInteger32Constant();
2770
2771     if (constant_from == 0 && constant_to <= kElementLoopUnrollThreshold) {
2772       initial_capacity = constant_to;
2773     }
2774   }
2775
2776   if (initial_capacity >= 0) {
2777     for (int i = 0; i < initial_capacity; i++) {
2778       HInstruction* key = Add<HConstant>(i);
2779       Add<HStoreKeyed>(elements, key, value, elements_kind);
2780     }
2781   } else {
2782     // Carefully loop backwards so that the "from" remains live through the loop
2783     // rather than the to. This often corresponds to keeping length live rather
2784     // then capacity, which helps register allocation, since length is used more
2785     // other than capacity after filling with holes.
2786     LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
2787
2788     HValue* key = builder.BeginBody(to, from, Token::GT);
2789
2790     HValue* adjusted_key = AddUncasted<HSub>(key, graph()->GetConstant1());
2791     adjusted_key->ClearFlag(HValue::kCanOverflow);
2792
2793     Add<HStoreKeyed>(elements, adjusted_key, value, elements_kind);
2794
2795     builder.EndBody();
2796   }
2797 }
2798
2799
2800 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements,
2801                                               ElementsKind elements_kind,
2802                                               HValue* from,
2803                                               HValue* to) {
2804   // Fast elements kinds need to be initialized in case statements below cause a
2805   // garbage collection.
2806
2807   HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
2808                      ? graph()->GetConstantHole()
2809                      : Add<HConstant>(HConstant::kHoleNaN);
2810
2811   // Since we're about to store a hole value, the store instruction below must
2812   // assume an elements kind that supports heap object values.
2813   if (IsFastSmiOrObjectElementsKind(elements_kind)) {
2814     elements_kind = FAST_HOLEY_ELEMENTS;
2815   }
2816
2817   BuildFillElementsWithValue(elements, elements_kind, from, to, hole);
2818 }
2819
2820
2821 void HGraphBuilder::BuildCopyProperties(HValue* from_properties,
2822                                         HValue* to_properties, HValue* length,
2823                                         HValue* capacity) {
2824   ElementsKind kind = FAST_ELEMENTS;
2825
2826   BuildFillElementsWithValue(to_properties, kind, length, capacity,
2827                              graph()->GetConstantUndefined());
2828
2829   LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
2830
2831   HValue* key = builder.BeginBody(length, graph()->GetConstant0(), Token::GT);
2832
2833   key = AddUncasted<HSub>(key, graph()->GetConstant1());
2834   key->ClearFlag(HValue::kCanOverflow);
2835
2836   HValue* element = Add<HLoadKeyed>(from_properties, key, nullptr, kind);
2837
2838   Add<HStoreKeyed>(to_properties, key, element, kind);
2839
2840   builder.EndBody();
2841 }
2842
2843
2844 void HGraphBuilder::BuildCopyElements(HValue* from_elements,
2845                                       ElementsKind from_elements_kind,
2846                                       HValue* to_elements,
2847                                       ElementsKind to_elements_kind,
2848                                       HValue* length,
2849                                       HValue* capacity) {
2850   int constant_capacity = -1;
2851   if (capacity != NULL &&
2852       capacity->IsConstant() &&
2853       HConstant::cast(capacity)->HasInteger32Value()) {
2854     int constant_candidate = HConstant::cast(capacity)->Integer32Value();
2855     if (constant_candidate <= kElementLoopUnrollThreshold) {
2856       constant_capacity = constant_candidate;
2857     }
2858   }
2859
2860   bool pre_fill_with_holes =
2861     IsFastDoubleElementsKind(from_elements_kind) &&
2862     IsFastObjectElementsKind(to_elements_kind);
2863   if (pre_fill_with_holes) {
2864     // If the copy might trigger a GC, make sure that the FixedArray is
2865     // pre-initialized with holes to make sure that it's always in a
2866     // consistent state.
2867     BuildFillElementsWithHole(to_elements, to_elements_kind,
2868                               graph()->GetConstant0(), NULL);
2869   }
2870
2871   if (constant_capacity != -1) {
2872     // Unroll the loop for small elements kinds.
2873     for (int i = 0; i < constant_capacity; i++) {
2874       HValue* key_constant = Add<HConstant>(i);
2875       HInstruction* value = Add<HLoadKeyed>(from_elements, key_constant,
2876                                             nullptr, from_elements_kind);
2877       Add<HStoreKeyed>(to_elements, key_constant, value, to_elements_kind);
2878     }
2879   } else {
2880     if (!pre_fill_with_holes &&
2881         (capacity == NULL || !length->Equals(capacity))) {
2882       BuildFillElementsWithHole(to_elements, to_elements_kind,
2883                                 length, NULL);
2884     }
2885
2886     LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
2887
2888     HValue* key = builder.BeginBody(length, graph()->GetConstant0(),
2889                                     Token::GT);
2890
2891     key = AddUncasted<HSub>(key, graph()->GetConstant1());
2892     key->ClearFlag(HValue::kCanOverflow);
2893
2894     HValue* element = Add<HLoadKeyed>(from_elements, key, nullptr,
2895                                       from_elements_kind, 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>(HConstant::kHoleNaN)
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>(
3007         elements, access,
3008         Add<HLoadNamedField>(boilerplate_elements, nullptr, 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(HValue* value, Type* type,
3022                                     HIfContinuation* continuation,
3023                                     MapEmbedding map_embedding) {
3024   IfBuilder if_nil(this);
3025   bool some_case_handled = false;
3026   bool some_case_missing = false;
3027
3028   if (type->Maybe(Type::Null())) {
3029     if (some_case_handled) if_nil.Or();
3030     if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull());
3031     some_case_handled = true;
3032   } else {
3033     some_case_missing = true;
3034   }
3035
3036   if (type->Maybe(Type::Undefined())) {
3037     if (some_case_handled) if_nil.Or();
3038     if_nil.If<HCompareObjectEqAndBranch>(value,
3039                                          graph()->GetConstantUndefined());
3040     some_case_handled = true;
3041   } else {
3042     some_case_missing = true;
3043   }
3044
3045   if (type->Maybe(Type::Undetectable())) {
3046     if (some_case_handled) if_nil.Or();
3047     if_nil.If<HIsUndetectableAndBranch>(value);
3048     some_case_handled = true;
3049   } else {
3050     some_case_missing = true;
3051   }
3052
3053   if (some_case_missing) {
3054     if_nil.Then();
3055     if_nil.Else();
3056     if (type->NumClasses() == 1) {
3057       BuildCheckHeapObject(value);
3058       // For ICs, the map checked below is a sentinel map that gets replaced by
3059       // the monomorphic map when the code is used as a template to generate a
3060       // new IC. For optimized functions, there is no sentinel map, the map
3061       // emitted below is the actual monomorphic map.
3062       if (map_embedding == kEmbedMapsViaWeakCells) {
3063         HValue* cell =
3064             Add<HConstant>(Map::WeakCellForMap(type->Classes().Current()));
3065         HValue* expected_map = Add<HLoadNamedField>(
3066             cell, nullptr, HObjectAccess::ForWeakCellValue());
3067         HValue* map =
3068             Add<HLoadNamedField>(value, nullptr, HObjectAccess::ForMap());
3069         IfBuilder map_check(this);
3070         map_check.IfNot<HCompareObjectEqAndBranch>(expected_map, map);
3071         map_check.ThenDeopt(Deoptimizer::kUnknownMap);
3072         map_check.End();
3073       } else {
3074         DCHECK(map_embedding == kEmbedMapsDirectly);
3075         Add<HCheckMaps>(value, type->Classes().Current());
3076       }
3077     } else {
3078       if_nil.Deopt(Deoptimizer::kTooManyUndetectableTypes);
3079     }
3080   }
3081
3082   if_nil.CaptureContinuation(continuation);
3083 }
3084
3085
3086 void HGraphBuilder::BuildCreateAllocationMemento(
3087     HValue* previous_object,
3088     HValue* previous_object_size,
3089     HValue* allocation_site) {
3090   DCHECK(allocation_site != NULL);
3091   HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>(
3092       previous_object, previous_object_size, HType::HeapObject());
3093   AddStoreMapConstant(
3094       allocation_memento, isolate()->factory()->allocation_memento_map());
3095   Add<HStoreNamedField>(
3096       allocation_memento,
3097       HObjectAccess::ForAllocationMementoSite(),
3098       allocation_site);
3099   if (FLAG_allocation_site_pretenuring) {
3100     HValue* memento_create_count =
3101         Add<HLoadNamedField>(allocation_site, nullptr,
3102                              HObjectAccess::ForAllocationSiteOffset(
3103                                  AllocationSite::kPretenureCreateCountOffset));
3104     memento_create_count = AddUncasted<HAdd>(
3105         memento_create_count, graph()->GetConstant1());
3106     // This smi value is reset to zero after every gc, overflow isn't a problem
3107     // since the counter is bounded by the new space size.
3108     memento_create_count->ClearFlag(HValue::kCanOverflow);
3109     Add<HStoreNamedField>(
3110         allocation_site, HObjectAccess::ForAllocationSiteOffset(
3111             AllocationSite::kPretenureCreateCountOffset), memento_create_count);
3112   }
3113 }
3114
3115
3116 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* closure) {
3117   // Get the global object, then the native context
3118   HInstruction* context = Add<HLoadNamedField>(
3119       closure, nullptr, HObjectAccess::ForFunctionContextPointer());
3120   HInstruction* global_object = Add<HLoadNamedField>(
3121       context, nullptr,
3122       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
3123   HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
3124       GlobalObject::kNativeContextOffset);
3125   return Add<HLoadNamedField>(global_object, nullptr, access);
3126 }
3127
3128
3129 HInstruction* HGraphBuilder::BuildGetScriptContext(int context_index) {
3130   HValue* native_context = BuildGetNativeContext();
3131   HValue* script_context_table = Add<HLoadNamedField>(
3132       native_context, nullptr,
3133       HObjectAccess::ForContextSlot(Context::SCRIPT_CONTEXT_TABLE_INDEX));
3134   return Add<HLoadNamedField>(script_context_table, nullptr,
3135                               HObjectAccess::ForScriptContext(context_index));
3136 }
3137
3138
3139 HInstruction* HGraphBuilder::BuildGetNativeContext() {
3140   // Get the global object, then the native context
3141   HValue* global_object = Add<HLoadNamedField>(
3142       context(), nullptr,
3143       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
3144   return Add<HLoadNamedField>(global_object, nullptr,
3145                               HObjectAccess::ForObservableJSObjectOffset(
3146                                   GlobalObject::kNativeContextOffset));
3147 }
3148
3149
3150 HInstruction* HGraphBuilder::BuildGetArrayFunction() {
3151   HInstruction* native_context = BuildGetNativeContext();
3152   HInstruction* index =
3153       Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX));
3154   return Add<HLoadKeyed>(native_context, index, nullptr, FAST_ELEMENTS);
3155 }
3156
3157
3158 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
3159     ElementsKind kind,
3160     HValue* allocation_site_payload,
3161     HValue* constructor_function,
3162     AllocationSiteOverrideMode override_mode) :
3163         builder_(builder),
3164         kind_(kind),
3165         allocation_site_payload_(allocation_site_payload),
3166         constructor_function_(constructor_function) {
3167   DCHECK(!allocation_site_payload->IsConstant() ||
3168          HConstant::cast(allocation_site_payload)->handle(
3169              builder_->isolate())->IsAllocationSite());
3170   mode_ = override_mode == DISABLE_ALLOCATION_SITES
3171       ? DONT_TRACK_ALLOCATION_SITE
3172       : AllocationSite::GetMode(kind);
3173 }
3174
3175
3176 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
3177                                               ElementsKind kind,
3178                                               HValue* constructor_function) :
3179     builder_(builder),
3180     kind_(kind),
3181     mode_(DONT_TRACK_ALLOCATION_SITE),
3182     allocation_site_payload_(NULL),
3183     constructor_function_(constructor_function) {
3184 }
3185
3186
3187 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
3188   if (!builder()->top_info()->IsStub()) {
3189     // A constant map is fine.
3190     Handle<Map> map(builder()->isolate()->get_initial_js_array_map(kind_),
3191                     builder()->isolate());
3192     return builder()->Add<HConstant>(map);
3193   }
3194
3195   if (constructor_function_ != NULL && kind_ == GetInitialFastElementsKind()) {
3196     // No need for a context lookup if the kind_ matches the initial
3197     // map, because we can just load the map in that case.
3198     HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
3199     return builder()->Add<HLoadNamedField>(constructor_function_, nullptr,
3200                                            access);
3201   }
3202
3203   // TODO(mvstanton): we should always have a constructor function if we
3204   // are creating a stub.
3205   HInstruction* native_context = constructor_function_ != NULL
3206       ? builder()->BuildGetNativeContext(constructor_function_)
3207       : builder()->BuildGetNativeContext();
3208
3209   HInstruction* index = builder()->Add<HConstant>(
3210       static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX));
3211
3212   HInstruction* map_array =
3213       builder()->Add<HLoadKeyed>(native_context, index, nullptr, FAST_ELEMENTS);
3214
3215   HInstruction* kind_index = builder()->Add<HConstant>(kind_);
3216
3217   return builder()->Add<HLoadKeyed>(map_array, kind_index, nullptr,
3218                                     FAST_ELEMENTS);
3219 }
3220
3221
3222 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
3223   // Find the map near the constructor function
3224   HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
3225   return builder()->Add<HLoadNamedField>(constructor_function_, nullptr,
3226                                          access);
3227 }
3228
3229
3230 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() {
3231   HConstant* capacity = builder()->Add<HConstant>(initial_capacity());
3232   return AllocateArray(capacity,
3233                        capacity,
3234                        builder()->graph()->GetConstant0());
3235 }
3236
3237
3238 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
3239     HValue* capacity,
3240     HConstant* capacity_upper_bound,
3241     HValue* length_field,
3242     FillMode fill_mode) {
3243   return AllocateArray(capacity,
3244                        capacity_upper_bound->GetInteger32Constant(),
3245                        length_field,
3246                        fill_mode);
3247 }
3248
3249
3250 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
3251     HValue* capacity,
3252     int capacity_upper_bound,
3253     HValue* length_field,
3254     FillMode fill_mode) {
3255   HConstant* elememts_size_upper_bound = capacity->IsInteger32Constant()
3256       ? HConstant::cast(capacity)
3257       : builder()->EstablishElementsAllocationSize(kind_, capacity_upper_bound);
3258
3259   HAllocate* array = AllocateArray(capacity, length_field, fill_mode);
3260   if (!elements_location_->has_size_upper_bound()) {
3261     elements_location_->set_size_upper_bound(elememts_size_upper_bound);
3262   }
3263   return array;
3264 }
3265
3266
3267 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
3268     HValue* capacity,
3269     HValue* length_field,
3270     FillMode fill_mode) {
3271   // These HForceRepresentations are because we store these as fields in the
3272   // objects we construct, and an int32-to-smi HChange could deopt. Accept
3273   // the deopt possibility now, before allocation occurs.
3274   capacity =
3275       builder()->AddUncasted<HForceRepresentation>(capacity,
3276                                                    Representation::Smi());
3277   length_field =
3278       builder()->AddUncasted<HForceRepresentation>(length_field,
3279                                                    Representation::Smi());
3280
3281   // Generate size calculation code here in order to make it dominate
3282   // the JSArray allocation.
3283   HValue* elements_size =
3284       builder()->BuildCalculateElementsSize(kind_, capacity);
3285
3286   // Allocate (dealing with failure appropriately)
3287   HAllocate* array_object = builder()->AllocateJSArrayObject(mode_);
3288
3289   // Fill in the fields: map, properties, length
3290   HValue* map;
3291   if (allocation_site_payload_ == NULL) {
3292     map = EmitInternalMapCode();
3293   } else {
3294     map = EmitMapCode();
3295   }
3296
3297   builder()->BuildJSArrayHeader(array_object,
3298                                 map,
3299                                 NULL,  // set elements to empty fixed array
3300                                 mode_,
3301                                 kind_,
3302                                 allocation_site_payload_,
3303                                 length_field);
3304
3305   // Allocate and initialize the elements
3306   elements_location_ = builder()->BuildAllocateElements(kind_, elements_size);
3307
3308   builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity);
3309
3310   // Set the elements
3311   builder()->Add<HStoreNamedField>(
3312       array_object, HObjectAccess::ForElementsPointer(), elements_location_);
3313
3314   if (fill_mode == FILL_WITH_HOLE) {
3315     builder()->BuildFillElementsWithHole(elements_location_, kind_,
3316                                          graph()->GetConstant0(), capacity);
3317   }
3318
3319   return array_object;
3320 }
3321
3322
3323 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin) {
3324   HValue* global_object = Add<HLoadNamedField>(
3325       context(), nullptr,
3326       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
3327   HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
3328       GlobalObject::kBuiltinsOffset);
3329   HValue* builtins = Add<HLoadNamedField>(global_object, nullptr, access);
3330   HObjectAccess function_access = HObjectAccess::ForObservableJSObjectOffset(
3331           JSBuiltinsObject::OffsetOfFunctionWithId(builtin));
3332   return Add<HLoadNamedField>(builtins, nullptr, function_access);
3333 }
3334
3335
3336 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
3337     : HGraphBuilder(info),
3338       function_state_(NULL),
3339       initial_function_state_(this, info, NORMAL_RETURN, 0),
3340       ast_context_(NULL),
3341       break_scope_(NULL),
3342       inlined_count_(0),
3343       globals_(10, info->zone()),
3344       osr_(new(info->zone()) HOsrBuilder(this)) {
3345   // This is not initialized in the initializer list because the
3346   // constructor for the initial state relies on function_state_ == NULL
3347   // to know it's the initial state.
3348   function_state_ = &initial_function_state_;
3349   InitializeAstVisitor(info->isolate(), info->zone());
3350   if (top_info()->is_tracking_positions()) {
3351     SetSourcePosition(info->shared_info()->start_position());
3352   }
3353 }
3354
3355
3356 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first,
3357                                                 HBasicBlock* second,
3358                                                 BailoutId join_id) {
3359   if (first == NULL) {
3360     return second;
3361   } else if (second == NULL) {
3362     return first;
3363   } else {
3364     HBasicBlock* join_block = graph()->CreateBasicBlock();
3365     Goto(first, join_block);
3366     Goto(second, join_block);
3367     join_block->SetJoinId(join_id);
3368     return join_block;
3369   }
3370 }
3371
3372
3373 HBasicBlock* HOptimizedGraphBuilder::JoinContinue(IterationStatement* statement,
3374                                                   HBasicBlock* exit_block,
3375                                                   HBasicBlock* continue_block) {
3376   if (continue_block != NULL) {
3377     if (exit_block != NULL) Goto(exit_block, continue_block);
3378     continue_block->SetJoinId(statement->ContinueId());
3379     return continue_block;
3380   }
3381   return exit_block;
3382 }
3383
3384
3385 HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement,
3386                                                 HBasicBlock* loop_entry,
3387                                                 HBasicBlock* body_exit,
3388                                                 HBasicBlock* loop_successor,
3389                                                 HBasicBlock* break_block) {
3390   if (body_exit != NULL) Goto(body_exit, loop_entry);
3391   loop_entry->PostProcessLoopHeader(statement);
3392   if (break_block != NULL) {
3393     if (loop_successor != NULL) Goto(loop_successor, break_block);
3394     break_block->SetJoinId(statement->ExitId());
3395     return break_block;
3396   }
3397   return loop_successor;
3398 }
3399
3400
3401 // Build a new loop header block and set it as the current block.
3402 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() {
3403   HBasicBlock* loop_entry = CreateLoopHeaderBlock();
3404   Goto(loop_entry);
3405   set_current_block(loop_entry);
3406   return loop_entry;
3407 }
3408
3409
3410 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry(
3411     IterationStatement* statement) {
3412   HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement)
3413       ? osr()->BuildOsrLoopEntry(statement)
3414       : BuildLoopEntry();
3415   return loop_entry;
3416 }
3417
3418
3419 void HBasicBlock::FinishExit(HControlInstruction* instruction,
3420                              SourcePosition position) {
3421   Finish(instruction, position);
3422   ClearEnvironment();
3423 }
3424
3425
3426 std::ostream& operator<<(std::ostream& os, const HBasicBlock& b) {
3427   return os << "B" << b.block_id();
3428 }
3429
3430
3431 HGraph::HGraph(CompilationInfo* info)
3432     : isolate_(info->isolate()),
3433       next_block_id_(0),
3434       entry_block_(NULL),
3435       blocks_(8, info->zone()),
3436       values_(16, info->zone()),
3437       phi_list_(NULL),
3438       uint32_instructions_(NULL),
3439       osr_(NULL),
3440       info_(info),
3441       zone_(info->zone()),
3442       is_recursive_(false),
3443       this_has_uses_(false),
3444       use_optimistic_licm_(false),
3445       depends_on_empty_array_proto_elements_(false),
3446       type_change_checksum_(0),
3447       maximum_environment_size_(0),
3448       no_side_effects_scope_count_(0),
3449       disallow_adding_new_values_(false) {
3450   if (info->IsStub()) {
3451     CallInterfaceDescriptor descriptor =
3452         info->code_stub()->GetCallInterfaceDescriptor();
3453     start_environment_ = new (zone_)
3454         HEnvironment(zone_, descriptor.GetEnvironmentParameterCount());
3455   } else {
3456     if (info->is_tracking_positions()) {
3457       info->TraceInlinedFunction(info->shared_info(), SourcePosition::Unknown(),
3458                                  InlinedFunctionInfo::kNoParentId);
3459     }
3460     start_environment_ =
3461         new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
3462   }
3463   start_environment_->set_ast_id(BailoutId::FunctionEntry());
3464   entry_block_ = CreateBasicBlock();
3465   entry_block_->SetInitialEnvironment(start_environment_);
3466 }
3467
3468
3469 HBasicBlock* HGraph::CreateBasicBlock() {
3470   HBasicBlock* result = new(zone()) HBasicBlock(this);
3471   blocks_.Add(result, zone());
3472   return result;
3473 }
3474
3475
3476 void HGraph::FinalizeUniqueness() {
3477   DisallowHeapAllocation no_gc;
3478   DCHECK(!OptimizingCompilerThread::IsOptimizerThread(isolate()));
3479   for (int i = 0; i < blocks()->length(); ++i) {
3480     for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
3481       it.Current()->FinalizeUniqueness();
3482     }
3483   }
3484 }
3485
3486
3487 int HGraph::SourcePositionToScriptPosition(SourcePosition pos) {
3488   return (FLAG_hydrogen_track_positions && !pos.IsUnknown())
3489              ? info()->start_position_for(pos.inlining_id()) + pos.position()
3490              : pos.raw();
3491 }
3492
3493
3494 // Block ordering was implemented with two mutually recursive methods,
3495 // HGraph::Postorder and HGraph::PostorderLoopBlocks.
3496 // The recursion could lead to stack overflow so the algorithm has been
3497 // implemented iteratively.
3498 // At a high level the algorithm looks like this:
3499 //
3500 // Postorder(block, loop_header) : {
3501 //   if (block has already been visited or is of another loop) return;
3502 //   mark block as visited;
3503 //   if (block is a loop header) {
3504 //     VisitLoopMembers(block, loop_header);
3505 //     VisitSuccessorsOfLoopHeader(block);
3506 //   } else {
3507 //     VisitSuccessors(block)
3508 //   }
3509 //   put block in result list;
3510 // }
3511 //
3512 // VisitLoopMembers(block, outer_loop_header) {
3513 //   foreach (block b in block loop members) {
3514 //     VisitSuccessorsOfLoopMember(b, outer_loop_header);
3515 //     if (b is loop header) VisitLoopMembers(b);
3516 //   }
3517 // }
3518 //
3519 // VisitSuccessorsOfLoopMember(block, outer_loop_header) {
3520 //   foreach (block b in block successors) Postorder(b, outer_loop_header)
3521 // }
3522 //
3523 // VisitSuccessorsOfLoopHeader(block) {
3524 //   foreach (block b in block successors) Postorder(b, block)
3525 // }
3526 //
3527 // VisitSuccessors(block, loop_header) {
3528 //   foreach (block b in block successors) Postorder(b, loop_header)
3529 // }
3530 //
3531 // The ordering is started calling Postorder(entry, NULL).
3532 //
3533 // Each instance of PostorderProcessor represents the "stack frame" of the
3534 // recursion, and particularly keeps the state of the loop (iteration) of the
3535 // "Visit..." function it represents.
3536 // To recycle memory we keep all the frames in a double linked list but
3537 // this means that we cannot use constructors to initialize the frames.
3538 //
3539 class PostorderProcessor : public ZoneObject {
3540  public:
3541   // Back link (towards the stack bottom).
3542   PostorderProcessor* parent() {return father_; }
3543   // Forward link (towards the stack top).
3544   PostorderProcessor* child() {return child_; }
3545   HBasicBlock* block() { return block_; }
3546   HLoopInformation* loop() { return loop_; }
3547   HBasicBlock* loop_header() { return loop_header_; }
3548
3549   static PostorderProcessor* CreateEntryProcessor(Zone* zone,
3550                                                   HBasicBlock* block) {
3551     PostorderProcessor* result = new(zone) PostorderProcessor(NULL);
3552     return result->SetupSuccessors(zone, block, NULL);
3553   }
3554
3555   PostorderProcessor* PerformStep(Zone* zone,
3556                                   ZoneList<HBasicBlock*>* order) {
3557     PostorderProcessor* next =
3558         PerformNonBacktrackingStep(zone, order);
3559     if (next != NULL) {
3560       return next;
3561     } else {
3562       return Backtrack(zone, order);
3563     }
3564   }
3565
3566  private:
3567   explicit PostorderProcessor(PostorderProcessor* father)
3568       : father_(father), child_(NULL), successor_iterator(NULL) { }
3569
3570   // Each enum value states the cycle whose state is kept by this instance.
3571   enum LoopKind {
3572     NONE,
3573     SUCCESSORS,
3574     SUCCESSORS_OF_LOOP_HEADER,
3575     LOOP_MEMBERS,
3576     SUCCESSORS_OF_LOOP_MEMBER
3577   };
3578
3579   // Each "Setup..." method is like a constructor for a cycle state.
3580   PostorderProcessor* SetupSuccessors(Zone* zone,
3581                                       HBasicBlock* block,
3582                                       HBasicBlock* loop_header) {
3583     if (block == NULL || block->IsOrdered() ||
3584         block->parent_loop_header() != loop_header) {
3585       kind_ = NONE;
3586       block_ = NULL;
3587       loop_ = NULL;
3588       loop_header_ = NULL;
3589       return this;
3590     } else {
3591       block_ = block;
3592       loop_ = NULL;
3593       block->MarkAsOrdered();
3594
3595       if (block->IsLoopHeader()) {
3596         kind_ = SUCCESSORS_OF_LOOP_HEADER;
3597         loop_header_ = block;
3598         InitializeSuccessors();
3599         PostorderProcessor* result = Push(zone);
3600         return result->SetupLoopMembers(zone, block, block->loop_information(),
3601                                         loop_header);
3602       } else {
3603         DCHECK(block->IsFinished());
3604         kind_ = SUCCESSORS;
3605         loop_header_ = loop_header;
3606         InitializeSuccessors();
3607         return this;
3608       }
3609     }
3610   }
3611
3612   PostorderProcessor* SetupLoopMembers(Zone* zone,
3613                                        HBasicBlock* block,
3614                                        HLoopInformation* loop,
3615                                        HBasicBlock* loop_header) {
3616     kind_ = LOOP_MEMBERS;
3617     block_ = block;
3618     loop_ = loop;
3619     loop_header_ = loop_header;
3620     InitializeLoopMembers();
3621     return this;
3622   }
3623
3624   PostorderProcessor* SetupSuccessorsOfLoopMember(
3625       HBasicBlock* block,
3626       HLoopInformation* loop,
3627       HBasicBlock* loop_header) {
3628     kind_ = SUCCESSORS_OF_LOOP_MEMBER;
3629     block_ = block;
3630     loop_ = loop;
3631     loop_header_ = loop_header;
3632     InitializeSuccessors();
3633     return this;
3634   }
3635
3636   // This method "allocates" a new stack frame.
3637   PostorderProcessor* Push(Zone* zone) {
3638     if (child_ == NULL) {
3639       child_ = new(zone) PostorderProcessor(this);
3640     }
3641     return child_;
3642   }
3643
3644   void ClosePostorder(ZoneList<HBasicBlock*>* order, Zone* zone) {
3645     DCHECK(block_->end()->FirstSuccessor() == NULL ||
3646            order->Contains(block_->end()->FirstSuccessor()) ||
3647            block_->end()->FirstSuccessor()->IsLoopHeader());
3648     DCHECK(block_->end()->SecondSuccessor() == NULL ||
3649            order->Contains(block_->end()->SecondSuccessor()) ||
3650            block_->end()->SecondSuccessor()->IsLoopHeader());
3651     order->Add(block_, zone);
3652   }
3653
3654   // This method is the basic block to walk up the stack.
3655   PostorderProcessor* Pop(Zone* zone,
3656                           ZoneList<HBasicBlock*>* order) {
3657     switch (kind_) {
3658       case SUCCESSORS:
3659       case SUCCESSORS_OF_LOOP_HEADER:
3660         ClosePostorder(order, zone);
3661         return father_;
3662       case LOOP_MEMBERS:
3663         return father_;
3664       case SUCCESSORS_OF_LOOP_MEMBER:
3665         if (block()->IsLoopHeader() && block() != loop_->loop_header()) {
3666           // In this case we need to perform a LOOP_MEMBERS cycle so we
3667           // initialize it and return this instead of father.
3668           return SetupLoopMembers(zone, block(),
3669                                   block()->loop_information(), loop_header_);
3670         } else {
3671           return father_;
3672         }
3673       case NONE:
3674         return father_;
3675     }
3676     UNREACHABLE();
3677     return NULL;
3678   }
3679
3680   // Walks up the stack.
3681   PostorderProcessor* Backtrack(Zone* zone,
3682                                 ZoneList<HBasicBlock*>* order) {
3683     PostorderProcessor* parent = Pop(zone, order);
3684     while (parent != NULL) {
3685       PostorderProcessor* next =
3686           parent->PerformNonBacktrackingStep(zone, order);
3687       if (next != NULL) {
3688         return next;
3689       } else {
3690         parent = parent->Pop(zone, order);
3691       }
3692     }
3693     return NULL;
3694   }
3695
3696   PostorderProcessor* PerformNonBacktrackingStep(
3697       Zone* zone,
3698       ZoneList<HBasicBlock*>* order) {
3699     HBasicBlock* next_block;
3700     switch (kind_) {
3701       case SUCCESSORS:
3702         next_block = AdvanceSuccessors();
3703         if (next_block != NULL) {
3704           PostorderProcessor* result = Push(zone);
3705           return result->SetupSuccessors(zone, next_block, loop_header_);
3706         }
3707         break;
3708       case SUCCESSORS_OF_LOOP_HEADER:
3709         next_block = AdvanceSuccessors();
3710         if (next_block != NULL) {
3711           PostorderProcessor* result = Push(zone);
3712           return result->SetupSuccessors(zone, next_block, block());
3713         }
3714         break;
3715       case LOOP_MEMBERS:
3716         next_block = AdvanceLoopMembers();
3717         if (next_block != NULL) {
3718           PostorderProcessor* result = Push(zone);
3719           return result->SetupSuccessorsOfLoopMember(next_block,
3720                                                      loop_, loop_header_);
3721         }
3722         break;
3723       case SUCCESSORS_OF_LOOP_MEMBER:
3724         next_block = AdvanceSuccessors();
3725         if (next_block != NULL) {
3726           PostorderProcessor* result = Push(zone);
3727           return result->SetupSuccessors(zone, next_block, loop_header_);
3728         }
3729         break;
3730       case NONE:
3731         return NULL;
3732     }
3733     return NULL;
3734   }
3735
3736   // The following two methods implement a "foreach b in successors" cycle.
3737   void InitializeSuccessors() {
3738     loop_index = 0;
3739     loop_length = 0;
3740     successor_iterator = HSuccessorIterator(block_->end());
3741   }
3742
3743   HBasicBlock* AdvanceSuccessors() {
3744     if (!successor_iterator.Done()) {
3745       HBasicBlock* result = successor_iterator.Current();
3746       successor_iterator.Advance();
3747       return result;
3748     }
3749     return NULL;
3750   }
3751
3752   // The following two methods implement a "foreach b in loop members" cycle.
3753   void InitializeLoopMembers() {
3754     loop_index = 0;
3755     loop_length = loop_->blocks()->length();
3756   }
3757
3758   HBasicBlock* AdvanceLoopMembers() {
3759     if (loop_index < loop_length) {
3760       HBasicBlock* result = loop_->blocks()->at(loop_index);
3761       loop_index++;
3762       return result;
3763     } else {
3764       return NULL;
3765     }
3766   }
3767
3768   LoopKind kind_;
3769   PostorderProcessor* father_;
3770   PostorderProcessor* child_;
3771   HLoopInformation* loop_;
3772   HBasicBlock* block_;
3773   HBasicBlock* loop_header_;
3774   int loop_index;
3775   int loop_length;
3776   HSuccessorIterator successor_iterator;
3777 };
3778
3779
3780 void HGraph::OrderBlocks() {
3781   CompilationPhase phase("H_Block ordering", info());
3782
3783 #ifdef DEBUG
3784   // Initially the blocks must not be ordered.
3785   for (int i = 0; i < blocks_.length(); ++i) {
3786     DCHECK(!blocks_[i]->IsOrdered());
3787   }
3788 #endif
3789
3790   PostorderProcessor* postorder =
3791       PostorderProcessor::CreateEntryProcessor(zone(), blocks_[0]);
3792   blocks_.Rewind(0);
3793   while (postorder) {
3794     postorder = postorder->PerformStep(zone(), &blocks_);
3795   }
3796
3797 #ifdef DEBUG
3798   // Now all blocks must be marked as ordered.
3799   for (int i = 0; i < blocks_.length(); ++i) {
3800     DCHECK(blocks_[i]->IsOrdered());
3801   }
3802 #endif
3803
3804   // Reverse block list and assign block IDs.
3805   for (int i = 0, j = blocks_.length(); --j >= i; ++i) {
3806     HBasicBlock* bi = blocks_[i];
3807     HBasicBlock* bj = blocks_[j];
3808     bi->set_block_id(j);
3809     bj->set_block_id(i);
3810     blocks_[i] = bj;
3811     blocks_[j] = bi;
3812   }
3813 }
3814
3815
3816 void HGraph::AssignDominators() {
3817   HPhase phase("H_Assign dominators", this);
3818   for (int i = 0; i < blocks_.length(); ++i) {
3819     HBasicBlock* block = blocks_[i];
3820     if (block->IsLoopHeader()) {
3821       // Only the first predecessor of a loop header is from outside the loop.
3822       // All others are back edges, and thus cannot dominate the loop header.
3823       block->AssignCommonDominator(block->predecessors()->first());
3824       block->AssignLoopSuccessorDominators();
3825     } else {
3826       for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) {
3827         blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
3828       }
3829     }
3830   }
3831 }
3832
3833
3834 bool HGraph::CheckArgumentsPhiUses() {
3835   int block_count = blocks_.length();
3836   for (int i = 0; i < block_count; ++i) {
3837     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
3838       HPhi* phi = blocks_[i]->phis()->at(j);
3839       // We don't support phi uses of arguments for now.
3840       if (phi->CheckFlag(HValue::kIsArguments)) return false;
3841     }
3842   }
3843   return true;
3844 }
3845
3846
3847 bool HGraph::CheckConstPhiUses() {
3848   int block_count = blocks_.length();
3849   for (int i = 0; i < block_count; ++i) {
3850     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
3851       HPhi* phi = blocks_[i]->phis()->at(j);
3852       // Check for the hole value (from an uninitialized const).
3853       for (int k = 0; k < phi->OperandCount(); k++) {
3854         if (phi->OperandAt(k) == GetConstantHole()) return false;
3855       }
3856     }
3857   }
3858   return true;
3859 }
3860
3861
3862 void HGraph::CollectPhis() {
3863   int block_count = blocks_.length();
3864   phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone());
3865   for (int i = 0; i < block_count; ++i) {
3866     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
3867       HPhi* phi = blocks_[i]->phis()->at(j);
3868       phi_list_->Add(phi, zone());
3869     }
3870   }
3871 }
3872
3873
3874 // Implementation of utility class to encapsulate the translation state for
3875 // a (possibly inlined) function.
3876 FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
3877                              CompilationInfo* info, InliningKind inlining_kind,
3878                              int inlining_id)
3879     : owner_(owner),
3880       compilation_info_(info),
3881       call_context_(NULL),
3882       inlining_kind_(inlining_kind),
3883       function_return_(NULL),
3884       test_context_(NULL),
3885       entry_(NULL),
3886       arguments_object_(NULL),
3887       arguments_elements_(NULL),
3888       inlining_id_(inlining_id),
3889       outer_source_position_(SourcePosition::Unknown()),
3890       outer_(owner->function_state()) {
3891   if (outer_ != NULL) {
3892     // State for an inline function.
3893     if (owner->ast_context()->IsTest()) {
3894       HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
3895       HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
3896       if_true->MarkAsInlineReturnTarget(owner->current_block());
3897       if_false->MarkAsInlineReturnTarget(owner->current_block());
3898       TestContext* outer_test_context = TestContext::cast(owner->ast_context());
3899       Expression* cond = outer_test_context->condition();
3900       // The AstContext constructor pushed on the context stack.  This newed
3901       // instance is the reason that AstContext can't be BASE_EMBEDDED.
3902       test_context_ = new TestContext(owner, cond, if_true, if_false);
3903     } else {
3904       function_return_ = owner->graph()->CreateBasicBlock();
3905       function_return()->MarkAsInlineReturnTarget(owner->current_block());
3906     }
3907     // Set this after possibly allocating a new TestContext above.
3908     call_context_ = owner->ast_context();
3909   }
3910
3911   // Push on the state stack.
3912   owner->set_function_state(this);
3913
3914   if (compilation_info_->is_tracking_positions()) {
3915     outer_source_position_ = owner->source_position();
3916     owner->EnterInlinedSource(
3917       info->shared_info()->start_position(),
3918       inlining_id);
3919     owner->SetSourcePosition(info->shared_info()->start_position());
3920   }
3921 }
3922
3923
3924 FunctionState::~FunctionState() {
3925   delete test_context_;
3926   owner_->set_function_state(outer_);
3927
3928   if (compilation_info_->is_tracking_positions()) {
3929     owner_->set_source_position(outer_source_position_);
3930     owner_->EnterInlinedSource(
3931       outer_->compilation_info()->shared_info()->start_position(),
3932       outer_->inlining_id());
3933   }
3934 }
3935
3936
3937 // Implementation of utility classes to represent an expression's context in
3938 // the AST.
3939 AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind)
3940     : owner_(owner),
3941       kind_(kind),
3942       outer_(owner->ast_context()),
3943       for_typeof_(false) {
3944   owner->set_ast_context(this);  // Push.
3945 #ifdef DEBUG
3946   DCHECK(owner->environment()->frame_type() == JS_FUNCTION);
3947   original_length_ = owner->environment()->length();
3948 #endif
3949 }
3950
3951
3952 AstContext::~AstContext() {
3953   owner_->set_ast_context(outer_);  // Pop.
3954 }
3955
3956
3957 EffectContext::~EffectContext() {
3958   DCHECK(owner()->HasStackOverflow() ||
3959          owner()->current_block() == NULL ||
3960          (owner()->environment()->length() == original_length_ &&
3961           owner()->environment()->frame_type() == JS_FUNCTION));
3962 }
3963
3964
3965 ValueContext::~ValueContext() {
3966   DCHECK(owner()->HasStackOverflow() ||
3967          owner()->current_block() == NULL ||
3968          (owner()->environment()->length() == original_length_ + 1 &&
3969           owner()->environment()->frame_type() == JS_FUNCTION));
3970 }
3971
3972
3973 void EffectContext::ReturnValue(HValue* value) {
3974   // The value is simply ignored.
3975 }
3976
3977
3978 void ValueContext::ReturnValue(HValue* value) {
3979   // The value is tracked in the bailout environment, and communicated
3980   // through the environment as the result of the expression.
3981   if (value->CheckFlag(HValue::kIsArguments)) {
3982     if (flag_ == ARGUMENTS_FAKED) {
3983       value = owner()->graph()->GetConstantUndefined();
3984     } else if (!arguments_allowed()) {
3985       owner()->Bailout(kBadValueContextForArgumentsValue);
3986     }
3987   }
3988   owner()->Push(value);
3989 }
3990
3991
3992 void TestContext::ReturnValue(HValue* value) {
3993   BuildBranch(value);
3994 }
3995
3996
3997 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
3998   DCHECK(!instr->IsControlInstruction());
3999   owner()->AddInstruction(instr);
4000   if (instr->HasObservableSideEffects()) {
4001     owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
4002   }
4003 }
4004
4005
4006 void EffectContext::ReturnControl(HControlInstruction* instr,
4007                                   BailoutId ast_id) {
4008   DCHECK(!instr->HasObservableSideEffects());
4009   HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
4010   HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
4011   instr->SetSuccessorAt(0, empty_true);
4012   instr->SetSuccessorAt(1, empty_false);
4013   owner()->FinishCurrentBlock(instr);
4014   HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id);
4015   owner()->set_current_block(join);
4016 }
4017
4018
4019 void EffectContext::ReturnContinuation(HIfContinuation* continuation,
4020                                        BailoutId ast_id) {
4021   HBasicBlock* true_branch = NULL;
4022   HBasicBlock* false_branch = NULL;
4023   continuation->Continue(&true_branch, &false_branch);
4024   if (!continuation->IsTrueReachable()) {
4025     owner()->set_current_block(false_branch);
4026   } else if (!continuation->IsFalseReachable()) {
4027     owner()->set_current_block(true_branch);
4028   } else {
4029     HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id);
4030     owner()->set_current_block(join);
4031   }
4032 }
4033
4034
4035 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
4036   DCHECK(!instr->IsControlInstruction());
4037   if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
4038     return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
4039   }
4040   owner()->AddInstruction(instr);
4041   owner()->Push(instr);
4042   if (instr->HasObservableSideEffects()) {
4043     owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
4044   }
4045 }
4046
4047
4048 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
4049   DCHECK(!instr->HasObservableSideEffects());
4050   if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
4051     return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
4052   }
4053   HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
4054   HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
4055   instr->SetSuccessorAt(0, materialize_true);
4056   instr->SetSuccessorAt(1, materialize_false);
4057   owner()->FinishCurrentBlock(instr);
4058   owner()->set_current_block(materialize_true);
4059   owner()->Push(owner()->graph()->GetConstantTrue());
4060   owner()->set_current_block(materialize_false);
4061   owner()->Push(owner()->graph()->GetConstantFalse());
4062   HBasicBlock* join =
4063     owner()->CreateJoin(materialize_true, materialize_false, ast_id);
4064   owner()->set_current_block(join);
4065 }
4066
4067
4068 void ValueContext::ReturnContinuation(HIfContinuation* continuation,
4069                                       BailoutId ast_id) {
4070   HBasicBlock* materialize_true = NULL;
4071   HBasicBlock* materialize_false = NULL;
4072   continuation->Continue(&materialize_true, &materialize_false);
4073   if (continuation->IsTrueReachable()) {
4074     owner()->set_current_block(materialize_true);
4075     owner()->Push(owner()->graph()->GetConstantTrue());
4076     owner()->set_current_block(materialize_true);
4077   }
4078   if (continuation->IsFalseReachable()) {
4079     owner()->set_current_block(materialize_false);
4080     owner()->Push(owner()->graph()->GetConstantFalse());
4081     owner()->set_current_block(materialize_false);
4082   }
4083   if (continuation->TrueAndFalseReachable()) {
4084     HBasicBlock* join =
4085         owner()->CreateJoin(materialize_true, materialize_false, ast_id);
4086     owner()->set_current_block(join);
4087   }
4088 }
4089
4090
4091 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
4092   DCHECK(!instr->IsControlInstruction());
4093   HOptimizedGraphBuilder* builder = owner();
4094   builder->AddInstruction(instr);
4095   // We expect a simulate after every expression with side effects, though
4096   // this one isn't actually needed (and wouldn't work if it were targeted).
4097   if (instr->HasObservableSideEffects()) {
4098     builder->Push(instr);
4099     builder->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
4100     builder->Pop();
4101   }
4102   BuildBranch(instr);
4103 }
4104
4105
4106 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
4107   DCHECK(!instr->HasObservableSideEffects());
4108   HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
4109   HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
4110   instr->SetSuccessorAt(0, empty_true);
4111   instr->SetSuccessorAt(1, empty_false);
4112   owner()->FinishCurrentBlock(instr);
4113   owner()->Goto(empty_true, if_true(), owner()->function_state());
4114   owner()->Goto(empty_false, if_false(), owner()->function_state());
4115   owner()->set_current_block(NULL);
4116 }
4117
4118
4119 void TestContext::ReturnContinuation(HIfContinuation* continuation,
4120                                      BailoutId ast_id) {
4121   HBasicBlock* true_branch = NULL;
4122   HBasicBlock* false_branch = NULL;
4123   continuation->Continue(&true_branch, &false_branch);
4124   if (continuation->IsTrueReachable()) {
4125     owner()->Goto(true_branch, if_true(), owner()->function_state());
4126   }
4127   if (continuation->IsFalseReachable()) {
4128     owner()->Goto(false_branch, if_false(), owner()->function_state());
4129   }
4130   owner()->set_current_block(NULL);
4131 }
4132
4133
4134 void TestContext::BuildBranch(HValue* value) {
4135   // We expect the graph to be in edge-split form: there is no edge that
4136   // connects a branch node to a join node.  We conservatively ensure that
4137   // property by always adding an empty block on the outgoing edges of this
4138   // branch.
4139   HOptimizedGraphBuilder* builder = owner();
4140   if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
4141     builder->Bailout(kArgumentsObjectValueInATestContext);
4142   }
4143   ToBooleanStub::Types expected(condition()->to_boolean_types());
4144   ReturnControl(owner()->New<HBranch>(value, expected), BailoutId::None());
4145 }
4146
4147
4148 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts.
4149 #define CHECK_BAILOUT(call)                     \
4150   do {                                          \
4151     call;                                       \
4152     if (HasStackOverflow()) return;             \
4153   } while (false)
4154
4155
4156 #define CHECK_ALIVE(call)                                       \
4157   do {                                                          \
4158     call;                                                       \
4159     if (HasStackOverflow() || current_block() == NULL) return;  \
4160   } while (false)
4161
4162
4163 #define CHECK_ALIVE_OR_RETURN(call, value)                            \
4164   do {                                                                \
4165     call;                                                             \
4166     if (HasStackOverflow() || current_block() == NULL) return value;  \
4167   } while (false)
4168
4169
4170 void HOptimizedGraphBuilder::Bailout(BailoutReason reason) {
4171   current_info()->AbortOptimization(reason);
4172   SetStackOverflow();
4173 }
4174
4175
4176 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) {
4177   EffectContext for_effect(this);
4178   Visit(expr);
4179 }
4180
4181
4182 void HOptimizedGraphBuilder::VisitForValue(Expression* expr,
4183                                            ArgumentsAllowedFlag flag) {
4184   ValueContext for_value(this, flag);
4185   Visit(expr);
4186 }
4187
4188
4189 void HOptimizedGraphBuilder::VisitForTypeOf(Expression* expr) {
4190   ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
4191   for_value.set_for_typeof(true);
4192   Visit(expr);
4193 }
4194
4195
4196 void HOptimizedGraphBuilder::VisitForControl(Expression* expr,
4197                                              HBasicBlock* true_block,
4198                                              HBasicBlock* false_block) {
4199   TestContext for_test(this, expr, true_block, false_block);
4200   Visit(expr);
4201 }
4202
4203
4204 void HOptimizedGraphBuilder::VisitExpressions(
4205     ZoneList<Expression*>* exprs) {
4206   for (int i = 0; i < exprs->length(); ++i) {
4207     CHECK_ALIVE(VisitForValue(exprs->at(i)));
4208   }
4209 }
4210
4211
4212 void HOptimizedGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs,
4213                                               ArgumentsAllowedFlag flag) {
4214   for (int i = 0; i < exprs->length(); ++i) {
4215     CHECK_ALIVE(VisitForValue(exprs->at(i), flag));
4216   }
4217 }
4218
4219
4220 bool HOptimizedGraphBuilder::BuildGraph() {
4221   if (IsSubclassConstructor(current_info()->function()->kind())) {
4222     Bailout(kSuperReference);
4223     return false;
4224   }
4225
4226   Scope* scope = current_info()->scope();
4227   SetUpScope(scope);
4228
4229   // Add an edge to the body entry.  This is warty: the graph's start
4230   // environment will be used by the Lithium translation as the initial
4231   // environment on graph entry, but it has now been mutated by the
4232   // Hydrogen translation of the instructions in the start block.  This
4233   // environment uses values which have not been defined yet.  These
4234   // Hydrogen instructions will then be replayed by the Lithium
4235   // translation, so they cannot have an environment effect.  The edge to
4236   // the body's entry block (along with some special logic for the start
4237   // block in HInstruction::InsertAfter) seals the start block from
4238   // getting unwanted instructions inserted.
4239   //
4240   // TODO(kmillikin): Fix this.  Stop mutating the initial environment.
4241   // Make the Hydrogen instructions in the initial block into Hydrogen
4242   // values (but not instructions), present in the initial environment and
4243   // not replayed by the Lithium translation.
4244   HEnvironment* initial_env = environment()->CopyWithoutHistory();
4245   HBasicBlock* body_entry = CreateBasicBlock(initial_env);
4246   Goto(body_entry);
4247   body_entry->SetJoinId(BailoutId::FunctionEntry());
4248   set_current_block(body_entry);
4249
4250   // Handle implicit declaration of the function name in named function
4251   // expressions before other declarations.
4252   if (scope->is_function_scope() && scope->function() != NULL) {
4253     VisitVariableDeclaration(scope->function());
4254   }
4255   VisitDeclarations(scope->declarations());
4256   Add<HSimulate>(BailoutId::Declarations());
4257
4258   Add<HStackCheck>(HStackCheck::kFunctionEntry);
4259
4260   VisitStatements(current_info()->function()->body());
4261   if (HasStackOverflow()) return false;
4262
4263   if (current_block() != NULL) {
4264     Add<HReturn>(graph()->GetConstantUndefined());
4265     set_current_block(NULL);
4266   }
4267
4268   // If the checksum of the number of type info changes is the same as the
4269   // last time this function was compiled, then this recompile is likely not
4270   // due to missing/inadequate type feedback, but rather too aggressive
4271   // optimization. Disable optimistic LICM in that case.
4272   Handle<Code> unoptimized_code(current_info()->shared_info()->code());
4273   DCHECK(unoptimized_code->kind() == Code::FUNCTION);
4274   Handle<TypeFeedbackInfo> type_info(
4275       TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
4276   int checksum = type_info->own_type_change_checksum();
4277   int composite_checksum = graph()->update_type_change_checksum(checksum);
4278   graph()->set_use_optimistic_licm(
4279       !type_info->matches_inlined_type_change_checksum(composite_checksum));
4280   type_info->set_inlined_type_change_checksum(composite_checksum);
4281
4282   // Perform any necessary OSR-specific cleanups or changes to the graph.
4283   osr()->FinishGraph();
4284
4285   return true;
4286 }
4287
4288
4289 bool HGraph::Optimize(BailoutReason* bailout_reason) {
4290   OrderBlocks();
4291   AssignDominators();
4292
4293   // We need to create a HConstant "zero" now so that GVN will fold every
4294   // zero-valued constant in the graph together.
4295   // The constant is needed to make idef-based bounds check work: the pass
4296   // evaluates relations with "zero" and that zero cannot be created after GVN.
4297   GetConstant0();
4298
4299 #ifdef DEBUG
4300   // Do a full verify after building the graph and computing dominators.
4301   Verify(true);
4302 #endif
4303
4304   if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) {
4305     Run<HEnvironmentLivenessAnalysisPhase>();
4306   }
4307
4308   if (!CheckConstPhiUses()) {
4309     *bailout_reason = kUnsupportedPhiUseOfConstVariable;
4310     return false;
4311   }
4312   Run<HRedundantPhiEliminationPhase>();
4313   if (!CheckArgumentsPhiUses()) {
4314     *bailout_reason = kUnsupportedPhiUseOfArguments;
4315     return false;
4316   }
4317
4318   // Find and mark unreachable code to simplify optimizations, especially gvn,
4319   // where unreachable code could unnecessarily defeat LICM.
4320   Run<HMarkUnreachableBlocksPhase>();
4321
4322   if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
4323   if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
4324
4325   if (FLAG_load_elimination) Run<HLoadEliminationPhase>();
4326
4327   CollectPhis();
4328
4329   if (has_osr()) osr()->FinishOsrValues();
4330
4331   Run<HInferRepresentationPhase>();
4332
4333   // Remove HSimulate instructions that have turned out not to be needed
4334   // after all by folding them into the following HSimulate.
4335   // This must happen after inferring representations.
4336   Run<HMergeRemovableSimulatesPhase>();
4337
4338   Run<HMarkDeoptimizeOnUndefinedPhase>();
4339   Run<HRepresentationChangesPhase>();
4340
4341   Run<HInferTypesPhase>();
4342
4343   // Must be performed before canonicalization to ensure that Canonicalize
4344   // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with
4345   // zero.
4346   Run<HUint32AnalysisPhase>();
4347
4348   if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>();
4349
4350   if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>();
4351
4352   if (FLAG_check_elimination) Run<HCheckEliminationPhase>();
4353
4354   if (FLAG_store_elimination) Run<HStoreEliminationPhase>();
4355
4356   Run<HRangeAnalysisPhase>();
4357
4358   Run<HComputeChangeUndefinedToNaN>();
4359
4360   // Eliminate redundant stack checks on backwards branches.
4361   Run<HStackCheckEliminationPhase>();
4362
4363   if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>();
4364   if (FLAG_array_bounds_checks_hoisting) Run<HBoundsCheckHoistingPhase>();
4365   if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
4366   if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
4367
4368   RestoreActualValues();
4369
4370   // Find unreachable code a second time, GVN and other optimizations may have
4371   // made blocks unreachable that were previously reachable.
4372   Run<HMarkUnreachableBlocksPhase>();
4373
4374   return true;
4375 }
4376
4377
4378 void HGraph::RestoreActualValues() {
4379   HPhase phase("H_Restore actual values", this);
4380
4381   for (int block_index = 0; block_index < blocks()->length(); block_index++) {
4382     HBasicBlock* block = blocks()->at(block_index);
4383
4384 #ifdef DEBUG
4385     for (int i = 0; i < block->phis()->length(); i++) {
4386       HPhi* phi = block->phis()->at(i);
4387       DCHECK(phi->ActualValue() == phi);
4388     }
4389 #endif
4390
4391     for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
4392       HInstruction* instruction = it.Current();
4393       if (instruction->ActualValue() == instruction) continue;
4394       if (instruction->CheckFlag(HValue::kIsDead)) {
4395         // The instruction was marked as deleted but left in the graph
4396         // as a control flow dependency point for subsequent
4397         // instructions.
4398         instruction->DeleteAndReplaceWith(instruction->ActualValue());
4399       } else {
4400         DCHECK(instruction->IsInformativeDefinition());
4401         if (instruction->IsPurelyInformativeDefinition()) {
4402           instruction->DeleteAndReplaceWith(instruction->RedefinedOperand());
4403         } else {
4404           instruction->ReplaceAllUsesWith(instruction->ActualValue());
4405         }
4406       }
4407     }
4408   }
4409 }
4410
4411
4412 void HOptimizedGraphBuilder::PushArgumentsFromEnvironment(int count) {
4413   ZoneList<HValue*> arguments(count, zone());
4414   for (int i = 0; i < count; ++i) {
4415     arguments.Add(Pop(), zone());
4416   }
4417
4418   HPushArguments* push_args = New<HPushArguments>();
4419   while (!arguments.is_empty()) {
4420     push_args->AddInput(arguments.RemoveLast());
4421   }
4422   AddInstruction(push_args);
4423 }
4424
4425
4426 template <class Instruction>
4427 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
4428   PushArgumentsFromEnvironment(call->argument_count());
4429   return call;
4430 }
4431
4432
4433 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) {
4434   // First special is HContext.
4435   HInstruction* context = Add<HContext>();
4436   environment()->BindContext(context);
4437
4438   // Create an arguments object containing the initial parameters.  Set the
4439   // initial values of parameters including "this" having parameter index 0.
4440   DCHECK_EQ(scope->num_parameters() + 1, environment()->parameter_count());
4441   HArgumentsObject* arguments_object =
4442       New<HArgumentsObject>(environment()->parameter_count());
4443   for (int i = 0; i < environment()->parameter_count(); ++i) {
4444     HInstruction* parameter = Add<HParameter>(i);
4445     arguments_object->AddArgument(parameter, zone());
4446     environment()->Bind(i, parameter);
4447   }
4448   AddInstruction(arguments_object);
4449   graph()->SetArgumentsObject(arguments_object);
4450
4451   HConstant* undefined_constant = graph()->GetConstantUndefined();
4452   // Initialize specials and locals to undefined.
4453   for (int i = environment()->parameter_count() + 1;
4454        i < environment()->length();
4455        ++i) {
4456     environment()->Bind(i, undefined_constant);
4457   }
4458
4459   // Handle the arguments and arguments shadow variables specially (they do
4460   // not have declarations).
4461   if (scope->arguments() != NULL) {
4462     environment()->Bind(scope->arguments(),
4463                         graph()->GetArgumentsObject());
4464   }
4465
4466   int rest_index;
4467   Variable* rest = scope->rest_parameter(&rest_index);
4468   if (rest) {
4469     return Bailout(kRestParameter);
4470   }
4471 }
4472
4473
4474 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
4475   for (int i = 0; i < statements->length(); i++) {
4476     Statement* stmt = statements->at(i);
4477     CHECK_ALIVE(Visit(stmt));
4478     if (stmt->IsJump()) break;
4479   }
4480 }
4481
4482
4483 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
4484   DCHECK(!HasStackOverflow());
4485   DCHECK(current_block() != NULL);
4486   DCHECK(current_block()->HasPredecessor());
4487
4488   Scope* outer_scope = scope();
4489   Scope* scope = stmt->scope();
4490   BreakAndContinueInfo break_info(stmt, outer_scope);
4491
4492   { BreakAndContinueScope push(&break_info, this);
4493     if (scope != NULL) {
4494       // Load the function object.
4495       Scope* declaration_scope = scope->DeclarationScope();
4496       HInstruction* function;
4497       HValue* outer_context = environment()->context();
4498       if (declaration_scope->is_script_scope() ||
4499           declaration_scope->is_eval_scope()) {
4500         function = new(zone()) HLoadContextSlot(
4501             outer_context, Context::CLOSURE_INDEX, HLoadContextSlot::kNoCheck);
4502       } else {
4503         function = New<HThisFunction>();
4504       }
4505       AddInstruction(function);
4506       // Allocate a block context and store it to the stack frame.
4507       HInstruction* inner_context = Add<HAllocateBlockContext>(
4508           outer_context, function, scope->GetScopeInfo(isolate()));
4509       HInstruction* instr = Add<HStoreFrameContext>(inner_context);
4510       set_scope(scope);
4511       environment()->BindContext(inner_context);
4512       if (instr->HasObservableSideEffects()) {
4513         AddSimulate(stmt->EntryId(), REMOVABLE_SIMULATE);
4514       }
4515       VisitDeclarations(scope->declarations());
4516       AddSimulate(stmt->DeclsId(), REMOVABLE_SIMULATE);
4517     }
4518     CHECK_BAILOUT(VisitStatements(stmt->statements()));
4519   }
4520   set_scope(outer_scope);
4521   if (scope != NULL && current_block() != NULL) {
4522     HValue* inner_context = environment()->context();
4523     HValue* outer_context = Add<HLoadNamedField>(
4524         inner_context, nullptr,
4525         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
4526
4527     HInstruction* instr = Add<HStoreFrameContext>(outer_context);
4528     environment()->BindContext(outer_context);
4529     if (instr->HasObservableSideEffects()) {
4530       AddSimulate(stmt->ExitId(), REMOVABLE_SIMULATE);
4531     }
4532   }
4533   HBasicBlock* break_block = break_info.break_block();
4534   if (break_block != NULL) {
4535     if (current_block() != NULL) Goto(break_block);
4536     break_block->SetJoinId(stmt->ExitId());
4537     set_current_block(break_block);
4538   }
4539 }
4540
4541
4542 void HOptimizedGraphBuilder::VisitExpressionStatement(
4543     ExpressionStatement* stmt) {
4544   DCHECK(!HasStackOverflow());
4545   DCHECK(current_block() != NULL);
4546   DCHECK(current_block()->HasPredecessor());
4547   VisitForEffect(stmt->expression());
4548 }
4549
4550
4551 void HOptimizedGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
4552   DCHECK(!HasStackOverflow());
4553   DCHECK(current_block() != NULL);
4554   DCHECK(current_block()->HasPredecessor());
4555 }
4556
4557
4558 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) {
4559   DCHECK(!HasStackOverflow());
4560   DCHECK(current_block() != NULL);
4561   DCHECK(current_block()->HasPredecessor());
4562   if (stmt->condition()->ToBooleanIsTrue()) {
4563     Add<HSimulate>(stmt->ThenId());
4564     Visit(stmt->then_statement());
4565   } else if (stmt->condition()->ToBooleanIsFalse()) {
4566     Add<HSimulate>(stmt->ElseId());
4567     Visit(stmt->else_statement());
4568   } else {
4569     HBasicBlock* cond_true = graph()->CreateBasicBlock();
4570     HBasicBlock* cond_false = graph()->CreateBasicBlock();
4571     CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false));
4572
4573     if (cond_true->HasPredecessor()) {
4574       cond_true->SetJoinId(stmt->ThenId());
4575       set_current_block(cond_true);
4576       CHECK_BAILOUT(Visit(stmt->then_statement()));
4577       cond_true = current_block();
4578     } else {
4579       cond_true = NULL;
4580     }
4581
4582     if (cond_false->HasPredecessor()) {
4583       cond_false->SetJoinId(stmt->ElseId());
4584       set_current_block(cond_false);
4585       CHECK_BAILOUT(Visit(stmt->else_statement()));
4586       cond_false = current_block();
4587     } else {
4588       cond_false = NULL;
4589     }
4590
4591     HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId());
4592     set_current_block(join);
4593   }
4594 }
4595
4596
4597 HBasicBlock* HOptimizedGraphBuilder::BreakAndContinueScope::Get(
4598     BreakableStatement* stmt,
4599     BreakType type,
4600     Scope** scope,
4601     int* drop_extra) {
4602   *drop_extra = 0;
4603   BreakAndContinueScope* current = this;
4604   while (current != NULL && current->info()->target() != stmt) {
4605     *drop_extra += current->info()->drop_extra();
4606     current = current->next();
4607   }
4608   DCHECK(current != NULL);  // Always found (unless stack is malformed).
4609   *scope = current->info()->scope();
4610
4611   if (type == BREAK) {
4612     *drop_extra += current->info()->drop_extra();
4613   }
4614
4615   HBasicBlock* block = NULL;
4616   switch (type) {
4617     case BREAK:
4618       block = current->info()->break_block();
4619       if (block == NULL) {
4620         block = current->owner()->graph()->CreateBasicBlock();
4621         current->info()->set_break_block(block);
4622       }
4623       break;
4624
4625     case CONTINUE:
4626       block = current->info()->continue_block();
4627       if (block == NULL) {
4628         block = current->owner()->graph()->CreateBasicBlock();
4629         current->info()->set_continue_block(block);
4630       }
4631       break;
4632   }
4633
4634   return block;
4635 }
4636
4637
4638 void HOptimizedGraphBuilder::VisitContinueStatement(
4639     ContinueStatement* stmt) {
4640   DCHECK(!HasStackOverflow());
4641   DCHECK(current_block() != NULL);
4642   DCHECK(current_block()->HasPredecessor());
4643   Scope* outer_scope = NULL;
4644   Scope* inner_scope = scope();
4645   int drop_extra = 0;
4646   HBasicBlock* continue_block = break_scope()->Get(
4647       stmt->target(), BreakAndContinueScope::CONTINUE,
4648       &outer_scope, &drop_extra);
4649   HValue* context = environment()->context();
4650   Drop(drop_extra);
4651   int context_pop_count = inner_scope->ContextChainLength(outer_scope);
4652   if (context_pop_count > 0) {
4653     while (context_pop_count-- > 0) {
4654       HInstruction* context_instruction = Add<HLoadNamedField>(
4655           context, nullptr,
4656           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
4657       context = context_instruction;
4658     }
4659     HInstruction* instr = Add<HStoreFrameContext>(context);
4660     if (instr->HasObservableSideEffects()) {
4661       AddSimulate(stmt->target()->EntryId(), REMOVABLE_SIMULATE);
4662     }
4663     environment()->BindContext(context);
4664   }
4665
4666   Goto(continue_block);
4667   set_current_block(NULL);
4668 }
4669
4670
4671 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
4672   DCHECK(!HasStackOverflow());
4673   DCHECK(current_block() != NULL);
4674   DCHECK(current_block()->HasPredecessor());
4675   Scope* outer_scope = NULL;
4676   Scope* inner_scope = scope();
4677   int drop_extra = 0;
4678   HBasicBlock* break_block = break_scope()->Get(
4679       stmt->target(), BreakAndContinueScope::BREAK,
4680       &outer_scope, &drop_extra);
4681   HValue* context = environment()->context();
4682   Drop(drop_extra);
4683   int context_pop_count = inner_scope->ContextChainLength(outer_scope);
4684   if (context_pop_count > 0) {
4685     while (context_pop_count-- > 0) {
4686       HInstruction* context_instruction = Add<HLoadNamedField>(
4687           context, nullptr,
4688           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
4689       context = context_instruction;
4690     }
4691     HInstruction* instr = Add<HStoreFrameContext>(context);
4692     if (instr->HasObservableSideEffects()) {
4693       AddSimulate(stmt->target()->ExitId(), REMOVABLE_SIMULATE);
4694     }
4695     environment()->BindContext(context);
4696   }
4697   Goto(break_block);
4698   set_current_block(NULL);
4699 }
4700
4701
4702 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
4703   DCHECK(!HasStackOverflow());
4704   DCHECK(current_block() != NULL);
4705   DCHECK(current_block()->HasPredecessor());
4706   FunctionState* state = function_state();
4707   AstContext* context = call_context();
4708   if (context == NULL) {
4709     // Not an inlined return, so an actual one.
4710     CHECK_ALIVE(VisitForValue(stmt->expression()));
4711     HValue* result = environment()->Pop();
4712     Add<HReturn>(result);
4713   } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
4714     // Return from an inlined construct call. In a test context the return value
4715     // will always evaluate to true, in a value context the return value needs
4716     // to be a JSObject.
4717     if (context->IsTest()) {
4718       TestContext* test = TestContext::cast(context);
4719       CHECK_ALIVE(VisitForEffect(stmt->expression()));
4720       Goto(test->if_true(), state);
4721     } else if (context->IsEffect()) {
4722       CHECK_ALIVE(VisitForEffect(stmt->expression()));
4723       Goto(function_return(), state);
4724     } else {
4725       DCHECK(context->IsValue());
4726       CHECK_ALIVE(VisitForValue(stmt->expression()));
4727       HValue* return_value = Pop();
4728       HValue* receiver = environment()->arguments_environment()->Lookup(0);
4729       HHasInstanceTypeAndBranch* typecheck =
4730           New<HHasInstanceTypeAndBranch>(return_value,
4731                                          FIRST_SPEC_OBJECT_TYPE,
4732                                          LAST_SPEC_OBJECT_TYPE);
4733       HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
4734       HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
4735       typecheck->SetSuccessorAt(0, if_spec_object);
4736       typecheck->SetSuccessorAt(1, not_spec_object);
4737       FinishCurrentBlock(typecheck);
4738       AddLeaveInlined(if_spec_object, return_value, state);
4739       AddLeaveInlined(not_spec_object, receiver, state);
4740     }
4741   } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
4742     // Return from an inlined setter call. The returned value is never used, the
4743     // value of an assignment is always the value of the RHS of the assignment.
4744     CHECK_ALIVE(VisitForEffect(stmt->expression()));
4745     if (context->IsTest()) {
4746       HValue* rhs = environment()->arguments_environment()->Lookup(1);
4747       context->ReturnValue(rhs);
4748     } else if (context->IsEffect()) {
4749       Goto(function_return(), state);
4750     } else {
4751       DCHECK(context->IsValue());
4752       HValue* rhs = environment()->arguments_environment()->Lookup(1);
4753       AddLeaveInlined(rhs, state);
4754     }
4755   } else {
4756     // Return from a normal inlined function. Visit the subexpression in the
4757     // expression context of the call.
4758     if (context->IsTest()) {
4759       TestContext* test = TestContext::cast(context);
4760       VisitForControl(stmt->expression(), test->if_true(), test->if_false());
4761     } else if (context->IsEffect()) {
4762       // Visit in value context and ignore the result. This is needed to keep
4763       // environment in sync with full-codegen since some visitors (e.g.
4764       // VisitCountOperation) use the operand stack differently depending on
4765       // context.
4766       CHECK_ALIVE(VisitForValue(stmt->expression()));
4767       Pop();
4768       Goto(function_return(), state);
4769     } else {
4770       DCHECK(context->IsValue());
4771       CHECK_ALIVE(VisitForValue(stmt->expression()));
4772       AddLeaveInlined(Pop(), state);
4773     }
4774   }
4775   set_current_block(NULL);
4776 }
4777
4778
4779 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) {
4780   DCHECK(!HasStackOverflow());
4781   DCHECK(current_block() != NULL);
4782   DCHECK(current_block()->HasPredecessor());
4783   return Bailout(kWithStatement);
4784 }
4785
4786
4787 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
4788   DCHECK(!HasStackOverflow());
4789   DCHECK(current_block() != NULL);
4790   DCHECK(current_block()->HasPredecessor());
4791
4792   ZoneList<CaseClause*>* clauses = stmt->cases();
4793   int clause_count = clauses->length();
4794   ZoneList<HBasicBlock*> body_blocks(clause_count, zone());
4795
4796   CHECK_ALIVE(VisitForValue(stmt->tag()));
4797   Add<HSimulate>(stmt->EntryId());
4798   HValue* tag_value = Top();
4799   Type* tag_type = stmt->tag()->bounds().lower;
4800
4801   // 1. Build all the tests, with dangling true branches
4802   BailoutId default_id = BailoutId::None();
4803   for (int i = 0; i < clause_count; ++i) {
4804     CaseClause* clause = clauses->at(i);
4805     if (clause->is_default()) {
4806       body_blocks.Add(NULL, zone());
4807       if (default_id.IsNone()) default_id = clause->EntryId();
4808       continue;
4809     }
4810
4811     // Generate a compare and branch.
4812     CHECK_ALIVE(VisitForValue(clause->label()));
4813     HValue* label_value = Pop();
4814
4815     Type* label_type = clause->label()->bounds().lower;
4816     Type* combined_type = clause->compare_type();
4817     HControlInstruction* compare = BuildCompareInstruction(
4818         Token::EQ_STRICT, tag_value, label_value, tag_type, label_type,
4819         combined_type,
4820         ScriptPositionToSourcePosition(stmt->tag()->position()),
4821         ScriptPositionToSourcePosition(clause->label()->position()),
4822         PUSH_BEFORE_SIMULATE, clause->id());
4823
4824     HBasicBlock* next_test_block = graph()->CreateBasicBlock();
4825     HBasicBlock* body_block = graph()->CreateBasicBlock();
4826     body_blocks.Add(body_block, zone());
4827     compare->SetSuccessorAt(0, body_block);
4828     compare->SetSuccessorAt(1, next_test_block);
4829     FinishCurrentBlock(compare);
4830
4831     set_current_block(body_block);
4832     Drop(1);  // tag_value
4833
4834     set_current_block(next_test_block);
4835   }
4836
4837   // Save the current block to use for the default or to join with the
4838   // exit.
4839   HBasicBlock* last_block = current_block();
4840   Drop(1);  // tag_value
4841
4842   // 2. Loop over the clauses and the linked list of tests in lockstep,
4843   // translating the clause bodies.
4844   HBasicBlock* fall_through_block = NULL;
4845
4846   BreakAndContinueInfo break_info(stmt, scope());
4847   { BreakAndContinueScope push(&break_info, this);
4848     for (int i = 0; i < clause_count; ++i) {
4849       CaseClause* clause = clauses->at(i);
4850
4851       // Identify the block where normal (non-fall-through) control flow
4852       // goes to.
4853       HBasicBlock* normal_block = NULL;
4854       if (clause->is_default()) {
4855         if (last_block == NULL) continue;
4856         normal_block = last_block;
4857         last_block = NULL;  // Cleared to indicate we've handled it.
4858       } else {
4859         normal_block = body_blocks[i];
4860       }
4861
4862       if (fall_through_block == NULL) {
4863         set_current_block(normal_block);
4864       } else {
4865         HBasicBlock* join = CreateJoin(fall_through_block,
4866                                        normal_block,
4867                                        clause->EntryId());
4868         set_current_block(join);
4869       }
4870
4871       CHECK_BAILOUT(VisitStatements(clause->statements()));
4872       fall_through_block = current_block();
4873     }
4874   }
4875
4876   // Create an up-to-3-way join.  Use the break block if it exists since
4877   // it's already a join block.
4878   HBasicBlock* break_block = break_info.break_block();
4879   if (break_block == NULL) {
4880     set_current_block(CreateJoin(fall_through_block,
4881                                  last_block,
4882                                  stmt->ExitId()));
4883   } else {
4884     if (fall_through_block != NULL) Goto(fall_through_block, break_block);
4885     if (last_block != NULL) Goto(last_block, break_block);
4886     break_block->SetJoinId(stmt->ExitId());
4887     set_current_block(break_block);
4888   }
4889 }
4890
4891
4892 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt,
4893                                            HBasicBlock* loop_entry) {
4894   Add<HSimulate>(stmt->StackCheckId());
4895   HStackCheck* stack_check =
4896       HStackCheck::cast(Add<HStackCheck>(HStackCheck::kBackwardsBranch));
4897   DCHECK(loop_entry->IsLoopHeader());
4898   loop_entry->loop_information()->set_stack_check(stack_check);
4899   CHECK_BAILOUT(Visit(stmt->body()));
4900 }
4901
4902
4903 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
4904   DCHECK(!HasStackOverflow());
4905   DCHECK(current_block() != NULL);
4906   DCHECK(current_block()->HasPredecessor());
4907   DCHECK(current_block() != NULL);
4908   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
4909
4910   BreakAndContinueInfo break_info(stmt, scope());
4911   {
4912     BreakAndContinueScope push(&break_info, this);
4913     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
4914   }
4915   HBasicBlock* body_exit =
4916       JoinContinue(stmt, current_block(), break_info.continue_block());
4917   HBasicBlock* loop_successor = NULL;
4918   if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) {
4919     set_current_block(body_exit);
4920     loop_successor = graph()->CreateBasicBlock();
4921     if (stmt->cond()->ToBooleanIsFalse()) {
4922       loop_entry->loop_information()->stack_check()->Eliminate();
4923       Goto(loop_successor);
4924       body_exit = NULL;
4925     } else {
4926       // The block for a true condition, the actual predecessor block of the
4927       // back edge.
4928       body_exit = graph()->CreateBasicBlock();
4929       CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor));
4930     }
4931     if (body_exit != NULL && body_exit->HasPredecessor()) {
4932       body_exit->SetJoinId(stmt->BackEdgeId());
4933     } else {
4934       body_exit = NULL;
4935     }
4936     if (loop_successor->HasPredecessor()) {
4937       loop_successor->SetJoinId(stmt->ExitId());
4938     } else {
4939       loop_successor = NULL;
4940     }
4941   }
4942   HBasicBlock* loop_exit = CreateLoop(stmt,
4943                                       loop_entry,
4944                                       body_exit,
4945                                       loop_successor,
4946                                       break_info.break_block());
4947   set_current_block(loop_exit);
4948 }
4949
4950
4951 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
4952   DCHECK(!HasStackOverflow());
4953   DCHECK(current_block() != NULL);
4954   DCHECK(current_block()->HasPredecessor());
4955   DCHECK(current_block() != NULL);
4956   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
4957
4958   // If the condition is constant true, do not generate a branch.
4959   HBasicBlock* loop_successor = NULL;
4960   if (!stmt->cond()->ToBooleanIsTrue()) {
4961     HBasicBlock* body_entry = graph()->CreateBasicBlock();
4962     loop_successor = graph()->CreateBasicBlock();
4963     CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
4964     if (body_entry->HasPredecessor()) {
4965       body_entry->SetJoinId(stmt->BodyId());
4966       set_current_block(body_entry);
4967     }
4968     if (loop_successor->HasPredecessor()) {
4969       loop_successor->SetJoinId(stmt->ExitId());
4970     } else {
4971       loop_successor = NULL;
4972     }
4973   }
4974
4975   BreakAndContinueInfo break_info(stmt, scope());
4976   if (current_block() != NULL) {
4977     BreakAndContinueScope push(&break_info, this);
4978     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
4979   }
4980   HBasicBlock* body_exit =
4981       JoinContinue(stmt, current_block(), break_info.continue_block());
4982   HBasicBlock* loop_exit = CreateLoop(stmt,
4983                                       loop_entry,
4984                                       body_exit,
4985                                       loop_successor,
4986                                       break_info.break_block());
4987   set_current_block(loop_exit);
4988 }
4989
4990
4991 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) {
4992   DCHECK(!HasStackOverflow());
4993   DCHECK(current_block() != NULL);
4994   DCHECK(current_block()->HasPredecessor());
4995   if (stmt->init() != NULL) {
4996     CHECK_ALIVE(Visit(stmt->init()));
4997   }
4998   DCHECK(current_block() != NULL);
4999   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
5000
5001   HBasicBlock* loop_successor = NULL;
5002   if (stmt->cond() != NULL) {
5003     HBasicBlock* body_entry = graph()->CreateBasicBlock();
5004     loop_successor = graph()->CreateBasicBlock();
5005     CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
5006     if (body_entry->HasPredecessor()) {
5007       body_entry->SetJoinId(stmt->BodyId());
5008       set_current_block(body_entry);
5009     }
5010     if (loop_successor->HasPredecessor()) {
5011       loop_successor->SetJoinId(stmt->ExitId());
5012     } else {
5013       loop_successor = NULL;
5014     }
5015   }
5016
5017   BreakAndContinueInfo break_info(stmt, scope());
5018   if (current_block() != NULL) {
5019     BreakAndContinueScope push(&break_info, this);
5020     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
5021   }
5022   HBasicBlock* body_exit =
5023       JoinContinue(stmt, current_block(), break_info.continue_block());
5024
5025   if (stmt->next() != NULL && body_exit != NULL) {
5026     set_current_block(body_exit);
5027     CHECK_BAILOUT(Visit(stmt->next()));
5028     body_exit = current_block();
5029   }
5030
5031   HBasicBlock* loop_exit = CreateLoop(stmt,
5032                                       loop_entry,
5033                                       body_exit,
5034                                       loop_successor,
5035                                       break_info.break_block());
5036   set_current_block(loop_exit);
5037 }
5038
5039
5040 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
5041   DCHECK(!HasStackOverflow());
5042   DCHECK(current_block() != NULL);
5043   DCHECK(current_block()->HasPredecessor());
5044
5045   if (!FLAG_optimize_for_in) {
5046     return Bailout(kForInStatementOptimizationIsDisabled);
5047   }
5048
5049   if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) {
5050     return Bailout(kForInStatementIsNotFastCase);
5051   }
5052
5053   if (!stmt->each()->IsVariableProxy() ||
5054       !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
5055     return Bailout(kForInStatementWithNonLocalEachVariable);
5056   }
5057
5058   Variable* each_var = stmt->each()->AsVariableProxy()->var();
5059
5060   CHECK_ALIVE(VisitForValue(stmt->enumerable()));
5061   HValue* enumerable = Top();  // Leave enumerable at the top.
5062
5063   HInstruction* map = Add<HForInPrepareMap>(enumerable);
5064   Add<HSimulate>(stmt->PrepareId());
5065
5066   HInstruction* array = Add<HForInCacheArray>(
5067       enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex);
5068
5069   HInstruction* enum_length = Add<HMapEnumLength>(map);
5070
5071   HInstruction* start_index = Add<HConstant>(0);
5072
5073   Push(map);
5074   Push(array);
5075   Push(enum_length);
5076   Push(start_index);
5077
5078   HInstruction* index_cache = Add<HForInCacheArray>(
5079       enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex);
5080   HForInCacheArray::cast(array)->set_index_cache(
5081       HForInCacheArray::cast(index_cache));
5082
5083   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
5084
5085   HValue* index = environment()->ExpressionStackAt(0);
5086   HValue* limit = environment()->ExpressionStackAt(1);
5087
5088   // Check that we still have more keys.
5089   HCompareNumericAndBranch* compare_index =
5090       New<HCompareNumericAndBranch>(index, limit, Token::LT);
5091   compare_index->set_observed_input_representation(
5092       Representation::Smi(), Representation::Smi());
5093
5094   HBasicBlock* loop_body = graph()->CreateBasicBlock();
5095   HBasicBlock* loop_successor = graph()->CreateBasicBlock();
5096
5097   compare_index->SetSuccessorAt(0, loop_body);
5098   compare_index->SetSuccessorAt(1, loop_successor);
5099   FinishCurrentBlock(compare_index);
5100
5101   set_current_block(loop_successor);
5102   Drop(5);
5103
5104   set_current_block(loop_body);
5105
5106   HValue* key = Add<HLoadKeyed>(
5107       environment()->ExpressionStackAt(2),  // Enum cache.
5108       environment()->ExpressionStackAt(0),  // Iteration index.
5109       environment()->ExpressionStackAt(0),
5110       FAST_ELEMENTS);
5111
5112   // Check if the expected map still matches that of the enumerable.
5113   // If not just deoptimize.
5114   Add<HCheckMapValue>(environment()->ExpressionStackAt(4),
5115                       environment()->ExpressionStackAt(3));
5116
5117   Bind(each_var, key);
5118
5119   BreakAndContinueInfo break_info(stmt, scope(), 5);
5120   {
5121     BreakAndContinueScope push(&break_info, this);
5122     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
5123   }
5124
5125   HBasicBlock* body_exit =
5126       JoinContinue(stmt, current_block(), break_info.continue_block());
5127
5128   if (body_exit != NULL) {
5129     set_current_block(body_exit);
5130
5131     HValue* current_index = Pop();
5132     Push(AddUncasted<HAdd>(current_index, graph()->GetConstant1()));
5133     body_exit = current_block();
5134   }
5135
5136   HBasicBlock* loop_exit = CreateLoop(stmt,
5137                                       loop_entry,
5138                                       body_exit,
5139                                       loop_successor,
5140                                       break_info.break_block());
5141
5142   set_current_block(loop_exit);
5143 }
5144
5145
5146 void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
5147   DCHECK(!HasStackOverflow());
5148   DCHECK(current_block() != NULL);
5149   DCHECK(current_block()->HasPredecessor());
5150   return Bailout(kForOfStatement);
5151 }
5152
5153
5154 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
5155   DCHECK(!HasStackOverflow());
5156   DCHECK(current_block() != NULL);
5157   DCHECK(current_block()->HasPredecessor());
5158   return Bailout(kTryCatchStatement);
5159 }
5160
5161
5162 void HOptimizedGraphBuilder::VisitTryFinallyStatement(
5163     TryFinallyStatement* stmt) {
5164   DCHECK(!HasStackOverflow());
5165   DCHECK(current_block() != NULL);
5166   DCHECK(current_block()->HasPredecessor());
5167   return Bailout(kTryFinallyStatement);
5168 }
5169
5170
5171 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
5172   DCHECK(!HasStackOverflow());
5173   DCHECK(current_block() != NULL);
5174   DCHECK(current_block()->HasPredecessor());
5175   return Bailout(kDebuggerStatement);
5176 }
5177
5178
5179 void HOptimizedGraphBuilder::VisitCaseClause(CaseClause* clause) {
5180   UNREACHABLE();
5181 }
5182
5183
5184 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
5185   DCHECK(!HasStackOverflow());
5186   DCHECK(current_block() != NULL);
5187   DCHECK(current_block()->HasPredecessor());
5188   Handle<SharedFunctionInfo> shared_info = expr->shared_info();
5189   if (shared_info.is_null()) {
5190     shared_info =
5191         Compiler::BuildFunctionInfo(expr, current_info()->script(), top_info());
5192   }
5193   // We also have a stack overflow if the recursive compilation did.
5194   if (HasStackOverflow()) return;
5195   HFunctionLiteral* instr =
5196       New<HFunctionLiteral>(shared_info, expr->pretenure());
5197   return ast_context()->ReturnInstruction(instr, expr->id());
5198 }
5199
5200
5201 void HOptimizedGraphBuilder::VisitClassLiteral(ClassLiteral* lit) {
5202   DCHECK(!HasStackOverflow());
5203   DCHECK(current_block() != NULL);
5204   DCHECK(current_block()->HasPredecessor());
5205   return Bailout(kClassLiteral);
5206 }
5207
5208
5209 void HOptimizedGraphBuilder::VisitNativeFunctionLiteral(
5210     NativeFunctionLiteral* expr) {
5211   DCHECK(!HasStackOverflow());
5212   DCHECK(current_block() != NULL);
5213   DCHECK(current_block()->HasPredecessor());
5214   return Bailout(kNativeFunctionLiteral);
5215 }
5216
5217
5218 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) {
5219   DCHECK(!HasStackOverflow());
5220   DCHECK(current_block() != NULL);
5221   DCHECK(current_block()->HasPredecessor());
5222   HBasicBlock* cond_true = graph()->CreateBasicBlock();
5223   HBasicBlock* cond_false = graph()->CreateBasicBlock();
5224   CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false));
5225
5226   // Visit the true and false subexpressions in the same AST context as the
5227   // whole expression.
5228   if (cond_true->HasPredecessor()) {
5229     cond_true->SetJoinId(expr->ThenId());
5230     set_current_block(cond_true);
5231     CHECK_BAILOUT(Visit(expr->then_expression()));
5232     cond_true = current_block();
5233   } else {
5234     cond_true = NULL;
5235   }
5236
5237   if (cond_false->HasPredecessor()) {
5238     cond_false->SetJoinId(expr->ElseId());
5239     set_current_block(cond_false);
5240     CHECK_BAILOUT(Visit(expr->else_expression()));
5241     cond_false = current_block();
5242   } else {
5243     cond_false = NULL;
5244   }
5245
5246   if (!ast_context()->IsTest()) {
5247     HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id());
5248     set_current_block(join);
5249     if (join != NULL && !ast_context()->IsEffect()) {
5250       return ast_context()->ReturnValue(Pop());
5251     }
5252   }
5253 }
5254
5255
5256 HOptimizedGraphBuilder::GlobalPropertyAccess
5257 HOptimizedGraphBuilder::LookupGlobalProperty(Variable* var, LookupIterator* it,
5258                                              PropertyAccessType access_type) {
5259   if (var->is_this() || !current_info()->has_global_object()) {
5260     return kUseGeneric;
5261   }
5262
5263   switch (it->state()) {
5264     case LookupIterator::ACCESSOR:
5265     case LookupIterator::ACCESS_CHECK:
5266     case LookupIterator::INTERCEPTOR:
5267     case LookupIterator::INTEGER_INDEXED_EXOTIC:
5268     case LookupIterator::NOT_FOUND:
5269       return kUseGeneric;
5270     case LookupIterator::DATA:
5271       if (access_type == STORE && it->IsReadOnly()) return kUseGeneric;
5272       return kUseCell;
5273     case LookupIterator::JSPROXY:
5274     case LookupIterator::TRANSITION:
5275       UNREACHABLE();
5276   }
5277   UNREACHABLE();
5278   return kUseGeneric;
5279 }
5280
5281
5282 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
5283   DCHECK(var->IsContextSlot());
5284   HValue* context = environment()->context();
5285   int length = scope()->ContextChainLength(var->scope());
5286   while (length-- > 0) {
5287     context = Add<HLoadNamedField>(
5288         context, nullptr,
5289         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
5290   }
5291   return context;
5292 }
5293
5294
5295 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
5296   if (expr->is_this()) {
5297     graph()->MarkThisHasUses();
5298   }
5299
5300   DCHECK(!HasStackOverflow());
5301   DCHECK(current_block() != NULL);
5302   DCHECK(current_block()->HasPredecessor());
5303   Variable* variable = expr->var();
5304   switch (variable->location()) {
5305     case Variable::UNALLOCATED: {
5306       if (IsLexicalVariableMode(variable->mode())) {
5307         // TODO(rossberg): should this be an DCHECK?
5308         return Bailout(kReferenceToGlobalLexicalVariable);
5309       }
5310       // Handle known global constants like 'undefined' specially to avoid a
5311       // load from a global cell for them.
5312       Handle<Object> constant_value =
5313           isolate()->factory()->GlobalConstantFor(variable->name());
5314       if (!constant_value.is_null()) {
5315         HConstant* instr = New<HConstant>(constant_value);
5316         return ast_context()->ReturnInstruction(instr, expr->id());
5317       }
5318
5319       Handle<GlobalObject> global(current_info()->global_object());
5320
5321       // Lookup in script contexts.
5322       {
5323         Handle<ScriptContextTable> script_contexts(
5324             global->native_context()->script_context_table());
5325         ScriptContextTable::LookupResult lookup;
5326         if (ScriptContextTable::Lookup(script_contexts, variable->name(),
5327                                        &lookup)) {
5328           Handle<Context> script_context = ScriptContextTable::GetContext(
5329               script_contexts, lookup.context_index);
5330           Handle<Object> current_value =
5331               FixedArray::get(script_context, lookup.slot_index);
5332
5333           // If the values is not the hole, it will stay initialized,
5334           // so no need to generate a check.
5335           if (*current_value == *isolate()->factory()->the_hole_value()) {
5336             return Bailout(kReferenceToUninitializedVariable);
5337           }
5338           HInstruction* result = New<HLoadNamedField>(
5339               Add<HConstant>(script_context), nullptr,
5340               HObjectAccess::ForContextSlot(lookup.slot_index));
5341           return ast_context()->ReturnInstruction(result, expr->id());
5342         }
5343       }
5344
5345       LookupIterator it(global, variable->name(),
5346                         LookupIterator::OWN_SKIP_INTERCEPTOR);
5347       GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD);
5348
5349       if (type == kUseCell) {
5350         Handle<PropertyCell> cell = it.GetPropertyCell();
5351         PropertyCell::AddDependentCompilationInfo(cell, top_info());
5352         if (it.property_details().cell_type() == PropertyCellType::kConstant) {
5353           Handle<Object> constant_object(cell->value(), isolate());
5354           if (constant_object->IsConsString()) {
5355             constant_object =
5356                 String::Flatten(Handle<String>::cast(constant_object));
5357           }
5358           HConstant* constant = New<HConstant>(constant_object);
5359           return ast_context()->ReturnInstruction(constant, expr->id());
5360         } else {
5361           HConstant* cell_constant = Add<HConstant>(cell);
5362           HLoadNamedField* instr = New<HLoadNamedField>(
5363               cell_constant, nullptr, HObjectAccess::ForPropertyCellValue());
5364           instr->ClearDependsOnFlag(kInobjectFields);
5365           instr->SetDependsOnFlag(kGlobalVars);
5366           return ast_context()->ReturnInstruction(instr, expr->id());
5367         }
5368       } else {
5369         HValue* global_object = Add<HLoadNamedField>(
5370             context(), nullptr,
5371             HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
5372         HLoadGlobalGeneric* instr =
5373             New<HLoadGlobalGeneric>(global_object,
5374                                     variable->name(),
5375                                     ast_context()->is_for_typeof());
5376         if (FLAG_vector_ics) {
5377           Handle<SharedFunctionInfo> current_shared =
5378               function_state()->compilation_info()->shared_info();
5379           instr->SetVectorAndSlot(
5380               handle(current_shared->feedback_vector(), isolate()),
5381               expr->VariableFeedbackSlot());
5382         }
5383         return ast_context()->ReturnInstruction(instr, expr->id());
5384       }
5385     }
5386
5387     case Variable::PARAMETER:
5388     case Variable::LOCAL: {
5389       HValue* value = LookupAndMakeLive(variable);
5390       if (value == graph()->GetConstantHole()) {
5391         DCHECK(IsDeclaredVariableMode(variable->mode()) &&
5392                variable->mode() != VAR);
5393         return Bailout(kReferenceToUninitializedVariable);
5394       }
5395       return ast_context()->ReturnValue(value);
5396     }
5397
5398     case Variable::CONTEXT: {
5399       HValue* context = BuildContextChainWalk(variable);
5400       HLoadContextSlot::Mode mode;
5401       switch (variable->mode()) {
5402         case LET:
5403         case CONST:
5404           mode = HLoadContextSlot::kCheckDeoptimize;
5405           break;
5406         case CONST_LEGACY:
5407           mode = HLoadContextSlot::kCheckReturnUndefined;
5408           break;
5409         default:
5410           mode = HLoadContextSlot::kNoCheck;
5411           break;
5412       }
5413       HLoadContextSlot* instr =
5414           new(zone()) HLoadContextSlot(context, variable->index(), mode);
5415       return ast_context()->ReturnInstruction(instr, expr->id());
5416     }
5417
5418     case Variable::LOOKUP:
5419       return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup);
5420   }
5421 }
5422
5423
5424 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) {
5425   DCHECK(!HasStackOverflow());
5426   DCHECK(current_block() != NULL);
5427   DCHECK(current_block()->HasPredecessor());
5428   HConstant* instr = New<HConstant>(expr->value());
5429   return ast_context()->ReturnInstruction(instr, expr->id());
5430 }
5431
5432
5433 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
5434   DCHECK(!HasStackOverflow());
5435   DCHECK(current_block() != NULL);
5436   DCHECK(current_block()->HasPredecessor());
5437   Handle<JSFunction> closure = function_state()->compilation_info()->closure();
5438   Handle<FixedArray> literals(closure->literals());
5439   HRegExpLiteral* instr = New<HRegExpLiteral>(literals,
5440                                               expr->pattern(),
5441                                               expr->flags(),
5442                                               expr->literal_index());
5443   return ast_context()->ReturnInstruction(instr, expr->id());
5444 }
5445
5446
5447 static bool CanInlinePropertyAccess(Handle<Map> map) {
5448   if (map->instance_type() == HEAP_NUMBER_TYPE) return true;
5449   if (map->instance_type() < FIRST_NONSTRING_TYPE) return true;
5450   return map->IsJSObjectMap() && !map->is_dictionary_map() &&
5451          !map->has_named_interceptor() &&
5452          // TODO(verwaest): Whitelist contexts to which we have access.
5453          !map->is_access_check_needed();
5454 }
5455
5456
5457 // Determines whether the given array or object literal boilerplate satisfies
5458 // all limits to be considered for fast deep-copying and computes the total
5459 // size of all objects that are part of the graph.
5460 static bool IsFastLiteral(Handle<JSObject> boilerplate,
5461                           int max_depth,
5462                           int* max_properties) {
5463   if (boilerplate->map()->is_deprecated() &&
5464       !JSObject::TryMigrateInstance(boilerplate)) {
5465     return false;
5466   }
5467
5468   DCHECK(max_depth >= 0 && *max_properties >= 0);
5469   if (max_depth == 0) return false;
5470
5471   Isolate* isolate = boilerplate->GetIsolate();
5472   Handle<FixedArrayBase> elements(boilerplate->elements());
5473   if (elements->length() > 0 &&
5474       elements->map() != isolate->heap()->fixed_cow_array_map()) {
5475     if (boilerplate->HasFastSmiOrObjectElements()) {
5476       Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
5477       int length = elements->length();
5478       for (int i = 0; i < length; i++) {
5479         if ((*max_properties)-- == 0) return false;
5480         Handle<Object> value(fast_elements->get(i), isolate);
5481         if (value->IsJSObject()) {
5482           Handle<JSObject> value_object = Handle<JSObject>::cast(value);
5483           if (!IsFastLiteral(value_object,
5484                              max_depth - 1,
5485                              max_properties)) {
5486             return false;
5487           }
5488         }
5489       }
5490     } else if (!boilerplate->HasFastDoubleElements()) {
5491       return false;
5492     }
5493   }
5494
5495   Handle<FixedArray> properties(boilerplate->properties());
5496   if (properties->length() > 0) {
5497     return false;
5498   } else {
5499     Handle<DescriptorArray> descriptors(
5500         boilerplate->map()->instance_descriptors());
5501     int limit = boilerplate->map()->NumberOfOwnDescriptors();
5502     for (int i = 0; i < limit; i++) {
5503       PropertyDetails details = descriptors->GetDetails(i);
5504       if (details.type() != DATA) continue;
5505       if ((*max_properties)-- == 0) return false;
5506       FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
5507       if (boilerplate->IsUnboxedDoubleField(field_index)) continue;
5508       Handle<Object> value(boilerplate->RawFastPropertyAt(field_index),
5509                            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
5529   expr->BuildConstantProperties(isolate());
5530   Handle<JSFunction> closure = function_state()->compilation_info()->closure();
5531   HInstruction* literal;
5532
5533   // Check whether to use fast or slow deep-copying for boilerplate.
5534   int max_properties = kMaxFastLiteralProperties;
5535   Handle<Object> literals_cell(closure->literals()->get(expr->literal_index()),
5536                                isolate());
5537   Handle<AllocationSite> site;
5538   Handle<JSObject> boilerplate;
5539   if (!literals_cell->IsUndefined()) {
5540     // Retrieve the boilerplate
5541     site = Handle<AllocationSite>::cast(literals_cell);
5542     boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()),
5543                                    isolate());
5544   }
5545
5546   if (!boilerplate.is_null() &&
5547       IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
5548     AllocationSiteUsageContext usage_context(isolate(), site, false);
5549     usage_context.EnterNewScope();
5550     literal = BuildFastLiteral(boilerplate, &usage_context);
5551     usage_context.ExitScope(site, boilerplate);
5552   } else {
5553     NoObservableSideEffectsScope no_effects(this);
5554     Handle<FixedArray> closure_literals(closure->literals(), isolate());
5555     Handle<FixedArray> constant_properties = expr->constant_properties();
5556     int literal_index = expr->literal_index();
5557     int flags = expr->ComputeFlags(true);
5558
5559     Add<HPushArguments>(Add<HConstant>(closure_literals),
5560                         Add<HConstant>(literal_index),
5561                         Add<HConstant>(constant_properties),
5562                         Add<HConstant>(flags));
5563
5564     Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral;
5565     literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
5566                                 Runtime::FunctionForId(function_id),
5567                                 4);
5568   }
5569
5570   // The object is expected in the bailout environment during computation
5571   // of the property values and is the value of the entire expression.
5572   Push(literal);
5573
5574   expr->CalculateEmitStore(zone());
5575
5576   for (int i = 0; i < expr->properties()->length(); i++) {
5577     ObjectLiteral::Property* property = expr->properties()->at(i);
5578     if (property->is_computed_name()) return Bailout(kComputedPropertyName);
5579     if (property->IsCompileTimeValue()) continue;
5580
5581     Literal* key = property->key()->AsLiteral();
5582     Expression* value = property->value();
5583
5584     switch (property->kind()) {
5585       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
5586         DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
5587         // Fall through.
5588       case ObjectLiteral::Property::COMPUTED:
5589         // It is safe to use [[Put]] here because the boilerplate already
5590         // contains computed properties with an uninitialized value.
5591         if (key->value()->IsInternalizedString()) {
5592           if (property->emit_store()) {
5593             CHECK_ALIVE(VisitForValue(value));
5594             HValue* value = Pop();
5595
5596             // Add [[HomeObject]] to function literals.
5597             if (FunctionLiteral::NeedsHomeObject(property->value())) {
5598               Handle<Symbol> sym = isolate()->factory()->home_object_symbol();
5599               HInstruction* store_home = BuildKeyedGeneric(
5600                   STORE, NULL, value, Add<HConstant>(sym), literal);
5601               AddInstruction(store_home);
5602               DCHECK(store_home->HasObservableSideEffects());
5603               Add<HSimulate>(property->value()->id(), REMOVABLE_SIMULATE);
5604             }
5605
5606             Handle<Map> map = property->GetReceiverType();
5607             Handle<String> name = key->AsPropertyName();
5608             HInstruction* store;
5609             if (map.is_null()) {
5610               // If we don't know the monomorphic type, do a generic store.
5611               CHECK_ALIVE(store = BuildNamedGeneric(
5612                   STORE, NULL, literal, name, value));
5613             } else {
5614               PropertyAccessInfo info(this, STORE, map, name);
5615               if (info.CanAccessMonomorphic()) {
5616                 HValue* checked_literal = Add<HCheckMaps>(literal, map);
5617                 DCHECK(!info.IsAccessorConstant());
5618                 store = BuildMonomorphicAccess(
5619                     &info, literal, checked_literal, value,
5620                     BailoutId::None(), BailoutId::None());
5621               } else {
5622                 CHECK_ALIVE(store = BuildNamedGeneric(
5623                     STORE, NULL, literal, name, value));
5624               }
5625             }
5626             AddInstruction(store);
5627             DCHECK(store->HasObservableSideEffects());
5628             Add<HSimulate>(key->id(), REMOVABLE_SIMULATE);
5629           } else {
5630             CHECK_ALIVE(VisitForEffect(value));
5631           }
5632           break;
5633         }
5634         // Fall through.
5635       case ObjectLiteral::Property::PROTOTYPE:
5636       case ObjectLiteral::Property::SETTER:
5637       case ObjectLiteral::Property::GETTER:
5638         return Bailout(kObjectLiteralWithComplexProperty);
5639       default: UNREACHABLE();
5640     }
5641   }
5642
5643   if (expr->has_function()) {
5644     // Return the result of the transformation to fast properties
5645     // instead of the original since this operation changes the map
5646     // of the object. This makes sure that the original object won't
5647     // be used by other optimized code before it is transformed
5648     // (e.g. because of code motion).
5649     HToFastProperties* result = Add<HToFastProperties>(Pop());
5650     return ast_context()->ReturnValue(result);
5651   } else {
5652     return ast_context()->ReturnValue(Pop());
5653   }
5654 }
5655
5656
5657 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
5658   DCHECK(!HasStackOverflow());
5659   DCHECK(current_block() != NULL);
5660   DCHECK(current_block()->HasPredecessor());
5661   expr->BuildConstantElements(isolate());
5662   ZoneList<Expression*>* subexprs = expr->values();
5663   int length = subexprs->length();
5664   HInstruction* literal;
5665
5666   Handle<AllocationSite> site;
5667   Handle<FixedArray> literals(environment()->closure()->literals(), isolate());
5668   bool uninitialized = false;
5669   Handle<Object> literals_cell(literals->get(expr->literal_index()),
5670                                isolate());
5671   Handle<JSObject> boilerplate_object;
5672   if (literals_cell->IsUndefined()) {
5673     uninitialized = true;
5674     Handle<Object> raw_boilerplate;
5675     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5676         isolate(), raw_boilerplate,
5677         Runtime::CreateArrayLiteralBoilerplate(
5678             isolate(), literals, expr->constant_elements()),
5679         Bailout(kArrayBoilerplateCreationFailed));
5680
5681     boilerplate_object = Handle<JSObject>::cast(raw_boilerplate);
5682     AllocationSiteCreationContext creation_context(isolate());
5683     site = creation_context.EnterNewScope();
5684     if (JSObject::DeepWalk(boilerplate_object, &creation_context).is_null()) {
5685       return Bailout(kArrayBoilerplateCreationFailed);
5686     }
5687     creation_context.ExitScope(site, boilerplate_object);
5688     literals->set(expr->literal_index(), *site);
5689
5690     if (boilerplate_object->elements()->map() ==
5691         isolate()->heap()->fixed_cow_array_map()) {
5692       isolate()->counters()->cow_arrays_created_runtime()->Increment();
5693     }
5694   } else {
5695     DCHECK(literals_cell->IsAllocationSite());
5696     site = Handle<AllocationSite>::cast(literals_cell);
5697     boilerplate_object = Handle<JSObject>(
5698         JSObject::cast(site->transition_info()), isolate());
5699   }
5700
5701   DCHECK(!boilerplate_object.is_null());
5702   DCHECK(site->SitePointsToLiteral());
5703
5704   ElementsKind boilerplate_elements_kind =
5705       boilerplate_object->GetElementsKind();
5706
5707   // Check whether to use fast or slow deep-copying for boilerplate.
5708   int max_properties = kMaxFastLiteralProperties;
5709   if (IsFastLiteral(boilerplate_object,
5710                     kMaxFastLiteralDepth,
5711                     &max_properties)) {
5712     AllocationSiteUsageContext usage_context(isolate(), site, false);
5713     usage_context.EnterNewScope();
5714     literal = BuildFastLiteral(boilerplate_object, &usage_context);
5715     usage_context.ExitScope(site, boilerplate_object);
5716   } else {
5717     NoObservableSideEffectsScope no_effects(this);
5718     // Boilerplate already exists and constant elements are never accessed,
5719     // pass an empty fixed array to the runtime function instead.
5720     Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array();
5721     int literal_index = expr->literal_index();
5722     int flags = expr->ComputeFlags(true);
5723
5724     Add<HPushArguments>(Add<HConstant>(literals),
5725                         Add<HConstant>(literal_index),
5726                         Add<HConstant>(constants),
5727                         Add<HConstant>(flags));
5728
5729     Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral;
5730     literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
5731                                 Runtime::FunctionForId(function_id),
5732                                 4);
5733
5734     // Register to deopt if the boilerplate ElementsKind changes.
5735     AllocationSite::RegisterForDeoptOnTransitionChange(site, top_info());
5736   }
5737
5738   // The array is expected in the bailout environment during computation
5739   // of the property values and is the value of the entire expression.
5740   Push(literal);
5741   // The literal index is on the stack, too.
5742   Push(Add<HConstant>(expr->literal_index()));
5743
5744   HInstruction* elements = NULL;
5745
5746   for (int i = 0; i < length; i++) {
5747     Expression* subexpr = subexprs->at(i);
5748     // If the subexpression is a literal or a simple materialized literal it
5749     // is already set in the cloned array.
5750     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
5751
5752     CHECK_ALIVE(VisitForValue(subexpr));
5753     HValue* value = Pop();
5754     if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral);
5755
5756     elements = AddLoadElements(literal);
5757
5758     HValue* key = Add<HConstant>(i);
5759
5760     switch (boilerplate_elements_kind) {
5761       case FAST_SMI_ELEMENTS:
5762       case FAST_HOLEY_SMI_ELEMENTS:
5763       case FAST_ELEMENTS:
5764       case FAST_HOLEY_ELEMENTS:
5765       case FAST_DOUBLE_ELEMENTS:
5766       case FAST_HOLEY_DOUBLE_ELEMENTS: {
5767         HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value,
5768                                               boilerplate_elements_kind);
5769         instr->SetUninitialized(uninitialized);
5770         break;
5771       }
5772       default:
5773         UNREACHABLE();
5774         break;
5775     }
5776
5777     Add<HSimulate>(expr->GetIdForElement(i));
5778   }
5779
5780   Drop(1);  // array literal index
5781   return ast_context()->ReturnValue(Pop());
5782 }
5783
5784
5785 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object,
5786                                                 Handle<Map> map) {
5787   BuildCheckHeapObject(object);
5788   return Add<HCheckMaps>(object, map);
5789 }
5790
5791
5792 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField(
5793     PropertyAccessInfo* info,
5794     HValue* checked_object) {
5795   // See if this is a load for an immutable property
5796   if (checked_object->ActualValue()->IsConstant()) {
5797     Handle<Object> object(
5798         HConstant::cast(checked_object->ActualValue())->handle(isolate()));
5799
5800     if (object->IsJSObject()) {
5801       LookupIterator it(object, info->name(),
5802                         LookupIterator::OWN_SKIP_INTERCEPTOR);
5803       Handle<Object> value = JSObject::GetDataProperty(&it);
5804       if (it.IsFound() && it.IsReadOnly() && !it.IsConfigurable()) {
5805         return New<HConstant>(value);
5806       }
5807     }
5808   }
5809
5810   HObjectAccess access = info->access();
5811   if (access.representation().IsDouble() &&
5812       (!FLAG_unbox_double_fields || !access.IsInobject())) {
5813     // Load the heap number.
5814     checked_object = Add<HLoadNamedField>(
5815         checked_object, nullptr,
5816         access.WithRepresentation(Representation::Tagged()));
5817     // Load the double value from it.
5818     access = HObjectAccess::ForHeapNumberValue();
5819   }
5820
5821   SmallMapList* map_list = info->field_maps();
5822   if (map_list->length() == 0) {
5823     return New<HLoadNamedField>(checked_object, checked_object, access);
5824   }
5825
5826   UniqueSet<Map>* maps = new(zone()) UniqueSet<Map>(map_list->length(), zone());
5827   for (int i = 0; i < map_list->length(); ++i) {
5828     maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone());
5829   }
5830   return New<HLoadNamedField>(
5831       checked_object, checked_object, access, maps, info->field_type());
5832 }
5833
5834
5835 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
5836     PropertyAccessInfo* info,
5837     HValue* checked_object,
5838     HValue* value) {
5839   bool transition_to_field = info->IsTransition();
5840   // TODO(verwaest): Move this logic into PropertyAccessInfo.
5841   HObjectAccess field_access = info->access();
5842
5843   HStoreNamedField *instr;
5844   if (field_access.representation().IsDouble() &&
5845       (!FLAG_unbox_double_fields || !field_access.IsInobject())) {
5846     HObjectAccess heap_number_access =
5847         field_access.WithRepresentation(Representation::Tagged());
5848     if (transition_to_field) {
5849       // The store requires a mutable HeapNumber to be allocated.
5850       NoObservableSideEffectsScope no_side_effects(this);
5851       HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
5852
5853       // TODO(hpayer): Allocation site pretenuring support.
5854       HInstruction* heap_number = Add<HAllocate>(heap_number_size,
5855           HType::HeapObject(),
5856           NOT_TENURED,
5857           MUTABLE_HEAP_NUMBER_TYPE);
5858       AddStoreMapConstant(
5859           heap_number, isolate()->factory()->mutable_heap_number_map());
5860       Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
5861                             value);
5862       instr = New<HStoreNamedField>(checked_object->ActualValue(),
5863                                     heap_number_access,
5864                                     heap_number);
5865     } else {
5866       // Already holds a HeapNumber; load the box and write its value field.
5867       HInstruction* heap_number =
5868           Add<HLoadNamedField>(checked_object, nullptr, heap_number_access);
5869       instr = New<HStoreNamedField>(heap_number,
5870                                     HObjectAccess::ForHeapNumberValue(),
5871                                     value, STORE_TO_INITIALIZED_ENTRY);
5872     }
5873   } else {
5874     if (field_access.representation().IsHeapObject()) {
5875       BuildCheckHeapObject(value);
5876     }
5877
5878     if (!info->field_maps()->is_empty()) {
5879       DCHECK(field_access.representation().IsHeapObject());
5880       value = Add<HCheckMaps>(value, info->field_maps());
5881     }
5882
5883     // This is a normal store.
5884     instr = New<HStoreNamedField>(
5885         checked_object->ActualValue(), field_access, value,
5886         transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY);
5887   }
5888
5889   if (transition_to_field) {
5890     Handle<Map> transition(info->transition());
5891     DCHECK(!transition->is_deprecated());
5892     instr->SetTransition(Add<HConstant>(transition));
5893   }
5894   return instr;
5895 }
5896
5897
5898 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible(
5899     PropertyAccessInfo* info) {
5900   if (!CanInlinePropertyAccess(map_)) return false;
5901
5902   // Currently only handle Type::Number as a polymorphic case.
5903   // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
5904   // instruction.
5905   if (IsNumberType()) return false;
5906
5907   // Values are only compatible for monomorphic load if they all behave the same
5908   // regarding value wrappers.
5909   if (IsValueWrapped() != info->IsValueWrapped()) return false;
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 (IsAccessorConstant()) {
5923     return accessor_.is_identical_to(info->accessor_) &&
5924         api_holder_.is_identical_to(info->api_holder_);
5925   }
5926
5927   if (IsDataConstant()) {
5928     return constant_.is_identical_to(info->constant_);
5929   }
5930
5931   DCHECK(IsData());
5932   if (!info->IsData()) 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 (!map_->IsJSObjectMap()) return true;
5969   LookupDescriptor(*map_, *name_);
5970   return LoadResult(map_);
5971 }
5972
5973
5974 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
5975   if (!IsLoad() && IsProperty() && IsReadOnly()) {
5976     return false;
5977   }
5978
5979   if (IsData()) {
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     return LoadFieldMaps(map);
5986   } else if (IsAccessorConstant()) {
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         api_holder_ =
5999             call_optimization.LookupHolderOfExpectedType(map_, &holder_lookup);
6000       }
6001     }
6002     accessor_ = accessor;
6003   } else if (IsDataConstant()) {
6004     constant_ = GetConstantFromMap(map);
6005   }
6006
6007   return true;
6008 }
6009
6010
6011 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps(
6012     Handle<Map> map) {
6013   // Clear any previously collected field maps/type.
6014   field_maps_.Clear();
6015   field_type_ = HType::Tagged();
6016
6017   // Figure out the field type from the accessor map.
6018   Handle<HeapType> field_type = GetFieldTypeFromMap(map);
6019
6020   // Collect the (stable) maps from the field type.
6021   int num_field_maps = field_type->NumClasses();
6022   if (num_field_maps > 0) {
6023     DCHECK(access_.representation().IsHeapObject());
6024     field_maps_.Reserve(num_field_maps, zone());
6025     HeapType::Iterator<Map> it = field_type->Classes();
6026     while (!it.Done()) {
6027       Handle<Map> field_map = it.Current();
6028       if (!field_map->is_stable()) {
6029         field_maps_.Clear();
6030         break;
6031       }
6032       field_maps_.Add(field_map, zone());
6033       it.Advance();
6034     }
6035   }
6036
6037   if (field_maps_.is_empty()) {
6038     // Store is not safe if the field map was cleared.
6039     return IsLoad() || !field_type->Is(HeapType::None());
6040   }
6041
6042   field_maps_.Sort();
6043   DCHECK_EQ(num_field_maps, field_maps_.length());
6044
6045   // Determine field HType from field HeapType.
6046   field_type_ = HType::FromType<HeapType>(field_type);
6047   DCHECK(field_type_.IsHeapObject());
6048
6049   // Add dependency on the map that introduced the field.
6050   Map::AddDependentCompilationInfo(GetFieldOwnerFromMap(map),
6051                                    DependentCode::kFieldTypeGroup, top_info());
6052   return true;
6053 }
6054
6055
6056 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
6057   Handle<Map> map = this->map();
6058
6059   while (map->prototype()->IsJSObject()) {
6060     holder_ = handle(JSObject::cast(map->prototype()));
6061     if (holder_->map()->is_deprecated()) {
6062       JSObject::TryMigrateInstance(holder_);
6063     }
6064     map = Handle<Map>(holder_->map());
6065     if (!CanInlinePropertyAccess(map)) {
6066       NotFound();
6067       return false;
6068     }
6069     LookupDescriptor(*map, *name_);
6070     if (IsFound()) return LoadResult(map);
6071   }
6072   NotFound();
6073   return true;
6074 }
6075
6076
6077 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsIntegerIndexedExotic() {
6078   InstanceType instance_type = map_->instance_type();
6079   return instance_type == JS_TYPED_ARRAY_TYPE && IsNonArrayIndexInteger(*name_);
6080 }
6081
6082
6083 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
6084   if (!CanInlinePropertyAccess(map_)) return false;
6085   if (IsJSObjectFieldAccessor()) return IsLoad();
6086   if (map_->function_with_prototype() && !map_->has_non_instance_prototype() &&
6087       name_.is_identical_to(isolate()->factory()->prototype_string())) {
6088     return IsLoad();
6089   }
6090   if (!LookupDescriptor()) return false;
6091   if (IsFound()) return IsLoad() || !IsReadOnly();
6092   if (IsIntegerIndexedExotic()) return false;
6093   if (!LookupInPrototypes()) return false;
6094   if (IsLoad()) return true;
6095
6096   if (IsAccessorConstant()) return true;
6097   LookupTransition(*map_, *name_, NONE);
6098   if (IsTransitionToData() && map_->unused_property_fields() > 0) {
6099     // Construct the object field access.
6100     int descriptor = transition()->LastAdded();
6101     int index =
6102         transition()->instance_descriptors()->GetFieldIndex(descriptor) -
6103         map_->inobject_properties();
6104     PropertyDetails details =
6105         transition()->instance_descriptors()->GetDetails(descriptor);
6106     Representation representation = details.representation();
6107     access_ = HObjectAccess::ForField(map_, index, representation, name_);
6108
6109     // Load field map for heap objects.
6110     return LoadFieldMaps(transition());
6111   }
6112   return false;
6113 }
6114
6115
6116 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic(
6117     SmallMapList* maps) {
6118   DCHECK(map_.is_identical_to(maps->first()));
6119   if (!CanAccessMonomorphic()) return false;
6120   STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
6121   if (maps->length() > kMaxLoadPolymorphism) return false;
6122
6123   HObjectAccess access = HObjectAccess::ForMap();  // bogus default
6124   if (GetJSObjectFieldAccess(&access)) {
6125     for (int i = 1; i < maps->length(); ++i) {
6126       PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
6127       HObjectAccess test_access = HObjectAccess::ForMap();  // bogus default
6128       if (!test_info.GetJSObjectFieldAccess(&test_access)) return false;
6129       if (!access.Equals(test_access)) return false;
6130     }
6131     return true;
6132   }
6133
6134   // Currently only handle numbers as a polymorphic case.
6135   // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
6136   // instruction.
6137   if (IsNumberType()) return false;
6138
6139   // Multiple maps cannot transition to the same target map.
6140   DCHECK(!IsLoad() || !IsTransition());
6141   if (IsTransition() && maps->length() > 1) return false;
6142
6143   for (int i = 1; i < maps->length(); ++i) {
6144     PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
6145     if (!test_info.IsCompatible(this)) return false;
6146   }
6147
6148   return true;
6149 }
6150
6151
6152 Handle<Map> HOptimizedGraphBuilder::PropertyAccessInfo::map() {
6153   JSFunction* ctor = IC::GetRootConstructor(
6154       *map_, current_info()->closure()->context()->native_context());
6155   if (ctor != NULL) return handle(ctor->initial_map());
6156   return map_;
6157 }
6158
6159
6160 static bool NeedsWrapping(Handle<Map> map, Handle<JSFunction> target) {
6161   return !map->IsJSObjectMap() &&
6162          is_sloppy(target->shared()->language_mode()) &&
6163          !target->shared()->native();
6164 }
6165
6166
6167 bool HOptimizedGraphBuilder::PropertyAccessInfo::NeedsWrappingFor(
6168     Handle<JSFunction> target) const {
6169   return NeedsWrapping(map_, target);
6170 }
6171
6172
6173 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess(
6174     PropertyAccessInfo* info,
6175     HValue* object,
6176     HValue* checked_object,
6177     HValue* value,
6178     BailoutId ast_id,
6179     BailoutId return_id,
6180     bool can_inline_accessor) {
6181
6182   HObjectAccess access = HObjectAccess::ForMap();  // bogus default
6183   if (info->GetJSObjectFieldAccess(&access)) {
6184     DCHECK(info->IsLoad());
6185     return New<HLoadNamedField>(object, checked_object, access);
6186   }
6187
6188   if (info->name().is_identical_to(isolate()->factory()->prototype_string()) &&
6189       info->map()->function_with_prototype()) {
6190     DCHECK(!info->map()->has_non_instance_prototype());
6191     return New<HLoadFunctionPrototype>(checked_object);
6192   }
6193
6194   HValue* checked_holder = checked_object;
6195   if (info->has_holder()) {
6196     Handle<JSObject> prototype(JSObject::cast(info->map()->prototype()));
6197     checked_holder = BuildCheckPrototypeMaps(prototype, info->holder());
6198   }
6199
6200   if (!info->IsFound()) {
6201     DCHECK(info->IsLoad());
6202     return graph()->GetConstantUndefined();
6203   }
6204
6205   if (info->IsData()) {
6206     if (info->IsLoad()) {
6207       return BuildLoadNamedField(info, checked_holder);
6208     } else {
6209       return BuildStoreNamedField(info, checked_object, value);
6210     }
6211   }
6212
6213   if (info->IsTransition()) {
6214     DCHECK(!info->IsLoad());
6215     return BuildStoreNamedField(info, checked_object, value);
6216   }
6217
6218   if (info->IsAccessorConstant()) {
6219     Push(checked_object);
6220     int argument_count = 1;
6221     if (!info->IsLoad()) {
6222       argument_count = 2;
6223       Push(value);
6224     }
6225
6226     if (info->NeedsWrappingFor(info->accessor())) {
6227       HValue* function = Add<HConstant>(info->accessor());
6228       PushArgumentsFromEnvironment(argument_count);
6229       return New<HCallFunction>(function, argument_count, WRAP_AND_CALL);
6230     } else if (FLAG_inline_accessors && can_inline_accessor) {
6231       bool success = info->IsLoad()
6232           ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id)
6233           : TryInlineSetter(
6234               info->accessor(), info->map(), ast_id, return_id, value);
6235       if (success || HasStackOverflow()) return NULL;
6236     }
6237
6238     PushArgumentsFromEnvironment(argument_count);
6239     return BuildCallConstantFunction(info->accessor(), argument_count);
6240   }
6241
6242   DCHECK(info->IsDataConstant());
6243   if (info->IsLoad()) {
6244     return New<HConstant>(info->constant());
6245   } else {
6246     return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant()));
6247   }
6248 }
6249
6250
6251 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
6252     PropertyAccessType access_type, Expression* expr, BailoutId ast_id,
6253     BailoutId return_id, HValue* object, HValue* value, SmallMapList* maps,
6254     Handle<String> name) {
6255   // Something did not match; must use a polymorphic load.
6256   int count = 0;
6257   HBasicBlock* join = NULL;
6258   HBasicBlock* number_block = NULL;
6259   bool handled_string = false;
6260
6261   bool handle_smi = false;
6262   STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
6263   int i;
6264   for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) {
6265     PropertyAccessInfo info(this, access_type, maps->at(i), name);
6266     if (info.IsStringType()) {
6267       if (handled_string) continue;
6268       handled_string = true;
6269     }
6270     if (info.CanAccessMonomorphic()) {
6271       count++;
6272       if (info.IsNumberType()) {
6273         handle_smi = true;
6274         break;
6275       }
6276     }
6277   }
6278
6279   if (i < maps->length()) {
6280     count = -1;
6281     maps->Clear();
6282   } else {
6283     count = 0;
6284   }
6285   HControlInstruction* smi_check = NULL;
6286   handled_string = false;
6287
6288   for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) {
6289     PropertyAccessInfo info(this, access_type, maps->at(i), name);
6290     if (info.IsStringType()) {
6291       if (handled_string) continue;
6292       handled_string = true;
6293     }
6294     if (!info.CanAccessMonomorphic()) continue;
6295
6296     if (count == 0) {
6297       join = graph()->CreateBasicBlock();
6298       if (handle_smi) {
6299         HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
6300         HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
6301         number_block = graph()->CreateBasicBlock();
6302         smi_check = New<HIsSmiAndBranch>(
6303             object, empty_smi_block, not_smi_block);
6304         FinishCurrentBlock(smi_check);
6305         GotoNoSimulate(empty_smi_block, number_block);
6306         set_current_block(not_smi_block);
6307       } else {
6308         BuildCheckHeapObject(object);
6309       }
6310     }
6311     ++count;
6312     HBasicBlock* if_true = graph()->CreateBasicBlock();
6313     HBasicBlock* if_false = graph()->CreateBasicBlock();
6314     HUnaryControlInstruction* compare;
6315
6316     HValue* dependency;
6317     if (info.IsNumberType()) {
6318       Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
6319       compare = New<HCompareMap>(object, heap_number_map, if_true, if_false);
6320       dependency = smi_check;
6321     } else if (info.IsStringType()) {
6322       compare = New<HIsStringAndBranch>(object, if_true, if_false);
6323       dependency = compare;
6324     } else {
6325       compare = New<HCompareMap>(object, info.map(), if_true, if_false);
6326       dependency = compare;
6327     }
6328     FinishCurrentBlock(compare);
6329
6330     if (info.IsNumberType()) {
6331       GotoNoSimulate(if_true, number_block);
6332       if_true = number_block;
6333     }
6334
6335     set_current_block(if_true);
6336
6337     HInstruction* access = BuildMonomorphicAccess(
6338         &info, object, dependency, value, ast_id,
6339         return_id, FLAG_polymorphic_inlining);
6340
6341     HValue* result = NULL;
6342     switch (access_type) {
6343       case LOAD:
6344         result = access;
6345         break;
6346       case STORE:
6347         result = value;
6348         break;
6349     }
6350
6351     if (access == NULL) {
6352       if (HasStackOverflow()) return;
6353     } else {
6354       if (!access->IsLinked()) AddInstruction(access);
6355       if (!ast_context()->IsEffect()) Push(result);
6356     }
6357
6358     if (current_block() != NULL) Goto(join);
6359     set_current_block(if_false);
6360   }
6361
6362   // Finish up.  Unconditionally deoptimize if we've handled all the maps we
6363   // know about and do not want to handle ones we've never seen.  Otherwise
6364   // use a generic IC.
6365   if (count == maps->length() && FLAG_deoptimize_uncommon_cases) {
6366     FinishExitWithHardDeoptimization(
6367         Deoptimizer::kUnknownMapInPolymorphicAccess);
6368   } else {
6369     HInstruction* instr = BuildNamedGeneric(access_type, expr, object, name,
6370                                             value);
6371     AddInstruction(instr);
6372     if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value);
6373
6374     if (join != NULL) {
6375       Goto(join);
6376     } else {
6377       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6378       if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
6379       return;
6380     }
6381   }
6382
6383   DCHECK(join != NULL);
6384   if (join->HasPredecessor()) {
6385     join->SetJoinId(ast_id);
6386     set_current_block(join);
6387     if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
6388   } else {
6389     set_current_block(NULL);
6390   }
6391 }
6392
6393
6394 static bool ComputeReceiverTypes(Expression* expr,
6395                                  HValue* receiver,
6396                                  SmallMapList** t,
6397                                  Zone* zone) {
6398   SmallMapList* maps = expr->GetReceiverTypes();
6399   *t = maps;
6400   bool monomorphic = expr->IsMonomorphic();
6401   if (maps != NULL && receiver->HasMonomorphicJSObjectType()) {
6402     Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
6403     maps->FilterForPossibleTransitions(root_map);
6404     monomorphic = maps->length() == 1;
6405   }
6406   return monomorphic && CanInlinePropertyAccess(maps->first());
6407 }
6408
6409
6410 static bool AreStringTypes(SmallMapList* maps) {
6411   for (int i = 0; i < maps->length(); i++) {
6412     if (maps->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
6413   }
6414   return true;
6415 }
6416
6417
6418 void HOptimizedGraphBuilder::BuildStore(Expression* expr,
6419                                         Property* prop,
6420                                         BailoutId ast_id,
6421                                         BailoutId return_id,
6422                                         bool is_uninitialized) {
6423   if (!prop->key()->IsPropertyName()) {
6424     // Keyed store.
6425     HValue* value = Pop();
6426     HValue* key = Pop();
6427     HValue* object = Pop();
6428     bool has_side_effects = false;
6429     HValue* result = HandleKeyedElementAccess(
6430         object, key, value, expr, ast_id, return_id, STORE, &has_side_effects);
6431     if (has_side_effects) {
6432       if (!ast_context()->IsEffect()) Push(value);
6433       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6434       if (!ast_context()->IsEffect()) Drop(1);
6435     }
6436     if (result == NULL) return;
6437     return ast_context()->ReturnValue(value);
6438   }
6439
6440   // Named store.
6441   HValue* value = Pop();
6442   HValue* object = Pop();
6443
6444   Literal* key = prop->key()->AsLiteral();
6445   Handle<String> name = Handle<String>::cast(key->value());
6446   DCHECK(!name.is_null());
6447
6448   HInstruction* instr = BuildNamedAccess(STORE, ast_id, return_id, expr,
6449                                          object, name, value, is_uninitialized);
6450   if (instr == NULL) return;
6451
6452   if (!ast_context()->IsEffect()) Push(value);
6453   AddInstruction(instr);
6454   if (instr->HasObservableSideEffects()) {
6455     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6456   }
6457   if (!ast_context()->IsEffect()) Drop(1);
6458   return ast_context()->ReturnValue(value);
6459 }
6460
6461
6462 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
6463   Property* prop = expr->target()->AsProperty();
6464   DCHECK(prop != NULL);
6465   CHECK_ALIVE(VisitForValue(prop->obj()));
6466   if (!prop->key()->IsPropertyName()) {
6467     CHECK_ALIVE(VisitForValue(prop->key()));
6468   }
6469   CHECK_ALIVE(VisitForValue(expr->value()));
6470   BuildStore(expr, prop, expr->id(),
6471              expr->AssignmentId(), expr->IsUninitialized());
6472 }
6473
6474
6475 // Because not every expression has a position and there is not common
6476 // superclass of Assignment and CountOperation, we cannot just pass the
6477 // owning expression instead of position and ast_id separately.
6478 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
6479     Variable* var,
6480     HValue* value,
6481     BailoutId ast_id) {
6482   Handle<GlobalObject> global(current_info()->global_object());
6483
6484   // Lookup in script contexts.
6485   {
6486     Handle<ScriptContextTable> script_contexts(
6487         global->native_context()->script_context_table());
6488     ScriptContextTable::LookupResult lookup;
6489     if (ScriptContextTable::Lookup(script_contexts, var->name(), &lookup)) {
6490       if (lookup.mode == CONST) {
6491         return Bailout(kNonInitializerAssignmentToConst);
6492       }
6493       Handle<Context> script_context =
6494           ScriptContextTable::GetContext(script_contexts, lookup.context_index);
6495
6496       Handle<Object> current_value =
6497           FixedArray::get(script_context, lookup.slot_index);
6498
6499       // If the values is not the hole, it will stay initialized,
6500       // so no need to generate a check.
6501       if (*current_value == *isolate()->factory()->the_hole_value()) {
6502         return Bailout(kReferenceToUninitializedVariable);
6503       }
6504
6505       HStoreNamedField* instr = Add<HStoreNamedField>(
6506           Add<HConstant>(script_context),
6507           HObjectAccess::ForContextSlot(lookup.slot_index), value);
6508       USE(instr);
6509       DCHECK(instr->HasObservableSideEffects());
6510       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6511       return;
6512     }
6513   }
6514
6515   LookupIterator it(global, var->name(), LookupIterator::OWN_SKIP_INTERCEPTOR);
6516   GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE);
6517   if (type == kUseCell) {
6518     Handle<PropertyCell> cell = it.GetPropertyCell();
6519     PropertyCell::AddDependentCompilationInfo(cell, top_info());
6520     if (it.property_details().cell_type() == PropertyCellType::kConstant) {
6521       Handle<Object> constant(cell->value(), isolate());
6522       if (value->IsConstant()) {
6523         HConstant* c_value = HConstant::cast(value);
6524         if (!constant.is_identical_to(c_value->handle(isolate()))) {
6525           Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment,
6526                            Deoptimizer::EAGER);
6527         }
6528       } else {
6529         HValue* c_constant = Add<HConstant>(constant);
6530         IfBuilder builder(this);
6531         if (constant->IsNumber()) {
6532           builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ);
6533         } else {
6534           builder.If<HCompareObjectEqAndBranch>(value, c_constant);
6535         }
6536         builder.Then();
6537         builder.Else();
6538         Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment,
6539                          Deoptimizer::EAGER);
6540         builder.End();
6541       }
6542     }
6543     HConstant* cell_constant = Add<HConstant>(cell);
6544     HInstruction* instr = Add<HStoreNamedField>(
6545         cell_constant, HObjectAccess::ForPropertyCellValue(), value);
6546     instr->ClearChangesFlag(kInobjectFields);
6547     instr->SetChangesFlag(kGlobalVars);
6548     if (instr->HasObservableSideEffects()) {
6549       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6550     }
6551   } else {
6552     HValue* global_object = Add<HLoadNamedField>(
6553         context(), nullptr,
6554         HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
6555     HStoreNamedGeneric* instr =
6556         Add<HStoreNamedGeneric>(global_object, var->name(), value,
6557                                 function_language_mode(), PREMONOMORPHIC);
6558     USE(instr);
6559     DCHECK(instr->HasObservableSideEffects());
6560     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6561   }
6562 }
6563
6564
6565 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
6566   Expression* target = expr->target();
6567   VariableProxy* proxy = target->AsVariableProxy();
6568   Property* prop = target->AsProperty();
6569   DCHECK(proxy == NULL || prop == NULL);
6570
6571   // We have a second position recorded in the FullCodeGenerator to have
6572   // type feedback for the binary operation.
6573   BinaryOperation* operation = expr->binary_operation();
6574
6575   if (proxy != NULL) {
6576     Variable* var = proxy->var();
6577     if (var->mode() == LET)  {
6578       return Bailout(kUnsupportedLetCompoundAssignment);
6579     }
6580
6581     CHECK_ALIVE(VisitForValue(operation));
6582
6583     switch (var->location()) {
6584       case Variable::UNALLOCATED:
6585         HandleGlobalVariableAssignment(var,
6586                                        Top(),
6587                                        expr->AssignmentId());
6588         break;
6589
6590       case Variable::PARAMETER:
6591       case Variable::LOCAL:
6592         if (var->mode() == CONST_LEGACY)  {
6593           return Bailout(kUnsupportedConstCompoundAssignment);
6594         }
6595         if (var->mode() == CONST) {
6596           return Bailout(kNonInitializerAssignmentToConst);
6597         }
6598         BindIfLive(var, Top());
6599         break;
6600
6601       case Variable::CONTEXT: {
6602         // Bail out if we try to mutate a parameter value in a function
6603         // using the arguments object.  We do not (yet) correctly handle the
6604         // arguments property of the function.
6605         if (current_info()->scope()->arguments() != NULL) {
6606           // Parameters will be allocated to context slots.  We have no
6607           // direct way to detect that the variable is a parameter so we do
6608           // a linear search of the parameter variables.
6609           int count = current_info()->scope()->num_parameters();
6610           for (int i = 0; i < count; ++i) {
6611             if (var == current_info()->scope()->parameter(i)) {
6612               Bailout(kAssignmentToParameterFunctionUsesArgumentsObject);
6613             }
6614           }
6615         }
6616
6617         HStoreContextSlot::Mode mode;
6618
6619         switch (var->mode()) {
6620           case LET:
6621             mode = HStoreContextSlot::kCheckDeoptimize;
6622             break;
6623           case CONST:
6624             return Bailout(kNonInitializerAssignmentToConst);
6625           case CONST_LEGACY:
6626             return ast_context()->ReturnValue(Pop());
6627           default:
6628             mode = HStoreContextSlot::kNoCheck;
6629         }
6630
6631         HValue* context = BuildContextChainWalk(var);
6632         HStoreContextSlot* instr = Add<HStoreContextSlot>(
6633             context, var->index(), mode, Top());
6634         if (instr->HasObservableSideEffects()) {
6635           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
6636         }
6637         break;
6638       }
6639
6640       case Variable::LOOKUP:
6641         return Bailout(kCompoundAssignmentToLookupSlot);
6642     }
6643     return ast_context()->ReturnValue(Pop());
6644
6645   } else if (prop != NULL) {
6646     CHECK_ALIVE(VisitForValue(prop->obj()));
6647     HValue* object = Top();
6648     HValue* key = NULL;
6649     if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
6650       CHECK_ALIVE(VisitForValue(prop->key()));
6651       key = Top();
6652     }
6653
6654     CHECK_ALIVE(PushLoad(prop, object, key));
6655
6656     CHECK_ALIVE(VisitForValue(expr->value()));
6657     HValue* right = Pop();
6658     HValue* left = Pop();
6659
6660     Push(BuildBinaryOperation(operation, left, right, PUSH_BEFORE_SIMULATE));
6661
6662     BuildStore(expr, prop, expr->id(),
6663                expr->AssignmentId(), expr->IsUninitialized());
6664   } else {
6665     return Bailout(kInvalidLhsInCompoundAssignment);
6666   }
6667 }
6668
6669
6670 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
6671   DCHECK(!HasStackOverflow());
6672   DCHECK(current_block() != NULL);
6673   DCHECK(current_block()->HasPredecessor());
6674   VariableProxy* proxy = expr->target()->AsVariableProxy();
6675   Property* prop = expr->target()->AsProperty();
6676   DCHECK(proxy == NULL || prop == NULL);
6677
6678   if (expr->is_compound()) {
6679     HandleCompoundAssignment(expr);
6680     return;
6681   }
6682
6683   if (prop != NULL) {
6684     HandlePropertyAssignment(expr);
6685   } else if (proxy != NULL) {
6686     Variable* var = proxy->var();
6687
6688     if (var->mode() == CONST) {
6689       if (expr->op() != Token::INIT_CONST) {
6690         return Bailout(kNonInitializerAssignmentToConst);
6691       }
6692     } else if (var->mode() == CONST_LEGACY) {
6693       if (expr->op() != Token::INIT_CONST_LEGACY) {
6694         CHECK_ALIVE(VisitForValue(expr->value()));
6695         return ast_context()->ReturnValue(Pop());
6696       }
6697
6698       if (var->IsStackAllocated()) {
6699         // We insert a use of the old value to detect unsupported uses of const
6700         // variables (e.g. initialization inside a loop).
6701         HValue* old_value = environment()->Lookup(var);
6702         Add<HUseConst>(old_value);
6703       }
6704     }
6705
6706     if (proxy->IsArguments()) return Bailout(kAssignmentToArguments);
6707
6708     // Handle the assignment.
6709     switch (var->location()) {
6710       case Variable::UNALLOCATED:
6711         CHECK_ALIVE(VisitForValue(expr->value()));
6712         HandleGlobalVariableAssignment(var,
6713                                        Top(),
6714                                        expr->AssignmentId());
6715         return ast_context()->ReturnValue(Pop());
6716
6717       case Variable::PARAMETER:
6718       case Variable::LOCAL: {
6719         // Perform an initialization check for let declared variables
6720         // or parameters.
6721         if (var->mode() == LET && expr->op() == Token::ASSIGN) {
6722           HValue* env_value = environment()->Lookup(var);
6723           if (env_value == graph()->GetConstantHole()) {
6724             return Bailout(kAssignmentToLetVariableBeforeInitialization);
6725           }
6726         }
6727         // We do not allow the arguments object to occur in a context where it
6728         // may escape, but assignments to stack-allocated locals are
6729         // permitted.
6730         CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
6731         HValue* value = Pop();
6732         BindIfLive(var, value);
6733         return ast_context()->ReturnValue(value);
6734       }
6735
6736       case Variable::CONTEXT: {
6737         // Bail out if we try to mutate a parameter value in a function using
6738         // the arguments object.  We do not (yet) correctly handle the
6739         // arguments property of the function.
6740         if (current_info()->scope()->arguments() != NULL) {
6741           // Parameters will rewrite to context slots.  We have no direct way
6742           // to detect that the variable is a parameter.
6743           int count = current_info()->scope()->num_parameters();
6744           for (int i = 0; i < count; ++i) {
6745             if (var == current_info()->scope()->parameter(i)) {
6746               return Bailout(kAssignmentToParameterInArgumentsObject);
6747             }
6748           }
6749         }
6750
6751         CHECK_ALIVE(VisitForValue(expr->value()));
6752         HStoreContextSlot::Mode mode;
6753         if (expr->op() == Token::ASSIGN) {
6754           switch (var->mode()) {
6755             case LET:
6756               mode = HStoreContextSlot::kCheckDeoptimize;
6757               break;
6758             case CONST:
6759               // This case is checked statically so no need to
6760               // perform checks here
6761               UNREACHABLE();
6762             case CONST_LEGACY:
6763               return ast_context()->ReturnValue(Pop());
6764             default:
6765               mode = HStoreContextSlot::kNoCheck;
6766           }
6767         } else if (expr->op() == Token::INIT_VAR ||
6768                    expr->op() == Token::INIT_LET ||
6769                    expr->op() == Token::INIT_CONST) {
6770           mode = HStoreContextSlot::kNoCheck;
6771         } else {
6772           DCHECK(expr->op() == Token::INIT_CONST_LEGACY);
6773
6774           mode = HStoreContextSlot::kCheckIgnoreAssignment;
6775         }
6776
6777         HValue* context = BuildContextChainWalk(var);
6778         HStoreContextSlot* instr = Add<HStoreContextSlot>(
6779             context, var->index(), mode, Top());
6780         if (instr->HasObservableSideEffects()) {
6781           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
6782         }
6783         return ast_context()->ReturnValue(Pop());
6784       }
6785
6786       case Variable::LOOKUP:
6787         return Bailout(kAssignmentToLOOKUPVariable);
6788     }
6789   } else {
6790     return Bailout(kInvalidLeftHandSideInAssignment);
6791   }
6792 }
6793
6794
6795 void HOptimizedGraphBuilder::VisitYield(Yield* expr) {
6796   // Generators are not optimized, so we should never get here.
6797   UNREACHABLE();
6798 }
6799
6800
6801 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
6802   DCHECK(!HasStackOverflow());
6803   DCHECK(current_block() != NULL);
6804   DCHECK(current_block()->HasPredecessor());
6805   if (!ast_context()->IsEffect()) {
6806     // The parser turns invalid left-hand sides in assignments into throw
6807     // statements, which may not be in effect contexts. We might still try
6808     // to optimize such functions; bail out now if we do.
6809     return Bailout(kInvalidLeftHandSideInAssignment);
6810   }
6811   CHECK_ALIVE(VisitForValue(expr->exception()));
6812
6813   HValue* value = environment()->Pop();
6814   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
6815   Add<HPushArguments>(value);
6816   Add<HCallRuntime>(isolate()->factory()->empty_string(),
6817                     Runtime::FunctionForId(Runtime::kThrow), 1);
6818   Add<HSimulate>(expr->id());
6819
6820   // If the throw definitely exits the function, we can finish with a dummy
6821   // control flow at this point.  This is not the case if the throw is inside
6822   // an inlined function which may be replaced.
6823   if (call_context() == NULL) {
6824     FinishExitCurrentBlock(New<HAbnormalExit>());
6825   }
6826 }
6827
6828
6829 HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) {
6830   if (string->IsConstant()) {
6831     HConstant* c_string = HConstant::cast(string);
6832     if (c_string->HasStringValue()) {
6833       return Add<HConstant>(c_string->StringValue()->map()->instance_type());
6834     }
6835   }
6836   return Add<HLoadNamedField>(
6837       Add<HLoadNamedField>(string, nullptr, HObjectAccess::ForMap()), nullptr,
6838       HObjectAccess::ForMapInstanceType());
6839 }
6840
6841
6842 HInstruction* HGraphBuilder::AddLoadStringLength(HValue* string) {
6843   if (string->IsConstant()) {
6844     HConstant* c_string = HConstant::cast(string);
6845     if (c_string->HasStringValue()) {
6846       return Add<HConstant>(c_string->StringValue()->length());
6847     }
6848   }
6849   return Add<HLoadNamedField>(string, nullptr,
6850                               HObjectAccess::ForStringLength());
6851 }
6852
6853
6854 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric(
6855     PropertyAccessType access_type, Expression* expr, HValue* object,
6856     Handle<String> name, HValue* value, bool is_uninitialized) {
6857   if (is_uninitialized) {
6858     Add<HDeoptimize>(
6859         Deoptimizer::kInsufficientTypeFeedbackForGenericNamedAccess,
6860         Deoptimizer::SOFT);
6861   }
6862   if (access_type == LOAD) {
6863     HLoadNamedGeneric* result =
6864         New<HLoadNamedGeneric>(object, name, PREMONOMORPHIC);
6865     if (FLAG_vector_ics) {
6866       Handle<SharedFunctionInfo> current_shared =
6867           function_state()->compilation_info()->shared_info();
6868       Handle<TypeFeedbackVector> vector =
6869           handle(current_shared->feedback_vector(), isolate());
6870       FeedbackVectorICSlot slot = expr->AsProperty()->PropertyFeedbackSlot();
6871       result->SetVectorAndSlot(vector, slot);
6872     }
6873     return result;
6874   } else {
6875     return New<HStoreNamedGeneric>(object, name, value,
6876                                    function_language_mode(), PREMONOMORPHIC);
6877   }
6878 }
6879
6880
6881
6882 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric(
6883     PropertyAccessType access_type,
6884     Expression* expr,
6885     HValue* object,
6886     HValue* key,
6887     HValue* value) {
6888   if (access_type == LOAD) {
6889     HLoadKeyedGeneric* result =
6890         New<HLoadKeyedGeneric>(object, key, PREMONOMORPHIC);
6891     if (FLAG_vector_ics) {
6892       Handle<SharedFunctionInfo> current_shared =
6893           function_state()->compilation_info()->shared_info();
6894       Handle<TypeFeedbackVector> vector =
6895           handle(current_shared->feedback_vector(), isolate());
6896       FeedbackVectorICSlot slot = expr->AsProperty()->PropertyFeedbackSlot();
6897       result->SetVectorAndSlot(vector, slot);
6898     }
6899     return result;
6900   } else {
6901     return New<HStoreKeyedGeneric>(object, key, value, function_language_mode(),
6902                                    PREMONOMORPHIC);
6903   }
6904 }
6905
6906
6907 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) {
6908   // Loads from a "stock" fast holey double arrays can elide the hole check.
6909   LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
6910   if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) &&
6911       isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
6912     Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
6913     Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
6914     BuildCheckPrototypeMaps(prototype, object_prototype);
6915     load_mode = ALLOW_RETURN_HOLE;
6916     graph()->MarkDependsOnEmptyArrayProtoElements();
6917   }
6918
6919   return load_mode;
6920 }
6921
6922
6923 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
6924     HValue* object,
6925     HValue* key,
6926     HValue* val,
6927     HValue* dependency,
6928     Handle<Map> map,
6929     PropertyAccessType access_type,
6930     KeyedAccessStoreMode store_mode) {
6931   HCheckMaps* checked_object = Add<HCheckMaps>(object, map, dependency);
6932
6933   if (access_type == STORE && map->prototype()->IsJSObject()) {
6934     // monomorphic stores need a prototype chain check because shape
6935     // changes could allow callbacks on elements in the chain that
6936     // aren't compatible with monomorphic keyed stores.
6937     PrototypeIterator iter(map);
6938     JSObject* holder = NULL;
6939     while (!iter.IsAtEnd()) {
6940       holder = JSObject::cast(*PrototypeIterator::GetCurrent(iter));
6941       iter.Advance();
6942     }
6943     DCHECK(holder && holder->IsJSObject());
6944
6945     BuildCheckPrototypeMaps(handle(JSObject::cast(map->prototype())),
6946                             Handle<JSObject>(holder));
6947   }
6948
6949   LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
6950   return BuildUncheckedMonomorphicElementAccess(
6951       checked_object, key, val,
6952       map->instance_type() == JS_ARRAY_TYPE,
6953       map->elements_kind(), access_type,
6954       load_mode, store_mode);
6955 }
6956
6957
6958 static bool CanInlineElementAccess(Handle<Map> map) {
6959   return map->IsJSObjectMap() && !map->has_slow_elements_kind() &&
6960          !map->has_indexed_interceptor() && !map->is_access_check_needed();
6961 }
6962
6963
6964 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
6965     HValue* object,
6966     HValue* key,
6967     HValue* val,
6968     SmallMapList* maps) {
6969   // For polymorphic loads of similar elements kinds (i.e. all tagged or all
6970   // double), always use the "worst case" code without a transition.  This is
6971   // much faster than transitioning the elements to the worst case, trading a
6972   // HTransitionElements for a HCheckMaps, and avoiding mutation of the array.
6973   bool has_double_maps = false;
6974   bool has_smi_or_object_maps = false;
6975   bool has_js_array_access = false;
6976   bool has_non_js_array_access = false;
6977   bool has_seen_holey_elements = false;
6978   Handle<Map> most_general_consolidated_map;
6979   for (int i = 0; i < maps->length(); ++i) {
6980     Handle<Map> map = maps->at(i);
6981     if (!CanInlineElementAccess(map)) return NULL;
6982     // Don't allow mixing of JSArrays with JSObjects.
6983     if (map->instance_type() == JS_ARRAY_TYPE) {
6984       if (has_non_js_array_access) return NULL;
6985       has_js_array_access = true;
6986     } else if (has_js_array_access) {
6987       return NULL;
6988     } else {
6989       has_non_js_array_access = true;
6990     }
6991     // Don't allow mixed, incompatible elements kinds.
6992     if (map->has_fast_double_elements()) {
6993       if (has_smi_or_object_maps) return NULL;
6994       has_double_maps = true;
6995     } else if (map->has_fast_smi_or_object_elements()) {
6996       if (has_double_maps) return NULL;
6997       has_smi_or_object_maps = true;
6998     } else {
6999       return NULL;
7000     }
7001     // Remember if we've ever seen holey elements.
7002     if (IsHoleyElementsKind(map->elements_kind())) {
7003       has_seen_holey_elements = true;
7004     }
7005     // Remember the most general elements kind, the code for its load will
7006     // properly handle all of the more specific cases.
7007     if ((i == 0) || IsMoreGeneralElementsKindTransition(
7008             most_general_consolidated_map->elements_kind(),
7009             map->elements_kind())) {
7010       most_general_consolidated_map = map;
7011     }
7012   }
7013   if (!has_double_maps && !has_smi_or_object_maps) return NULL;
7014
7015   HCheckMaps* checked_object = Add<HCheckMaps>(object, maps);
7016   // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS.
7017   // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS.
7018   ElementsKind consolidated_elements_kind = has_seen_holey_elements
7019       ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind())
7020       : most_general_consolidated_map->elements_kind();
7021   HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
7022       checked_object, key, val,
7023       most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
7024       consolidated_elements_kind,
7025       LOAD, NEVER_RETURN_HOLE, STANDARD_STORE);
7026   return instr;
7027 }
7028
7029
7030 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
7031     Expression* expr,
7032     HValue* object,
7033     HValue* key,
7034     HValue* val,
7035     SmallMapList* maps,
7036     PropertyAccessType access_type,
7037     KeyedAccessStoreMode store_mode,
7038     bool* has_side_effects) {
7039   *has_side_effects = false;
7040   BuildCheckHeapObject(object);
7041
7042   if (access_type == LOAD) {
7043     HInstruction* consolidated_load =
7044         TryBuildConsolidatedElementLoad(object, key, val, maps);
7045     if (consolidated_load != NULL) {
7046       *has_side_effects |= consolidated_load->HasObservableSideEffects();
7047       return consolidated_load;
7048     }
7049   }
7050
7051   // Elements_kind transition support.
7052   MapHandleList transition_target(maps->length());
7053   // Collect possible transition targets.
7054   MapHandleList possible_transitioned_maps(maps->length());
7055   for (int i = 0; i < maps->length(); ++i) {
7056     Handle<Map> map = maps->at(i);
7057     // Loads from strings or loads with a mix of string and non-string maps
7058     // shouldn't be handled polymorphically.
7059     DCHECK(access_type != LOAD || !map->IsStringMap());
7060     ElementsKind elements_kind = map->elements_kind();
7061     if (CanInlineElementAccess(map) && IsFastElementsKind(elements_kind) &&
7062         elements_kind != GetInitialFastElementsKind()) {
7063       possible_transitioned_maps.Add(map);
7064     }
7065     if (elements_kind == SLOPPY_ARGUMENTS_ELEMENTS) {
7066       HInstruction* result = BuildKeyedGeneric(access_type, expr, object, key,
7067                                                val);
7068       *has_side_effects = result->HasObservableSideEffects();
7069       return AddInstruction(result);
7070     }
7071   }
7072   // Get transition target for each map (NULL == no transition).
7073   for (int i = 0; i < maps->length(); ++i) {
7074     Handle<Map> map = maps->at(i);
7075     Handle<Map> transitioned_map =
7076         map->FindTransitionedMap(&possible_transitioned_maps);
7077     transition_target.Add(transitioned_map);
7078   }
7079
7080   MapHandleList untransitionable_maps(maps->length());
7081   HTransitionElementsKind* transition = NULL;
7082   for (int i = 0; i < maps->length(); ++i) {
7083     Handle<Map> map = maps->at(i);
7084     DCHECK(map->IsMap());
7085     if (!transition_target.at(i).is_null()) {
7086       DCHECK(Map::IsValidElementsTransition(
7087           map->elements_kind(),
7088           transition_target.at(i)->elements_kind()));
7089       transition = Add<HTransitionElementsKind>(object, map,
7090                                                 transition_target.at(i));
7091     } else {
7092       untransitionable_maps.Add(map);
7093     }
7094   }
7095
7096   // If only one map is left after transitioning, handle this case
7097   // monomorphically.
7098   DCHECK(untransitionable_maps.length() >= 1);
7099   if (untransitionable_maps.length() == 1) {
7100     Handle<Map> untransitionable_map = untransitionable_maps[0];
7101     HInstruction* instr = NULL;
7102     if (!CanInlineElementAccess(untransitionable_map)) {
7103       instr = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key,
7104                                                val));
7105     } else {
7106       instr = BuildMonomorphicElementAccess(
7107           object, key, val, transition, untransitionable_map, access_type,
7108           store_mode);
7109     }
7110     *has_side_effects |= instr->HasObservableSideEffects();
7111     return access_type == STORE ? val : instr;
7112   }
7113
7114   HBasicBlock* join = graph()->CreateBasicBlock();
7115
7116   for (int i = 0; i < untransitionable_maps.length(); ++i) {
7117     Handle<Map> map = untransitionable_maps[i];
7118     ElementsKind elements_kind = map->elements_kind();
7119     HBasicBlock* this_map = graph()->CreateBasicBlock();
7120     HBasicBlock* other_map = graph()->CreateBasicBlock();
7121     HCompareMap* mapcompare =
7122         New<HCompareMap>(object, map, this_map, other_map);
7123     FinishCurrentBlock(mapcompare);
7124
7125     set_current_block(this_map);
7126     HInstruction* access = NULL;
7127     if (!CanInlineElementAccess(map)) {
7128       access = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key,
7129                                                 val));
7130     } else {
7131       DCHECK(IsFastElementsKind(elements_kind) ||
7132              IsExternalArrayElementsKind(elements_kind) ||
7133              IsFixedTypedArrayElementsKind(elements_kind));
7134       LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
7135       // Happily, mapcompare is a checked object.
7136       access = BuildUncheckedMonomorphicElementAccess(
7137           mapcompare, key, val,
7138           map->instance_type() == JS_ARRAY_TYPE,
7139           elements_kind, access_type,
7140           load_mode,
7141           store_mode);
7142     }
7143     *has_side_effects |= access->HasObservableSideEffects();
7144     // The caller will use has_side_effects and add a correct Simulate.
7145     access->SetFlag(HValue::kHasNoObservableSideEffects);
7146     if (access_type == LOAD) {
7147       Push(access);
7148     }
7149     NoObservableSideEffectsScope scope(this);
7150     GotoNoSimulate(join);
7151     set_current_block(other_map);
7152   }
7153
7154   // Ensure that we visited at least one map above that goes to join. This is
7155   // necessary because FinishExitWithHardDeoptimization does an AbnormalExit
7156   // rather than joining the join block. If this becomes an issue, insert a
7157   // generic access in the case length() == 0.
7158   DCHECK(join->predecessors()->length() > 0);
7159   // Deopt if none of the cases matched.
7160   NoObservableSideEffectsScope scope(this);
7161   FinishExitWithHardDeoptimization(
7162       Deoptimizer::kUnknownMapInPolymorphicElementAccess);
7163   set_current_block(join);
7164   return access_type == STORE ? val : Pop();
7165 }
7166
7167
7168 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
7169     HValue* obj, HValue* key, HValue* val, Expression* expr, BailoutId ast_id,
7170     BailoutId return_id, PropertyAccessType access_type,
7171     bool* has_side_effects) {
7172   // TODO(mvstanton): This optimization causes trouble for vector-based
7173   // KeyedLoadICs, turn it off for now.
7174   if (!FLAG_vector_ics && key->ActualValue()->IsConstant()) {
7175     Handle<Object> constant =
7176         HConstant::cast(key->ActualValue())->handle(isolate());
7177     uint32_t array_index;
7178     if (constant->IsString() &&
7179         !Handle<String>::cast(constant)->AsArrayIndex(&array_index)) {
7180       if (!constant->IsUniqueName()) {
7181         constant = isolate()->factory()->InternalizeString(
7182             Handle<String>::cast(constant));
7183       }
7184       HInstruction* instr =
7185           BuildNamedAccess(access_type, ast_id, return_id, expr, obj,
7186                            Handle<String>::cast(constant), val, false);
7187       if (instr == NULL || instr->IsLinked()) {
7188         *has_side_effects = false;
7189       } else {
7190         AddInstruction(instr);
7191         *has_side_effects = instr->HasObservableSideEffects();
7192       }
7193       return instr;
7194     }
7195   }
7196
7197   DCHECK(!expr->IsPropertyName());
7198   HInstruction* instr = NULL;
7199
7200   SmallMapList* maps;
7201   bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, zone());
7202
7203   bool force_generic = false;
7204   if (expr->GetKeyType() == PROPERTY) {
7205     // Non-Generic accesses assume that elements are being accessed, and will
7206     // deopt for non-index keys, which the IC knows will occur.
7207     // TODO(jkummerow): Consider adding proper support for property accesses.
7208     force_generic = true;
7209     monomorphic = false;
7210   } else if (access_type == STORE &&
7211              (monomorphic || (maps != NULL && !maps->is_empty()))) {
7212     // Stores can't be mono/polymorphic if their prototype chain has dictionary
7213     // elements. However a receiver map that has dictionary elements itself
7214     // should be left to normal mono/poly behavior (the other maps may benefit
7215     // from highly optimized stores).
7216     for (int i = 0; i < maps->length(); i++) {
7217       Handle<Map> current_map = maps->at(i);
7218       if (current_map->DictionaryElementsInPrototypeChainOnly()) {
7219         force_generic = true;
7220         monomorphic = false;
7221         break;
7222       }
7223     }
7224   } else if (access_type == LOAD && !monomorphic &&
7225              (maps != NULL && !maps->is_empty())) {
7226     // Polymorphic loads have to go generic if any of the maps are strings.
7227     // If some, but not all of the maps are strings, we should go generic
7228     // because polymorphic access wants to key on ElementsKind and isn't
7229     // compatible with strings.
7230     for (int i = 0; i < maps->length(); i++) {
7231       Handle<Map> current_map = maps->at(i);
7232       if (current_map->IsStringMap()) {
7233         force_generic = true;
7234         break;
7235       }
7236     }
7237   }
7238
7239   if (monomorphic) {
7240     Handle<Map> map = maps->first();
7241     if (!CanInlineElementAccess(map)) {
7242       instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key,
7243                                                val));
7244     } else {
7245       BuildCheckHeapObject(obj);
7246       instr = BuildMonomorphicElementAccess(
7247           obj, key, val, NULL, map, access_type, expr->GetStoreMode());
7248     }
7249   } else if (!force_generic && (maps != NULL && !maps->is_empty())) {
7250     return HandlePolymorphicElementAccess(expr, obj, key, val, maps,
7251                                           access_type, expr->GetStoreMode(),
7252                                           has_side_effects);
7253   } else {
7254     if (access_type == STORE) {
7255       if (expr->IsAssignment() &&
7256           expr->AsAssignment()->HasNoTypeInformation()) {
7257         Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedStore,
7258                          Deoptimizer::SOFT);
7259       }
7260     } else {
7261       if (expr->AsProperty()->HasNoTypeInformation()) {
7262         Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedLoad,
7263                          Deoptimizer::SOFT);
7264       }
7265     }
7266     instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key, val));
7267   }
7268   *has_side_effects = instr->HasObservableSideEffects();
7269   return instr;
7270 }
7271
7272
7273 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() {
7274   // Outermost function already has arguments on the stack.
7275   if (function_state()->outer() == NULL) return;
7276
7277   if (function_state()->arguments_pushed()) return;
7278
7279   // Push arguments when entering inlined function.
7280   HEnterInlined* entry = function_state()->entry();
7281   entry->set_arguments_pushed();
7282
7283   HArgumentsObject* arguments = entry->arguments_object();
7284   const ZoneList<HValue*>* arguments_values = arguments->arguments_values();
7285
7286   HInstruction* insert_after = entry;
7287   for (int i = 0; i < arguments_values->length(); i++) {
7288     HValue* argument = arguments_values->at(i);
7289     HInstruction* push_argument = New<HPushArguments>(argument);
7290     push_argument->InsertAfter(insert_after);
7291     insert_after = push_argument;
7292   }
7293
7294   HArgumentsElements* arguments_elements = New<HArgumentsElements>(true);
7295   arguments_elements->ClearFlag(HValue::kUseGVN);
7296   arguments_elements->InsertAfter(insert_after);
7297   function_state()->set_arguments_elements(arguments_elements);
7298 }
7299
7300
7301 bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) {
7302   VariableProxy* proxy = expr->obj()->AsVariableProxy();
7303   if (proxy == NULL) return false;
7304   if (!proxy->var()->IsStackAllocated()) return false;
7305   if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
7306     return false;
7307   }
7308
7309   HInstruction* result = NULL;
7310   if (expr->key()->IsPropertyName()) {
7311     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
7312     if (!String::Equals(name, isolate()->factory()->length_string())) {
7313       return false;
7314     }
7315
7316     if (function_state()->outer() == NULL) {
7317       HInstruction* elements = Add<HArgumentsElements>(false);
7318       result = New<HArgumentsLength>(elements);
7319     } else {
7320       // Number of arguments without receiver.
7321       int argument_count = environment()->
7322           arguments_environment()->parameter_count() - 1;
7323       result = New<HConstant>(argument_count);
7324     }
7325   } else {
7326     Push(graph()->GetArgumentsObject());
7327     CHECK_ALIVE_OR_RETURN(VisitForValue(expr->key()), true);
7328     HValue* key = Pop();
7329     Drop(1);  // Arguments object.
7330     if (function_state()->outer() == NULL) {
7331       HInstruction* elements = Add<HArgumentsElements>(false);
7332       HInstruction* length = Add<HArgumentsLength>(elements);
7333       HInstruction* checked_key = Add<HBoundsCheck>(key, length);
7334       result = New<HAccessArgumentsAt>(elements, length, checked_key);
7335     } else {
7336       EnsureArgumentsArePushedForAccess();
7337
7338       // Number of arguments without receiver.
7339       HInstruction* elements = function_state()->arguments_elements();
7340       int argument_count = environment()->
7341           arguments_environment()->parameter_count() - 1;
7342       HInstruction* length = Add<HConstant>(argument_count);
7343       HInstruction* checked_key = Add<HBoundsCheck>(key, length);
7344       result = New<HAccessArgumentsAt>(elements, length, checked_key);
7345     }
7346   }
7347   ast_context()->ReturnInstruction(result, expr->id());
7348   return true;
7349 }
7350
7351
7352 HInstruction* HOptimizedGraphBuilder::BuildNamedAccess(
7353     PropertyAccessType access,
7354     BailoutId ast_id,
7355     BailoutId return_id,
7356     Expression* expr,
7357     HValue* object,
7358     Handle<String> name,
7359     HValue* value,
7360     bool is_uninitialized) {
7361   SmallMapList* maps;
7362   ComputeReceiverTypes(expr, object, &maps, zone());
7363   DCHECK(maps != NULL);
7364
7365   if (maps->length() > 0) {
7366     PropertyAccessInfo info(this, access, maps->first(), name);
7367     if (!info.CanAccessAsMonomorphic(maps)) {
7368       HandlePolymorphicNamedFieldAccess(access, expr, ast_id, return_id, object,
7369                                         value, maps, name);
7370       return NULL;
7371     }
7372
7373     HValue* checked_object;
7374     // Type::Number() is only supported by polymorphic load/call handling.
7375     DCHECK(!info.IsNumberType());
7376     BuildCheckHeapObject(object);
7377     if (AreStringTypes(maps)) {
7378       checked_object =
7379           Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
7380     } else {
7381       checked_object = Add<HCheckMaps>(object, maps);
7382     }
7383     return BuildMonomorphicAccess(
7384         &info, object, checked_object, value, ast_id, return_id);
7385   }
7386
7387   return BuildNamedGeneric(access, expr, object, name, value, is_uninitialized);
7388 }
7389
7390
7391 void HOptimizedGraphBuilder::PushLoad(Property* expr,
7392                                       HValue* object,
7393                                       HValue* key) {
7394   ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
7395   Push(object);
7396   if (key != NULL) Push(key);
7397   BuildLoad(expr, expr->LoadId());
7398 }
7399
7400
7401 void HOptimizedGraphBuilder::BuildLoad(Property* expr,
7402                                        BailoutId ast_id) {
7403   HInstruction* instr = NULL;
7404   if (expr->IsStringAccess()) {
7405     HValue* index = Pop();
7406     HValue* string = Pop();
7407     HInstruction* char_code = BuildStringCharCodeAt(string, index);
7408     AddInstruction(char_code);
7409     instr = NewUncasted<HStringCharFromCode>(char_code);
7410
7411   } else if (expr->key()->IsPropertyName()) {
7412     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
7413     HValue* object = Pop();
7414
7415     instr = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr,
7416                              object, name, NULL, expr->IsUninitialized());
7417     if (instr == NULL) return;
7418     if (instr->IsLinked()) return ast_context()->ReturnValue(instr);
7419
7420   } else {
7421     HValue* key = Pop();
7422     HValue* obj = Pop();
7423
7424     bool has_side_effects = false;
7425     HValue* load = HandleKeyedElementAccess(
7426         obj, key, NULL, expr, ast_id, expr->LoadId(), LOAD, &has_side_effects);
7427     if (has_side_effects) {
7428       if (ast_context()->IsEffect()) {
7429         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
7430       } else {
7431         Push(load);
7432         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
7433         Drop(1);
7434       }
7435     }
7436     if (load == NULL) return;
7437     return ast_context()->ReturnValue(load);
7438   }
7439   return ast_context()->ReturnInstruction(instr, ast_id);
7440 }
7441
7442
7443 void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
7444   DCHECK(!HasStackOverflow());
7445   DCHECK(current_block() != NULL);
7446   DCHECK(current_block()->HasPredecessor());
7447
7448   if (TryArgumentsAccess(expr)) return;
7449
7450   CHECK_ALIVE(VisitForValue(expr->obj()));
7451   if (!expr->key()->IsPropertyName() || expr->IsStringAccess()) {
7452     CHECK_ALIVE(VisitForValue(expr->key()));
7453   }
7454
7455   BuildLoad(expr, expr->id());
7456 }
7457
7458
7459 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant) {
7460   HCheckMaps* check = Add<HCheckMaps>(
7461       Add<HConstant>(constant), handle(constant->map()));
7462   check->ClearDependsOnFlag(kElementsKind);
7463   return check;
7464 }
7465
7466
7467 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
7468                                                      Handle<JSObject> holder) {
7469   PrototypeIterator iter(isolate(), prototype,
7470                          PrototypeIterator::START_AT_RECEIVER);
7471   while (holder.is_null() ||
7472          !PrototypeIterator::GetCurrent(iter).is_identical_to(holder)) {
7473     BuildConstantMapCheck(
7474         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
7475     iter.Advance();
7476     if (iter.IsAtEnd()) {
7477       return NULL;
7478     }
7479   }
7480   return BuildConstantMapCheck(
7481       Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
7482 }
7483
7484
7485 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
7486                                                    Handle<Map> receiver_map) {
7487   if (!holder.is_null()) {
7488     Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
7489     BuildCheckPrototypeMaps(prototype, holder);
7490   }
7491 }
7492
7493
7494 HInstruction* HOptimizedGraphBuilder::NewPlainFunctionCall(
7495     HValue* fun, int argument_count, bool pass_argument_count) {
7496   return New<HCallJSFunction>(fun, argument_count, pass_argument_count);
7497 }
7498
7499
7500 HInstruction* HOptimizedGraphBuilder::NewArgumentAdaptorCall(
7501     HValue* fun, HValue* context,
7502     int argument_count, HValue* expected_param_count) {
7503   ArgumentAdaptorDescriptor descriptor(isolate());
7504   HValue* arity = Add<HConstant>(argument_count - 1);
7505
7506   HValue* op_vals[] = { context, fun, arity, expected_param_count };
7507
7508   Handle<Code> adaptor =
7509       isolate()->builtins()->ArgumentsAdaptorTrampoline();
7510   HConstant* adaptor_value = Add<HConstant>(adaptor);
7511
7512   return New<HCallWithDescriptor>(
7513       adaptor_value, argument_count, descriptor,
7514       Vector<HValue*>(op_vals, descriptor.GetEnvironmentLength()));
7515 }
7516
7517
7518 HInstruction* HOptimizedGraphBuilder::BuildCallConstantFunction(
7519     Handle<JSFunction> jsfun, int argument_count) {
7520   HValue* target = Add<HConstant>(jsfun);
7521   // For constant functions, we try to avoid calling the
7522   // argument adaptor and instead call the function directly
7523   int formal_parameter_count =
7524       jsfun->shared()->internal_formal_parameter_count();
7525   bool dont_adapt_arguments =
7526       (formal_parameter_count ==
7527        SharedFunctionInfo::kDontAdaptArgumentsSentinel);
7528   int arity = argument_count - 1;
7529   bool can_invoke_directly =
7530       dont_adapt_arguments || formal_parameter_count == arity;
7531   if (can_invoke_directly) {
7532     if (jsfun.is_identical_to(current_info()->closure())) {
7533       graph()->MarkRecursive();
7534     }
7535     return NewPlainFunctionCall(target, argument_count, dont_adapt_arguments);
7536   } else {
7537     HValue* param_count_value = Add<HConstant>(formal_parameter_count);
7538     HValue* context = Add<HLoadNamedField>(
7539         target, nullptr, HObjectAccess::ForFunctionContextPointer());
7540     return NewArgumentAdaptorCall(target, context,
7541         argument_count, param_count_value);
7542   }
7543   UNREACHABLE();
7544   return NULL;
7545 }
7546
7547
7548 class FunctionSorter {
7549  public:
7550   explicit FunctionSorter(int index = 0, int ticks = 0, int size = 0)
7551       : index_(index), ticks_(ticks), size_(size) {}
7552
7553   int index() const { return index_; }
7554   int ticks() const { return ticks_; }
7555   int size() const { return size_; }
7556
7557  private:
7558   int index_;
7559   int ticks_;
7560   int size_;
7561 };
7562
7563
7564 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) {
7565   int diff = lhs.ticks() - rhs.ticks();
7566   if (diff != 0) return diff > 0;
7567   return lhs.size() < rhs.size();
7568 }
7569
7570
7571 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
7572                                                         HValue* receiver,
7573                                                         SmallMapList* maps,
7574                                                         Handle<String> name) {
7575   int argument_count = expr->arguments()->length() + 1;  // Includes receiver.
7576   FunctionSorter order[kMaxCallPolymorphism];
7577
7578   bool handle_smi = false;
7579   bool handled_string = false;
7580   int ordered_functions = 0;
7581
7582   int i;
7583   for (i = 0; i < maps->length() && ordered_functions < kMaxCallPolymorphism;
7584        ++i) {
7585     PropertyAccessInfo info(this, LOAD, maps->at(i), name);
7586     if (info.CanAccessMonomorphic() && info.IsDataConstant() &&
7587         info.constant()->IsJSFunction()) {
7588       if (info.IsStringType()) {
7589         if (handled_string) continue;
7590         handled_string = true;
7591       }
7592       Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
7593       if (info.IsNumberType()) {
7594         handle_smi = true;
7595       }
7596       expr->set_target(target);
7597       order[ordered_functions++] = FunctionSorter(
7598           i, target->shared()->profiler_ticks(), InliningAstSize(target));
7599     }
7600   }
7601
7602   std::sort(order, order + ordered_functions);
7603
7604   if (i < maps->length()) {
7605     maps->Clear();
7606     ordered_functions = -1;
7607   }
7608
7609   HBasicBlock* number_block = NULL;
7610   HBasicBlock* join = NULL;
7611   handled_string = false;
7612   int count = 0;
7613
7614   for (int fn = 0; fn < ordered_functions; ++fn) {
7615     int i = order[fn].index();
7616     PropertyAccessInfo info(this, LOAD, maps->at(i), name);
7617     if (info.IsStringType()) {
7618       if (handled_string) continue;
7619       handled_string = true;
7620     }
7621     // Reloads the target.
7622     info.CanAccessMonomorphic();
7623     Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
7624
7625     expr->set_target(target);
7626     if (count == 0) {
7627       // Only needed once.
7628       join = graph()->CreateBasicBlock();
7629       if (handle_smi) {
7630         HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
7631         HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
7632         number_block = graph()->CreateBasicBlock();
7633         FinishCurrentBlock(New<HIsSmiAndBranch>(
7634                 receiver, empty_smi_block, not_smi_block));
7635         GotoNoSimulate(empty_smi_block, number_block);
7636         set_current_block(not_smi_block);
7637       } else {
7638         BuildCheckHeapObject(receiver);
7639       }
7640     }
7641     ++count;
7642     HBasicBlock* if_true = graph()->CreateBasicBlock();
7643     HBasicBlock* if_false = graph()->CreateBasicBlock();
7644     HUnaryControlInstruction* compare;
7645
7646     Handle<Map> map = info.map();
7647     if (info.IsNumberType()) {
7648       Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
7649       compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
7650     } else if (info.IsStringType()) {
7651       compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
7652     } else {
7653       compare = New<HCompareMap>(receiver, map, if_true, if_false);
7654     }
7655     FinishCurrentBlock(compare);
7656
7657     if (info.IsNumberType()) {
7658       GotoNoSimulate(if_true, number_block);
7659       if_true = number_block;
7660     }
7661
7662     set_current_block(if_true);
7663
7664     AddCheckPrototypeMaps(info.holder(), map);
7665
7666     HValue* function = Add<HConstant>(expr->target());
7667     environment()->SetExpressionStackAt(0, function);
7668     Push(receiver);
7669     CHECK_ALIVE(VisitExpressions(expr->arguments()));
7670     bool needs_wrapping = info.NeedsWrappingFor(target);
7671     bool try_inline = FLAG_polymorphic_inlining && !needs_wrapping;
7672     if (FLAG_trace_inlining && try_inline) {
7673       Handle<JSFunction> caller = current_info()->closure();
7674       SmartArrayPointer<char> caller_name =
7675           caller->shared()->DebugName()->ToCString();
7676       PrintF("Trying to inline the polymorphic call to %s from %s\n",
7677              name->ToCString().get(),
7678              caller_name.get());
7679     }
7680     if (try_inline && TryInlineCall(expr)) {
7681       // Trying to inline will signal that we should bailout from the
7682       // entire compilation by setting stack overflow on the visitor.
7683       if (HasStackOverflow()) return;
7684     } else {
7685       // Since HWrapReceiver currently cannot actually wrap numbers and strings,
7686       // use the regular CallFunctionStub for method calls to wrap the receiver.
7687       // TODO(verwaest): Support creation of value wrappers directly in
7688       // HWrapReceiver.
7689       HInstruction* call = needs_wrapping
7690           ? NewUncasted<HCallFunction>(
7691               function, argument_count, WRAP_AND_CALL)
7692           : BuildCallConstantFunction(target, argument_count);
7693       PushArgumentsFromEnvironment(argument_count);
7694       AddInstruction(call);
7695       Drop(1);  // Drop the function.
7696       if (!ast_context()->IsEffect()) Push(call);
7697     }
7698
7699     if (current_block() != NULL) Goto(join);
7700     set_current_block(if_false);
7701   }
7702
7703   // Finish up.  Unconditionally deoptimize if we've handled all the maps we
7704   // know about and do not want to handle ones we've never seen.  Otherwise
7705   // use a generic IC.
7706   if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) {
7707     FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall);
7708   } else {
7709     Property* prop = expr->expression()->AsProperty();
7710     HInstruction* function = BuildNamedGeneric(
7711         LOAD, prop, receiver, name, NULL, prop->IsUninitialized());
7712     AddInstruction(function);
7713     Push(function);
7714     AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
7715
7716     environment()->SetExpressionStackAt(1, function);
7717     environment()->SetExpressionStackAt(0, receiver);
7718     CHECK_ALIVE(VisitExpressions(expr->arguments()));
7719
7720     CallFunctionFlags flags = receiver->type().IsJSObject()
7721         ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD;
7722     HInstruction* call = New<HCallFunction>(
7723         function, argument_count, flags);
7724
7725     PushArgumentsFromEnvironment(argument_count);
7726
7727     Drop(1);  // Function.
7728
7729     if (join != NULL) {
7730       AddInstruction(call);
7731       if (!ast_context()->IsEffect()) Push(call);
7732       Goto(join);
7733     } else {
7734       return ast_context()->ReturnInstruction(call, expr->id());
7735     }
7736   }
7737
7738   // We assume that control flow is always live after an expression.  So
7739   // even without predecessors to the join block, we set it as the exit
7740   // block and continue by adding instructions there.
7741   DCHECK(join != NULL);
7742   if (join->HasPredecessor()) {
7743     set_current_block(join);
7744     join->SetJoinId(expr->id());
7745     if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
7746   } else {
7747     set_current_block(NULL);
7748   }
7749 }
7750
7751
7752 void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target,
7753                                          Handle<JSFunction> caller,
7754                                          const char* reason) {
7755   if (FLAG_trace_inlining) {
7756     SmartArrayPointer<char> target_name =
7757         target->shared()->DebugName()->ToCString();
7758     SmartArrayPointer<char> caller_name =
7759         caller->shared()->DebugName()->ToCString();
7760     if (reason == NULL) {
7761       PrintF("Inlined %s called from %s.\n", target_name.get(),
7762              caller_name.get());
7763     } else {
7764       PrintF("Did not inline %s called from %s (%s).\n",
7765              target_name.get(), caller_name.get(), reason);
7766     }
7767   }
7768 }
7769
7770
7771 static const int kNotInlinable = 1000000000;
7772
7773
7774 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) {
7775   if (!FLAG_use_inlining) return kNotInlinable;
7776
7777   // Precondition: call is monomorphic and we have found a target with the
7778   // appropriate arity.
7779   Handle<JSFunction> caller = current_info()->closure();
7780   Handle<SharedFunctionInfo> target_shared(target->shared());
7781
7782   // Always inline builtins marked for inlining.
7783   if (target->IsBuiltin()) {
7784     return target_shared->inline_builtin() ? 0 : kNotInlinable;
7785   }
7786
7787   if (target_shared->IsApiFunction()) {
7788     TraceInline(target, caller, "target is api function");
7789     return kNotInlinable;
7790   }
7791
7792   // Do a quick check on source code length to avoid parsing large
7793   // inlining candidates.
7794   if (target_shared->SourceSize() >
7795       Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) {
7796     TraceInline(target, caller, "target text too big");
7797     return kNotInlinable;
7798   }
7799
7800   // Target must be inlineable.
7801   if (!target_shared->IsInlineable()) {
7802     TraceInline(target, caller, "target not inlineable");
7803     return kNotInlinable;
7804   }
7805   if (target_shared->disable_optimization_reason() != kNoReason) {
7806     TraceInline(target, caller, "target contains unsupported syntax [early]");
7807     return kNotInlinable;
7808   }
7809
7810   int nodes_added = target_shared->ast_node_count();
7811   return nodes_added;
7812 }
7813
7814
7815 bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
7816                                        int arguments_count,
7817                                        HValue* implicit_return_value,
7818                                        BailoutId ast_id, BailoutId return_id,
7819                                        InliningKind inlining_kind) {
7820   if (target->context()->native_context() !=
7821       top_info()->closure()->context()->native_context()) {
7822     return false;
7823   }
7824   int nodes_added = InliningAstSize(target);
7825   if (nodes_added == kNotInlinable) return false;
7826
7827   Handle<JSFunction> caller = current_info()->closure();
7828
7829   if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
7830     TraceInline(target, caller, "target AST is too large [early]");
7831     return false;
7832   }
7833
7834   // Don't inline deeper than the maximum number of inlining levels.
7835   HEnvironment* env = environment();
7836   int current_level = 1;
7837   while (env->outer() != NULL) {
7838     if (current_level == FLAG_max_inlining_levels) {
7839       TraceInline(target, caller, "inline depth limit reached");
7840       return false;
7841     }
7842     if (env->outer()->frame_type() == JS_FUNCTION) {
7843       current_level++;
7844     }
7845     env = env->outer();
7846   }
7847
7848   // Don't inline recursive functions.
7849   for (FunctionState* state = function_state();
7850        state != NULL;
7851        state = state->outer()) {
7852     if (*state->compilation_info()->closure() == *target) {
7853       TraceInline(target, caller, "target is recursive");
7854       return false;
7855     }
7856   }
7857
7858   // We don't want to add more than a certain number of nodes from inlining.
7859   // Always inline small methods (<= 10 nodes).
7860   if (inlined_count_ > Min(FLAG_max_inlined_nodes_cumulative,
7861                            kUnlimitedMaxInlinedNodesCumulative)) {
7862     TraceInline(target, caller, "cumulative AST node limit reached");
7863     return false;
7864   }
7865
7866   // Parse and allocate variables.
7867   // Use the same AstValueFactory for creating strings in the sub-compilation
7868   // step, but don't transfer ownership to target_info.
7869   ParseInfo parse_info(zone(), target);
7870   parse_info.set_ast_value_factory(
7871       top_info()->parse_info()->ast_value_factory());
7872   parse_info.set_ast_value_factory_owned(false);
7873
7874   CompilationInfo target_info(&parse_info);
7875   Handle<SharedFunctionInfo> target_shared(target->shared());
7876   if (!Compiler::ParseAndAnalyze(target_info.parse_info())) {
7877     if (target_info.isolate()->has_pending_exception()) {
7878       // Parse or scope error, never optimize this function.
7879       SetStackOverflow();
7880       target_shared->DisableOptimization(kParseScopeError);
7881     }
7882     TraceInline(target, caller, "parse failure");
7883     return false;
7884   }
7885
7886   if (target_info.scope()->num_heap_slots() > 0) {
7887     TraceInline(target, caller, "target has context-allocated variables");
7888     return false;
7889   }
7890   FunctionLiteral* function = target_info.function();
7891
7892   // The following conditions must be checked again after re-parsing, because
7893   // earlier the information might not have been complete due to lazy parsing.
7894   nodes_added = function->ast_node_count();
7895   if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
7896     TraceInline(target, caller, "target AST is too large [late]");
7897     return false;
7898   }
7899   if (function->dont_optimize()) {
7900     TraceInline(target, caller, "target contains unsupported syntax [late]");
7901     return false;
7902   }
7903
7904   // If the function uses the arguments object check that inlining of functions
7905   // with arguments object is enabled and the arguments-variable is
7906   // stack allocated.
7907   if (function->scope()->arguments() != NULL) {
7908     if (!FLAG_inline_arguments) {
7909       TraceInline(target, caller, "target uses arguments object");
7910       return false;
7911     }
7912   }
7913
7914   // All declarations must be inlineable.
7915   ZoneList<Declaration*>* decls = target_info.scope()->declarations();
7916   int decl_count = decls->length();
7917   for (int i = 0; i < decl_count; ++i) {
7918     if (!decls->at(i)->IsInlineable()) {
7919       TraceInline(target, caller, "target has non-trivial declaration");
7920       return false;
7921     }
7922   }
7923
7924   // Generate the deoptimization data for the unoptimized version of
7925   // the target function if we don't already have it.
7926   if (!Compiler::EnsureDeoptimizationSupport(&target_info)) {
7927     TraceInline(target, caller, "could not generate deoptimization info");
7928     return false;
7929   }
7930
7931   // ----------------------------------------------------------------
7932   // After this point, we've made a decision to inline this function (so
7933   // TryInline should always return true).
7934
7935   // Type-check the inlined function.
7936   DCHECK(target_shared->has_deoptimization_support());
7937   AstTyper::Run(&target_info);
7938
7939   int inlining_id = 0;
7940   if (top_info()->is_tracking_positions()) {
7941     inlining_id = top_info()->TraceInlinedFunction(
7942         target_shared, source_position(), function_state()->inlining_id());
7943   }
7944
7945   // Save the pending call context. Set up new one for the inlined function.
7946   // The function state is new-allocated because we need to delete it
7947   // in two different places.
7948   FunctionState* target_state =
7949       new FunctionState(this, &target_info, inlining_kind, inlining_id);
7950
7951   HConstant* undefined = graph()->GetConstantUndefined();
7952
7953   HEnvironment* inner_env =
7954       environment()->CopyForInlining(target,
7955                                      arguments_count,
7956                                      function,
7957                                      undefined,
7958                                      function_state()->inlining_kind());
7959
7960   HConstant* context = Add<HConstant>(Handle<Context>(target->context()));
7961   inner_env->BindContext(context);
7962
7963   // Create a dematerialized arguments object for the function, also copy the
7964   // current arguments values to use them for materialization.
7965   HEnvironment* arguments_env = inner_env->arguments_environment();
7966   int parameter_count = arguments_env->parameter_count();
7967   HArgumentsObject* arguments_object = Add<HArgumentsObject>(parameter_count);
7968   for (int i = 0; i < parameter_count; i++) {
7969     arguments_object->AddArgument(arguments_env->Lookup(i), zone());
7970   }
7971
7972   // If the function uses arguments object then bind bind one.
7973   if (function->scope()->arguments() != NULL) {
7974     DCHECK(function->scope()->arguments()->IsStackAllocated());
7975     inner_env->Bind(function->scope()->arguments(), arguments_object);
7976   }
7977
7978   // Capture the state before invoking the inlined function for deopt in the
7979   // inlined function. This simulate has no bailout-id since it's not directly
7980   // reachable for deopt, and is only used to capture the state. If the simulate
7981   // becomes reachable by merging, the ast id of the simulate merged into it is
7982   // adopted.
7983   Add<HSimulate>(BailoutId::None());
7984
7985   current_block()->UpdateEnvironment(inner_env);
7986   Scope* saved_scope = scope();
7987   set_scope(target_info.scope());
7988   HEnterInlined* enter_inlined =
7989       Add<HEnterInlined>(return_id, target, context, arguments_count, function,
7990                          function_state()->inlining_kind(),
7991                          function->scope()->arguments(), arguments_object);
7992   if (top_info()->is_tracking_positions()) {
7993     enter_inlined->set_inlining_id(inlining_id);
7994   }
7995   function_state()->set_entry(enter_inlined);
7996
7997   VisitDeclarations(target_info.scope()->declarations());
7998   VisitStatements(function->body());
7999   set_scope(saved_scope);
8000   if (HasStackOverflow()) {
8001     // Bail out if the inline function did, as we cannot residualize a call
8002     // instead, but do not disable optimization for the outer function.
8003     TraceInline(target, caller, "inline graph construction failed");
8004     target_shared->DisableOptimization(kInliningBailedOut);
8005     current_info()->RetryOptimization(kInliningBailedOut);
8006     delete target_state;
8007     return true;
8008   }
8009
8010   // Update inlined nodes count.
8011   inlined_count_ += nodes_added;
8012
8013   Handle<Code> unoptimized_code(target_shared->code());
8014   DCHECK(unoptimized_code->kind() == Code::FUNCTION);
8015   Handle<TypeFeedbackInfo> type_info(
8016       TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
8017   graph()->update_type_change_checksum(type_info->own_type_change_checksum());
8018
8019   TraceInline(target, caller, NULL);
8020
8021   if (current_block() != NULL) {
8022     FunctionState* state = function_state();
8023     if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
8024       // Falling off the end of an inlined construct call. In a test context the
8025       // return value will always evaluate to true, in a value context the
8026       // return value is the newly allocated receiver.
8027       if (call_context()->IsTest()) {
8028         Goto(inlined_test_context()->if_true(), state);
8029       } else if (call_context()->IsEffect()) {
8030         Goto(function_return(), state);
8031       } else {
8032         DCHECK(call_context()->IsValue());
8033         AddLeaveInlined(implicit_return_value, state);
8034       }
8035     } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
8036       // Falling off the end of an inlined setter call. The returned value is
8037       // never used, the value of an assignment is always the value of the RHS
8038       // of the assignment.
8039       if (call_context()->IsTest()) {
8040         inlined_test_context()->ReturnValue(implicit_return_value);
8041       } else if (call_context()->IsEffect()) {
8042         Goto(function_return(), state);
8043       } else {
8044         DCHECK(call_context()->IsValue());
8045         AddLeaveInlined(implicit_return_value, state);
8046       }
8047     } else {
8048       // Falling off the end of a normal inlined function. This basically means
8049       // returning undefined.
8050       if (call_context()->IsTest()) {
8051         Goto(inlined_test_context()->if_false(), state);
8052       } else if (call_context()->IsEffect()) {
8053         Goto(function_return(), state);
8054       } else {
8055         DCHECK(call_context()->IsValue());
8056         AddLeaveInlined(undefined, state);
8057       }
8058     }
8059   }
8060
8061   // Fix up the function exits.
8062   if (inlined_test_context() != NULL) {
8063     HBasicBlock* if_true = inlined_test_context()->if_true();
8064     HBasicBlock* if_false = inlined_test_context()->if_false();
8065
8066     HEnterInlined* entry = function_state()->entry();
8067
8068     // Pop the return test context from the expression context stack.
8069     DCHECK(ast_context() == inlined_test_context());
8070     ClearInlinedTestContext();
8071     delete target_state;
8072
8073     // Forward to the real test context.
8074     if (if_true->HasPredecessor()) {
8075       entry->RegisterReturnTarget(if_true, zone());
8076       if_true->SetJoinId(ast_id);
8077       HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
8078       Goto(if_true, true_target, function_state());
8079     }
8080     if (if_false->HasPredecessor()) {
8081       entry->RegisterReturnTarget(if_false, zone());
8082       if_false->SetJoinId(ast_id);
8083       HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
8084       Goto(if_false, false_target, function_state());
8085     }
8086     set_current_block(NULL);
8087     return true;
8088
8089   } else if (function_return()->HasPredecessor()) {
8090     function_state()->entry()->RegisterReturnTarget(function_return(), zone());
8091     function_return()->SetJoinId(ast_id);
8092     set_current_block(function_return());
8093   } else {
8094     set_current_block(NULL);
8095   }
8096   delete target_state;
8097   return true;
8098 }
8099
8100
8101 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) {
8102   return TryInline(expr->target(), expr->arguments()->length(), NULL,
8103                    expr->id(), expr->ReturnId(), NORMAL_RETURN);
8104 }
8105
8106
8107 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr,
8108                                                 HValue* implicit_return_value) {
8109   return TryInline(expr->target(), expr->arguments()->length(),
8110                    implicit_return_value, expr->id(), expr->ReturnId(),
8111                    CONSTRUCT_CALL_RETURN);
8112 }
8113
8114
8115 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
8116                                              Handle<Map> receiver_map,
8117                                              BailoutId ast_id,
8118                                              BailoutId return_id) {
8119   if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true;
8120   return TryInline(getter, 0, NULL, ast_id, return_id, GETTER_CALL_RETURN);
8121 }
8122
8123
8124 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
8125                                              Handle<Map> receiver_map,
8126                                              BailoutId id,
8127                                              BailoutId assignment_id,
8128                                              HValue* implicit_return_value) {
8129   if (TryInlineApiSetter(setter, receiver_map, id)) return true;
8130   return TryInline(setter, 1, implicit_return_value, id, assignment_id,
8131                    SETTER_CALL_RETURN);
8132 }
8133
8134
8135 bool HOptimizedGraphBuilder::TryInlineIndirectCall(Handle<JSFunction> function,
8136                                                    Call* expr,
8137                                                    int arguments_count) {
8138   return TryInline(function, arguments_count, NULL, expr->id(),
8139                    expr->ReturnId(), NORMAL_RETURN);
8140 }
8141
8142
8143 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) {
8144   if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
8145   BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
8146   switch (id) {
8147     case kMathExp:
8148       if (!FLAG_fast_math) break;
8149       // Fall through if FLAG_fast_math.
8150     case kMathRound:
8151     case kMathFround:
8152     case kMathFloor:
8153     case kMathAbs:
8154     case kMathSqrt:
8155     case kMathLog:
8156     case kMathClz32:
8157       if (expr->arguments()->length() == 1) {
8158         HValue* argument = Pop();
8159         Drop(2);  // Receiver and function.
8160         HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
8161         ast_context()->ReturnInstruction(op, expr->id());
8162         return true;
8163       }
8164       break;
8165     case kMathImul:
8166       if (expr->arguments()->length() == 2) {
8167         HValue* right = Pop();
8168         HValue* left = Pop();
8169         Drop(2);  // Receiver and function.
8170         HInstruction* op =
8171             HMul::NewImul(isolate(), zone(), context(), left, right);
8172         ast_context()->ReturnInstruction(op, expr->id());
8173         return true;
8174       }
8175       break;
8176     default:
8177       // Not supported for inlining yet.
8178       break;
8179   }
8180   return false;
8181 }
8182
8183
8184 // static
8185 bool HOptimizedGraphBuilder::IsReadOnlyLengthDescriptor(
8186     Handle<Map> jsarray_map) {
8187   DCHECK(!jsarray_map->is_dictionary_map());
8188   Isolate* isolate = jsarray_map->GetIsolate();
8189   Handle<Name> length_string = isolate->factory()->length_string();
8190   DescriptorArray* descriptors = jsarray_map->instance_descriptors();
8191   int number = descriptors->SearchWithCache(*length_string, *jsarray_map);
8192   DCHECK_NE(DescriptorArray::kNotFound, number);
8193   return descriptors->GetDetails(number).IsReadOnly();
8194 }
8195
8196
8197 // static
8198 bool HOptimizedGraphBuilder::CanInlineArrayResizeOperation(
8199     Handle<Map> receiver_map) {
8200   return !receiver_map.is_null() &&
8201          receiver_map->instance_type() == JS_ARRAY_TYPE &&
8202          IsFastElementsKind(receiver_map->elements_kind()) &&
8203          !receiver_map->is_dictionary_map() &&
8204          !IsReadOnlyLengthDescriptor(receiver_map) &&
8205          !receiver_map->is_observed() && receiver_map->is_extensible();
8206 }
8207
8208
8209 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
8210     Call* expr, Handle<JSFunction> function, Handle<Map> receiver_map,
8211     int args_count_no_receiver) {
8212   if (!function->shared()->HasBuiltinFunctionId()) return false;
8213   BuiltinFunctionId id = function->shared()->builtin_function_id();
8214   int argument_count = args_count_no_receiver + 1;  // Plus receiver.
8215
8216   if (receiver_map.is_null()) {
8217     HValue* receiver = environment()->ExpressionStackAt(args_count_no_receiver);
8218     if (receiver->IsConstant() &&
8219         HConstant::cast(receiver)->handle(isolate())->IsHeapObject()) {
8220       receiver_map =
8221           handle(Handle<HeapObject>::cast(
8222                      HConstant::cast(receiver)->handle(isolate()))->map());
8223     }
8224   }
8225   // Try to inline calls like Math.* as operations in the calling function.
8226   switch (id) {
8227     case kStringCharCodeAt:
8228     case kStringCharAt:
8229       if (argument_count == 2) {
8230         HValue* index = Pop();
8231         HValue* string = Pop();
8232         Drop(1);  // Function.
8233         HInstruction* char_code =
8234             BuildStringCharCodeAt(string, index);
8235         if (id == kStringCharCodeAt) {
8236           ast_context()->ReturnInstruction(char_code, expr->id());
8237           return true;
8238         }
8239         AddInstruction(char_code);
8240         HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
8241         ast_context()->ReturnInstruction(result, expr->id());
8242         return true;
8243       }
8244       break;
8245     case kStringFromCharCode:
8246       if (argument_count == 2) {
8247         HValue* argument = Pop();
8248         Drop(2);  // Receiver and function.
8249         HInstruction* result = NewUncasted<HStringCharFromCode>(argument);
8250         ast_context()->ReturnInstruction(result, expr->id());
8251         return true;
8252       }
8253       break;
8254     case kMathExp:
8255       if (!FLAG_fast_math) break;
8256       // Fall through if FLAG_fast_math.
8257     case kMathRound:
8258     case kMathFround:
8259     case kMathFloor:
8260     case kMathAbs:
8261     case kMathSqrt:
8262     case kMathLog:
8263     case kMathClz32:
8264       if (argument_count == 2) {
8265         HValue* argument = Pop();
8266         Drop(2);  // Receiver and function.
8267         HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
8268         ast_context()->ReturnInstruction(op, expr->id());
8269         return true;
8270       }
8271       break;
8272     case kMathPow:
8273       if (argument_count == 3) {
8274         HValue* right = Pop();
8275         HValue* left = Pop();
8276         Drop(2);  // Receiver and function.
8277         HInstruction* result = NULL;
8278         // Use sqrt() if exponent is 0.5 or -0.5.
8279         if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
8280           double exponent = HConstant::cast(right)->DoubleValue();
8281           if (exponent == 0.5) {
8282             result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf);
8283           } else if (exponent == -0.5) {
8284             HValue* one = graph()->GetConstant1();
8285             HInstruction* sqrt = AddUncasted<HUnaryMathOperation>(
8286                 left, kMathPowHalf);
8287             // MathPowHalf doesn't have side effects so there's no need for
8288             // an environment simulation here.
8289             DCHECK(!sqrt->HasObservableSideEffects());
8290             result = NewUncasted<HDiv>(one, sqrt);
8291           } else if (exponent == 2.0) {
8292             result = NewUncasted<HMul>(left, left);
8293           }
8294         }
8295
8296         if (result == NULL) {
8297           result = NewUncasted<HPower>(left, right);
8298         }
8299         ast_context()->ReturnInstruction(result, expr->id());
8300         return true;
8301       }
8302       break;
8303     case kMathMax:
8304     case kMathMin:
8305       if (argument_count == 3) {
8306         HValue* right = Pop();
8307         HValue* left = Pop();
8308         Drop(2);  // Receiver and function.
8309         HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
8310                                                      : HMathMinMax::kMathMax;
8311         HInstruction* result = NewUncasted<HMathMinMax>(left, right, op);
8312         ast_context()->ReturnInstruction(result, expr->id());
8313         return true;
8314       }
8315       break;
8316     case kMathImul:
8317       if (argument_count == 3) {
8318         HValue* right = Pop();
8319         HValue* left = Pop();
8320         Drop(2);  // Receiver and function.
8321         HInstruction* result =
8322             HMul::NewImul(isolate(), zone(), context(), left, right);
8323         ast_context()->ReturnInstruction(result, expr->id());
8324         return true;
8325       }
8326       break;
8327     case kArrayPop: {
8328       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
8329       ElementsKind elements_kind = receiver_map->elements_kind();
8330
8331       Drop(args_count_no_receiver);
8332       HValue* result;
8333       HValue* reduced_length;
8334       HValue* receiver = Pop();
8335
8336       HValue* checked_object = AddCheckMap(receiver, receiver_map);
8337       HValue* length =
8338           Add<HLoadNamedField>(checked_object, nullptr,
8339                                HObjectAccess::ForArrayLength(elements_kind));
8340
8341       Drop(1);  // Function.
8342
8343       { NoObservableSideEffectsScope scope(this);
8344         IfBuilder length_checker(this);
8345
8346         HValue* bounds_check = length_checker.If<HCompareNumericAndBranch>(
8347             length, graph()->GetConstant0(), Token::EQ);
8348         length_checker.Then();
8349
8350         if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
8351
8352         length_checker.Else();
8353         HValue* elements = AddLoadElements(checked_object);
8354         // Ensure that we aren't popping from a copy-on-write array.
8355         if (IsFastSmiOrObjectElementsKind(elements_kind)) {
8356           elements = BuildCopyElementsOnWrite(checked_object, elements,
8357                                               elements_kind, length);
8358         }
8359         reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1());
8360         result = AddElementAccess(elements, reduced_length, NULL,
8361                                   bounds_check, elements_kind, LOAD);
8362         HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
8363                            ? graph()->GetConstantHole()
8364                            : Add<HConstant>(HConstant::kHoleNaN);
8365         if (IsFastSmiOrObjectElementsKind(elements_kind)) {
8366           elements_kind = FAST_HOLEY_ELEMENTS;
8367         }
8368         AddElementAccess(
8369             elements, reduced_length, hole, bounds_check, elements_kind, STORE);
8370         Add<HStoreNamedField>(
8371             checked_object, HObjectAccess::ForArrayLength(elements_kind),
8372             reduced_length, STORE_TO_INITIALIZED_ENTRY);
8373
8374         if (!ast_context()->IsEffect()) Push(result);
8375
8376         length_checker.End();
8377       }
8378       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
8379       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8380       if (!ast_context()->IsEffect()) Drop(1);
8381
8382       ast_context()->ReturnValue(result);
8383       return true;
8384     }
8385     case kArrayPush: {
8386       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
8387       ElementsKind elements_kind = receiver_map->elements_kind();
8388
8389       // If there may be elements accessors in the prototype chain, the fast
8390       // inlined version can't be used.
8391       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
8392       // If there currently can be no elements accessors on the prototype chain,
8393       // it doesn't mean that there won't be any later. Install a full prototype
8394       // chain check to trap element accessors being installed on the prototype
8395       // chain, which would cause elements to go to dictionary mode and result
8396       // in a map change.
8397       Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
8398       BuildCheckPrototypeMaps(prototype, Handle<JSObject>());
8399
8400       const int argc = args_count_no_receiver;
8401       if (argc != 1) return false;
8402
8403       HValue* value_to_push = Pop();
8404       HValue* array = Pop();
8405       Drop(1);  // Drop function.
8406
8407       HInstruction* new_size = NULL;
8408       HValue* length = NULL;
8409
8410       {
8411         NoObservableSideEffectsScope scope(this);
8412
8413         length = Add<HLoadNamedField>(
8414             array, nullptr, HObjectAccess::ForArrayLength(elements_kind));
8415
8416         new_size = AddUncasted<HAdd>(length, graph()->GetConstant1());
8417
8418         bool is_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
8419         HValue* checked_array = Add<HCheckMaps>(array, receiver_map);
8420         BuildUncheckedMonomorphicElementAccess(
8421             checked_array, length, value_to_push, is_array, elements_kind,
8422             STORE, NEVER_RETURN_HOLE, STORE_AND_GROW_NO_TRANSITION);
8423
8424         if (!ast_context()->IsEffect()) Push(new_size);
8425         Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8426         if (!ast_context()->IsEffect()) Drop(1);
8427       }
8428
8429       ast_context()->ReturnValue(new_size);
8430       return true;
8431     }
8432     case kArrayShift: {
8433       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
8434       ElementsKind kind = receiver_map->elements_kind();
8435
8436       // If there may be elements accessors in the prototype chain, the fast
8437       // inlined version can't be used.
8438       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
8439
8440       // If there currently can be no elements accessors on the prototype chain,
8441       // it doesn't mean that there won't be any later. Install a full prototype
8442       // chain check to trap element accessors being installed on the prototype
8443       // chain, which would cause elements to go to dictionary mode and result
8444       // in a map change.
8445       BuildCheckPrototypeMaps(
8446           handle(JSObject::cast(receiver_map->prototype()), isolate()),
8447           Handle<JSObject>::null());
8448
8449       // Threshold for fast inlined Array.shift().
8450       HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16));
8451
8452       Drop(args_count_no_receiver);
8453       HValue* receiver = Pop();
8454       HValue* function = Pop();
8455       HValue* result;
8456
8457       {
8458         NoObservableSideEffectsScope scope(this);
8459
8460         HValue* length = Add<HLoadNamedField>(
8461             receiver, nullptr, HObjectAccess::ForArrayLength(kind));
8462
8463         IfBuilder if_lengthiszero(this);
8464         HValue* lengthiszero = if_lengthiszero.If<HCompareNumericAndBranch>(
8465             length, graph()->GetConstant0(), Token::EQ);
8466         if_lengthiszero.Then();
8467         {
8468           if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
8469         }
8470         if_lengthiszero.Else();
8471         {
8472           HValue* elements = AddLoadElements(receiver);
8473
8474           // Check if we can use the fast inlined Array.shift().
8475           IfBuilder if_inline(this);
8476           if_inline.If<HCompareNumericAndBranch>(
8477               length, inline_threshold, Token::LTE);
8478           if (IsFastSmiOrObjectElementsKind(kind)) {
8479             // We cannot handle copy-on-write backing stores here.
8480             if_inline.AndIf<HCompareMap>(
8481                 elements, isolate()->factory()->fixed_array_map());
8482           }
8483           if_inline.Then();
8484           {
8485             // Remember the result.
8486             if (!ast_context()->IsEffect()) {
8487               Push(AddElementAccess(elements, graph()->GetConstant0(), NULL,
8488                                     lengthiszero, kind, LOAD));
8489             }
8490
8491             // Compute the new length.
8492             HValue* new_length = AddUncasted<HSub>(
8493                 length, graph()->GetConstant1());
8494             new_length->ClearFlag(HValue::kCanOverflow);
8495
8496             // Copy the remaining elements.
8497             LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
8498             {
8499               HValue* new_key = loop.BeginBody(
8500                   graph()->GetConstant0(), new_length, Token::LT);
8501               HValue* key = AddUncasted<HAdd>(new_key, graph()->GetConstant1());
8502               key->ClearFlag(HValue::kCanOverflow);
8503               ElementsKind copy_kind =
8504                   kind == FAST_HOLEY_SMI_ELEMENTS ? FAST_HOLEY_ELEMENTS : kind;
8505               HValue* element = AddUncasted<HLoadKeyed>(
8506                   elements, key, lengthiszero, copy_kind, ALLOW_RETURN_HOLE);
8507               HStoreKeyed* store =
8508                   Add<HStoreKeyed>(elements, new_key, element, copy_kind);
8509               store->SetFlag(HValue::kAllowUndefinedAsNaN);
8510             }
8511             loop.EndBody();
8512
8513             // Put a hole at the end.
8514             HValue* hole = IsFastSmiOrObjectElementsKind(kind)
8515                                ? graph()->GetConstantHole()
8516                                : Add<HConstant>(HConstant::kHoleNaN);
8517             if (IsFastSmiOrObjectElementsKind(kind)) kind = FAST_HOLEY_ELEMENTS;
8518             Add<HStoreKeyed>(
8519                 elements, new_length, hole, kind, INITIALIZING_STORE);
8520
8521             // Remember new length.
8522             Add<HStoreNamedField>(
8523                 receiver, HObjectAccess::ForArrayLength(kind),
8524                 new_length, STORE_TO_INITIALIZED_ENTRY);
8525           }
8526           if_inline.Else();
8527           {
8528             Add<HPushArguments>(receiver);
8529             result = Add<HCallJSFunction>(function, 1, true);
8530             if (!ast_context()->IsEffect()) Push(result);
8531           }
8532           if_inline.End();
8533         }
8534         if_lengthiszero.End();
8535       }
8536       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
8537       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8538       if (!ast_context()->IsEffect()) Drop(1);
8539       ast_context()->ReturnValue(result);
8540       return true;
8541     }
8542     case kArrayIndexOf:
8543     case kArrayLastIndexOf: {
8544       if (receiver_map.is_null()) return false;
8545       if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
8546       ElementsKind kind = receiver_map->elements_kind();
8547       if (!IsFastElementsKind(kind)) return false;
8548       if (receiver_map->is_observed()) return false;
8549       if (argument_count != 2) return false;
8550       if (!receiver_map->is_extensible()) return false;
8551
8552       // If there may be elements accessors in the prototype chain, the fast
8553       // inlined version can't be used.
8554       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
8555
8556       // If there currently can be no elements accessors on the prototype chain,
8557       // it doesn't mean that there won't be any later. Install a full prototype
8558       // chain check to trap element accessors being installed on the prototype
8559       // chain, which would cause elements to go to dictionary mode and result
8560       // in a map change.
8561       BuildCheckPrototypeMaps(
8562           handle(JSObject::cast(receiver_map->prototype()), isolate()),
8563           Handle<JSObject>::null());
8564
8565       HValue* search_element = Pop();
8566       HValue* receiver = Pop();
8567       Drop(1);  // Drop function.
8568
8569       ArrayIndexOfMode mode = (id == kArrayIndexOf)
8570           ? kFirstIndexOf : kLastIndexOf;
8571       HValue* index = BuildArrayIndexOf(receiver, search_element, kind, mode);
8572
8573       if (!ast_context()->IsEffect()) Push(index);
8574       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8575       if (!ast_context()->IsEffect()) Drop(1);
8576       ast_context()->ReturnValue(index);
8577       return true;
8578     }
8579     default:
8580       // Not yet supported for inlining.
8581       break;
8582   }
8583   return false;
8584 }
8585
8586
8587 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr,
8588                                                       HValue* receiver) {
8589   Handle<JSFunction> function = expr->target();
8590   int argc = expr->arguments()->length();
8591   SmallMapList receiver_maps;
8592   return TryInlineApiCall(function,
8593                           receiver,
8594                           &receiver_maps,
8595                           argc,
8596                           expr->id(),
8597                           kCallApiFunction);
8598 }
8599
8600
8601 bool HOptimizedGraphBuilder::TryInlineApiMethodCall(
8602     Call* expr,
8603     HValue* receiver,
8604     SmallMapList* receiver_maps) {
8605   Handle<JSFunction> function = expr->target();
8606   int argc = expr->arguments()->length();
8607   return TryInlineApiCall(function,
8608                           receiver,
8609                           receiver_maps,
8610                           argc,
8611                           expr->id(),
8612                           kCallApiMethod);
8613 }
8614
8615
8616 bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<JSFunction> function,
8617                                                 Handle<Map> receiver_map,
8618                                                 BailoutId ast_id) {
8619   SmallMapList receiver_maps(1, zone());
8620   receiver_maps.Add(receiver_map, zone());
8621   return TryInlineApiCall(function,
8622                           NULL,  // Receiver is on expression stack.
8623                           &receiver_maps,
8624                           0,
8625                           ast_id,
8626                           kCallApiGetter);
8627 }
8628
8629
8630 bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<JSFunction> function,
8631                                                 Handle<Map> receiver_map,
8632                                                 BailoutId ast_id) {
8633   SmallMapList receiver_maps(1, zone());
8634   receiver_maps.Add(receiver_map, zone());
8635   return TryInlineApiCall(function,
8636                           NULL,  // Receiver is on expression stack.
8637                           &receiver_maps,
8638                           1,
8639                           ast_id,
8640                           kCallApiSetter);
8641 }
8642
8643
8644 bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function,
8645                                                HValue* receiver,
8646                                                SmallMapList* receiver_maps,
8647                                                int argc,
8648                                                BailoutId ast_id,
8649                                                ApiCallType call_type) {
8650   if (function->context()->native_context() !=
8651       top_info()->closure()->context()->native_context()) {
8652     return false;
8653   }
8654   CallOptimization optimization(function);
8655   if (!optimization.is_simple_api_call()) return false;
8656   Handle<Map> holder_map;
8657   for (int i = 0; i < receiver_maps->length(); ++i) {
8658     auto map = receiver_maps->at(i);
8659     // Don't inline calls to receivers requiring accesschecks.
8660     if (map->is_access_check_needed()) return false;
8661   }
8662   if (call_type == kCallApiFunction) {
8663     // Cannot embed a direct reference to the global proxy map
8664     // as it maybe dropped on deserialization.
8665     CHECK(!isolate()->serializer_enabled());
8666     DCHECK_EQ(0, receiver_maps->length());
8667     receiver_maps->Add(handle(function->global_proxy()->map()), zone());
8668   }
8669   CallOptimization::HolderLookup holder_lookup =
8670       CallOptimization::kHolderNotFound;
8671   Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
8672       receiver_maps->first(), &holder_lookup);
8673   if (holder_lookup == CallOptimization::kHolderNotFound) return false;
8674
8675   if (FLAG_trace_inlining) {
8676     PrintF("Inlining api function ");
8677     function->ShortPrint();
8678     PrintF("\n");
8679   }
8680
8681   bool is_function = false;
8682   bool is_store = false;
8683   switch (call_type) {
8684     case kCallApiFunction:
8685     case kCallApiMethod:
8686       // Need to check that none of the receiver maps could have changed.
8687       Add<HCheckMaps>(receiver, receiver_maps);
8688       // Need to ensure the chain between receiver and api_holder is intact.
8689       if (holder_lookup == CallOptimization::kHolderFound) {
8690         AddCheckPrototypeMaps(api_holder, receiver_maps->first());
8691       } else {
8692         DCHECK_EQ(holder_lookup, CallOptimization::kHolderIsReceiver);
8693       }
8694       // Includes receiver.
8695       PushArgumentsFromEnvironment(argc + 1);
8696       is_function = true;
8697       break;
8698     case kCallApiGetter:
8699       // Receiver and prototype chain cannot have changed.
8700       DCHECK_EQ(0, argc);
8701       DCHECK_NULL(receiver);
8702       // Receiver is on expression stack.
8703       receiver = Pop();
8704       Add<HPushArguments>(receiver);
8705       break;
8706     case kCallApiSetter:
8707       {
8708         is_store = true;
8709         // Receiver and prototype chain cannot have changed.
8710         DCHECK_EQ(1, argc);
8711         DCHECK_NULL(receiver);
8712         // Receiver and value are on expression stack.
8713         HValue* value = Pop();
8714         receiver = Pop();
8715         Add<HPushArguments>(receiver, value);
8716         break;
8717      }
8718   }
8719
8720   HValue* holder = NULL;
8721   switch (holder_lookup) {
8722     case CallOptimization::kHolderFound:
8723       holder = Add<HConstant>(api_holder);
8724       break;
8725     case CallOptimization::kHolderIsReceiver:
8726       holder = receiver;
8727       break;
8728     case CallOptimization::kHolderNotFound:
8729       UNREACHABLE();
8730       break;
8731   }
8732   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
8733   Handle<Object> call_data_obj(api_call_info->data(), isolate());
8734   bool call_data_undefined = call_data_obj->IsUndefined();
8735   HValue* call_data = Add<HConstant>(call_data_obj);
8736   ApiFunction fun(v8::ToCData<Address>(api_call_info->callback()));
8737   ExternalReference ref = ExternalReference(&fun,
8738                                             ExternalReference::DIRECT_API_CALL,
8739                                             isolate());
8740   HValue* api_function_address = Add<HConstant>(ExternalReference(ref));
8741
8742   HValue* op_vals[] = {context(), Add<HConstant>(function), call_data, holder,
8743                        api_function_address, nullptr};
8744
8745   HInstruction* call = nullptr;
8746   if (!is_function) {
8747     CallApiAccessorStub stub(isolate(), is_store, call_data_undefined);
8748     Handle<Code> code = stub.GetCode();
8749     HConstant* code_value = Add<HConstant>(code);
8750     ApiAccessorDescriptor descriptor(isolate());
8751     DCHECK(arraysize(op_vals) - 1 == descriptor.GetEnvironmentLength());
8752     call = New<HCallWithDescriptor>(
8753         code_value, argc + 1, descriptor,
8754         Vector<HValue*>(op_vals, descriptor.GetEnvironmentLength()));
8755   } else if (argc <= CallApiFunctionWithFixedArgsStub::kMaxFixedArgs) {
8756     CallApiFunctionWithFixedArgsStub stub(isolate(), argc, call_data_undefined);
8757     Handle<Code> code = stub.GetCode();
8758     HConstant* code_value = Add<HConstant>(code);
8759     ApiFunctionWithFixedArgsDescriptor descriptor(isolate());
8760     DCHECK(arraysize(op_vals) - 1 == descriptor.GetEnvironmentLength());
8761     call = New<HCallWithDescriptor>(
8762         code_value, argc + 1, descriptor,
8763         Vector<HValue*>(op_vals, descriptor.GetEnvironmentLength()));
8764     Drop(1);  // Drop function.
8765   } else {
8766     op_vals[arraysize(op_vals) - 1] = Add<HConstant>(argc);
8767     CallApiFunctionStub stub(isolate(), call_data_undefined);
8768     Handle<Code> code = stub.GetCode();
8769     HConstant* code_value = Add<HConstant>(code);
8770     ApiFunctionDescriptor descriptor(isolate());
8771     DCHECK(arraysize(op_vals) == descriptor.GetEnvironmentLength());
8772     call = New<HCallWithDescriptor>(
8773         code_value, argc + 1, descriptor,
8774         Vector<HValue*>(op_vals, descriptor.GetEnvironmentLength()));
8775     Drop(1);  // Drop function.
8776   }
8777
8778   ast_context()->ReturnInstruction(call, ast_id);
8779   return true;
8780 }
8781
8782
8783 void HOptimizedGraphBuilder::HandleIndirectCall(Call* expr, HValue* function,
8784                                                 int arguments_count) {
8785   Handle<JSFunction> known_function;
8786   int args_count_no_receiver = arguments_count - 1;
8787   if (function->IsConstant() &&
8788       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
8789     known_function =
8790         Handle<JSFunction>::cast(HConstant::cast(function)->handle(isolate()));
8791     if (TryInlineBuiltinMethodCall(expr, known_function, Handle<Map>(),
8792                                    args_count_no_receiver)) {
8793       if (FLAG_trace_inlining) {
8794         PrintF("Inlining builtin ");
8795         known_function->ShortPrint();
8796         PrintF("\n");
8797       }
8798       return;
8799     }
8800
8801     if (TryInlineIndirectCall(known_function, expr, args_count_no_receiver)) {
8802       return;
8803     }
8804   }
8805
8806   PushArgumentsFromEnvironment(arguments_count);
8807   HInvokeFunction* call =
8808       New<HInvokeFunction>(function, known_function, arguments_count);
8809   Drop(1);  // Function
8810   ast_context()->ReturnInstruction(call, expr->id());
8811 }
8812
8813
8814 bool HOptimizedGraphBuilder::TryIndirectCall(Call* expr) {
8815   DCHECK(expr->expression()->IsProperty());
8816
8817   if (!expr->IsMonomorphic()) {
8818     return false;
8819   }
8820   Handle<Map> function_map = expr->GetReceiverTypes()->first();
8821   if (function_map->instance_type() != JS_FUNCTION_TYPE ||
8822       !expr->target()->shared()->HasBuiltinFunctionId()) {
8823     return false;
8824   }
8825
8826   switch (expr->target()->shared()->builtin_function_id()) {
8827     case kFunctionCall: {
8828       if (expr->arguments()->length() == 0) return false;
8829       BuildFunctionCall(expr);
8830       return true;
8831     }
8832     case kFunctionApply: {
8833       // For .apply, only the pattern f.apply(receiver, arguments)
8834       // is supported.
8835       if (current_info()->scope()->arguments() == NULL) return false;
8836
8837       if (!CanBeFunctionApplyArguments(expr)) return false;
8838
8839       BuildFunctionApply(expr);
8840       return true;
8841     }
8842     default: { return false; }
8843   }
8844   UNREACHABLE();
8845 }
8846
8847
8848 void HOptimizedGraphBuilder::BuildFunctionApply(Call* expr) {
8849   ZoneList<Expression*>* args = expr->arguments();
8850   CHECK_ALIVE(VisitForValue(args->at(0)));
8851   HValue* receiver = Pop();  // receiver
8852   HValue* function = Pop();  // f
8853   Drop(1);  // apply
8854
8855   Handle<Map> function_map = expr->GetReceiverTypes()->first();
8856   HValue* checked_function = AddCheckMap(function, function_map);
8857
8858   if (function_state()->outer() == NULL) {
8859     HInstruction* elements = Add<HArgumentsElements>(false);
8860     HInstruction* length = Add<HArgumentsLength>(elements);
8861     HValue* wrapped_receiver = BuildWrapReceiver(receiver, checked_function);
8862     HInstruction* result = New<HApplyArguments>(function,
8863                                                 wrapped_receiver,
8864                                                 length,
8865                                                 elements);
8866     ast_context()->ReturnInstruction(result, expr->id());
8867   } else {
8868     // We are inside inlined function and we know exactly what is inside
8869     // arguments object. But we need to be able to materialize at deopt.
8870     DCHECK_EQ(environment()->arguments_environment()->parameter_count(),
8871               function_state()->entry()->arguments_object()->arguments_count());
8872     HArgumentsObject* args = function_state()->entry()->arguments_object();
8873     const ZoneList<HValue*>* arguments_values = args->arguments_values();
8874     int arguments_count = arguments_values->length();
8875     Push(function);
8876     Push(BuildWrapReceiver(receiver, checked_function));
8877     for (int i = 1; i < arguments_count; i++) {
8878       Push(arguments_values->at(i));
8879     }
8880     HandleIndirectCall(expr, function, arguments_count);
8881   }
8882 }
8883
8884
8885 // f.call(...)
8886 void HOptimizedGraphBuilder::BuildFunctionCall(Call* expr) {
8887   HValue* function = Top();  // f
8888   Handle<Map> function_map = expr->GetReceiverTypes()->first();
8889   HValue* checked_function = AddCheckMap(function, function_map);
8890
8891   // f and call are on the stack in the unoptimized code
8892   // during evaluation of the arguments.
8893   CHECK_ALIVE(VisitExpressions(expr->arguments()));
8894
8895   int args_length = expr->arguments()->length();
8896   int receiver_index = args_length - 1;
8897   // Patch the receiver.
8898   HValue* receiver = BuildWrapReceiver(
8899       environment()->ExpressionStackAt(receiver_index), checked_function);
8900   environment()->SetExpressionStackAt(receiver_index, receiver);
8901
8902   // Call must not be on the stack from now on.
8903   int call_index = args_length + 1;
8904   environment()->RemoveExpressionStackAt(call_index);
8905
8906   HandleIndirectCall(expr, function, args_length);
8907 }
8908
8909
8910 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function,
8911                                                     Handle<JSFunction> target) {
8912   SharedFunctionInfo* shared = target->shared();
8913   if (is_sloppy(shared->language_mode()) && !shared->native()) {
8914     // Cannot embed a direct reference to the global proxy
8915     // as is it dropped on deserialization.
8916     CHECK(!isolate()->serializer_enabled());
8917     Handle<JSObject> global_proxy(target->context()->global_proxy());
8918     return Add<HConstant>(global_proxy);
8919   }
8920   return graph()->GetConstantUndefined();
8921 }
8922
8923
8924 void HOptimizedGraphBuilder::BuildArrayCall(Expression* expression,
8925                                             int arguments_count,
8926                                             HValue* function,
8927                                             Handle<AllocationSite> site) {
8928   Add<HCheckValue>(function, array_function());
8929
8930   if (IsCallArrayInlineable(arguments_count, site)) {
8931     BuildInlinedCallArray(expression, arguments_count, site);
8932     return;
8933   }
8934
8935   HInstruction* call = PreProcessCall(New<HCallNewArray>(
8936       function, arguments_count + 1, site->GetElementsKind()));
8937   if (expression->IsCall()) {
8938     Drop(1);
8939   }
8940   ast_context()->ReturnInstruction(call, expression->id());
8941 }
8942
8943
8944 HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver,
8945                                                   HValue* search_element,
8946                                                   ElementsKind kind,
8947                                                   ArrayIndexOfMode mode) {
8948   DCHECK(IsFastElementsKind(kind));
8949
8950   NoObservableSideEffectsScope no_effects(this);
8951
8952   HValue* elements = AddLoadElements(receiver);
8953   HValue* length = AddLoadArrayLength(receiver, kind);
8954
8955   HValue* initial;
8956   HValue* terminating;
8957   Token::Value token;
8958   LoopBuilder::Direction direction;
8959   if (mode == kFirstIndexOf) {
8960     initial = graph()->GetConstant0();
8961     terminating = length;
8962     token = Token::LT;
8963     direction = LoopBuilder::kPostIncrement;
8964   } else {
8965     DCHECK_EQ(kLastIndexOf, mode);
8966     initial = length;
8967     terminating = graph()->GetConstant0();
8968     token = Token::GT;
8969     direction = LoopBuilder::kPreDecrement;
8970   }
8971
8972   Push(graph()->GetConstantMinus1());
8973   if (IsFastDoubleElementsKind(kind) || IsFastSmiElementsKind(kind)) {
8974     // Make sure that we can actually compare numbers correctly below, see
8975     // https://code.google.com/p/chromium/issues/detail?id=407946 for details.
8976     search_element = AddUncasted<HForceRepresentation>(
8977         search_element, IsFastSmiElementsKind(kind) ? Representation::Smi()
8978                                                     : Representation::Double());
8979
8980     LoopBuilder loop(this, context(), direction);
8981     {
8982       HValue* index = loop.BeginBody(initial, terminating, token);
8983       HValue* element = AddUncasted<HLoadKeyed>(elements, index, nullptr, kind,
8984                                                 ALLOW_RETURN_HOLE);
8985       IfBuilder if_issame(this);
8986       if_issame.If<HCompareNumericAndBranch>(element, search_element,
8987                                              Token::EQ_STRICT);
8988       if_issame.Then();
8989       {
8990         Drop(1);
8991         Push(index);
8992         loop.Break();
8993       }
8994       if_issame.End();
8995     }
8996     loop.EndBody();
8997   } else {
8998     IfBuilder if_isstring(this);
8999     if_isstring.If<HIsStringAndBranch>(search_element);
9000     if_isstring.Then();
9001     {
9002       LoopBuilder loop(this, context(), direction);
9003       {
9004         HValue* index = loop.BeginBody(initial, terminating, token);
9005         HValue* element = AddUncasted<HLoadKeyed>(elements, index, nullptr,
9006                                                   kind, ALLOW_RETURN_HOLE);
9007         IfBuilder if_issame(this);
9008         if_issame.If<HIsStringAndBranch>(element);
9009         if_issame.AndIf<HStringCompareAndBranch>(
9010             element, search_element, Token::EQ_STRICT);
9011         if_issame.Then();
9012         {
9013           Drop(1);
9014           Push(index);
9015           loop.Break();
9016         }
9017         if_issame.End();
9018       }
9019       loop.EndBody();
9020     }
9021     if_isstring.Else();
9022     {
9023       IfBuilder if_isnumber(this);
9024       if_isnumber.If<HIsSmiAndBranch>(search_element);
9025       if_isnumber.OrIf<HCompareMap>(
9026           search_element, isolate()->factory()->heap_number_map());
9027       if_isnumber.Then();
9028       {
9029         HValue* search_number =
9030             AddUncasted<HForceRepresentation>(search_element,
9031                                               Representation::Double());
9032         LoopBuilder loop(this, context(), direction);
9033         {
9034           HValue* index = loop.BeginBody(initial, terminating, token);
9035           HValue* element = AddUncasted<HLoadKeyed>(elements, index, nullptr,
9036                                                     kind, ALLOW_RETURN_HOLE);
9037
9038           IfBuilder if_element_isnumber(this);
9039           if_element_isnumber.If<HIsSmiAndBranch>(element);
9040           if_element_isnumber.OrIf<HCompareMap>(
9041               element, isolate()->factory()->heap_number_map());
9042           if_element_isnumber.Then();
9043           {
9044             HValue* number =
9045                 AddUncasted<HForceRepresentation>(element,
9046                                                   Representation::Double());
9047             IfBuilder if_issame(this);
9048             if_issame.If<HCompareNumericAndBranch>(
9049                 number, search_number, Token::EQ_STRICT);
9050             if_issame.Then();
9051             {
9052               Drop(1);
9053               Push(index);
9054               loop.Break();
9055             }
9056             if_issame.End();
9057           }
9058           if_element_isnumber.End();
9059         }
9060         loop.EndBody();
9061       }
9062       if_isnumber.Else();
9063       {
9064         LoopBuilder loop(this, context(), direction);
9065         {
9066           HValue* index = loop.BeginBody(initial, terminating, token);
9067           HValue* element = AddUncasted<HLoadKeyed>(elements, index, nullptr,
9068                                                     kind, ALLOW_RETURN_HOLE);
9069           IfBuilder if_issame(this);
9070           if_issame.If<HCompareObjectEqAndBranch>(
9071               element, search_element);
9072           if_issame.Then();
9073           {
9074             Drop(1);
9075             Push(index);
9076             loop.Break();
9077           }
9078           if_issame.End();
9079         }
9080         loop.EndBody();
9081       }
9082       if_isnumber.End();
9083     }
9084     if_isstring.End();
9085   }
9086
9087   return Pop();
9088 }
9089
9090
9091 bool HOptimizedGraphBuilder::TryHandleArrayCall(Call* expr, HValue* function) {
9092   if (!array_function().is_identical_to(expr->target())) {
9093     return false;
9094   }
9095
9096   Handle<AllocationSite> site = expr->allocation_site();
9097   if (site.is_null()) return false;
9098
9099   BuildArrayCall(expr,
9100                  expr->arguments()->length(),
9101                  function,
9102                  site);
9103   return true;
9104 }
9105
9106
9107 bool HOptimizedGraphBuilder::TryHandleArrayCallNew(CallNew* expr,
9108                                                    HValue* function) {
9109   if (!array_function().is_identical_to(expr->target())) {
9110     return false;
9111   }
9112
9113   Handle<AllocationSite> site = expr->allocation_site();
9114   if (site.is_null()) return false;
9115
9116   BuildArrayCall(expr, expr->arguments()->length(), function, site);
9117   return true;
9118 }
9119
9120
9121 bool HOptimizedGraphBuilder::CanBeFunctionApplyArguments(Call* expr) {
9122   ZoneList<Expression*>* args = expr->arguments();
9123   if (args->length() != 2) return false;
9124   VariableProxy* arg_two = args->at(1)->AsVariableProxy();
9125   if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
9126   HValue* arg_two_value = LookupAndMakeLive(arg_two->var());
9127   if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
9128   return true;
9129 }
9130
9131
9132 void HOptimizedGraphBuilder::VisitCall(Call* expr) {
9133   DCHECK(!HasStackOverflow());
9134   DCHECK(current_block() != NULL);
9135   DCHECK(current_block()->HasPredecessor());
9136   Expression* callee = expr->expression();
9137   int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
9138   HInstruction* call = NULL;
9139
9140   Property* prop = callee->AsProperty();
9141   if (prop != NULL) {
9142     CHECK_ALIVE(VisitForValue(prop->obj()));
9143     HValue* receiver = Top();
9144
9145     SmallMapList* maps;
9146     ComputeReceiverTypes(expr, receiver, &maps, zone());
9147
9148     if (prop->key()->IsPropertyName() && maps->length() > 0) {
9149       Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
9150       PropertyAccessInfo info(this, LOAD, maps->first(), name);
9151       if (!info.CanAccessAsMonomorphic(maps)) {
9152         HandlePolymorphicCallNamed(expr, receiver, maps, name);
9153         return;
9154       }
9155     }
9156
9157     HValue* key = NULL;
9158     if (!prop->key()->IsPropertyName()) {
9159       CHECK_ALIVE(VisitForValue(prop->key()));
9160       key = Pop();
9161     }
9162
9163     CHECK_ALIVE(PushLoad(prop, receiver, key));
9164     HValue* function = Pop();
9165
9166     if (function->IsConstant() &&
9167         HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
9168       // Push the function under the receiver.
9169       environment()->SetExpressionStackAt(0, function);
9170       Push(receiver);
9171
9172       Handle<JSFunction> known_function = Handle<JSFunction>::cast(
9173           HConstant::cast(function)->handle(isolate()));
9174       expr->set_target(known_function);
9175
9176       if (TryIndirectCall(expr)) return;
9177       CHECK_ALIVE(VisitExpressions(expr->arguments()));
9178
9179       Handle<Map> map = maps->length() == 1 ? maps->first() : Handle<Map>();
9180       if (TryInlineBuiltinMethodCall(expr, known_function, map,
9181                                      expr->arguments()->length())) {
9182         if (FLAG_trace_inlining) {
9183           PrintF("Inlining builtin ");
9184           known_function->ShortPrint();
9185           PrintF("\n");
9186         }
9187         return;
9188       }
9189       if (TryInlineApiMethodCall(expr, receiver, maps)) return;
9190
9191       // Wrap the receiver if necessary.
9192       if (NeedsWrapping(maps->first(), known_function)) {
9193         // Since HWrapReceiver currently cannot actually wrap numbers and
9194         // strings, use the regular CallFunctionStub for method calls to wrap
9195         // the receiver.
9196         // TODO(verwaest): Support creation of value wrappers directly in
9197         // HWrapReceiver.
9198         call = New<HCallFunction>(
9199             function, argument_count, WRAP_AND_CALL);
9200       } else if (TryInlineCall(expr)) {
9201         return;
9202       } else {
9203         call = BuildCallConstantFunction(known_function, argument_count);
9204       }
9205
9206     } else {
9207       ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED;
9208       if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) {
9209         // We have to use EAGER deoptimization here because Deoptimizer::SOFT
9210         // gets ignored by the always-opt flag, which leads to incorrect code.
9211         Add<HDeoptimize>(
9212             Deoptimizer::kInsufficientTypeFeedbackForCallWithArguments,
9213             Deoptimizer::EAGER);
9214         arguments_flag = ARGUMENTS_FAKED;
9215       }
9216
9217       // Push the function under the receiver.
9218       environment()->SetExpressionStackAt(0, function);
9219       Push(receiver);
9220
9221       CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag));
9222       CallFunctionFlags flags = receiver->type().IsJSObject()
9223           ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD;
9224       call = New<HCallFunction>(function, argument_count, flags);
9225     }
9226     PushArgumentsFromEnvironment(argument_count);
9227
9228   } else {
9229     VariableProxy* proxy = expr->expression()->AsVariableProxy();
9230     if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
9231       return Bailout(kPossibleDirectCallToEval);
9232     }
9233
9234     // The function is on the stack in the unoptimized code during
9235     // evaluation of the arguments.
9236     CHECK_ALIVE(VisitForValue(expr->expression()));
9237     HValue* function = Top();
9238     if (function->IsConstant() &&
9239         HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
9240       Handle<Object> constant = HConstant::cast(function)->handle(isolate());
9241       Handle<JSFunction> target = Handle<JSFunction>::cast(constant);
9242       expr->SetKnownGlobalTarget(target);
9243     }
9244
9245     // Placeholder for the receiver.
9246     Push(graph()->GetConstantUndefined());
9247     CHECK_ALIVE(VisitExpressions(expr->arguments()));
9248
9249     if (expr->IsMonomorphic()) {
9250       Add<HCheckValue>(function, expr->target());
9251
9252       // Patch the global object on the stack by the expected receiver.
9253       HValue* receiver = ImplicitReceiverFor(function, expr->target());
9254       const int receiver_index = argument_count - 1;
9255       environment()->SetExpressionStackAt(receiver_index, receiver);
9256
9257       if (TryInlineBuiltinFunctionCall(expr)) {
9258         if (FLAG_trace_inlining) {
9259           PrintF("Inlining builtin ");
9260           expr->target()->ShortPrint();
9261           PrintF("\n");
9262         }
9263         return;
9264       }
9265       if (TryInlineApiFunctionCall(expr, receiver)) return;
9266       if (TryHandleArrayCall(expr, function)) return;
9267       if (TryInlineCall(expr)) return;
9268
9269       PushArgumentsFromEnvironment(argument_count);
9270       call = BuildCallConstantFunction(expr->target(), argument_count);
9271     } else {
9272       PushArgumentsFromEnvironment(argument_count);
9273       HCallFunction* call_function =
9274           New<HCallFunction>(function, argument_count);
9275       call = call_function;
9276       if (expr->is_uninitialized() &&
9277           expr->IsUsingCallFeedbackICSlot(isolate())) {
9278         // We've never seen this call before, so let's have Crankshaft learn
9279         // through the type vector.
9280         Handle<SharedFunctionInfo> current_shared =
9281             function_state()->compilation_info()->shared_info();
9282         Handle<TypeFeedbackVector> vector =
9283             handle(current_shared->feedback_vector(), isolate());
9284         FeedbackVectorICSlot slot = expr->CallFeedbackICSlot();
9285         call_function->SetVectorAndSlot(vector, slot);
9286       }
9287     }
9288   }
9289
9290   Drop(1);  // Drop the function.
9291   return ast_context()->ReturnInstruction(call, expr->id());
9292 }
9293
9294
9295 void HOptimizedGraphBuilder::BuildInlinedCallArray(
9296     Expression* expression,
9297     int argument_count,
9298     Handle<AllocationSite> site) {
9299   DCHECK(!site.is_null());
9300   DCHECK(argument_count >= 0 && argument_count <= 1);
9301   NoObservableSideEffectsScope no_effects(this);
9302
9303   // We should at least have the constructor on the expression stack.
9304   HValue* constructor = environment()->ExpressionStackAt(argument_count);
9305
9306   // Register on the site for deoptimization if the transition feedback changes.
9307   AllocationSite::RegisterForDeoptOnTransitionChange(site, top_info());
9308   ElementsKind kind = site->GetElementsKind();
9309   HInstruction* site_instruction = Add<HConstant>(site);
9310
9311   // In the single constant argument case, we may have to adjust elements kind
9312   // to avoid creating a packed non-empty array.
9313   if (argument_count == 1 && !IsHoleyElementsKind(kind)) {
9314     HValue* argument = environment()->Top();
9315     if (argument->IsConstant()) {
9316       HConstant* constant_argument = HConstant::cast(argument);
9317       DCHECK(constant_argument->HasSmiValue());
9318       int constant_array_size = constant_argument->Integer32Value();
9319       if (constant_array_size != 0) {
9320         kind = GetHoleyElementsKind(kind);
9321       }
9322     }
9323   }
9324
9325   // Build the array.
9326   JSArrayBuilder array_builder(this,
9327                                kind,
9328                                site_instruction,
9329                                constructor,
9330                                DISABLE_ALLOCATION_SITES);
9331   HValue* new_object = argument_count == 0
9332       ? array_builder.AllocateEmptyArray()
9333       : BuildAllocateArrayFromLength(&array_builder, Top());
9334
9335   int args_to_drop = argument_count + (expression->IsCall() ? 2 : 1);
9336   Drop(args_to_drop);
9337   ast_context()->ReturnValue(new_object);
9338 }
9339
9340
9341 // Checks whether allocation using the given constructor can be inlined.
9342 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
9343   return constructor->has_initial_map() &&
9344       constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
9345       constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize &&
9346       constructor->initial_map()->InitialPropertiesLength() == 0;
9347 }
9348
9349
9350 bool HOptimizedGraphBuilder::IsCallArrayInlineable(
9351     int argument_count,
9352     Handle<AllocationSite> site) {
9353   Handle<JSFunction> caller = current_info()->closure();
9354   Handle<JSFunction> target = array_function();
9355   // We should have the function plus array arguments on the environment stack.
9356   DCHECK(environment()->length() >= (argument_count + 1));
9357   DCHECK(!site.is_null());
9358
9359   bool inline_ok = false;
9360   if (site->CanInlineCall()) {
9361     // We also want to avoid inlining in certain 1 argument scenarios.
9362     if (argument_count == 1) {
9363       HValue* argument = Top();
9364       if (argument->IsConstant()) {
9365         // Do not inline if the constant length argument is not a smi or
9366         // outside the valid range for unrolled loop initialization.
9367         HConstant* constant_argument = HConstant::cast(argument);
9368         if (constant_argument->HasSmiValue()) {
9369           int value = constant_argument->Integer32Value();
9370           inline_ok = value >= 0 && value <= kElementLoopUnrollThreshold;
9371           if (!inline_ok) {
9372             TraceInline(target, caller,
9373                         "Constant length outside of valid inlining range.");
9374           }
9375         }
9376       } else {
9377         TraceInline(target, caller,
9378                     "Dont inline [new] Array(n) where n isn't constant.");
9379       }
9380     } else if (argument_count == 0) {
9381       inline_ok = true;
9382     } else {
9383       TraceInline(target, caller, "Too many arguments to inline.");
9384     }
9385   } else {
9386     TraceInline(target, caller, "AllocationSite requested no inlining.");
9387   }
9388
9389   if (inline_ok) {
9390     TraceInline(target, caller, NULL);
9391   }
9392   return inline_ok;
9393 }
9394
9395
9396 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
9397   DCHECK(!HasStackOverflow());
9398   DCHECK(current_block() != NULL);
9399   DCHECK(current_block()->HasPredecessor());
9400   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
9401   int argument_count = expr->arguments()->length() + 1;  // Plus constructor.
9402   Factory* factory = isolate()->factory();
9403
9404   // The constructor function is on the stack in the unoptimized code
9405   // during evaluation of the arguments.
9406   CHECK_ALIVE(VisitForValue(expr->expression()));
9407   HValue* function = Top();
9408   CHECK_ALIVE(VisitExpressions(expr->arguments()));
9409
9410   if (function->IsConstant() &&
9411       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
9412     Handle<Object> constant = HConstant::cast(function)->handle(isolate());
9413     expr->SetKnownGlobalTarget(Handle<JSFunction>::cast(constant));
9414   }
9415
9416   if (FLAG_inline_construct &&
9417       expr->IsMonomorphic() &&
9418       IsAllocationInlineable(expr->target())) {
9419     Handle<JSFunction> constructor = expr->target();
9420     HValue* check = Add<HCheckValue>(function, constructor);
9421
9422     // Force completion of inobject slack tracking before generating
9423     // allocation code to finalize instance size.
9424     if (constructor->IsInobjectSlackTrackingInProgress()) {
9425       constructor->CompleteInobjectSlackTracking();
9426     }
9427
9428     // Calculate instance size from initial map of constructor.
9429     DCHECK(constructor->has_initial_map());
9430     Handle<Map> initial_map(constructor->initial_map());
9431     int instance_size = initial_map->instance_size();
9432     DCHECK(initial_map->InitialPropertiesLength() == 0);
9433
9434     // Allocate an instance of the implicit receiver object.
9435     HValue* size_in_bytes = Add<HConstant>(instance_size);
9436     HAllocationMode allocation_mode;
9437     if (FLAG_pretenuring_call_new) {
9438       if (FLAG_allocation_site_pretenuring) {
9439         // Try to use pretenuring feedback.
9440         Handle<AllocationSite> allocation_site = expr->allocation_site();
9441         allocation_mode = HAllocationMode(allocation_site);
9442         // Take a dependency on allocation site.
9443         AllocationSite::RegisterForDeoptOnTenureChange(allocation_site,
9444                                                        top_info());
9445       }
9446     }
9447
9448     HAllocate* receiver = BuildAllocate(
9449         size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode);
9450     receiver->set_known_initial_map(initial_map);
9451
9452     // Initialize map and fields of the newly allocated object.
9453     { NoObservableSideEffectsScope no_effects(this);
9454       DCHECK(initial_map->instance_type() == JS_OBJECT_TYPE);
9455       Add<HStoreNamedField>(receiver,
9456           HObjectAccess::ForMapAndOffset(initial_map, JSObject::kMapOffset),
9457           Add<HConstant>(initial_map));
9458       HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array());
9459       Add<HStoreNamedField>(receiver,
9460           HObjectAccess::ForMapAndOffset(initial_map,
9461                                          JSObject::kPropertiesOffset),
9462           empty_fixed_array);
9463       Add<HStoreNamedField>(receiver,
9464           HObjectAccess::ForMapAndOffset(initial_map,
9465                                          JSObject::kElementsOffset),
9466           empty_fixed_array);
9467       if (initial_map->inobject_properties() != 0) {
9468         HConstant* undefined = graph()->GetConstantUndefined();
9469         for (int i = 0; i < initial_map->inobject_properties(); i++) {
9470           int property_offset = initial_map->GetInObjectPropertyOffset(i);
9471           Add<HStoreNamedField>(receiver,
9472               HObjectAccess::ForMapAndOffset(initial_map, property_offset),
9473               undefined);
9474         }
9475       }
9476     }
9477
9478     // Replace the constructor function with a newly allocated receiver using
9479     // the index of the receiver from the top of the expression stack.
9480     const int receiver_index = argument_count - 1;
9481     DCHECK(environment()->ExpressionStackAt(receiver_index) == function);
9482     environment()->SetExpressionStackAt(receiver_index, receiver);
9483
9484     if (TryInlineConstruct(expr, receiver)) {
9485       // Inlining worked, add a dependency on the initial map to make sure that
9486       // this code is deoptimized whenever the initial map of the constructor
9487       // changes.
9488       Map::AddDependentCompilationInfo(
9489           initial_map, DependentCode::kInitialMapChangedGroup, top_info());
9490       return;
9491     }
9492
9493     // TODO(mstarzinger): For now we remove the previous HAllocate and all
9494     // corresponding instructions and instead add HPushArguments for the
9495     // arguments in case inlining failed.  What we actually should do is for
9496     // inlining to try to build a subgraph without mutating the parent graph.
9497     HInstruction* instr = current_block()->last();
9498     do {
9499       HInstruction* prev_instr = instr->previous();
9500       instr->DeleteAndReplaceWith(NULL);
9501       instr = prev_instr;
9502     } while (instr != check);
9503     environment()->SetExpressionStackAt(receiver_index, function);
9504     HInstruction* call =
9505       PreProcessCall(New<HCallNew>(function, argument_count));
9506     return ast_context()->ReturnInstruction(call, expr->id());
9507   } else {
9508     // The constructor function is both an operand to the instruction and an
9509     // argument to the construct call.
9510     if (TryHandleArrayCallNew(expr, function)) return;
9511
9512     HInstruction* call =
9513         PreProcessCall(New<HCallNew>(function, argument_count));
9514     return ast_context()->ReturnInstruction(call, expr->id());
9515   }
9516 }
9517
9518
9519 template <class ViewClass>
9520 void HGraphBuilder::BuildArrayBufferViewInitialization(
9521     HValue* obj,
9522     HValue* buffer,
9523     HValue* byte_offset,
9524     HValue* byte_length) {
9525
9526   for (int offset = ViewClass::kSize;
9527        offset < ViewClass::kSizeWithInternalFields;
9528        offset += kPointerSize) {
9529     Add<HStoreNamedField>(obj,
9530         HObjectAccess::ForObservableJSObjectOffset(offset),
9531         graph()->GetConstant0());
9532   }
9533
9534   Add<HStoreNamedField>(
9535       obj,
9536       HObjectAccess::ForJSArrayBufferViewByteOffset(),
9537       byte_offset);
9538   Add<HStoreNamedField>(
9539       obj,
9540       HObjectAccess::ForJSArrayBufferViewByteLength(),
9541       byte_length);
9542
9543   if (buffer != NULL) {
9544     Add<HStoreNamedField>(
9545         obj,
9546         HObjectAccess::ForJSArrayBufferViewBuffer(), buffer);
9547     HObjectAccess weak_first_view_access =
9548         HObjectAccess::ForJSArrayBufferWeakFirstView();
9549     Add<HStoreNamedField>(
9550         obj, HObjectAccess::ForJSArrayBufferViewWeakNext(),
9551         Add<HLoadNamedField>(buffer, nullptr, weak_first_view_access));
9552     Add<HStoreNamedField>(buffer, weak_first_view_access, obj);
9553   } else {
9554     Add<HStoreNamedField>(
9555         obj,
9556         HObjectAccess::ForJSArrayBufferViewBuffer(),
9557         Add<HConstant>(static_cast<int32_t>(0)));
9558     Add<HStoreNamedField>(obj,
9559         HObjectAccess::ForJSArrayBufferViewWeakNext(),
9560         graph()->GetConstantUndefined());
9561   }
9562 }
9563
9564
9565 void HOptimizedGraphBuilder::GenerateDataViewInitialize(
9566     CallRuntime* expr) {
9567   ZoneList<Expression*>* arguments = expr->arguments();
9568
9569   DCHECK(arguments->length()== 4);
9570   CHECK_ALIVE(VisitForValue(arguments->at(0)));
9571   HValue* obj = Pop();
9572
9573   CHECK_ALIVE(VisitForValue(arguments->at(1)));
9574   HValue* buffer = Pop();
9575
9576   CHECK_ALIVE(VisitForValue(arguments->at(2)));
9577   HValue* byte_offset = Pop();
9578
9579   CHECK_ALIVE(VisitForValue(arguments->at(3)));
9580   HValue* byte_length = Pop();
9581
9582   {
9583     NoObservableSideEffectsScope scope(this);
9584     BuildArrayBufferViewInitialization<JSDataView>(
9585         obj, buffer, byte_offset, byte_length);
9586   }
9587 }
9588
9589
9590 static Handle<Map> TypedArrayMap(Isolate* isolate,
9591                                  ExternalArrayType array_type,
9592                                  ElementsKind target_kind) {
9593   Handle<Context> native_context = isolate->native_context();
9594   Handle<JSFunction> fun;
9595   switch (array_type) {
9596 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
9597     case kExternal##Type##Array:                                              \
9598       fun = Handle<JSFunction>(native_context->type##_array_fun());           \
9599       break;
9600
9601     TYPED_ARRAYS(TYPED_ARRAY_CASE)
9602 #undef TYPED_ARRAY_CASE
9603   }
9604   Handle<Map> map(fun->initial_map());
9605   return Map::AsElementsKind(map, target_kind);
9606 }
9607
9608
9609 HValue* HOptimizedGraphBuilder::BuildAllocateExternalElements(
9610     ExternalArrayType array_type,
9611     bool is_zero_byte_offset,
9612     HValue* buffer, HValue* byte_offset, HValue* length) {
9613   Handle<Map> external_array_map(
9614       isolate()->heap()->MapForExternalArrayType(array_type));
9615
9616   // The HForceRepresentation is to prevent possible deopt on int-smi
9617   // conversion after allocation but before the new object fields are set.
9618   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
9619   HValue* elements =
9620       Add<HAllocate>(
9621           Add<HConstant>(ExternalArray::kAlignedSize),
9622           HType::HeapObject(),
9623           NOT_TENURED,
9624           external_array_map->instance_type());
9625
9626   AddStoreMapConstant(elements, external_array_map);
9627   Add<HStoreNamedField>(elements,
9628       HObjectAccess::ForFixedArrayLength(), length);
9629
9630   HValue* backing_store = Add<HLoadNamedField>(
9631       buffer, nullptr, HObjectAccess::ForJSArrayBufferBackingStore());
9632
9633   HValue* typed_array_start;
9634   if (is_zero_byte_offset) {
9635     typed_array_start = backing_store;
9636   } else {
9637     HInstruction* external_pointer =
9638         AddUncasted<HAdd>(backing_store, byte_offset);
9639     // Arguments are checked prior to call to TypedArrayInitialize,
9640     // including byte_offset.
9641     external_pointer->ClearFlag(HValue::kCanOverflow);
9642     typed_array_start = external_pointer;
9643   }
9644
9645   Add<HStoreNamedField>(elements,
9646       HObjectAccess::ForExternalArrayExternalPointer(),
9647       typed_array_start);
9648
9649   return elements;
9650 }
9651
9652
9653 HValue* HOptimizedGraphBuilder::BuildAllocateFixedTypedArray(
9654     ExternalArrayType array_type, size_t element_size,
9655     ElementsKind fixed_elements_kind,
9656     HValue* byte_length, HValue* length) {
9657   STATIC_ASSERT(
9658       (FixedTypedArrayBase::kHeaderSize & kObjectAlignmentMask) == 0);
9659   HValue* total_size;
9660
9661   // if fixed array's elements are not aligned to object's alignment,
9662   // we need to align the whole array to object alignment.
9663   if (element_size % kObjectAlignment != 0) {
9664     total_size = BuildObjectSizeAlignment(
9665         byte_length, FixedTypedArrayBase::kHeaderSize);
9666   } else {
9667     total_size = AddUncasted<HAdd>(byte_length,
9668         Add<HConstant>(FixedTypedArrayBase::kHeaderSize));
9669     total_size->ClearFlag(HValue::kCanOverflow);
9670   }
9671
9672   // The HForceRepresentation is to prevent possible deopt on int-smi
9673   // conversion after allocation but before the new object fields are set.
9674   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
9675   Handle<Map> fixed_typed_array_map(
9676       isolate()->heap()->MapForFixedTypedArray(array_type));
9677   HValue* elements =
9678       Add<HAllocate>(total_size, HType::HeapObject(),
9679                      NOT_TENURED, fixed_typed_array_map->instance_type());
9680   AddStoreMapConstant(elements, fixed_typed_array_map);
9681
9682   Add<HStoreNamedField>(elements,
9683       HObjectAccess::ForFixedArrayLength(),
9684       length);
9685
9686   HValue* filler = Add<HConstant>(static_cast<int32_t>(0));
9687
9688   {
9689     LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
9690
9691     HValue* key = builder.BeginBody(
9692         Add<HConstant>(static_cast<int32_t>(0)),
9693         length, Token::LT);
9694     Add<HStoreKeyed>(elements, key, filler, fixed_elements_kind);
9695
9696     builder.EndBody();
9697   }
9698   return elements;
9699 }
9700
9701
9702 void HOptimizedGraphBuilder::GenerateTypedArrayInitialize(
9703     CallRuntime* expr) {
9704   ZoneList<Expression*>* arguments = expr->arguments();
9705
9706   static const int kObjectArg = 0;
9707   static const int kArrayIdArg = 1;
9708   static const int kBufferArg = 2;
9709   static const int kByteOffsetArg = 3;
9710   static const int kByteLengthArg = 4;
9711   static const int kArgsLength = 5;
9712   DCHECK(arguments->length() == kArgsLength);
9713
9714
9715   CHECK_ALIVE(VisitForValue(arguments->at(kObjectArg)));
9716   HValue* obj = Pop();
9717
9718   if (arguments->at(kArrayIdArg)->IsLiteral()) {
9719     // This should never happen in real use, but can happen when fuzzing.
9720     // Just bail out.
9721     Bailout(kNeedSmiLiteral);
9722     return;
9723   }
9724   Handle<Object> value =
9725       static_cast<Literal*>(arguments->at(kArrayIdArg))->value();
9726   if (!value->IsSmi()) {
9727     // This should never happen in real use, but can happen when fuzzing.
9728     // Just bail out.
9729     Bailout(kNeedSmiLiteral);
9730     return;
9731   }
9732   int array_id = Smi::cast(*value)->value();
9733
9734   HValue* buffer;
9735   if (!arguments->at(kBufferArg)->IsNullLiteral()) {
9736     CHECK_ALIVE(VisitForValue(arguments->at(kBufferArg)));
9737     buffer = Pop();
9738   } else {
9739     buffer = NULL;
9740   }
9741
9742   HValue* byte_offset;
9743   bool is_zero_byte_offset;
9744
9745   if (arguments->at(kByteOffsetArg)->IsLiteral()
9746       && Smi::FromInt(0) ==
9747       *static_cast<Literal*>(arguments->at(kByteOffsetArg))->value()) {
9748     byte_offset = Add<HConstant>(static_cast<int32_t>(0));
9749     is_zero_byte_offset = true;
9750   } else {
9751     CHECK_ALIVE(VisitForValue(arguments->at(kByteOffsetArg)));
9752     byte_offset = Pop();
9753     is_zero_byte_offset = false;
9754     DCHECK(buffer != NULL);
9755   }
9756
9757   CHECK_ALIVE(VisitForValue(arguments->at(kByteLengthArg)));
9758   HValue* byte_length = Pop();
9759
9760   NoObservableSideEffectsScope scope(this);
9761   IfBuilder byte_offset_smi(this);
9762
9763   if (!is_zero_byte_offset) {
9764     byte_offset_smi.If<HIsSmiAndBranch>(byte_offset);
9765     byte_offset_smi.Then();
9766   }
9767
9768   ExternalArrayType array_type =
9769       kExternalInt8Array;  // Bogus initialization.
9770   size_t element_size = 1;  // Bogus initialization.
9771   ElementsKind external_elements_kind =  // Bogus initialization.
9772       EXTERNAL_INT8_ELEMENTS;
9773   ElementsKind fixed_elements_kind =  // Bogus initialization.
9774       INT8_ELEMENTS;
9775   Runtime::ArrayIdToTypeAndSize(array_id,
9776       &array_type,
9777       &external_elements_kind,
9778       &fixed_elements_kind,
9779       &element_size);
9780
9781
9782   { //  byte_offset is Smi.
9783     BuildArrayBufferViewInitialization<JSTypedArray>(
9784         obj, buffer, byte_offset, byte_length);
9785
9786
9787     HInstruction* length = AddUncasted<HDiv>(byte_length,
9788         Add<HConstant>(static_cast<int32_t>(element_size)));
9789
9790     Add<HStoreNamedField>(obj,
9791         HObjectAccess::ForJSTypedArrayLength(),
9792         length);
9793
9794     HValue* elements;
9795     if (buffer != NULL) {
9796       elements = BuildAllocateExternalElements(
9797           array_type, is_zero_byte_offset, buffer, byte_offset, length);
9798       Handle<Map> obj_map = TypedArrayMap(
9799           isolate(), array_type, external_elements_kind);
9800       AddStoreMapConstant(obj, obj_map);
9801     } else {
9802       DCHECK(is_zero_byte_offset);
9803       elements = BuildAllocateFixedTypedArray(
9804           array_type, element_size, fixed_elements_kind,
9805           byte_length, length);
9806     }
9807     Add<HStoreNamedField>(
9808         obj, HObjectAccess::ForElementsPointer(), elements);
9809   }
9810
9811   if (!is_zero_byte_offset) {
9812     byte_offset_smi.Else();
9813     { //  byte_offset is not Smi.
9814       Push(obj);
9815       CHECK_ALIVE(VisitForValue(arguments->at(kArrayIdArg)));
9816       Push(buffer);
9817       Push(byte_offset);
9818       Push(byte_length);
9819       PushArgumentsFromEnvironment(kArgsLength);
9820       Add<HCallRuntime>(expr->name(), expr->function(), kArgsLength);
9821     }
9822   }
9823   byte_offset_smi.End();
9824 }
9825
9826
9827 void HOptimizedGraphBuilder::GenerateMaxSmi(CallRuntime* expr) {
9828   DCHECK(expr->arguments()->length() == 0);
9829   HConstant* max_smi = New<HConstant>(static_cast<int32_t>(Smi::kMaxValue));
9830   return ast_context()->ReturnInstruction(max_smi, expr->id());
9831 }
9832
9833
9834 void HOptimizedGraphBuilder::GenerateTypedArrayMaxSizeInHeap(
9835     CallRuntime* expr) {
9836   DCHECK(expr->arguments()->length() == 0);
9837   HConstant* result = New<HConstant>(static_cast<int32_t>(
9838         FLAG_typed_array_max_size_in_heap));
9839   return ast_context()->ReturnInstruction(result, expr->id());
9840 }
9841
9842
9843 void HOptimizedGraphBuilder::GenerateArrayBufferGetByteLength(
9844     CallRuntime* expr) {
9845   DCHECK(expr->arguments()->length() == 1);
9846   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
9847   HValue* buffer = Pop();
9848   HInstruction* result = New<HLoadNamedField>(
9849       buffer, nullptr, HObjectAccess::ForJSArrayBufferByteLength());
9850   return ast_context()->ReturnInstruction(result, expr->id());
9851 }
9852
9853
9854 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength(
9855     CallRuntime* expr) {
9856   DCHECK(expr->arguments()->length() == 1);
9857   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
9858   HValue* buffer = Pop();
9859   HInstruction* result = New<HLoadNamedField>(
9860       buffer, nullptr, HObjectAccess::ForJSArrayBufferViewByteLength());
9861   return ast_context()->ReturnInstruction(result, expr->id());
9862 }
9863
9864
9865 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset(
9866     CallRuntime* expr) {
9867   DCHECK(expr->arguments()->length() == 1);
9868   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
9869   HValue* buffer = Pop();
9870   HInstruction* result = New<HLoadNamedField>(
9871       buffer, nullptr, HObjectAccess::ForJSArrayBufferViewByteOffset());
9872   return ast_context()->ReturnInstruction(result, expr->id());
9873 }
9874
9875
9876 void HOptimizedGraphBuilder::GenerateTypedArrayGetLength(
9877     CallRuntime* expr) {
9878   DCHECK(expr->arguments()->length() == 1);
9879   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
9880   HValue* buffer = Pop();
9881   HInstruction* result = New<HLoadNamedField>(
9882       buffer, nullptr, HObjectAccess::ForJSTypedArrayLength());
9883   return ast_context()->ReturnInstruction(result, expr->id());
9884 }
9885
9886
9887 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
9888   DCHECK(!HasStackOverflow());
9889   DCHECK(current_block() != NULL);
9890   DCHECK(current_block()->HasPredecessor());
9891   if (expr->is_jsruntime()) {
9892     return Bailout(kCallToAJavaScriptRuntimeFunction);
9893   }
9894
9895   const Runtime::Function* function = expr->function();
9896   DCHECK(function != NULL);
9897   switch (function->function_id) {
9898 #define CALL_INTRINSIC_GENERATOR(Name) \
9899   case Runtime::kInline##Name:         \
9900     return Generate##Name(expr);
9901
9902     FOR_EACH_HYDROGEN_INTRINSIC(CALL_INTRINSIC_GENERATOR)
9903 #undef CALL_INTRINSIC_GENERATOR
9904     default: {
9905       Handle<String> name = expr->name();
9906       int argument_count = expr->arguments()->length();
9907       CHECK_ALIVE(VisitExpressions(expr->arguments()));
9908       PushArgumentsFromEnvironment(argument_count);
9909       HCallRuntime* call = New<HCallRuntime>(name, function, argument_count);
9910       return ast_context()->ReturnInstruction(call, expr->id());
9911     }
9912   }
9913 }
9914
9915
9916 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
9917   DCHECK(!HasStackOverflow());
9918   DCHECK(current_block() != NULL);
9919   DCHECK(current_block()->HasPredecessor());
9920   switch (expr->op()) {
9921     case Token::DELETE: return VisitDelete(expr);
9922     case Token::VOID: return VisitVoid(expr);
9923     case Token::TYPEOF: return VisitTypeof(expr);
9924     case Token::NOT: return VisitNot(expr);
9925     default: UNREACHABLE();
9926   }
9927 }
9928
9929
9930 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
9931   Property* prop = expr->expression()->AsProperty();
9932   VariableProxy* proxy = expr->expression()->AsVariableProxy();
9933   if (prop != NULL) {
9934     CHECK_ALIVE(VisitForValue(prop->obj()));
9935     CHECK_ALIVE(VisitForValue(prop->key()));
9936     HValue* key = Pop();
9937     HValue* obj = Pop();
9938     HValue* function = AddLoadJSBuiltin(Builtins::DELETE);
9939     Add<HPushArguments>(obj, key, Add<HConstant>(function_language_mode()));
9940     // TODO(olivf) InvokeFunction produces a check for the parameter count,
9941     // even though we are certain to pass the correct number of arguments here.
9942     HInstruction* instr = New<HInvokeFunction>(function, 3);
9943     return ast_context()->ReturnInstruction(instr, expr->id());
9944   } else if (proxy != NULL) {
9945     Variable* var = proxy->var();
9946     if (var->IsUnallocated()) {
9947       Bailout(kDeleteWithGlobalVariable);
9948     } else if (var->IsStackAllocated() || var->IsContextSlot()) {
9949       // Result of deleting non-global variables is false.  'this' is not
9950       // really a variable, though we implement it as one.  The
9951       // subexpression does not have side effects.
9952       HValue* value = var->is_this()
9953           ? graph()->GetConstantTrue()
9954           : graph()->GetConstantFalse();
9955       return ast_context()->ReturnValue(value);
9956     } else {
9957       Bailout(kDeleteWithNonGlobalVariable);
9958     }
9959   } else {
9960     // Result of deleting non-property, non-variable reference is true.
9961     // Evaluate the subexpression for side effects.
9962     CHECK_ALIVE(VisitForEffect(expr->expression()));
9963     return ast_context()->ReturnValue(graph()->GetConstantTrue());
9964   }
9965 }
9966
9967
9968 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) {
9969   CHECK_ALIVE(VisitForEffect(expr->expression()));
9970   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
9971 }
9972
9973
9974 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
9975   CHECK_ALIVE(VisitForTypeOf(expr->expression()));
9976   HValue* value = Pop();
9977   HInstruction* instr = New<HTypeof>(value);
9978   return ast_context()->ReturnInstruction(instr, expr->id());
9979 }
9980
9981
9982 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) {
9983   if (ast_context()->IsTest()) {
9984     TestContext* context = TestContext::cast(ast_context());
9985     VisitForControl(expr->expression(),
9986                     context->if_false(),
9987                     context->if_true());
9988     return;
9989   }
9990
9991   if (ast_context()->IsEffect()) {
9992     VisitForEffect(expr->expression());
9993     return;
9994   }
9995
9996   DCHECK(ast_context()->IsValue());
9997   HBasicBlock* materialize_false = graph()->CreateBasicBlock();
9998   HBasicBlock* materialize_true = graph()->CreateBasicBlock();
9999   CHECK_BAILOUT(VisitForControl(expr->expression(),
10000                                 materialize_false,
10001                                 materialize_true));
10002
10003   if (materialize_false->HasPredecessor()) {
10004     materialize_false->SetJoinId(expr->MaterializeFalseId());
10005     set_current_block(materialize_false);
10006     Push(graph()->GetConstantFalse());
10007   } else {
10008     materialize_false = NULL;
10009   }
10010
10011   if (materialize_true->HasPredecessor()) {
10012     materialize_true->SetJoinId(expr->MaterializeTrueId());
10013     set_current_block(materialize_true);
10014     Push(graph()->GetConstantTrue());
10015   } else {
10016     materialize_true = NULL;
10017   }
10018
10019   HBasicBlock* join =
10020     CreateJoin(materialize_false, materialize_true, expr->id());
10021   set_current_block(join);
10022   if (join != NULL) return ast_context()->ReturnValue(Pop());
10023 }
10024
10025
10026 HInstruction* HOptimizedGraphBuilder::BuildIncrement(
10027     bool returns_original_input,
10028     CountOperation* expr) {
10029   // The input to the count operation is on top of the expression stack.
10030   Representation rep = Representation::FromType(expr->type());
10031   if (rep.IsNone() || rep.IsTagged()) {
10032     rep = Representation::Smi();
10033   }
10034
10035   if (returns_original_input) {
10036     // We need an explicit HValue representing ToNumber(input).  The
10037     // actual HChange instruction we need is (sometimes) added in a later
10038     // phase, so it is not available now to be used as an input to HAdd and
10039     // as the return value.
10040     HInstruction* number_input = AddUncasted<HForceRepresentation>(Pop(), rep);
10041     if (!rep.IsDouble()) {
10042       number_input->SetFlag(HInstruction::kFlexibleRepresentation);
10043       number_input->SetFlag(HInstruction::kCannotBeTagged);
10044     }
10045     Push(number_input);
10046   }
10047
10048   // The addition has no side effects, so we do not need
10049   // to simulate the expression stack after this instruction.
10050   // Any later failures deopt to the load of the input or earlier.
10051   HConstant* delta = (expr->op() == Token::INC)
10052       ? graph()->GetConstant1()
10053       : graph()->GetConstantMinus1();
10054   HInstruction* instr = AddUncasted<HAdd>(Top(), delta);
10055   if (instr->IsAdd()) {
10056     HAdd* add = HAdd::cast(instr);
10057     add->set_observed_input_representation(1, rep);
10058     add->set_observed_input_representation(2, Representation::Smi());
10059   }
10060   instr->SetFlag(HInstruction::kCannotBeTagged);
10061   instr->ClearAllSideEffects();
10062   return instr;
10063 }
10064
10065
10066 void HOptimizedGraphBuilder::BuildStoreForEffect(Expression* expr,
10067                                                  Property* prop,
10068                                                  BailoutId ast_id,
10069                                                  BailoutId return_id,
10070                                                  HValue* object,
10071                                                  HValue* key,
10072                                                  HValue* value) {
10073   EffectContext for_effect(this);
10074   Push(object);
10075   if (key != NULL) Push(key);
10076   Push(value);
10077   BuildStore(expr, prop, ast_id, return_id);
10078 }
10079
10080
10081 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
10082   DCHECK(!HasStackOverflow());
10083   DCHECK(current_block() != NULL);
10084   DCHECK(current_block()->HasPredecessor());
10085   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
10086   Expression* target = expr->expression();
10087   VariableProxy* proxy = target->AsVariableProxy();
10088   Property* prop = target->AsProperty();
10089   if (proxy == NULL && prop == NULL) {
10090     return Bailout(kInvalidLhsInCountOperation);
10091   }
10092
10093   // Match the full code generator stack by simulating an extra stack
10094   // element for postfix operations in a non-effect context.  The return
10095   // value is ToNumber(input).
10096   bool returns_original_input =
10097       expr->is_postfix() && !ast_context()->IsEffect();
10098   HValue* input = NULL;  // ToNumber(original_input).
10099   HValue* after = NULL;  // The result after incrementing or decrementing.
10100
10101   if (proxy != NULL) {
10102     Variable* var = proxy->var();
10103     if (var->mode() == CONST_LEGACY)  {
10104       return Bailout(kUnsupportedCountOperationWithConst);
10105     }
10106     if (var->mode() == CONST) {
10107       return Bailout(kNonInitializerAssignmentToConst);
10108     }
10109     // Argument of the count operation is a variable, not a property.
10110     DCHECK(prop == NULL);
10111     CHECK_ALIVE(VisitForValue(target));
10112
10113     after = BuildIncrement(returns_original_input, expr);
10114     input = returns_original_input ? Top() : Pop();
10115     Push(after);
10116
10117     switch (var->location()) {
10118       case Variable::UNALLOCATED:
10119         HandleGlobalVariableAssignment(var,
10120                                        after,
10121                                        expr->AssignmentId());
10122         break;
10123
10124       case Variable::PARAMETER:
10125       case Variable::LOCAL:
10126         BindIfLive(var, after);
10127         break;
10128
10129       case Variable::CONTEXT: {
10130         // Bail out if we try to mutate a parameter value in a function
10131         // using the arguments object.  We do not (yet) correctly handle the
10132         // arguments property of the function.
10133         if (current_info()->scope()->arguments() != NULL) {
10134           // Parameters will rewrite to context slots.  We have no direct
10135           // way to detect that the variable is a parameter so we use a
10136           // linear search of the parameter list.
10137           int count = current_info()->scope()->num_parameters();
10138           for (int i = 0; i < count; ++i) {
10139             if (var == current_info()->scope()->parameter(i)) {
10140               return Bailout(kAssignmentToParameterInArgumentsObject);
10141             }
10142           }
10143         }
10144
10145         HValue* context = BuildContextChainWalk(var);
10146         HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode())
10147             ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck;
10148         HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
10149                                                           mode, after);
10150         if (instr->HasObservableSideEffects()) {
10151           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
10152         }
10153         break;
10154       }
10155
10156       case Variable::LOOKUP:
10157         return Bailout(kLookupVariableInCountOperation);
10158     }
10159
10160     Drop(returns_original_input ? 2 : 1);
10161     return ast_context()->ReturnValue(expr->is_postfix() ? input : after);
10162   }
10163
10164   // Argument of the count operation is a property.
10165   DCHECK(prop != NULL);
10166   if (returns_original_input) Push(graph()->GetConstantUndefined());
10167
10168   CHECK_ALIVE(VisitForValue(prop->obj()));
10169   HValue* object = Top();
10170
10171   HValue* key = NULL;
10172   if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
10173     CHECK_ALIVE(VisitForValue(prop->key()));
10174     key = Top();
10175   }
10176
10177   CHECK_ALIVE(PushLoad(prop, object, key));
10178
10179   after = BuildIncrement(returns_original_input, expr);
10180
10181   if (returns_original_input) {
10182     input = Pop();
10183     // Drop object and key to push it again in the effect context below.
10184     Drop(key == NULL ? 1 : 2);
10185     environment()->SetExpressionStackAt(0, input);
10186     CHECK_ALIVE(BuildStoreForEffect(
10187         expr, prop, expr->id(), expr->AssignmentId(), object, key, after));
10188     return ast_context()->ReturnValue(Pop());
10189   }
10190
10191   environment()->SetExpressionStackAt(0, after);
10192   return BuildStore(expr, prop, expr->id(), expr->AssignmentId());
10193 }
10194
10195
10196 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt(
10197     HValue* string,
10198     HValue* index) {
10199   if (string->IsConstant() && index->IsConstant()) {
10200     HConstant* c_string = HConstant::cast(string);
10201     HConstant* c_index = HConstant::cast(index);
10202     if (c_string->HasStringValue() && c_index->HasNumberValue()) {
10203       int32_t i = c_index->NumberValueAsInteger32();
10204       Handle<String> s = c_string->StringValue();
10205       if (i < 0 || i >= s->length()) {
10206         return New<HConstant>(std::numeric_limits<double>::quiet_NaN());
10207       }
10208       return New<HConstant>(s->Get(i));
10209     }
10210   }
10211   string = BuildCheckString(string);
10212   index = Add<HBoundsCheck>(index, AddLoadStringLength(string));
10213   return New<HStringCharCodeAt>(string, index);
10214 }
10215
10216
10217 // Checks if the given shift amounts have following forms:
10218 // (N1) and (N2) with N1 + N2 = 32; (sa) and (32 - sa).
10219 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa,
10220                                              HValue* const32_minus_sa) {
10221   if (sa->IsConstant() && const32_minus_sa->IsConstant()) {
10222     const HConstant* c1 = HConstant::cast(sa);
10223     const HConstant* c2 = HConstant::cast(const32_minus_sa);
10224     return c1->HasInteger32Value() && c2->HasInteger32Value() &&
10225         (c1->Integer32Value() + c2->Integer32Value() == 32);
10226   }
10227   if (!const32_minus_sa->IsSub()) return false;
10228   HSub* sub = HSub::cast(const32_minus_sa);
10229   return sub->left()->EqualsInteger32Constant(32) && sub->right() == sa;
10230 }
10231
10232
10233 // Checks if the left and the right are shift instructions with the oposite
10234 // directions that can be replaced by one rotate right instruction or not.
10235 // Returns the operand and the shift amount for the rotate instruction in the
10236 // former case.
10237 bool HGraphBuilder::MatchRotateRight(HValue* left,
10238                                      HValue* right,
10239                                      HValue** operand,
10240                                      HValue** shift_amount) {
10241   HShl* shl;
10242   HShr* shr;
10243   if (left->IsShl() && right->IsShr()) {
10244     shl = HShl::cast(left);
10245     shr = HShr::cast(right);
10246   } else if (left->IsShr() && right->IsShl()) {
10247     shl = HShl::cast(right);
10248     shr = HShr::cast(left);
10249   } else {
10250     return false;
10251   }
10252   if (shl->left() != shr->left()) return false;
10253
10254   if (!ShiftAmountsAllowReplaceByRotate(shl->right(), shr->right()) &&
10255       !ShiftAmountsAllowReplaceByRotate(shr->right(), shl->right())) {
10256     return false;
10257   }
10258   *operand = shr->left();
10259   *shift_amount = shr->right();
10260   return true;
10261 }
10262
10263
10264 bool CanBeZero(HValue* right) {
10265   if (right->IsConstant()) {
10266     HConstant* right_const = HConstant::cast(right);
10267     if (right_const->HasInteger32Value() &&
10268        (right_const->Integer32Value() & 0x1f) != 0) {
10269       return false;
10270     }
10271   }
10272   return true;
10273 }
10274
10275
10276 HValue* HGraphBuilder::EnforceNumberType(HValue* number,
10277                                          Type* expected) {
10278   if (expected->Is(Type::SignedSmall())) {
10279     return AddUncasted<HForceRepresentation>(number, Representation::Smi());
10280   }
10281   if (expected->Is(Type::Signed32())) {
10282     return AddUncasted<HForceRepresentation>(number,
10283                                              Representation::Integer32());
10284   }
10285   return number;
10286 }
10287
10288
10289 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Type** expected) {
10290   if (value->IsConstant()) {
10291     HConstant* constant = HConstant::cast(value);
10292     Maybe<HConstant*> number =
10293         constant->CopyToTruncatedNumber(isolate(), zone());
10294     if (number.IsJust()) {
10295       *expected = Type::Number(zone());
10296       return AddInstruction(number.FromJust());
10297     }
10298   }
10299
10300   // We put temporary values on the stack, which don't correspond to anything
10301   // in baseline code. Since nothing is observable we avoid recording those
10302   // pushes with a NoObservableSideEffectsScope.
10303   NoObservableSideEffectsScope no_effects(this);
10304
10305   Type* expected_type = *expected;
10306
10307   // Separate the number type from the rest.
10308   Type* expected_obj =
10309       Type::Intersect(expected_type, Type::NonNumber(zone()), zone());
10310   Type* expected_number =
10311       Type::Intersect(expected_type, Type::Number(zone()), zone());
10312
10313   // We expect to get a number.
10314   // (We need to check first, since Type::None->Is(Type::Any()) == true.
10315   if (expected_obj->Is(Type::None())) {
10316     DCHECK(!expected_number->Is(Type::None(zone())));
10317     return value;
10318   }
10319
10320   if (expected_obj->Is(Type::Undefined(zone()))) {
10321     // This is already done by HChange.
10322     *expected = Type::Union(expected_number, Type::Number(zone()), zone());
10323     return value;
10324   }
10325
10326   return value;
10327 }
10328
10329
10330 HValue* HOptimizedGraphBuilder::BuildBinaryOperation(
10331     BinaryOperation* expr,
10332     HValue* left,
10333     HValue* right,
10334     PushBeforeSimulateBehavior push_sim_result) {
10335   Type* left_type = expr->left()->bounds().lower;
10336   Type* right_type = expr->right()->bounds().lower;
10337   Type* result_type = expr->bounds().lower;
10338   Maybe<int> fixed_right_arg = expr->fixed_right_arg();
10339   Handle<AllocationSite> allocation_site = expr->allocation_site();
10340
10341   HAllocationMode allocation_mode;
10342   if (FLAG_allocation_site_pretenuring && !allocation_site.is_null()) {
10343     allocation_mode = HAllocationMode(allocation_site);
10344   }
10345
10346   HValue* result = HGraphBuilder::BuildBinaryOperation(
10347       expr->op(), left, right, left_type, right_type, result_type,
10348       fixed_right_arg, allocation_mode);
10349   // Add a simulate after instructions with observable side effects, and
10350   // after phis, which are the result of BuildBinaryOperation when we
10351   // inlined some complex subgraph.
10352   if (result->HasObservableSideEffects() || result->IsPhi()) {
10353     if (push_sim_result == PUSH_BEFORE_SIMULATE) {
10354       Push(result);
10355       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
10356       Drop(1);
10357     } else {
10358       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
10359     }
10360   }
10361   return result;
10362 }
10363
10364
10365 HValue* HGraphBuilder::BuildBinaryOperation(
10366     Token::Value op,
10367     HValue* left,
10368     HValue* right,
10369     Type* left_type,
10370     Type* right_type,
10371     Type* result_type,
10372     Maybe<int> fixed_right_arg,
10373     HAllocationMode allocation_mode) {
10374
10375   Representation left_rep = Representation::FromType(left_type);
10376   Representation right_rep = Representation::FromType(right_type);
10377
10378   bool maybe_string_add = op == Token::ADD &&
10379                           (left_type->Maybe(Type::String()) ||
10380                            left_type->Maybe(Type::Receiver()) ||
10381                            right_type->Maybe(Type::String()) ||
10382                            right_type->Maybe(Type::Receiver()));
10383
10384   if (!left_type->IsInhabited()) {
10385     Add<HDeoptimize>(
10386         Deoptimizer::kInsufficientTypeFeedbackForLHSOfBinaryOperation,
10387         Deoptimizer::SOFT);
10388     // TODO(rossberg): we should be able to get rid of non-continuous
10389     // defaults.
10390     left_type = Type::Any(zone());
10391   } else {
10392     if (!maybe_string_add) left = TruncateToNumber(left, &left_type);
10393     left_rep = Representation::FromType(left_type);
10394   }
10395
10396   if (!right_type->IsInhabited()) {
10397     Add<HDeoptimize>(
10398         Deoptimizer::kInsufficientTypeFeedbackForRHSOfBinaryOperation,
10399         Deoptimizer::SOFT);
10400     right_type = Type::Any(zone());
10401   } else {
10402     if (!maybe_string_add) right = TruncateToNumber(right, &right_type);
10403     right_rep = Representation::FromType(right_type);
10404   }
10405
10406   // Special case for string addition here.
10407   if (op == Token::ADD &&
10408       (left_type->Is(Type::String()) || right_type->Is(Type::String()))) {
10409     // Validate type feedback for left argument.
10410     if (left_type->Is(Type::String())) {
10411       left = BuildCheckString(left);
10412     }
10413
10414     // Validate type feedback for right argument.
10415     if (right_type->Is(Type::String())) {
10416       right = BuildCheckString(right);
10417     }
10418
10419     // Convert left argument as necessary.
10420     if (left_type->Is(Type::Number())) {
10421       DCHECK(right_type->Is(Type::String()));
10422       left = BuildNumberToString(left, left_type);
10423     } else if (!left_type->Is(Type::String())) {
10424       DCHECK(right_type->Is(Type::String()));
10425       HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_RIGHT);
10426       Add<HPushArguments>(left, right);
10427       return AddUncasted<HInvokeFunction>(function, 2);
10428     }
10429
10430     // Convert right argument as necessary.
10431     if (right_type->Is(Type::Number())) {
10432       DCHECK(left_type->Is(Type::String()));
10433       right = BuildNumberToString(right, right_type);
10434     } else if (!right_type->Is(Type::String())) {
10435       DCHECK(left_type->Is(Type::String()));
10436       HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT);
10437       Add<HPushArguments>(left, right);
10438       return AddUncasted<HInvokeFunction>(function, 2);
10439     }
10440
10441     // Fast paths for empty constant strings.
10442     Handle<String> left_string =
10443         left->IsConstant() && HConstant::cast(left)->HasStringValue()
10444             ? HConstant::cast(left)->StringValue()
10445             : Handle<String>();
10446     Handle<String> right_string =
10447         right->IsConstant() && HConstant::cast(right)->HasStringValue()
10448             ? HConstant::cast(right)->StringValue()
10449             : Handle<String>();
10450     if (!left_string.is_null() && left_string->length() == 0) return right;
10451     if (!right_string.is_null() && right_string->length() == 0) return left;
10452     if (!left_string.is_null() && !right_string.is_null()) {
10453       return AddUncasted<HStringAdd>(
10454           left, right, allocation_mode.GetPretenureMode(),
10455           STRING_ADD_CHECK_NONE, allocation_mode.feedback_site());
10456     }
10457
10458     // Register the dependent code with the allocation site.
10459     if (!allocation_mode.feedback_site().is_null()) {
10460       DCHECK(!graph()->info()->IsStub());
10461       Handle<AllocationSite> site(allocation_mode.feedback_site());
10462       AllocationSite::RegisterForDeoptOnTenureChange(site, top_info());
10463     }
10464
10465     // Inline the string addition into the stub when creating allocation
10466     // mementos to gather allocation site feedback, or if we can statically
10467     // infer that we're going to create a cons string.
10468     if ((graph()->info()->IsStub() &&
10469          allocation_mode.CreateAllocationMementos()) ||
10470         (left->IsConstant() &&
10471          HConstant::cast(left)->HasStringValue() &&
10472          HConstant::cast(left)->StringValue()->length() + 1 >=
10473            ConsString::kMinLength) ||
10474         (right->IsConstant() &&
10475          HConstant::cast(right)->HasStringValue() &&
10476          HConstant::cast(right)->StringValue()->length() + 1 >=
10477            ConsString::kMinLength)) {
10478       return BuildStringAdd(left, right, allocation_mode);
10479     }
10480
10481     // Fallback to using the string add stub.
10482     return AddUncasted<HStringAdd>(
10483         left, right, allocation_mode.GetPretenureMode(),
10484         STRING_ADD_CHECK_NONE, allocation_mode.feedback_site());
10485   }
10486
10487   if (graph()->info()->IsStub()) {
10488     left = EnforceNumberType(left, left_type);
10489     right = EnforceNumberType(right, right_type);
10490   }
10491
10492   Representation result_rep = Representation::FromType(result_type);
10493
10494   bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) ||
10495                           (right_rep.IsTagged() && !right_rep.IsSmi());
10496
10497   HInstruction* instr = NULL;
10498   // Only the stub is allowed to call into the runtime, since otherwise we would
10499   // inline several instructions (including the two pushes) for every tagged
10500   // operation in optimized code, which is more expensive, than a stub call.
10501   if (graph()->info()->IsStub() && is_non_primitive) {
10502     HValue* function = AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op));
10503     Add<HPushArguments>(left, right);
10504     instr = AddUncasted<HInvokeFunction>(function, 2);
10505   } else {
10506     switch (op) {
10507       case Token::ADD:
10508         instr = AddUncasted<HAdd>(left, right);
10509         break;
10510       case Token::SUB:
10511         instr = AddUncasted<HSub>(left, right);
10512         break;
10513       case Token::MUL:
10514         instr = AddUncasted<HMul>(left, right);
10515         break;
10516       case Token::MOD: {
10517         if (fixed_right_arg.IsJust() &&
10518             !right->EqualsInteger32Constant(fixed_right_arg.FromJust())) {
10519           HConstant* fixed_right =
10520               Add<HConstant>(static_cast<int>(fixed_right_arg.FromJust()));
10521           IfBuilder if_same(this);
10522           if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ);
10523           if_same.Then();
10524           if_same.ElseDeopt(Deoptimizer::kUnexpectedRHSOfBinaryOperation);
10525           right = fixed_right;
10526         }
10527         instr = AddUncasted<HMod>(left, right);
10528         break;
10529       }
10530       case Token::DIV:
10531         instr = AddUncasted<HDiv>(left, right);
10532         break;
10533       case Token::BIT_XOR:
10534       case Token::BIT_AND:
10535         instr = AddUncasted<HBitwise>(op, left, right);
10536         break;
10537       case Token::BIT_OR: {
10538         HValue* operand, *shift_amount;
10539         if (left_type->Is(Type::Signed32()) &&
10540             right_type->Is(Type::Signed32()) &&
10541             MatchRotateRight(left, right, &operand, &shift_amount)) {
10542           instr = AddUncasted<HRor>(operand, shift_amount);
10543         } else {
10544           instr = AddUncasted<HBitwise>(op, left, right);
10545         }
10546         break;
10547       }
10548       case Token::SAR:
10549         instr = AddUncasted<HSar>(left, right);
10550         break;
10551       case Token::SHR:
10552         instr = AddUncasted<HShr>(left, right);
10553         if (instr->IsShr() && CanBeZero(right)) {
10554           graph()->RecordUint32Instruction(instr);
10555         }
10556         break;
10557       case Token::SHL:
10558         instr = AddUncasted<HShl>(left, right);
10559         break;
10560       default:
10561         UNREACHABLE();
10562     }
10563   }
10564
10565   if (instr->IsBinaryOperation()) {
10566     HBinaryOperation* binop = HBinaryOperation::cast(instr);
10567     binop->set_observed_input_representation(1, left_rep);
10568     binop->set_observed_input_representation(2, right_rep);
10569     binop->initialize_output_representation(result_rep);
10570     if (graph()->info()->IsStub()) {
10571       // Stub should not call into stub.
10572       instr->SetFlag(HValue::kCannotBeTagged);
10573       // And should truncate on HForceRepresentation already.
10574       if (left->IsForceRepresentation()) {
10575         left->CopyFlag(HValue::kTruncatingToSmi, instr);
10576         left->CopyFlag(HValue::kTruncatingToInt32, instr);
10577       }
10578       if (right->IsForceRepresentation()) {
10579         right->CopyFlag(HValue::kTruncatingToSmi, instr);
10580         right->CopyFlag(HValue::kTruncatingToInt32, instr);
10581       }
10582     }
10583   }
10584   return instr;
10585 }
10586
10587
10588 // Check for the form (%_ClassOf(foo) === 'BarClass').
10589 static bool IsClassOfTest(CompareOperation* expr) {
10590   if (expr->op() != Token::EQ_STRICT) return false;
10591   CallRuntime* call = expr->left()->AsCallRuntime();
10592   if (call == NULL) return false;
10593   Literal* literal = expr->right()->AsLiteral();
10594   if (literal == NULL) return false;
10595   if (!literal->value()->IsString()) return false;
10596   if (!call->name()->IsOneByteEqualTo(STATIC_CHAR_VECTOR("_ClassOf"))) {
10597     return false;
10598   }
10599   DCHECK(call->arguments()->length() == 1);
10600   return true;
10601 }
10602
10603
10604 void HOptimizedGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
10605   DCHECK(!HasStackOverflow());
10606   DCHECK(current_block() != NULL);
10607   DCHECK(current_block()->HasPredecessor());
10608   switch (expr->op()) {
10609     case Token::COMMA:
10610       return VisitComma(expr);
10611     case Token::OR:
10612     case Token::AND:
10613       return VisitLogicalExpression(expr);
10614     default:
10615       return VisitArithmeticExpression(expr);
10616   }
10617 }
10618
10619
10620 void HOptimizedGraphBuilder::VisitComma(BinaryOperation* expr) {
10621   CHECK_ALIVE(VisitForEffect(expr->left()));
10622   // Visit the right subexpression in the same AST context as the entire
10623   // expression.
10624   Visit(expr->right());
10625 }
10626
10627
10628 void HOptimizedGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
10629   bool is_logical_and = expr->op() == Token::AND;
10630   if (ast_context()->IsTest()) {
10631     TestContext* context = TestContext::cast(ast_context());
10632     // Translate left subexpression.
10633     HBasicBlock* eval_right = graph()->CreateBasicBlock();
10634     if (is_logical_and) {
10635       CHECK_BAILOUT(VisitForControl(expr->left(),
10636                                     eval_right,
10637                                     context->if_false()));
10638     } else {
10639       CHECK_BAILOUT(VisitForControl(expr->left(),
10640                                     context->if_true(),
10641                                     eval_right));
10642     }
10643
10644     // Translate right subexpression by visiting it in the same AST
10645     // context as the entire expression.
10646     if (eval_right->HasPredecessor()) {
10647       eval_right->SetJoinId(expr->RightId());
10648       set_current_block(eval_right);
10649       Visit(expr->right());
10650     }
10651
10652   } else if (ast_context()->IsValue()) {
10653     CHECK_ALIVE(VisitForValue(expr->left()));
10654     DCHECK(current_block() != NULL);
10655     HValue* left_value = Top();
10656
10657     // Short-circuit left values that always evaluate to the same boolean value.
10658     if (expr->left()->ToBooleanIsTrue() || expr->left()->ToBooleanIsFalse()) {
10659       // l (evals true)  && r -> r
10660       // l (evals true)  || r -> l
10661       // l (evals false) && r -> l
10662       // l (evals false) || r -> r
10663       if (is_logical_and == expr->left()->ToBooleanIsTrue()) {
10664         Drop(1);
10665         CHECK_ALIVE(VisitForValue(expr->right()));
10666       }
10667       return ast_context()->ReturnValue(Pop());
10668     }
10669
10670     // We need an extra block to maintain edge-split form.
10671     HBasicBlock* empty_block = graph()->CreateBasicBlock();
10672     HBasicBlock* eval_right = graph()->CreateBasicBlock();
10673     ToBooleanStub::Types expected(expr->left()->to_boolean_types());
10674     HBranch* test = is_logical_and
10675         ? New<HBranch>(left_value, expected, eval_right, empty_block)
10676         : New<HBranch>(left_value, expected, empty_block, eval_right);
10677     FinishCurrentBlock(test);
10678
10679     set_current_block(eval_right);
10680     Drop(1);  // Value of the left subexpression.
10681     CHECK_BAILOUT(VisitForValue(expr->right()));
10682
10683     HBasicBlock* join_block =
10684       CreateJoin(empty_block, current_block(), expr->id());
10685     set_current_block(join_block);
10686     return ast_context()->ReturnValue(Pop());
10687
10688   } else {
10689     DCHECK(ast_context()->IsEffect());
10690     // In an effect context, we don't need the value of the left subexpression,
10691     // only its control flow and side effects.  We need an extra block to
10692     // maintain edge-split form.
10693     HBasicBlock* empty_block = graph()->CreateBasicBlock();
10694     HBasicBlock* right_block = graph()->CreateBasicBlock();
10695     if (is_logical_and) {
10696       CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
10697     } else {
10698       CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
10699     }
10700
10701     // TODO(kmillikin): Find a way to fix this.  It's ugly that there are
10702     // actually two empty blocks (one here and one inserted by
10703     // TestContext::BuildBranch, and that they both have an HSimulate though the
10704     // second one is not a merge node, and that we really have no good AST ID to
10705     // put on that first HSimulate.
10706
10707     if (empty_block->HasPredecessor()) {
10708       empty_block->SetJoinId(expr->id());
10709     } else {
10710       empty_block = NULL;
10711     }
10712
10713     if (right_block->HasPredecessor()) {
10714       right_block->SetJoinId(expr->RightId());
10715       set_current_block(right_block);
10716       CHECK_BAILOUT(VisitForEffect(expr->right()));
10717       right_block = current_block();
10718     } else {
10719       right_block = NULL;
10720     }
10721
10722     HBasicBlock* join_block =
10723       CreateJoin(empty_block, right_block, expr->id());
10724     set_current_block(join_block);
10725     // We did not materialize any value in the predecessor environments,
10726     // so there is no need to handle it here.
10727   }
10728 }
10729
10730
10731 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
10732   CHECK_ALIVE(VisitForValue(expr->left()));
10733   CHECK_ALIVE(VisitForValue(expr->right()));
10734   SetSourcePosition(expr->position());
10735   HValue* right = Pop();
10736   HValue* left = Pop();
10737   HValue* result =
10738       BuildBinaryOperation(expr, left, right,
10739           ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
10740                                     : PUSH_BEFORE_SIMULATE);
10741   if (top_info()->is_tracking_positions() && result->IsBinaryOperation()) {
10742     HBinaryOperation::cast(result)->SetOperandPositions(
10743         zone(),
10744         ScriptPositionToSourcePosition(expr->left()->position()),
10745         ScriptPositionToSourcePosition(expr->right()->position()));
10746   }
10747   return ast_context()->ReturnValue(result);
10748 }
10749
10750
10751 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
10752                                                         Expression* sub_expr,
10753                                                         Handle<String> check) {
10754   CHECK_ALIVE(VisitForTypeOf(sub_expr));
10755   SetSourcePosition(expr->position());
10756   HValue* value = Pop();
10757   HTypeofIsAndBranch* instr = New<HTypeofIsAndBranch>(value, check);
10758   return ast_context()->ReturnControl(instr, expr->id());
10759 }
10760
10761
10762 static bool IsLiteralCompareBool(Isolate* isolate,
10763                                  HValue* left,
10764                                  Token::Value op,
10765                                  HValue* right) {
10766   return op == Token::EQ_STRICT &&
10767       ((left->IsConstant() &&
10768           HConstant::cast(left)->handle(isolate)->IsBoolean()) ||
10769        (right->IsConstant() &&
10770            HConstant::cast(right)->handle(isolate)->IsBoolean()));
10771 }
10772
10773
10774 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
10775   DCHECK(!HasStackOverflow());
10776   DCHECK(current_block() != NULL);
10777   DCHECK(current_block()->HasPredecessor());
10778
10779   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
10780
10781   // Check for a few fast cases. The AST visiting behavior must be in sync
10782   // with the full codegen: We don't push both left and right values onto
10783   // the expression stack when one side is a special-case literal.
10784   Expression* sub_expr = NULL;
10785   Handle<String> check;
10786   if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
10787     return HandleLiteralCompareTypeof(expr, sub_expr, check);
10788   }
10789   if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) {
10790     return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
10791   }
10792   if (expr->IsLiteralCompareNull(&sub_expr)) {
10793     return HandleLiteralCompareNil(expr, sub_expr, kNullValue);
10794   }
10795
10796   if (IsClassOfTest(expr)) {
10797     CallRuntime* call = expr->left()->AsCallRuntime();
10798     DCHECK(call->arguments()->length() == 1);
10799     CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10800     HValue* value = Pop();
10801     Literal* literal = expr->right()->AsLiteral();
10802     Handle<String> rhs = Handle<String>::cast(literal->value());
10803     HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs);
10804     return ast_context()->ReturnControl(instr, expr->id());
10805   }
10806
10807   Type* left_type = expr->left()->bounds().lower;
10808   Type* right_type = expr->right()->bounds().lower;
10809   Type* combined_type = expr->combined_type();
10810
10811   CHECK_ALIVE(VisitForValue(expr->left()));
10812   CHECK_ALIVE(VisitForValue(expr->right()));
10813
10814   HValue* right = Pop();
10815   HValue* left = Pop();
10816   Token::Value op = expr->op();
10817
10818   if (IsLiteralCompareBool(isolate(), left, op, right)) {
10819     HCompareObjectEqAndBranch* result =
10820         New<HCompareObjectEqAndBranch>(left, right);
10821     return ast_context()->ReturnControl(result, expr->id());
10822   }
10823
10824   if (op == Token::INSTANCEOF) {
10825     // Check to see if the rhs of the instanceof is a global function not
10826     // residing in new space. If it is we assume that the function will stay the
10827     // same.
10828     Handle<JSFunction> target = Handle<JSFunction>::null();
10829     VariableProxy* proxy = expr->right()->AsVariableProxy();
10830     bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated();
10831     if (global_function && current_info()->has_global_object()) {
10832       Handle<String> name = proxy->name();
10833       Handle<GlobalObject> global(current_info()->global_object());
10834       LookupIterator it(global, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
10835       Handle<Object> value = JSObject::GetDataProperty(&it);
10836       if (it.IsFound() && value->IsJSFunction()) {
10837         Handle<JSFunction> candidate = Handle<JSFunction>::cast(value);
10838         // If the function is in new space we assume it's more likely to
10839         // change and thus prefer the general IC code.
10840         if (!isolate()->heap()->InNewSpace(*candidate)) {
10841           target = candidate;
10842         }
10843       }
10844     }
10845
10846     // If the target is not null we have found a known global function that is
10847     // assumed to stay the same for this instanceof.
10848     if (target.is_null()) {
10849       HInstanceOf* result = New<HInstanceOf>(left, right);
10850       return ast_context()->ReturnInstruction(result, expr->id());
10851     } else {
10852       Add<HCheckValue>(right, target);
10853       HInstanceOfKnownGlobal* result =
10854         New<HInstanceOfKnownGlobal>(left, target);
10855       return ast_context()->ReturnInstruction(result, expr->id());
10856     }
10857
10858     // Code below assumes that we don't fall through.
10859     UNREACHABLE();
10860   } else if (op == Token::IN) {
10861     HValue* function = AddLoadJSBuiltin(Builtins::IN);
10862     Add<HPushArguments>(left, right);
10863     // TODO(olivf) InvokeFunction produces a check for the parameter count,
10864     // even though we are certain to pass the correct number of arguments here.
10865     HInstruction* result = New<HInvokeFunction>(function, 2);
10866     return ast_context()->ReturnInstruction(result, expr->id());
10867   }
10868
10869   PushBeforeSimulateBehavior push_behavior =
10870     ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
10871                               : PUSH_BEFORE_SIMULATE;
10872   HControlInstruction* compare = BuildCompareInstruction(
10873       op, left, right, left_type, right_type, combined_type,
10874       ScriptPositionToSourcePosition(expr->left()->position()),
10875       ScriptPositionToSourcePosition(expr->right()->position()),
10876       push_behavior, expr->id());
10877   if (compare == NULL) return;  // Bailed out.
10878   return ast_context()->ReturnControl(compare, expr->id());
10879 }
10880
10881
10882 HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
10883     Token::Value op, HValue* left, HValue* right, Type* left_type,
10884     Type* right_type, Type* combined_type, SourcePosition left_position,
10885     SourcePosition right_position, PushBeforeSimulateBehavior push_sim_result,
10886     BailoutId bailout_id) {
10887   // Cases handled below depend on collected type feedback. They should
10888   // soft deoptimize when there is no type feedback.
10889   if (!combined_type->IsInhabited()) {
10890     Add<HDeoptimize>(
10891         Deoptimizer::kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation,
10892         Deoptimizer::SOFT);
10893     combined_type = left_type = right_type = Type::Any(zone());
10894   }
10895
10896   Representation left_rep = Representation::FromType(left_type);
10897   Representation right_rep = Representation::FromType(right_type);
10898   Representation combined_rep = Representation::FromType(combined_type);
10899
10900   if (combined_type->Is(Type::Receiver())) {
10901     if (Token::IsEqualityOp(op)) {
10902       // HCompareObjectEqAndBranch can only deal with object, so
10903       // exclude numbers.
10904       if ((left->IsConstant() &&
10905            HConstant::cast(left)->HasNumberValue()) ||
10906           (right->IsConstant() &&
10907            HConstant::cast(right)->HasNumberValue())) {
10908         Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant,
10909                          Deoptimizer::SOFT);
10910         // The caller expects a branch instruction, so make it happy.
10911         return New<HBranch>(graph()->GetConstantTrue());
10912       }
10913       // Can we get away with map check and not instance type check?
10914       HValue* operand_to_check =
10915           left->block()->block_id() < right->block()->block_id() ? left : right;
10916       if (combined_type->IsClass()) {
10917         Handle<Map> map = combined_type->AsClass()->Map();
10918         AddCheckMap(operand_to_check, map);
10919         HCompareObjectEqAndBranch* result =
10920             New<HCompareObjectEqAndBranch>(left, right);
10921         if (top_info()->is_tracking_positions()) {
10922           result->set_operand_position(zone(), 0, left_position);
10923           result->set_operand_position(zone(), 1, right_position);
10924         }
10925         return result;
10926       } else {
10927         BuildCheckHeapObject(operand_to_check);
10928         Add<HCheckInstanceType>(operand_to_check,
10929                                 HCheckInstanceType::IS_SPEC_OBJECT);
10930         HCompareObjectEqAndBranch* result =
10931             New<HCompareObjectEqAndBranch>(left, right);
10932         return result;
10933       }
10934     } else {
10935       Bailout(kUnsupportedNonPrimitiveCompare);
10936       return NULL;
10937     }
10938   } else if (combined_type->Is(Type::InternalizedString()) &&
10939              Token::IsEqualityOp(op)) {
10940     // If we have a constant argument, it should be consistent with the type
10941     // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch).
10942     if ((left->IsConstant() &&
10943          !HConstant::cast(left)->HasInternalizedStringValue()) ||
10944         (right->IsConstant() &&
10945          !HConstant::cast(right)->HasInternalizedStringValue())) {
10946       Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant,
10947                        Deoptimizer::SOFT);
10948       // The caller expects a branch instruction, so make it happy.
10949       return New<HBranch>(graph()->GetConstantTrue());
10950     }
10951     BuildCheckHeapObject(left);
10952     Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING);
10953     BuildCheckHeapObject(right);
10954     Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING);
10955     HCompareObjectEqAndBranch* result =
10956         New<HCompareObjectEqAndBranch>(left, right);
10957     return result;
10958   } else if (combined_type->Is(Type::String())) {
10959     BuildCheckHeapObject(left);
10960     Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING);
10961     BuildCheckHeapObject(right);
10962     Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING);
10963     HStringCompareAndBranch* result =
10964         New<HStringCompareAndBranch>(left, right, op);
10965     return result;
10966   } else {
10967     if (combined_rep.IsTagged() || combined_rep.IsNone()) {
10968       HCompareGeneric* result = Add<HCompareGeneric>(left, right, op);
10969       result->set_observed_input_representation(1, left_rep);
10970       result->set_observed_input_representation(2, right_rep);
10971       if (result->HasObservableSideEffects()) {
10972         if (push_sim_result == PUSH_BEFORE_SIMULATE) {
10973           Push(result);
10974           AddSimulate(bailout_id, REMOVABLE_SIMULATE);
10975           Drop(1);
10976         } else {
10977           AddSimulate(bailout_id, REMOVABLE_SIMULATE);
10978         }
10979       }
10980       // TODO(jkummerow): Can we make this more efficient?
10981       HBranch* branch = New<HBranch>(result);
10982       return branch;
10983     } else {
10984       HCompareNumericAndBranch* result =
10985           New<HCompareNumericAndBranch>(left, right, op);
10986       result->set_observed_input_representation(left_rep, right_rep);
10987       if (top_info()->is_tracking_positions()) {
10988         result->SetOperandPositions(zone(), left_position, right_position);
10989       }
10990       return result;
10991     }
10992   }
10993 }
10994
10995
10996 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
10997                                                      Expression* sub_expr,
10998                                                      NilValue nil) {
10999   DCHECK(!HasStackOverflow());
11000   DCHECK(current_block() != NULL);
11001   DCHECK(current_block()->HasPredecessor());
11002   DCHECK(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
11003   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
11004   CHECK_ALIVE(VisitForValue(sub_expr));
11005   HValue* value = Pop();
11006   if (expr->op() == Token::EQ_STRICT) {
11007     HConstant* nil_constant = nil == kNullValue
11008         ? graph()->GetConstantNull()
11009         : graph()->GetConstantUndefined();
11010     HCompareObjectEqAndBranch* instr =
11011         New<HCompareObjectEqAndBranch>(value, nil_constant);
11012     return ast_context()->ReturnControl(instr, expr->id());
11013   } else {
11014     DCHECK_EQ(Token::EQ, expr->op());
11015     Type* type = expr->combined_type()->Is(Type::None())
11016         ? Type::Any(zone()) : expr->combined_type();
11017     HIfContinuation continuation;
11018     BuildCompareNil(value, type, &continuation);
11019     return ast_context()->ReturnContinuation(&continuation, expr->id());
11020   }
11021 }
11022
11023
11024 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
11025   // If we share optimized code between different closures, the
11026   // this-function is not a constant, except inside an inlined body.
11027   if (function_state()->outer() != NULL) {
11028       return New<HConstant>(
11029           function_state()->compilation_info()->closure());
11030   } else {
11031       return New<HThisFunction>();
11032   }
11033 }
11034
11035
11036 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
11037     Handle<JSObject> boilerplate_object,
11038     AllocationSiteUsageContext* site_context) {
11039   NoObservableSideEffectsScope no_effects(this);
11040   InstanceType instance_type = boilerplate_object->map()->instance_type();
11041   DCHECK(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE);
11042
11043   HType type = instance_type == JS_ARRAY_TYPE
11044       ? HType::JSArray() : HType::JSObject();
11045   HValue* object_size_constant = Add<HConstant>(
11046       boilerplate_object->map()->instance_size());
11047
11048   PretenureFlag pretenure_flag = NOT_TENURED;
11049   Handle<AllocationSite> site(site_context->current());
11050   if (FLAG_allocation_site_pretenuring) {
11051     pretenure_flag = site_context->current()->GetPretenureMode();
11052     AllocationSite::RegisterForDeoptOnTenureChange(site, top_info());
11053   }
11054
11055   AllocationSite::RegisterForDeoptOnTransitionChange(site, top_info());
11056
11057   HInstruction* object = Add<HAllocate>(object_size_constant, type,
11058       pretenure_flag, instance_type, site_context->current());
11059
11060   // If allocation folding reaches Page::kMaxRegularHeapObjectSize the
11061   // elements array may not get folded into the object. Hence, we set the
11062   // elements pointer to empty fixed array and let store elimination remove
11063   // this store in the folding case.
11064   HConstant* empty_fixed_array = Add<HConstant>(
11065       isolate()->factory()->empty_fixed_array());
11066   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
11067       empty_fixed_array);
11068
11069   BuildEmitObjectHeader(boilerplate_object, object);
11070
11071   Handle<FixedArrayBase> elements(boilerplate_object->elements());
11072   int elements_size = (elements->length() > 0 &&
11073       elements->map() != isolate()->heap()->fixed_cow_array_map()) ?
11074           elements->Size() : 0;
11075
11076   if (pretenure_flag == TENURED &&
11077       elements->map() == isolate()->heap()->fixed_cow_array_map() &&
11078       isolate()->heap()->InNewSpace(*elements)) {
11079     // If we would like to pretenure a fixed cow array, we must ensure that the
11080     // array is already in old space, otherwise we'll create too many old-to-
11081     // new-space pointers (overflowing the store buffer).
11082     elements = Handle<FixedArrayBase>(
11083         isolate()->factory()->CopyAndTenureFixedCOWArray(
11084             Handle<FixedArray>::cast(elements)));
11085     boilerplate_object->set_elements(*elements);
11086   }
11087
11088   HInstruction* object_elements = NULL;
11089   if (elements_size > 0) {
11090     HValue* object_elements_size = Add<HConstant>(elements_size);
11091     InstanceType instance_type = boilerplate_object->HasFastDoubleElements()
11092         ? FIXED_DOUBLE_ARRAY_TYPE : FIXED_ARRAY_TYPE;
11093     object_elements = Add<HAllocate>(
11094         object_elements_size, HType::HeapObject(),
11095         pretenure_flag, instance_type, site_context->current());
11096   }
11097   BuildInitElementsInObjectHeader(boilerplate_object, object, object_elements);
11098
11099   // Copy object elements if non-COW.
11100   if (object_elements != NULL) {
11101     BuildEmitElements(boilerplate_object, elements, object_elements,
11102                       site_context);
11103   }
11104
11105   // Copy in-object properties.
11106   if (boilerplate_object->map()->NumberOfFields() != 0 ||
11107       boilerplate_object->map()->unused_property_fields() > 0) {
11108     BuildEmitInObjectProperties(boilerplate_object, object, site_context,
11109                                 pretenure_flag);
11110   }
11111   return object;
11112 }
11113
11114
11115 void HOptimizedGraphBuilder::BuildEmitObjectHeader(
11116     Handle<JSObject> boilerplate_object,
11117     HInstruction* object) {
11118   DCHECK(boilerplate_object->properties()->length() == 0);
11119
11120   Handle<Map> boilerplate_object_map(boilerplate_object->map());
11121   AddStoreMapConstant(object, boilerplate_object_map);
11122
11123   Handle<Object> properties_field =
11124       Handle<Object>(boilerplate_object->properties(), isolate());
11125   DCHECK(*properties_field == isolate()->heap()->empty_fixed_array());
11126   HInstruction* properties = Add<HConstant>(properties_field);
11127   HObjectAccess access = HObjectAccess::ForPropertiesPointer();
11128   Add<HStoreNamedField>(object, access, properties);
11129
11130   if (boilerplate_object->IsJSArray()) {
11131     Handle<JSArray> boilerplate_array =
11132         Handle<JSArray>::cast(boilerplate_object);
11133     Handle<Object> length_field =
11134         Handle<Object>(boilerplate_array->length(), isolate());
11135     HInstruction* length = Add<HConstant>(length_field);
11136
11137     DCHECK(boilerplate_array->length()->IsSmi());
11138     Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(
11139         boilerplate_array->GetElementsKind()), length);
11140   }
11141 }
11142
11143
11144 void HOptimizedGraphBuilder::BuildInitElementsInObjectHeader(
11145     Handle<JSObject> boilerplate_object,
11146     HInstruction* object,
11147     HInstruction* object_elements) {
11148   DCHECK(boilerplate_object->properties()->length() == 0);
11149   if (object_elements == NULL) {
11150     Handle<Object> elements_field =
11151         Handle<Object>(boilerplate_object->elements(), isolate());
11152     object_elements = Add<HConstant>(elements_field);
11153   }
11154   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
11155       object_elements);
11156 }
11157
11158
11159 void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
11160     Handle<JSObject> boilerplate_object,
11161     HInstruction* object,
11162     AllocationSiteUsageContext* site_context,
11163     PretenureFlag pretenure_flag) {
11164   Handle<Map> boilerplate_map(boilerplate_object->map());
11165   Handle<DescriptorArray> descriptors(boilerplate_map->instance_descriptors());
11166   int limit = boilerplate_map->NumberOfOwnDescriptors();
11167
11168   int copied_fields = 0;
11169   for (int i = 0; i < limit; i++) {
11170     PropertyDetails details = descriptors->GetDetails(i);
11171     if (details.type() != DATA) continue;
11172     copied_fields++;
11173     FieldIndex field_index = FieldIndex::ForDescriptor(*boilerplate_map, i);
11174
11175
11176     int property_offset = field_index.offset();
11177     Handle<Name> name(descriptors->GetKey(i));
11178
11179     // The access for the store depends on the type of the boilerplate.
11180     HObjectAccess access = boilerplate_object->IsJSArray() ?
11181         HObjectAccess::ForJSArrayOffset(property_offset) :
11182         HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
11183
11184     if (boilerplate_object->IsUnboxedDoubleField(field_index)) {
11185       CHECK(!boilerplate_object->IsJSArray());
11186       double value = boilerplate_object->RawFastDoublePropertyAt(field_index);
11187       access = access.WithRepresentation(Representation::Double());
11188       Add<HStoreNamedField>(object, access, Add<HConstant>(value));
11189       continue;
11190     }
11191     Handle<Object> value(boilerplate_object->RawFastPropertyAt(field_index),
11192                          isolate());
11193
11194     if (value->IsJSObject()) {
11195       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
11196       Handle<AllocationSite> current_site = site_context->EnterNewScope();
11197       HInstruction* result =
11198           BuildFastLiteral(value_object, site_context);
11199       site_context->ExitScope(current_site, value_object);
11200       Add<HStoreNamedField>(object, access, result);
11201     } else {
11202       Representation representation = details.representation();
11203       HInstruction* value_instruction;
11204
11205       if (representation.IsDouble()) {
11206         // Allocate a HeapNumber box and store the value into it.
11207         HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize);
11208         // This heap number alloc does not have a corresponding
11209         // AllocationSite. That is okay because
11210         // 1) it's a child object of another object with a valid allocation site
11211         // 2) we can just use the mode of the parent object for pretenuring
11212         HInstruction* double_box =
11213             Add<HAllocate>(heap_number_constant, HType::HeapObject(),
11214                 pretenure_flag, MUTABLE_HEAP_NUMBER_TYPE);
11215         AddStoreMapConstant(double_box,
11216             isolate()->factory()->mutable_heap_number_map());
11217         // Unwrap the mutable heap number from the boilerplate.
11218         HValue* double_value =
11219             Add<HConstant>(Handle<HeapNumber>::cast(value)->value());
11220         Add<HStoreNamedField>(
11221             double_box, HObjectAccess::ForHeapNumberValue(), double_value);
11222         value_instruction = double_box;
11223       } else if (representation.IsSmi()) {
11224         value_instruction = value->IsUninitialized()
11225             ? graph()->GetConstant0()
11226             : Add<HConstant>(value);
11227         // Ensure that value is stored as smi.
11228         access = access.WithRepresentation(representation);
11229       } else {
11230         value_instruction = Add<HConstant>(value);
11231       }
11232
11233       Add<HStoreNamedField>(object, access, value_instruction);
11234     }
11235   }
11236
11237   int inobject_properties = boilerplate_object->map()->inobject_properties();
11238   HInstruction* value_instruction =
11239       Add<HConstant>(isolate()->factory()->one_pointer_filler_map());
11240   for (int i = copied_fields; i < inobject_properties; i++) {
11241     DCHECK(boilerplate_object->IsJSObject());
11242     int property_offset = boilerplate_object->GetInObjectPropertyOffset(i);
11243     HObjectAccess access =
11244         HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
11245     Add<HStoreNamedField>(object, access, value_instruction);
11246   }
11247 }
11248
11249
11250 void HOptimizedGraphBuilder::BuildEmitElements(
11251     Handle<JSObject> boilerplate_object,
11252     Handle<FixedArrayBase> elements,
11253     HValue* object_elements,
11254     AllocationSiteUsageContext* site_context) {
11255   ElementsKind kind = boilerplate_object->map()->elements_kind();
11256   int elements_length = elements->length();
11257   HValue* object_elements_length = Add<HConstant>(elements_length);
11258   BuildInitializeElementsHeader(object_elements, kind, object_elements_length);
11259
11260   // Copy elements backing store content.
11261   if (elements->IsFixedDoubleArray()) {
11262     BuildEmitFixedDoubleArray(elements, kind, object_elements);
11263   } else if (elements->IsFixedArray()) {
11264     BuildEmitFixedArray(elements, kind, object_elements,
11265                         site_context);
11266   } else {
11267     UNREACHABLE();
11268   }
11269 }
11270
11271
11272 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray(
11273     Handle<FixedArrayBase> elements,
11274     ElementsKind kind,
11275     HValue* object_elements) {
11276   HInstruction* boilerplate_elements = Add<HConstant>(elements);
11277   int elements_length = elements->length();
11278   for (int i = 0; i < elements_length; i++) {
11279     HValue* key_constant = Add<HConstant>(i);
11280     HInstruction* value_instruction = Add<HLoadKeyed>(
11281         boilerplate_elements, key_constant, nullptr, kind, ALLOW_RETURN_HOLE);
11282     HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant,
11283                                            value_instruction, kind);
11284     store->SetFlag(HValue::kAllowUndefinedAsNaN);
11285   }
11286 }
11287
11288
11289 void HOptimizedGraphBuilder::BuildEmitFixedArray(
11290     Handle<FixedArrayBase> elements,
11291     ElementsKind kind,
11292     HValue* object_elements,
11293     AllocationSiteUsageContext* site_context) {
11294   HInstruction* boilerplate_elements = Add<HConstant>(elements);
11295   int elements_length = elements->length();
11296   Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
11297   for (int i = 0; i < elements_length; i++) {
11298     Handle<Object> value(fast_elements->get(i), isolate());
11299     HValue* key_constant = Add<HConstant>(i);
11300     if (value->IsJSObject()) {
11301       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
11302       Handle<AllocationSite> current_site = site_context->EnterNewScope();
11303       HInstruction* result =
11304           BuildFastLiteral(value_object, site_context);
11305       site_context->ExitScope(current_site, value_object);
11306       Add<HStoreKeyed>(object_elements, key_constant, result, kind);
11307     } else {
11308       ElementsKind copy_kind =
11309           kind == FAST_HOLEY_SMI_ELEMENTS ? FAST_HOLEY_ELEMENTS : kind;
11310       HInstruction* value_instruction =
11311           Add<HLoadKeyed>(boilerplate_elements, key_constant, nullptr,
11312                           copy_kind, ALLOW_RETURN_HOLE);
11313       Add<HStoreKeyed>(object_elements, key_constant, value_instruction,
11314                        copy_kind);
11315     }
11316   }
11317 }
11318
11319
11320 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
11321   DCHECK(!HasStackOverflow());
11322   DCHECK(current_block() != NULL);
11323   DCHECK(current_block()->HasPredecessor());
11324   HInstruction* instr = BuildThisFunction();
11325   return ast_context()->ReturnInstruction(instr, expr->id());
11326 }
11327
11328
11329 void HOptimizedGraphBuilder::VisitSuperReference(SuperReference* expr) {
11330   DCHECK(!HasStackOverflow());
11331   DCHECK(current_block() != NULL);
11332   DCHECK(current_block()->HasPredecessor());
11333   return Bailout(kSuperReference);
11334 }
11335
11336
11337 void HOptimizedGraphBuilder::VisitDeclarations(
11338     ZoneList<Declaration*>* declarations) {
11339   DCHECK(globals_.is_empty());
11340   AstVisitor::VisitDeclarations(declarations);
11341   if (!globals_.is_empty()) {
11342     Handle<FixedArray> array =
11343        isolate()->factory()->NewFixedArray(globals_.length(), TENURED);
11344     for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i));
11345     int flags =
11346         DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) |
11347         DeclareGlobalsNativeFlag::encode(current_info()->is_native()) |
11348         DeclareGlobalsLanguageMode::encode(current_info()->language_mode());
11349     Add<HDeclareGlobals>(array, flags);
11350     globals_.Rewind(0);
11351   }
11352 }
11353
11354
11355 void HOptimizedGraphBuilder::VisitVariableDeclaration(
11356     VariableDeclaration* declaration) {
11357   VariableProxy* proxy = declaration->proxy();
11358   VariableMode mode = declaration->mode();
11359   Variable* variable = proxy->var();
11360   bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
11361   switch (variable->location()) {
11362     case Variable::UNALLOCATED:
11363       globals_.Add(variable->name(), zone());
11364       globals_.Add(variable->binding_needs_init()
11365                        ? isolate()->factory()->the_hole_value()
11366                        : isolate()->factory()->undefined_value(), zone());
11367       return;
11368     case Variable::PARAMETER:
11369     case Variable::LOCAL:
11370       if (hole_init) {
11371         HValue* value = graph()->GetConstantHole();
11372         environment()->Bind(variable, value);
11373       }
11374       break;
11375     case Variable::CONTEXT:
11376       if (hole_init) {
11377         HValue* value = graph()->GetConstantHole();
11378         HValue* context = environment()->context();
11379         HStoreContextSlot* store = Add<HStoreContextSlot>(
11380             context, variable->index(), HStoreContextSlot::kNoCheck, value);
11381         if (store->HasObservableSideEffects()) {
11382           Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
11383         }
11384       }
11385       break;
11386     case Variable::LOOKUP:
11387       return Bailout(kUnsupportedLookupSlotInDeclaration);
11388   }
11389 }
11390
11391
11392 void HOptimizedGraphBuilder::VisitFunctionDeclaration(
11393     FunctionDeclaration* declaration) {
11394   VariableProxy* proxy = declaration->proxy();
11395   Variable* variable = proxy->var();
11396   switch (variable->location()) {
11397     case Variable::UNALLOCATED: {
11398       globals_.Add(variable->name(), zone());
11399       Handle<SharedFunctionInfo> function = Compiler::BuildFunctionInfo(
11400           declaration->fun(), current_info()->script(), top_info());
11401       // Check for stack-overflow exception.
11402       if (function.is_null()) return SetStackOverflow();
11403       globals_.Add(function, zone());
11404       return;
11405     }
11406     case Variable::PARAMETER:
11407     case Variable::LOCAL: {
11408       CHECK_ALIVE(VisitForValue(declaration->fun()));
11409       HValue* value = Pop();
11410       BindIfLive(variable, value);
11411       break;
11412     }
11413     case Variable::CONTEXT: {
11414       CHECK_ALIVE(VisitForValue(declaration->fun()));
11415       HValue* value = Pop();
11416       HValue* context = environment()->context();
11417       HStoreContextSlot* store = Add<HStoreContextSlot>(
11418           context, variable->index(), HStoreContextSlot::kNoCheck, value);
11419       if (store->HasObservableSideEffects()) {
11420         Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
11421       }
11422       break;
11423     }
11424     case Variable::LOOKUP:
11425       return Bailout(kUnsupportedLookupSlotInDeclaration);
11426   }
11427 }
11428
11429
11430 void HOptimizedGraphBuilder::VisitModuleDeclaration(
11431     ModuleDeclaration* declaration) {
11432   UNREACHABLE();
11433 }
11434
11435
11436 void HOptimizedGraphBuilder::VisitImportDeclaration(
11437     ImportDeclaration* declaration) {
11438   UNREACHABLE();
11439 }
11440
11441
11442 void HOptimizedGraphBuilder::VisitExportDeclaration(
11443     ExportDeclaration* declaration) {
11444   UNREACHABLE();
11445 }
11446
11447
11448 void HOptimizedGraphBuilder::VisitModuleLiteral(ModuleLiteral* module) {
11449   UNREACHABLE();
11450 }
11451
11452
11453 void HOptimizedGraphBuilder::VisitModulePath(ModulePath* module) {
11454   UNREACHABLE();
11455 }
11456
11457
11458 void HOptimizedGraphBuilder::VisitModuleUrl(ModuleUrl* module) {
11459   UNREACHABLE();
11460 }
11461
11462
11463 void HOptimizedGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) {
11464   UNREACHABLE();
11465 }
11466
11467
11468 // Generators for inline runtime functions.
11469 // Support for types.
11470 void HOptimizedGraphBuilder::GenerateIsSmi(CallRuntime* call) {
11471   DCHECK(call->arguments()->length() == 1);
11472   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11473   HValue* value = Pop();
11474   HIsSmiAndBranch* result = New<HIsSmiAndBranch>(value);
11475   return ast_context()->ReturnControl(result, call->id());
11476 }
11477
11478
11479 void HOptimizedGraphBuilder::GenerateIsSpecObject(CallRuntime* call) {
11480   DCHECK(call->arguments()->length() == 1);
11481   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11482   HValue* value = Pop();
11483   HHasInstanceTypeAndBranch* result =
11484       New<HHasInstanceTypeAndBranch>(value,
11485                                      FIRST_SPEC_OBJECT_TYPE,
11486                                      LAST_SPEC_OBJECT_TYPE);
11487   return ast_context()->ReturnControl(result, call->id());
11488 }
11489
11490
11491 void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) {
11492   DCHECK(call->arguments()->length() == 1);
11493   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11494   HValue* value = Pop();
11495   HHasInstanceTypeAndBranch* result =
11496       New<HHasInstanceTypeAndBranch>(value, JS_FUNCTION_TYPE);
11497   return ast_context()->ReturnControl(result, call->id());
11498 }
11499
11500
11501 void HOptimizedGraphBuilder::GenerateIsMinusZero(CallRuntime* call) {
11502   DCHECK(call->arguments()->length() == 1);
11503   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11504   HValue* value = Pop();
11505   HCompareMinusZeroAndBranch* result = New<HCompareMinusZeroAndBranch>(value);
11506   return ast_context()->ReturnControl(result, call->id());
11507 }
11508
11509
11510 void HOptimizedGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
11511   DCHECK(call->arguments()->length() == 1);
11512   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11513   HValue* value = Pop();
11514   HHasCachedArrayIndexAndBranch* result =
11515       New<HHasCachedArrayIndexAndBranch>(value);
11516   return ast_context()->ReturnControl(result, call->id());
11517 }
11518
11519
11520 void HOptimizedGraphBuilder::GenerateIsArray(CallRuntime* call) {
11521   DCHECK(call->arguments()->length() == 1);
11522   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11523   HValue* value = Pop();
11524   HHasInstanceTypeAndBranch* result =
11525       New<HHasInstanceTypeAndBranch>(value, JS_ARRAY_TYPE);
11526   return ast_context()->ReturnControl(result, call->id());
11527 }
11528
11529
11530 void HOptimizedGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
11531   DCHECK(call->arguments()->length() == 1);
11532   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11533   HValue* value = Pop();
11534   HHasInstanceTypeAndBranch* result =
11535       New<HHasInstanceTypeAndBranch>(value, JS_REGEXP_TYPE);
11536   return ast_context()->ReturnControl(result, call->id());
11537 }
11538
11539
11540 void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) {
11541   DCHECK(call->arguments()->length() == 1);
11542   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11543   HValue* value = Pop();
11544   HIsObjectAndBranch* result = New<HIsObjectAndBranch>(value);
11545   return ast_context()->ReturnControl(result, call->id());
11546 }
11547
11548
11549 void HOptimizedGraphBuilder::GenerateIsJSProxy(CallRuntime* call) {
11550   DCHECK(call->arguments()->length() == 1);
11551   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11552   HValue* value = Pop();
11553   HIfContinuation continuation;
11554   IfBuilder if_proxy(this);
11555
11556   HValue* smicheck = if_proxy.IfNot<HIsSmiAndBranch>(value);
11557   if_proxy.And();
11558   HValue* map = Add<HLoadNamedField>(value, smicheck, HObjectAccess::ForMap());
11559   HValue* instance_type =
11560       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
11561   if_proxy.If<HCompareNumericAndBranch>(
11562       instance_type, Add<HConstant>(FIRST_JS_PROXY_TYPE), Token::GTE);
11563   if_proxy.And();
11564   if_proxy.If<HCompareNumericAndBranch>(
11565       instance_type, Add<HConstant>(LAST_JS_PROXY_TYPE), Token::LTE);
11566
11567   if_proxy.CaptureContinuation(&continuation);
11568   return ast_context()->ReturnContinuation(&continuation, call->id());
11569 }
11570
11571
11572 void HOptimizedGraphBuilder::GenerateHasFastPackedElements(CallRuntime* call) {
11573   DCHECK(call->arguments()->length() == 1);
11574   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11575   HValue* object = Pop();
11576   HIfContinuation continuation(graph()->CreateBasicBlock(),
11577                                graph()->CreateBasicBlock());
11578   IfBuilder if_not_smi(this);
11579   if_not_smi.IfNot<HIsSmiAndBranch>(object);
11580   if_not_smi.Then();
11581   {
11582     NoObservableSideEffectsScope no_effects(this);
11583
11584     IfBuilder if_fast_packed(this);
11585     HValue* elements_kind = BuildGetElementsKind(object);
11586     if_fast_packed.If<HCompareNumericAndBranch>(
11587         elements_kind, Add<HConstant>(FAST_SMI_ELEMENTS), Token::EQ);
11588     if_fast_packed.Or();
11589     if_fast_packed.If<HCompareNumericAndBranch>(
11590         elements_kind, Add<HConstant>(FAST_ELEMENTS), Token::EQ);
11591     if_fast_packed.Or();
11592     if_fast_packed.If<HCompareNumericAndBranch>(
11593         elements_kind, Add<HConstant>(FAST_DOUBLE_ELEMENTS), Token::EQ);
11594     if_fast_packed.JoinContinuation(&continuation);
11595   }
11596   if_not_smi.JoinContinuation(&continuation);
11597   return ast_context()->ReturnContinuation(&continuation, call->id());
11598 }
11599
11600
11601 void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
11602   DCHECK(call->arguments()->length() == 1);
11603   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11604   HValue* value = Pop();
11605   HIsUndetectableAndBranch* result = New<HIsUndetectableAndBranch>(value);
11606   return ast_context()->ReturnControl(result, call->id());
11607 }
11608
11609
11610 // Support for construct call checks.
11611 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
11612   DCHECK(call->arguments()->length() == 0);
11613   if (function_state()->outer() != NULL) {
11614     // We are generating graph for inlined function.
11615     HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN
11616         ? graph()->GetConstantTrue()
11617         : graph()->GetConstantFalse();
11618     return ast_context()->ReturnValue(value);
11619   } else {
11620     return ast_context()->ReturnControl(New<HIsConstructCallAndBranch>(),
11621                                         call->id());
11622   }
11623 }
11624
11625
11626 // Support for arguments.length and arguments[?].
11627 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
11628   DCHECK(call->arguments()->length() == 0);
11629   HInstruction* result = NULL;
11630   if (function_state()->outer() == NULL) {
11631     HInstruction* elements = Add<HArgumentsElements>(false);
11632     result = New<HArgumentsLength>(elements);
11633   } else {
11634     // Number of arguments without receiver.
11635     int argument_count = environment()->
11636         arguments_environment()->parameter_count() - 1;
11637     result = New<HConstant>(argument_count);
11638   }
11639   return ast_context()->ReturnInstruction(result, call->id());
11640 }
11641
11642
11643 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) {
11644   DCHECK(call->arguments()->length() == 1);
11645   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11646   HValue* index = Pop();
11647   HInstruction* result = NULL;
11648   if (function_state()->outer() == NULL) {
11649     HInstruction* elements = Add<HArgumentsElements>(false);
11650     HInstruction* length = Add<HArgumentsLength>(elements);
11651     HInstruction* checked_index = Add<HBoundsCheck>(index, length);
11652     result = New<HAccessArgumentsAt>(elements, length, checked_index);
11653   } else {
11654     EnsureArgumentsArePushedForAccess();
11655
11656     // Number of arguments without receiver.
11657     HInstruction* elements = function_state()->arguments_elements();
11658     int argument_count = environment()->
11659         arguments_environment()->parameter_count() - 1;
11660     HInstruction* length = Add<HConstant>(argument_count);
11661     HInstruction* checked_key = Add<HBoundsCheck>(index, length);
11662     result = New<HAccessArgumentsAt>(elements, length, checked_key);
11663   }
11664   return ast_context()->ReturnInstruction(result, call->id());
11665 }
11666
11667
11668 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) {
11669   DCHECK(call->arguments()->length() == 1);
11670   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11671   HValue* object = Pop();
11672
11673   IfBuilder if_objectisvalue(this);
11674   HValue* objectisvalue = if_objectisvalue.If<HHasInstanceTypeAndBranch>(
11675       object, JS_VALUE_TYPE);
11676   if_objectisvalue.Then();
11677   {
11678     // Return the actual value.
11679     Push(Add<HLoadNamedField>(
11680             object, objectisvalue,
11681             HObjectAccess::ForObservableJSObjectOffset(
11682                 JSValue::kValueOffset)));
11683     Add<HSimulate>(call->id(), FIXED_SIMULATE);
11684   }
11685   if_objectisvalue.Else();
11686   {
11687     // If the object is not a value return the object.
11688     Push(object);
11689     Add<HSimulate>(call->id(), FIXED_SIMULATE);
11690   }
11691   if_objectisvalue.End();
11692   return ast_context()->ReturnValue(Pop());
11693 }
11694
11695
11696 void HOptimizedGraphBuilder::GenerateJSValueGetValue(CallRuntime* call) {
11697   DCHECK(call->arguments()->length() == 1);
11698   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11699   HValue* value = Pop();
11700   HInstruction* result = Add<HLoadNamedField>(
11701       value, nullptr,
11702       HObjectAccess::ForObservableJSObjectOffset(JSValue::kValueOffset));
11703   return ast_context()->ReturnInstruction(result, call->id());
11704 }
11705
11706
11707 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) {
11708   DCHECK(call->arguments()->length() == 2);
11709   DCHECK_NOT_NULL(call->arguments()->at(1)->AsLiteral());
11710   Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->value()));
11711   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11712   HValue* date = Pop();
11713   HDateField* result = New<HDateField>(date, index);
11714   return ast_context()->ReturnInstruction(result, call->id());
11715 }
11716
11717
11718 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar(
11719     CallRuntime* call) {
11720   DCHECK(call->arguments()->length() == 3);
11721   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11722   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11723   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
11724   HValue* string = Pop();
11725   HValue* value = Pop();
11726   HValue* index = Pop();
11727   Add<HSeqStringSetChar>(String::ONE_BYTE_ENCODING, string,
11728                          index, value);
11729   Add<HSimulate>(call->id(), FIXED_SIMULATE);
11730   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
11731 }
11732
11733
11734 void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar(
11735     CallRuntime* call) {
11736   DCHECK(call->arguments()->length() == 3);
11737   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11738   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11739   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
11740   HValue* string = Pop();
11741   HValue* value = Pop();
11742   HValue* index = Pop();
11743   Add<HSeqStringSetChar>(String::TWO_BYTE_ENCODING, string,
11744                          index, value);
11745   Add<HSimulate>(call->id(), FIXED_SIMULATE);
11746   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
11747 }
11748
11749
11750 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
11751   DCHECK(call->arguments()->length() == 2);
11752   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11753   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11754   HValue* value = Pop();
11755   HValue* object = Pop();
11756
11757   // Check if object is a JSValue.
11758   IfBuilder if_objectisvalue(this);
11759   if_objectisvalue.If<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE);
11760   if_objectisvalue.Then();
11761   {
11762     // Create in-object property store to kValueOffset.
11763     Add<HStoreNamedField>(object,
11764         HObjectAccess::ForObservableJSObjectOffset(JSValue::kValueOffset),
11765         value);
11766     if (!ast_context()->IsEffect()) {
11767       Push(value);
11768     }
11769     Add<HSimulate>(call->id(), FIXED_SIMULATE);
11770   }
11771   if_objectisvalue.Else();
11772   {
11773     // Nothing to do in this case.
11774     if (!ast_context()->IsEffect()) {
11775       Push(value);
11776     }
11777     Add<HSimulate>(call->id(), FIXED_SIMULATE);
11778   }
11779   if_objectisvalue.End();
11780   if (!ast_context()->IsEffect()) {
11781     Drop(1);
11782   }
11783   return ast_context()->ReturnValue(value);
11784 }
11785
11786
11787 // Fast support for charCodeAt(n).
11788 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
11789   DCHECK(call->arguments()->length() == 2);
11790   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11791   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11792   HValue* index = Pop();
11793   HValue* string = Pop();
11794   HInstruction* result = BuildStringCharCodeAt(string, index);
11795   return ast_context()->ReturnInstruction(result, call->id());
11796 }
11797
11798
11799 // Fast support for string.charAt(n) and string[n].
11800 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
11801   DCHECK(call->arguments()->length() == 1);
11802   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11803   HValue* char_code = Pop();
11804   HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
11805   return ast_context()->ReturnInstruction(result, call->id());
11806 }
11807
11808
11809 // Fast support for string.charAt(n) and string[n].
11810 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
11811   DCHECK(call->arguments()->length() == 2);
11812   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11813   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11814   HValue* index = Pop();
11815   HValue* string = Pop();
11816   HInstruction* char_code = BuildStringCharCodeAt(string, index);
11817   AddInstruction(char_code);
11818   HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
11819   return ast_context()->ReturnInstruction(result, call->id());
11820 }
11821
11822
11823 // Fast support for object equality testing.
11824 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
11825   DCHECK(call->arguments()->length() == 2);
11826   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11827   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11828   HValue* right = Pop();
11829   HValue* left = Pop();
11830   HCompareObjectEqAndBranch* result =
11831       New<HCompareObjectEqAndBranch>(left, right);
11832   return ast_context()->ReturnControl(result, call->id());
11833 }
11834
11835
11836 // Fast support for StringAdd.
11837 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) {
11838   DCHECK_EQ(2, call->arguments()->length());
11839   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11840   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11841   HValue* right = Pop();
11842   HValue* left = Pop();
11843   HInstruction* result = NewUncasted<HStringAdd>(left, right);
11844   return ast_context()->ReturnInstruction(result, call->id());
11845 }
11846
11847
11848 // Fast support for SubString.
11849 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) {
11850   DCHECK_EQ(3, call->arguments()->length());
11851   CHECK_ALIVE(VisitExpressions(call->arguments()));
11852   PushArgumentsFromEnvironment(call->arguments()->length());
11853   HCallStub* result = New<HCallStub>(CodeStub::SubString, 3);
11854   return ast_context()->ReturnInstruction(result, call->id());
11855 }
11856
11857
11858 // Fast support for StringCompare.
11859 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) {
11860   DCHECK_EQ(2, call->arguments()->length());
11861   CHECK_ALIVE(VisitExpressions(call->arguments()));
11862   PushArgumentsFromEnvironment(call->arguments()->length());
11863   HCallStub* result = New<HCallStub>(CodeStub::StringCompare, 2);
11864   return ast_context()->ReturnInstruction(result, call->id());
11865 }
11866
11867
11868 void HOptimizedGraphBuilder::GenerateStringGetLength(CallRuntime* call) {
11869   DCHECK(call->arguments()->length() == 1);
11870   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11871   HValue* string = Pop();
11872   HInstruction* result = AddLoadStringLength(string);
11873   return ast_context()->ReturnInstruction(result, call->id());
11874 }
11875
11876
11877 // Support for direct calls from JavaScript to native RegExp code.
11878 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
11879   DCHECK_EQ(4, call->arguments()->length());
11880   CHECK_ALIVE(VisitExpressions(call->arguments()));
11881   PushArgumentsFromEnvironment(call->arguments()->length());
11882   HCallStub* result = New<HCallStub>(CodeStub::RegExpExec, 4);
11883   return ast_context()->ReturnInstruction(result, call->id());
11884 }
11885
11886
11887 void HOptimizedGraphBuilder::GenerateDoubleLo(CallRuntime* call) {
11888   DCHECK_EQ(1, call->arguments()->length());
11889   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11890   HValue* value = Pop();
11891   HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::LOW);
11892   return ast_context()->ReturnInstruction(result, call->id());
11893 }
11894
11895
11896 void HOptimizedGraphBuilder::GenerateDoubleHi(CallRuntime* call) {
11897   DCHECK_EQ(1, call->arguments()->length());
11898   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11899   HValue* value = Pop();
11900   HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::HIGH);
11901   return ast_context()->ReturnInstruction(result, call->id());
11902 }
11903
11904
11905 void HOptimizedGraphBuilder::GenerateConstructDouble(CallRuntime* call) {
11906   DCHECK_EQ(2, call->arguments()->length());
11907   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11908   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11909   HValue* lo = Pop();
11910   HValue* hi = Pop();
11911   HInstruction* result = NewUncasted<HConstructDouble>(hi, lo);
11912   return ast_context()->ReturnInstruction(result, call->id());
11913 }
11914
11915
11916 // Construct a RegExp exec result with two in-object properties.
11917 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
11918   DCHECK_EQ(3, call->arguments()->length());
11919   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11920   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11921   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
11922   HValue* input = Pop();
11923   HValue* index = Pop();
11924   HValue* length = Pop();
11925   HValue* result = BuildRegExpConstructResult(length, index, input);
11926   return ast_context()->ReturnValue(result);
11927 }
11928
11929
11930 // Support for fast native caches.
11931 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
11932   return Bailout(kInlinedRuntimeFunctionGetFromCache);
11933 }
11934
11935
11936 // Fast support for number to string.
11937 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) {
11938   DCHECK_EQ(1, call->arguments()->length());
11939   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11940   HValue* number = Pop();
11941   HValue* result = BuildNumberToString(number, Type::Any(zone()));
11942   return ast_context()->ReturnValue(result);
11943 }
11944
11945
11946 // Fast call for custom callbacks.
11947 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) {
11948   // 1 ~ The function to call is not itself an argument to the call.
11949   int arg_count = call->arguments()->length() - 1;
11950   DCHECK(arg_count >= 1);  // There's always at least a receiver.
11951
11952   CHECK_ALIVE(VisitExpressions(call->arguments()));
11953   // The function is the last argument
11954   HValue* function = Pop();
11955   // Push the arguments to the stack
11956   PushArgumentsFromEnvironment(arg_count);
11957
11958   IfBuilder if_is_jsfunction(this);
11959   if_is_jsfunction.If<HHasInstanceTypeAndBranch>(function, JS_FUNCTION_TYPE);
11960
11961   if_is_jsfunction.Then();
11962   {
11963     HInstruction* invoke_result =
11964         Add<HInvokeFunction>(function, arg_count);
11965     if (!ast_context()->IsEffect()) {
11966       Push(invoke_result);
11967     }
11968     Add<HSimulate>(call->id(), FIXED_SIMULATE);
11969   }
11970
11971   if_is_jsfunction.Else();
11972   {
11973     HInstruction* call_result =
11974         Add<HCallFunction>(function, arg_count);
11975     if (!ast_context()->IsEffect()) {
11976       Push(call_result);
11977     }
11978     Add<HSimulate>(call->id(), FIXED_SIMULATE);
11979   }
11980   if_is_jsfunction.End();
11981
11982   if (ast_context()->IsEffect()) {
11983     // EffectContext::ReturnValue ignores the value, so we can just pass
11984     // 'undefined' (as we do not have the call result anymore).
11985     return ast_context()->ReturnValue(graph()->GetConstantUndefined());
11986   } else {
11987     return ast_context()->ReturnValue(Pop());
11988   }
11989 }
11990
11991
11992 // Fast call to math functions.
11993 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) {
11994   DCHECK_EQ(2, call->arguments()->length());
11995   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11996   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
11997   HValue* right = Pop();
11998   HValue* left = Pop();
11999   HInstruction* result = NewUncasted<HPower>(left, right);
12000   return ast_context()->ReturnInstruction(result, call->id());
12001 }
12002
12003
12004 void HOptimizedGraphBuilder::GenerateMathClz32(CallRuntime* call) {
12005   DCHECK(call->arguments()->length() == 1);
12006   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12007   HValue* value = Pop();
12008   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathClz32);
12009   return ast_context()->ReturnInstruction(result, call->id());
12010 }
12011
12012
12013 void HOptimizedGraphBuilder::GenerateMathFloor(CallRuntime* call) {
12014   DCHECK(call->arguments()->length() == 1);
12015   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12016   HValue* value = Pop();
12017   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathFloor);
12018   return ast_context()->ReturnInstruction(result, call->id());
12019 }
12020
12021
12022 void HOptimizedGraphBuilder::GenerateMathLogRT(CallRuntime* call) {
12023   DCHECK(call->arguments()->length() == 1);
12024   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12025   HValue* value = Pop();
12026   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathLog);
12027   return ast_context()->ReturnInstruction(result, call->id());
12028 }
12029
12030
12031 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
12032   DCHECK(call->arguments()->length() == 1);
12033   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12034   HValue* value = Pop();
12035   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt);
12036   return ast_context()->ReturnInstruction(result, call->id());
12037 }
12038
12039
12040 HValue* HOptimizedGraphBuilder::BuildOrderedHashTableHashToBucket(
12041     HValue* hash, HValue* num_buckets) {
12042   HValue* mask = AddUncasted<HSub>(num_buckets, graph()->GetConstant1());
12043   mask->ChangeRepresentation(Representation::Integer32());
12044   mask->ClearFlag(HValue::kCanOverflow);
12045   return AddUncasted<HBitwise>(Token::BIT_AND, hash, mask);
12046 }
12047
12048
12049 template <typename CollectionType>
12050 HValue* HOptimizedGraphBuilder::BuildOrderedHashTableHashToEntry(
12051     HValue* table, HValue* hash, HValue* num_buckets) {
12052   HValue* bucket = BuildOrderedHashTableHashToBucket(hash, num_buckets);
12053   HValue* entry_index = AddUncasted<HAdd>(
12054       bucket, Add<HConstant>(CollectionType::kHashTableStartIndex));
12055   entry_index->ClearFlag(HValue::kCanOverflow);
12056   HValue* entry = Add<HLoadKeyed>(table, entry_index, nullptr, FAST_ELEMENTS);
12057   entry->set_type(HType::Smi());
12058   return entry;
12059 }
12060
12061
12062 template <typename CollectionType>
12063 HValue* HOptimizedGraphBuilder::BuildOrderedHashTableEntryToIndex(
12064     HValue* entry, HValue* num_buckets) {
12065   HValue* index =
12066       AddUncasted<HMul>(entry, Add<HConstant>(CollectionType::kEntrySize));
12067   index->ClearFlag(HValue::kCanOverflow);
12068   index = AddUncasted<HAdd>(index, num_buckets);
12069   index->ClearFlag(HValue::kCanOverflow);
12070   index = AddUncasted<HAdd>(
12071       index, Add<HConstant>(CollectionType::kHashTableStartIndex));
12072   index->ClearFlag(HValue::kCanOverflow);
12073   return index;
12074 }
12075
12076
12077 template <typename CollectionType>
12078 HValue* HOptimizedGraphBuilder::BuildOrderedHashTableFindEntry(HValue* table,
12079                                                                HValue* key,
12080                                                                HValue* hash) {
12081   HValue* num_buckets = Add<HLoadNamedField>(
12082       table, nullptr,
12083       HObjectAccess::ForOrderedHashTableNumberOfBuckets<CollectionType>());
12084
12085   HValue* entry = BuildOrderedHashTableHashToEntry<CollectionType>(table, hash,
12086                                                                    num_buckets);
12087
12088   Push(entry);
12089
12090   LoopBuilder loop(this);
12091   loop.BeginBody(1);
12092
12093   entry = Pop();
12094
12095   {
12096     IfBuilder if_not_found(this);
12097     if_not_found.If<HCompareNumericAndBranch>(
12098         entry, Add<HConstant>(CollectionType::kNotFound), Token::EQ);
12099     if_not_found.Then();
12100     Push(entry);
12101     loop.Break();
12102   }
12103
12104   HValue* key_index =
12105       BuildOrderedHashTableEntryToIndex<CollectionType>(entry, num_buckets);
12106   HValue* candidate_key =
12107       Add<HLoadKeyed>(table, key_index, nullptr, FAST_ELEMENTS);
12108
12109   {
12110     IfBuilder if_keys_equal(this);
12111     if_keys_equal.If<HIsStringAndBranch>(candidate_key);
12112     if_keys_equal.AndIf<HStringCompareAndBranch>(candidate_key, key,
12113                                                  Token::EQ_STRICT);
12114     if_keys_equal.Then();
12115     Push(key_index);
12116     loop.Break();
12117   }
12118
12119   // BuildChainAt
12120   HValue* chain_index = AddUncasted<HAdd>(
12121       key_index, Add<HConstant>(CollectionType::kChainOffset));
12122   chain_index->ClearFlag(HValue::kCanOverflow);
12123   entry = Add<HLoadKeyed>(table, chain_index, nullptr, FAST_ELEMENTS);
12124   entry->set_type(HType::Smi());
12125   Push(entry);
12126
12127   loop.EndBody();
12128
12129   return Pop();
12130 }
12131
12132
12133 void HOptimizedGraphBuilder::GenerateMapGet(CallRuntime* call) {
12134   DCHECK(call->arguments()->length() == 2);
12135   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12136   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12137   HValue* key = Pop();
12138   HValue* receiver = Pop();
12139
12140   NoObservableSideEffectsScope no_effects(this);
12141
12142   HIfContinuation continuation;
12143   HValue* hash =
12144       BuildStringHashLoadIfIsStringAndHashComputed(key, &continuation);
12145   {
12146     IfBuilder string_checker(this, &continuation);
12147     string_checker.Then();
12148     {
12149       HValue* table = Add<HLoadNamedField>(
12150           receiver, nullptr, HObjectAccess::ForJSCollectionTable());
12151       HValue* key_index =
12152           BuildOrderedHashTableFindEntry<OrderedHashMap>(table, key, hash);
12153       IfBuilder if_found(this);
12154       if_found.If<HCompareNumericAndBranch>(
12155           key_index, Add<HConstant>(OrderedHashMap::kNotFound), Token::NE);
12156       if_found.Then();
12157       {
12158         HValue* value_index = AddUncasted<HAdd>(
12159             key_index, Add<HConstant>(OrderedHashMap::kValueOffset));
12160         value_index->ClearFlag(HValue::kCanOverflow);
12161         Push(Add<HLoadKeyed>(table, value_index, nullptr, FAST_ELEMENTS));
12162       }
12163       if_found.Else();
12164       Push(graph()->GetConstantUndefined());
12165       if_found.End();
12166     }
12167     string_checker.Else();
12168     {
12169       Add<HPushArguments>(receiver, key);
12170       Push(Add<HCallRuntime>(call->name(),
12171                              Runtime::FunctionForId(Runtime::kMapGet), 2));
12172     }
12173   }
12174
12175   return ast_context()->ReturnValue(Pop());
12176 }
12177
12178
12179 HValue* HOptimizedGraphBuilder::BuildStringHashLoadIfIsStringAndHashComputed(
12180     HValue* object, HIfContinuation* continuation) {
12181   IfBuilder string_checker(this);
12182   string_checker.If<HIsStringAndBranch>(object);
12183   string_checker.And();
12184   HValue* hash = Add<HLoadNamedField>(object, nullptr,
12185                                       HObjectAccess::ForStringHashField());
12186   HValue* hash_not_computed_mask = Add<HConstant>(String::kHashNotComputedMask);
12187   HValue* hash_computed_test =
12188       AddUncasted<HBitwise>(Token::BIT_AND, hash, hash_not_computed_mask);
12189   string_checker.If<HCompareNumericAndBranch>(
12190       hash_computed_test, graph()->GetConstant0(), Token::EQ);
12191   string_checker.Then();
12192   HValue* shifted_hash =
12193       AddUncasted<HShr>(hash, Add<HConstant>(String::kHashShift));
12194   string_checker.CaptureContinuation(continuation);
12195   return shifted_hash;
12196 }
12197
12198
12199 template <typename CollectionType>
12200 void HOptimizedGraphBuilder::BuildJSCollectionHas(
12201     CallRuntime* call, const Runtime::Function* c_function) {
12202   DCHECK(call->arguments()->length() == 2);
12203   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12204   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12205   HValue* key = Pop();
12206   HValue* receiver = Pop();
12207
12208   NoObservableSideEffectsScope no_effects(this);
12209
12210   HIfContinuation continuation;
12211   HValue* hash =
12212       BuildStringHashLoadIfIsStringAndHashComputed(key, &continuation);
12213   {
12214     IfBuilder string_checker(this, &continuation);
12215     string_checker.Then();
12216     {
12217       HValue* table = Add<HLoadNamedField>(
12218           receiver, nullptr, HObjectAccess::ForJSCollectionTable());
12219       HValue* key_index =
12220           BuildOrderedHashTableFindEntry<CollectionType>(table, key, hash);
12221       {
12222         IfBuilder if_found(this);
12223         if_found.If<HCompareNumericAndBranch>(
12224             key_index, Add<HConstant>(CollectionType::kNotFound), Token::NE);
12225         if_found.Then();
12226         Push(graph()->GetConstantTrue());
12227         if_found.Else();
12228         Push(graph()->GetConstantFalse());
12229       }
12230     }
12231     string_checker.Else();
12232     {
12233       Add<HPushArguments>(receiver, key);
12234       Push(Add<HCallRuntime>(call->name(), c_function, 2));
12235     }
12236   }
12237
12238   return ast_context()->ReturnValue(Pop());
12239 }
12240
12241
12242 void HOptimizedGraphBuilder::GenerateMapHas(CallRuntime* call) {
12243   BuildJSCollectionHas<OrderedHashMap>(
12244       call, Runtime::FunctionForId(Runtime::kMapHas));
12245 }
12246
12247
12248 void HOptimizedGraphBuilder::GenerateSetHas(CallRuntime* call) {
12249   BuildJSCollectionHas<OrderedHashSet>(
12250       call, Runtime::FunctionForId(Runtime::kSetHas));
12251 }
12252
12253
12254 template <typename CollectionType>
12255 HValue* HOptimizedGraphBuilder::BuildOrderedHashTableAddEntry(
12256     HValue* table, HValue* key, HValue* hash,
12257     HIfContinuation* join_continuation) {
12258   HValue* num_buckets = Add<HLoadNamedField>(
12259       table, nullptr,
12260       HObjectAccess::ForOrderedHashTableNumberOfBuckets<CollectionType>());
12261   HValue* capacity = AddUncasted<HMul>(
12262       num_buckets, Add<HConstant>(CollectionType::kLoadFactor));
12263   capacity->ClearFlag(HValue::kCanOverflow);
12264   HValue* num_elements = Add<HLoadNamedField>(
12265       table, nullptr,
12266       HObjectAccess::ForOrderedHashTableNumberOfElements<CollectionType>());
12267   HValue* num_deleted = Add<HLoadNamedField>(
12268       table, nullptr, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
12269                           CollectionType>());
12270   HValue* used = AddUncasted<HAdd>(num_elements, num_deleted);
12271   used->ClearFlag(HValue::kCanOverflow);
12272   IfBuilder if_space_available(this);
12273   if_space_available.If<HCompareNumericAndBranch>(capacity, used, Token::GT);
12274   if_space_available.Then();
12275   HValue* bucket = BuildOrderedHashTableHashToBucket(hash, num_buckets);
12276   HValue* entry = used;
12277   HValue* key_index =
12278       BuildOrderedHashTableEntryToIndex<CollectionType>(entry, num_buckets);
12279
12280   HValue* bucket_index = AddUncasted<HAdd>(
12281       bucket, Add<HConstant>(CollectionType::kHashTableStartIndex));
12282   bucket_index->ClearFlag(HValue::kCanOverflow);
12283   HValue* chain_entry =
12284       Add<HLoadKeyed>(table, bucket_index, nullptr, FAST_ELEMENTS);
12285   chain_entry->set_type(HType::Smi());
12286
12287   HValue* chain_index = AddUncasted<HAdd>(
12288       key_index, Add<HConstant>(CollectionType::kChainOffset));
12289   chain_index->ClearFlag(HValue::kCanOverflow);
12290
12291   Add<HStoreKeyed>(table, bucket_index, entry, FAST_ELEMENTS);
12292   Add<HStoreKeyed>(table, chain_index, chain_entry, FAST_ELEMENTS);
12293   Add<HStoreKeyed>(table, key_index, key, FAST_ELEMENTS);
12294
12295   HValue* new_num_elements =
12296       AddUncasted<HAdd>(num_elements, graph()->GetConstant1());
12297   new_num_elements->ClearFlag(HValue::kCanOverflow);
12298   Add<HStoreNamedField>(
12299       table,
12300       HObjectAccess::ForOrderedHashTableNumberOfElements<CollectionType>(),
12301       new_num_elements);
12302   if_space_available.JoinContinuation(join_continuation);
12303   return key_index;
12304 }
12305
12306
12307 void HOptimizedGraphBuilder::GenerateMapSet(CallRuntime* call) {
12308   DCHECK(call->arguments()->length() == 3);
12309   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12310   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12311   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
12312   HValue* value = Pop();
12313   HValue* key = Pop();
12314   HValue* receiver = Pop();
12315
12316   NoObservableSideEffectsScope no_effects(this);
12317
12318   HIfContinuation return_or_call_runtime_continuation(
12319       graph()->CreateBasicBlock(), graph()->CreateBasicBlock());
12320   HIfContinuation got_string_hash;
12321   HValue* hash =
12322       BuildStringHashLoadIfIsStringAndHashComputed(key, &got_string_hash);
12323   IfBuilder string_checker(this, &got_string_hash);
12324   string_checker.Then();
12325   {
12326     HValue* table = Add<HLoadNamedField>(receiver, nullptr,
12327                                          HObjectAccess::ForJSCollectionTable());
12328     HValue* key_index =
12329         BuildOrderedHashTableFindEntry<OrderedHashMap>(table, key, hash);
12330     {
12331       IfBuilder if_found(this);
12332       if_found.If<HCompareNumericAndBranch>(
12333           key_index, Add<HConstant>(OrderedHashMap::kNotFound), Token::NE);
12334       if_found.Then();
12335       {
12336         HValue* value_index = AddUncasted<HAdd>(
12337             key_index, Add<HConstant>(OrderedHashMap::kValueOffset));
12338         value_index->ClearFlag(HValue::kCanOverflow);
12339         Add<HStoreKeyed>(table, value_index, value, FAST_ELEMENTS);
12340       }
12341       if_found.Else();
12342       {
12343         HIfContinuation did_add(graph()->CreateBasicBlock(),
12344                                 graph()->CreateBasicBlock());
12345         HValue* key_index = BuildOrderedHashTableAddEntry<OrderedHashMap>(
12346             table, key, hash, &did_add);
12347         IfBuilder if_did_add(this, &did_add);
12348         if_did_add.Then();
12349         {
12350           HValue* value_index = AddUncasted<HAdd>(
12351               key_index, Add<HConstant>(OrderedHashMap::kValueOffset));
12352           value_index->ClearFlag(HValue::kCanOverflow);
12353           Add<HStoreKeyed>(table, value_index, value, FAST_ELEMENTS);
12354         }
12355         if_did_add.JoinContinuation(&return_or_call_runtime_continuation);
12356       }
12357     }
12358   }
12359   string_checker.JoinContinuation(&return_or_call_runtime_continuation);
12360
12361   {
12362     IfBuilder return_or_call_runtime(this,
12363                                      &return_or_call_runtime_continuation);
12364     return_or_call_runtime.Then();
12365     Push(receiver);
12366     return_or_call_runtime.Else();
12367     Add<HPushArguments>(receiver, key, value);
12368     Push(Add<HCallRuntime>(call->name(),
12369                            Runtime::FunctionForId(Runtime::kMapSet), 3));
12370   }
12371
12372   return ast_context()->ReturnValue(Pop());
12373 }
12374
12375
12376 void HOptimizedGraphBuilder::GenerateSetAdd(CallRuntime* call) {
12377   DCHECK(call->arguments()->length() == 2);
12378   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12379   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12380   HValue* key = Pop();
12381   HValue* receiver = Pop();
12382
12383   NoObservableSideEffectsScope no_effects(this);
12384
12385   HIfContinuation return_or_call_runtime_continuation(
12386       graph()->CreateBasicBlock(), graph()->CreateBasicBlock());
12387   HIfContinuation got_string_hash;
12388   HValue* hash =
12389       BuildStringHashLoadIfIsStringAndHashComputed(key, &got_string_hash);
12390   IfBuilder string_checker(this, &got_string_hash);
12391   string_checker.Then();
12392   {
12393     HValue* table = Add<HLoadNamedField>(receiver, nullptr,
12394                                          HObjectAccess::ForJSCollectionTable());
12395     HValue* key_index =
12396         BuildOrderedHashTableFindEntry<OrderedHashSet>(table, key, hash);
12397     {
12398       IfBuilder if_not_found(this);
12399       if_not_found.If<HCompareNumericAndBranch>(
12400           key_index, Add<HConstant>(OrderedHashSet::kNotFound), Token::EQ);
12401       if_not_found.Then();
12402       BuildOrderedHashTableAddEntry<OrderedHashSet>(
12403           table, key, hash, &return_or_call_runtime_continuation);
12404     }
12405   }
12406   string_checker.JoinContinuation(&return_or_call_runtime_continuation);
12407
12408   {
12409     IfBuilder return_or_call_runtime(this,
12410                                      &return_or_call_runtime_continuation);
12411     return_or_call_runtime.Then();
12412     Push(receiver);
12413     return_or_call_runtime.Else();
12414     Add<HPushArguments>(receiver, key);
12415     Push(Add<HCallRuntime>(call->name(),
12416                            Runtime::FunctionForId(Runtime::kSetAdd), 2));
12417   }
12418
12419   return ast_context()->ReturnValue(Pop());
12420 }
12421
12422
12423 template <typename CollectionType>
12424 void HOptimizedGraphBuilder::BuildJSCollectionDelete(
12425     CallRuntime* call, const Runtime::Function* c_function) {
12426   DCHECK(call->arguments()->length() == 2);
12427   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12428   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12429   HValue* key = Pop();
12430   HValue* receiver = Pop();
12431
12432   NoObservableSideEffectsScope no_effects(this);
12433
12434   HIfContinuation return_or_call_runtime_continuation(
12435       graph()->CreateBasicBlock(), graph()->CreateBasicBlock());
12436   HIfContinuation got_string_hash;
12437   HValue* hash =
12438       BuildStringHashLoadIfIsStringAndHashComputed(key, &got_string_hash);
12439   IfBuilder string_checker(this, &got_string_hash);
12440   string_checker.Then();
12441   {
12442     HValue* table = Add<HLoadNamedField>(receiver, nullptr,
12443                                          HObjectAccess::ForJSCollectionTable());
12444     HValue* key_index =
12445         BuildOrderedHashTableFindEntry<CollectionType>(table, key, hash);
12446     {
12447       IfBuilder if_found(this);
12448       if_found.If<HCompareNumericAndBranch>(
12449           key_index, Add<HConstant>(CollectionType::kNotFound), Token::NE);
12450       if_found.Then();
12451       {
12452         // If we're removing an element, we might need to shrink.
12453         // If we do need to shrink, we'll be bailing out to the runtime.
12454         HValue* num_elements = Add<HLoadNamedField>(
12455             table, nullptr, HObjectAccess::ForOrderedHashTableNumberOfElements<
12456                                 CollectionType>());
12457         num_elements = AddUncasted<HSub>(num_elements, graph()->GetConstant1());
12458         num_elements->ClearFlag(HValue::kCanOverflow);
12459
12460         HValue* num_buckets = Add<HLoadNamedField>(
12461             table, nullptr, HObjectAccess::ForOrderedHashTableNumberOfBuckets<
12462                                 CollectionType>());
12463         // threshold is capacity >> 2; we simplify this to num_buckets >> 1
12464         // since kLoadFactor is 2.
12465         STATIC_ASSERT(CollectionType::kLoadFactor == 2);
12466         HValue* threshold =
12467             AddUncasted<HShr>(num_buckets, graph()->GetConstant1());
12468
12469         IfBuilder if_need_not_shrink(this);
12470         if_need_not_shrink.If<HCompareNumericAndBranch>(num_elements, threshold,
12471                                                         Token::GTE);
12472         if_need_not_shrink.Then();
12473         {
12474           Add<HStoreKeyed>(table, key_index, graph()->GetConstantHole(),
12475                            FAST_ELEMENTS);
12476
12477           // For maps, also need to clear the value.
12478           if (CollectionType::kChainOffset > 1) {
12479             HValue* value_index =
12480                 AddUncasted<HAdd>(key_index, graph()->GetConstant1());
12481             value_index->ClearFlag(HValue::kCanOverflow);
12482             Add<HStoreKeyed>(table, value_index, graph()->GetConstantHole(),
12483                              FAST_ELEMENTS);
12484           }
12485           STATIC_ASSERT(CollectionType::kChainOffset <= 2);
12486
12487           HValue* num_deleted = Add<HLoadNamedField>(
12488               table, nullptr,
12489               HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
12490                   CollectionType>());
12491           num_deleted = AddUncasted<HAdd>(num_deleted, graph()->GetConstant1());
12492           num_deleted->ClearFlag(HValue::kCanOverflow);
12493           Add<HStoreNamedField>(
12494               table, HObjectAccess::ForOrderedHashTableNumberOfElements<
12495                          CollectionType>(),
12496               num_elements);
12497           Add<HStoreNamedField>(
12498               table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
12499                          CollectionType>(),
12500               num_deleted);
12501           Push(graph()->GetConstantTrue());
12502         }
12503         if_need_not_shrink.JoinContinuation(
12504             &return_or_call_runtime_continuation);
12505       }
12506       if_found.Else();
12507       {
12508         // Not found, so we're done.
12509         Push(graph()->GetConstantFalse());
12510       }
12511     }
12512   }
12513   string_checker.JoinContinuation(&return_or_call_runtime_continuation);
12514
12515   {
12516     IfBuilder return_or_call_runtime(this,
12517                                      &return_or_call_runtime_continuation);
12518     return_or_call_runtime.Then();
12519     return_or_call_runtime.Else();
12520     Add<HPushArguments>(receiver, key);
12521     Push(Add<HCallRuntime>(call->name(), c_function, 2));
12522   }
12523
12524   return ast_context()->ReturnValue(Pop());
12525 }
12526
12527
12528 void HOptimizedGraphBuilder::GenerateMapDelete(CallRuntime* call) {
12529   BuildJSCollectionDelete<OrderedHashMap>(
12530       call, Runtime::FunctionForId(Runtime::kMapDelete));
12531 }
12532
12533
12534 void HOptimizedGraphBuilder::GenerateSetDelete(CallRuntime* call) {
12535   BuildJSCollectionDelete<OrderedHashSet>(
12536       call, Runtime::FunctionForId(Runtime::kSetDelete));
12537 }
12538
12539
12540 void HOptimizedGraphBuilder::GenerateSetGetSize(CallRuntime* call) {
12541   DCHECK(call->arguments()->length() == 1);
12542   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12543   HValue* receiver = Pop();
12544   HValue* table = Add<HLoadNamedField>(receiver, nullptr,
12545                                        HObjectAccess::ForJSCollectionTable());
12546   HInstruction* result = New<HLoadNamedField>(
12547       table, nullptr,
12548       HObjectAccess::ForOrderedHashTableNumberOfElements<OrderedHashSet>());
12549   return ast_context()->ReturnInstruction(result, call->id());
12550 }
12551
12552
12553 void HOptimizedGraphBuilder::GenerateMapGetSize(CallRuntime* call) {
12554   DCHECK(call->arguments()->length() == 1);
12555   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12556   HValue* receiver = Pop();
12557   HValue* table = Add<HLoadNamedField>(receiver, nullptr,
12558                                        HObjectAccess::ForJSCollectionTable());
12559   HInstruction* result = New<HLoadNamedField>(
12560       table, nullptr,
12561       HObjectAccess::ForOrderedHashTableNumberOfElements<OrderedHashMap>());
12562   return ast_context()->ReturnInstruction(result, call->id());
12563 }
12564
12565
12566 template <typename CollectionType>
12567 HValue* HOptimizedGraphBuilder::BuildAllocateOrderedHashTable() {
12568   static const int kCapacity = CollectionType::kMinCapacity;
12569   static const int kBucketCount = kCapacity / CollectionType::kLoadFactor;
12570   static const int kFixedArrayLength = CollectionType::kHashTableStartIndex +
12571                                        kBucketCount +
12572                                        (kCapacity * CollectionType::kEntrySize);
12573   static const int kSizeInBytes =
12574       FixedArray::kHeaderSize + (kFixedArrayLength * kPointerSize);
12575
12576   // Allocate the table and add the proper map.
12577   HValue* table =
12578       Add<HAllocate>(Add<HConstant>(kSizeInBytes), HType::HeapObject(),
12579                      NOT_TENURED, FIXED_ARRAY_TYPE);
12580   AddStoreMapConstant(table, isolate()->factory()->ordered_hash_table_map());
12581
12582   // Initialize the FixedArray...
12583   HValue* length = Add<HConstant>(kFixedArrayLength);
12584   Add<HStoreNamedField>(table, HObjectAccess::ForFixedArrayLength(), length);
12585
12586   // ...and the OrderedHashTable fields.
12587   Add<HStoreNamedField>(
12588       table,
12589       HObjectAccess::ForOrderedHashTableNumberOfBuckets<CollectionType>(),
12590       Add<HConstant>(kBucketCount));
12591   Add<HStoreNamedField>(
12592       table,
12593       HObjectAccess::ForOrderedHashTableNumberOfElements<CollectionType>(),
12594       graph()->GetConstant0());
12595   Add<HStoreNamedField>(
12596       table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
12597                  CollectionType>(),
12598       graph()->GetConstant0());
12599
12600   // Fill the buckets with kNotFound.
12601   HValue* not_found = Add<HConstant>(CollectionType::kNotFound);
12602   for (int i = 0; i < kBucketCount; ++i) {
12603     Add<HStoreNamedField>(
12604         table, HObjectAccess::ForOrderedHashTableBucket<CollectionType>(i),
12605         not_found);
12606   }
12607
12608   // Fill the data table with undefined.
12609   HValue* undefined = graph()->GetConstantUndefined();
12610   for (int i = 0; i < (kCapacity * CollectionType::kEntrySize); ++i) {
12611     Add<HStoreNamedField>(table,
12612                           HObjectAccess::ForOrderedHashTableDataTableIndex<
12613                               CollectionType, kBucketCount>(i),
12614                           undefined);
12615   }
12616
12617   return table;
12618 }
12619
12620
12621 void HOptimizedGraphBuilder::GenerateSetInitialize(CallRuntime* call) {
12622   DCHECK(call->arguments()->length() == 1);
12623   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12624   HValue* receiver = Pop();
12625
12626   NoObservableSideEffectsScope no_effects(this);
12627   HValue* table = BuildAllocateOrderedHashTable<OrderedHashSet>();
12628   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(), table);
12629   return ast_context()->ReturnValue(receiver);
12630 }
12631
12632
12633 void HOptimizedGraphBuilder::GenerateMapInitialize(CallRuntime* call) {
12634   DCHECK(call->arguments()->length() == 1);
12635   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12636   HValue* receiver = Pop();
12637
12638   NoObservableSideEffectsScope no_effects(this);
12639   HValue* table = BuildAllocateOrderedHashTable<OrderedHashMap>();
12640   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(), table);
12641   return ast_context()->ReturnValue(receiver);
12642 }
12643
12644
12645 template <typename CollectionType>
12646 void HOptimizedGraphBuilder::BuildOrderedHashTableClear(HValue* receiver) {
12647   HValue* old_table = Add<HLoadNamedField>(
12648       receiver, nullptr, HObjectAccess::ForJSCollectionTable());
12649   HValue* new_table = BuildAllocateOrderedHashTable<CollectionType>();
12650   Add<HStoreNamedField>(
12651       old_table, HObjectAccess::ForOrderedHashTableNextTable<CollectionType>(),
12652       new_table);
12653   Add<HStoreNamedField>(
12654       old_table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
12655                      CollectionType>(),
12656       Add<HConstant>(CollectionType::kClearedTableSentinel));
12657   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(),
12658                         new_table);
12659 }
12660
12661
12662 void HOptimizedGraphBuilder::GenerateSetClear(CallRuntime* call) {
12663   DCHECK(call->arguments()->length() == 1);
12664   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12665   HValue* receiver = Pop();
12666
12667   NoObservableSideEffectsScope no_effects(this);
12668   BuildOrderedHashTableClear<OrderedHashSet>(receiver);
12669   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
12670 }
12671
12672
12673 void HOptimizedGraphBuilder::GenerateMapClear(CallRuntime* call) {
12674   DCHECK(call->arguments()->length() == 1);
12675   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12676   HValue* receiver = Pop();
12677
12678   NoObservableSideEffectsScope no_effects(this);
12679   BuildOrderedHashTableClear<OrderedHashMap>(receiver);
12680   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
12681 }
12682
12683
12684 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
12685   DCHECK(call->arguments()->length() == 1);
12686   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12687   HValue* value = Pop();
12688   HGetCachedArrayIndex* result = New<HGetCachedArrayIndex>(value);
12689   return ast_context()->ReturnInstruction(result, call->id());
12690 }
12691
12692
12693 void HOptimizedGraphBuilder::GenerateFastOneByteArrayJoin(CallRuntime* call) {
12694   // Simply returning undefined here would be semantically correct and even
12695   // avoid the bailout. Nevertheless, some ancient benchmarks like SunSpider's
12696   // string-fasta would tank, because fullcode contains an optimized version.
12697   // Obviously the fullcode => Crankshaft => bailout => fullcode dance is
12698   // faster... *sigh*
12699   return Bailout(kInlinedRuntimeFunctionFastOneByteArrayJoin);
12700 }
12701
12702
12703 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode(
12704     CallRuntime* call) {
12705   Add<HDebugBreak>();
12706   return ast_context()->ReturnValue(graph()->GetConstant0());
12707 }
12708
12709
12710 void HOptimizedGraphBuilder::GenerateDebugIsActive(CallRuntime* call) {
12711   DCHECK(call->arguments()->length() == 0);
12712   HValue* ref =
12713       Add<HConstant>(ExternalReference::debug_is_active_address(isolate()));
12714   HValue* value =
12715       Add<HLoadNamedField>(ref, nullptr, HObjectAccess::ForExternalUInteger8());
12716   return ast_context()->ReturnValue(value);
12717 }
12718
12719
12720 void HOptimizedGraphBuilder::GenerateGetPrototype(CallRuntime* call) {
12721   DCHECK(call->arguments()->length() == 1);
12722   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12723   HValue* object = Pop();
12724
12725   NoObservableSideEffectsScope no_effects(this);
12726
12727   HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap());
12728   HValue* bit_field =
12729       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField());
12730   HValue* is_access_check_needed_mask =
12731       Add<HConstant>(1 << Map::kIsAccessCheckNeeded);
12732   HValue* is_access_check_needed_test = AddUncasted<HBitwise>(
12733       Token::BIT_AND, bit_field, is_access_check_needed_mask);
12734
12735   HValue* proto =
12736       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForPrototype());
12737   HValue* proto_map =
12738       Add<HLoadNamedField>(proto, nullptr, HObjectAccess::ForMap());
12739   HValue* proto_bit_field =
12740       Add<HLoadNamedField>(proto_map, nullptr, HObjectAccess::ForMapBitField());
12741   HValue* is_hidden_prototype_mask =
12742       Add<HConstant>(1 << Map::kIsHiddenPrototype);
12743   HValue* is_hidden_prototype_test = AddUncasted<HBitwise>(
12744       Token::BIT_AND, proto_bit_field, is_hidden_prototype_mask);
12745
12746   {
12747     IfBuilder needs_runtime(this);
12748     needs_runtime.If<HCompareNumericAndBranch>(
12749         is_access_check_needed_test, graph()->GetConstant0(), Token::NE);
12750     needs_runtime.OrIf<HCompareNumericAndBranch>(
12751         is_hidden_prototype_test, graph()->GetConstant0(), Token::NE);
12752
12753     needs_runtime.Then();
12754     {
12755       Add<HPushArguments>(object);
12756       Push(Add<HCallRuntime>(
12757           call->name(), Runtime::FunctionForId(Runtime::kGetPrototype), 1));
12758     }
12759
12760     needs_runtime.Else();
12761     Push(proto);
12762   }
12763   return ast_context()->ReturnValue(Pop());
12764 }
12765
12766
12767 #undef CHECK_BAILOUT
12768 #undef CHECK_ALIVE
12769
12770
12771 HEnvironment::HEnvironment(HEnvironment* outer,
12772                            Scope* scope,
12773                            Handle<JSFunction> closure,
12774                            Zone* zone)
12775     : closure_(closure),
12776       values_(0, zone),
12777       frame_type_(JS_FUNCTION),
12778       parameter_count_(0),
12779       specials_count_(1),
12780       local_count_(0),
12781       outer_(outer),
12782       entry_(NULL),
12783       pop_count_(0),
12784       push_count_(0),
12785       ast_id_(BailoutId::None()),
12786       zone_(zone) {
12787   Scope* declaration_scope = scope->DeclarationScope();
12788   Initialize(declaration_scope->num_parameters() + 1,
12789              declaration_scope->num_stack_slots(), 0);
12790 }
12791
12792
12793 HEnvironment::HEnvironment(Zone* zone, int parameter_count)
12794     : values_(0, zone),
12795       frame_type_(STUB),
12796       parameter_count_(parameter_count),
12797       specials_count_(1),
12798       local_count_(0),
12799       outer_(NULL),
12800       entry_(NULL),
12801       pop_count_(0),
12802       push_count_(0),
12803       ast_id_(BailoutId::None()),
12804       zone_(zone) {
12805   Initialize(parameter_count, 0, 0);
12806 }
12807
12808
12809 HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone)
12810     : values_(0, zone),
12811       frame_type_(JS_FUNCTION),
12812       parameter_count_(0),
12813       specials_count_(0),
12814       local_count_(0),
12815       outer_(NULL),
12816       entry_(NULL),
12817       pop_count_(0),
12818       push_count_(0),
12819       ast_id_(other->ast_id()),
12820       zone_(zone) {
12821   Initialize(other);
12822 }
12823
12824
12825 HEnvironment::HEnvironment(HEnvironment* outer,
12826                            Handle<JSFunction> closure,
12827                            FrameType frame_type,
12828                            int arguments,
12829                            Zone* zone)
12830     : closure_(closure),
12831       values_(arguments, zone),
12832       frame_type_(frame_type),
12833       parameter_count_(arguments),
12834       specials_count_(0),
12835       local_count_(0),
12836       outer_(outer),
12837       entry_(NULL),
12838       pop_count_(0),
12839       push_count_(0),
12840       ast_id_(BailoutId::None()),
12841       zone_(zone) {
12842 }
12843
12844
12845 void HEnvironment::Initialize(int parameter_count,
12846                               int local_count,
12847                               int stack_height) {
12848   parameter_count_ = parameter_count;
12849   local_count_ = local_count;
12850
12851   // Avoid reallocating the temporaries' backing store on the first Push.
12852   int total = parameter_count + specials_count_ + local_count + stack_height;
12853   values_.Initialize(total + 4, zone());
12854   for (int i = 0; i < total; ++i) values_.Add(NULL, zone());
12855 }
12856
12857
12858 void HEnvironment::Initialize(const HEnvironment* other) {
12859   closure_ = other->closure();
12860   values_.AddAll(other->values_, zone());
12861   assigned_variables_.Union(other->assigned_variables_, zone());
12862   frame_type_ = other->frame_type_;
12863   parameter_count_ = other->parameter_count_;
12864   local_count_ = other->local_count_;
12865   if (other->outer_ != NULL) outer_ = other->outer_->Copy();  // Deep copy.
12866   entry_ = other->entry_;
12867   pop_count_ = other->pop_count_;
12868   push_count_ = other->push_count_;
12869   specials_count_ = other->specials_count_;
12870   ast_id_ = other->ast_id_;
12871 }
12872
12873
12874 void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
12875   DCHECK(!block->IsLoopHeader());
12876   DCHECK(values_.length() == other->values_.length());
12877
12878   int length = values_.length();
12879   for (int i = 0; i < length; ++i) {
12880     HValue* value = values_[i];
12881     if (value != NULL && value->IsPhi() && value->block() == block) {
12882       // There is already a phi for the i'th value.
12883       HPhi* phi = HPhi::cast(value);
12884       // Assert index is correct and that we haven't missed an incoming edge.
12885       DCHECK(phi->merged_index() == i || !phi->HasMergedIndex());
12886       DCHECK(phi->OperandCount() == block->predecessors()->length());
12887       phi->AddInput(other->values_[i]);
12888     } else if (values_[i] != other->values_[i]) {
12889       // There is a fresh value on the incoming edge, a phi is needed.
12890       DCHECK(values_[i] != NULL && other->values_[i] != NULL);
12891       HPhi* phi = block->AddNewPhi(i);
12892       HValue* old_value = values_[i];
12893       for (int j = 0; j < block->predecessors()->length(); j++) {
12894         phi->AddInput(old_value);
12895       }
12896       phi->AddInput(other->values_[i]);
12897       this->values_[i] = phi;
12898     }
12899   }
12900 }
12901
12902
12903 void HEnvironment::Bind(int index, HValue* value) {
12904   DCHECK(value != NULL);
12905   assigned_variables_.Add(index, zone());
12906   values_[index] = value;
12907 }
12908
12909
12910 bool HEnvironment::HasExpressionAt(int index) const {
12911   return index >= parameter_count_ + specials_count_ + local_count_;
12912 }
12913
12914
12915 bool HEnvironment::ExpressionStackIsEmpty() const {
12916   DCHECK(length() >= first_expression_index());
12917   return length() == first_expression_index();
12918 }
12919
12920
12921 void HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) {
12922   int count = index_from_top + 1;
12923   int index = values_.length() - count;
12924   DCHECK(HasExpressionAt(index));
12925   // The push count must include at least the element in question or else
12926   // the new value will not be included in this environment's history.
12927   if (push_count_ < count) {
12928     // This is the same effect as popping then re-pushing 'count' elements.
12929     pop_count_ += (count - push_count_);
12930     push_count_ = count;
12931   }
12932   values_[index] = value;
12933 }
12934
12935
12936 HValue* HEnvironment::RemoveExpressionStackAt(int index_from_top) {
12937   int count = index_from_top + 1;
12938   int index = values_.length() - count;
12939   DCHECK(HasExpressionAt(index));
12940   // Simulate popping 'count' elements and then
12941   // pushing 'count - 1' elements back.
12942   pop_count_ += Max(count - push_count_, 0);
12943   push_count_ = Max(push_count_ - count, 0) + (count - 1);
12944   return values_.Remove(index);
12945 }
12946
12947
12948 void HEnvironment::Drop(int count) {
12949   for (int i = 0; i < count; ++i) {
12950     Pop();
12951   }
12952 }
12953
12954
12955 HEnvironment* HEnvironment::Copy() const {
12956   return new(zone()) HEnvironment(this, zone());
12957 }
12958
12959
12960 HEnvironment* HEnvironment::CopyWithoutHistory() const {
12961   HEnvironment* result = Copy();
12962   result->ClearHistory();
12963   return result;
12964 }
12965
12966
12967 HEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const {
12968   HEnvironment* new_env = Copy();
12969   for (int i = 0; i < values_.length(); ++i) {
12970     HPhi* phi = loop_header->AddNewPhi(i);
12971     phi->AddInput(values_[i]);
12972     new_env->values_[i] = phi;
12973   }
12974   new_env->ClearHistory();
12975   return new_env;
12976 }
12977
12978
12979 HEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer,
12980                                                   Handle<JSFunction> target,
12981                                                   FrameType frame_type,
12982                                                   int arguments) const {
12983   HEnvironment* new_env =
12984       new(zone()) HEnvironment(outer, target, frame_type,
12985                                arguments + 1, zone());
12986   for (int i = 0; i <= arguments; ++i) {  // Include receiver.
12987     new_env->Push(ExpressionStackAt(arguments - i));
12988   }
12989   new_env->ClearHistory();
12990   return new_env;
12991 }
12992
12993
12994 HEnvironment* HEnvironment::CopyForInlining(
12995     Handle<JSFunction> target,
12996     int arguments,
12997     FunctionLiteral* function,
12998     HConstant* undefined,
12999     InliningKind inlining_kind) const {
13000   DCHECK(frame_type() == JS_FUNCTION);
13001
13002   // Outer environment is a copy of this one without the arguments.
13003   int arity = function->scope()->num_parameters();
13004
13005   HEnvironment* outer = Copy();
13006   outer->Drop(arguments + 1);  // Including receiver.
13007   outer->ClearHistory();
13008
13009   if (inlining_kind == CONSTRUCT_CALL_RETURN) {
13010     // Create artificial constructor stub environment.  The receiver should
13011     // actually be the constructor function, but we pass the newly allocated
13012     // object instead, DoComputeConstructStubFrame() relies on that.
13013     outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments);
13014   } else if (inlining_kind == GETTER_CALL_RETURN) {
13015     // We need an additional StackFrame::INTERNAL frame for restoring the
13016     // correct context.
13017     outer = CreateStubEnvironment(outer, target, JS_GETTER, arguments);
13018   } else if (inlining_kind == SETTER_CALL_RETURN) {
13019     // We need an additional StackFrame::INTERNAL frame for temporarily saving
13020     // the argument of the setter, see StoreStubCompiler::CompileStoreViaSetter.
13021     outer = CreateStubEnvironment(outer, target, JS_SETTER, arguments);
13022   }
13023
13024   if (arity != arguments) {
13025     // Create artificial arguments adaptation environment.
13026     outer = CreateStubEnvironment(outer, target, ARGUMENTS_ADAPTOR, arguments);
13027   }
13028
13029   HEnvironment* inner =
13030       new(zone()) HEnvironment(outer, function->scope(), target, zone());
13031   // Get the argument values from the original environment.
13032   for (int i = 0; i <= arity; ++i) {  // Include receiver.
13033     HValue* push = (i <= arguments) ?
13034         ExpressionStackAt(arguments - i) : undefined;
13035     inner->SetValueAt(i, push);
13036   }
13037   inner->SetValueAt(arity + 1, context());
13038   for (int i = arity + 2; i < inner->length(); ++i) {
13039     inner->SetValueAt(i, undefined);
13040   }
13041
13042   inner->set_ast_id(BailoutId::FunctionEntry());
13043   return inner;
13044 }
13045
13046
13047 std::ostream& operator<<(std::ostream& os, const HEnvironment& env) {
13048   for (int i = 0; i < env.length(); i++) {
13049     if (i == 0) os << "parameters\n";
13050     if (i == env.parameter_count()) os << "specials\n";
13051     if (i == env.parameter_count() + env.specials_count()) os << "locals\n";
13052     if (i == env.parameter_count() + env.specials_count() + env.local_count()) {
13053       os << "expressions\n";
13054     }
13055     HValue* val = env.values()->at(i);
13056     os << i << ": ";
13057     if (val != NULL) {
13058       os << val;
13059     } else {
13060       os << "NULL";
13061     }
13062     os << "\n";
13063   }
13064   return os << "\n";
13065 }
13066
13067
13068 void HTracer::TraceCompilation(CompilationInfo* info) {
13069   Tag tag(this, "compilation");
13070   if (info->IsOptimizing()) {
13071     Handle<String> name = info->function()->debug_name();
13072     PrintStringProperty("name", name->ToCString().get());
13073     PrintIndent();
13074     trace_.Add("method \"%s:%d\"\n",
13075                name->ToCString().get(),
13076                info->optimization_id());
13077   } else {
13078     CodeStub::Major major_key = info->code_stub()->MajorKey();
13079     PrintStringProperty("name", CodeStub::MajorName(major_key, false));
13080     PrintStringProperty("method", "stub");
13081   }
13082   PrintLongProperty("date",
13083                     static_cast<int64_t>(base::OS::TimeCurrentMillis()));
13084 }
13085
13086
13087 void HTracer::TraceLithium(const char* name, LChunk* chunk) {
13088   DCHECK(!chunk->isolate()->concurrent_recompilation_enabled());
13089   AllowHandleDereference allow_deref;
13090   AllowDeferredHandleDereference allow_deferred_deref;
13091   Trace(name, chunk->graph(), chunk);
13092 }
13093
13094
13095 void HTracer::TraceHydrogen(const char* name, HGraph* graph) {
13096   DCHECK(!graph->isolate()->concurrent_recompilation_enabled());
13097   AllowHandleDereference allow_deref;
13098   AllowDeferredHandleDereference allow_deferred_deref;
13099   Trace(name, graph, NULL);
13100 }
13101
13102
13103 void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
13104   Tag tag(this, "cfg");
13105   PrintStringProperty("name", name);
13106   const ZoneList<HBasicBlock*>* blocks = graph->blocks();
13107   for (int i = 0; i < blocks->length(); i++) {
13108     HBasicBlock* current = blocks->at(i);
13109     Tag block_tag(this, "block");
13110     PrintBlockProperty("name", current->block_id());
13111     PrintIntProperty("from_bci", -1);
13112     PrintIntProperty("to_bci", -1);
13113
13114     if (!current->predecessors()->is_empty()) {
13115       PrintIndent();
13116       trace_.Add("predecessors");
13117       for (int j = 0; j < current->predecessors()->length(); ++j) {
13118         trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id());
13119       }
13120       trace_.Add("\n");
13121     } else {
13122       PrintEmptyProperty("predecessors");
13123     }
13124
13125     if (current->end()->SuccessorCount() == 0) {
13126       PrintEmptyProperty("successors");
13127     } else  {
13128       PrintIndent();
13129       trace_.Add("successors");
13130       for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) {
13131         trace_.Add(" \"B%d\"", it.Current()->block_id());
13132       }
13133       trace_.Add("\n");
13134     }
13135
13136     PrintEmptyProperty("xhandlers");
13137
13138     {
13139       PrintIndent();
13140       trace_.Add("flags");
13141       if (current->IsLoopSuccessorDominator()) {
13142         trace_.Add(" \"dom-loop-succ\"");
13143       }
13144       if (current->IsUnreachable()) {
13145         trace_.Add(" \"dead\"");
13146       }
13147       if (current->is_osr_entry()) {
13148         trace_.Add(" \"osr\"");
13149       }
13150       trace_.Add("\n");
13151     }
13152
13153     if (current->dominator() != NULL) {
13154       PrintBlockProperty("dominator", current->dominator()->block_id());
13155     }
13156
13157     PrintIntProperty("loop_depth", current->LoopNestingDepth());
13158
13159     if (chunk != NULL) {
13160       int first_index = current->first_instruction_index();
13161       int last_index = current->last_instruction_index();
13162       PrintIntProperty(
13163           "first_lir_id",
13164           LifetimePosition::FromInstructionIndex(first_index).Value());
13165       PrintIntProperty(
13166           "last_lir_id",
13167           LifetimePosition::FromInstructionIndex(last_index).Value());
13168     }
13169
13170     {
13171       Tag states_tag(this, "states");
13172       Tag locals_tag(this, "locals");
13173       int total = current->phis()->length();
13174       PrintIntProperty("size", current->phis()->length());
13175       PrintStringProperty("method", "None");
13176       for (int j = 0; j < total; ++j) {
13177         HPhi* phi = current->phis()->at(j);
13178         PrintIndent();
13179         std::ostringstream os;
13180         os << phi->merged_index() << " " << NameOf(phi) << " " << *phi << "\n";
13181         trace_.Add(os.str().c_str());
13182       }
13183     }
13184
13185     {
13186       Tag HIR_tag(this, "HIR");
13187       for (HInstructionIterator it(current); !it.Done(); it.Advance()) {
13188         HInstruction* instruction = it.Current();
13189         int uses = instruction->UseCount();
13190         PrintIndent();
13191         std::ostringstream os;
13192         os << "0 " << uses << " " << NameOf(instruction) << " " << *instruction;
13193         if (graph->info()->is_tracking_positions() &&
13194             instruction->has_position() && instruction->position().raw() != 0) {
13195           const SourcePosition pos = instruction->position();
13196           os << " pos:";
13197           if (pos.inlining_id() != 0) os << pos.inlining_id() << "_";
13198           os << pos.position();
13199         }
13200         os << " <|@\n";
13201         trace_.Add(os.str().c_str());
13202       }
13203     }
13204
13205
13206     if (chunk != NULL) {
13207       Tag LIR_tag(this, "LIR");
13208       int first_index = current->first_instruction_index();
13209       int last_index = current->last_instruction_index();
13210       if (first_index != -1 && last_index != -1) {
13211         const ZoneList<LInstruction*>* instructions = chunk->instructions();
13212         for (int i = first_index; i <= last_index; ++i) {
13213           LInstruction* linstr = instructions->at(i);
13214           if (linstr != NULL) {
13215             PrintIndent();
13216             trace_.Add("%d ",
13217                        LifetimePosition::FromInstructionIndex(i).Value());
13218             linstr->PrintTo(&trace_);
13219             std::ostringstream os;
13220             os << " [hir:" << NameOf(linstr->hydrogen_value()) << "] <|@\n";
13221             trace_.Add(os.str().c_str());
13222           }
13223         }
13224       }
13225     }
13226   }
13227 }
13228
13229
13230 void HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) {
13231   Tag tag(this, "intervals");
13232   PrintStringProperty("name", name);
13233
13234   const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
13235   for (int i = 0; i < fixed_d->length(); ++i) {
13236     TraceLiveRange(fixed_d->at(i), "fixed", allocator->zone());
13237   }
13238
13239   const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges();
13240   for (int i = 0; i < fixed->length(); ++i) {
13241     TraceLiveRange(fixed->at(i), "fixed", allocator->zone());
13242   }
13243
13244   const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges();
13245   for (int i = 0; i < live_ranges->length(); ++i) {
13246     TraceLiveRange(live_ranges->at(i), "object", allocator->zone());
13247   }
13248 }
13249
13250
13251 void HTracer::TraceLiveRange(LiveRange* range, const char* type,
13252                              Zone* zone) {
13253   if (range != NULL && !range->IsEmpty()) {
13254     PrintIndent();
13255     trace_.Add("%d %s", range->id(), type);
13256     if (range->HasRegisterAssigned()) {
13257       LOperand* op = range->CreateAssignedOperand(zone);
13258       int assigned_reg = op->index();
13259       if (op->IsDoubleRegister()) {
13260         trace_.Add(" \"%s\"",
13261                    DoubleRegister::AllocationIndexToString(assigned_reg));
13262       } else {
13263         DCHECK(op->IsRegister());
13264         trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg));
13265       }
13266     } else if (range->IsSpilled()) {
13267       LOperand* op = range->TopLevel()->GetSpillOperand();
13268       if (op->IsDoubleStackSlot()) {
13269         trace_.Add(" \"double_stack:%d\"", op->index());
13270       } else {
13271         DCHECK(op->IsStackSlot());
13272         trace_.Add(" \"stack:%d\"", op->index());
13273       }
13274     }
13275     int parent_index = -1;
13276     if (range->IsChild()) {
13277       parent_index = range->parent()->id();
13278     } else {
13279       parent_index = range->id();
13280     }
13281     LOperand* op = range->FirstHint();
13282     int hint_index = -1;
13283     if (op != NULL && op->IsUnallocated()) {
13284       hint_index = LUnallocated::cast(op)->virtual_register();
13285     }
13286     trace_.Add(" %d %d", parent_index, hint_index);
13287     UseInterval* cur_interval = range->first_interval();
13288     while (cur_interval != NULL && range->Covers(cur_interval->start())) {
13289       trace_.Add(" [%d, %d[",
13290                  cur_interval->start().Value(),
13291                  cur_interval->end().Value());
13292       cur_interval = cur_interval->next();
13293     }
13294
13295     UsePosition* current_pos = range->first_pos();
13296     while (current_pos != NULL) {
13297       if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
13298         trace_.Add(" %d M", current_pos->pos().Value());
13299       }
13300       current_pos = current_pos->next();
13301     }
13302
13303     trace_.Add(" \"\"\n");
13304   }
13305 }
13306
13307
13308 void HTracer::FlushToFile() {
13309   AppendChars(filename_.start(), trace_.ToCString().get(), trace_.length(),
13310               false);
13311   trace_.Reset();
13312 }
13313
13314
13315 void HStatistics::Initialize(CompilationInfo* info) {
13316   if (info->shared_info().is_null()) return;
13317   source_size_ += info->shared_info()->SourceSize();
13318 }
13319
13320
13321 void HStatistics::Print() {
13322   PrintF(
13323       "\n"
13324       "----------------------------------------"
13325       "----------------------------------------\n"
13326       "--- Hydrogen timing results:\n"
13327       "----------------------------------------"
13328       "----------------------------------------\n");
13329   base::TimeDelta sum;
13330   for (int i = 0; i < times_.length(); ++i) {
13331     sum += times_[i];
13332   }
13333
13334   for (int i = 0; i < names_.length(); ++i) {
13335     PrintF("%33s", names_[i]);
13336     double ms = times_[i].InMillisecondsF();
13337     double percent = times_[i].PercentOf(sum);
13338     PrintF(" %8.3f ms / %4.1f %% ", ms, percent);
13339
13340     size_t size = sizes_[i];
13341     double size_percent = static_cast<double>(size) * 100 / total_size_;
13342     PrintF(" %9zu bytes / %4.1f %%\n", size, size_percent);
13343   }
13344
13345   PrintF(
13346       "----------------------------------------"
13347       "----------------------------------------\n");
13348   base::TimeDelta total = create_graph_ + optimize_graph_ + generate_code_;
13349   PrintF("%33s %8.3f ms / %4.1f %% \n", "Create graph",
13350          create_graph_.InMillisecondsF(), create_graph_.PercentOf(total));
13351   PrintF("%33s %8.3f ms / %4.1f %% \n", "Optimize graph",
13352          optimize_graph_.InMillisecondsF(), optimize_graph_.PercentOf(total));
13353   PrintF("%33s %8.3f ms / %4.1f %% \n", "Generate and install code",
13354          generate_code_.InMillisecondsF(), generate_code_.PercentOf(total));
13355   PrintF(
13356       "----------------------------------------"
13357       "----------------------------------------\n");
13358   PrintF("%33s %8.3f ms           %9zu bytes\n", "Total",
13359          total.InMillisecondsF(), total_size_);
13360   PrintF("%33s     (%.1f times slower than full code gen)\n", "",
13361          total.TimesOf(full_code_gen_));
13362
13363   double source_size_in_kb = static_cast<double>(source_size_) / 1024;
13364   double normalized_time =  source_size_in_kb > 0
13365       ? total.InMillisecondsF() / source_size_in_kb
13366       : 0;
13367   double normalized_size_in_kb =
13368       source_size_in_kb > 0
13369           ? static_cast<double>(total_size_) / 1024 / source_size_in_kb
13370           : 0;
13371   PrintF("%33s %8.3f ms           %7.3f kB allocated\n",
13372          "Average per kB source", normalized_time, normalized_size_in_kb);
13373 }
13374
13375
13376 void HStatistics::SaveTiming(const char* name, base::TimeDelta time,
13377                              size_t size) {
13378   total_size_ += size;
13379   for (int i = 0; i < names_.length(); ++i) {
13380     if (strcmp(names_[i], name) == 0) {
13381       times_[i] += time;
13382       sizes_[i] += size;
13383       return;
13384     }
13385   }
13386   names_.Add(name);
13387   times_.Add(time);
13388   sizes_.Add(size);
13389 }
13390
13391
13392 HPhase::~HPhase() {
13393   if (ShouldProduceTraceOutput()) {
13394     isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
13395   }
13396
13397 #ifdef DEBUG
13398   graph_->Verify(false);  // No full verify.
13399 #endif
13400 }
13401
13402 } }  // namespace v8::internal