Correctify instanceof and make it optimizable.
[platform/upstream/v8.git] / src / hydrogen.cc
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/hydrogen.h"
6
7 #include <sstream>
8
9 #include "src/allocation-site-scopes.h"
10 #include "src/ast-numbering.h"
11 #include "src/full-codegen/full-codegen.h"
12 #include "src/hydrogen-bce.h"
13 #include "src/hydrogen-bch.h"
14 #include "src/hydrogen-canonicalize.h"
15 #include "src/hydrogen-check-elimination.h"
16 #include "src/hydrogen-dce.h"
17 #include "src/hydrogen-dehoist.h"
18 #include "src/hydrogen-environment-liveness.h"
19 #include "src/hydrogen-escape-analysis.h"
20 #include "src/hydrogen-gvn.h"
21 #include "src/hydrogen-infer-representation.h"
22 #include "src/hydrogen-infer-types.h"
23 #include "src/hydrogen-load-elimination.h"
24 #include "src/hydrogen-mark-deoptimize.h"
25 #include "src/hydrogen-mark-unreachable.h"
26 #include "src/hydrogen-osr.h"
27 #include "src/hydrogen-range-analysis.h"
28 #include "src/hydrogen-redundant-phi.h"
29 #include "src/hydrogen-removable-simulates.h"
30 #include "src/hydrogen-representation-changes.h"
31 #include "src/hydrogen-sce.h"
32 #include "src/hydrogen-store-elimination.h"
33 #include "src/hydrogen-uint32-analysis.h"
34 #include "src/ic/call-optimization.h"
35 #include "src/ic/ic.h"
36 // GetRootConstructor
37 #include "src/ic/ic-inl.h"
38 #include "src/lithium-allocator.h"
39 #include "src/parser.h"
40 #include "src/runtime/runtime.h"
41 #include "src/scopeinfo.h"
42 #include "src/typing.h"
43
44 #if V8_TARGET_ARCH_IA32
45 #include "src/ia32/lithium-codegen-ia32.h"  // NOLINT
46 #elif V8_TARGET_ARCH_X64
47 #include "src/x64/lithium-codegen-x64.h"  // NOLINT
48 #elif V8_TARGET_ARCH_ARM64
49 #include "src/arm64/lithium-codegen-arm64.h"  // NOLINT
50 #elif V8_TARGET_ARCH_ARM
51 #include "src/arm/lithium-codegen-arm.h"  // NOLINT
52 #elif V8_TARGET_ARCH_PPC
53 #include "src/ppc/lithium-codegen-ppc.h"  // NOLINT
54 #elif V8_TARGET_ARCH_MIPS
55 #include "src/mips/lithium-codegen-mips.h"  // NOLINT
56 #elif V8_TARGET_ARCH_MIPS64
57 #include "src/mips64/lithium-codegen-mips64.h"  // NOLINT
58 #elif V8_TARGET_ARCH_X87
59 #include "src/x87/lithium-codegen-x87.h"  // NOLINT
60 #else
61 #error Unsupported target architecture.
62 #endif
63
64 namespace v8 {
65 namespace internal {
66
67 HBasicBlock::HBasicBlock(HGraph* graph)
68     : block_id_(graph->GetNextBlockID()),
69       graph_(graph),
70       phis_(4, graph->zone()),
71       first_(NULL),
72       last_(NULL),
73       end_(NULL),
74       loop_information_(NULL),
75       predecessors_(2, graph->zone()),
76       dominator_(NULL),
77       dominated_blocks_(4, graph->zone()),
78       last_environment_(NULL),
79       argument_count_(-1),
80       first_instruction_index_(-1),
81       last_instruction_index_(-1),
82       deleted_phis_(4, graph->zone()),
83       parent_loop_header_(NULL),
84       inlined_entry_block_(NULL),
85       is_inline_return_target_(false),
86       is_reachable_(true),
87       dominates_loop_successors_(false),
88       is_osr_entry_(false),
89       is_ordered_(false) { }
90
91
92 Isolate* HBasicBlock::isolate() const {
93   return graph_->isolate();
94 }
95
96
97 void HBasicBlock::MarkUnreachable() {
98   is_reachable_ = false;
99 }
100
101
102 void HBasicBlock::AttachLoopInformation() {
103   DCHECK(!IsLoopHeader());
104   loop_information_ = new(zone()) HLoopInformation(this, zone());
105 }
106
107
108 void HBasicBlock::DetachLoopInformation() {
109   DCHECK(IsLoopHeader());
110   loop_information_ = NULL;
111 }
112
113
114 void HBasicBlock::AddPhi(HPhi* phi) {
115   DCHECK(!IsStartBlock());
116   phis_.Add(phi, zone());
117   phi->SetBlock(this);
118 }
119
120
121 void HBasicBlock::RemovePhi(HPhi* phi) {
122   DCHECK(phi->block() == this);
123   DCHECK(phis_.Contains(phi));
124   phi->Kill();
125   phis_.RemoveElement(phi);
126   phi->SetBlock(NULL);
127 }
128
129
130 void HBasicBlock::AddInstruction(HInstruction* instr, SourcePosition position) {
131   DCHECK(!IsStartBlock() || !IsFinished());
132   DCHECK(!instr->IsLinked());
133   DCHECK(!IsFinished());
134
135   if (!position.IsUnknown()) {
136     instr->set_position(position);
137   }
138   if (first_ == NULL) {
139     DCHECK(last_environment() != NULL);
140     DCHECK(!last_environment()->ast_id().IsNone());
141     HBlockEntry* entry = new(zone()) HBlockEntry();
142     entry->InitializeAsFirst(this);
143     if (!position.IsUnknown()) {
144       entry->set_position(position);
145     } else {
146       DCHECK(!FLAG_hydrogen_track_positions ||
147              !graph()->info()->IsOptimizing() || instr->IsAbnormalExit());
148     }
149     first_ = last_ = entry;
150   }
151   instr->InsertAfter(last_);
152 }
153
154
155 HPhi* HBasicBlock::AddNewPhi(int merged_index) {
156   if (graph()->IsInsideNoSideEffectsScope()) {
157     merged_index = HPhi::kInvalidMergedIndex;
158   }
159   HPhi* phi = new(zone()) HPhi(merged_index, zone());
160   AddPhi(phi);
161   return phi;
162 }
163
164
165 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id,
166                                        RemovableSimulate removable) {
167   DCHECK(HasEnvironment());
168   HEnvironment* environment = last_environment();
169   DCHECK(ast_id.IsNone() ||
170          ast_id == BailoutId::StubEntry() ||
171          environment->closure()->shared()->VerifyBailoutId(ast_id));
172
173   int push_count = environment->push_count();
174   int pop_count = environment->pop_count();
175
176   HSimulate* instr =
177       new(zone()) HSimulate(ast_id, pop_count, zone(), removable);
178 #ifdef DEBUG
179   instr->set_closure(environment->closure());
180 #endif
181   // Order of pushed values: newest (top of stack) first. This allows
182   // HSimulate::MergeWith() to easily append additional pushed values
183   // that are older (from further down the stack).
184   for (int i = 0; i < push_count; ++i) {
185     instr->AddPushedValue(environment->ExpressionStackAt(i));
186   }
187   for (GrowableBitVector::Iterator it(environment->assigned_variables(),
188                                       zone());
189        !it.Done();
190        it.Advance()) {
191     int index = it.Current();
192     instr->AddAssignedValue(index, environment->Lookup(index));
193   }
194   environment->ClearHistory();
195   return instr;
196 }
197
198
199 void HBasicBlock::Finish(HControlInstruction* end, SourcePosition position) {
200   DCHECK(!IsFinished());
201   AddInstruction(end, position);
202   end_ = end;
203   for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
204     it.Current()->RegisterPredecessor(this);
205   }
206 }
207
208
209 void HBasicBlock::Goto(HBasicBlock* block, SourcePosition position,
210                        FunctionState* state, bool add_simulate) {
211   bool drop_extra = state != NULL &&
212       state->inlining_kind() == NORMAL_RETURN;
213
214   if (block->IsInlineReturnTarget()) {
215     HEnvironment* env = last_environment();
216     int argument_count = env->arguments_environment()->parameter_count();
217     AddInstruction(new(zone())
218                    HLeaveInlined(state->entry(), argument_count),
219                    position);
220     UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
221   }
222
223   if (add_simulate) AddNewSimulate(BailoutId::None(), position);
224   HGoto* instr = new(zone()) HGoto(block);
225   Finish(instr, position);
226 }
227
228
229 void HBasicBlock::AddLeaveInlined(HValue* return_value, FunctionState* state,
230                                   SourcePosition position) {
231   HBasicBlock* target = state->function_return();
232   bool drop_extra = state->inlining_kind() == NORMAL_RETURN;
233
234   DCHECK(target->IsInlineReturnTarget());
235   DCHECK(return_value != NULL);
236   HEnvironment* env = last_environment();
237   int argument_count = env->arguments_environment()->parameter_count();
238   AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count),
239                  position);
240   UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
241   last_environment()->Push(return_value);
242   AddNewSimulate(BailoutId::None(), position);
243   HGoto* instr = new(zone()) HGoto(target);
244   Finish(instr, position);
245 }
246
247
248 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
249   DCHECK(!HasEnvironment());
250   DCHECK(first() == NULL);
251   UpdateEnvironment(env);
252 }
253
254
255 void HBasicBlock::UpdateEnvironment(HEnvironment* env) {
256   last_environment_ = env;
257   graph()->update_maximum_environment_size(env->first_expression_index());
258 }
259
260
261 void HBasicBlock::SetJoinId(BailoutId ast_id) {
262   int length = predecessors_.length();
263   DCHECK(length > 0);
264   for (int i = 0; i < length; i++) {
265     HBasicBlock* predecessor = predecessors_[i];
266     DCHECK(predecessor->end()->IsGoto());
267     HSimulate* simulate = HSimulate::cast(predecessor->end()->previous());
268     DCHECK(i != 0 ||
269            (predecessor->last_environment()->closure().is_null() ||
270             predecessor->last_environment()->closure()->shared()
271               ->VerifyBailoutId(ast_id)));
272     simulate->set_ast_id(ast_id);
273     predecessor->last_environment()->set_ast_id(ast_id);
274   }
275 }
276
277
278 bool HBasicBlock::Dominates(HBasicBlock* other) const {
279   HBasicBlock* current = other->dominator();
280   while (current != NULL) {
281     if (current == this) return true;
282     current = current->dominator();
283   }
284   return false;
285 }
286
287
288 bool HBasicBlock::EqualToOrDominates(HBasicBlock* other) const {
289   if (this == other) return true;
290   return Dominates(other);
291 }
292
293
294 int HBasicBlock::LoopNestingDepth() const {
295   const HBasicBlock* current = this;
296   int result  = (current->IsLoopHeader()) ? 1 : 0;
297   while (current->parent_loop_header() != NULL) {
298     current = current->parent_loop_header();
299     result++;
300   }
301   return result;
302 }
303
304
305 void HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) {
306   DCHECK(IsLoopHeader());
307
308   SetJoinId(stmt->EntryId());
309   if (predecessors()->length() == 1) {
310     // This is a degenerated loop.
311     DetachLoopInformation();
312     return;
313   }
314
315   // Only the first entry into the loop is from outside the loop. All other
316   // entries must be back edges.
317   for (int i = 1; i < predecessors()->length(); ++i) {
318     loop_information()->RegisterBackEdge(predecessors()->at(i));
319   }
320 }
321
322
323 void HBasicBlock::MarkSuccEdgeUnreachable(int succ) {
324   DCHECK(IsFinished());
325   HBasicBlock* succ_block = end()->SuccessorAt(succ);
326
327   DCHECK(succ_block->predecessors()->length() == 1);
328   succ_block->MarkUnreachable();
329 }
330
331
332 void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
333   if (HasPredecessor()) {
334     // Only loop header blocks can have a predecessor added after
335     // instructions have been added to the block (they have phis for all
336     // values in the environment, these phis may be eliminated later).
337     DCHECK(IsLoopHeader() || first_ == NULL);
338     HEnvironment* incoming_env = pred->last_environment();
339     if (IsLoopHeader()) {
340       DCHECK_EQ(phis()->length(), incoming_env->length());
341       for (int i = 0; i < phis_.length(); ++i) {
342         phis_[i]->AddInput(incoming_env->values()->at(i));
343       }
344     } else {
345       last_environment()->AddIncomingEdge(this, pred->last_environment());
346     }
347   } else if (!HasEnvironment() && !IsFinished()) {
348     DCHECK(!IsLoopHeader());
349     SetInitialEnvironment(pred->last_environment()->Copy());
350   }
351
352   predecessors_.Add(pred, zone());
353 }
354
355
356 void HBasicBlock::AddDominatedBlock(HBasicBlock* block) {
357   DCHECK(!dominated_blocks_.Contains(block));
358   // Keep the list of dominated blocks sorted such that if there is two
359   // succeeding block in this list, the predecessor is before the successor.
360   int index = 0;
361   while (index < dominated_blocks_.length() &&
362          dominated_blocks_[index]->block_id() < block->block_id()) {
363     ++index;
364   }
365   dominated_blocks_.InsertAt(index, block, zone());
366 }
367
368
369 void HBasicBlock::AssignCommonDominator(HBasicBlock* other) {
370   if (dominator_ == NULL) {
371     dominator_ = other;
372     other->AddDominatedBlock(this);
373   } else if (other->dominator() != NULL) {
374     HBasicBlock* first = dominator_;
375     HBasicBlock* second = other;
376
377     while (first != second) {
378       if (first->block_id() > second->block_id()) {
379         first = first->dominator();
380       } else {
381         second = second->dominator();
382       }
383       DCHECK(first != NULL && second != NULL);
384     }
385
386     if (dominator_ != first) {
387       DCHECK(dominator_->dominated_blocks_.Contains(this));
388       dominator_->dominated_blocks_.RemoveElement(this);
389       dominator_ = first;
390       first->AddDominatedBlock(this);
391     }
392   }
393 }
394
395
396 void HBasicBlock::AssignLoopSuccessorDominators() {
397   // Mark blocks that dominate all subsequent reachable blocks inside their
398   // loop. Exploit the fact that blocks are sorted in reverse post order. When
399   // the loop is visited in increasing block id order, if the number of
400   // non-loop-exiting successor edges at the dominator_candidate block doesn't
401   // exceed the number of previously encountered predecessor edges, there is no
402   // path from the loop header to any block with higher id that doesn't go
403   // through the dominator_candidate block. In this case, the
404   // dominator_candidate block is guaranteed to dominate all blocks reachable
405   // from it with higher ids.
406   HBasicBlock* last = loop_information()->GetLastBackEdge();
407   int outstanding_successors = 1;  // one edge from the pre-header
408   // Header always dominates everything.
409   MarkAsLoopSuccessorDominator();
410   for (int j = block_id(); j <= last->block_id(); ++j) {
411     HBasicBlock* dominator_candidate = graph_->blocks()->at(j);
412     for (HPredecessorIterator it(dominator_candidate); !it.Done();
413          it.Advance()) {
414       HBasicBlock* predecessor = it.Current();
415       // Don't count back edges.
416       if (predecessor->block_id() < dominator_candidate->block_id()) {
417         outstanding_successors--;
418       }
419     }
420
421     // If more successors than predecessors have been seen in the loop up to
422     // now, it's not possible to guarantee that the current block dominates
423     // all of the blocks with higher IDs. In this case, assume conservatively
424     // that those paths through loop that don't go through the current block
425     // contain all of the loop's dependencies. Also be careful to record
426     // dominator information about the current loop that's being processed,
427     // and not nested loops, which will be processed when
428     // AssignLoopSuccessorDominators gets called on their header.
429     DCHECK(outstanding_successors >= 0);
430     HBasicBlock* parent_loop_header = dominator_candidate->parent_loop_header();
431     if (outstanding_successors == 0 &&
432         (parent_loop_header == this && !dominator_candidate->IsLoopHeader())) {
433       dominator_candidate->MarkAsLoopSuccessorDominator();
434     }
435     HControlInstruction* end = dominator_candidate->end();
436     for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
437       HBasicBlock* successor = it.Current();
438       // Only count successors that remain inside the loop and don't loop back
439       // to a loop header.
440       if (successor->block_id() > dominator_candidate->block_id() &&
441           successor->block_id() <= last->block_id()) {
442         // Backwards edges must land on loop headers.
443         DCHECK(successor->block_id() > dominator_candidate->block_id() ||
444                successor->IsLoopHeader());
445         outstanding_successors++;
446       }
447     }
448   }
449 }
450
451
452 int HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const {
453   for (int i = 0; i < predecessors_.length(); ++i) {
454     if (predecessors_[i] == predecessor) return i;
455   }
456   UNREACHABLE();
457   return -1;
458 }
459
460
461 #ifdef DEBUG
462 void HBasicBlock::Verify() {
463   // Check that every block is finished.
464   DCHECK(IsFinished());
465   DCHECK(block_id() >= 0);
466
467   // Check that the incoming edges are in edge split form.
468   if (predecessors_.length() > 1) {
469     for (int i = 0; i < predecessors_.length(); ++i) {
470       DCHECK(predecessors_[i]->end()->SecondSuccessor() == NULL);
471     }
472   }
473 }
474 #endif
475
476
477 void HLoopInformation::RegisterBackEdge(HBasicBlock* block) {
478   this->back_edges_.Add(block, block->zone());
479   AddBlock(block);
480 }
481
482
483 HBasicBlock* HLoopInformation::GetLastBackEdge() const {
484   int max_id = -1;
485   HBasicBlock* result = NULL;
486   for (int i = 0; i < back_edges_.length(); ++i) {
487     HBasicBlock* cur = back_edges_[i];
488     if (cur->block_id() > max_id) {
489       max_id = cur->block_id();
490       result = cur;
491     }
492   }
493   return result;
494 }
495
496
497 void HLoopInformation::AddBlock(HBasicBlock* block) {
498   if (block == loop_header()) return;
499   if (block->parent_loop_header() == loop_header()) return;
500   if (block->parent_loop_header() != NULL) {
501     AddBlock(block->parent_loop_header());
502   } else {
503     block->set_parent_loop_header(loop_header());
504     blocks_.Add(block, block->zone());
505     for (int i = 0; i < block->predecessors()->length(); ++i) {
506       AddBlock(block->predecessors()->at(i));
507     }
508   }
509 }
510
511
512 #ifdef DEBUG
513
514 // Checks reachability of the blocks in this graph and stores a bit in
515 // the BitVector "reachable()" for every block that can be reached
516 // from the start block of the graph. If "dont_visit" is non-null, the given
517 // block is treated as if it would not be part of the graph. "visited_count()"
518 // returns the number of reachable blocks.
519 class ReachabilityAnalyzer BASE_EMBEDDED {
520  public:
521   ReachabilityAnalyzer(HBasicBlock* entry_block,
522                        int block_count,
523                        HBasicBlock* dont_visit)
524       : visited_count_(0),
525         stack_(16, entry_block->zone()),
526         reachable_(block_count, entry_block->zone()),
527         dont_visit_(dont_visit) {
528     PushBlock(entry_block);
529     Analyze();
530   }
531
532   int visited_count() const { return visited_count_; }
533   const BitVector* reachable() const { return &reachable_; }
534
535  private:
536   void PushBlock(HBasicBlock* block) {
537     if (block != NULL && block != dont_visit_ &&
538         !reachable_.Contains(block->block_id())) {
539       reachable_.Add(block->block_id());
540       stack_.Add(block, block->zone());
541       visited_count_++;
542     }
543   }
544
545   void Analyze() {
546     while (!stack_.is_empty()) {
547       HControlInstruction* end = stack_.RemoveLast()->end();
548       for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
549         PushBlock(it.Current());
550       }
551     }
552   }
553
554   int visited_count_;
555   ZoneList<HBasicBlock*> stack_;
556   BitVector reachable_;
557   HBasicBlock* dont_visit_;
558 };
559
560
561 void HGraph::Verify(bool do_full_verify) const {
562   Heap::RelocationLock relocation_lock(isolate()->heap());
563   AllowHandleDereference allow_deref;
564   AllowDeferredHandleDereference allow_deferred_deref;
565   for (int i = 0; i < blocks_.length(); i++) {
566     HBasicBlock* block = blocks_.at(i);
567
568     block->Verify();
569
570     // Check that every block contains at least one node and that only the last
571     // node is a control instruction.
572     HInstruction* current = block->first();
573     DCHECK(current != NULL && current->IsBlockEntry());
574     while (current != NULL) {
575       DCHECK((current->next() == NULL) == current->IsControlInstruction());
576       DCHECK(current->block() == block);
577       current->Verify();
578       current = current->next();
579     }
580
581     // Check that successors are correctly set.
582     HBasicBlock* first = block->end()->FirstSuccessor();
583     HBasicBlock* second = block->end()->SecondSuccessor();
584     DCHECK(second == NULL || first != NULL);
585
586     // Check that the predecessor array is correct.
587     if (first != NULL) {
588       DCHECK(first->predecessors()->Contains(block));
589       if (second != NULL) {
590         DCHECK(second->predecessors()->Contains(block));
591       }
592     }
593
594     // Check that phis have correct arguments.
595     for (int j = 0; j < block->phis()->length(); j++) {
596       HPhi* phi = block->phis()->at(j);
597       phi->Verify();
598     }
599
600     // Check that all join blocks have predecessors that end with an
601     // unconditional goto and agree on their environment node id.
602     if (block->predecessors()->length() >= 2) {
603       BailoutId id =
604           block->predecessors()->first()->last_environment()->ast_id();
605       for (int k = 0; k < block->predecessors()->length(); k++) {
606         HBasicBlock* predecessor = block->predecessors()->at(k);
607         DCHECK(predecessor->end()->IsGoto() ||
608                predecessor->end()->IsDeoptimize());
609         DCHECK(predecessor->last_environment()->ast_id() == id);
610       }
611     }
612   }
613
614   // Check special property of first block to have no predecessors.
615   DCHECK(blocks_.at(0)->predecessors()->is_empty());
616
617   if (do_full_verify) {
618     // Check that the graph is fully connected.
619     ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL);
620     DCHECK(analyzer.visited_count() == blocks_.length());
621
622     // Check that entry block dominator is NULL.
623     DCHECK(entry_block_->dominator() == NULL);
624
625     // Check dominators.
626     for (int i = 0; i < blocks_.length(); ++i) {
627       HBasicBlock* block = blocks_.at(i);
628       if (block->dominator() == NULL) {
629         // Only start block may have no dominator assigned to.
630         DCHECK(i == 0);
631       } else {
632         // Assert that block is unreachable if dominator must not be visited.
633         ReachabilityAnalyzer dominator_analyzer(entry_block_,
634                                                 blocks_.length(),
635                                                 block->dominator());
636         DCHECK(!dominator_analyzer.reachable()->Contains(block->block_id()));
637       }
638     }
639   }
640 }
641
642 #endif
643
644
645 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
646                                int32_t value) {
647   if (!pointer->is_set()) {
648     // Can't pass GetInvalidContext() to HConstant::New, because that will
649     // recursively call GetConstant
650     HConstant* constant = HConstant::New(isolate(), zone(), NULL, value);
651     constant->InsertAfter(entry_block()->first());
652     pointer->set(constant);
653     return constant;
654   }
655   return ReinsertConstantIfNecessary(pointer->get());
656 }
657
658
659 HConstant* HGraph::ReinsertConstantIfNecessary(HConstant* constant) {
660   if (!constant->IsLinked()) {
661     // The constant was removed from the graph. Reinsert.
662     constant->ClearFlag(HValue::kIsDead);
663     constant->InsertAfter(entry_block()->first());
664   }
665   return constant;
666 }
667
668
669 HConstant* HGraph::GetConstant0() {
670   return GetConstant(&constant_0_, 0);
671 }
672
673
674 HConstant* HGraph::GetConstant1() {
675   return GetConstant(&constant_1_, 1);
676 }
677
678
679 HConstant* HGraph::GetConstantMinus1() {
680   return GetConstant(&constant_minus1_, -1);
681 }
682
683
684 HConstant* HGraph::GetConstantBool(bool value) {
685   return value ? GetConstantTrue() : GetConstantFalse();
686 }
687
688
689 #define DEFINE_GET_CONSTANT(Name, name, type, htype, boolean_value)            \
690 HConstant* HGraph::GetConstant##Name() {                                       \
691   if (!constant_##name##_.is_set()) {                                          \
692     HConstant* constant = new(zone()) HConstant(                               \
693         Unique<Object>::CreateImmovable(isolate()->factory()->name##_value()), \
694         Unique<Map>::CreateImmovable(isolate()->factory()->type##_map()),      \
695         false,                                                                 \
696         Representation::Tagged(),                                              \
697         htype,                                                                 \
698         true,                                                                  \
699         boolean_value,                                                         \
700         false,                                                                 \
701         ODDBALL_TYPE);                                                         \
702     constant->InsertAfter(entry_block()->first());                             \
703     constant_##name##_.set(constant);                                          \
704   }                                                                            \
705   return ReinsertConstantIfNecessary(constant_##name##_.get());                \
706 }
707
708
709 DEFINE_GET_CONSTANT(Undefined, undefined, undefined, HType::Undefined(), false)
710 DEFINE_GET_CONSTANT(True, true, boolean, HType::Boolean(), true)
711 DEFINE_GET_CONSTANT(False, false, boolean, HType::Boolean(), false)
712 DEFINE_GET_CONSTANT(Hole, the_hole, the_hole, HType::None(), false)
713 DEFINE_GET_CONSTANT(Null, null, null, HType::Null(), false)
714
715
716 #undef DEFINE_GET_CONSTANT
717
718 #define DEFINE_IS_CONSTANT(Name, name)                                         \
719 bool HGraph::IsConstant##Name(HConstant* constant) {                           \
720   return constant_##name##_.is_set() && constant == constant_##name##_.get();  \
721 }
722 DEFINE_IS_CONSTANT(Undefined, undefined)
723 DEFINE_IS_CONSTANT(0, 0)
724 DEFINE_IS_CONSTANT(1, 1)
725 DEFINE_IS_CONSTANT(Minus1, minus1)
726 DEFINE_IS_CONSTANT(True, true)
727 DEFINE_IS_CONSTANT(False, false)
728 DEFINE_IS_CONSTANT(Hole, the_hole)
729 DEFINE_IS_CONSTANT(Null, null)
730
731 #undef DEFINE_IS_CONSTANT
732
733
734 HConstant* HGraph::GetInvalidContext() {
735   return GetConstant(&constant_invalid_context_, 0xFFFFC0C7);
736 }
737
738
739 bool HGraph::IsStandardConstant(HConstant* constant) {
740   if (IsConstantUndefined(constant)) return true;
741   if (IsConstant0(constant)) return true;
742   if (IsConstant1(constant)) return true;
743   if (IsConstantMinus1(constant)) return true;
744   if (IsConstantTrue(constant)) return true;
745   if (IsConstantFalse(constant)) return true;
746   if (IsConstantHole(constant)) return true;
747   if (IsConstantNull(constant)) return true;
748   return false;
749 }
750
751
752 HGraphBuilder::IfBuilder::IfBuilder() : builder_(NULL), needs_compare_(true) {}
753
754
755 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder)
756     : needs_compare_(true) {
757   Initialize(builder);
758 }
759
760
761 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder,
762                                     HIfContinuation* continuation)
763     : needs_compare_(false), first_true_block_(NULL), first_false_block_(NULL) {
764   InitializeDontCreateBlocks(builder);
765   continuation->Continue(&first_true_block_, &first_false_block_);
766 }
767
768
769 void HGraphBuilder::IfBuilder::InitializeDontCreateBlocks(
770     HGraphBuilder* builder) {
771   builder_ = builder;
772   finished_ = false;
773   did_then_ = false;
774   did_else_ = false;
775   did_else_if_ = false;
776   did_and_ = false;
777   did_or_ = false;
778   captured_ = false;
779   pending_merge_block_ = false;
780   split_edge_merge_block_ = NULL;
781   merge_at_join_blocks_ = NULL;
782   normal_merge_at_join_block_count_ = 0;
783   deopt_merge_at_join_block_count_ = 0;
784 }
785
786
787 void HGraphBuilder::IfBuilder::Initialize(HGraphBuilder* builder) {
788   InitializeDontCreateBlocks(builder);
789   HEnvironment* env = builder->environment();
790   first_true_block_ = builder->CreateBasicBlock(env->Copy());
791   first_false_block_ = builder->CreateBasicBlock(env->Copy());
792 }
793
794
795 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare(
796     HControlInstruction* compare) {
797   DCHECK(did_then_ == did_else_);
798   if (did_else_) {
799     // Handle if-then-elseif
800     did_else_if_ = true;
801     did_else_ = false;
802     did_then_ = false;
803     did_and_ = false;
804     did_or_ = false;
805     pending_merge_block_ = false;
806     split_edge_merge_block_ = NULL;
807     HEnvironment* env = builder()->environment();
808     first_true_block_ = builder()->CreateBasicBlock(env->Copy());
809     first_false_block_ = builder()->CreateBasicBlock(env->Copy());
810   }
811   if (split_edge_merge_block_ != NULL) {
812     HEnvironment* env = first_false_block_->last_environment();
813     HBasicBlock* split_edge = builder()->CreateBasicBlock(env->Copy());
814     if (did_or_) {
815       compare->SetSuccessorAt(0, split_edge);
816       compare->SetSuccessorAt(1, first_false_block_);
817     } else {
818       compare->SetSuccessorAt(0, first_true_block_);
819       compare->SetSuccessorAt(1, split_edge);
820     }
821     builder()->GotoNoSimulate(split_edge, split_edge_merge_block_);
822   } else {
823     compare->SetSuccessorAt(0, first_true_block_);
824     compare->SetSuccessorAt(1, first_false_block_);
825   }
826   builder()->FinishCurrentBlock(compare);
827   needs_compare_ = false;
828   return compare;
829 }
830
831
832 void HGraphBuilder::IfBuilder::Or() {
833   DCHECK(!needs_compare_);
834   DCHECK(!did_and_);
835   did_or_ = true;
836   HEnvironment* env = first_false_block_->last_environment();
837   if (split_edge_merge_block_ == NULL) {
838     split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
839     builder()->GotoNoSimulate(first_true_block_, split_edge_merge_block_);
840     first_true_block_ = split_edge_merge_block_;
841   }
842   builder()->set_current_block(first_false_block_);
843   first_false_block_ = builder()->CreateBasicBlock(env->Copy());
844 }
845
846
847 void HGraphBuilder::IfBuilder::And() {
848   DCHECK(!needs_compare_);
849   DCHECK(!did_or_);
850   did_and_ = true;
851   HEnvironment* env = first_false_block_->last_environment();
852   if (split_edge_merge_block_ == NULL) {
853     split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
854     builder()->GotoNoSimulate(first_false_block_, split_edge_merge_block_);
855     first_false_block_ = split_edge_merge_block_;
856   }
857   builder()->set_current_block(first_true_block_);
858   first_true_block_ = builder()->CreateBasicBlock(env->Copy());
859 }
860
861
862 void HGraphBuilder::IfBuilder::CaptureContinuation(
863     HIfContinuation* continuation) {
864   DCHECK(!did_else_if_);
865   DCHECK(!finished_);
866   DCHECK(!captured_);
867
868   HBasicBlock* true_block = NULL;
869   HBasicBlock* false_block = NULL;
870   Finish(&true_block, &false_block);
871   DCHECK(true_block != NULL);
872   DCHECK(false_block != NULL);
873   continuation->Capture(true_block, false_block);
874   captured_ = true;
875   builder()->set_current_block(NULL);
876   End();
877 }
878
879
880 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) {
881   DCHECK(!did_else_if_);
882   DCHECK(!finished_);
883   DCHECK(!captured_);
884   HBasicBlock* true_block = NULL;
885   HBasicBlock* false_block = NULL;
886   Finish(&true_block, &false_block);
887   merge_at_join_blocks_ = NULL;
888   if (true_block != NULL && !true_block->IsFinished()) {
889     DCHECK(continuation->IsTrueReachable());
890     builder()->GotoNoSimulate(true_block, continuation->true_branch());
891   }
892   if (false_block != NULL && !false_block->IsFinished()) {
893     DCHECK(continuation->IsFalseReachable());
894     builder()->GotoNoSimulate(false_block, continuation->false_branch());
895   }
896   captured_ = true;
897   End();
898 }
899
900
901 void HGraphBuilder::IfBuilder::Then() {
902   DCHECK(!captured_);
903   DCHECK(!finished_);
904   did_then_ = true;
905   if (needs_compare_) {
906     // Handle if's without any expressions, they jump directly to the "else"
907     // branch. However, we must pretend that the "then" branch is reachable,
908     // so that the graph builder visits it and sees any live range extending
909     // constructs within it.
910     HConstant* constant_false = builder()->graph()->GetConstantFalse();
911     ToBooleanStub::Types boolean_type = ToBooleanStub::Types();
912     boolean_type.Add(ToBooleanStub::BOOLEAN);
913     HBranch* branch = builder()->New<HBranch>(
914         constant_false, boolean_type, first_true_block_, first_false_block_);
915     builder()->FinishCurrentBlock(branch);
916   }
917   builder()->set_current_block(first_true_block_);
918   pending_merge_block_ = true;
919 }
920
921
922 void HGraphBuilder::IfBuilder::Else() {
923   DCHECK(did_then_);
924   DCHECK(!captured_);
925   DCHECK(!finished_);
926   AddMergeAtJoinBlock(false);
927   builder()->set_current_block(first_false_block_);
928   pending_merge_block_ = true;
929   did_else_ = true;
930 }
931
932
933 void HGraphBuilder::IfBuilder::Deopt(Deoptimizer::DeoptReason reason) {
934   DCHECK(did_then_);
935   builder()->Add<HDeoptimize>(reason, Deoptimizer::EAGER);
936   AddMergeAtJoinBlock(true);
937 }
938
939
940 void HGraphBuilder::IfBuilder::Return(HValue* value) {
941   HValue* parameter_count = builder()->graph()->GetConstantMinus1();
942   builder()->FinishExitCurrentBlock(
943       builder()->New<HReturn>(value, parameter_count));
944   AddMergeAtJoinBlock(false);
945 }
946
947
948 void HGraphBuilder::IfBuilder::AddMergeAtJoinBlock(bool deopt) {
949   if (!pending_merge_block_) return;
950   HBasicBlock* block = builder()->current_block();
951   DCHECK(block == NULL || !block->IsFinished());
952   MergeAtJoinBlock* record = new (builder()->zone())
953       MergeAtJoinBlock(block, deopt, merge_at_join_blocks_);
954   merge_at_join_blocks_ = record;
955   if (block != NULL) {
956     DCHECK(block->end() == NULL);
957     if (deopt) {
958       normal_merge_at_join_block_count_++;
959     } else {
960       deopt_merge_at_join_block_count_++;
961     }
962   }
963   builder()->set_current_block(NULL);
964   pending_merge_block_ = false;
965 }
966
967
968 void HGraphBuilder::IfBuilder::Finish() {
969   DCHECK(!finished_);
970   if (!did_then_) {
971     Then();
972   }
973   AddMergeAtJoinBlock(false);
974   if (!did_else_) {
975     Else();
976     AddMergeAtJoinBlock(false);
977   }
978   finished_ = true;
979 }
980
981
982 void HGraphBuilder::IfBuilder::Finish(HBasicBlock** then_continuation,
983                                       HBasicBlock** else_continuation) {
984   Finish();
985
986   MergeAtJoinBlock* else_record = merge_at_join_blocks_;
987   if (else_continuation != NULL) {
988     *else_continuation = else_record->block_;
989   }
990   MergeAtJoinBlock* then_record = else_record->next_;
991   if (then_continuation != NULL) {
992     *then_continuation = then_record->block_;
993   }
994   DCHECK(then_record->next_ == NULL);
995 }
996
997
998 void HGraphBuilder::IfBuilder::EndUnreachable() {
999   if (captured_) return;
1000   Finish();
1001   builder()->set_current_block(nullptr);
1002 }
1003
1004
1005 void HGraphBuilder::IfBuilder::End() {
1006   if (captured_) return;
1007   Finish();
1008
1009   int total_merged_blocks = normal_merge_at_join_block_count_ +
1010     deopt_merge_at_join_block_count_;
1011   DCHECK(total_merged_blocks >= 1);
1012   HBasicBlock* merge_block =
1013       total_merged_blocks == 1 ? NULL : builder()->graph()->CreateBasicBlock();
1014
1015   // Merge non-deopt blocks first to ensure environment has right size for
1016   // padding.
1017   MergeAtJoinBlock* current = merge_at_join_blocks_;
1018   while (current != NULL) {
1019     if (!current->deopt_ && current->block_ != NULL) {
1020       // If there is only one block that makes it through to the end of the
1021       // if, then just set it as the current block and continue rather then
1022       // creating an unnecessary merge block.
1023       if (total_merged_blocks == 1) {
1024         builder()->set_current_block(current->block_);
1025         return;
1026       }
1027       builder()->GotoNoSimulate(current->block_, merge_block);
1028     }
1029     current = current->next_;
1030   }
1031
1032   // Merge deopt blocks, padding when necessary.
1033   current = merge_at_join_blocks_;
1034   while (current != NULL) {
1035     if (current->deopt_ && current->block_ != NULL) {
1036       current->block_->FinishExit(
1037           HAbnormalExit::New(builder()->isolate(), builder()->zone(), NULL),
1038           SourcePosition::Unknown());
1039     }
1040     current = current->next_;
1041   }
1042   builder()->set_current_block(merge_block);
1043 }
1044
1045
1046 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder) {
1047   Initialize(builder, NULL, kWhileTrue, NULL);
1048 }
1049
1050
1051 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
1052                                         LoopBuilder::Direction direction) {
1053   Initialize(builder, context, direction, builder->graph()->GetConstant1());
1054 }
1055
1056
1057 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
1058                                         LoopBuilder::Direction direction,
1059                                         HValue* increment_amount) {
1060   Initialize(builder, context, direction, increment_amount);
1061   increment_amount_ = increment_amount;
1062 }
1063
1064
1065 void HGraphBuilder::LoopBuilder::Initialize(HGraphBuilder* builder,
1066                                             HValue* context,
1067                                             Direction direction,
1068                                             HValue* increment_amount) {
1069   builder_ = builder;
1070   context_ = context;
1071   direction_ = direction;
1072   increment_amount_ = increment_amount;
1073
1074   finished_ = false;
1075   header_block_ = builder->CreateLoopHeaderBlock();
1076   body_block_ = NULL;
1077   exit_block_ = NULL;
1078   exit_trampoline_block_ = NULL;
1079 }
1080
1081
1082 HValue* HGraphBuilder::LoopBuilder::BeginBody(
1083     HValue* initial,
1084     HValue* terminating,
1085     Token::Value token) {
1086   DCHECK(direction_ != kWhileTrue);
1087   HEnvironment* env = builder_->environment();
1088   phi_ = header_block_->AddNewPhi(env->values()->length());
1089   phi_->AddInput(initial);
1090   env->Push(initial);
1091   builder_->GotoNoSimulate(header_block_);
1092
1093   HEnvironment* body_env = env->Copy();
1094   HEnvironment* exit_env = env->Copy();
1095   // Remove the phi from the expression stack
1096   body_env->Pop();
1097   exit_env->Pop();
1098   body_block_ = builder_->CreateBasicBlock(body_env);
1099   exit_block_ = builder_->CreateBasicBlock(exit_env);
1100
1101   builder_->set_current_block(header_block_);
1102   env->Pop();
1103   builder_->FinishCurrentBlock(builder_->New<HCompareNumericAndBranch>(
1104           phi_, terminating, token, body_block_, exit_block_));
1105
1106   builder_->set_current_block(body_block_);
1107   if (direction_ == kPreIncrement || direction_ == kPreDecrement) {
1108     Isolate* isolate = builder_->isolate();
1109     HValue* one = builder_->graph()->GetConstant1();
1110     if (direction_ == kPreIncrement) {
1111       increment_ = HAdd::New(isolate, zone(), context_, phi_, one);
1112     } else {
1113       increment_ = HSub::New(isolate, zone(), context_, phi_, one);
1114     }
1115     increment_->ClearFlag(HValue::kCanOverflow);
1116     builder_->AddInstruction(increment_);
1117     return increment_;
1118   } else {
1119     return phi_;
1120   }
1121 }
1122
1123
1124 void HGraphBuilder::LoopBuilder::BeginBody(int drop_count) {
1125   DCHECK(direction_ == kWhileTrue);
1126   HEnvironment* env = builder_->environment();
1127   builder_->GotoNoSimulate(header_block_);
1128   builder_->set_current_block(header_block_);
1129   env->Drop(drop_count);
1130 }
1131
1132
1133 void HGraphBuilder::LoopBuilder::Break() {
1134   if (exit_trampoline_block_ == NULL) {
1135     // Its the first time we saw a break.
1136     if (direction_ == kWhileTrue) {
1137       HEnvironment* env = builder_->environment()->Copy();
1138       exit_trampoline_block_ = builder_->CreateBasicBlock(env);
1139     } else {
1140       HEnvironment* env = exit_block_->last_environment()->Copy();
1141       exit_trampoline_block_ = builder_->CreateBasicBlock(env);
1142       builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_);
1143     }
1144   }
1145
1146   builder_->GotoNoSimulate(exit_trampoline_block_);
1147   builder_->set_current_block(NULL);
1148 }
1149
1150
1151 void HGraphBuilder::LoopBuilder::EndBody() {
1152   DCHECK(!finished_);
1153
1154   if (direction_ == kPostIncrement || direction_ == kPostDecrement) {
1155     Isolate* isolate = builder_->isolate();
1156     if (direction_ == kPostIncrement) {
1157       increment_ =
1158           HAdd::New(isolate, zone(), context_, phi_, increment_amount_);
1159     } else {
1160       increment_ =
1161           HSub::New(isolate, zone(), context_, phi_, increment_amount_);
1162     }
1163     increment_->ClearFlag(HValue::kCanOverflow);
1164     builder_->AddInstruction(increment_);
1165   }
1166
1167   if (direction_ != kWhileTrue) {
1168     // Push the new increment value on the expression stack to merge into
1169     // the phi.
1170     builder_->environment()->Push(increment_);
1171   }
1172   HBasicBlock* last_block = builder_->current_block();
1173   builder_->GotoNoSimulate(last_block, header_block_);
1174   header_block_->loop_information()->RegisterBackEdge(last_block);
1175
1176   if (exit_trampoline_block_ != NULL) {
1177     builder_->set_current_block(exit_trampoline_block_);
1178   } else {
1179     builder_->set_current_block(exit_block_);
1180   }
1181   finished_ = true;
1182 }
1183
1184
1185 HGraph* HGraphBuilder::CreateGraph() {
1186   graph_ = new(zone()) HGraph(info_);
1187   if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_);
1188   CompilationPhase phase("H_Block building", info_);
1189   set_current_block(graph()->entry_block());
1190   if (!BuildGraph()) return NULL;
1191   graph()->FinalizeUniqueness();
1192   return graph_;
1193 }
1194
1195
1196 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
1197   DCHECK(current_block() != NULL);
1198   DCHECK(!FLAG_hydrogen_track_positions ||
1199          !position_.IsUnknown() ||
1200          !info_->IsOptimizing());
1201   current_block()->AddInstruction(instr, source_position());
1202   if (graph()->IsInsideNoSideEffectsScope()) {
1203     instr->SetFlag(HValue::kHasNoObservableSideEffects);
1204   }
1205   return instr;
1206 }
1207
1208
1209 void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) {
1210   DCHECK(!FLAG_hydrogen_track_positions ||
1211          !info_->IsOptimizing() ||
1212          !position_.IsUnknown());
1213   current_block()->Finish(last, source_position());
1214   if (last->IsReturn() || last->IsAbnormalExit()) {
1215     set_current_block(NULL);
1216   }
1217 }
1218
1219
1220 void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) {
1221   DCHECK(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() ||
1222          !position_.IsUnknown());
1223   current_block()->FinishExit(instruction, source_position());
1224   if (instruction->IsReturn() || instruction->IsAbnormalExit()) {
1225     set_current_block(NULL);
1226   }
1227 }
1228
1229
1230 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) {
1231   if (FLAG_native_code_counters && counter->Enabled()) {
1232     HValue* reference = Add<HConstant>(ExternalReference(counter));
1233     HValue* old_value =
1234         Add<HLoadNamedField>(reference, nullptr, HObjectAccess::ForCounter());
1235     HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1());
1236     new_value->ClearFlag(HValue::kCanOverflow);  // Ignore counter overflow
1237     Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(),
1238                           new_value, STORE_TO_INITIALIZED_ENTRY);
1239   }
1240 }
1241
1242
1243 void HGraphBuilder::AddSimulate(BailoutId id,
1244                                 RemovableSimulate removable) {
1245   DCHECK(current_block() != NULL);
1246   DCHECK(!graph()->IsInsideNoSideEffectsScope());
1247   current_block()->AddNewSimulate(id, source_position(), removable);
1248 }
1249
1250
1251 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
1252   HBasicBlock* b = graph()->CreateBasicBlock();
1253   b->SetInitialEnvironment(env);
1254   return b;
1255 }
1256
1257
1258 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
1259   HBasicBlock* header = graph()->CreateBasicBlock();
1260   HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
1261   header->SetInitialEnvironment(entry_env);
1262   header->AttachLoopInformation();
1263   return header;
1264 }
1265
1266
1267 HValue* HGraphBuilder::BuildGetElementsKind(HValue* object) {
1268   HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap());
1269
1270   HValue* bit_field2 =
1271       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2());
1272   return BuildDecodeField<Map::ElementsKindBits>(bit_field2);
1273 }
1274
1275
1276 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) {
1277   if (obj->type().IsHeapObject()) return obj;
1278   return Add<HCheckHeapObject>(obj);
1279 }
1280
1281
1282 void HGraphBuilder::FinishExitWithHardDeoptimization(
1283     Deoptimizer::DeoptReason reason) {
1284   Add<HDeoptimize>(reason, Deoptimizer::EAGER);
1285   FinishExitCurrentBlock(New<HAbnormalExit>());
1286 }
1287
1288
1289 HValue* HGraphBuilder::BuildCheckString(HValue* string) {
1290   if (!string->type().IsString()) {
1291     DCHECK(!string->IsConstant() ||
1292            !HConstant::cast(string)->HasStringValue());
1293     BuildCheckHeapObject(string);
1294     return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
1295   }
1296   return string;
1297 }
1298
1299
1300 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) {
1301   if (object->type().IsJSObject()) return object;
1302   if (function->IsConstant() &&
1303       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
1304     Handle<JSFunction> f = Handle<JSFunction>::cast(
1305         HConstant::cast(function)->handle(isolate()));
1306     SharedFunctionInfo* shared = f->shared();
1307     if (is_strict(shared->language_mode()) || shared->native()) return object;
1308   }
1309   return Add<HWrapReceiver>(object, function);
1310 }
1311
1312
1313 HValue* HGraphBuilder::BuildCheckAndGrowElementsCapacity(
1314     HValue* object, HValue* elements, ElementsKind kind, HValue* length,
1315     HValue* capacity, HValue* key) {
1316   HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
1317   HValue* max_capacity = AddUncasted<HAdd>(capacity, max_gap);
1318   Add<HBoundsCheck>(key, max_capacity);
1319
1320   HValue* new_capacity = BuildNewElementsCapacity(key);
1321   HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind, kind,
1322                                                    length, new_capacity);
1323   return new_elements;
1324 }
1325
1326
1327 HValue* HGraphBuilder::BuildCheckForCapacityGrow(
1328     HValue* object,
1329     HValue* elements,
1330     ElementsKind kind,
1331     HValue* length,
1332     HValue* key,
1333     bool is_js_array,
1334     PropertyAccessType access_type) {
1335   IfBuilder length_checker(this);
1336
1337   Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
1338   length_checker.If<HCompareNumericAndBranch>(key, length, token);
1339
1340   length_checker.Then();
1341
1342   HValue* current_capacity = AddLoadFixedArrayLength(elements);
1343
1344   if (top_info()->IsStub()) {
1345     IfBuilder capacity_checker(this);
1346     capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity,
1347                                                   Token::GTE);
1348     capacity_checker.Then();
1349     HValue* new_elements = BuildCheckAndGrowElementsCapacity(
1350         object, elements, kind, length, current_capacity, key);
1351     environment()->Push(new_elements);
1352     capacity_checker.Else();
1353     environment()->Push(elements);
1354     capacity_checker.End();
1355   } else {
1356     HValue* result = Add<HMaybeGrowElements>(
1357         object, elements, key, current_capacity, is_js_array, kind);
1358     environment()->Push(result);
1359   }
1360
1361   if (is_js_array) {
1362     HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1());
1363     new_length->ClearFlag(HValue::kCanOverflow);
1364
1365     Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind),
1366                           new_length);
1367   }
1368
1369   if (access_type == STORE && kind == FAST_SMI_ELEMENTS) {
1370     HValue* checked_elements = environment()->Top();
1371
1372     // Write zero to ensure that the new element is initialized with some smi.
1373     Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), kind);
1374   }
1375
1376   length_checker.Else();
1377   Add<HBoundsCheck>(key, length);
1378
1379   environment()->Push(elements);
1380   length_checker.End();
1381
1382   return environment()->Pop();
1383 }
1384
1385
1386 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
1387                                                 HValue* elements,
1388                                                 ElementsKind kind,
1389                                                 HValue* length) {
1390   Factory* factory = isolate()->factory();
1391
1392   IfBuilder cow_checker(this);
1393
1394   cow_checker.If<HCompareMap>(elements, factory->fixed_cow_array_map());
1395   cow_checker.Then();
1396
1397   HValue* capacity = AddLoadFixedArrayLength(elements);
1398
1399   HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind,
1400                                                    kind, length, capacity);
1401
1402   environment()->Push(new_elements);
1403
1404   cow_checker.Else();
1405
1406   environment()->Push(elements);
1407
1408   cow_checker.End();
1409
1410   return environment()->Pop();
1411 }
1412
1413
1414 void HGraphBuilder::BuildTransitionElementsKind(HValue* object,
1415                                                 HValue* map,
1416                                                 ElementsKind from_kind,
1417                                                 ElementsKind to_kind,
1418                                                 bool is_jsarray) {
1419   DCHECK(!IsFastHoleyElementsKind(from_kind) ||
1420          IsFastHoleyElementsKind(to_kind));
1421
1422   if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) {
1423     Add<HTrapAllocationMemento>(object);
1424   }
1425
1426   if (!IsSimpleMapChangeTransition(from_kind, to_kind)) {
1427     HInstruction* elements = AddLoadElements(object);
1428
1429     HInstruction* empty_fixed_array = Add<HConstant>(
1430         isolate()->factory()->empty_fixed_array());
1431
1432     IfBuilder if_builder(this);
1433
1434     if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array);
1435
1436     if_builder.Then();
1437
1438     HInstruction* elements_length = AddLoadFixedArrayLength(elements);
1439
1440     HInstruction* array_length =
1441         is_jsarray
1442             ? Add<HLoadNamedField>(object, nullptr,
1443                                    HObjectAccess::ForArrayLength(from_kind))
1444             : elements_length;
1445
1446     BuildGrowElementsCapacity(object, elements, from_kind, to_kind,
1447                               array_length, elements_length);
1448
1449     if_builder.End();
1450   }
1451
1452   Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map);
1453 }
1454
1455
1456 void HGraphBuilder::BuildJSObjectCheck(HValue* receiver,
1457                                        int bit_field_mask) {
1458   // Check that the object isn't a smi.
1459   Add<HCheckHeapObject>(receiver);
1460
1461   // Get the map of the receiver.
1462   HValue* map =
1463       Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
1464
1465   // Check the instance type and if an access check is needed, this can be
1466   // done with a single load, since both bytes are adjacent in the map.
1467   HObjectAccess access(HObjectAccess::ForMapInstanceTypeAndBitField());
1468   HValue* instance_type_and_bit_field =
1469       Add<HLoadNamedField>(map, nullptr, access);
1470
1471   HValue* mask = Add<HConstant>(0x00FF | (bit_field_mask << 8));
1472   HValue* and_result = AddUncasted<HBitwise>(Token::BIT_AND,
1473                                              instance_type_and_bit_field,
1474                                              mask);
1475   HValue* sub_result = AddUncasted<HSub>(and_result,
1476                                          Add<HConstant>(JS_OBJECT_TYPE));
1477   Add<HBoundsCheck>(sub_result,
1478                     Add<HConstant>(LAST_JS_OBJECT_TYPE + 1 - JS_OBJECT_TYPE));
1479 }
1480
1481
1482 void HGraphBuilder::BuildKeyedIndexCheck(HValue* key,
1483                                          HIfContinuation* join_continuation) {
1484   // The sometimes unintuitively backward ordering of the ifs below is
1485   // convoluted, but necessary.  All of the paths must guarantee that the
1486   // if-true of the continuation returns a smi element index and the if-false of
1487   // the continuation returns either a symbol or a unique string key. All other
1488   // object types cause a deopt to fall back to the runtime.
1489
1490   IfBuilder key_smi_if(this);
1491   key_smi_if.If<HIsSmiAndBranch>(key);
1492   key_smi_if.Then();
1493   {
1494     Push(key);  // Nothing to do, just continue to true of continuation.
1495   }
1496   key_smi_if.Else();
1497   {
1498     HValue* map = Add<HLoadNamedField>(key, nullptr, HObjectAccess::ForMap());
1499     HValue* instance_type =
1500         Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
1501
1502     // Non-unique string, check for a string with a hash code that is actually
1503     // an index.
1504     STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE);
1505     IfBuilder not_string_or_name_if(this);
1506     not_string_or_name_if.If<HCompareNumericAndBranch>(
1507         instance_type,
1508         Add<HConstant>(LAST_UNIQUE_NAME_TYPE),
1509         Token::GT);
1510
1511     not_string_or_name_if.Then();
1512     {
1513       // Non-smi, non-Name, non-String: Try to convert to smi in case of
1514       // HeapNumber.
1515       // TODO(danno): This could call some variant of ToString
1516       Push(AddUncasted<HForceRepresentation>(key, Representation::Smi()));
1517     }
1518     not_string_or_name_if.Else();
1519     {
1520       // String or Name: check explicitly for Name, they can short-circuit
1521       // directly to unique non-index key path.
1522       IfBuilder not_symbol_if(this);
1523       not_symbol_if.If<HCompareNumericAndBranch>(
1524           instance_type,
1525           Add<HConstant>(SYMBOL_TYPE),
1526           Token::NE);
1527
1528       not_symbol_if.Then();
1529       {
1530         // String: check whether the String is a String of an index. If it is,
1531         // extract the index value from the hash.
1532         HValue* hash = Add<HLoadNamedField>(key, nullptr,
1533                                             HObjectAccess::ForNameHashField());
1534         HValue* not_index_mask = Add<HConstant>(static_cast<int>(
1535             String::kContainsCachedArrayIndexMask));
1536
1537         HValue* not_index_test = AddUncasted<HBitwise>(
1538             Token::BIT_AND, hash, not_index_mask);
1539
1540         IfBuilder string_index_if(this);
1541         string_index_if.If<HCompareNumericAndBranch>(not_index_test,
1542                                                      graph()->GetConstant0(),
1543                                                      Token::EQ);
1544         string_index_if.Then();
1545         {
1546           // String with index in hash: extract string and merge to index path.
1547           Push(BuildDecodeField<String::ArrayIndexValueBits>(hash));
1548         }
1549         string_index_if.Else();
1550         {
1551           // Key is a non-index String, check for uniqueness/internalization.
1552           // If it's not internalized yet, internalize it now.
1553           HValue* not_internalized_bit = AddUncasted<HBitwise>(
1554               Token::BIT_AND,
1555               instance_type,
1556               Add<HConstant>(static_cast<int>(kIsNotInternalizedMask)));
1557
1558           IfBuilder internalized(this);
1559           internalized.If<HCompareNumericAndBranch>(not_internalized_bit,
1560                                                     graph()->GetConstant0(),
1561                                                     Token::EQ);
1562           internalized.Then();
1563           Push(key);
1564
1565           internalized.Else();
1566           Add<HPushArguments>(key);
1567           HValue* intern_key = Add<HCallRuntime>(
1568               isolate()->factory()->empty_string(),
1569               Runtime::FunctionForId(Runtime::kInternalizeString), 1);
1570           Push(intern_key);
1571
1572           internalized.End();
1573           // Key guaranteed to be a unique string
1574         }
1575         string_index_if.JoinContinuation(join_continuation);
1576       }
1577       not_symbol_if.Else();
1578       {
1579         Push(key);  // Key is symbol
1580       }
1581       not_symbol_if.JoinContinuation(join_continuation);
1582     }
1583     not_string_or_name_if.JoinContinuation(join_continuation);
1584   }
1585   key_smi_if.JoinContinuation(join_continuation);
1586 }
1587
1588
1589 void HGraphBuilder::BuildNonGlobalObjectCheck(HValue* receiver) {
1590   // Get the the instance type of the receiver, and make sure that it is
1591   // not one of the global object types.
1592   HValue* map =
1593       Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
1594   HValue* instance_type =
1595       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
1596   STATIC_ASSERT(JS_BUILTINS_OBJECT_TYPE == JS_GLOBAL_OBJECT_TYPE + 1);
1597   HValue* min_global_type = Add<HConstant>(JS_GLOBAL_OBJECT_TYPE);
1598   HValue* max_global_type = Add<HConstant>(JS_BUILTINS_OBJECT_TYPE);
1599
1600   IfBuilder if_global_object(this);
1601   if_global_object.If<HCompareNumericAndBranch>(instance_type,
1602                                                 max_global_type,
1603                                                 Token::LTE);
1604   if_global_object.And();
1605   if_global_object.If<HCompareNumericAndBranch>(instance_type,
1606                                                 min_global_type,
1607                                                 Token::GTE);
1608   if_global_object.ThenDeopt(Deoptimizer::kReceiverWasAGlobalObject);
1609   if_global_object.End();
1610 }
1611
1612
1613 void HGraphBuilder::BuildTestForDictionaryProperties(
1614     HValue* object,
1615     HIfContinuation* continuation) {
1616   HValue* properties = Add<HLoadNamedField>(
1617       object, nullptr, HObjectAccess::ForPropertiesPointer());
1618   HValue* properties_map =
1619       Add<HLoadNamedField>(properties, nullptr, HObjectAccess::ForMap());
1620   HValue* hash_map = Add<HLoadRoot>(Heap::kHashTableMapRootIndex);
1621   IfBuilder builder(this);
1622   builder.If<HCompareObjectEqAndBranch>(properties_map, hash_map);
1623   builder.CaptureContinuation(continuation);
1624 }
1625
1626
1627 HValue* HGraphBuilder::BuildKeyedLookupCacheHash(HValue* object,
1628                                                  HValue* key) {
1629   // Load the map of the receiver, compute the keyed lookup cache hash
1630   // based on 32 bits of the map pointer and the string hash.
1631   HValue* object_map =
1632       Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMapAsInteger32());
1633   HValue* shifted_map = AddUncasted<HShr>(
1634       object_map, Add<HConstant>(KeyedLookupCache::kMapHashShift));
1635   HValue* string_hash =
1636       Add<HLoadNamedField>(key, nullptr, HObjectAccess::ForStringHashField());
1637   HValue* shifted_hash = AddUncasted<HShr>(
1638       string_hash, Add<HConstant>(String::kHashShift));
1639   HValue* xor_result = AddUncasted<HBitwise>(Token::BIT_XOR, shifted_map,
1640                                              shifted_hash);
1641   int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
1642   return AddUncasted<HBitwise>(Token::BIT_AND, xor_result,
1643                                Add<HConstant>(mask));
1644 }
1645
1646
1647 HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) {
1648   int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed());
1649   HValue* seed = Add<HConstant>(seed_value);
1650   HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, index, seed);
1651
1652   // hash = ~hash + (hash << 15);
1653   HValue* shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(15));
1654   HValue* not_hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash,
1655                                            graph()->GetConstantMinus1());
1656   hash = AddUncasted<HAdd>(shifted_hash, not_hash);
1657
1658   // hash = hash ^ (hash >> 12);
1659   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(12));
1660   hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
1661
1662   // hash = hash + (hash << 2);
1663   shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(2));
1664   hash = AddUncasted<HAdd>(hash, shifted_hash);
1665
1666   // hash = hash ^ (hash >> 4);
1667   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(4));
1668   hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
1669
1670   // hash = hash * 2057;
1671   hash = AddUncasted<HMul>(hash, Add<HConstant>(2057));
1672   hash->ClearFlag(HValue::kCanOverflow);
1673
1674   // hash = hash ^ (hash >> 16);
1675   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(16));
1676   return AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
1677 }
1678
1679
1680 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(
1681     HValue* receiver, HValue* elements, HValue* key, HValue* hash,
1682     LanguageMode language_mode) {
1683   HValue* capacity =
1684       Add<HLoadKeyed>(elements, Add<HConstant>(NameDictionary::kCapacityIndex),
1685                       nullptr, FAST_ELEMENTS);
1686
1687   HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1());
1688   mask->ChangeRepresentation(Representation::Integer32());
1689   mask->ClearFlag(HValue::kCanOverflow);
1690
1691   HValue* entry = hash;
1692   HValue* count = graph()->GetConstant1();
1693   Push(entry);
1694   Push(count);
1695
1696   HIfContinuation return_or_loop_continuation(graph()->CreateBasicBlock(),
1697                                               graph()->CreateBasicBlock());
1698   HIfContinuation found_key_match_continuation(graph()->CreateBasicBlock(),
1699                                                graph()->CreateBasicBlock());
1700   LoopBuilder probe_loop(this);
1701   probe_loop.BeginBody(2);  // Drop entry, count from last environment to
1702                             // appease live range building without simulates.
1703
1704   count = Pop();
1705   entry = Pop();
1706   entry = AddUncasted<HBitwise>(Token::BIT_AND, entry, mask);
1707   int entry_size = SeededNumberDictionary::kEntrySize;
1708   HValue* base_index = AddUncasted<HMul>(entry, Add<HConstant>(entry_size));
1709   base_index->ClearFlag(HValue::kCanOverflow);
1710   int start_offset = SeededNumberDictionary::kElementsStartIndex;
1711   HValue* key_index =
1712       AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset));
1713   key_index->ClearFlag(HValue::kCanOverflow);
1714
1715   HValue* candidate_key =
1716       Add<HLoadKeyed>(elements, key_index, nullptr, FAST_ELEMENTS);
1717   IfBuilder if_undefined(this);
1718   if_undefined.If<HCompareObjectEqAndBranch>(candidate_key,
1719                                              graph()->GetConstantUndefined());
1720   if_undefined.Then();
1721   {
1722     // element == undefined means "not found". Call the runtime.
1723     // TODO(jkummerow): walk the prototype chain instead.
1724     Add<HPushArguments>(receiver, key);
1725     Push(Add<HCallRuntime>(
1726         isolate()->factory()->empty_string(),
1727         Runtime::FunctionForId(is_strong(language_mode)
1728                                    ? Runtime::kKeyedGetPropertyStrong
1729                                    : Runtime::kKeyedGetProperty),
1730         2));
1731   }
1732   if_undefined.Else();
1733   {
1734     IfBuilder if_match(this);
1735     if_match.If<HCompareObjectEqAndBranch>(candidate_key, key);
1736     if_match.Then();
1737     if_match.Else();
1738
1739     // Update non-internalized string in the dictionary with internalized key?
1740     IfBuilder if_update_with_internalized(this);
1741     HValue* smi_check =
1742         if_update_with_internalized.IfNot<HIsSmiAndBranch>(candidate_key);
1743     if_update_with_internalized.And();
1744     HValue* map = AddLoadMap(candidate_key, smi_check);
1745     HValue* instance_type =
1746         Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
1747     HValue* not_internalized_bit = AddUncasted<HBitwise>(
1748         Token::BIT_AND, instance_type,
1749         Add<HConstant>(static_cast<int>(kIsNotInternalizedMask)));
1750     if_update_with_internalized.If<HCompareNumericAndBranch>(
1751         not_internalized_bit, graph()->GetConstant0(), Token::NE);
1752     if_update_with_internalized.And();
1753     if_update_with_internalized.IfNot<HCompareObjectEqAndBranch>(
1754         candidate_key, graph()->GetConstantHole());
1755     if_update_with_internalized.AndIf<HStringCompareAndBranch>(candidate_key,
1756                                                                key, Token::EQ);
1757     if_update_with_internalized.Then();
1758     // Replace a key that is a non-internalized string by the equivalent
1759     // internalized string for faster further lookups.
1760     Add<HStoreKeyed>(elements, key_index, key, FAST_ELEMENTS);
1761     if_update_with_internalized.Else();
1762
1763     if_update_with_internalized.JoinContinuation(&found_key_match_continuation);
1764     if_match.JoinContinuation(&found_key_match_continuation);
1765
1766     IfBuilder found_key_match(this, &found_key_match_continuation);
1767     found_key_match.Then();
1768     // Key at current probe matches. Relevant bits in the |details| field must
1769     // be zero, otherwise the dictionary element requires special handling.
1770     HValue* details_index =
1771         AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 2));
1772     details_index->ClearFlag(HValue::kCanOverflow);
1773     HValue* details =
1774         Add<HLoadKeyed>(elements, details_index, nullptr, FAST_ELEMENTS);
1775     int details_mask = PropertyDetails::TypeField::kMask;
1776     details = AddUncasted<HBitwise>(Token::BIT_AND, details,
1777                                     Add<HConstant>(details_mask));
1778     IfBuilder details_compare(this);
1779     details_compare.If<HCompareNumericAndBranch>(
1780         details, graph()->GetConstant0(), Token::EQ);
1781     details_compare.Then();
1782     HValue* result_index =
1783         AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 1));
1784     result_index->ClearFlag(HValue::kCanOverflow);
1785     Push(Add<HLoadKeyed>(elements, result_index, nullptr, FAST_ELEMENTS));
1786     details_compare.Else();
1787     Add<HPushArguments>(receiver, key);
1788     Push(Add<HCallRuntime>(
1789         isolate()->factory()->empty_string(),
1790         Runtime::FunctionForId(is_strong(language_mode)
1791                                    ? Runtime::kKeyedGetPropertyStrong
1792                                    : Runtime::kKeyedGetProperty),
1793         2));
1794     details_compare.End();
1795
1796     found_key_match.Else();
1797     found_key_match.JoinContinuation(&return_or_loop_continuation);
1798   }
1799   if_undefined.JoinContinuation(&return_or_loop_continuation);
1800
1801   IfBuilder return_or_loop(this, &return_or_loop_continuation);
1802   return_or_loop.Then();
1803   probe_loop.Break();
1804
1805   return_or_loop.Else();
1806   entry = AddUncasted<HAdd>(entry, count);
1807   entry->ClearFlag(HValue::kCanOverflow);
1808   count = AddUncasted<HAdd>(count, graph()->GetConstant1());
1809   count->ClearFlag(HValue::kCanOverflow);
1810   Push(entry);
1811   Push(count);
1812
1813   probe_loop.EndBody();
1814
1815   return_or_loop.End();
1816
1817   return Pop();
1818 }
1819
1820
1821 HValue* HGraphBuilder::BuildRegExpConstructResult(HValue* length,
1822                                                   HValue* index,
1823                                                   HValue* input) {
1824   NoObservableSideEffectsScope scope(this);
1825   HConstant* max_length = Add<HConstant>(JSObject::kInitialMaxFastElementArray);
1826   Add<HBoundsCheck>(length, max_length);
1827
1828   // Generate size calculation code here in order to make it dominate
1829   // the JSRegExpResult allocation.
1830   ElementsKind elements_kind = FAST_ELEMENTS;
1831   HValue* size = BuildCalculateElementsSize(elements_kind, length);
1832
1833   // Allocate the JSRegExpResult and the FixedArray in one step.
1834   HValue* result = Add<HAllocate>(
1835       Add<HConstant>(JSRegExpResult::kSize), HType::JSArray(),
1836       NOT_TENURED, JS_ARRAY_TYPE);
1837
1838   // Initialize the JSRegExpResult header.
1839   HValue* global_object = Add<HLoadNamedField>(
1840       context(), nullptr,
1841       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
1842   HValue* native_context = Add<HLoadNamedField>(
1843       global_object, nullptr, HObjectAccess::ForGlobalObjectNativeContext());
1844   Add<HStoreNamedField>(
1845       result, HObjectAccess::ForMap(),
1846       Add<HLoadNamedField>(
1847           native_context, nullptr,
1848           HObjectAccess::ForContextSlot(Context::REGEXP_RESULT_MAP_INDEX)));
1849   HConstant* empty_fixed_array =
1850       Add<HConstant>(isolate()->factory()->empty_fixed_array());
1851   Add<HStoreNamedField>(
1852       result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset),
1853       empty_fixed_array);
1854   Add<HStoreNamedField>(
1855       result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
1856       empty_fixed_array);
1857   Add<HStoreNamedField>(
1858       result, HObjectAccess::ForJSArrayOffset(JSArray::kLengthOffset), length);
1859
1860   // Initialize the additional fields.
1861   Add<HStoreNamedField>(
1862       result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kIndexOffset),
1863       index);
1864   Add<HStoreNamedField>(
1865       result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kInputOffset),
1866       input);
1867
1868   // Allocate and initialize the elements header.
1869   HAllocate* elements = BuildAllocateElements(elements_kind, size);
1870   BuildInitializeElementsHeader(elements, elements_kind, length);
1871
1872   if (!elements->has_size_upper_bound()) {
1873     HConstant* size_in_bytes_upper_bound = EstablishElementsAllocationSize(
1874         elements_kind, max_length->Integer32Value());
1875     elements->set_size_upper_bound(size_in_bytes_upper_bound);
1876   }
1877
1878   Add<HStoreNamedField>(
1879       result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
1880       elements);
1881
1882   // Initialize the elements contents with undefined.
1883   BuildFillElementsWithValue(
1884       elements, elements_kind, graph()->GetConstant0(), length,
1885       graph()->GetConstantUndefined());
1886
1887   return result;
1888 }
1889
1890
1891 HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) {
1892   NoObservableSideEffectsScope scope(this);
1893
1894   // Convert constant numbers at compile time.
1895   if (object->IsConstant() && HConstant::cast(object)->HasNumberValue()) {
1896     Handle<Object> number = HConstant::cast(object)->handle(isolate());
1897     Handle<String> result = isolate()->factory()->NumberToString(number);
1898     return Add<HConstant>(result);
1899   }
1900
1901   // Create a joinable continuation.
1902   HIfContinuation found(graph()->CreateBasicBlock(),
1903                         graph()->CreateBasicBlock());
1904
1905   // Load the number string cache.
1906   HValue* number_string_cache =
1907       Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex);
1908
1909   // Make the hash mask from the length of the number string cache. It
1910   // contains two elements (number and string) for each cache entry.
1911   HValue* mask = AddLoadFixedArrayLength(number_string_cache);
1912   mask->set_type(HType::Smi());
1913   mask = AddUncasted<HSar>(mask, graph()->GetConstant1());
1914   mask = AddUncasted<HSub>(mask, graph()->GetConstant1());
1915
1916   // Check whether object is a smi.
1917   IfBuilder if_objectissmi(this);
1918   if_objectissmi.If<HIsSmiAndBranch>(object);
1919   if_objectissmi.Then();
1920   {
1921     // Compute hash for smi similar to smi_get_hash().
1922     HValue* hash = AddUncasted<HBitwise>(Token::BIT_AND, object, mask);
1923
1924     // Load the key.
1925     HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
1926     HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, nullptr,
1927                                   FAST_ELEMENTS, ALLOW_RETURN_HOLE);
1928
1929     // Check if object == key.
1930     IfBuilder if_objectiskey(this);
1931     if_objectiskey.If<HCompareObjectEqAndBranch>(object, key);
1932     if_objectiskey.Then();
1933     {
1934       // Make the key_index available.
1935       Push(key_index);
1936     }
1937     if_objectiskey.JoinContinuation(&found);
1938   }
1939   if_objectissmi.Else();
1940   {
1941     if (type->Is(Type::SignedSmall())) {
1942       if_objectissmi.Deopt(Deoptimizer::kExpectedSmi);
1943     } else {
1944       // Check if the object is a heap number.
1945       IfBuilder if_objectisnumber(this);
1946       HValue* objectisnumber = if_objectisnumber.If<HCompareMap>(
1947           object, isolate()->factory()->heap_number_map());
1948       if_objectisnumber.Then();
1949       {
1950         // Compute hash for heap number similar to double_get_hash().
1951         HValue* low = Add<HLoadNamedField>(
1952             object, objectisnumber,
1953             HObjectAccess::ForHeapNumberValueLowestBits());
1954         HValue* high = Add<HLoadNamedField>(
1955             object, objectisnumber,
1956             HObjectAccess::ForHeapNumberValueHighestBits());
1957         HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, low, high);
1958         hash = AddUncasted<HBitwise>(Token::BIT_AND, hash, mask);
1959
1960         // Load the key.
1961         HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
1962         HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, nullptr,
1963                                       FAST_ELEMENTS, ALLOW_RETURN_HOLE);
1964
1965         // Check if the key is a heap number and compare it with the object.
1966         IfBuilder if_keyisnotsmi(this);
1967         HValue* keyisnotsmi = if_keyisnotsmi.IfNot<HIsSmiAndBranch>(key);
1968         if_keyisnotsmi.Then();
1969         {
1970           IfBuilder if_keyisheapnumber(this);
1971           if_keyisheapnumber.If<HCompareMap>(
1972               key, isolate()->factory()->heap_number_map());
1973           if_keyisheapnumber.Then();
1974           {
1975             // Check if values of key and object match.
1976             IfBuilder if_keyeqobject(this);
1977             if_keyeqobject.If<HCompareNumericAndBranch>(
1978                 Add<HLoadNamedField>(key, keyisnotsmi,
1979                                      HObjectAccess::ForHeapNumberValue()),
1980                 Add<HLoadNamedField>(object, objectisnumber,
1981                                      HObjectAccess::ForHeapNumberValue()),
1982                 Token::EQ);
1983             if_keyeqobject.Then();
1984             {
1985               // Make the key_index available.
1986               Push(key_index);
1987             }
1988             if_keyeqobject.JoinContinuation(&found);
1989           }
1990           if_keyisheapnumber.JoinContinuation(&found);
1991         }
1992         if_keyisnotsmi.JoinContinuation(&found);
1993       }
1994       if_objectisnumber.Else();
1995       {
1996         if (type->Is(Type::Number())) {
1997           if_objectisnumber.Deopt(Deoptimizer::kExpectedHeapNumber);
1998         }
1999       }
2000       if_objectisnumber.JoinContinuation(&found);
2001     }
2002   }
2003   if_objectissmi.JoinContinuation(&found);
2004
2005   // Check for cache hit.
2006   IfBuilder if_found(this, &found);
2007   if_found.Then();
2008   {
2009     // Count number to string operation in native code.
2010     AddIncrementCounter(isolate()->counters()->number_to_string_native());
2011
2012     // Load the value in case of cache hit.
2013     HValue* key_index = Pop();
2014     HValue* value_index = AddUncasted<HAdd>(key_index, graph()->GetConstant1());
2015     Push(Add<HLoadKeyed>(number_string_cache, value_index, nullptr,
2016                          FAST_ELEMENTS, ALLOW_RETURN_HOLE));
2017   }
2018   if_found.Else();
2019   {
2020     // Cache miss, fallback to runtime.
2021     Add<HPushArguments>(object);
2022     Push(Add<HCallRuntime>(
2023             isolate()->factory()->empty_string(),
2024             Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
2025             1));
2026   }
2027   if_found.End();
2028
2029   return Pop();
2030 }
2031
2032
2033 HValue* HGraphBuilder::BuildToObject(HValue* receiver) {
2034   NoObservableSideEffectsScope scope(this);
2035
2036   // Create a joinable continuation.
2037   HIfContinuation wrap(graph()->CreateBasicBlock(),
2038                        graph()->CreateBasicBlock());
2039
2040   // Determine the proper global constructor function required to wrap
2041   // {receiver} into a JSValue, unless {receiver} is already a {JSReceiver}, in
2042   // which case we just return it.  Deopts to Runtime::kToObject if {receiver}
2043   // is undefined or null.
2044   IfBuilder receiver_is_smi(this);
2045   receiver_is_smi.If<HIsSmiAndBranch>(receiver);
2046   receiver_is_smi.Then();
2047   {
2048     // Use global Number function.
2049     Push(Add<HConstant>(Context::NUMBER_FUNCTION_INDEX));
2050   }
2051   receiver_is_smi.Else();
2052   {
2053     // Determine {receiver} map and instance type.
2054     HValue* receiver_map =
2055         Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
2056     HValue* receiver_instance_type = Add<HLoadNamedField>(
2057         receiver_map, nullptr, HObjectAccess::ForMapInstanceType());
2058
2059     // First check whether {receiver} is already a spec object (fast case).
2060     IfBuilder receiver_is_not_spec_object(this);
2061     receiver_is_not_spec_object.If<HCompareNumericAndBranch>(
2062         receiver_instance_type, Add<HConstant>(FIRST_SPEC_OBJECT_TYPE),
2063         Token::LT);
2064     receiver_is_not_spec_object.Then();
2065     {
2066       // Load the constructor function index from the {receiver} map.
2067       HValue* constructor_function_index = Add<HLoadNamedField>(
2068           receiver_map, nullptr,
2069           HObjectAccess::ForMapInObjectPropertiesOrConstructorFunctionIndex());
2070
2071       // Check if {receiver} has a constructor (null and undefined have no
2072       // constructors, so we deoptimize to the runtime to throw an exception).
2073       IfBuilder constructor_function_index_is_invalid(this);
2074       constructor_function_index_is_invalid.If<HCompareNumericAndBranch>(
2075           constructor_function_index,
2076           Add<HConstant>(Map::kNoConstructorFunctionIndex), Token::EQ);
2077       constructor_function_index_is_invalid.ThenDeopt(
2078           Deoptimizer::kUndefinedOrNullInToObject);
2079       constructor_function_index_is_invalid.End();
2080
2081       // Use the global constructor function.
2082       Push(constructor_function_index);
2083     }
2084     receiver_is_not_spec_object.JoinContinuation(&wrap);
2085   }
2086   receiver_is_smi.JoinContinuation(&wrap);
2087
2088   // Wrap the receiver if necessary.
2089   IfBuilder if_wrap(this, &wrap);
2090   if_wrap.Then();
2091   {
2092     // Grab the constructor function index.
2093     HValue* constructor_index = Pop();
2094
2095     // Load native context.
2096     HValue* native_context = BuildGetNativeContext();
2097
2098     // Determine the initial map for the global constructor.
2099     HValue* constructor = Add<HLoadKeyed>(native_context, constructor_index,
2100                                           nullptr, FAST_ELEMENTS);
2101     HValue* constructor_initial_map = Add<HLoadNamedField>(
2102         constructor, nullptr, HObjectAccess::ForPrototypeOrInitialMap());
2103     // Allocate and initialize a JSValue wrapper.
2104     HValue* value =
2105         BuildAllocate(Add<HConstant>(JSValue::kSize), HType::JSObject(),
2106                       JS_VALUE_TYPE, HAllocationMode());
2107     Add<HStoreNamedField>(value, HObjectAccess::ForMap(),
2108                           constructor_initial_map);
2109     HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
2110     Add<HStoreNamedField>(value, HObjectAccess::ForPropertiesPointer(),
2111                           empty_fixed_array);
2112     Add<HStoreNamedField>(value, HObjectAccess::ForElementsPointer(),
2113                           empty_fixed_array);
2114     Add<HStoreNamedField>(value, HObjectAccess::ForObservableJSObjectOffset(
2115                                      JSValue::kValueOffset),
2116                           receiver);
2117     Push(value);
2118   }
2119   if_wrap.Else();
2120   { Push(receiver); }
2121   if_wrap.End();
2122   return Pop();
2123 }
2124
2125
2126 HAllocate* HGraphBuilder::BuildAllocate(
2127     HValue* object_size,
2128     HType type,
2129     InstanceType instance_type,
2130     HAllocationMode allocation_mode) {
2131   // Compute the effective allocation size.
2132   HValue* size = object_size;
2133   if (allocation_mode.CreateAllocationMementos()) {
2134     size = AddUncasted<HAdd>(size, Add<HConstant>(AllocationMemento::kSize));
2135     size->ClearFlag(HValue::kCanOverflow);
2136   }
2137
2138   // Perform the actual allocation.
2139   HAllocate* object = Add<HAllocate>(
2140       size, type, allocation_mode.GetPretenureMode(),
2141       instance_type, allocation_mode.feedback_site());
2142
2143   // Setup the allocation memento.
2144   if (allocation_mode.CreateAllocationMementos()) {
2145     BuildCreateAllocationMemento(
2146         object, object_size, allocation_mode.current_site());
2147   }
2148
2149   return object;
2150 }
2151
2152
2153 HValue* HGraphBuilder::BuildAddStringLengths(HValue* left_length,
2154                                              HValue* right_length) {
2155   // Compute the combined string length and check against max string length.
2156   HValue* length = AddUncasted<HAdd>(left_length, right_length);
2157   // Check that length <= kMaxLength <=> length < MaxLength + 1.
2158   HValue* max_length = Add<HConstant>(String::kMaxLength + 1);
2159   Add<HBoundsCheck>(length, max_length);
2160   return length;
2161 }
2162
2163
2164 HValue* HGraphBuilder::BuildCreateConsString(
2165     HValue* length,
2166     HValue* left,
2167     HValue* right,
2168     HAllocationMode allocation_mode) {
2169   // Determine the string instance types.
2170   HInstruction* left_instance_type = AddLoadStringInstanceType(left);
2171   HInstruction* right_instance_type = AddLoadStringInstanceType(right);
2172
2173   // Allocate the cons string object. HAllocate does not care whether we
2174   // pass CONS_STRING_TYPE or CONS_ONE_BYTE_STRING_TYPE here, so we just use
2175   // CONS_STRING_TYPE here. Below we decide whether the cons string is
2176   // one-byte or two-byte and set the appropriate map.
2177   DCHECK(HAllocate::CompatibleInstanceTypes(CONS_STRING_TYPE,
2178                                             CONS_ONE_BYTE_STRING_TYPE));
2179   HAllocate* result = BuildAllocate(Add<HConstant>(ConsString::kSize),
2180                                     HType::String(), CONS_STRING_TYPE,
2181                                     allocation_mode);
2182
2183   // Compute intersection and difference of instance types.
2184   HValue* anded_instance_types = AddUncasted<HBitwise>(
2185       Token::BIT_AND, left_instance_type, right_instance_type);
2186   HValue* xored_instance_types = AddUncasted<HBitwise>(
2187       Token::BIT_XOR, left_instance_type, right_instance_type);
2188
2189   // We create a one-byte cons string if
2190   // 1. both strings are one-byte, or
2191   // 2. at least one of the strings is two-byte, but happens to contain only
2192   //    one-byte characters.
2193   // To do this, we check
2194   // 1. if both strings are one-byte, or if the one-byte data hint is set in
2195   //    both strings, or
2196   // 2. if one of the strings has the one-byte data hint set and the other
2197   //    string is one-byte.
2198   IfBuilder if_onebyte(this);
2199   STATIC_ASSERT(kOneByteStringTag != 0);
2200   STATIC_ASSERT(kOneByteDataHintMask != 0);
2201   if_onebyte.If<HCompareNumericAndBranch>(
2202       AddUncasted<HBitwise>(
2203           Token::BIT_AND, anded_instance_types,
2204           Add<HConstant>(static_cast<int32_t>(
2205                   kStringEncodingMask | kOneByteDataHintMask))),
2206       graph()->GetConstant0(), Token::NE);
2207   if_onebyte.Or();
2208   STATIC_ASSERT(kOneByteStringTag != 0 &&
2209                 kOneByteDataHintTag != 0 &&
2210                 kOneByteDataHintTag != kOneByteStringTag);
2211   if_onebyte.If<HCompareNumericAndBranch>(
2212       AddUncasted<HBitwise>(
2213           Token::BIT_AND, xored_instance_types,
2214           Add<HConstant>(static_cast<int32_t>(
2215                   kOneByteStringTag | kOneByteDataHintTag))),
2216       Add<HConstant>(static_cast<int32_t>(
2217               kOneByteStringTag | kOneByteDataHintTag)), Token::EQ);
2218   if_onebyte.Then();
2219   {
2220     // We can safely skip the write barrier for storing the map here.
2221     Add<HStoreNamedField>(
2222         result, HObjectAccess::ForMap(),
2223         Add<HConstant>(isolate()->factory()->cons_one_byte_string_map()));
2224   }
2225   if_onebyte.Else();
2226   {
2227     // We can safely skip the write barrier for storing the map here.
2228     Add<HStoreNamedField>(
2229         result, HObjectAccess::ForMap(),
2230         Add<HConstant>(isolate()->factory()->cons_string_map()));
2231   }
2232   if_onebyte.End();
2233
2234   // Initialize the cons string fields.
2235   Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
2236                         Add<HConstant>(String::kEmptyHashField));
2237   Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
2238   Add<HStoreNamedField>(result, HObjectAccess::ForConsStringFirst(), left);
2239   Add<HStoreNamedField>(result, HObjectAccess::ForConsStringSecond(), right);
2240
2241   // Count the native string addition.
2242   AddIncrementCounter(isolate()->counters()->string_add_native());
2243
2244   return result;
2245 }
2246
2247
2248 void HGraphBuilder::BuildCopySeqStringChars(HValue* src,
2249                                             HValue* src_offset,
2250                                             String::Encoding src_encoding,
2251                                             HValue* dst,
2252                                             HValue* dst_offset,
2253                                             String::Encoding dst_encoding,
2254                                             HValue* length) {
2255   DCHECK(dst_encoding != String::ONE_BYTE_ENCODING ||
2256          src_encoding == String::ONE_BYTE_ENCODING);
2257   LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
2258   HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT);
2259   {
2260     HValue* src_index = AddUncasted<HAdd>(src_offset, index);
2261     HValue* value =
2262         AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index);
2263     HValue* dst_index = AddUncasted<HAdd>(dst_offset, index);
2264     Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value);
2265   }
2266   loop.EndBody();
2267 }
2268
2269
2270 HValue* HGraphBuilder::BuildObjectSizeAlignment(
2271     HValue* unaligned_size, int header_size) {
2272   DCHECK((header_size & kObjectAlignmentMask) == 0);
2273   HValue* size = AddUncasted<HAdd>(
2274       unaligned_size, Add<HConstant>(static_cast<int32_t>(
2275           header_size + kObjectAlignmentMask)));
2276   size->ClearFlag(HValue::kCanOverflow);
2277   return AddUncasted<HBitwise>(
2278       Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>(
2279           ~kObjectAlignmentMask)));
2280 }
2281
2282
2283 HValue* HGraphBuilder::BuildUncheckedStringAdd(
2284     HValue* left,
2285     HValue* right,
2286     HAllocationMode allocation_mode) {
2287   // Determine the string lengths.
2288   HValue* left_length = AddLoadStringLength(left);
2289   HValue* right_length = AddLoadStringLength(right);
2290
2291   // Compute the combined string length.
2292   HValue* length = BuildAddStringLengths(left_length, right_length);
2293
2294   // Do some manual constant folding here.
2295   if (left_length->IsConstant()) {
2296     HConstant* c_left_length = HConstant::cast(left_length);
2297     DCHECK_NE(0, c_left_length->Integer32Value());
2298     if (c_left_length->Integer32Value() + 1 >= ConsString::kMinLength) {
2299       // The right string contains at least one character.
2300       return BuildCreateConsString(length, left, right, allocation_mode);
2301     }
2302   } else if (right_length->IsConstant()) {
2303     HConstant* c_right_length = HConstant::cast(right_length);
2304     DCHECK_NE(0, c_right_length->Integer32Value());
2305     if (c_right_length->Integer32Value() + 1 >= ConsString::kMinLength) {
2306       // The left string contains at least one character.
2307       return BuildCreateConsString(length, left, right, allocation_mode);
2308     }
2309   }
2310
2311   // Check if we should create a cons string.
2312   IfBuilder if_createcons(this);
2313   if_createcons.If<HCompareNumericAndBranch>(
2314       length, Add<HConstant>(ConsString::kMinLength), Token::GTE);
2315   if_createcons.Then();
2316   {
2317     // Create a cons string.
2318     Push(BuildCreateConsString(length, left, right, allocation_mode));
2319   }
2320   if_createcons.Else();
2321   {
2322     // Determine the string instance types.
2323     HValue* left_instance_type = AddLoadStringInstanceType(left);
2324     HValue* right_instance_type = AddLoadStringInstanceType(right);
2325
2326     // Compute union and difference of instance types.
2327     HValue* ored_instance_types = AddUncasted<HBitwise>(
2328         Token::BIT_OR, left_instance_type, right_instance_type);
2329     HValue* xored_instance_types = AddUncasted<HBitwise>(
2330         Token::BIT_XOR, left_instance_type, right_instance_type);
2331
2332     // Check if both strings have the same encoding and both are
2333     // sequential.
2334     IfBuilder if_sameencodingandsequential(this);
2335     if_sameencodingandsequential.If<HCompareNumericAndBranch>(
2336         AddUncasted<HBitwise>(
2337             Token::BIT_AND, xored_instance_types,
2338             Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
2339         graph()->GetConstant0(), Token::EQ);
2340     if_sameencodingandsequential.And();
2341     STATIC_ASSERT(kSeqStringTag == 0);
2342     if_sameencodingandsequential.If<HCompareNumericAndBranch>(
2343         AddUncasted<HBitwise>(
2344             Token::BIT_AND, ored_instance_types,
2345             Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))),
2346         graph()->GetConstant0(), Token::EQ);
2347     if_sameencodingandsequential.Then();
2348     {
2349       HConstant* string_map =
2350           Add<HConstant>(isolate()->factory()->string_map());
2351       HConstant* one_byte_string_map =
2352           Add<HConstant>(isolate()->factory()->one_byte_string_map());
2353
2354       // Determine map and size depending on whether result is one-byte string.
2355       IfBuilder if_onebyte(this);
2356       STATIC_ASSERT(kOneByteStringTag != 0);
2357       if_onebyte.If<HCompareNumericAndBranch>(
2358           AddUncasted<HBitwise>(
2359               Token::BIT_AND, ored_instance_types,
2360               Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
2361           graph()->GetConstant0(), Token::NE);
2362       if_onebyte.Then();
2363       {
2364         // Allocate sequential one-byte string object.
2365         Push(length);
2366         Push(one_byte_string_map);
2367       }
2368       if_onebyte.Else();
2369       {
2370         // Allocate sequential two-byte string object.
2371         HValue* size = AddUncasted<HShl>(length, graph()->GetConstant1());
2372         size->ClearFlag(HValue::kCanOverflow);
2373         size->SetFlag(HValue::kUint32);
2374         Push(size);
2375         Push(string_map);
2376       }
2377       if_onebyte.End();
2378       HValue* map = Pop();
2379
2380       // Calculate the number of bytes needed for the characters in the
2381       // string while observing object alignment.
2382       STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0);
2383       HValue* size = BuildObjectSizeAlignment(Pop(), SeqString::kHeaderSize);
2384
2385       // Allocate the string object. HAllocate does not care whether we pass
2386       // STRING_TYPE or ONE_BYTE_STRING_TYPE here, so we just use STRING_TYPE.
2387       HAllocate* result = BuildAllocate(
2388           size, HType::String(), STRING_TYPE, allocation_mode);
2389       Add<HStoreNamedField>(result, HObjectAccess::ForMap(), map);
2390
2391       // Initialize the string fields.
2392       Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
2393                             Add<HConstant>(String::kEmptyHashField));
2394       Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
2395
2396       // Copy characters to the result string.
2397       IfBuilder if_twobyte(this);
2398       if_twobyte.If<HCompareObjectEqAndBranch>(map, string_map);
2399       if_twobyte.Then();
2400       {
2401         // Copy characters from the left string.
2402         BuildCopySeqStringChars(
2403             left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
2404             result, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
2405             left_length);
2406
2407         // Copy characters from the right string.
2408         BuildCopySeqStringChars(
2409             right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
2410             result, left_length, String::TWO_BYTE_ENCODING,
2411             right_length);
2412       }
2413       if_twobyte.Else();
2414       {
2415         // Copy characters from the left string.
2416         BuildCopySeqStringChars(
2417             left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
2418             result, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
2419             left_length);
2420
2421         // Copy characters from the right string.
2422         BuildCopySeqStringChars(
2423             right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
2424             result, left_length, String::ONE_BYTE_ENCODING,
2425             right_length);
2426       }
2427       if_twobyte.End();
2428
2429       // Count the native string addition.
2430       AddIncrementCounter(isolate()->counters()->string_add_native());
2431
2432       // Return the sequential string.
2433       Push(result);
2434     }
2435     if_sameencodingandsequential.Else();
2436     {
2437       // Fallback to the runtime to add the two strings.
2438       Add<HPushArguments>(left, right);
2439       Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
2440                              Runtime::FunctionForId(Runtime::kStringAdd), 2));
2441     }
2442     if_sameencodingandsequential.End();
2443   }
2444   if_createcons.End();
2445
2446   return Pop();
2447 }
2448
2449
2450 HValue* HGraphBuilder::BuildStringAdd(
2451     HValue* left,
2452     HValue* right,
2453     HAllocationMode allocation_mode) {
2454   NoObservableSideEffectsScope no_effects(this);
2455
2456   // Determine string lengths.
2457   HValue* left_length = AddLoadStringLength(left);
2458   HValue* right_length = AddLoadStringLength(right);
2459
2460   // Check if left string is empty.
2461   IfBuilder if_leftempty(this);
2462   if_leftempty.If<HCompareNumericAndBranch>(
2463       left_length, graph()->GetConstant0(), Token::EQ);
2464   if_leftempty.Then();
2465   {
2466     // Count the native string addition.
2467     AddIncrementCounter(isolate()->counters()->string_add_native());
2468
2469     // Just return the right string.
2470     Push(right);
2471   }
2472   if_leftempty.Else();
2473   {
2474     // Check if right string is empty.
2475     IfBuilder if_rightempty(this);
2476     if_rightempty.If<HCompareNumericAndBranch>(
2477         right_length, graph()->GetConstant0(), Token::EQ);
2478     if_rightempty.Then();
2479     {
2480       // Count the native string addition.
2481       AddIncrementCounter(isolate()->counters()->string_add_native());
2482
2483       // Just return the left string.
2484       Push(left);
2485     }
2486     if_rightempty.Else();
2487     {
2488       // Add the two non-empty strings.
2489       Push(BuildUncheckedStringAdd(left, right, allocation_mode));
2490     }
2491     if_rightempty.End();
2492   }
2493   if_leftempty.End();
2494
2495   return Pop();
2496 }
2497
2498
2499 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
2500     HValue* checked_object,
2501     HValue* key,
2502     HValue* val,
2503     bool is_js_array,
2504     ElementsKind elements_kind,
2505     PropertyAccessType access_type,
2506     LoadKeyedHoleMode load_mode,
2507     KeyedAccessStoreMode store_mode) {
2508   DCHECK(top_info()->IsStub() || checked_object->IsCompareMap() ||
2509          checked_object->IsCheckMaps());
2510   DCHECK(!IsFixedTypedArrayElementsKind(elements_kind) || !is_js_array);
2511   // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
2512   // on a HElementsTransition instruction. The flag can also be removed if the
2513   // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
2514   // ElementsKind transitions. Finally, the dependency can be removed for stores
2515   // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
2516   // generated store code.
2517   if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
2518       (elements_kind == FAST_ELEMENTS && access_type == STORE)) {
2519     checked_object->ClearDependsOnFlag(kElementsKind);
2520   }
2521
2522   bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
2523   bool fast_elements = IsFastObjectElementsKind(elements_kind);
2524   HValue* elements = AddLoadElements(checked_object);
2525   if (access_type == STORE && (fast_elements || fast_smi_only_elements) &&
2526       store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
2527     HCheckMaps* check_cow_map = Add<HCheckMaps>(
2528         elements, isolate()->factory()->fixed_array_map());
2529     check_cow_map->ClearDependsOnFlag(kElementsKind);
2530   }
2531   HInstruction* length = NULL;
2532   if (is_js_array) {
2533     length = Add<HLoadNamedField>(
2534         checked_object->ActualValue(), checked_object,
2535         HObjectAccess::ForArrayLength(elements_kind));
2536   } else {
2537     length = AddLoadFixedArrayLength(elements);
2538   }
2539   length->set_type(HType::Smi());
2540   HValue* checked_key = NULL;
2541   if (IsFixedTypedArrayElementsKind(elements_kind)) {
2542     checked_object = Add<HCheckArrayBufferNotNeutered>(checked_object);
2543
2544     HValue* external_pointer = Add<HLoadNamedField>(
2545         elements, nullptr,
2546         HObjectAccess::ForFixedTypedArrayBaseExternalPointer());
2547     HValue* base_pointer = Add<HLoadNamedField>(
2548         elements, nullptr, HObjectAccess::ForFixedTypedArrayBaseBasePointer());
2549     HValue* backing_store = AddUncasted<HAdd>(
2550         external_pointer, base_pointer, Strength::WEAK, AddOfExternalAndTagged);
2551
2552     if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
2553       NoObservableSideEffectsScope no_effects(this);
2554       IfBuilder length_checker(this);
2555       length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
2556       length_checker.Then();
2557       IfBuilder negative_checker(this);
2558       HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
2559           key, graph()->GetConstant0(), Token::GTE);
2560       negative_checker.Then();
2561       HInstruction* result = AddElementAccess(
2562           backing_store, key, val, bounds_check, elements_kind, access_type);
2563       negative_checker.ElseDeopt(Deoptimizer::kNegativeKeyEncountered);
2564       negative_checker.End();
2565       length_checker.End();
2566       return result;
2567     } else {
2568       DCHECK(store_mode == STANDARD_STORE);
2569       checked_key = Add<HBoundsCheck>(key, length);
2570       return AddElementAccess(
2571           backing_store, checked_key, val,
2572           checked_object, elements_kind, access_type);
2573     }
2574   }
2575   DCHECK(fast_smi_only_elements ||
2576          fast_elements ||
2577          IsFastDoubleElementsKind(elements_kind));
2578
2579   // In case val is stored into a fast smi array, assure that the value is a smi
2580   // before manipulating the backing store. Otherwise the actual store may
2581   // deopt, leaving the backing store in an invalid state.
2582   if (access_type == STORE && IsFastSmiElementsKind(elements_kind) &&
2583       !val->type().IsSmi()) {
2584     val = AddUncasted<HForceRepresentation>(val, Representation::Smi());
2585   }
2586
2587   if (IsGrowStoreMode(store_mode)) {
2588     NoObservableSideEffectsScope no_effects(this);
2589     Representation representation = HStoreKeyed::RequiredValueRepresentation(
2590         elements_kind, STORE_TO_INITIALIZED_ENTRY);
2591     val = AddUncasted<HForceRepresentation>(val, representation);
2592     elements = BuildCheckForCapacityGrow(checked_object, elements,
2593                                          elements_kind, length, key,
2594                                          is_js_array, access_type);
2595     checked_key = key;
2596   } else {
2597     checked_key = Add<HBoundsCheck>(key, length);
2598
2599     if (access_type == STORE && (fast_elements || fast_smi_only_elements)) {
2600       if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
2601         NoObservableSideEffectsScope no_effects(this);
2602         elements = BuildCopyElementsOnWrite(checked_object, elements,
2603                                             elements_kind, length);
2604       } else {
2605         HCheckMaps* check_cow_map = Add<HCheckMaps>(
2606             elements, isolate()->factory()->fixed_array_map());
2607         check_cow_map->ClearDependsOnFlag(kElementsKind);
2608       }
2609     }
2610   }
2611   return AddElementAccess(elements, checked_key, val, checked_object,
2612                           elements_kind, access_type, load_mode);
2613 }
2614
2615
2616 HValue* HGraphBuilder::BuildAllocateArrayFromLength(
2617     JSArrayBuilder* array_builder,
2618     HValue* length_argument) {
2619   if (length_argument->IsConstant() &&
2620       HConstant::cast(length_argument)->HasSmiValue()) {
2621     int array_length = HConstant::cast(length_argument)->Integer32Value();
2622     if (array_length == 0) {
2623       return array_builder->AllocateEmptyArray();
2624     } else {
2625       return array_builder->AllocateArray(length_argument,
2626                                           array_length,
2627                                           length_argument);
2628     }
2629   }
2630
2631   HValue* constant_zero = graph()->GetConstant0();
2632   HConstant* max_alloc_length =
2633       Add<HConstant>(JSObject::kInitialMaxFastElementArray);
2634   HInstruction* checked_length = Add<HBoundsCheck>(length_argument,
2635                                                    max_alloc_length);
2636   IfBuilder if_builder(this);
2637   if_builder.If<HCompareNumericAndBranch>(checked_length, constant_zero,
2638                                           Token::EQ);
2639   if_builder.Then();
2640   const int initial_capacity = JSArray::kPreallocatedArrayElements;
2641   HConstant* initial_capacity_node = Add<HConstant>(initial_capacity);
2642   Push(initial_capacity_node);  // capacity
2643   Push(constant_zero);          // length
2644   if_builder.Else();
2645   if (!(top_info()->IsStub()) &&
2646       IsFastPackedElementsKind(array_builder->kind())) {
2647     // We'll come back later with better (holey) feedback.
2648     if_builder.Deopt(
2649         Deoptimizer::kHoleyArrayDespitePackedElements_kindFeedback);
2650   } else {
2651     Push(checked_length);         // capacity
2652     Push(checked_length);         // length
2653   }
2654   if_builder.End();
2655
2656   // Figure out total size
2657   HValue* length = Pop();
2658   HValue* capacity = Pop();
2659   return array_builder->AllocateArray(capacity, max_alloc_length, length);
2660 }
2661
2662
2663 HValue* HGraphBuilder::BuildCalculateElementsSize(ElementsKind kind,
2664                                                   HValue* capacity) {
2665   int elements_size = IsFastDoubleElementsKind(kind)
2666       ? kDoubleSize
2667       : kPointerSize;
2668
2669   HConstant* elements_size_value = Add<HConstant>(elements_size);
2670   HInstruction* mul =
2671       HMul::NewImul(isolate(), zone(), context(), capacity->ActualValue(),
2672                     elements_size_value);
2673   AddInstruction(mul);
2674   mul->ClearFlag(HValue::kCanOverflow);
2675
2676   STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize);
2677
2678   HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize);
2679   HValue* total_size = AddUncasted<HAdd>(mul, header_size);
2680   total_size->ClearFlag(HValue::kCanOverflow);
2681   return total_size;
2682 }
2683
2684
2685 HAllocate* HGraphBuilder::AllocateJSArrayObject(AllocationSiteMode mode) {
2686   int base_size = JSArray::kSize;
2687   if (mode == TRACK_ALLOCATION_SITE) {
2688     base_size += AllocationMemento::kSize;
2689   }
2690   HConstant* size_in_bytes = Add<HConstant>(base_size);
2691   return Add<HAllocate>(
2692       size_in_bytes, HType::JSArray(), NOT_TENURED, JS_OBJECT_TYPE);
2693 }
2694
2695
2696 HConstant* HGraphBuilder::EstablishElementsAllocationSize(
2697     ElementsKind kind,
2698     int capacity) {
2699   int base_size = IsFastDoubleElementsKind(kind)
2700       ? FixedDoubleArray::SizeFor(capacity)
2701       : FixedArray::SizeFor(capacity);
2702
2703   return Add<HConstant>(base_size);
2704 }
2705
2706
2707 HAllocate* HGraphBuilder::BuildAllocateElements(ElementsKind kind,
2708                                                 HValue* size_in_bytes) {
2709   InstanceType instance_type = IsFastDoubleElementsKind(kind)
2710       ? FIXED_DOUBLE_ARRAY_TYPE
2711       : FIXED_ARRAY_TYPE;
2712
2713   return Add<HAllocate>(size_in_bytes, HType::HeapObject(), NOT_TENURED,
2714                         instance_type);
2715 }
2716
2717
2718 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements,
2719                                                   ElementsKind kind,
2720                                                   HValue* capacity) {
2721   Factory* factory = isolate()->factory();
2722   Handle<Map> map = IsFastDoubleElementsKind(kind)
2723       ? factory->fixed_double_array_map()
2724       : factory->fixed_array_map();
2725
2726   Add<HStoreNamedField>(elements, HObjectAccess::ForMap(), Add<HConstant>(map));
2727   Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(),
2728                         capacity);
2729 }
2730
2731
2732 HValue* HGraphBuilder::BuildAllocateAndInitializeArray(ElementsKind kind,
2733                                                        HValue* capacity) {
2734   // The HForceRepresentation is to prevent possible deopt on int-smi
2735   // conversion after allocation but before the new object fields are set.
2736   capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi());
2737   HValue* size_in_bytes = BuildCalculateElementsSize(kind, capacity);
2738   HValue* new_array = BuildAllocateElements(kind, size_in_bytes);
2739   BuildInitializeElementsHeader(new_array, kind, capacity);
2740   return new_array;
2741 }
2742
2743
2744 void HGraphBuilder::BuildJSArrayHeader(HValue* array,
2745                                        HValue* array_map,
2746                                        HValue* elements,
2747                                        AllocationSiteMode mode,
2748                                        ElementsKind elements_kind,
2749                                        HValue* allocation_site_payload,
2750                                        HValue* length_field) {
2751   Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map);
2752
2753   HConstant* empty_fixed_array =
2754     Add<HConstant>(isolate()->factory()->empty_fixed_array());
2755
2756   Add<HStoreNamedField>(
2757       array, HObjectAccess::ForPropertiesPointer(), empty_fixed_array);
2758
2759   Add<HStoreNamedField>(
2760       array, HObjectAccess::ForElementsPointer(),
2761       elements != NULL ? elements : empty_fixed_array);
2762
2763   Add<HStoreNamedField>(
2764       array, HObjectAccess::ForArrayLength(elements_kind), length_field);
2765
2766   if (mode == TRACK_ALLOCATION_SITE) {
2767     BuildCreateAllocationMemento(
2768         array, Add<HConstant>(JSArray::kSize), allocation_site_payload);
2769   }
2770 }
2771
2772
2773 HInstruction* HGraphBuilder::AddElementAccess(
2774     HValue* elements,
2775     HValue* checked_key,
2776     HValue* val,
2777     HValue* dependency,
2778     ElementsKind elements_kind,
2779     PropertyAccessType access_type,
2780     LoadKeyedHoleMode load_mode) {
2781   if (access_type == STORE) {
2782     DCHECK(val != NULL);
2783     if (elements_kind == UINT8_CLAMPED_ELEMENTS) {
2784       val = Add<HClampToUint8>(val);
2785     }
2786     return Add<HStoreKeyed>(elements, checked_key, val, elements_kind,
2787                             STORE_TO_INITIALIZED_ENTRY);
2788   }
2789
2790   DCHECK(access_type == LOAD);
2791   DCHECK(val == NULL);
2792   HLoadKeyed* load = Add<HLoadKeyed>(
2793       elements, checked_key, dependency, elements_kind, load_mode);
2794   if (elements_kind == UINT32_ELEMENTS) {
2795     graph()->RecordUint32Instruction(load);
2796   }
2797   return load;
2798 }
2799
2800
2801 HLoadNamedField* HGraphBuilder::AddLoadMap(HValue* object,
2802                                            HValue* dependency) {
2803   return Add<HLoadNamedField>(object, dependency, HObjectAccess::ForMap());
2804 }
2805
2806
2807 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object,
2808                                                 HValue* dependency) {
2809   return Add<HLoadNamedField>(
2810       object, dependency, HObjectAccess::ForElementsPointer());
2811 }
2812
2813
2814 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(
2815     HValue* array,
2816     HValue* dependency) {
2817   return Add<HLoadNamedField>(
2818       array, dependency, HObjectAccess::ForFixedArrayLength());
2819 }
2820
2821
2822 HLoadNamedField* HGraphBuilder::AddLoadArrayLength(HValue* array,
2823                                                    ElementsKind kind,
2824                                                    HValue* dependency) {
2825   return Add<HLoadNamedField>(
2826       array, dependency, HObjectAccess::ForArrayLength(kind));
2827 }
2828
2829
2830 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) {
2831   HValue* half_old_capacity = AddUncasted<HShr>(old_capacity,
2832                                                 graph_->GetConstant1());
2833
2834   HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity);
2835   new_capacity->ClearFlag(HValue::kCanOverflow);
2836
2837   HValue* min_growth = Add<HConstant>(16);
2838
2839   new_capacity = AddUncasted<HAdd>(new_capacity, min_growth);
2840   new_capacity->ClearFlag(HValue::kCanOverflow);
2841
2842   return new_capacity;
2843 }
2844
2845
2846 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
2847                                                  HValue* elements,
2848                                                  ElementsKind kind,
2849                                                  ElementsKind new_kind,
2850                                                  HValue* length,
2851                                                  HValue* new_capacity) {
2852   Add<HBoundsCheck>(new_capacity, Add<HConstant>(
2853           (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >>
2854           ElementsKindToShiftSize(new_kind)));
2855
2856   HValue* new_elements =
2857       BuildAllocateAndInitializeArray(new_kind, new_capacity);
2858
2859   BuildCopyElements(elements, kind, new_elements,
2860                     new_kind, length, new_capacity);
2861
2862   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
2863                         new_elements);
2864
2865   return new_elements;
2866 }
2867
2868
2869 void HGraphBuilder::BuildFillElementsWithValue(HValue* elements,
2870                                                ElementsKind elements_kind,
2871                                                HValue* from,
2872                                                HValue* to,
2873                                                HValue* value) {
2874   if (to == NULL) {
2875     to = AddLoadFixedArrayLength(elements);
2876   }
2877
2878   // Special loop unfolding case
2879   STATIC_ASSERT(JSArray::kPreallocatedArrayElements <=
2880                 kElementLoopUnrollThreshold);
2881   int initial_capacity = -1;
2882   if (from->IsInteger32Constant() && to->IsInteger32Constant()) {
2883     int constant_from = from->GetInteger32Constant();
2884     int constant_to = to->GetInteger32Constant();
2885
2886     if (constant_from == 0 && constant_to <= kElementLoopUnrollThreshold) {
2887       initial_capacity = constant_to;
2888     }
2889   }
2890
2891   if (initial_capacity >= 0) {
2892     for (int i = 0; i < initial_capacity; i++) {
2893       HInstruction* key = Add<HConstant>(i);
2894       Add<HStoreKeyed>(elements, key, value, elements_kind);
2895     }
2896   } else {
2897     // Carefully loop backwards so that the "from" remains live through the loop
2898     // rather than the to. This often corresponds to keeping length live rather
2899     // then capacity, which helps register allocation, since length is used more
2900     // other than capacity after filling with holes.
2901     LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
2902
2903     HValue* key = builder.BeginBody(to, from, Token::GT);
2904
2905     HValue* adjusted_key = AddUncasted<HSub>(key, graph()->GetConstant1());
2906     adjusted_key->ClearFlag(HValue::kCanOverflow);
2907
2908     Add<HStoreKeyed>(elements, adjusted_key, value, elements_kind);
2909
2910     builder.EndBody();
2911   }
2912 }
2913
2914
2915 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements,
2916                                               ElementsKind elements_kind,
2917                                               HValue* from,
2918                                               HValue* to) {
2919   // Fast elements kinds need to be initialized in case statements below cause a
2920   // garbage collection.
2921
2922   HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
2923                      ? graph()->GetConstantHole()
2924                      : Add<HConstant>(HConstant::kHoleNaN);
2925
2926   // Since we're about to store a hole value, the store instruction below must
2927   // assume an elements kind that supports heap object values.
2928   if (IsFastSmiOrObjectElementsKind(elements_kind)) {
2929     elements_kind = FAST_HOLEY_ELEMENTS;
2930   }
2931
2932   BuildFillElementsWithValue(elements, elements_kind, from, to, hole);
2933 }
2934
2935
2936 void HGraphBuilder::BuildCopyProperties(HValue* from_properties,
2937                                         HValue* to_properties, HValue* length,
2938                                         HValue* capacity) {
2939   ElementsKind kind = FAST_ELEMENTS;
2940
2941   BuildFillElementsWithValue(to_properties, kind, length, capacity,
2942                              graph()->GetConstantUndefined());
2943
2944   LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
2945
2946   HValue* key = builder.BeginBody(length, graph()->GetConstant0(), Token::GT);
2947
2948   key = AddUncasted<HSub>(key, graph()->GetConstant1());
2949   key->ClearFlag(HValue::kCanOverflow);
2950
2951   HValue* element = Add<HLoadKeyed>(from_properties, key, nullptr, kind);
2952
2953   Add<HStoreKeyed>(to_properties, key, element, kind);
2954
2955   builder.EndBody();
2956 }
2957
2958
2959 void HGraphBuilder::BuildCopyElements(HValue* from_elements,
2960                                       ElementsKind from_elements_kind,
2961                                       HValue* to_elements,
2962                                       ElementsKind to_elements_kind,
2963                                       HValue* length,
2964                                       HValue* capacity) {
2965   int constant_capacity = -1;
2966   if (capacity != NULL &&
2967       capacity->IsConstant() &&
2968       HConstant::cast(capacity)->HasInteger32Value()) {
2969     int constant_candidate = HConstant::cast(capacity)->Integer32Value();
2970     if (constant_candidate <= kElementLoopUnrollThreshold) {
2971       constant_capacity = constant_candidate;
2972     }
2973   }
2974
2975   bool pre_fill_with_holes =
2976     IsFastDoubleElementsKind(from_elements_kind) &&
2977     IsFastObjectElementsKind(to_elements_kind);
2978   if (pre_fill_with_holes) {
2979     // If the copy might trigger a GC, make sure that the FixedArray is
2980     // pre-initialized with holes to make sure that it's always in a
2981     // consistent state.
2982     BuildFillElementsWithHole(to_elements, to_elements_kind,
2983                               graph()->GetConstant0(), NULL);
2984   }
2985
2986   if (constant_capacity != -1) {
2987     // Unroll the loop for small elements kinds.
2988     for (int i = 0; i < constant_capacity; i++) {
2989       HValue* key_constant = Add<HConstant>(i);
2990       HInstruction* value = Add<HLoadKeyed>(from_elements, key_constant,
2991                                             nullptr, from_elements_kind);
2992       Add<HStoreKeyed>(to_elements, key_constant, value, to_elements_kind);
2993     }
2994   } else {
2995     if (!pre_fill_with_holes &&
2996         (capacity == NULL || !length->Equals(capacity))) {
2997       BuildFillElementsWithHole(to_elements, to_elements_kind,
2998                                 length, NULL);
2999     }
3000
3001     LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
3002
3003     HValue* key = builder.BeginBody(length, graph()->GetConstant0(),
3004                                     Token::GT);
3005
3006     key = AddUncasted<HSub>(key, graph()->GetConstant1());
3007     key->ClearFlag(HValue::kCanOverflow);
3008
3009     HValue* element = Add<HLoadKeyed>(from_elements, key, nullptr,
3010                                       from_elements_kind, ALLOW_RETURN_HOLE);
3011
3012     ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) &&
3013                          IsFastSmiElementsKind(to_elements_kind))
3014       ? FAST_HOLEY_ELEMENTS : to_elements_kind;
3015
3016     if (IsHoleyElementsKind(from_elements_kind) &&
3017         from_elements_kind != to_elements_kind) {
3018       IfBuilder if_hole(this);
3019       if_hole.If<HCompareHoleAndBranch>(element);
3020       if_hole.Then();
3021       HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind)
3022                                      ? Add<HConstant>(HConstant::kHoleNaN)
3023                                      : graph()->GetConstantHole();
3024       Add<HStoreKeyed>(to_elements, key, hole_constant, kind);
3025       if_hole.Else();
3026       HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind);
3027       store->SetFlag(HValue::kAllowUndefinedAsNaN);
3028       if_hole.End();
3029     } else {
3030       HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind);
3031       store->SetFlag(HValue::kAllowUndefinedAsNaN);
3032     }
3033
3034     builder.EndBody();
3035   }
3036
3037   Counters* counters = isolate()->counters();
3038   AddIncrementCounter(counters->inlined_copied_elements());
3039 }
3040
3041
3042 HValue* HGraphBuilder::BuildCloneShallowArrayCow(HValue* boilerplate,
3043                                                  HValue* allocation_site,
3044                                                  AllocationSiteMode mode,
3045                                                  ElementsKind kind) {
3046   HAllocate* array = AllocateJSArrayObject(mode);
3047
3048   HValue* map = AddLoadMap(boilerplate);
3049   HValue* elements = AddLoadElements(boilerplate);
3050   HValue* length = AddLoadArrayLength(boilerplate, kind);
3051
3052   BuildJSArrayHeader(array,
3053                      map,
3054                      elements,
3055                      mode,
3056                      FAST_ELEMENTS,
3057                      allocation_site,
3058                      length);
3059   return array;
3060 }
3061
3062
3063 HValue* HGraphBuilder::BuildCloneShallowArrayEmpty(HValue* boilerplate,
3064                                                    HValue* allocation_site,
3065                                                    AllocationSiteMode mode) {
3066   HAllocate* array = AllocateJSArrayObject(mode);
3067
3068   HValue* map = AddLoadMap(boilerplate);
3069
3070   BuildJSArrayHeader(array,
3071                      map,
3072                      NULL,  // set elements to empty fixed array
3073                      mode,
3074                      FAST_ELEMENTS,
3075                      allocation_site,
3076                      graph()->GetConstant0());
3077   return array;
3078 }
3079
3080
3081 HValue* HGraphBuilder::BuildCloneShallowArrayNonEmpty(HValue* boilerplate,
3082                                                       HValue* allocation_site,
3083                                                       AllocationSiteMode mode,
3084                                                       ElementsKind kind) {
3085   HValue* boilerplate_elements = AddLoadElements(boilerplate);
3086   HValue* capacity = AddLoadFixedArrayLength(boilerplate_elements);
3087
3088   // Generate size calculation code here in order to make it dominate
3089   // the JSArray allocation.
3090   HValue* elements_size = BuildCalculateElementsSize(kind, capacity);
3091
3092   // Create empty JSArray object for now, store elimination should remove
3093   // redundant initialization of elements and length fields and at the same
3094   // time the object will be fully prepared for GC if it happens during
3095   // elements allocation.
3096   HValue* result = BuildCloneShallowArrayEmpty(
3097       boilerplate, allocation_site, mode);
3098
3099   HAllocate* elements = BuildAllocateElements(kind, elements_size);
3100
3101   // This function implicitly relies on the fact that the
3102   // FastCloneShallowArrayStub is called only for literals shorter than
3103   // JSObject::kInitialMaxFastElementArray.
3104   // Can't add HBoundsCheck here because otherwise the stub will eager a frame.
3105   HConstant* size_upper_bound = EstablishElementsAllocationSize(
3106       kind, JSObject::kInitialMaxFastElementArray);
3107   elements->set_size_upper_bound(size_upper_bound);
3108
3109   Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(), elements);
3110
3111   // The allocation for the cloned array above causes register pressure on
3112   // machines with low register counts. Force a reload of the boilerplate
3113   // elements here to free up a register for the allocation to avoid unnecessary
3114   // spillage.
3115   boilerplate_elements = AddLoadElements(boilerplate);
3116   boilerplate_elements->SetFlag(HValue::kCantBeReplaced);
3117
3118   // Copy the elements array header.
3119   for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) {
3120     HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i);
3121     Add<HStoreNamedField>(
3122         elements, access,
3123         Add<HLoadNamedField>(boilerplate_elements, nullptr, access));
3124   }
3125
3126   // And the result of the length
3127   HValue* length = AddLoadArrayLength(boilerplate, kind);
3128   Add<HStoreNamedField>(result, HObjectAccess::ForArrayLength(kind), length);
3129
3130   BuildCopyElements(boilerplate_elements, kind, elements,
3131                     kind, length, NULL);
3132   return result;
3133 }
3134
3135
3136 void HGraphBuilder::BuildCompareNil(HValue* value, Type* type,
3137                                     HIfContinuation* continuation,
3138                                     MapEmbedding map_embedding) {
3139   IfBuilder if_nil(this);
3140   bool some_case_handled = false;
3141   bool some_case_missing = false;
3142
3143   if (type->Maybe(Type::Null())) {
3144     if (some_case_handled) if_nil.Or();
3145     if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull());
3146     some_case_handled = true;
3147   } else {
3148     some_case_missing = true;
3149   }
3150
3151   if (type->Maybe(Type::Undefined())) {
3152     if (some_case_handled) if_nil.Or();
3153     if_nil.If<HCompareObjectEqAndBranch>(value,
3154                                          graph()->GetConstantUndefined());
3155     some_case_handled = true;
3156   } else {
3157     some_case_missing = true;
3158   }
3159
3160   if (type->Maybe(Type::Undetectable())) {
3161     if (some_case_handled) if_nil.Or();
3162     if_nil.If<HIsUndetectableAndBranch>(value);
3163     some_case_handled = true;
3164   } else {
3165     some_case_missing = true;
3166   }
3167
3168   if (some_case_missing) {
3169     if_nil.Then();
3170     if_nil.Else();
3171     if (type->NumClasses() == 1) {
3172       BuildCheckHeapObject(value);
3173       // For ICs, the map checked below is a sentinel map that gets replaced by
3174       // the monomorphic map when the code is used as a template to generate a
3175       // new IC. For optimized functions, there is no sentinel map, the map
3176       // emitted below is the actual monomorphic map.
3177       if (map_embedding == kEmbedMapsViaWeakCells) {
3178         HValue* cell =
3179             Add<HConstant>(Map::WeakCellForMap(type->Classes().Current()));
3180         HValue* expected_map = Add<HLoadNamedField>(
3181             cell, nullptr, HObjectAccess::ForWeakCellValue());
3182         HValue* map =
3183             Add<HLoadNamedField>(value, nullptr, HObjectAccess::ForMap());
3184         IfBuilder map_check(this);
3185         map_check.IfNot<HCompareObjectEqAndBranch>(expected_map, map);
3186         map_check.ThenDeopt(Deoptimizer::kUnknownMap);
3187         map_check.End();
3188       } else {
3189         DCHECK(map_embedding == kEmbedMapsDirectly);
3190         Add<HCheckMaps>(value, type->Classes().Current());
3191       }
3192     } else {
3193       if_nil.Deopt(Deoptimizer::kTooManyUndetectableTypes);
3194     }
3195   }
3196
3197   if_nil.CaptureContinuation(continuation);
3198 }
3199
3200
3201 void HGraphBuilder::BuildCreateAllocationMemento(
3202     HValue* previous_object,
3203     HValue* previous_object_size,
3204     HValue* allocation_site) {
3205   DCHECK(allocation_site != NULL);
3206   HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>(
3207       previous_object, previous_object_size, HType::HeapObject());
3208   AddStoreMapConstant(
3209       allocation_memento, isolate()->factory()->allocation_memento_map());
3210   Add<HStoreNamedField>(
3211       allocation_memento,
3212       HObjectAccess::ForAllocationMementoSite(),
3213       allocation_site);
3214   if (FLAG_allocation_site_pretenuring) {
3215     HValue* memento_create_count =
3216         Add<HLoadNamedField>(allocation_site, nullptr,
3217                              HObjectAccess::ForAllocationSiteOffset(
3218                                  AllocationSite::kPretenureCreateCountOffset));
3219     memento_create_count = AddUncasted<HAdd>(
3220         memento_create_count, graph()->GetConstant1());
3221     // This smi value is reset to zero after every gc, overflow isn't a problem
3222     // since the counter is bounded by the new space size.
3223     memento_create_count->ClearFlag(HValue::kCanOverflow);
3224     Add<HStoreNamedField>(
3225         allocation_site, HObjectAccess::ForAllocationSiteOffset(
3226             AllocationSite::kPretenureCreateCountOffset), memento_create_count);
3227   }
3228 }
3229
3230
3231 HInstruction* HGraphBuilder::BuildGetNativeContext() {
3232   // Get the global object, then the native context
3233   HValue* global_object = Add<HLoadNamedField>(
3234       context(), nullptr,
3235       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
3236   return Add<HLoadNamedField>(global_object, nullptr,
3237                               HObjectAccess::ForObservableJSObjectOffset(
3238                                   GlobalObject::kNativeContextOffset));
3239 }
3240
3241
3242 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* closure) {
3243   // Get the global object, then the native context
3244   HInstruction* context = Add<HLoadNamedField>(
3245       closure, nullptr, HObjectAccess::ForFunctionContextPointer());
3246   HInstruction* global_object = Add<HLoadNamedField>(
3247       context, nullptr,
3248       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
3249   HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
3250       GlobalObject::kNativeContextOffset);
3251   return Add<HLoadNamedField>(global_object, nullptr, access);
3252 }
3253
3254
3255 HInstruction* HGraphBuilder::BuildGetScriptContext(int context_index) {
3256   HValue* native_context = BuildGetNativeContext();
3257   HValue* script_context_table = Add<HLoadNamedField>(
3258       native_context, nullptr,
3259       HObjectAccess::ForContextSlot(Context::SCRIPT_CONTEXT_TABLE_INDEX));
3260   return Add<HLoadNamedField>(script_context_table, nullptr,
3261                               HObjectAccess::ForScriptContext(context_index));
3262 }
3263
3264
3265 HValue* HGraphBuilder::BuildGetParentContext(HValue* depth, int depth_value) {
3266   HValue* script_context = context();
3267   if (depth != NULL) {
3268     HValue* zero = graph()->GetConstant0();
3269
3270     Push(script_context);
3271     Push(depth);
3272
3273     LoopBuilder loop(this);
3274     loop.BeginBody(2);  // Drop script_context and depth from last environment
3275                         // to appease live range building without simulates.
3276     depth = Pop();
3277     script_context = Pop();
3278
3279     script_context = Add<HLoadNamedField>(
3280         script_context, nullptr,
3281         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
3282     depth = AddUncasted<HSub>(depth, graph()->GetConstant1());
3283     depth->ClearFlag(HValue::kCanOverflow);
3284
3285     IfBuilder if_break(this);
3286     if_break.If<HCompareNumericAndBranch, HValue*>(depth, zero, Token::EQ);
3287     if_break.Then();
3288     {
3289       Push(script_context);  // The result.
3290       loop.Break();
3291     }
3292     if_break.Else();
3293     {
3294       Push(script_context);
3295       Push(depth);
3296     }
3297     loop.EndBody();
3298     if_break.End();
3299
3300     script_context = Pop();
3301   } else if (depth_value > 0) {
3302     // Unroll the above loop.
3303     for (int i = 0; i < depth_value; i++) {
3304       script_context = Add<HLoadNamedField>(
3305           script_context, nullptr,
3306           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
3307     }
3308   }
3309   return script_context;
3310 }
3311
3312
3313 HInstruction* HGraphBuilder::BuildGetArrayFunction() {
3314   HInstruction* native_context = BuildGetNativeContext();
3315   HInstruction* index =
3316       Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX));
3317   return Add<HLoadKeyed>(native_context, index, nullptr, FAST_ELEMENTS);
3318 }
3319
3320
3321 HValue* HGraphBuilder::BuildArrayBufferViewFieldAccessor(HValue* object,
3322                                                          HValue* checked_object,
3323                                                          FieldIndex index) {
3324   NoObservableSideEffectsScope scope(this);
3325   HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
3326       index.offset(), Representation::Tagged());
3327   HInstruction* buffer = Add<HLoadNamedField>(
3328       object, checked_object, HObjectAccess::ForJSArrayBufferViewBuffer());
3329   HInstruction* field = Add<HLoadNamedField>(object, checked_object, access);
3330
3331   HInstruction* flags = Add<HLoadNamedField>(
3332       buffer, nullptr, HObjectAccess::ForJSArrayBufferBitField());
3333   HValue* was_neutered_mask =
3334       Add<HConstant>(1 << JSArrayBuffer::WasNeutered::kShift);
3335   HValue* was_neutered_test =
3336       AddUncasted<HBitwise>(Token::BIT_AND, flags, was_neutered_mask);
3337
3338   IfBuilder if_was_neutered(this);
3339   if_was_neutered.If<HCompareNumericAndBranch>(
3340       was_neutered_test, graph()->GetConstant0(), Token::NE);
3341   if_was_neutered.Then();
3342   Push(graph()->GetConstant0());
3343   if_was_neutered.Else();
3344   Push(field);
3345   if_was_neutered.End();
3346
3347   return Pop();
3348 }
3349
3350
3351 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
3352     ElementsKind kind,
3353     HValue* allocation_site_payload,
3354     HValue* constructor_function,
3355     AllocationSiteOverrideMode override_mode) :
3356         builder_(builder),
3357         kind_(kind),
3358         allocation_site_payload_(allocation_site_payload),
3359         constructor_function_(constructor_function) {
3360   DCHECK(!allocation_site_payload->IsConstant() ||
3361          HConstant::cast(allocation_site_payload)->handle(
3362              builder_->isolate())->IsAllocationSite());
3363   mode_ = override_mode == DISABLE_ALLOCATION_SITES
3364       ? DONT_TRACK_ALLOCATION_SITE
3365       : AllocationSite::GetMode(kind);
3366 }
3367
3368
3369 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
3370                                               ElementsKind kind,
3371                                               HValue* constructor_function) :
3372     builder_(builder),
3373     kind_(kind),
3374     mode_(DONT_TRACK_ALLOCATION_SITE),
3375     allocation_site_payload_(NULL),
3376     constructor_function_(constructor_function) {
3377 }
3378
3379
3380 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
3381   if (!builder()->top_info()->IsStub()) {
3382     // A constant map is fine.
3383     Handle<Map> map(builder()->isolate()->get_initial_js_array_map(kind_),
3384                     builder()->isolate());
3385     return builder()->Add<HConstant>(map);
3386   }
3387
3388   if (constructor_function_ != NULL && kind_ == GetInitialFastElementsKind()) {
3389     // No need for a context lookup if the kind_ matches the initial
3390     // map, because we can just load the map in that case.
3391     HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
3392     return builder()->Add<HLoadNamedField>(constructor_function_, nullptr,
3393                                            access);
3394   }
3395
3396   // TODO(mvstanton): we should always have a constructor function if we
3397   // are creating a stub.
3398   HInstruction* native_context = constructor_function_ != NULL
3399       ? builder()->BuildGetNativeContext(constructor_function_)
3400       : builder()->BuildGetNativeContext();
3401
3402   HInstruction* index = builder()->Add<HConstant>(
3403       static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX));
3404
3405   HInstruction* map_array =
3406       builder()->Add<HLoadKeyed>(native_context, index, nullptr, FAST_ELEMENTS);
3407
3408   HInstruction* kind_index = builder()->Add<HConstant>(kind_);
3409
3410   return builder()->Add<HLoadKeyed>(map_array, kind_index, nullptr,
3411                                     FAST_ELEMENTS);
3412 }
3413
3414
3415 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
3416   // Find the map near the constructor function
3417   HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
3418   return builder()->Add<HLoadNamedField>(constructor_function_, nullptr,
3419                                          access);
3420 }
3421
3422
3423 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() {
3424   HConstant* capacity = builder()->Add<HConstant>(initial_capacity());
3425   return AllocateArray(capacity,
3426                        capacity,
3427                        builder()->graph()->GetConstant0());
3428 }
3429
3430
3431 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
3432     HValue* capacity,
3433     HConstant* capacity_upper_bound,
3434     HValue* length_field,
3435     FillMode fill_mode) {
3436   return AllocateArray(capacity,
3437                        capacity_upper_bound->GetInteger32Constant(),
3438                        length_field,
3439                        fill_mode);
3440 }
3441
3442
3443 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
3444     HValue* capacity,
3445     int capacity_upper_bound,
3446     HValue* length_field,
3447     FillMode fill_mode) {
3448   HConstant* elememts_size_upper_bound = capacity->IsInteger32Constant()
3449       ? HConstant::cast(capacity)
3450       : builder()->EstablishElementsAllocationSize(kind_, capacity_upper_bound);
3451
3452   HAllocate* array = AllocateArray(capacity, length_field, fill_mode);
3453   if (!elements_location_->has_size_upper_bound()) {
3454     elements_location_->set_size_upper_bound(elememts_size_upper_bound);
3455   }
3456   return array;
3457 }
3458
3459
3460 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
3461     HValue* capacity,
3462     HValue* length_field,
3463     FillMode fill_mode) {
3464   // These HForceRepresentations are because we store these as fields in the
3465   // objects we construct, and an int32-to-smi HChange could deopt. Accept
3466   // the deopt possibility now, before allocation occurs.
3467   capacity =
3468       builder()->AddUncasted<HForceRepresentation>(capacity,
3469                                                    Representation::Smi());
3470   length_field =
3471       builder()->AddUncasted<HForceRepresentation>(length_field,
3472                                                    Representation::Smi());
3473
3474   // Generate size calculation code here in order to make it dominate
3475   // the JSArray allocation.
3476   HValue* elements_size =
3477       builder()->BuildCalculateElementsSize(kind_, capacity);
3478
3479   // Allocate (dealing with failure appropriately)
3480   HAllocate* array_object = builder()->AllocateJSArrayObject(mode_);
3481
3482   // Fill in the fields: map, properties, length
3483   HValue* map;
3484   if (allocation_site_payload_ == NULL) {
3485     map = EmitInternalMapCode();
3486   } else {
3487     map = EmitMapCode();
3488   }
3489
3490   builder()->BuildJSArrayHeader(array_object,
3491                                 map,
3492                                 NULL,  // set elements to empty fixed array
3493                                 mode_,
3494                                 kind_,
3495                                 allocation_site_payload_,
3496                                 length_field);
3497
3498   // Allocate and initialize the elements
3499   elements_location_ = builder()->BuildAllocateElements(kind_, elements_size);
3500
3501   builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity);
3502
3503   // Set the elements
3504   builder()->Add<HStoreNamedField>(
3505       array_object, HObjectAccess::ForElementsPointer(), elements_location_);
3506
3507   if (fill_mode == FILL_WITH_HOLE) {
3508     builder()->BuildFillElementsWithHole(elements_location_, kind_,
3509                                          graph()->GetConstant0(), capacity);
3510   }
3511
3512   return array_object;
3513 }
3514
3515
3516 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin) {
3517   HValue* global_object = Add<HLoadNamedField>(
3518       context(), nullptr,
3519       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
3520   HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
3521       GlobalObject::kBuiltinsOffset);
3522   HValue* builtins = Add<HLoadNamedField>(global_object, nullptr, access);
3523   HObjectAccess function_access = HObjectAccess::ForObservableJSObjectOffset(
3524           JSBuiltinsObject::OffsetOfFunctionWithId(builtin));
3525   return Add<HLoadNamedField>(builtins, nullptr, function_access);
3526 }
3527
3528
3529 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
3530     : HGraphBuilder(info),
3531       function_state_(NULL),
3532       initial_function_state_(this, info, NORMAL_RETURN, 0),
3533       ast_context_(NULL),
3534       break_scope_(NULL),
3535       inlined_count_(0),
3536       globals_(10, info->zone()),
3537       osr_(new(info->zone()) HOsrBuilder(this)) {
3538   // This is not initialized in the initializer list because the
3539   // constructor for the initial state relies on function_state_ == NULL
3540   // to know it's the initial state.
3541   function_state_ = &initial_function_state_;
3542   InitializeAstVisitor(info->isolate(), info->zone());
3543   if (top_info()->is_tracking_positions()) {
3544     SetSourcePosition(info->shared_info()->start_position());
3545   }
3546 }
3547
3548
3549 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first,
3550                                                 HBasicBlock* second,
3551                                                 BailoutId join_id) {
3552   if (first == NULL) {
3553     return second;
3554   } else if (second == NULL) {
3555     return first;
3556   } else {
3557     HBasicBlock* join_block = graph()->CreateBasicBlock();
3558     Goto(first, join_block);
3559     Goto(second, join_block);
3560     join_block->SetJoinId(join_id);
3561     return join_block;
3562   }
3563 }
3564
3565
3566 HBasicBlock* HOptimizedGraphBuilder::JoinContinue(IterationStatement* statement,
3567                                                   HBasicBlock* exit_block,
3568                                                   HBasicBlock* continue_block) {
3569   if (continue_block != NULL) {
3570     if (exit_block != NULL) Goto(exit_block, continue_block);
3571     continue_block->SetJoinId(statement->ContinueId());
3572     return continue_block;
3573   }
3574   return exit_block;
3575 }
3576
3577
3578 HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement,
3579                                                 HBasicBlock* loop_entry,
3580                                                 HBasicBlock* body_exit,
3581                                                 HBasicBlock* loop_successor,
3582                                                 HBasicBlock* break_block) {
3583   if (body_exit != NULL) Goto(body_exit, loop_entry);
3584   loop_entry->PostProcessLoopHeader(statement);
3585   if (break_block != NULL) {
3586     if (loop_successor != NULL) Goto(loop_successor, break_block);
3587     break_block->SetJoinId(statement->ExitId());
3588     return break_block;
3589   }
3590   return loop_successor;
3591 }
3592
3593
3594 // Build a new loop header block and set it as the current block.
3595 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() {
3596   HBasicBlock* loop_entry = CreateLoopHeaderBlock();
3597   Goto(loop_entry);
3598   set_current_block(loop_entry);
3599   return loop_entry;
3600 }
3601
3602
3603 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry(
3604     IterationStatement* statement) {
3605   HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement)
3606       ? osr()->BuildOsrLoopEntry(statement)
3607       : BuildLoopEntry();
3608   return loop_entry;
3609 }
3610
3611
3612 void HBasicBlock::FinishExit(HControlInstruction* instruction,
3613                              SourcePosition position) {
3614   Finish(instruction, position);
3615   ClearEnvironment();
3616 }
3617
3618
3619 std::ostream& operator<<(std::ostream& os, const HBasicBlock& b) {
3620   return os << "B" << b.block_id();
3621 }
3622
3623
3624 HGraph::HGraph(CompilationInfo* info)
3625     : isolate_(info->isolate()),
3626       next_block_id_(0),
3627       entry_block_(NULL),
3628       blocks_(8, info->zone()),
3629       values_(16, info->zone()),
3630       phi_list_(NULL),
3631       uint32_instructions_(NULL),
3632       osr_(NULL),
3633       info_(info),
3634       zone_(info->zone()),
3635       is_recursive_(false),
3636       use_optimistic_licm_(false),
3637       depends_on_empty_array_proto_elements_(false),
3638       type_change_checksum_(0),
3639       maximum_environment_size_(0),
3640       no_side_effects_scope_count_(0),
3641       disallow_adding_new_values_(false) {
3642   if (info->IsStub()) {
3643     CallInterfaceDescriptor descriptor =
3644         info->code_stub()->GetCallInterfaceDescriptor();
3645     start_environment_ =
3646         new (zone_) HEnvironment(zone_, descriptor.GetRegisterParameterCount());
3647   } else {
3648     if (info->is_tracking_positions()) {
3649       info->TraceInlinedFunction(info->shared_info(), SourcePosition::Unknown(),
3650                                  InlinedFunctionInfo::kNoParentId);
3651     }
3652     start_environment_ =
3653         new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
3654   }
3655   start_environment_->set_ast_id(BailoutId::FunctionEntry());
3656   entry_block_ = CreateBasicBlock();
3657   entry_block_->SetInitialEnvironment(start_environment_);
3658 }
3659
3660
3661 HBasicBlock* HGraph::CreateBasicBlock() {
3662   HBasicBlock* result = new(zone()) HBasicBlock(this);
3663   blocks_.Add(result, zone());
3664   return result;
3665 }
3666
3667
3668 void HGraph::FinalizeUniqueness() {
3669   DisallowHeapAllocation no_gc;
3670   for (int i = 0; i < blocks()->length(); ++i) {
3671     for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
3672       it.Current()->FinalizeUniqueness();
3673     }
3674   }
3675 }
3676
3677
3678 int HGraph::SourcePositionToScriptPosition(SourcePosition pos) {
3679   return (FLAG_hydrogen_track_positions && !pos.IsUnknown())
3680              ? info()->start_position_for(pos.inlining_id()) + pos.position()
3681              : pos.raw();
3682 }
3683
3684
3685 // Block ordering was implemented with two mutually recursive methods,
3686 // HGraph::Postorder and HGraph::PostorderLoopBlocks.
3687 // The recursion could lead to stack overflow so the algorithm has been
3688 // implemented iteratively.
3689 // At a high level the algorithm looks like this:
3690 //
3691 // Postorder(block, loop_header) : {
3692 //   if (block has already been visited or is of another loop) return;
3693 //   mark block as visited;
3694 //   if (block is a loop header) {
3695 //     VisitLoopMembers(block, loop_header);
3696 //     VisitSuccessorsOfLoopHeader(block);
3697 //   } else {
3698 //     VisitSuccessors(block)
3699 //   }
3700 //   put block in result list;
3701 // }
3702 //
3703 // VisitLoopMembers(block, outer_loop_header) {
3704 //   foreach (block b in block loop members) {
3705 //     VisitSuccessorsOfLoopMember(b, outer_loop_header);
3706 //     if (b is loop header) VisitLoopMembers(b);
3707 //   }
3708 // }
3709 //
3710 // VisitSuccessorsOfLoopMember(block, outer_loop_header) {
3711 //   foreach (block b in block successors) Postorder(b, outer_loop_header)
3712 // }
3713 //
3714 // VisitSuccessorsOfLoopHeader(block) {
3715 //   foreach (block b in block successors) Postorder(b, block)
3716 // }
3717 //
3718 // VisitSuccessors(block, loop_header) {
3719 //   foreach (block b in block successors) Postorder(b, loop_header)
3720 // }
3721 //
3722 // The ordering is started calling Postorder(entry, NULL).
3723 //
3724 // Each instance of PostorderProcessor represents the "stack frame" of the
3725 // recursion, and particularly keeps the state of the loop (iteration) of the
3726 // "Visit..." function it represents.
3727 // To recycle memory we keep all the frames in a double linked list but
3728 // this means that we cannot use constructors to initialize the frames.
3729 //
3730 class PostorderProcessor : public ZoneObject {
3731  public:
3732   // Back link (towards the stack bottom).
3733   PostorderProcessor* parent() {return father_; }
3734   // Forward link (towards the stack top).
3735   PostorderProcessor* child() {return child_; }
3736   HBasicBlock* block() { return block_; }
3737   HLoopInformation* loop() { return loop_; }
3738   HBasicBlock* loop_header() { return loop_header_; }
3739
3740   static PostorderProcessor* CreateEntryProcessor(Zone* zone,
3741                                                   HBasicBlock* block) {
3742     PostorderProcessor* result = new(zone) PostorderProcessor(NULL);
3743     return result->SetupSuccessors(zone, block, NULL);
3744   }
3745
3746   PostorderProcessor* PerformStep(Zone* zone,
3747                                   ZoneList<HBasicBlock*>* order) {
3748     PostorderProcessor* next =
3749         PerformNonBacktrackingStep(zone, order);
3750     if (next != NULL) {
3751       return next;
3752     } else {
3753       return Backtrack(zone, order);
3754     }
3755   }
3756
3757  private:
3758   explicit PostorderProcessor(PostorderProcessor* father)
3759       : father_(father), child_(NULL), successor_iterator(NULL) { }
3760
3761   // Each enum value states the cycle whose state is kept by this instance.
3762   enum LoopKind {
3763     NONE,
3764     SUCCESSORS,
3765     SUCCESSORS_OF_LOOP_HEADER,
3766     LOOP_MEMBERS,
3767     SUCCESSORS_OF_LOOP_MEMBER
3768   };
3769
3770   // Each "Setup..." method is like a constructor for a cycle state.
3771   PostorderProcessor* SetupSuccessors(Zone* zone,
3772                                       HBasicBlock* block,
3773                                       HBasicBlock* loop_header) {
3774     if (block == NULL || block->IsOrdered() ||
3775         block->parent_loop_header() != loop_header) {
3776       kind_ = NONE;
3777       block_ = NULL;
3778       loop_ = NULL;
3779       loop_header_ = NULL;
3780       return this;
3781     } else {
3782       block_ = block;
3783       loop_ = NULL;
3784       block->MarkAsOrdered();
3785
3786       if (block->IsLoopHeader()) {
3787         kind_ = SUCCESSORS_OF_LOOP_HEADER;
3788         loop_header_ = block;
3789         InitializeSuccessors();
3790         PostorderProcessor* result = Push(zone);
3791         return result->SetupLoopMembers(zone, block, block->loop_information(),
3792                                         loop_header);
3793       } else {
3794         DCHECK(block->IsFinished());
3795         kind_ = SUCCESSORS;
3796         loop_header_ = loop_header;
3797         InitializeSuccessors();
3798         return this;
3799       }
3800     }
3801   }
3802
3803   PostorderProcessor* SetupLoopMembers(Zone* zone,
3804                                        HBasicBlock* block,
3805                                        HLoopInformation* loop,
3806                                        HBasicBlock* loop_header) {
3807     kind_ = LOOP_MEMBERS;
3808     block_ = block;
3809     loop_ = loop;
3810     loop_header_ = loop_header;
3811     InitializeLoopMembers();
3812     return this;
3813   }
3814
3815   PostorderProcessor* SetupSuccessorsOfLoopMember(
3816       HBasicBlock* block,
3817       HLoopInformation* loop,
3818       HBasicBlock* loop_header) {
3819     kind_ = SUCCESSORS_OF_LOOP_MEMBER;
3820     block_ = block;
3821     loop_ = loop;
3822     loop_header_ = loop_header;
3823     InitializeSuccessors();
3824     return this;
3825   }
3826
3827   // This method "allocates" a new stack frame.
3828   PostorderProcessor* Push(Zone* zone) {
3829     if (child_ == NULL) {
3830       child_ = new(zone) PostorderProcessor(this);
3831     }
3832     return child_;
3833   }
3834
3835   void ClosePostorder(ZoneList<HBasicBlock*>* order, Zone* zone) {
3836     DCHECK(block_->end()->FirstSuccessor() == NULL ||
3837            order->Contains(block_->end()->FirstSuccessor()) ||
3838            block_->end()->FirstSuccessor()->IsLoopHeader());
3839     DCHECK(block_->end()->SecondSuccessor() == NULL ||
3840            order->Contains(block_->end()->SecondSuccessor()) ||
3841            block_->end()->SecondSuccessor()->IsLoopHeader());
3842     order->Add(block_, zone);
3843   }
3844
3845   // This method is the basic block to walk up the stack.
3846   PostorderProcessor* Pop(Zone* zone,
3847                           ZoneList<HBasicBlock*>* order) {
3848     switch (kind_) {
3849       case SUCCESSORS:
3850       case SUCCESSORS_OF_LOOP_HEADER:
3851         ClosePostorder(order, zone);
3852         return father_;
3853       case LOOP_MEMBERS:
3854         return father_;
3855       case SUCCESSORS_OF_LOOP_MEMBER:
3856         if (block()->IsLoopHeader() && block() != loop_->loop_header()) {
3857           // In this case we need to perform a LOOP_MEMBERS cycle so we
3858           // initialize it and return this instead of father.
3859           return SetupLoopMembers(zone, block(),
3860                                   block()->loop_information(), loop_header_);
3861         } else {
3862           return father_;
3863         }
3864       case NONE:
3865         return father_;
3866     }
3867     UNREACHABLE();
3868     return NULL;
3869   }
3870
3871   // Walks up the stack.
3872   PostorderProcessor* Backtrack(Zone* zone,
3873                                 ZoneList<HBasicBlock*>* order) {
3874     PostorderProcessor* parent = Pop(zone, order);
3875     while (parent != NULL) {
3876       PostorderProcessor* next =
3877           parent->PerformNonBacktrackingStep(zone, order);
3878       if (next != NULL) {
3879         return next;
3880       } else {
3881         parent = parent->Pop(zone, order);
3882       }
3883     }
3884     return NULL;
3885   }
3886
3887   PostorderProcessor* PerformNonBacktrackingStep(
3888       Zone* zone,
3889       ZoneList<HBasicBlock*>* order) {
3890     HBasicBlock* next_block;
3891     switch (kind_) {
3892       case SUCCESSORS:
3893         next_block = AdvanceSuccessors();
3894         if (next_block != NULL) {
3895           PostorderProcessor* result = Push(zone);
3896           return result->SetupSuccessors(zone, next_block, loop_header_);
3897         }
3898         break;
3899       case SUCCESSORS_OF_LOOP_HEADER:
3900         next_block = AdvanceSuccessors();
3901         if (next_block != NULL) {
3902           PostorderProcessor* result = Push(zone);
3903           return result->SetupSuccessors(zone, next_block, block());
3904         }
3905         break;
3906       case LOOP_MEMBERS:
3907         next_block = AdvanceLoopMembers();
3908         if (next_block != NULL) {
3909           PostorderProcessor* result = Push(zone);
3910           return result->SetupSuccessorsOfLoopMember(next_block,
3911                                                      loop_, loop_header_);
3912         }
3913         break;
3914       case SUCCESSORS_OF_LOOP_MEMBER:
3915         next_block = AdvanceSuccessors();
3916         if (next_block != NULL) {
3917           PostorderProcessor* result = Push(zone);
3918           return result->SetupSuccessors(zone, next_block, loop_header_);
3919         }
3920         break;
3921       case NONE:
3922         return NULL;
3923     }
3924     return NULL;
3925   }
3926
3927   // The following two methods implement a "foreach b in successors" cycle.
3928   void InitializeSuccessors() {
3929     loop_index = 0;
3930     loop_length = 0;
3931     successor_iterator = HSuccessorIterator(block_->end());
3932   }
3933
3934   HBasicBlock* AdvanceSuccessors() {
3935     if (!successor_iterator.Done()) {
3936       HBasicBlock* result = successor_iterator.Current();
3937       successor_iterator.Advance();
3938       return result;
3939     }
3940     return NULL;
3941   }
3942
3943   // The following two methods implement a "foreach b in loop members" cycle.
3944   void InitializeLoopMembers() {
3945     loop_index = 0;
3946     loop_length = loop_->blocks()->length();
3947   }
3948
3949   HBasicBlock* AdvanceLoopMembers() {
3950     if (loop_index < loop_length) {
3951       HBasicBlock* result = loop_->blocks()->at(loop_index);
3952       loop_index++;
3953       return result;
3954     } else {
3955       return NULL;
3956     }
3957   }
3958
3959   LoopKind kind_;
3960   PostorderProcessor* father_;
3961   PostorderProcessor* child_;
3962   HLoopInformation* loop_;
3963   HBasicBlock* block_;
3964   HBasicBlock* loop_header_;
3965   int loop_index;
3966   int loop_length;
3967   HSuccessorIterator successor_iterator;
3968 };
3969
3970
3971 void HGraph::OrderBlocks() {
3972   CompilationPhase phase("H_Block ordering", info());
3973
3974 #ifdef DEBUG
3975   // Initially the blocks must not be ordered.
3976   for (int i = 0; i < blocks_.length(); ++i) {
3977     DCHECK(!blocks_[i]->IsOrdered());
3978   }
3979 #endif
3980
3981   PostorderProcessor* postorder =
3982       PostorderProcessor::CreateEntryProcessor(zone(), blocks_[0]);
3983   blocks_.Rewind(0);
3984   while (postorder) {
3985     postorder = postorder->PerformStep(zone(), &blocks_);
3986   }
3987
3988 #ifdef DEBUG
3989   // Now all blocks must be marked as ordered.
3990   for (int i = 0; i < blocks_.length(); ++i) {
3991     DCHECK(blocks_[i]->IsOrdered());
3992   }
3993 #endif
3994
3995   // Reverse block list and assign block IDs.
3996   for (int i = 0, j = blocks_.length(); --j >= i; ++i) {
3997     HBasicBlock* bi = blocks_[i];
3998     HBasicBlock* bj = blocks_[j];
3999     bi->set_block_id(j);
4000     bj->set_block_id(i);
4001     blocks_[i] = bj;
4002     blocks_[j] = bi;
4003   }
4004 }
4005
4006
4007 void HGraph::AssignDominators() {
4008   HPhase phase("H_Assign dominators", this);
4009   for (int i = 0; i < blocks_.length(); ++i) {
4010     HBasicBlock* block = blocks_[i];
4011     if (block->IsLoopHeader()) {
4012       // Only the first predecessor of a loop header is from outside the loop.
4013       // All others are back edges, and thus cannot dominate the loop header.
4014       block->AssignCommonDominator(block->predecessors()->first());
4015       block->AssignLoopSuccessorDominators();
4016     } else {
4017       for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) {
4018         blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
4019       }
4020     }
4021   }
4022 }
4023
4024
4025 bool HGraph::CheckArgumentsPhiUses() {
4026   int block_count = blocks_.length();
4027   for (int i = 0; i < block_count; ++i) {
4028     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
4029       HPhi* phi = blocks_[i]->phis()->at(j);
4030       // We don't support phi uses of arguments for now.
4031       if (phi->CheckFlag(HValue::kIsArguments)) return false;
4032     }
4033   }
4034   return true;
4035 }
4036
4037
4038 bool HGraph::CheckConstPhiUses() {
4039   int block_count = blocks_.length();
4040   for (int i = 0; i < block_count; ++i) {
4041     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
4042       HPhi* phi = blocks_[i]->phis()->at(j);
4043       // Check for the hole value (from an uninitialized const).
4044       for (int k = 0; k < phi->OperandCount(); k++) {
4045         if (phi->OperandAt(k) == GetConstantHole()) return false;
4046       }
4047     }
4048   }
4049   return true;
4050 }
4051
4052
4053 void HGraph::CollectPhis() {
4054   int block_count = blocks_.length();
4055   phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone());
4056   for (int i = 0; i < block_count; ++i) {
4057     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
4058       HPhi* phi = blocks_[i]->phis()->at(j);
4059       phi_list_->Add(phi, zone());
4060     }
4061   }
4062 }
4063
4064
4065 // Implementation of utility class to encapsulate the translation state for
4066 // a (possibly inlined) function.
4067 FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
4068                              CompilationInfo* info, InliningKind inlining_kind,
4069                              int inlining_id)
4070     : owner_(owner),
4071       compilation_info_(info),
4072       call_context_(NULL),
4073       inlining_kind_(inlining_kind),
4074       function_return_(NULL),
4075       test_context_(NULL),
4076       entry_(NULL),
4077       arguments_object_(NULL),
4078       arguments_elements_(NULL),
4079       inlining_id_(inlining_id),
4080       outer_source_position_(SourcePosition::Unknown()),
4081       outer_(owner->function_state()) {
4082   if (outer_ != NULL) {
4083     // State for an inline function.
4084     if (owner->ast_context()->IsTest()) {
4085       HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
4086       HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
4087       if_true->MarkAsInlineReturnTarget(owner->current_block());
4088       if_false->MarkAsInlineReturnTarget(owner->current_block());
4089       TestContext* outer_test_context = TestContext::cast(owner->ast_context());
4090       Expression* cond = outer_test_context->condition();
4091       // The AstContext constructor pushed on the context stack.  This newed
4092       // instance is the reason that AstContext can't be BASE_EMBEDDED.
4093       test_context_ = new TestContext(owner, cond, if_true, if_false);
4094     } else {
4095       function_return_ = owner->graph()->CreateBasicBlock();
4096       function_return()->MarkAsInlineReturnTarget(owner->current_block());
4097     }
4098     // Set this after possibly allocating a new TestContext above.
4099     call_context_ = owner->ast_context();
4100   }
4101
4102   // Push on the state stack.
4103   owner->set_function_state(this);
4104
4105   if (compilation_info_->is_tracking_positions()) {
4106     outer_source_position_ = owner->source_position();
4107     owner->EnterInlinedSource(
4108       info->shared_info()->start_position(),
4109       inlining_id);
4110     owner->SetSourcePosition(info->shared_info()->start_position());
4111   }
4112 }
4113
4114
4115 FunctionState::~FunctionState() {
4116   delete test_context_;
4117   owner_->set_function_state(outer_);
4118
4119   if (compilation_info_->is_tracking_positions()) {
4120     owner_->set_source_position(outer_source_position_);
4121     owner_->EnterInlinedSource(
4122       outer_->compilation_info()->shared_info()->start_position(),
4123       outer_->inlining_id());
4124   }
4125 }
4126
4127
4128 // Implementation of utility classes to represent an expression's context in
4129 // the AST.
4130 AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind)
4131     : owner_(owner),
4132       kind_(kind),
4133       outer_(owner->ast_context()),
4134       typeof_mode_(NOT_INSIDE_TYPEOF) {
4135   owner->set_ast_context(this);  // Push.
4136 #ifdef DEBUG
4137   DCHECK(owner->environment()->frame_type() == JS_FUNCTION);
4138   original_length_ = owner->environment()->length();
4139 #endif
4140 }
4141
4142
4143 AstContext::~AstContext() {
4144   owner_->set_ast_context(outer_);  // Pop.
4145 }
4146
4147
4148 EffectContext::~EffectContext() {
4149   DCHECK(owner()->HasStackOverflow() ||
4150          owner()->current_block() == NULL ||
4151          (owner()->environment()->length() == original_length_ &&
4152           owner()->environment()->frame_type() == JS_FUNCTION));
4153 }
4154
4155
4156 ValueContext::~ValueContext() {
4157   DCHECK(owner()->HasStackOverflow() ||
4158          owner()->current_block() == NULL ||
4159          (owner()->environment()->length() == original_length_ + 1 &&
4160           owner()->environment()->frame_type() == JS_FUNCTION));
4161 }
4162
4163
4164 void EffectContext::ReturnValue(HValue* value) {
4165   // The value is simply ignored.
4166 }
4167
4168
4169 void ValueContext::ReturnValue(HValue* value) {
4170   // The value is tracked in the bailout environment, and communicated
4171   // through the environment as the result of the expression.
4172   if (value->CheckFlag(HValue::kIsArguments)) {
4173     if (flag_ == ARGUMENTS_FAKED) {
4174       value = owner()->graph()->GetConstantUndefined();
4175     } else if (!arguments_allowed()) {
4176       owner()->Bailout(kBadValueContextForArgumentsValue);
4177     }
4178   }
4179   owner()->Push(value);
4180 }
4181
4182
4183 void TestContext::ReturnValue(HValue* value) {
4184   BuildBranch(value);
4185 }
4186
4187
4188 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
4189   DCHECK(!instr->IsControlInstruction());
4190   owner()->AddInstruction(instr);
4191   if (instr->HasObservableSideEffects()) {
4192     owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
4193   }
4194 }
4195
4196
4197 void EffectContext::ReturnControl(HControlInstruction* instr,
4198                                   BailoutId ast_id) {
4199   DCHECK(!instr->HasObservableSideEffects());
4200   HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
4201   HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
4202   instr->SetSuccessorAt(0, empty_true);
4203   instr->SetSuccessorAt(1, empty_false);
4204   owner()->FinishCurrentBlock(instr);
4205   HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id);
4206   owner()->set_current_block(join);
4207 }
4208
4209
4210 void EffectContext::ReturnContinuation(HIfContinuation* continuation,
4211                                        BailoutId ast_id) {
4212   HBasicBlock* true_branch = NULL;
4213   HBasicBlock* false_branch = NULL;
4214   continuation->Continue(&true_branch, &false_branch);
4215   if (!continuation->IsTrueReachable()) {
4216     owner()->set_current_block(false_branch);
4217   } else if (!continuation->IsFalseReachable()) {
4218     owner()->set_current_block(true_branch);
4219   } else {
4220     HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id);
4221     owner()->set_current_block(join);
4222   }
4223 }
4224
4225
4226 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
4227   DCHECK(!instr->IsControlInstruction());
4228   if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
4229     return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
4230   }
4231   owner()->AddInstruction(instr);
4232   owner()->Push(instr);
4233   if (instr->HasObservableSideEffects()) {
4234     owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
4235   }
4236 }
4237
4238
4239 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
4240   DCHECK(!instr->HasObservableSideEffects());
4241   if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
4242     return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
4243   }
4244   HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
4245   HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
4246   instr->SetSuccessorAt(0, materialize_true);
4247   instr->SetSuccessorAt(1, materialize_false);
4248   owner()->FinishCurrentBlock(instr);
4249   owner()->set_current_block(materialize_true);
4250   owner()->Push(owner()->graph()->GetConstantTrue());
4251   owner()->set_current_block(materialize_false);
4252   owner()->Push(owner()->graph()->GetConstantFalse());
4253   HBasicBlock* join =
4254     owner()->CreateJoin(materialize_true, materialize_false, ast_id);
4255   owner()->set_current_block(join);
4256 }
4257
4258
4259 void ValueContext::ReturnContinuation(HIfContinuation* continuation,
4260                                       BailoutId ast_id) {
4261   HBasicBlock* materialize_true = NULL;
4262   HBasicBlock* materialize_false = NULL;
4263   continuation->Continue(&materialize_true, &materialize_false);
4264   if (continuation->IsTrueReachable()) {
4265     owner()->set_current_block(materialize_true);
4266     owner()->Push(owner()->graph()->GetConstantTrue());
4267     owner()->set_current_block(materialize_true);
4268   }
4269   if (continuation->IsFalseReachable()) {
4270     owner()->set_current_block(materialize_false);
4271     owner()->Push(owner()->graph()->GetConstantFalse());
4272     owner()->set_current_block(materialize_false);
4273   }
4274   if (continuation->TrueAndFalseReachable()) {
4275     HBasicBlock* join =
4276         owner()->CreateJoin(materialize_true, materialize_false, ast_id);
4277     owner()->set_current_block(join);
4278   }
4279 }
4280
4281
4282 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
4283   DCHECK(!instr->IsControlInstruction());
4284   HOptimizedGraphBuilder* builder = owner();
4285   builder->AddInstruction(instr);
4286   // We expect a simulate after every expression with side effects, though
4287   // this one isn't actually needed (and wouldn't work if it were targeted).
4288   if (instr->HasObservableSideEffects()) {
4289     builder->Push(instr);
4290     builder->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
4291     builder->Pop();
4292   }
4293   BuildBranch(instr);
4294 }
4295
4296
4297 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
4298   DCHECK(!instr->HasObservableSideEffects());
4299   HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
4300   HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
4301   instr->SetSuccessorAt(0, empty_true);
4302   instr->SetSuccessorAt(1, empty_false);
4303   owner()->FinishCurrentBlock(instr);
4304   owner()->Goto(empty_true, if_true(), owner()->function_state());
4305   owner()->Goto(empty_false, if_false(), owner()->function_state());
4306   owner()->set_current_block(NULL);
4307 }
4308
4309
4310 void TestContext::ReturnContinuation(HIfContinuation* continuation,
4311                                      BailoutId ast_id) {
4312   HBasicBlock* true_branch = NULL;
4313   HBasicBlock* false_branch = NULL;
4314   continuation->Continue(&true_branch, &false_branch);
4315   if (continuation->IsTrueReachable()) {
4316     owner()->Goto(true_branch, if_true(), owner()->function_state());
4317   }
4318   if (continuation->IsFalseReachable()) {
4319     owner()->Goto(false_branch, if_false(), owner()->function_state());
4320   }
4321   owner()->set_current_block(NULL);
4322 }
4323
4324
4325 void TestContext::BuildBranch(HValue* value) {
4326   // We expect the graph to be in edge-split form: there is no edge that
4327   // connects a branch node to a join node.  We conservatively ensure that
4328   // property by always adding an empty block on the outgoing edges of this
4329   // branch.
4330   HOptimizedGraphBuilder* builder = owner();
4331   if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
4332     builder->Bailout(kArgumentsObjectValueInATestContext);
4333   }
4334   ToBooleanStub::Types expected(condition()->to_boolean_types());
4335   ReturnControl(owner()->New<HBranch>(value, expected), BailoutId::None());
4336 }
4337
4338
4339 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts.
4340 #define CHECK_BAILOUT(call)                     \
4341   do {                                          \
4342     call;                                       \
4343     if (HasStackOverflow()) return;             \
4344   } while (false)
4345
4346
4347 #define CHECK_ALIVE(call)                                       \
4348   do {                                                          \
4349     call;                                                       \
4350     if (HasStackOverflow() || current_block() == NULL) return;  \
4351   } while (false)
4352
4353
4354 #define CHECK_ALIVE_OR_RETURN(call, value)                            \
4355   do {                                                                \
4356     call;                                                             \
4357     if (HasStackOverflow() || current_block() == NULL) return value;  \
4358   } while (false)
4359
4360
4361 void HOptimizedGraphBuilder::Bailout(BailoutReason reason) {
4362   current_info()->AbortOptimization(reason);
4363   SetStackOverflow();
4364 }
4365
4366
4367 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) {
4368   EffectContext for_effect(this);
4369   Visit(expr);
4370 }
4371
4372
4373 void HOptimizedGraphBuilder::VisitForValue(Expression* expr,
4374                                            ArgumentsAllowedFlag flag) {
4375   ValueContext for_value(this, flag);
4376   Visit(expr);
4377 }
4378
4379
4380 void HOptimizedGraphBuilder::VisitForTypeOf(Expression* expr) {
4381   ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
4382   for_value.set_typeof_mode(INSIDE_TYPEOF);
4383   Visit(expr);
4384 }
4385
4386
4387 void HOptimizedGraphBuilder::VisitForControl(Expression* expr,
4388                                              HBasicBlock* true_block,
4389                                              HBasicBlock* false_block) {
4390   TestContext for_test(this, expr, true_block, false_block);
4391   Visit(expr);
4392 }
4393
4394
4395 void HOptimizedGraphBuilder::VisitExpressions(
4396     ZoneList<Expression*>* exprs) {
4397   for (int i = 0; i < exprs->length(); ++i) {
4398     CHECK_ALIVE(VisitForValue(exprs->at(i)));
4399   }
4400 }
4401
4402
4403 void HOptimizedGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs,
4404                                               ArgumentsAllowedFlag flag) {
4405   for (int i = 0; i < exprs->length(); ++i) {
4406     CHECK_ALIVE(VisitForValue(exprs->at(i), flag));
4407   }
4408 }
4409
4410
4411 bool HOptimizedGraphBuilder::BuildGraph() {
4412   if (IsSubclassConstructor(current_info()->literal()->kind())) {
4413     Bailout(kSuperReference);
4414     return false;
4415   }
4416
4417   int slots = current_info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
4418   if (current_info()->scope()->is_script_scope() && slots > 0) {
4419     Bailout(kScriptContext);
4420     return false;
4421   }
4422
4423   Scope* scope = current_info()->scope();
4424   SetUpScope(scope);
4425
4426   // Add an edge to the body entry.  This is warty: the graph's start
4427   // environment will be used by the Lithium translation as the initial
4428   // environment on graph entry, but it has now been mutated by the
4429   // Hydrogen translation of the instructions in the start block.  This
4430   // environment uses values which have not been defined yet.  These
4431   // Hydrogen instructions will then be replayed by the Lithium
4432   // translation, so they cannot have an environment effect.  The edge to
4433   // the body's entry block (along with some special logic for the start
4434   // block in HInstruction::InsertAfter) seals the start block from
4435   // getting unwanted instructions inserted.
4436   //
4437   // TODO(kmillikin): Fix this.  Stop mutating the initial environment.
4438   // Make the Hydrogen instructions in the initial block into Hydrogen
4439   // values (but not instructions), present in the initial environment and
4440   // not replayed by the Lithium translation.
4441   HEnvironment* initial_env = environment()->CopyWithoutHistory();
4442   HBasicBlock* body_entry = CreateBasicBlock(initial_env);
4443   Goto(body_entry);
4444   body_entry->SetJoinId(BailoutId::FunctionEntry());
4445   set_current_block(body_entry);
4446
4447   VisitDeclarations(scope->declarations());
4448   Add<HSimulate>(BailoutId::Declarations());
4449
4450   Add<HStackCheck>(HStackCheck::kFunctionEntry);
4451
4452   VisitStatements(current_info()->literal()->body());
4453   if (HasStackOverflow()) return false;
4454
4455   if (current_block() != NULL) {
4456     Add<HReturn>(graph()->GetConstantUndefined());
4457     set_current_block(NULL);
4458   }
4459
4460   // If the checksum of the number of type info changes is the same as the
4461   // last time this function was compiled, then this recompile is likely not
4462   // due to missing/inadequate type feedback, but rather too aggressive
4463   // optimization. Disable optimistic LICM in that case.
4464   Handle<Code> unoptimized_code(current_info()->shared_info()->code());
4465   DCHECK(unoptimized_code->kind() == Code::FUNCTION);
4466   Handle<TypeFeedbackInfo> type_info(
4467       TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
4468   int checksum = type_info->own_type_change_checksum();
4469   int composite_checksum = graph()->update_type_change_checksum(checksum);
4470   graph()->set_use_optimistic_licm(
4471       !type_info->matches_inlined_type_change_checksum(composite_checksum));
4472   type_info->set_inlined_type_change_checksum(composite_checksum);
4473
4474   // Perform any necessary OSR-specific cleanups or changes to the graph.
4475   osr()->FinishGraph();
4476
4477   return true;
4478 }
4479
4480
4481 bool HGraph::Optimize(BailoutReason* bailout_reason) {
4482   OrderBlocks();
4483   AssignDominators();
4484
4485   // We need to create a HConstant "zero" now so that GVN will fold every
4486   // zero-valued constant in the graph together.
4487   // The constant is needed to make idef-based bounds check work: the pass
4488   // evaluates relations with "zero" and that zero cannot be created after GVN.
4489   GetConstant0();
4490
4491 #ifdef DEBUG
4492   // Do a full verify after building the graph and computing dominators.
4493   Verify(true);
4494 #endif
4495
4496   if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) {
4497     Run<HEnvironmentLivenessAnalysisPhase>();
4498   }
4499
4500   if (!CheckConstPhiUses()) {
4501     *bailout_reason = kUnsupportedPhiUseOfConstVariable;
4502     return false;
4503   }
4504   Run<HRedundantPhiEliminationPhase>();
4505   if (!CheckArgumentsPhiUses()) {
4506     *bailout_reason = kUnsupportedPhiUseOfArguments;
4507     return false;
4508   }
4509
4510   // Find and mark unreachable code to simplify optimizations, especially gvn,
4511   // where unreachable code could unnecessarily defeat LICM.
4512   Run<HMarkUnreachableBlocksPhase>();
4513
4514   if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
4515   if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
4516
4517   if (FLAG_load_elimination) Run<HLoadEliminationPhase>();
4518
4519   CollectPhis();
4520
4521   if (has_osr()) osr()->FinishOsrValues();
4522
4523   Run<HInferRepresentationPhase>();
4524
4525   // Remove HSimulate instructions that have turned out not to be needed
4526   // after all by folding them into the following HSimulate.
4527   // This must happen after inferring representations.
4528   Run<HMergeRemovableSimulatesPhase>();
4529
4530   Run<HMarkDeoptimizeOnUndefinedPhase>();
4531   Run<HRepresentationChangesPhase>();
4532
4533   Run<HInferTypesPhase>();
4534
4535   // Must be performed before canonicalization to ensure that Canonicalize
4536   // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with
4537   // zero.
4538   Run<HUint32AnalysisPhase>();
4539
4540   if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>();
4541
4542   if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>();
4543
4544   if (FLAG_check_elimination) Run<HCheckEliminationPhase>();
4545
4546   if (FLAG_store_elimination) Run<HStoreEliminationPhase>();
4547
4548   Run<HRangeAnalysisPhase>();
4549
4550   Run<HComputeChangeUndefinedToNaN>();
4551
4552   // Eliminate redundant stack checks on backwards branches.
4553   Run<HStackCheckEliminationPhase>();
4554
4555   if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>();
4556   if (FLAG_array_bounds_checks_hoisting) Run<HBoundsCheckHoistingPhase>();
4557   if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
4558   if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
4559
4560   RestoreActualValues();
4561
4562   // Find unreachable code a second time, GVN and other optimizations may have
4563   // made blocks unreachable that were previously reachable.
4564   Run<HMarkUnreachableBlocksPhase>();
4565
4566   return true;
4567 }
4568
4569
4570 void HGraph::RestoreActualValues() {
4571   HPhase phase("H_Restore actual values", this);
4572
4573   for (int block_index = 0; block_index < blocks()->length(); block_index++) {
4574     HBasicBlock* block = blocks()->at(block_index);
4575
4576 #ifdef DEBUG
4577     for (int i = 0; i < block->phis()->length(); i++) {
4578       HPhi* phi = block->phis()->at(i);
4579       DCHECK(phi->ActualValue() == phi);
4580     }
4581 #endif
4582
4583     for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
4584       HInstruction* instruction = it.Current();
4585       if (instruction->ActualValue() == instruction) continue;
4586       if (instruction->CheckFlag(HValue::kIsDead)) {
4587         // The instruction was marked as deleted but left in the graph
4588         // as a control flow dependency point for subsequent
4589         // instructions.
4590         instruction->DeleteAndReplaceWith(instruction->ActualValue());
4591       } else {
4592         DCHECK(instruction->IsInformativeDefinition());
4593         if (instruction->IsPurelyInformativeDefinition()) {
4594           instruction->DeleteAndReplaceWith(instruction->RedefinedOperand());
4595         } else {
4596           instruction->ReplaceAllUsesWith(instruction->ActualValue());
4597         }
4598       }
4599     }
4600   }
4601 }
4602
4603
4604 void HOptimizedGraphBuilder::PushArgumentsFromEnvironment(int count) {
4605   ZoneList<HValue*> arguments(count, zone());
4606   for (int i = 0; i < count; ++i) {
4607     arguments.Add(Pop(), zone());
4608   }
4609
4610   HPushArguments* push_args = New<HPushArguments>();
4611   while (!arguments.is_empty()) {
4612     push_args->AddInput(arguments.RemoveLast());
4613   }
4614   AddInstruction(push_args);
4615 }
4616
4617
4618 template <class Instruction>
4619 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
4620   PushArgumentsFromEnvironment(call->argument_count());
4621   return call;
4622 }
4623
4624
4625 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) {
4626   // First special is HContext.
4627   HInstruction* context = Add<HContext>();
4628   environment()->BindContext(context);
4629
4630   // Create an arguments object containing the initial parameters.  Set the
4631   // initial values of parameters including "this" having parameter index 0.
4632   DCHECK_EQ(scope->num_parameters() + 1, environment()->parameter_count());
4633   HArgumentsObject* arguments_object =
4634       New<HArgumentsObject>(environment()->parameter_count());
4635   for (int i = 0; i < environment()->parameter_count(); ++i) {
4636     HInstruction* parameter = Add<HParameter>(i);
4637     arguments_object->AddArgument(parameter, zone());
4638     environment()->Bind(i, parameter);
4639   }
4640   AddInstruction(arguments_object);
4641   graph()->SetArgumentsObject(arguments_object);
4642
4643   HConstant* undefined_constant = graph()->GetConstantUndefined();
4644   // Initialize specials and locals to undefined.
4645   for (int i = environment()->parameter_count() + 1;
4646        i < environment()->length();
4647        ++i) {
4648     environment()->Bind(i, undefined_constant);
4649   }
4650
4651   // Handle the arguments and arguments shadow variables specially (they do
4652   // not have declarations).
4653   if (scope->arguments() != NULL) {
4654     environment()->Bind(scope->arguments(),
4655                         graph()->GetArgumentsObject());
4656   }
4657
4658   int rest_index;
4659   Variable* rest = scope->rest_parameter(&rest_index);
4660   if (rest) {
4661     return Bailout(kRestParameter);
4662   }
4663
4664   if (scope->this_function_var() != nullptr ||
4665       scope->new_target_var() != nullptr) {
4666     return Bailout(kSuperReference);
4667   }
4668 }
4669
4670
4671 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
4672   for (int i = 0; i < statements->length(); i++) {
4673     Statement* stmt = statements->at(i);
4674     CHECK_ALIVE(Visit(stmt));
4675     if (stmt->IsJump()) break;
4676   }
4677 }
4678
4679
4680 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
4681   DCHECK(!HasStackOverflow());
4682   DCHECK(current_block() != NULL);
4683   DCHECK(current_block()->HasPredecessor());
4684
4685   Scope* outer_scope = scope();
4686   Scope* scope = stmt->scope();
4687   BreakAndContinueInfo break_info(stmt, outer_scope);
4688
4689   { BreakAndContinueScope push(&break_info, this);
4690     if (scope != NULL) {
4691       if (scope->NeedsContext()) {
4692         // Load the function object.
4693         Scope* declaration_scope = scope->DeclarationScope();
4694         HInstruction* function;
4695         HValue* outer_context = environment()->context();
4696         if (declaration_scope->is_script_scope() ||
4697             declaration_scope->is_eval_scope()) {
4698           function = new (zone())
4699               HLoadContextSlot(outer_context, Context::CLOSURE_INDEX,
4700                                HLoadContextSlot::kNoCheck);
4701         } else {
4702           function = New<HThisFunction>();
4703         }
4704         AddInstruction(function);
4705         // Allocate a block context and store it to the stack frame.
4706         HInstruction* inner_context = Add<HAllocateBlockContext>(
4707             outer_context, function, scope->GetScopeInfo(isolate()));
4708         HInstruction* instr = Add<HStoreFrameContext>(inner_context);
4709         set_scope(scope);
4710         environment()->BindContext(inner_context);
4711         if (instr->HasObservableSideEffects()) {
4712           AddSimulate(stmt->EntryId(), REMOVABLE_SIMULATE);
4713         }
4714       }
4715       VisitDeclarations(scope->declarations());
4716       AddSimulate(stmt->DeclsId(), REMOVABLE_SIMULATE);
4717     }
4718     CHECK_BAILOUT(VisitStatements(stmt->statements()));
4719   }
4720   set_scope(outer_scope);
4721   if (scope != NULL && current_block() != NULL &&
4722       scope->ContextLocalCount() > 0) {
4723     HValue* inner_context = environment()->context();
4724     HValue* outer_context = Add<HLoadNamedField>(
4725         inner_context, nullptr,
4726         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
4727
4728     HInstruction* instr = Add<HStoreFrameContext>(outer_context);
4729     environment()->BindContext(outer_context);
4730     if (instr->HasObservableSideEffects()) {
4731       AddSimulate(stmt->ExitId(), REMOVABLE_SIMULATE);
4732     }
4733   }
4734   HBasicBlock* break_block = break_info.break_block();
4735   if (break_block != NULL) {
4736     if (current_block() != NULL) Goto(break_block);
4737     break_block->SetJoinId(stmt->ExitId());
4738     set_current_block(break_block);
4739   }
4740 }
4741
4742
4743 void HOptimizedGraphBuilder::VisitExpressionStatement(
4744     ExpressionStatement* stmt) {
4745   DCHECK(!HasStackOverflow());
4746   DCHECK(current_block() != NULL);
4747   DCHECK(current_block()->HasPredecessor());
4748   VisitForEffect(stmt->expression());
4749 }
4750
4751
4752 void HOptimizedGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
4753   DCHECK(!HasStackOverflow());
4754   DCHECK(current_block() != NULL);
4755   DCHECK(current_block()->HasPredecessor());
4756 }
4757
4758
4759 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) {
4760   DCHECK(!HasStackOverflow());
4761   DCHECK(current_block() != NULL);
4762   DCHECK(current_block()->HasPredecessor());
4763   if (stmt->condition()->ToBooleanIsTrue()) {
4764     Add<HSimulate>(stmt->ThenId());
4765     Visit(stmt->then_statement());
4766   } else if (stmt->condition()->ToBooleanIsFalse()) {
4767     Add<HSimulate>(stmt->ElseId());
4768     Visit(stmt->else_statement());
4769   } else {
4770     HBasicBlock* cond_true = graph()->CreateBasicBlock();
4771     HBasicBlock* cond_false = graph()->CreateBasicBlock();
4772     CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false));
4773
4774     if (cond_true->HasPredecessor()) {
4775       cond_true->SetJoinId(stmt->ThenId());
4776       set_current_block(cond_true);
4777       CHECK_BAILOUT(Visit(stmt->then_statement()));
4778       cond_true = current_block();
4779     } else {
4780       cond_true = NULL;
4781     }
4782
4783     if (cond_false->HasPredecessor()) {
4784       cond_false->SetJoinId(stmt->ElseId());
4785       set_current_block(cond_false);
4786       CHECK_BAILOUT(Visit(stmt->else_statement()));
4787       cond_false = current_block();
4788     } else {
4789       cond_false = NULL;
4790     }
4791
4792     HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId());
4793     set_current_block(join);
4794   }
4795 }
4796
4797
4798 HBasicBlock* HOptimizedGraphBuilder::BreakAndContinueScope::Get(
4799     BreakableStatement* stmt,
4800     BreakType type,
4801     Scope** scope,
4802     int* drop_extra) {
4803   *drop_extra = 0;
4804   BreakAndContinueScope* current = this;
4805   while (current != NULL && current->info()->target() != stmt) {
4806     *drop_extra += current->info()->drop_extra();
4807     current = current->next();
4808   }
4809   DCHECK(current != NULL);  // Always found (unless stack is malformed).
4810   *scope = current->info()->scope();
4811
4812   if (type == BREAK) {
4813     *drop_extra += current->info()->drop_extra();
4814   }
4815
4816   HBasicBlock* block = NULL;
4817   switch (type) {
4818     case BREAK:
4819       block = current->info()->break_block();
4820       if (block == NULL) {
4821         block = current->owner()->graph()->CreateBasicBlock();
4822         current->info()->set_break_block(block);
4823       }
4824       break;
4825
4826     case CONTINUE:
4827       block = current->info()->continue_block();
4828       if (block == NULL) {
4829         block = current->owner()->graph()->CreateBasicBlock();
4830         current->info()->set_continue_block(block);
4831       }
4832       break;
4833   }
4834
4835   return block;
4836 }
4837
4838
4839 void HOptimizedGraphBuilder::VisitContinueStatement(
4840     ContinueStatement* stmt) {
4841   DCHECK(!HasStackOverflow());
4842   DCHECK(current_block() != NULL);
4843   DCHECK(current_block()->HasPredecessor());
4844   Scope* outer_scope = NULL;
4845   Scope* inner_scope = scope();
4846   int drop_extra = 0;
4847   HBasicBlock* continue_block = break_scope()->Get(
4848       stmt->target(), BreakAndContinueScope::CONTINUE,
4849       &outer_scope, &drop_extra);
4850   HValue* context = environment()->context();
4851   Drop(drop_extra);
4852   int context_pop_count = inner_scope->ContextChainLength(outer_scope);
4853   if (context_pop_count > 0) {
4854     while (context_pop_count-- > 0) {
4855       HInstruction* context_instruction = Add<HLoadNamedField>(
4856           context, nullptr,
4857           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
4858       context = context_instruction;
4859     }
4860     HInstruction* instr = Add<HStoreFrameContext>(context);
4861     if (instr->HasObservableSideEffects()) {
4862       AddSimulate(stmt->target()->EntryId(), REMOVABLE_SIMULATE);
4863     }
4864     environment()->BindContext(context);
4865   }
4866
4867   Goto(continue_block);
4868   set_current_block(NULL);
4869 }
4870
4871
4872 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
4873   DCHECK(!HasStackOverflow());
4874   DCHECK(current_block() != NULL);
4875   DCHECK(current_block()->HasPredecessor());
4876   Scope* outer_scope = NULL;
4877   Scope* inner_scope = scope();
4878   int drop_extra = 0;
4879   HBasicBlock* break_block = break_scope()->Get(
4880       stmt->target(), BreakAndContinueScope::BREAK,
4881       &outer_scope, &drop_extra);
4882   HValue* context = environment()->context();
4883   Drop(drop_extra);
4884   int context_pop_count = inner_scope->ContextChainLength(outer_scope);
4885   if (context_pop_count > 0) {
4886     while (context_pop_count-- > 0) {
4887       HInstruction* context_instruction = Add<HLoadNamedField>(
4888           context, nullptr,
4889           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
4890       context = context_instruction;
4891     }
4892     HInstruction* instr = Add<HStoreFrameContext>(context);
4893     if (instr->HasObservableSideEffects()) {
4894       AddSimulate(stmt->target()->ExitId(), REMOVABLE_SIMULATE);
4895     }
4896     environment()->BindContext(context);
4897   }
4898   Goto(break_block);
4899   set_current_block(NULL);
4900 }
4901
4902
4903 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
4904   DCHECK(!HasStackOverflow());
4905   DCHECK(current_block() != NULL);
4906   DCHECK(current_block()->HasPredecessor());
4907   FunctionState* state = function_state();
4908   AstContext* context = call_context();
4909   if (context == NULL) {
4910     // Not an inlined return, so an actual one.
4911     CHECK_ALIVE(VisitForValue(stmt->expression()));
4912     HValue* result = environment()->Pop();
4913     Add<HReturn>(result);
4914   } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
4915     // Return from an inlined construct call. In a test context the return value
4916     // will always evaluate to true, in a value context the return value needs
4917     // to be a JSObject.
4918     if (context->IsTest()) {
4919       TestContext* test = TestContext::cast(context);
4920       CHECK_ALIVE(VisitForEffect(stmt->expression()));
4921       Goto(test->if_true(), state);
4922     } else if (context->IsEffect()) {
4923       CHECK_ALIVE(VisitForEffect(stmt->expression()));
4924       Goto(function_return(), state);
4925     } else {
4926       DCHECK(context->IsValue());
4927       CHECK_ALIVE(VisitForValue(stmt->expression()));
4928       HValue* return_value = Pop();
4929       HValue* receiver = environment()->arguments_environment()->Lookup(0);
4930       HHasInstanceTypeAndBranch* typecheck =
4931           New<HHasInstanceTypeAndBranch>(return_value,
4932                                          FIRST_SPEC_OBJECT_TYPE,
4933                                          LAST_SPEC_OBJECT_TYPE);
4934       HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
4935       HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
4936       typecheck->SetSuccessorAt(0, if_spec_object);
4937       typecheck->SetSuccessorAt(1, not_spec_object);
4938       FinishCurrentBlock(typecheck);
4939       AddLeaveInlined(if_spec_object, return_value, state);
4940       AddLeaveInlined(not_spec_object, receiver, state);
4941     }
4942   } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
4943     // Return from an inlined setter call. The returned value is never used, the
4944     // value of an assignment is always the value of the RHS of the assignment.
4945     CHECK_ALIVE(VisitForEffect(stmt->expression()));
4946     if (context->IsTest()) {
4947       HValue* rhs = environment()->arguments_environment()->Lookup(1);
4948       context->ReturnValue(rhs);
4949     } else if (context->IsEffect()) {
4950       Goto(function_return(), state);
4951     } else {
4952       DCHECK(context->IsValue());
4953       HValue* rhs = environment()->arguments_environment()->Lookup(1);
4954       AddLeaveInlined(rhs, state);
4955     }
4956   } else {
4957     // Return from a normal inlined function. Visit the subexpression in the
4958     // expression context of the call.
4959     if (context->IsTest()) {
4960       TestContext* test = TestContext::cast(context);
4961       VisitForControl(stmt->expression(), test->if_true(), test->if_false());
4962     } else if (context->IsEffect()) {
4963       // Visit in value context and ignore the result. This is needed to keep
4964       // environment in sync with full-codegen since some visitors (e.g.
4965       // VisitCountOperation) use the operand stack differently depending on
4966       // context.
4967       CHECK_ALIVE(VisitForValue(stmt->expression()));
4968       Pop();
4969       Goto(function_return(), state);
4970     } else {
4971       DCHECK(context->IsValue());
4972       CHECK_ALIVE(VisitForValue(stmt->expression()));
4973       AddLeaveInlined(Pop(), state);
4974     }
4975   }
4976   set_current_block(NULL);
4977 }
4978
4979
4980 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) {
4981   DCHECK(!HasStackOverflow());
4982   DCHECK(current_block() != NULL);
4983   DCHECK(current_block()->HasPredecessor());
4984   return Bailout(kWithStatement);
4985 }
4986
4987
4988 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
4989   DCHECK(!HasStackOverflow());
4990   DCHECK(current_block() != NULL);
4991   DCHECK(current_block()->HasPredecessor());
4992
4993   ZoneList<CaseClause*>* clauses = stmt->cases();
4994   int clause_count = clauses->length();
4995   ZoneList<HBasicBlock*> body_blocks(clause_count, zone());
4996
4997   CHECK_ALIVE(VisitForValue(stmt->tag()));
4998   Add<HSimulate>(stmt->EntryId());
4999   HValue* tag_value = Top();
5000   Type* tag_type = stmt->tag()->bounds().lower;
5001
5002   // 1. Build all the tests, with dangling true branches
5003   BailoutId default_id = BailoutId::None();
5004   for (int i = 0; i < clause_count; ++i) {
5005     CaseClause* clause = clauses->at(i);
5006     if (clause->is_default()) {
5007       body_blocks.Add(NULL, zone());
5008       if (default_id.IsNone()) default_id = clause->EntryId();
5009       continue;
5010     }
5011
5012     // Generate a compare and branch.
5013     CHECK_ALIVE(VisitForValue(clause->label()));
5014     HValue* label_value = Pop();
5015
5016     Type* label_type = clause->label()->bounds().lower;
5017     Type* combined_type = clause->compare_type();
5018     HControlInstruction* compare = BuildCompareInstruction(
5019         Token::EQ_STRICT, tag_value, label_value, tag_type, label_type,
5020         combined_type,
5021         ScriptPositionToSourcePosition(stmt->tag()->position()),
5022         ScriptPositionToSourcePosition(clause->label()->position()),
5023         PUSH_BEFORE_SIMULATE, clause->id());
5024
5025     HBasicBlock* next_test_block = graph()->CreateBasicBlock();
5026     HBasicBlock* body_block = graph()->CreateBasicBlock();
5027     body_blocks.Add(body_block, zone());
5028     compare->SetSuccessorAt(0, body_block);
5029     compare->SetSuccessorAt(1, next_test_block);
5030     FinishCurrentBlock(compare);
5031
5032     set_current_block(body_block);
5033     Drop(1);  // tag_value
5034
5035     set_current_block(next_test_block);
5036   }
5037
5038   // Save the current block to use for the default or to join with the
5039   // exit.
5040   HBasicBlock* last_block = current_block();
5041   Drop(1);  // tag_value
5042
5043   // 2. Loop over the clauses and the linked list of tests in lockstep,
5044   // translating the clause bodies.
5045   HBasicBlock* fall_through_block = NULL;
5046
5047   BreakAndContinueInfo break_info(stmt, scope());
5048   { BreakAndContinueScope push(&break_info, this);
5049     for (int i = 0; i < clause_count; ++i) {
5050       CaseClause* clause = clauses->at(i);
5051
5052       // Identify the block where normal (non-fall-through) control flow
5053       // goes to.
5054       HBasicBlock* normal_block = NULL;
5055       if (clause->is_default()) {
5056         if (last_block == NULL) continue;
5057         normal_block = last_block;
5058         last_block = NULL;  // Cleared to indicate we've handled it.
5059       } else {
5060         normal_block = body_blocks[i];
5061       }
5062
5063       if (fall_through_block == NULL) {
5064         set_current_block(normal_block);
5065       } else {
5066         HBasicBlock* join = CreateJoin(fall_through_block,
5067                                        normal_block,
5068                                        clause->EntryId());
5069         set_current_block(join);
5070       }
5071
5072       CHECK_BAILOUT(VisitStatements(clause->statements()));
5073       fall_through_block = current_block();
5074     }
5075   }
5076
5077   // Create an up-to-3-way join.  Use the break block if it exists since
5078   // it's already a join block.
5079   HBasicBlock* break_block = break_info.break_block();
5080   if (break_block == NULL) {
5081     set_current_block(CreateJoin(fall_through_block,
5082                                  last_block,
5083                                  stmt->ExitId()));
5084   } else {
5085     if (fall_through_block != NULL) Goto(fall_through_block, break_block);
5086     if (last_block != NULL) Goto(last_block, break_block);
5087     break_block->SetJoinId(stmt->ExitId());
5088     set_current_block(break_block);
5089   }
5090 }
5091
5092
5093 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt,
5094                                            HBasicBlock* loop_entry) {
5095   Add<HSimulate>(stmt->StackCheckId());
5096   HStackCheck* stack_check =
5097       HStackCheck::cast(Add<HStackCheck>(HStackCheck::kBackwardsBranch));
5098   DCHECK(loop_entry->IsLoopHeader());
5099   loop_entry->loop_information()->set_stack_check(stack_check);
5100   CHECK_BAILOUT(Visit(stmt->body()));
5101 }
5102
5103
5104 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
5105   DCHECK(!HasStackOverflow());
5106   DCHECK(current_block() != NULL);
5107   DCHECK(current_block()->HasPredecessor());
5108   DCHECK(current_block() != NULL);
5109   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
5110
5111   BreakAndContinueInfo break_info(stmt, scope());
5112   {
5113     BreakAndContinueScope push(&break_info, this);
5114     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
5115   }
5116   HBasicBlock* body_exit =
5117       JoinContinue(stmt, current_block(), break_info.continue_block());
5118   HBasicBlock* loop_successor = NULL;
5119   if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) {
5120     set_current_block(body_exit);
5121     loop_successor = graph()->CreateBasicBlock();
5122     if (stmt->cond()->ToBooleanIsFalse()) {
5123       loop_entry->loop_information()->stack_check()->Eliminate();
5124       Goto(loop_successor);
5125       body_exit = NULL;
5126     } else {
5127       // The block for a true condition, the actual predecessor block of the
5128       // back edge.
5129       body_exit = graph()->CreateBasicBlock();
5130       CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor));
5131     }
5132     if (body_exit != NULL && body_exit->HasPredecessor()) {
5133       body_exit->SetJoinId(stmt->BackEdgeId());
5134     } else {
5135       body_exit = NULL;
5136     }
5137     if (loop_successor->HasPredecessor()) {
5138       loop_successor->SetJoinId(stmt->ExitId());
5139     } else {
5140       loop_successor = NULL;
5141     }
5142   }
5143   HBasicBlock* loop_exit = CreateLoop(stmt,
5144                                       loop_entry,
5145                                       body_exit,
5146                                       loop_successor,
5147                                       break_info.break_block());
5148   set_current_block(loop_exit);
5149 }
5150
5151
5152 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
5153   DCHECK(!HasStackOverflow());
5154   DCHECK(current_block() != NULL);
5155   DCHECK(current_block()->HasPredecessor());
5156   DCHECK(current_block() != NULL);
5157   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
5158
5159   // If the condition is constant true, do not generate a branch.
5160   HBasicBlock* loop_successor = NULL;
5161   if (!stmt->cond()->ToBooleanIsTrue()) {
5162     HBasicBlock* body_entry = graph()->CreateBasicBlock();
5163     loop_successor = graph()->CreateBasicBlock();
5164     CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
5165     if (body_entry->HasPredecessor()) {
5166       body_entry->SetJoinId(stmt->BodyId());
5167       set_current_block(body_entry);
5168     }
5169     if (loop_successor->HasPredecessor()) {
5170       loop_successor->SetJoinId(stmt->ExitId());
5171     } else {
5172       loop_successor = NULL;
5173     }
5174   }
5175
5176   BreakAndContinueInfo break_info(stmt, scope());
5177   if (current_block() != NULL) {
5178     BreakAndContinueScope push(&break_info, this);
5179     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
5180   }
5181   HBasicBlock* body_exit =
5182       JoinContinue(stmt, current_block(), break_info.continue_block());
5183   HBasicBlock* loop_exit = CreateLoop(stmt,
5184                                       loop_entry,
5185                                       body_exit,
5186                                       loop_successor,
5187                                       break_info.break_block());
5188   set_current_block(loop_exit);
5189 }
5190
5191
5192 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) {
5193   DCHECK(!HasStackOverflow());
5194   DCHECK(current_block() != NULL);
5195   DCHECK(current_block()->HasPredecessor());
5196   if (stmt->init() != NULL) {
5197     CHECK_ALIVE(Visit(stmt->init()));
5198   }
5199   DCHECK(current_block() != NULL);
5200   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
5201
5202   HBasicBlock* loop_successor = NULL;
5203   if (stmt->cond() != NULL) {
5204     HBasicBlock* body_entry = graph()->CreateBasicBlock();
5205     loop_successor = graph()->CreateBasicBlock();
5206     CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
5207     if (body_entry->HasPredecessor()) {
5208       body_entry->SetJoinId(stmt->BodyId());
5209       set_current_block(body_entry);
5210     }
5211     if (loop_successor->HasPredecessor()) {
5212       loop_successor->SetJoinId(stmt->ExitId());
5213     } else {
5214       loop_successor = NULL;
5215     }
5216   }
5217
5218   BreakAndContinueInfo break_info(stmt, scope());
5219   if (current_block() != NULL) {
5220     BreakAndContinueScope push(&break_info, this);
5221     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
5222   }
5223   HBasicBlock* body_exit =
5224       JoinContinue(stmt, current_block(), break_info.continue_block());
5225
5226   if (stmt->next() != NULL && body_exit != NULL) {
5227     set_current_block(body_exit);
5228     CHECK_BAILOUT(Visit(stmt->next()));
5229     body_exit = current_block();
5230   }
5231
5232   HBasicBlock* loop_exit = CreateLoop(stmt,
5233                                       loop_entry,
5234                                       body_exit,
5235                                       loop_successor,
5236                                       break_info.break_block());
5237   set_current_block(loop_exit);
5238 }
5239
5240
5241 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
5242   DCHECK(!HasStackOverflow());
5243   DCHECK(current_block() != NULL);
5244   DCHECK(current_block()->HasPredecessor());
5245
5246   if (!FLAG_optimize_for_in) {
5247     return Bailout(kForInStatementOptimizationIsDisabled);
5248   }
5249
5250   if (!stmt->each()->IsVariableProxy() ||
5251       !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
5252     return Bailout(kForInStatementWithNonLocalEachVariable);
5253   }
5254
5255   Variable* each_var = stmt->each()->AsVariableProxy()->var();
5256
5257   CHECK_ALIVE(VisitForValue(stmt->enumerable()));
5258   HValue* enumerable = Top();  // Leave enumerable at the top.
5259
5260   IfBuilder if_undefined_or_null(this);
5261   if_undefined_or_null.If<HCompareObjectEqAndBranch>(
5262       enumerable, graph()->GetConstantUndefined());
5263   if_undefined_or_null.Or();
5264   if_undefined_or_null.If<HCompareObjectEqAndBranch>(
5265       enumerable, graph()->GetConstantNull());
5266   if_undefined_or_null.ThenDeopt(Deoptimizer::kUndefinedOrNullInForIn);
5267   if_undefined_or_null.End();
5268   BuildForInBody(stmt, each_var, enumerable);
5269 }
5270
5271
5272 void HOptimizedGraphBuilder::BuildForInBody(ForInStatement* stmt,
5273                                             Variable* each_var,
5274                                             HValue* enumerable) {
5275   HInstruction* map;
5276   HInstruction* array;
5277   HInstruction* enum_length;
5278   bool fast = stmt->for_in_type() == ForInStatement::FAST_FOR_IN;
5279   if (fast) {
5280     map = Add<HForInPrepareMap>(enumerable);
5281     Add<HSimulate>(stmt->PrepareId());
5282
5283     array = Add<HForInCacheArray>(enumerable, map,
5284                                   DescriptorArray::kEnumCacheBridgeCacheIndex);
5285     enum_length = Add<HMapEnumLength>(map);
5286
5287     HInstruction* index_cache = Add<HForInCacheArray>(
5288         enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex);
5289     HForInCacheArray::cast(array)
5290         ->set_index_cache(HForInCacheArray::cast(index_cache));
5291   } else {
5292     Add<HSimulate>(stmt->PrepareId());
5293     {
5294       NoObservableSideEffectsScope no_effects(this);
5295       BuildJSObjectCheck(enumerable, 0);
5296     }
5297     Add<HSimulate>(stmt->ToObjectId());
5298
5299     map = graph()->GetConstant1();
5300     Runtime::FunctionId function_id = Runtime::kGetPropertyNamesFast;
5301     Add<HPushArguments>(enumerable);
5302     array = Add<HCallRuntime>(isolate()->factory()->empty_string(),
5303                               Runtime::FunctionForId(function_id), 1);
5304     Push(array);
5305     Add<HSimulate>(stmt->EnumId());
5306     Drop(1);
5307     Handle<Map> array_map = isolate()->factory()->fixed_array_map();
5308     HValue* check = Add<HCheckMaps>(array, array_map);
5309     enum_length = AddLoadFixedArrayLength(array, check);
5310   }
5311
5312   HInstruction* start_index = Add<HConstant>(0);
5313
5314   Push(map);
5315   Push(array);
5316   Push(enum_length);
5317   Push(start_index);
5318
5319   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
5320
5321   // Reload the values to ensure we have up-to-date values inside of the loop.
5322   // This is relevant especially for OSR where the values don't come from the
5323   // computation above, but from the OSR entry block.
5324   enumerable = environment()->ExpressionStackAt(4);
5325   HValue* index = environment()->ExpressionStackAt(0);
5326   HValue* limit = environment()->ExpressionStackAt(1);
5327
5328   // Check that we still have more keys.
5329   HCompareNumericAndBranch* compare_index =
5330       New<HCompareNumericAndBranch>(index, limit, Token::LT);
5331   compare_index->set_observed_input_representation(
5332       Representation::Smi(), Representation::Smi());
5333
5334   HBasicBlock* loop_body = graph()->CreateBasicBlock();
5335   HBasicBlock* loop_successor = graph()->CreateBasicBlock();
5336
5337   compare_index->SetSuccessorAt(0, loop_body);
5338   compare_index->SetSuccessorAt(1, loop_successor);
5339   FinishCurrentBlock(compare_index);
5340
5341   set_current_block(loop_successor);
5342   Drop(5);
5343
5344   set_current_block(loop_body);
5345
5346   HValue* key =
5347       Add<HLoadKeyed>(environment()->ExpressionStackAt(2),  // Enum cache.
5348                       index, index, FAST_ELEMENTS);
5349
5350   if (fast) {
5351     // Check if the expected map still matches that of the enumerable.
5352     // If not just deoptimize.
5353     Add<HCheckMapValue>(enumerable, environment()->ExpressionStackAt(3));
5354     Bind(each_var, key);
5355   } else {
5356     Add<HPushArguments>(enumerable, key);
5357     Runtime::FunctionId function_id = Runtime::kForInFilter;
5358     key = Add<HCallRuntime>(isolate()->factory()->empty_string(),
5359                             Runtime::FunctionForId(function_id), 2);
5360     Push(key);
5361     Add<HSimulate>(stmt->FilterId());
5362     key = Pop();
5363     Bind(each_var, key);
5364     IfBuilder if_undefined(this);
5365     if_undefined.If<HCompareObjectEqAndBranch>(key,
5366                                                graph()->GetConstantUndefined());
5367     if_undefined.ThenDeopt(Deoptimizer::kUndefined);
5368     if_undefined.End();
5369     Add<HSimulate>(stmt->AssignmentId());
5370   }
5371
5372   BreakAndContinueInfo break_info(stmt, scope(), 5);
5373   {
5374     BreakAndContinueScope push(&break_info, this);
5375     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
5376   }
5377
5378   HBasicBlock* body_exit =
5379       JoinContinue(stmt, current_block(), break_info.continue_block());
5380
5381   if (body_exit != NULL) {
5382     set_current_block(body_exit);
5383
5384     HValue* current_index = Pop();
5385     Push(AddUncasted<HAdd>(current_index, graph()->GetConstant1()));
5386     body_exit = current_block();
5387   }
5388
5389   HBasicBlock* loop_exit = CreateLoop(stmt,
5390                                       loop_entry,
5391                                       body_exit,
5392                                       loop_successor,
5393                                       break_info.break_block());
5394
5395   set_current_block(loop_exit);
5396 }
5397
5398
5399 void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
5400   DCHECK(!HasStackOverflow());
5401   DCHECK(current_block() != NULL);
5402   DCHECK(current_block()->HasPredecessor());
5403   return Bailout(kForOfStatement);
5404 }
5405
5406
5407 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
5408   DCHECK(!HasStackOverflow());
5409   DCHECK(current_block() != NULL);
5410   DCHECK(current_block()->HasPredecessor());
5411   return Bailout(kTryCatchStatement);
5412 }
5413
5414
5415 void HOptimizedGraphBuilder::VisitTryFinallyStatement(
5416     TryFinallyStatement* stmt) {
5417   DCHECK(!HasStackOverflow());
5418   DCHECK(current_block() != NULL);
5419   DCHECK(current_block()->HasPredecessor());
5420   return Bailout(kTryFinallyStatement);
5421 }
5422
5423
5424 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
5425   DCHECK(!HasStackOverflow());
5426   DCHECK(current_block() != NULL);
5427   DCHECK(current_block()->HasPredecessor());
5428   return Bailout(kDebuggerStatement);
5429 }
5430
5431
5432 void HOptimizedGraphBuilder::VisitCaseClause(CaseClause* clause) {
5433   UNREACHABLE();
5434 }
5435
5436
5437 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
5438   DCHECK(!HasStackOverflow());
5439   DCHECK(current_block() != NULL);
5440   DCHECK(current_block()->HasPredecessor());
5441   Handle<SharedFunctionInfo> shared_info = Compiler::GetSharedFunctionInfo(
5442       expr, current_info()->script(), top_info());
5443   // We also have a stack overflow if the recursive compilation did.
5444   if (HasStackOverflow()) return;
5445   HFunctionLiteral* instr =
5446       New<HFunctionLiteral>(shared_info, expr->pretenure());
5447   return ast_context()->ReturnInstruction(instr, expr->id());
5448 }
5449
5450
5451 void HOptimizedGraphBuilder::VisitClassLiteral(ClassLiteral* lit) {
5452   DCHECK(!HasStackOverflow());
5453   DCHECK(current_block() != NULL);
5454   DCHECK(current_block()->HasPredecessor());
5455   return Bailout(kClassLiteral);
5456 }
5457
5458
5459 void HOptimizedGraphBuilder::VisitNativeFunctionLiteral(
5460     NativeFunctionLiteral* expr) {
5461   DCHECK(!HasStackOverflow());
5462   DCHECK(current_block() != NULL);
5463   DCHECK(current_block()->HasPredecessor());
5464   return Bailout(kNativeFunctionLiteral);
5465 }
5466
5467
5468 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) {
5469   DCHECK(!HasStackOverflow());
5470   DCHECK(current_block() != NULL);
5471   DCHECK(current_block()->HasPredecessor());
5472   HBasicBlock* cond_true = graph()->CreateBasicBlock();
5473   HBasicBlock* cond_false = graph()->CreateBasicBlock();
5474   CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false));
5475
5476   // Visit the true and false subexpressions in the same AST context as the
5477   // whole expression.
5478   if (cond_true->HasPredecessor()) {
5479     cond_true->SetJoinId(expr->ThenId());
5480     set_current_block(cond_true);
5481     CHECK_BAILOUT(Visit(expr->then_expression()));
5482     cond_true = current_block();
5483   } else {
5484     cond_true = NULL;
5485   }
5486
5487   if (cond_false->HasPredecessor()) {
5488     cond_false->SetJoinId(expr->ElseId());
5489     set_current_block(cond_false);
5490     CHECK_BAILOUT(Visit(expr->else_expression()));
5491     cond_false = current_block();
5492   } else {
5493     cond_false = NULL;
5494   }
5495
5496   if (!ast_context()->IsTest()) {
5497     HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id());
5498     set_current_block(join);
5499     if (join != NULL && !ast_context()->IsEffect()) {
5500       return ast_context()->ReturnValue(Pop());
5501     }
5502   }
5503 }
5504
5505
5506 HOptimizedGraphBuilder::GlobalPropertyAccess
5507 HOptimizedGraphBuilder::LookupGlobalProperty(Variable* var, LookupIterator* it,
5508                                              PropertyAccessType access_type) {
5509   if (var->is_this() || !current_info()->has_global_object()) {
5510     return kUseGeneric;
5511   }
5512
5513   switch (it->state()) {
5514     case LookupIterator::ACCESSOR:
5515     case LookupIterator::ACCESS_CHECK:
5516     case LookupIterator::INTERCEPTOR:
5517     case LookupIterator::INTEGER_INDEXED_EXOTIC:
5518     case LookupIterator::NOT_FOUND:
5519       return kUseGeneric;
5520     case LookupIterator::DATA:
5521       if (access_type == STORE && it->IsReadOnly()) return kUseGeneric;
5522       return kUseCell;
5523     case LookupIterator::JSPROXY:
5524     case LookupIterator::TRANSITION:
5525       UNREACHABLE();
5526   }
5527   UNREACHABLE();
5528   return kUseGeneric;
5529 }
5530
5531
5532 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
5533   DCHECK(var->IsContextSlot());
5534   HValue* context = environment()->context();
5535   int length = scope()->ContextChainLength(var->scope());
5536   while (length-- > 0) {
5537     context = Add<HLoadNamedField>(
5538         context, nullptr,
5539         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
5540   }
5541   return context;
5542 }
5543
5544
5545 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
5546   DCHECK(!HasStackOverflow());
5547   DCHECK(current_block() != NULL);
5548   DCHECK(current_block()->HasPredecessor());
5549   Variable* variable = expr->var();
5550   switch (variable->location()) {
5551     case VariableLocation::GLOBAL:
5552     case VariableLocation::UNALLOCATED: {
5553       if (IsLexicalVariableMode(variable->mode())) {
5554         // TODO(rossberg): should this be an DCHECK?
5555         return Bailout(kReferenceToGlobalLexicalVariable);
5556       }
5557       // Handle known global constants like 'undefined' specially to avoid a
5558       // load from a global cell for them.
5559       Handle<Object> constant_value =
5560           isolate()->factory()->GlobalConstantFor(variable->name());
5561       if (!constant_value.is_null()) {
5562         HConstant* instr = New<HConstant>(constant_value);
5563         return ast_context()->ReturnInstruction(instr, expr->id());
5564       }
5565
5566       Handle<GlobalObject> global(current_info()->global_object());
5567
5568       // Lookup in script contexts.
5569       {
5570         Handle<ScriptContextTable> script_contexts(
5571             global->native_context()->script_context_table());
5572         ScriptContextTable::LookupResult lookup;
5573         if (ScriptContextTable::Lookup(script_contexts, variable->name(),
5574                                        &lookup)) {
5575           Handle<Context> script_context = ScriptContextTable::GetContext(
5576               script_contexts, lookup.context_index);
5577           Handle<Object> current_value =
5578               FixedArray::get(script_context, lookup.slot_index);
5579
5580           // If the values is not the hole, it will stay initialized,
5581           // so no need to generate a check.
5582           if (*current_value == *isolate()->factory()->the_hole_value()) {
5583             return Bailout(kReferenceToUninitializedVariable);
5584           }
5585           HInstruction* result = New<HLoadNamedField>(
5586               Add<HConstant>(script_context), nullptr,
5587               HObjectAccess::ForContextSlot(lookup.slot_index));
5588           return ast_context()->ReturnInstruction(result, expr->id());
5589         }
5590       }
5591
5592       LookupIterator it(global, variable->name(), LookupIterator::OWN);
5593       GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD);
5594
5595       if (type == kUseCell) {
5596         Handle<PropertyCell> cell = it.GetPropertyCell();
5597         top_info()->dependencies()->AssumePropertyCell(cell);
5598         auto cell_type = it.property_details().cell_type();
5599         if (cell_type == PropertyCellType::kConstant ||
5600             cell_type == PropertyCellType::kUndefined) {
5601           Handle<Object> constant_object(cell->value(), isolate());
5602           if (constant_object->IsConsString()) {
5603             constant_object =
5604                 String::Flatten(Handle<String>::cast(constant_object));
5605           }
5606           HConstant* constant = New<HConstant>(constant_object);
5607           return ast_context()->ReturnInstruction(constant, expr->id());
5608         } else {
5609           auto access = HObjectAccess::ForPropertyCellValue();
5610           UniqueSet<Map>* field_maps = nullptr;
5611           if (cell_type == PropertyCellType::kConstantType) {
5612             switch (cell->GetConstantType()) {
5613               case PropertyCellConstantType::kSmi:
5614                 access = access.WithRepresentation(Representation::Smi());
5615                 break;
5616               case PropertyCellConstantType::kStableMap: {
5617                 // Check that the map really is stable. The heap object could
5618                 // have mutated without the cell updating state. In that case,
5619                 // make no promises about the loaded value except that it's a
5620                 // heap object.
5621                 access =
5622                     access.WithRepresentation(Representation::HeapObject());
5623                 Handle<Map> map(HeapObject::cast(cell->value())->map());
5624                 if (map->is_stable()) {
5625                   field_maps = new (zone())
5626                       UniqueSet<Map>(Unique<Map>::CreateImmovable(map), zone());
5627                 }
5628                 break;
5629               }
5630             }
5631           }
5632           HConstant* cell_constant = Add<HConstant>(cell);
5633           HLoadNamedField* instr;
5634           if (field_maps == nullptr) {
5635             instr = New<HLoadNamedField>(cell_constant, nullptr, access);
5636           } else {
5637             instr = New<HLoadNamedField>(cell_constant, nullptr, access,
5638                                          field_maps, HType::HeapObject());
5639           }
5640           instr->ClearDependsOnFlag(kInobjectFields);
5641           instr->SetDependsOnFlag(kGlobalVars);
5642           return ast_context()->ReturnInstruction(instr, expr->id());
5643         }
5644       } else if (variable->IsGlobalSlot()) {
5645         DCHECK(variable->index() > 0);
5646         DCHECK(variable->IsStaticGlobalObjectProperty());
5647         int slot_index = variable->index();
5648         int depth = scope()->ContextChainLength(variable->scope());
5649
5650         HLoadGlobalViaContext* instr =
5651             New<HLoadGlobalViaContext>(depth, slot_index);
5652         return ast_context()->ReturnInstruction(instr, expr->id());
5653
5654       } else {
5655         HValue* global_object = Add<HLoadNamedField>(
5656             context(), nullptr,
5657             HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
5658         HLoadGlobalGeneric* instr = New<HLoadGlobalGeneric>(
5659             global_object, variable->name(), ast_context()->typeof_mode());
5660         instr->SetVectorAndSlot(handle(current_feedback_vector(), isolate()),
5661                                 expr->VariableFeedbackSlot());
5662         return ast_context()->ReturnInstruction(instr, expr->id());
5663       }
5664     }
5665
5666     case VariableLocation::PARAMETER:
5667     case VariableLocation::LOCAL: {
5668       HValue* value = LookupAndMakeLive(variable);
5669       if (value == graph()->GetConstantHole()) {
5670         DCHECK(IsDeclaredVariableMode(variable->mode()) &&
5671                variable->mode() != VAR);
5672         return Bailout(kReferenceToUninitializedVariable);
5673       }
5674       return ast_context()->ReturnValue(value);
5675     }
5676
5677     case VariableLocation::CONTEXT: {
5678       HValue* context = BuildContextChainWalk(variable);
5679       HLoadContextSlot::Mode mode;
5680       switch (variable->mode()) {
5681         case LET:
5682         case CONST:
5683           mode = HLoadContextSlot::kCheckDeoptimize;
5684           break;
5685         case CONST_LEGACY:
5686           mode = HLoadContextSlot::kCheckReturnUndefined;
5687           break;
5688         default:
5689           mode = HLoadContextSlot::kNoCheck;
5690           break;
5691       }
5692       HLoadContextSlot* instr =
5693           new(zone()) HLoadContextSlot(context, variable->index(), mode);
5694       return ast_context()->ReturnInstruction(instr, expr->id());
5695     }
5696
5697     case VariableLocation::LOOKUP:
5698       return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup);
5699   }
5700 }
5701
5702
5703 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) {
5704   DCHECK(!HasStackOverflow());
5705   DCHECK(current_block() != NULL);
5706   DCHECK(current_block()->HasPredecessor());
5707   HConstant* instr = New<HConstant>(expr->value());
5708   return ast_context()->ReturnInstruction(instr, expr->id());
5709 }
5710
5711
5712 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
5713   DCHECK(!HasStackOverflow());
5714   DCHECK(current_block() != NULL);
5715   DCHECK(current_block()->HasPredecessor());
5716   Handle<JSFunction> closure = function_state()->compilation_info()->closure();
5717   Handle<FixedArray> literals(closure->literals());
5718   HRegExpLiteral* instr = New<HRegExpLiteral>(literals,
5719                                               expr->pattern(),
5720                                               expr->flags(),
5721                                               expr->literal_index());
5722   return ast_context()->ReturnInstruction(instr, expr->id());
5723 }
5724
5725
5726 static bool CanInlinePropertyAccess(Handle<Map> map) {
5727   if (map->instance_type() == HEAP_NUMBER_TYPE) return true;
5728   if (map->instance_type() < FIRST_NONSTRING_TYPE) return true;
5729   return map->IsJSObjectMap() && !map->is_dictionary_map() &&
5730          !map->has_named_interceptor() &&
5731          // TODO(verwaest): Whitelist contexts to which we have access.
5732          !map->is_access_check_needed();
5733 }
5734
5735
5736 // Determines whether the given array or object literal boilerplate satisfies
5737 // all limits to be considered for fast deep-copying and computes the total
5738 // size of all objects that are part of the graph.
5739 static bool IsFastLiteral(Handle<JSObject> boilerplate,
5740                           int max_depth,
5741                           int* max_properties) {
5742   if (boilerplate->map()->is_deprecated() &&
5743       !JSObject::TryMigrateInstance(boilerplate)) {
5744     return false;
5745   }
5746
5747   DCHECK(max_depth >= 0 && *max_properties >= 0);
5748   if (max_depth == 0) return false;
5749
5750   Isolate* isolate = boilerplate->GetIsolate();
5751   Handle<FixedArrayBase> elements(boilerplate->elements());
5752   if (elements->length() > 0 &&
5753       elements->map() != isolate->heap()->fixed_cow_array_map()) {
5754     if (boilerplate->HasFastSmiOrObjectElements()) {
5755       Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
5756       int length = elements->length();
5757       for (int i = 0; i < length; i++) {
5758         if ((*max_properties)-- == 0) return false;
5759         Handle<Object> value(fast_elements->get(i), isolate);
5760         if (value->IsJSObject()) {
5761           Handle<JSObject> value_object = Handle<JSObject>::cast(value);
5762           if (!IsFastLiteral(value_object,
5763                              max_depth - 1,
5764                              max_properties)) {
5765             return false;
5766           }
5767         }
5768       }
5769     } else if (!boilerplate->HasFastDoubleElements()) {
5770       return false;
5771     }
5772   }
5773
5774   Handle<FixedArray> properties(boilerplate->properties());
5775   if (properties->length() > 0) {
5776     return false;
5777   } else {
5778     Handle<DescriptorArray> descriptors(
5779         boilerplate->map()->instance_descriptors());
5780     int limit = boilerplate->map()->NumberOfOwnDescriptors();
5781     for (int i = 0; i < limit; i++) {
5782       PropertyDetails details = descriptors->GetDetails(i);
5783       if (details.type() != DATA) continue;
5784       if ((*max_properties)-- == 0) return false;
5785       FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
5786       if (boilerplate->IsUnboxedDoubleField(field_index)) continue;
5787       Handle<Object> value(boilerplate->RawFastPropertyAt(field_index),
5788                            isolate);
5789       if (value->IsJSObject()) {
5790         Handle<JSObject> value_object = Handle<JSObject>::cast(value);
5791         if (!IsFastLiteral(value_object,
5792                            max_depth - 1,
5793                            max_properties)) {
5794           return false;
5795         }
5796       }
5797     }
5798   }
5799   return true;
5800 }
5801
5802
5803 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
5804   DCHECK(!HasStackOverflow());
5805   DCHECK(current_block() != NULL);
5806   DCHECK(current_block()->HasPredecessor());
5807
5808   Handle<JSFunction> closure = function_state()->compilation_info()->closure();
5809   HInstruction* literal;
5810
5811   // Check whether to use fast or slow deep-copying for boilerplate.
5812   int max_properties = kMaxFastLiteralProperties;
5813   Handle<Object> literals_cell(closure->literals()->get(expr->literal_index()),
5814                                isolate());
5815   Handle<AllocationSite> site;
5816   Handle<JSObject> boilerplate;
5817   if (!literals_cell->IsUndefined()) {
5818     // Retrieve the boilerplate
5819     site = Handle<AllocationSite>::cast(literals_cell);
5820     boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()),
5821                                    isolate());
5822   }
5823
5824   if (!boilerplate.is_null() &&
5825       IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
5826     AllocationSiteUsageContext site_context(isolate(), site, false);
5827     site_context.EnterNewScope();
5828     literal = BuildFastLiteral(boilerplate, &site_context);
5829     site_context.ExitScope(site, boilerplate);
5830   } else {
5831     NoObservableSideEffectsScope no_effects(this);
5832     Handle<FixedArray> closure_literals(closure->literals(), isolate());
5833     Handle<FixedArray> constant_properties = expr->constant_properties();
5834     int literal_index = expr->literal_index();
5835     int flags = expr->ComputeFlags(true);
5836
5837     Add<HPushArguments>(Add<HConstant>(closure_literals),
5838                         Add<HConstant>(literal_index),
5839                         Add<HConstant>(constant_properties),
5840                         Add<HConstant>(flags));
5841
5842     Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral;
5843     literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
5844                                 Runtime::FunctionForId(function_id),
5845                                 4);
5846   }
5847
5848   // The object is expected in the bailout environment during computation
5849   // of the property values and is the value of the entire expression.
5850   Push(literal);
5851   int store_slot_index = 0;
5852   for (int i = 0; i < expr->properties()->length(); i++) {
5853     ObjectLiteral::Property* property = expr->properties()->at(i);
5854     if (property->is_computed_name()) return Bailout(kComputedPropertyName);
5855     if (property->IsCompileTimeValue()) continue;
5856
5857     Literal* key = property->key()->AsLiteral();
5858     Expression* value = property->value();
5859
5860     switch (property->kind()) {
5861       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
5862         DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
5863         // Fall through.
5864       case ObjectLiteral::Property::COMPUTED:
5865         // It is safe to use [[Put]] here because the boilerplate already
5866         // contains computed properties with an uninitialized value.
5867         if (key->value()->IsInternalizedString()) {
5868           if (property->emit_store()) {
5869             CHECK_ALIVE(VisitForValue(value));
5870             HValue* value = Pop();
5871
5872             Handle<Map> map = property->GetReceiverType();
5873             Handle<String> name = key->AsPropertyName();
5874             HValue* store;
5875             FeedbackVectorICSlot slot = expr->GetNthSlot(store_slot_index++);
5876             if (map.is_null()) {
5877               // If we don't know the monomorphic type, do a generic store.
5878               CHECK_ALIVE(store = BuildNamedGeneric(STORE, NULL, slot, literal,
5879                                                     name, value));
5880             } else {
5881               PropertyAccessInfo info(this, STORE, map, name);
5882               if (info.CanAccessMonomorphic()) {
5883                 HValue* checked_literal = Add<HCheckMaps>(literal, map);
5884                 DCHECK(!info.IsAccessorConstant());
5885                 store = BuildMonomorphicAccess(
5886                     &info, literal, checked_literal, value,
5887                     BailoutId::None(), BailoutId::None());
5888               } else {
5889                 CHECK_ALIVE(store = BuildNamedGeneric(STORE, NULL, slot,
5890                                                       literal, name, value));
5891               }
5892             }
5893             if (store->IsInstruction()) {
5894               AddInstruction(HInstruction::cast(store));
5895             }
5896             DCHECK(store->HasObservableSideEffects());
5897             Add<HSimulate>(key->id(), REMOVABLE_SIMULATE);
5898
5899             // Add [[HomeObject]] to function literals.
5900             if (FunctionLiteral::NeedsHomeObject(property->value())) {
5901               Handle<Symbol> sym = isolate()->factory()->home_object_symbol();
5902               HInstruction* store_home = BuildNamedGeneric(
5903                   STORE, NULL, expr->GetNthSlot(store_slot_index++), value, sym,
5904                   literal);
5905               AddInstruction(store_home);
5906               DCHECK(store_home->HasObservableSideEffects());
5907               Add<HSimulate>(property->value()->id(), REMOVABLE_SIMULATE);
5908             }
5909           } else {
5910             CHECK_ALIVE(VisitForEffect(value));
5911           }
5912           break;
5913         }
5914         // Fall through.
5915       case ObjectLiteral::Property::PROTOTYPE:
5916       case ObjectLiteral::Property::SETTER:
5917       case ObjectLiteral::Property::GETTER:
5918         return Bailout(kObjectLiteralWithComplexProperty);
5919       default: UNREACHABLE();
5920     }
5921   }
5922
5923   // Crankshaft may not consume all the slots because it doesn't emit accessors.
5924   DCHECK(!FLAG_vector_stores || store_slot_index <= expr->slot_count());
5925
5926   if (expr->has_function()) {
5927     // Return the result of the transformation to fast properties
5928     // instead of the original since this operation changes the map
5929     // of the object. This makes sure that the original object won't
5930     // be used by other optimized code before it is transformed
5931     // (e.g. because of code motion).
5932     HToFastProperties* result = Add<HToFastProperties>(Pop());
5933     return ast_context()->ReturnValue(result);
5934   } else {
5935     return ast_context()->ReturnValue(Pop());
5936   }
5937 }
5938
5939
5940 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
5941   DCHECK(!HasStackOverflow());
5942   DCHECK(current_block() != NULL);
5943   DCHECK(current_block()->HasPredecessor());
5944   expr->BuildConstantElements(isolate());
5945   ZoneList<Expression*>* subexprs = expr->values();
5946   int length = subexprs->length();
5947   HInstruction* literal;
5948
5949   Handle<AllocationSite> site;
5950   Handle<FixedArray> literals(environment()->closure()->literals(), isolate());
5951   bool uninitialized = false;
5952   Handle<Object> literals_cell(literals->get(expr->literal_index()),
5953                                isolate());
5954   Handle<JSObject> boilerplate_object;
5955   if (literals_cell->IsUndefined()) {
5956     uninitialized = true;
5957     Handle<Object> raw_boilerplate;
5958     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
5959         isolate(), raw_boilerplate,
5960         Runtime::CreateArrayLiteralBoilerplate(
5961             isolate(), literals, expr->constant_elements(),
5962             is_strong(function_language_mode())),
5963         Bailout(kArrayBoilerplateCreationFailed));
5964
5965     boilerplate_object = Handle<JSObject>::cast(raw_boilerplate);
5966     AllocationSiteCreationContext creation_context(isolate());
5967     site = creation_context.EnterNewScope();
5968     if (JSObject::DeepWalk(boilerplate_object, &creation_context).is_null()) {
5969       return Bailout(kArrayBoilerplateCreationFailed);
5970     }
5971     creation_context.ExitScope(site, boilerplate_object);
5972     literals->set(expr->literal_index(), *site);
5973
5974     if (boilerplate_object->elements()->map() ==
5975         isolate()->heap()->fixed_cow_array_map()) {
5976       isolate()->counters()->cow_arrays_created_runtime()->Increment();
5977     }
5978   } else {
5979     DCHECK(literals_cell->IsAllocationSite());
5980     site = Handle<AllocationSite>::cast(literals_cell);
5981     boilerplate_object = Handle<JSObject>(
5982         JSObject::cast(site->transition_info()), isolate());
5983   }
5984
5985   DCHECK(!boilerplate_object.is_null());
5986   DCHECK(site->SitePointsToLiteral());
5987
5988   ElementsKind boilerplate_elements_kind =
5989       boilerplate_object->GetElementsKind();
5990
5991   // Check whether to use fast or slow deep-copying for boilerplate.
5992   int max_properties = kMaxFastLiteralProperties;
5993   if (IsFastLiteral(boilerplate_object,
5994                     kMaxFastLiteralDepth,
5995                     &max_properties)) {
5996     AllocationSiteUsageContext site_context(isolate(), site, false);
5997     site_context.EnterNewScope();
5998     literal = BuildFastLiteral(boilerplate_object, &site_context);
5999     site_context.ExitScope(site, boilerplate_object);
6000   } else {
6001     NoObservableSideEffectsScope no_effects(this);
6002     // Boilerplate already exists and constant elements are never accessed,
6003     // pass an empty fixed array to the runtime function instead.
6004     Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array();
6005     int literal_index = expr->literal_index();
6006     int flags = expr->ComputeFlags(true);
6007
6008     Add<HPushArguments>(Add<HConstant>(literals),
6009                         Add<HConstant>(literal_index),
6010                         Add<HConstant>(constants),
6011                         Add<HConstant>(flags));
6012
6013     Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral;
6014     literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
6015                                 Runtime::FunctionForId(function_id),
6016                                 4);
6017
6018     // Register to deopt if the boilerplate ElementsKind changes.
6019     top_info()->dependencies()->AssumeTransitionStable(site);
6020   }
6021
6022   // The array is expected in the bailout environment during computation
6023   // of the property values and is the value of the entire expression.
6024   Push(literal);
6025   // The literal index is on the stack, too.
6026   Push(Add<HConstant>(expr->literal_index()));
6027
6028   HInstruction* elements = NULL;
6029
6030   for (int i = 0; i < length; i++) {
6031     Expression* subexpr = subexprs->at(i);
6032     if (subexpr->IsSpread()) {
6033       return Bailout(kSpread);
6034     }
6035
6036     // If the subexpression is a literal or a simple materialized literal it
6037     // is already set in the cloned array.
6038     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
6039
6040     CHECK_ALIVE(VisitForValue(subexpr));
6041     HValue* value = Pop();
6042     if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral);
6043
6044     elements = AddLoadElements(literal);
6045
6046     HValue* key = Add<HConstant>(i);
6047
6048     switch (boilerplate_elements_kind) {
6049       case FAST_SMI_ELEMENTS:
6050       case FAST_HOLEY_SMI_ELEMENTS:
6051       case FAST_ELEMENTS:
6052       case FAST_HOLEY_ELEMENTS:
6053       case FAST_DOUBLE_ELEMENTS:
6054       case FAST_HOLEY_DOUBLE_ELEMENTS: {
6055         HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value,
6056                                               boilerplate_elements_kind);
6057         instr->SetUninitialized(uninitialized);
6058         break;
6059       }
6060       default:
6061         UNREACHABLE();
6062         break;
6063     }
6064
6065     Add<HSimulate>(expr->GetIdForElement(i));
6066   }
6067
6068   Drop(1);  // array literal index
6069   return ast_context()->ReturnValue(Pop());
6070 }
6071
6072
6073 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object,
6074                                                 Handle<Map> map) {
6075   BuildCheckHeapObject(object);
6076   return Add<HCheckMaps>(object, map);
6077 }
6078
6079
6080 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField(
6081     PropertyAccessInfo* info,
6082     HValue* checked_object) {
6083   // See if this is a load for an immutable property
6084   if (checked_object->ActualValue()->IsConstant()) {
6085     Handle<Object> object(
6086         HConstant::cast(checked_object->ActualValue())->handle(isolate()));
6087
6088     if (object->IsJSObject()) {
6089       LookupIterator it(object, info->name(),
6090                         LookupIterator::OWN_SKIP_INTERCEPTOR);
6091       Handle<Object> value = JSReceiver::GetDataProperty(&it);
6092       if (it.IsFound() && it.IsReadOnly() && !it.IsConfigurable()) {
6093         return New<HConstant>(value);
6094       }
6095     }
6096   }
6097
6098   HObjectAccess access = info->access();
6099   if (access.representation().IsDouble() &&
6100       (!FLAG_unbox_double_fields || !access.IsInobject())) {
6101     // Load the heap number.
6102     checked_object = Add<HLoadNamedField>(
6103         checked_object, nullptr,
6104         access.WithRepresentation(Representation::Tagged()));
6105     // Load the double value from it.
6106     access = HObjectAccess::ForHeapNumberValue();
6107   }
6108
6109   SmallMapList* map_list = info->field_maps();
6110   if (map_list->length() == 0) {
6111     return New<HLoadNamedField>(checked_object, checked_object, access);
6112   }
6113
6114   UniqueSet<Map>* maps = new(zone()) UniqueSet<Map>(map_list->length(), zone());
6115   for (int i = 0; i < map_list->length(); ++i) {
6116     maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone());
6117   }
6118   return New<HLoadNamedField>(
6119       checked_object, checked_object, access, maps, info->field_type());
6120 }
6121
6122
6123 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
6124     PropertyAccessInfo* info,
6125     HValue* checked_object,
6126     HValue* value) {
6127   bool transition_to_field = info->IsTransition();
6128   // TODO(verwaest): Move this logic into PropertyAccessInfo.
6129   HObjectAccess field_access = info->access();
6130
6131   HStoreNamedField *instr;
6132   if (field_access.representation().IsDouble() &&
6133       (!FLAG_unbox_double_fields || !field_access.IsInobject())) {
6134     HObjectAccess heap_number_access =
6135         field_access.WithRepresentation(Representation::Tagged());
6136     if (transition_to_field) {
6137       // The store requires a mutable HeapNumber to be allocated.
6138       NoObservableSideEffectsScope no_side_effects(this);
6139       HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
6140
6141       // TODO(hpayer): Allocation site pretenuring support.
6142       HInstruction* heap_number = Add<HAllocate>(heap_number_size,
6143           HType::HeapObject(),
6144           NOT_TENURED,
6145           MUTABLE_HEAP_NUMBER_TYPE);
6146       AddStoreMapConstant(
6147           heap_number, isolate()->factory()->mutable_heap_number_map());
6148       Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
6149                             value);
6150       instr = New<HStoreNamedField>(checked_object->ActualValue(),
6151                                     heap_number_access,
6152                                     heap_number);
6153     } else {
6154       // Already holds a HeapNumber; load the box and write its value field.
6155       HInstruction* heap_number =
6156           Add<HLoadNamedField>(checked_object, nullptr, heap_number_access);
6157       instr = New<HStoreNamedField>(heap_number,
6158                                     HObjectAccess::ForHeapNumberValue(),
6159                                     value, STORE_TO_INITIALIZED_ENTRY);
6160     }
6161   } else {
6162     if (field_access.representation().IsHeapObject()) {
6163       BuildCheckHeapObject(value);
6164     }
6165
6166     if (!info->field_maps()->is_empty()) {
6167       DCHECK(field_access.representation().IsHeapObject());
6168       value = Add<HCheckMaps>(value, info->field_maps());
6169     }
6170
6171     // This is a normal store.
6172     instr = New<HStoreNamedField>(
6173         checked_object->ActualValue(), field_access, value,
6174         transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY);
6175   }
6176
6177   if (transition_to_field) {
6178     Handle<Map> transition(info->transition());
6179     DCHECK(!transition->is_deprecated());
6180     instr->SetTransition(Add<HConstant>(transition));
6181   }
6182   return instr;
6183 }
6184
6185
6186 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible(
6187     PropertyAccessInfo* info) {
6188   if (!CanInlinePropertyAccess(map_)) return false;
6189
6190   // Currently only handle Type::Number as a polymorphic case.
6191   // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
6192   // instruction.
6193   if (IsNumberType()) return false;
6194
6195   // Values are only compatible for monomorphic load if they all behave the same
6196   // regarding value wrappers.
6197   if (IsValueWrapped() != info->IsValueWrapped()) return false;
6198
6199   if (!LookupDescriptor()) return false;
6200
6201   if (!IsFound()) {
6202     return (!info->IsFound() || info->has_holder()) &&
6203            map()->prototype() == info->map()->prototype();
6204   }
6205
6206   // Mismatch if the other access info found the property in the prototype
6207   // chain.
6208   if (info->has_holder()) return false;
6209
6210   if (IsAccessorConstant()) {
6211     return accessor_.is_identical_to(info->accessor_) &&
6212         api_holder_.is_identical_to(info->api_holder_);
6213   }
6214
6215   if (IsDataConstant()) {
6216     return constant_.is_identical_to(info->constant_);
6217   }
6218
6219   DCHECK(IsData());
6220   if (!info->IsData()) return false;
6221
6222   Representation r = access_.representation();
6223   if (IsLoad()) {
6224     if (!info->access_.representation().IsCompatibleForLoad(r)) return false;
6225   } else {
6226     if (!info->access_.representation().IsCompatibleForStore(r)) return false;
6227   }
6228   if (info->access_.offset() != access_.offset()) return false;
6229   if (info->access_.IsInobject() != access_.IsInobject()) return false;
6230   if (IsLoad()) {
6231     if (field_maps_.is_empty()) {
6232       info->field_maps_.Clear();
6233     } else if (!info->field_maps_.is_empty()) {
6234       for (int i = 0; i < field_maps_.length(); ++i) {
6235         info->field_maps_.AddMapIfMissing(field_maps_.at(i), info->zone());
6236       }
6237       info->field_maps_.Sort();
6238     }
6239   } else {
6240     // We can only merge stores that agree on their field maps. The comparison
6241     // below is safe, since we keep the field maps sorted.
6242     if (field_maps_.length() != info->field_maps_.length()) return false;
6243     for (int i = 0; i < field_maps_.length(); ++i) {
6244       if (!field_maps_.at(i).is_identical_to(info->field_maps_.at(i))) {
6245         return false;
6246       }
6247     }
6248   }
6249   info->GeneralizeRepresentation(r);
6250   info->field_type_ = info->field_type_.Combine(field_type_);
6251   return true;
6252 }
6253
6254
6255 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() {
6256   if (!map_->IsJSObjectMap()) return true;
6257   LookupDescriptor(*map_, *name_);
6258   return LoadResult(map_);
6259 }
6260
6261
6262 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
6263   if (!IsLoad() && IsProperty() && IsReadOnly()) {
6264     return false;
6265   }
6266
6267   if (IsData()) {
6268     // Construct the object field access.
6269     int index = GetLocalFieldIndexFromMap(map);
6270     access_ = HObjectAccess::ForField(map, index, representation(), name_);
6271
6272     // Load field map for heap objects.
6273     return LoadFieldMaps(map);
6274   } else if (IsAccessorConstant()) {
6275     Handle<Object> accessors = GetAccessorsFromMap(map);
6276     if (!accessors->IsAccessorPair()) return false;
6277     Object* raw_accessor =
6278         IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter()
6279                  : Handle<AccessorPair>::cast(accessors)->setter();
6280     if (!raw_accessor->IsJSFunction()) return false;
6281     Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor));
6282     if (accessor->shared()->IsApiFunction()) {
6283       CallOptimization call_optimization(accessor);
6284       if (call_optimization.is_simple_api_call()) {
6285         CallOptimization::HolderLookup holder_lookup;
6286         api_holder_ =
6287             call_optimization.LookupHolderOfExpectedType(map_, &holder_lookup);
6288       }
6289     }
6290     accessor_ = accessor;
6291   } else if (IsDataConstant()) {
6292     constant_ = GetConstantFromMap(map);
6293   }
6294
6295   return true;
6296 }
6297
6298
6299 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps(
6300     Handle<Map> map) {
6301   // Clear any previously collected field maps/type.
6302   field_maps_.Clear();
6303   field_type_ = HType::Tagged();
6304
6305   // Figure out the field type from the accessor map.
6306   Handle<HeapType> field_type = GetFieldTypeFromMap(map);
6307
6308   // Collect the (stable) maps from the field type.
6309   int num_field_maps = field_type->NumClasses();
6310   if (num_field_maps > 0) {
6311     DCHECK(access_.representation().IsHeapObject());
6312     field_maps_.Reserve(num_field_maps, zone());
6313     HeapType::Iterator<Map> it = field_type->Classes();
6314     while (!it.Done()) {
6315       Handle<Map> field_map = it.Current();
6316       if (!field_map->is_stable()) {
6317         field_maps_.Clear();
6318         break;
6319       }
6320       field_maps_.Add(field_map, zone());
6321       it.Advance();
6322     }
6323   }
6324
6325   if (field_maps_.is_empty()) {
6326     // Store is not safe if the field map was cleared.
6327     return IsLoad() || !field_type->Is(HeapType::None());
6328   }
6329
6330   field_maps_.Sort();
6331   DCHECK_EQ(num_field_maps, field_maps_.length());
6332
6333   // Determine field HType from field HeapType.
6334   field_type_ = HType::FromType<HeapType>(field_type);
6335   DCHECK(field_type_.IsHeapObject());
6336
6337   // Add dependency on the map that introduced the field.
6338   top_info()->dependencies()->AssumeFieldType(GetFieldOwnerFromMap(map));
6339   return true;
6340 }
6341
6342
6343 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
6344   Handle<Map> map = this->map();
6345
6346   while (map->prototype()->IsJSObject()) {
6347     holder_ = handle(JSObject::cast(map->prototype()));
6348     if (holder_->map()->is_deprecated()) {
6349       JSObject::TryMigrateInstance(holder_);
6350     }
6351     map = Handle<Map>(holder_->map());
6352     if (!CanInlinePropertyAccess(map)) {
6353       NotFound();
6354       return false;
6355     }
6356     LookupDescriptor(*map, *name_);
6357     if (IsFound()) return LoadResult(map);
6358   }
6359
6360   NotFound();
6361   return !map->prototype()->IsJSReceiver();
6362 }
6363
6364
6365 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsIntegerIndexedExotic() {
6366   InstanceType instance_type = map_->instance_type();
6367   return instance_type == JS_TYPED_ARRAY_TYPE &&
6368          IsSpecialIndex(isolate()->unicode_cache(), *name_);
6369 }
6370
6371
6372 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
6373   if (!CanInlinePropertyAccess(map_)) return false;
6374   if (IsJSObjectFieldAccessor()) return IsLoad();
6375   if (IsJSArrayBufferViewFieldAccessor()) return IsLoad();
6376   if (map_->function_with_prototype() && !map_->has_non_instance_prototype() &&
6377       name_.is_identical_to(isolate()->factory()->prototype_string())) {
6378     return IsLoad();
6379   }
6380   if (!LookupDescriptor()) return false;
6381   if (IsFound()) return IsLoad() || !IsReadOnly();
6382   if (IsIntegerIndexedExotic()) return false;
6383   if (!LookupInPrototypes()) return false;
6384   if (IsLoad()) return true;
6385
6386   if (IsAccessorConstant()) return true;
6387   LookupTransition(*map_, *name_, NONE);
6388   if (IsTransitionToData() && map_->unused_property_fields() > 0) {
6389     // Construct the object field access.
6390     int descriptor = transition()->LastAdded();
6391     int index =
6392         transition()->instance_descriptors()->GetFieldIndex(descriptor) -
6393         map_->GetInObjectProperties();
6394     PropertyDetails details =
6395         transition()->instance_descriptors()->GetDetails(descriptor);
6396     Representation representation = details.representation();
6397     access_ = HObjectAccess::ForField(map_, index, representation, name_);
6398
6399     // Load field map for heap objects.
6400     return LoadFieldMaps(transition());
6401   }
6402   return false;
6403 }
6404
6405
6406 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic(
6407     SmallMapList* maps) {
6408   DCHECK(map_.is_identical_to(maps->first()));
6409   if (!CanAccessMonomorphic()) return false;
6410   STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
6411   if (maps->length() > kMaxLoadPolymorphism) return false;
6412   HObjectAccess access = HObjectAccess::ForMap();  // bogus default
6413   if (GetJSObjectFieldAccess(&access)) {
6414     for (int i = 1; i < maps->length(); ++i) {
6415       PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
6416       HObjectAccess test_access = HObjectAccess::ForMap();  // bogus default
6417       if (!test_info.GetJSObjectFieldAccess(&test_access)) return false;
6418       if (!access.Equals(test_access)) return false;
6419     }
6420     return true;
6421   }
6422   if (GetJSArrayBufferViewFieldAccess(&access)) {
6423     for (int i = 1; i < maps->length(); ++i) {
6424       PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
6425       HObjectAccess test_access = HObjectAccess::ForMap();  // bogus default
6426       if (!test_info.GetJSArrayBufferViewFieldAccess(&test_access)) {
6427         return false;
6428       }
6429       if (!access.Equals(test_access)) return false;
6430     }
6431     return true;
6432   }
6433
6434   // Currently only handle numbers as a polymorphic case.
6435   // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
6436   // instruction.
6437   if (IsNumberType()) return false;
6438
6439   // Multiple maps cannot transition to the same target map.
6440   DCHECK(!IsLoad() || !IsTransition());
6441   if (IsTransition() && maps->length() > 1) return false;
6442
6443   for (int i = 1; i < maps->length(); ++i) {
6444     PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
6445     if (!test_info.IsCompatible(this)) return false;
6446   }
6447
6448   return true;
6449 }
6450
6451
6452 Handle<Map> HOptimizedGraphBuilder::PropertyAccessInfo::map() {
6453   JSFunction* ctor = IC::GetRootConstructor(
6454       *map_, current_info()->closure()->context()->native_context());
6455   if (ctor != NULL) return handle(ctor->initial_map());
6456   return map_;
6457 }
6458
6459
6460 static bool NeedsWrapping(Handle<Map> map, Handle<JSFunction> target) {
6461   return !map->IsJSObjectMap() &&
6462          is_sloppy(target->shared()->language_mode()) &&
6463          !target->shared()->native();
6464 }
6465
6466
6467 bool HOptimizedGraphBuilder::PropertyAccessInfo::NeedsWrappingFor(
6468     Handle<JSFunction> target) const {
6469   return NeedsWrapping(map_, target);
6470 }
6471
6472
6473 HValue* HOptimizedGraphBuilder::BuildMonomorphicAccess(
6474     PropertyAccessInfo* info, HValue* object, HValue* checked_object,
6475     HValue* value, BailoutId ast_id, BailoutId return_id,
6476     bool can_inline_accessor) {
6477   HObjectAccess access = HObjectAccess::ForMap();  // bogus default
6478   if (info->GetJSObjectFieldAccess(&access)) {
6479     DCHECK(info->IsLoad());
6480     return New<HLoadNamedField>(object, checked_object, access);
6481   }
6482
6483   if (info->GetJSArrayBufferViewFieldAccess(&access)) {
6484     DCHECK(info->IsLoad());
6485     checked_object = Add<HCheckArrayBufferNotNeutered>(checked_object);
6486     return New<HLoadNamedField>(object, checked_object, access);
6487   }
6488
6489   if (info->name().is_identical_to(isolate()->factory()->prototype_string()) &&
6490       info->map()->function_with_prototype()) {
6491     DCHECK(!info->map()->has_non_instance_prototype());
6492     return New<HLoadFunctionPrototype>(checked_object);
6493   }
6494
6495   HValue* checked_holder = checked_object;
6496   if (info->has_holder()) {
6497     Handle<JSObject> prototype(JSObject::cast(info->map()->prototype()));
6498     checked_holder = BuildCheckPrototypeMaps(prototype, info->holder());
6499   }
6500
6501   if (!info->IsFound()) {
6502     DCHECK(info->IsLoad());
6503     if (is_strong(function_language_mode())) {
6504       return New<HCallRuntime>(
6505           isolate()->factory()->empty_string(),
6506           Runtime::FunctionForId(Runtime::kThrowStrongModeImplicitConversion),
6507           0);
6508     } else {
6509       return graph()->GetConstantUndefined();
6510     }
6511   }
6512
6513   if (info->IsData()) {
6514     if (info->IsLoad()) {
6515       return BuildLoadNamedField(info, checked_holder);
6516     } else {
6517       return BuildStoreNamedField(info, checked_object, value);
6518     }
6519   }
6520
6521   if (info->IsTransition()) {
6522     DCHECK(!info->IsLoad());
6523     return BuildStoreNamedField(info, checked_object, value);
6524   }
6525
6526   if (info->IsAccessorConstant()) {
6527     Push(checked_object);
6528     int argument_count = 1;
6529     if (!info->IsLoad()) {
6530       argument_count = 2;
6531       Push(value);
6532     }
6533
6534     if (info->NeedsWrappingFor(info->accessor())) {
6535       HValue* function = Add<HConstant>(info->accessor());
6536       PushArgumentsFromEnvironment(argument_count);
6537       return New<HCallFunction>(function, argument_count, WRAP_AND_CALL);
6538     } else if (FLAG_inline_accessors && can_inline_accessor) {
6539       bool success = info->IsLoad()
6540           ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id)
6541           : TryInlineSetter(
6542               info->accessor(), info->map(), ast_id, return_id, value);
6543       if (success || HasStackOverflow()) return NULL;
6544     }
6545
6546     PushArgumentsFromEnvironment(argument_count);
6547     return BuildCallConstantFunction(info->accessor(), argument_count);
6548   }
6549
6550   DCHECK(info->IsDataConstant());
6551   if (info->IsLoad()) {
6552     return New<HConstant>(info->constant());
6553   } else {
6554     return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant()));
6555   }
6556 }
6557
6558
6559 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
6560     PropertyAccessType access_type, Expression* expr, FeedbackVectorICSlot slot,
6561     BailoutId ast_id, BailoutId return_id, HValue* object, HValue* value,
6562     SmallMapList* maps, Handle<String> name) {
6563   // Something did not match; must use a polymorphic load.
6564   int count = 0;
6565   HBasicBlock* join = NULL;
6566   HBasicBlock* number_block = NULL;
6567   bool handled_string = false;
6568
6569   bool handle_smi = false;
6570   STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
6571   int i;
6572   for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) {
6573     PropertyAccessInfo info(this, access_type, maps->at(i), name);
6574     if (info.IsStringType()) {
6575       if (handled_string) continue;
6576       handled_string = true;
6577     }
6578     if (info.CanAccessMonomorphic()) {
6579       count++;
6580       if (info.IsNumberType()) {
6581         handle_smi = true;
6582         break;
6583       }
6584     }
6585   }
6586
6587   if (i < maps->length()) {
6588     count = -1;
6589     maps->Clear();
6590   } else {
6591     count = 0;
6592   }
6593   HControlInstruction* smi_check = NULL;
6594   handled_string = false;
6595
6596   for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) {
6597     PropertyAccessInfo info(this, access_type, maps->at(i), name);
6598     if (info.IsStringType()) {
6599       if (handled_string) continue;
6600       handled_string = true;
6601     }
6602     if (!info.CanAccessMonomorphic()) continue;
6603
6604     if (count == 0) {
6605       join = graph()->CreateBasicBlock();
6606       if (handle_smi) {
6607         HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
6608         HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
6609         number_block = graph()->CreateBasicBlock();
6610         smi_check = New<HIsSmiAndBranch>(
6611             object, empty_smi_block, not_smi_block);
6612         FinishCurrentBlock(smi_check);
6613         GotoNoSimulate(empty_smi_block, number_block);
6614         set_current_block(not_smi_block);
6615       } else {
6616         BuildCheckHeapObject(object);
6617       }
6618     }
6619     ++count;
6620     HBasicBlock* if_true = graph()->CreateBasicBlock();
6621     HBasicBlock* if_false = graph()->CreateBasicBlock();
6622     HUnaryControlInstruction* compare;
6623
6624     HValue* dependency;
6625     if (info.IsNumberType()) {
6626       Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
6627       compare = New<HCompareMap>(object, heap_number_map, if_true, if_false);
6628       dependency = smi_check;
6629     } else if (info.IsStringType()) {
6630       compare = New<HIsStringAndBranch>(object, if_true, if_false);
6631       dependency = compare;
6632     } else {
6633       compare = New<HCompareMap>(object, info.map(), if_true, if_false);
6634       dependency = compare;
6635     }
6636     FinishCurrentBlock(compare);
6637
6638     if (info.IsNumberType()) {
6639       GotoNoSimulate(if_true, number_block);
6640       if_true = number_block;
6641     }
6642
6643     set_current_block(if_true);
6644
6645     HValue* access =
6646         BuildMonomorphicAccess(&info, object, dependency, value, ast_id,
6647                                return_id, FLAG_polymorphic_inlining);
6648
6649     HValue* result = NULL;
6650     switch (access_type) {
6651       case LOAD:
6652         result = access;
6653         break;
6654       case STORE:
6655         result = value;
6656         break;
6657     }
6658
6659     if (access == NULL) {
6660       if (HasStackOverflow()) return;
6661     } else {
6662       if (access->IsInstruction()) {
6663         HInstruction* instr = HInstruction::cast(access);
6664         if (!instr->IsLinked()) AddInstruction(instr);
6665       }
6666       if (!ast_context()->IsEffect()) Push(result);
6667     }
6668
6669     if (current_block() != NULL) Goto(join);
6670     set_current_block(if_false);
6671   }
6672
6673   // Finish up.  Unconditionally deoptimize if we've handled all the maps we
6674   // know about and do not want to handle ones we've never seen.  Otherwise
6675   // use a generic IC.
6676   if (count == maps->length() && FLAG_deoptimize_uncommon_cases) {
6677     FinishExitWithHardDeoptimization(
6678         Deoptimizer::kUnknownMapInPolymorphicAccess);
6679   } else {
6680     HInstruction* instr =
6681         BuildNamedGeneric(access_type, expr, slot, object, name, value);
6682     AddInstruction(instr);
6683     if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value);
6684
6685     if (join != NULL) {
6686       Goto(join);
6687     } else {
6688       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6689       if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
6690       return;
6691     }
6692   }
6693
6694   DCHECK(join != NULL);
6695   if (join->HasPredecessor()) {
6696     join->SetJoinId(ast_id);
6697     set_current_block(join);
6698     if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
6699   } else {
6700     set_current_block(NULL);
6701   }
6702 }
6703
6704
6705 static bool ComputeReceiverTypes(Expression* expr,
6706                                  HValue* receiver,
6707                                  SmallMapList** t,
6708                                  Zone* zone) {
6709   SmallMapList* maps = expr->GetReceiverTypes();
6710   *t = maps;
6711   bool monomorphic = expr->IsMonomorphic();
6712   if (maps != NULL && receiver->HasMonomorphicJSObjectType()) {
6713     Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
6714     maps->FilterForPossibleTransitions(root_map);
6715     monomorphic = maps->length() == 1;
6716   }
6717   return monomorphic && CanInlinePropertyAccess(maps->first());
6718 }
6719
6720
6721 static bool AreStringTypes(SmallMapList* maps) {
6722   for (int i = 0; i < maps->length(); i++) {
6723     if (maps->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
6724   }
6725   return true;
6726 }
6727
6728
6729 void HOptimizedGraphBuilder::BuildStore(Expression* expr, Property* prop,
6730                                         FeedbackVectorICSlot slot,
6731                                         BailoutId ast_id, BailoutId return_id,
6732                                         bool is_uninitialized) {
6733   if (!prop->key()->IsPropertyName()) {
6734     // Keyed store.
6735     HValue* value = Pop();
6736     HValue* key = Pop();
6737     HValue* object = Pop();
6738     bool has_side_effects = false;
6739     HValue* result =
6740         HandleKeyedElementAccess(object, key, value, expr, slot, ast_id,
6741                                  return_id, STORE, &has_side_effects);
6742     if (has_side_effects) {
6743       if (!ast_context()->IsEffect()) Push(value);
6744       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6745       if (!ast_context()->IsEffect()) Drop(1);
6746     }
6747     if (result == NULL) return;
6748     return ast_context()->ReturnValue(value);
6749   }
6750
6751   // Named store.
6752   HValue* value = Pop();
6753   HValue* object = Pop();
6754
6755   Literal* key = prop->key()->AsLiteral();
6756   Handle<String> name = Handle<String>::cast(key->value());
6757   DCHECK(!name.is_null());
6758
6759   HValue* access = BuildNamedAccess(STORE, ast_id, return_id, expr, slot,
6760                                     object, name, value, is_uninitialized);
6761   if (access == NULL) return;
6762
6763   if (!ast_context()->IsEffect()) Push(value);
6764   if (access->IsInstruction()) AddInstruction(HInstruction::cast(access));
6765   if (access->HasObservableSideEffects()) {
6766     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6767   }
6768   if (!ast_context()->IsEffect()) Drop(1);
6769   return ast_context()->ReturnValue(value);
6770 }
6771
6772
6773 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
6774   Property* prop = expr->target()->AsProperty();
6775   DCHECK(prop != NULL);
6776   CHECK_ALIVE(VisitForValue(prop->obj()));
6777   if (!prop->key()->IsPropertyName()) {
6778     CHECK_ALIVE(VisitForValue(prop->key()));
6779   }
6780   CHECK_ALIVE(VisitForValue(expr->value()));
6781   BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(),
6782              expr->AssignmentId(), expr->IsUninitialized());
6783 }
6784
6785
6786 // Because not every expression has a position and there is not common
6787 // superclass of Assignment and CountOperation, we cannot just pass the
6788 // owning expression instead of position and ast_id separately.
6789 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
6790     Variable* var, HValue* value, FeedbackVectorICSlot ic_slot,
6791     BailoutId ast_id) {
6792   Handle<GlobalObject> global(current_info()->global_object());
6793
6794   // Lookup in script contexts.
6795   {
6796     Handle<ScriptContextTable> script_contexts(
6797         global->native_context()->script_context_table());
6798     ScriptContextTable::LookupResult lookup;
6799     if (ScriptContextTable::Lookup(script_contexts, var->name(), &lookup)) {
6800       if (lookup.mode == CONST) {
6801         return Bailout(kNonInitializerAssignmentToConst);
6802       }
6803       Handle<Context> script_context =
6804           ScriptContextTable::GetContext(script_contexts, lookup.context_index);
6805
6806       Handle<Object> current_value =
6807           FixedArray::get(script_context, lookup.slot_index);
6808
6809       // If the values is not the hole, it will stay initialized,
6810       // so no need to generate a check.
6811       if (*current_value == *isolate()->factory()->the_hole_value()) {
6812         return Bailout(kReferenceToUninitializedVariable);
6813       }
6814
6815       HStoreNamedField* instr = Add<HStoreNamedField>(
6816           Add<HConstant>(script_context),
6817           HObjectAccess::ForContextSlot(lookup.slot_index), value);
6818       USE(instr);
6819       DCHECK(instr->HasObservableSideEffects());
6820       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6821       return;
6822     }
6823   }
6824
6825   LookupIterator it(global, var->name(), LookupIterator::OWN);
6826   GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE);
6827   if (type == kUseCell) {
6828     Handle<PropertyCell> cell = it.GetPropertyCell();
6829     top_info()->dependencies()->AssumePropertyCell(cell);
6830     auto cell_type = it.property_details().cell_type();
6831     if (cell_type == PropertyCellType::kConstant ||
6832         cell_type == PropertyCellType::kUndefined) {
6833       Handle<Object> constant(cell->value(), isolate());
6834       if (value->IsConstant()) {
6835         HConstant* c_value = HConstant::cast(value);
6836         if (!constant.is_identical_to(c_value->handle(isolate()))) {
6837           Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment,
6838                            Deoptimizer::EAGER);
6839         }
6840       } else {
6841         HValue* c_constant = Add<HConstant>(constant);
6842         IfBuilder builder(this);
6843         if (constant->IsNumber()) {
6844           builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ);
6845         } else {
6846           builder.If<HCompareObjectEqAndBranch>(value, c_constant);
6847         }
6848         builder.Then();
6849         builder.Else();
6850         Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment,
6851                          Deoptimizer::EAGER);
6852         builder.End();
6853       }
6854     }
6855     HConstant* cell_constant = Add<HConstant>(cell);
6856     auto access = HObjectAccess::ForPropertyCellValue();
6857     if (cell_type == PropertyCellType::kConstantType) {
6858       switch (cell->GetConstantType()) {
6859         case PropertyCellConstantType::kSmi:
6860           access = access.WithRepresentation(Representation::Smi());
6861           break;
6862         case PropertyCellConstantType::kStableMap: {
6863           // The map may no longer be stable, deopt if it's ever different from
6864           // what is currently there, which will allow for restablization.
6865           Handle<Map> map(HeapObject::cast(cell->value())->map());
6866           Add<HCheckHeapObject>(value);
6867           value = Add<HCheckMaps>(value, map);
6868           access = access.WithRepresentation(Representation::HeapObject());
6869           break;
6870         }
6871       }
6872     }
6873     HInstruction* instr = Add<HStoreNamedField>(cell_constant, access, value);
6874     instr->ClearChangesFlag(kInobjectFields);
6875     instr->SetChangesFlag(kGlobalVars);
6876     if (instr->HasObservableSideEffects()) {
6877       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6878     }
6879   } else if (var->IsGlobalSlot()) {
6880     DCHECK(var->index() > 0);
6881     DCHECK(var->IsStaticGlobalObjectProperty());
6882     int slot_index = var->index();
6883     int depth = scope()->ContextChainLength(var->scope());
6884
6885     HStoreGlobalViaContext* instr = Add<HStoreGlobalViaContext>(
6886         value, depth, slot_index, function_language_mode());
6887     USE(instr);
6888     DCHECK(instr->HasObservableSideEffects());
6889     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6890
6891   } else {
6892     HValue* global_object = Add<HLoadNamedField>(
6893         context(), nullptr,
6894         HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
6895     HStoreNamedGeneric* instr =
6896         Add<HStoreNamedGeneric>(global_object, var->name(), value,
6897                                 function_language_mode(), PREMONOMORPHIC);
6898     if (FLAG_vector_stores) {
6899       Handle<TypeFeedbackVector> vector =
6900           handle(current_feedback_vector(), isolate());
6901       instr->SetVectorAndSlot(vector, ic_slot);
6902     }
6903     USE(instr);
6904     DCHECK(instr->HasObservableSideEffects());
6905     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6906   }
6907 }
6908
6909
6910 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
6911   Expression* target = expr->target();
6912   VariableProxy* proxy = target->AsVariableProxy();
6913   Property* prop = target->AsProperty();
6914   DCHECK(proxy == NULL || prop == NULL);
6915
6916   // We have a second position recorded in the FullCodeGenerator to have
6917   // type feedback for the binary operation.
6918   BinaryOperation* operation = expr->binary_operation();
6919
6920   if (proxy != NULL) {
6921     Variable* var = proxy->var();
6922     if (var->mode() == LET)  {
6923       return Bailout(kUnsupportedLetCompoundAssignment);
6924     }
6925
6926     CHECK_ALIVE(VisitForValue(operation));
6927
6928     switch (var->location()) {
6929       case VariableLocation::GLOBAL:
6930       case VariableLocation::UNALLOCATED:
6931         HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(),
6932                                        expr->AssignmentId());
6933         break;
6934
6935       case VariableLocation::PARAMETER:
6936       case VariableLocation::LOCAL:
6937         if (var->mode() == CONST_LEGACY)  {
6938           return Bailout(kUnsupportedConstCompoundAssignment);
6939         }
6940         if (var->mode() == CONST) {
6941           return Bailout(kNonInitializerAssignmentToConst);
6942         }
6943         BindIfLive(var, Top());
6944         break;
6945
6946       case VariableLocation::CONTEXT: {
6947         // Bail out if we try to mutate a parameter value in a function
6948         // using the arguments object.  We do not (yet) correctly handle the
6949         // arguments property of the function.
6950         if (current_info()->scope()->arguments() != NULL) {
6951           // Parameters will be allocated to context slots.  We have no
6952           // direct way to detect that the variable is a parameter so we do
6953           // a linear search of the parameter variables.
6954           int count = current_info()->scope()->num_parameters();
6955           for (int i = 0; i < count; ++i) {
6956             if (var == current_info()->scope()->parameter(i)) {
6957               Bailout(kAssignmentToParameterFunctionUsesArgumentsObject);
6958             }
6959           }
6960         }
6961
6962         HStoreContextSlot::Mode mode;
6963
6964         switch (var->mode()) {
6965           case LET:
6966             mode = HStoreContextSlot::kCheckDeoptimize;
6967             break;
6968           case CONST:
6969             return Bailout(kNonInitializerAssignmentToConst);
6970           case CONST_LEGACY:
6971             return ast_context()->ReturnValue(Pop());
6972           default:
6973             mode = HStoreContextSlot::kNoCheck;
6974         }
6975
6976         HValue* context = BuildContextChainWalk(var);
6977         HStoreContextSlot* instr = Add<HStoreContextSlot>(
6978             context, var->index(), mode, Top());
6979         if (instr->HasObservableSideEffects()) {
6980           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
6981         }
6982         break;
6983       }
6984
6985       case VariableLocation::LOOKUP:
6986         return Bailout(kCompoundAssignmentToLookupSlot);
6987     }
6988     return ast_context()->ReturnValue(Pop());
6989
6990   } else if (prop != NULL) {
6991     CHECK_ALIVE(VisitForValue(prop->obj()));
6992     HValue* object = Top();
6993     HValue* key = NULL;
6994     if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
6995       CHECK_ALIVE(VisitForValue(prop->key()));
6996       key = Top();
6997     }
6998
6999     CHECK_ALIVE(PushLoad(prop, object, key));
7000
7001     CHECK_ALIVE(VisitForValue(expr->value()));
7002     HValue* right = Pop();
7003     HValue* left = Pop();
7004
7005     Push(BuildBinaryOperation(operation, left, right, PUSH_BEFORE_SIMULATE));
7006
7007     BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(),
7008                expr->AssignmentId(), expr->IsUninitialized());
7009   } else {
7010     return Bailout(kInvalidLhsInCompoundAssignment);
7011   }
7012 }
7013
7014
7015 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
7016   DCHECK(!HasStackOverflow());
7017   DCHECK(current_block() != NULL);
7018   DCHECK(current_block()->HasPredecessor());
7019   VariableProxy* proxy = expr->target()->AsVariableProxy();
7020   Property* prop = expr->target()->AsProperty();
7021   DCHECK(proxy == NULL || prop == NULL);
7022
7023   if (expr->is_compound()) {
7024     HandleCompoundAssignment(expr);
7025     return;
7026   }
7027
7028   if (prop != NULL) {
7029     HandlePropertyAssignment(expr);
7030   } else if (proxy != NULL) {
7031     Variable* var = proxy->var();
7032
7033     if (var->mode() == CONST) {
7034       if (expr->op() != Token::INIT_CONST) {
7035         return Bailout(kNonInitializerAssignmentToConst);
7036       }
7037     } else if (var->mode() == CONST_LEGACY) {
7038       if (expr->op() != Token::INIT_CONST_LEGACY) {
7039         CHECK_ALIVE(VisitForValue(expr->value()));
7040         return ast_context()->ReturnValue(Pop());
7041       }
7042
7043       if (var->IsStackAllocated()) {
7044         // We insert a use of the old value to detect unsupported uses of const
7045         // variables (e.g. initialization inside a loop).
7046         HValue* old_value = environment()->Lookup(var);
7047         Add<HUseConst>(old_value);
7048       }
7049     }
7050
7051     if (proxy->IsArguments()) return Bailout(kAssignmentToArguments);
7052
7053     // Handle the assignment.
7054     switch (var->location()) {
7055       case VariableLocation::GLOBAL:
7056       case VariableLocation::UNALLOCATED:
7057         CHECK_ALIVE(VisitForValue(expr->value()));
7058         HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(),
7059                                        expr->AssignmentId());
7060         return ast_context()->ReturnValue(Pop());
7061
7062       case VariableLocation::PARAMETER:
7063       case VariableLocation::LOCAL: {
7064         // Perform an initialization check for let declared variables
7065         // or parameters.
7066         if (var->mode() == LET && expr->op() == Token::ASSIGN) {
7067           HValue* env_value = environment()->Lookup(var);
7068           if (env_value == graph()->GetConstantHole()) {
7069             return Bailout(kAssignmentToLetVariableBeforeInitialization);
7070           }
7071         }
7072         // We do not allow the arguments object to occur in a context where it
7073         // may escape, but assignments to stack-allocated locals are
7074         // permitted.
7075         CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
7076         HValue* value = Pop();
7077         BindIfLive(var, value);
7078         return ast_context()->ReturnValue(value);
7079       }
7080
7081       case VariableLocation::CONTEXT: {
7082         // Bail out if we try to mutate a parameter value in a function using
7083         // the arguments object.  We do not (yet) correctly handle the
7084         // arguments property of the function.
7085         if (current_info()->scope()->arguments() != NULL) {
7086           // Parameters will rewrite to context slots.  We have no direct way
7087           // to detect that the variable is a parameter.
7088           int count = current_info()->scope()->num_parameters();
7089           for (int i = 0; i < count; ++i) {
7090             if (var == current_info()->scope()->parameter(i)) {
7091               return Bailout(kAssignmentToParameterInArgumentsObject);
7092             }
7093           }
7094         }
7095
7096         CHECK_ALIVE(VisitForValue(expr->value()));
7097         HStoreContextSlot::Mode mode;
7098         if (expr->op() == Token::ASSIGN) {
7099           switch (var->mode()) {
7100             case LET:
7101               mode = HStoreContextSlot::kCheckDeoptimize;
7102               break;
7103             case CONST:
7104               // This case is checked statically so no need to
7105               // perform checks here
7106               UNREACHABLE();
7107             case CONST_LEGACY:
7108               return ast_context()->ReturnValue(Pop());
7109             default:
7110               mode = HStoreContextSlot::kNoCheck;
7111           }
7112         } else if (expr->op() == Token::INIT_VAR ||
7113                    expr->op() == Token::INIT_LET ||
7114                    expr->op() == Token::INIT_CONST) {
7115           mode = HStoreContextSlot::kNoCheck;
7116         } else {
7117           DCHECK(expr->op() == Token::INIT_CONST_LEGACY);
7118
7119           mode = HStoreContextSlot::kCheckIgnoreAssignment;
7120         }
7121
7122         HValue* context = BuildContextChainWalk(var);
7123         HStoreContextSlot* instr = Add<HStoreContextSlot>(
7124             context, var->index(), mode, Top());
7125         if (instr->HasObservableSideEffects()) {
7126           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
7127         }
7128         return ast_context()->ReturnValue(Pop());
7129       }
7130
7131       case VariableLocation::LOOKUP:
7132         return Bailout(kAssignmentToLOOKUPVariable);
7133     }
7134   } else {
7135     return Bailout(kInvalidLeftHandSideInAssignment);
7136   }
7137 }
7138
7139
7140 void HOptimizedGraphBuilder::VisitYield(Yield* expr) {
7141   // Generators are not optimized, so we should never get here.
7142   UNREACHABLE();
7143 }
7144
7145
7146 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
7147   DCHECK(!HasStackOverflow());
7148   DCHECK(current_block() != NULL);
7149   DCHECK(current_block()->HasPredecessor());
7150   if (!ast_context()->IsEffect()) {
7151     // The parser turns invalid left-hand sides in assignments into throw
7152     // statements, which may not be in effect contexts. We might still try
7153     // to optimize such functions; bail out now if we do.
7154     return Bailout(kInvalidLeftHandSideInAssignment);
7155   }
7156   CHECK_ALIVE(VisitForValue(expr->exception()));
7157
7158   HValue* value = environment()->Pop();
7159   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
7160   Add<HPushArguments>(value);
7161   Add<HCallRuntime>(isolate()->factory()->empty_string(),
7162                     Runtime::FunctionForId(Runtime::kThrow), 1);
7163   Add<HSimulate>(expr->id());
7164
7165   // If the throw definitely exits the function, we can finish with a dummy
7166   // control flow at this point.  This is not the case if the throw is inside
7167   // an inlined function which may be replaced.
7168   if (call_context() == NULL) {
7169     FinishExitCurrentBlock(New<HAbnormalExit>());
7170   }
7171 }
7172
7173
7174 HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) {
7175   if (string->IsConstant()) {
7176     HConstant* c_string = HConstant::cast(string);
7177     if (c_string->HasStringValue()) {
7178       return Add<HConstant>(c_string->StringValue()->map()->instance_type());
7179     }
7180   }
7181   return Add<HLoadNamedField>(
7182       Add<HLoadNamedField>(string, nullptr, HObjectAccess::ForMap()), nullptr,
7183       HObjectAccess::ForMapInstanceType());
7184 }
7185
7186
7187 HInstruction* HGraphBuilder::AddLoadStringLength(HValue* string) {
7188   return AddInstruction(BuildLoadStringLength(string));
7189 }
7190
7191
7192 HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* string) {
7193   if (string->IsConstant()) {
7194     HConstant* c_string = HConstant::cast(string);
7195     if (c_string->HasStringValue()) {
7196       return New<HConstant>(c_string->StringValue()->length());
7197     }
7198   }
7199   return New<HLoadNamedField>(string, nullptr,
7200                               HObjectAccess::ForStringLength());
7201 }
7202
7203
7204 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric(
7205     PropertyAccessType access_type, Expression* expr, FeedbackVectorICSlot slot,
7206     HValue* object, Handle<Name> name, HValue* value, bool is_uninitialized) {
7207   if (is_uninitialized) {
7208     Add<HDeoptimize>(
7209         Deoptimizer::kInsufficientTypeFeedbackForGenericNamedAccess,
7210         Deoptimizer::SOFT);
7211   }
7212   if (access_type == LOAD) {
7213     Handle<TypeFeedbackVector> vector =
7214         handle(current_feedback_vector(), isolate());
7215
7216     if (!expr->AsProperty()->key()->IsPropertyName()) {
7217       // It's possible that a keyed load of a constant string was converted
7218       // to a named load. Here, at the last minute, we need to make sure to
7219       // use a generic Keyed Load if we are using the type vector, because
7220       // it has to share information with full code.
7221       HConstant* key = Add<HConstant>(name);
7222       HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(
7223           object, key, function_language_mode(), PREMONOMORPHIC);
7224       result->SetVectorAndSlot(vector, slot);
7225       return result;
7226     }
7227
7228     HLoadNamedGeneric* result = New<HLoadNamedGeneric>(
7229         object, name, function_language_mode(), PREMONOMORPHIC);
7230     result->SetVectorAndSlot(vector, slot);
7231     return result;
7232   } else {
7233     if (FLAG_vector_stores &&
7234         current_feedback_vector()->GetKind(slot) == Code::KEYED_STORE_IC) {
7235       // It's possible that a keyed store of a constant string was converted
7236       // to a named store. Here, at the last minute, we need to make sure to
7237       // use a generic Keyed Store if we are using the type vector, because
7238       // it has to share information with full code.
7239       HConstant* key = Add<HConstant>(name);
7240       HStoreKeyedGeneric* result = New<HStoreKeyedGeneric>(
7241           object, key, value, function_language_mode(), PREMONOMORPHIC);
7242       Handle<TypeFeedbackVector> vector =
7243           handle(current_feedback_vector(), isolate());
7244       result->SetVectorAndSlot(vector, slot);
7245       return result;
7246     }
7247
7248     HStoreNamedGeneric* result = New<HStoreNamedGeneric>(
7249         object, name, value, function_language_mode(), PREMONOMORPHIC);
7250     if (FLAG_vector_stores) {
7251       Handle<TypeFeedbackVector> vector =
7252           handle(current_feedback_vector(), isolate());
7253       result->SetVectorAndSlot(vector, slot);
7254     }
7255     return result;
7256   }
7257 }
7258
7259
7260 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric(
7261     PropertyAccessType access_type, Expression* expr, FeedbackVectorICSlot slot,
7262     HValue* object, HValue* key, HValue* value) {
7263   if (access_type == LOAD) {
7264     InlineCacheState initial_state = expr->AsProperty()->GetInlineCacheState();
7265     HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(
7266         object, key, function_language_mode(), initial_state);
7267     // HLoadKeyedGeneric with vector ics benefits from being encoded as
7268     // MEGAMORPHIC because the vector/slot combo becomes unnecessary.
7269     if (initial_state != MEGAMORPHIC) {
7270       // We need to pass vector information.
7271       Handle<TypeFeedbackVector> vector =
7272           handle(current_feedback_vector(), isolate());
7273       result->SetVectorAndSlot(vector, slot);
7274     }
7275     return result;
7276   } else {
7277     HStoreKeyedGeneric* result = New<HStoreKeyedGeneric>(
7278         object, key, value, function_language_mode(), PREMONOMORPHIC);
7279     if (FLAG_vector_stores) {
7280       Handle<TypeFeedbackVector> vector =
7281           handle(current_feedback_vector(), isolate());
7282       result->SetVectorAndSlot(vector, slot);
7283     }
7284     return result;
7285   }
7286 }
7287
7288
7289 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) {
7290   // Loads from a "stock" fast holey double arrays can elide the hole check.
7291   // Loads from a "stock" fast holey array can convert the hole to undefined
7292   // with impunity.
7293   LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
7294   bool holey_double_elements =
7295       *map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS);
7296   bool holey_elements =
7297       *map == isolate()->get_initial_js_array_map(FAST_HOLEY_ELEMENTS);
7298   if ((holey_double_elements || holey_elements) &&
7299       isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
7300     load_mode =
7301         holey_double_elements ? ALLOW_RETURN_HOLE : CONVERT_HOLE_TO_UNDEFINED;
7302
7303     Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
7304     Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
7305     BuildCheckPrototypeMaps(prototype, object_prototype);
7306     graph()->MarkDependsOnEmptyArrayProtoElements();
7307   }
7308   return load_mode;
7309 }
7310
7311
7312 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
7313     HValue* object,
7314     HValue* key,
7315     HValue* val,
7316     HValue* dependency,
7317     Handle<Map> map,
7318     PropertyAccessType access_type,
7319     KeyedAccessStoreMode store_mode) {
7320   HCheckMaps* checked_object = Add<HCheckMaps>(object, map, dependency);
7321
7322   if (access_type == STORE && map->prototype()->IsJSObject()) {
7323     // monomorphic stores need a prototype chain check because shape
7324     // changes could allow callbacks on elements in the chain that
7325     // aren't compatible with monomorphic keyed stores.
7326     PrototypeIterator iter(map);
7327     JSObject* holder = NULL;
7328     while (!iter.IsAtEnd()) {
7329       holder = JSObject::cast(*PrototypeIterator::GetCurrent(iter));
7330       iter.Advance();
7331     }
7332     DCHECK(holder && holder->IsJSObject());
7333
7334     BuildCheckPrototypeMaps(handle(JSObject::cast(map->prototype())),
7335                             Handle<JSObject>(holder));
7336   }
7337
7338   LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
7339   return BuildUncheckedMonomorphicElementAccess(
7340       checked_object, key, val,
7341       map->instance_type() == JS_ARRAY_TYPE,
7342       map->elements_kind(), access_type,
7343       load_mode, store_mode);
7344 }
7345
7346
7347 static bool CanInlineElementAccess(Handle<Map> map) {
7348   return map->IsJSObjectMap() && !map->has_dictionary_elements() &&
7349          !map->has_sloppy_arguments_elements() &&
7350          !map->has_indexed_interceptor() && !map->is_access_check_needed();
7351 }
7352
7353
7354 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
7355     HValue* object,
7356     HValue* key,
7357     HValue* val,
7358     SmallMapList* maps) {
7359   // For polymorphic loads of similar elements kinds (i.e. all tagged or all
7360   // double), always use the "worst case" code without a transition.  This is
7361   // much faster than transitioning the elements to the worst case, trading a
7362   // HTransitionElements for a HCheckMaps, and avoiding mutation of the array.
7363   bool has_double_maps = false;
7364   bool has_smi_or_object_maps = false;
7365   bool has_js_array_access = false;
7366   bool has_non_js_array_access = false;
7367   bool has_seen_holey_elements = false;
7368   Handle<Map> most_general_consolidated_map;
7369   for (int i = 0; i < maps->length(); ++i) {
7370     Handle<Map> map = maps->at(i);
7371     if (!CanInlineElementAccess(map)) return NULL;
7372     // Don't allow mixing of JSArrays with JSObjects.
7373     if (map->instance_type() == JS_ARRAY_TYPE) {
7374       if (has_non_js_array_access) return NULL;
7375       has_js_array_access = true;
7376     } else if (has_js_array_access) {
7377       return NULL;
7378     } else {
7379       has_non_js_array_access = true;
7380     }
7381     // Don't allow mixed, incompatible elements kinds.
7382     if (map->has_fast_double_elements()) {
7383       if (has_smi_or_object_maps) return NULL;
7384       has_double_maps = true;
7385     } else if (map->has_fast_smi_or_object_elements()) {
7386       if (has_double_maps) return NULL;
7387       has_smi_or_object_maps = true;
7388     } else {
7389       return NULL;
7390     }
7391     // Remember if we've ever seen holey elements.
7392     if (IsHoleyElementsKind(map->elements_kind())) {
7393       has_seen_holey_elements = true;
7394     }
7395     // Remember the most general elements kind, the code for its load will
7396     // properly handle all of the more specific cases.
7397     if ((i == 0) || IsMoreGeneralElementsKindTransition(
7398             most_general_consolidated_map->elements_kind(),
7399             map->elements_kind())) {
7400       most_general_consolidated_map = map;
7401     }
7402   }
7403   if (!has_double_maps && !has_smi_or_object_maps) return NULL;
7404
7405   HCheckMaps* checked_object = Add<HCheckMaps>(object, maps);
7406   // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS.
7407   // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS.
7408   ElementsKind consolidated_elements_kind = has_seen_holey_elements
7409       ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind())
7410       : most_general_consolidated_map->elements_kind();
7411   HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
7412       checked_object, key, val,
7413       most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
7414       consolidated_elements_kind,
7415       LOAD, NEVER_RETURN_HOLE, STANDARD_STORE);
7416   return instr;
7417 }
7418
7419
7420 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
7421     Expression* expr, FeedbackVectorICSlot slot, HValue* object, HValue* key,
7422     HValue* val, SmallMapList* maps, PropertyAccessType access_type,
7423     KeyedAccessStoreMode store_mode, bool* has_side_effects) {
7424   *has_side_effects = false;
7425   BuildCheckHeapObject(object);
7426
7427   if (access_type == LOAD) {
7428     HInstruction* consolidated_load =
7429         TryBuildConsolidatedElementLoad(object, key, val, maps);
7430     if (consolidated_load != NULL) {
7431       *has_side_effects |= consolidated_load->HasObservableSideEffects();
7432       return consolidated_load;
7433     }
7434   }
7435
7436   // Elements_kind transition support.
7437   MapHandleList transition_target(maps->length());
7438   // Collect possible transition targets.
7439   MapHandleList possible_transitioned_maps(maps->length());
7440   for (int i = 0; i < maps->length(); ++i) {
7441     Handle<Map> map = maps->at(i);
7442     // Loads from strings or loads with a mix of string and non-string maps
7443     // shouldn't be handled polymorphically.
7444     DCHECK(access_type != LOAD || !map->IsStringMap());
7445     ElementsKind elements_kind = map->elements_kind();
7446     if (CanInlineElementAccess(map) && IsFastElementsKind(elements_kind) &&
7447         elements_kind != GetInitialFastElementsKind()) {
7448       possible_transitioned_maps.Add(map);
7449     }
7450     if (IsSloppyArgumentsElements(elements_kind)) {
7451       HInstruction* result =
7452           BuildKeyedGeneric(access_type, expr, slot, object, key, val);
7453       *has_side_effects = result->HasObservableSideEffects();
7454       return AddInstruction(result);
7455     }
7456   }
7457   // Get transition target for each map (NULL == no transition).
7458   for (int i = 0; i < maps->length(); ++i) {
7459     Handle<Map> map = maps->at(i);
7460     Handle<Map> transitioned_map =
7461         Map::FindTransitionedMap(map, &possible_transitioned_maps);
7462     transition_target.Add(transitioned_map);
7463   }
7464
7465   MapHandleList untransitionable_maps(maps->length());
7466   HTransitionElementsKind* transition = NULL;
7467   for (int i = 0; i < maps->length(); ++i) {
7468     Handle<Map> map = maps->at(i);
7469     DCHECK(map->IsMap());
7470     if (!transition_target.at(i).is_null()) {
7471       DCHECK(Map::IsValidElementsTransition(
7472           map->elements_kind(),
7473           transition_target.at(i)->elements_kind()));
7474       transition = Add<HTransitionElementsKind>(object, map,
7475                                                 transition_target.at(i));
7476     } else {
7477       untransitionable_maps.Add(map);
7478     }
7479   }
7480
7481   // If only one map is left after transitioning, handle this case
7482   // monomorphically.
7483   DCHECK(untransitionable_maps.length() >= 1);
7484   if (untransitionable_maps.length() == 1) {
7485     Handle<Map> untransitionable_map = untransitionable_maps[0];
7486     HInstruction* instr = NULL;
7487     if (!CanInlineElementAccess(untransitionable_map)) {
7488       instr = AddInstruction(
7489           BuildKeyedGeneric(access_type, expr, slot, object, key, val));
7490     } else {
7491       instr = BuildMonomorphicElementAccess(
7492           object, key, val, transition, untransitionable_map, access_type,
7493           store_mode);
7494     }
7495     *has_side_effects |= instr->HasObservableSideEffects();
7496     return access_type == STORE ? val : instr;
7497   }
7498
7499   HBasicBlock* join = graph()->CreateBasicBlock();
7500
7501   for (int i = 0; i < untransitionable_maps.length(); ++i) {
7502     Handle<Map> map = untransitionable_maps[i];
7503     ElementsKind elements_kind = map->elements_kind();
7504     HBasicBlock* this_map = graph()->CreateBasicBlock();
7505     HBasicBlock* other_map = graph()->CreateBasicBlock();
7506     HCompareMap* mapcompare =
7507         New<HCompareMap>(object, map, this_map, other_map);
7508     FinishCurrentBlock(mapcompare);
7509
7510     set_current_block(this_map);
7511     HInstruction* access = NULL;
7512     if (!CanInlineElementAccess(map)) {
7513       access = AddInstruction(
7514           BuildKeyedGeneric(access_type, expr, slot, object, key, val));
7515     } else {
7516       DCHECK(IsFastElementsKind(elements_kind) ||
7517              IsFixedTypedArrayElementsKind(elements_kind));
7518       LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
7519       // Happily, mapcompare is a checked object.
7520       access = BuildUncheckedMonomorphicElementAccess(
7521           mapcompare, key, val,
7522           map->instance_type() == JS_ARRAY_TYPE,
7523           elements_kind, access_type,
7524           load_mode,
7525           store_mode);
7526     }
7527     *has_side_effects |= access->HasObservableSideEffects();
7528     // The caller will use has_side_effects and add a correct Simulate.
7529     access->SetFlag(HValue::kHasNoObservableSideEffects);
7530     if (access_type == LOAD) {
7531       Push(access);
7532     }
7533     NoObservableSideEffectsScope scope(this);
7534     GotoNoSimulate(join);
7535     set_current_block(other_map);
7536   }
7537
7538   // Ensure that we visited at least one map above that goes to join. This is
7539   // necessary because FinishExitWithHardDeoptimization does an AbnormalExit
7540   // rather than joining the join block. If this becomes an issue, insert a
7541   // generic access in the case length() == 0.
7542   DCHECK(join->predecessors()->length() > 0);
7543   // Deopt if none of the cases matched.
7544   NoObservableSideEffectsScope scope(this);
7545   FinishExitWithHardDeoptimization(
7546       Deoptimizer::kUnknownMapInPolymorphicElementAccess);
7547   set_current_block(join);
7548   return access_type == STORE ? val : Pop();
7549 }
7550
7551
7552 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
7553     HValue* obj, HValue* key, HValue* val, Expression* expr,
7554     FeedbackVectorICSlot slot, BailoutId ast_id, BailoutId return_id,
7555     PropertyAccessType access_type, bool* has_side_effects) {
7556   if (key->ActualValue()->IsConstant()) {
7557     Handle<Object> constant =
7558         HConstant::cast(key->ActualValue())->handle(isolate());
7559     uint32_t array_index;
7560     if (constant->IsString() &&
7561         !Handle<String>::cast(constant)->AsArrayIndex(&array_index)) {
7562       if (!constant->IsUniqueName()) {
7563         constant = isolate()->factory()->InternalizeString(
7564             Handle<String>::cast(constant));
7565       }
7566       HValue* access =
7567           BuildNamedAccess(access_type, ast_id, return_id, expr, slot, obj,
7568                            Handle<String>::cast(constant), val, false);
7569       if (access == NULL || access->IsPhi() ||
7570           HInstruction::cast(access)->IsLinked()) {
7571         *has_side_effects = false;
7572       } else {
7573         HInstruction* instr = HInstruction::cast(access);
7574         AddInstruction(instr);
7575         *has_side_effects = instr->HasObservableSideEffects();
7576       }
7577       return access;
7578     }
7579   }
7580
7581   DCHECK(!expr->IsPropertyName());
7582   HInstruction* instr = NULL;
7583
7584   SmallMapList* maps;
7585   bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, zone());
7586
7587   bool force_generic = false;
7588   if (expr->GetKeyType() == PROPERTY) {
7589     // Non-Generic accesses assume that elements are being accessed, and will
7590     // deopt for non-index keys, which the IC knows will occur.
7591     // TODO(jkummerow): Consider adding proper support for property accesses.
7592     force_generic = true;
7593     monomorphic = false;
7594   } else if (access_type == STORE &&
7595              (monomorphic || (maps != NULL && !maps->is_empty()))) {
7596     // Stores can't be mono/polymorphic if their prototype chain has dictionary
7597     // elements. However a receiver map that has dictionary elements itself
7598     // should be left to normal mono/poly behavior (the other maps may benefit
7599     // from highly optimized stores).
7600     for (int i = 0; i < maps->length(); i++) {
7601       Handle<Map> current_map = maps->at(i);
7602       if (current_map->DictionaryElementsInPrototypeChainOnly()) {
7603         force_generic = true;
7604         monomorphic = false;
7605         break;
7606       }
7607     }
7608   } else if (access_type == LOAD && !monomorphic &&
7609              (maps != NULL && !maps->is_empty())) {
7610     // Polymorphic loads have to go generic if any of the maps are strings.
7611     // If some, but not all of the maps are strings, we should go generic
7612     // because polymorphic access wants to key on ElementsKind and isn't
7613     // compatible with strings.
7614     for (int i = 0; i < maps->length(); i++) {
7615       Handle<Map> current_map = maps->at(i);
7616       if (current_map->IsStringMap()) {
7617         force_generic = true;
7618         break;
7619       }
7620     }
7621   }
7622
7623   if (monomorphic) {
7624     Handle<Map> map = maps->first();
7625     if (!CanInlineElementAccess(map)) {
7626       instr = AddInstruction(
7627           BuildKeyedGeneric(access_type, expr, slot, obj, key, val));
7628     } else {
7629       BuildCheckHeapObject(obj);
7630       instr = BuildMonomorphicElementAccess(
7631           obj, key, val, NULL, map, access_type, expr->GetStoreMode());
7632     }
7633   } else if (!force_generic && (maps != NULL && !maps->is_empty())) {
7634     return HandlePolymorphicElementAccess(expr, slot, obj, key, val, maps,
7635                                           access_type, expr->GetStoreMode(),
7636                                           has_side_effects);
7637   } else {
7638     if (access_type == STORE) {
7639       if (expr->IsAssignment() &&
7640           expr->AsAssignment()->HasNoTypeInformation()) {
7641         Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedStore,
7642                          Deoptimizer::SOFT);
7643       }
7644     } else {
7645       if (expr->AsProperty()->HasNoTypeInformation()) {
7646         Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedLoad,
7647                          Deoptimizer::SOFT);
7648       }
7649     }
7650     instr = AddInstruction(
7651         BuildKeyedGeneric(access_type, expr, slot, obj, key, val));
7652   }
7653   *has_side_effects = instr->HasObservableSideEffects();
7654   return instr;
7655 }
7656
7657
7658 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() {
7659   // Outermost function already has arguments on the stack.
7660   if (function_state()->outer() == NULL) return;
7661
7662   if (function_state()->arguments_pushed()) return;
7663
7664   // Push arguments when entering inlined function.
7665   HEnterInlined* entry = function_state()->entry();
7666   entry->set_arguments_pushed();
7667
7668   HArgumentsObject* arguments = entry->arguments_object();
7669   const ZoneList<HValue*>* arguments_values = arguments->arguments_values();
7670
7671   HInstruction* insert_after = entry;
7672   for (int i = 0; i < arguments_values->length(); i++) {
7673     HValue* argument = arguments_values->at(i);
7674     HInstruction* push_argument = New<HPushArguments>(argument);
7675     push_argument->InsertAfter(insert_after);
7676     insert_after = push_argument;
7677   }
7678
7679   HArgumentsElements* arguments_elements = New<HArgumentsElements>(true);
7680   arguments_elements->ClearFlag(HValue::kUseGVN);
7681   arguments_elements->InsertAfter(insert_after);
7682   function_state()->set_arguments_elements(arguments_elements);
7683 }
7684
7685
7686 bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) {
7687   VariableProxy* proxy = expr->obj()->AsVariableProxy();
7688   if (proxy == NULL) return false;
7689   if (!proxy->var()->IsStackAllocated()) return false;
7690   if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
7691     return false;
7692   }
7693
7694   HInstruction* result = NULL;
7695   if (expr->key()->IsPropertyName()) {
7696     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
7697     if (!String::Equals(name, isolate()->factory()->length_string())) {
7698       return false;
7699     }
7700
7701     if (function_state()->outer() == NULL) {
7702       HInstruction* elements = Add<HArgumentsElements>(false);
7703       result = New<HArgumentsLength>(elements);
7704     } else {
7705       // Number of arguments without receiver.
7706       int argument_count = environment()->
7707           arguments_environment()->parameter_count() - 1;
7708       result = New<HConstant>(argument_count);
7709     }
7710   } else {
7711     Push(graph()->GetArgumentsObject());
7712     CHECK_ALIVE_OR_RETURN(VisitForValue(expr->key()), true);
7713     HValue* key = Pop();
7714     Drop(1);  // Arguments object.
7715     if (function_state()->outer() == NULL) {
7716       HInstruction* elements = Add<HArgumentsElements>(false);
7717       HInstruction* length = Add<HArgumentsLength>(elements);
7718       HInstruction* checked_key = Add<HBoundsCheck>(key, length);
7719       result = New<HAccessArgumentsAt>(elements, length, checked_key);
7720     } else {
7721       EnsureArgumentsArePushedForAccess();
7722
7723       // Number of arguments without receiver.
7724       HInstruction* elements = function_state()->arguments_elements();
7725       int argument_count = environment()->
7726           arguments_environment()->parameter_count() - 1;
7727       HInstruction* length = Add<HConstant>(argument_count);
7728       HInstruction* checked_key = Add<HBoundsCheck>(key, length);
7729       result = New<HAccessArgumentsAt>(elements, length, checked_key);
7730     }
7731   }
7732   ast_context()->ReturnInstruction(result, expr->id());
7733   return true;
7734 }
7735
7736
7737 HValue* HOptimizedGraphBuilder::BuildNamedAccess(
7738     PropertyAccessType access, BailoutId ast_id, BailoutId return_id,
7739     Expression* expr, FeedbackVectorICSlot slot, HValue* object,
7740     Handle<String> name, HValue* value, bool is_uninitialized) {
7741   SmallMapList* maps;
7742   ComputeReceiverTypes(expr, object, &maps, zone());
7743   DCHECK(maps != NULL);
7744
7745   if (maps->length() > 0) {
7746     PropertyAccessInfo info(this, access, maps->first(), name);
7747     if (!info.CanAccessAsMonomorphic(maps)) {
7748       HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id,
7749                                         object, value, maps, name);
7750       return NULL;
7751     }
7752
7753     HValue* checked_object;
7754     // Type::Number() is only supported by polymorphic load/call handling.
7755     DCHECK(!info.IsNumberType());
7756     BuildCheckHeapObject(object);
7757     if (AreStringTypes(maps)) {
7758       checked_object =
7759           Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
7760     } else {
7761       checked_object = Add<HCheckMaps>(object, maps);
7762     }
7763     return BuildMonomorphicAccess(
7764         &info, object, checked_object, value, ast_id, return_id);
7765   }
7766
7767   return BuildNamedGeneric(access, expr, slot, object, name, value,
7768                            is_uninitialized);
7769 }
7770
7771
7772 void HOptimizedGraphBuilder::PushLoad(Property* expr,
7773                                       HValue* object,
7774                                       HValue* key) {
7775   ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
7776   Push(object);
7777   if (key != NULL) Push(key);
7778   BuildLoad(expr, expr->LoadId());
7779 }
7780
7781
7782 void HOptimizedGraphBuilder::BuildLoad(Property* expr,
7783                                        BailoutId ast_id) {
7784   HInstruction* instr = NULL;
7785   if (expr->IsStringAccess()) {
7786     HValue* index = Pop();
7787     HValue* string = Pop();
7788     HInstruction* char_code = BuildStringCharCodeAt(string, index);
7789     AddInstruction(char_code);
7790     instr = NewUncasted<HStringCharFromCode>(char_code);
7791
7792   } else if (expr->key()->IsPropertyName()) {
7793     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
7794     HValue* object = Pop();
7795
7796     HValue* value = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr,
7797                                      expr->PropertyFeedbackSlot(), object, name,
7798                                      NULL, expr->IsUninitialized());
7799     if (value == NULL) return;
7800     if (value->IsPhi()) return ast_context()->ReturnValue(value);
7801     instr = HInstruction::cast(value);
7802     if (instr->IsLinked()) return ast_context()->ReturnValue(instr);
7803
7804   } else {
7805     HValue* key = Pop();
7806     HValue* obj = Pop();
7807
7808     bool has_side_effects = false;
7809     HValue* load = HandleKeyedElementAccess(
7810         obj, key, NULL, expr, expr->PropertyFeedbackSlot(), ast_id,
7811         expr->LoadId(), LOAD, &has_side_effects);
7812     if (has_side_effects) {
7813       if (ast_context()->IsEffect()) {
7814         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
7815       } else {
7816         Push(load);
7817         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
7818         Drop(1);
7819       }
7820     }
7821     if (load == NULL) return;
7822     return ast_context()->ReturnValue(load);
7823   }
7824   return ast_context()->ReturnInstruction(instr, ast_id);
7825 }
7826
7827
7828 void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
7829   DCHECK(!HasStackOverflow());
7830   DCHECK(current_block() != NULL);
7831   DCHECK(current_block()->HasPredecessor());
7832
7833   if (TryArgumentsAccess(expr)) return;
7834
7835   CHECK_ALIVE(VisitForValue(expr->obj()));
7836   if (!expr->key()->IsPropertyName() || expr->IsStringAccess()) {
7837     CHECK_ALIVE(VisitForValue(expr->key()));
7838   }
7839
7840   BuildLoad(expr, expr->id());
7841 }
7842
7843
7844 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant) {
7845   HCheckMaps* check = Add<HCheckMaps>(
7846       Add<HConstant>(constant), handle(constant->map()));
7847   check->ClearDependsOnFlag(kElementsKind);
7848   return check;
7849 }
7850
7851
7852 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
7853                                                      Handle<JSObject> holder) {
7854   PrototypeIterator iter(isolate(), prototype,
7855                          PrototypeIterator::START_AT_RECEIVER);
7856   while (holder.is_null() ||
7857          !PrototypeIterator::GetCurrent(iter).is_identical_to(holder)) {
7858     BuildConstantMapCheck(
7859         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
7860     iter.Advance();
7861     if (iter.IsAtEnd()) {
7862       return NULL;
7863     }
7864   }
7865   return BuildConstantMapCheck(
7866       Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
7867 }
7868
7869
7870 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
7871                                                    Handle<Map> receiver_map) {
7872   if (!holder.is_null()) {
7873     Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
7874     BuildCheckPrototypeMaps(prototype, holder);
7875   }
7876 }
7877
7878
7879 HInstruction* HOptimizedGraphBuilder::NewPlainFunctionCall(
7880     HValue* fun, int argument_count, bool pass_argument_count) {
7881   return New<HCallJSFunction>(fun, argument_count, pass_argument_count);
7882 }
7883
7884
7885 HInstruction* HOptimizedGraphBuilder::NewArgumentAdaptorCall(
7886     HValue* fun, HValue* context,
7887     int argument_count, HValue* expected_param_count) {
7888   ArgumentAdaptorDescriptor descriptor(isolate());
7889   HValue* arity = Add<HConstant>(argument_count - 1);
7890
7891   HValue* op_vals[] = { context, fun, arity, expected_param_count };
7892
7893   Handle<Code> adaptor =
7894       isolate()->builtins()->ArgumentsAdaptorTrampoline();
7895   HConstant* adaptor_value = Add<HConstant>(adaptor);
7896
7897   return New<HCallWithDescriptor>(adaptor_value, argument_count, descriptor,
7898                                   Vector<HValue*>(op_vals, arraysize(op_vals)));
7899 }
7900
7901
7902 HInstruction* HOptimizedGraphBuilder::BuildCallConstantFunction(
7903     Handle<JSFunction> jsfun, int argument_count) {
7904   HValue* target = Add<HConstant>(jsfun);
7905   // For constant functions, we try to avoid calling the
7906   // argument adaptor and instead call the function directly
7907   int formal_parameter_count =
7908       jsfun->shared()->internal_formal_parameter_count();
7909   bool dont_adapt_arguments =
7910       (formal_parameter_count ==
7911        SharedFunctionInfo::kDontAdaptArgumentsSentinel);
7912   int arity = argument_count - 1;
7913   bool can_invoke_directly =
7914       dont_adapt_arguments || formal_parameter_count == arity;
7915   if (can_invoke_directly) {
7916     if (jsfun.is_identical_to(current_info()->closure())) {
7917       graph()->MarkRecursive();
7918     }
7919     return NewPlainFunctionCall(target, argument_count, dont_adapt_arguments);
7920   } else {
7921     HValue* param_count_value = Add<HConstant>(formal_parameter_count);
7922     HValue* context = Add<HLoadNamedField>(
7923         target, nullptr, HObjectAccess::ForFunctionContextPointer());
7924     return NewArgumentAdaptorCall(target, context,
7925         argument_count, param_count_value);
7926   }
7927   UNREACHABLE();
7928   return NULL;
7929 }
7930
7931
7932 class FunctionSorter {
7933  public:
7934   explicit FunctionSorter(int index = 0, int ticks = 0, int size = 0)
7935       : index_(index), ticks_(ticks), size_(size) {}
7936
7937   int index() const { return index_; }
7938   int ticks() const { return ticks_; }
7939   int size() const { return size_; }
7940
7941  private:
7942   int index_;
7943   int ticks_;
7944   int size_;
7945 };
7946
7947
7948 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) {
7949   int diff = lhs.ticks() - rhs.ticks();
7950   if (diff != 0) return diff > 0;
7951   return lhs.size() < rhs.size();
7952 }
7953
7954
7955 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
7956                                                         HValue* receiver,
7957                                                         SmallMapList* maps,
7958                                                         Handle<String> name) {
7959   int argument_count = expr->arguments()->length() + 1;  // Includes receiver.
7960   FunctionSorter order[kMaxCallPolymorphism];
7961
7962   bool handle_smi = false;
7963   bool handled_string = false;
7964   int ordered_functions = 0;
7965
7966   int i;
7967   for (i = 0; i < maps->length() && ordered_functions < kMaxCallPolymorphism;
7968        ++i) {
7969     PropertyAccessInfo info(this, LOAD, maps->at(i), name);
7970     if (info.CanAccessMonomorphic() && info.IsDataConstant() &&
7971         info.constant()->IsJSFunction()) {
7972       if (info.IsStringType()) {
7973         if (handled_string) continue;
7974         handled_string = true;
7975       }
7976       Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
7977       if (info.IsNumberType()) {
7978         handle_smi = true;
7979       }
7980       expr->set_target(target);
7981       order[ordered_functions++] = FunctionSorter(
7982           i, target->shared()->profiler_ticks(), InliningAstSize(target));
7983     }
7984   }
7985
7986   std::sort(order, order + ordered_functions);
7987
7988   if (i < maps->length()) {
7989     maps->Clear();
7990     ordered_functions = -1;
7991   }
7992
7993   HBasicBlock* number_block = NULL;
7994   HBasicBlock* join = NULL;
7995   handled_string = false;
7996   int count = 0;
7997
7998   for (int fn = 0; fn < ordered_functions; ++fn) {
7999     int i = order[fn].index();
8000     PropertyAccessInfo info(this, LOAD, maps->at(i), name);
8001     if (info.IsStringType()) {
8002       if (handled_string) continue;
8003       handled_string = true;
8004     }
8005     // Reloads the target.
8006     info.CanAccessMonomorphic();
8007     Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
8008
8009     expr->set_target(target);
8010     if (count == 0) {
8011       // Only needed once.
8012       join = graph()->CreateBasicBlock();
8013       if (handle_smi) {
8014         HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
8015         HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
8016         number_block = graph()->CreateBasicBlock();
8017         FinishCurrentBlock(New<HIsSmiAndBranch>(
8018                 receiver, empty_smi_block, not_smi_block));
8019         GotoNoSimulate(empty_smi_block, number_block);
8020         set_current_block(not_smi_block);
8021       } else {
8022         BuildCheckHeapObject(receiver);
8023       }
8024     }
8025     ++count;
8026     HBasicBlock* if_true = graph()->CreateBasicBlock();
8027     HBasicBlock* if_false = graph()->CreateBasicBlock();
8028     HUnaryControlInstruction* compare;
8029
8030     Handle<Map> map = info.map();
8031     if (info.IsNumberType()) {
8032       Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
8033       compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
8034     } else if (info.IsStringType()) {
8035       compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
8036     } else {
8037       compare = New<HCompareMap>(receiver, map, if_true, if_false);
8038     }
8039     FinishCurrentBlock(compare);
8040
8041     if (info.IsNumberType()) {
8042       GotoNoSimulate(if_true, number_block);
8043       if_true = number_block;
8044     }
8045
8046     set_current_block(if_true);
8047
8048     AddCheckPrototypeMaps(info.holder(), map);
8049
8050     HValue* function = Add<HConstant>(expr->target());
8051     environment()->SetExpressionStackAt(0, function);
8052     Push(receiver);
8053     CHECK_ALIVE(VisitExpressions(expr->arguments()));
8054     bool needs_wrapping = info.NeedsWrappingFor(target);
8055     bool try_inline = FLAG_polymorphic_inlining && !needs_wrapping;
8056     if (FLAG_trace_inlining && try_inline) {
8057       Handle<JSFunction> caller = current_info()->closure();
8058       base::SmartArrayPointer<char> caller_name =
8059           caller->shared()->DebugName()->ToCString();
8060       PrintF("Trying to inline the polymorphic call to %s from %s\n",
8061              name->ToCString().get(),
8062              caller_name.get());
8063     }
8064     if (try_inline && TryInlineCall(expr)) {
8065       // Trying to inline will signal that we should bailout from the
8066       // entire compilation by setting stack overflow on the visitor.
8067       if (HasStackOverflow()) return;
8068     } else {
8069       // Since HWrapReceiver currently cannot actually wrap numbers and strings,
8070       // use the regular CallFunctionStub for method calls to wrap the receiver.
8071       // TODO(verwaest): Support creation of value wrappers directly in
8072       // HWrapReceiver.
8073       HInstruction* call = needs_wrapping
8074           ? NewUncasted<HCallFunction>(
8075               function, argument_count, WRAP_AND_CALL)
8076           : BuildCallConstantFunction(target, argument_count);
8077       PushArgumentsFromEnvironment(argument_count);
8078       AddInstruction(call);
8079       Drop(1);  // Drop the function.
8080       if (!ast_context()->IsEffect()) Push(call);
8081     }
8082
8083     if (current_block() != NULL) Goto(join);
8084     set_current_block(if_false);
8085   }
8086
8087   // Finish up.  Unconditionally deoptimize if we've handled all the maps we
8088   // know about and do not want to handle ones we've never seen.  Otherwise
8089   // use a generic IC.
8090   if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) {
8091     FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall);
8092   } else {
8093     Property* prop = expr->expression()->AsProperty();
8094     HInstruction* function =
8095         BuildNamedGeneric(LOAD, prop, prop->PropertyFeedbackSlot(), receiver,
8096                           name, NULL, prop->IsUninitialized());
8097     AddInstruction(function);
8098     Push(function);
8099     AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
8100
8101     environment()->SetExpressionStackAt(1, function);
8102     environment()->SetExpressionStackAt(0, receiver);
8103     CHECK_ALIVE(VisitExpressions(expr->arguments()));
8104
8105     CallFunctionFlags flags = receiver->type().IsJSObject()
8106         ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD;
8107     HInstruction* call = New<HCallFunction>(
8108         function, argument_count, flags);
8109
8110     PushArgumentsFromEnvironment(argument_count);
8111
8112     Drop(1);  // Function.
8113
8114     if (join != NULL) {
8115       AddInstruction(call);
8116       if (!ast_context()->IsEffect()) Push(call);
8117       Goto(join);
8118     } else {
8119       return ast_context()->ReturnInstruction(call, expr->id());
8120     }
8121   }
8122
8123   // We assume that control flow is always live after an expression.  So
8124   // even without predecessors to the join block, we set it as the exit
8125   // block and continue by adding instructions there.
8126   DCHECK(join != NULL);
8127   if (join->HasPredecessor()) {
8128     set_current_block(join);
8129     join->SetJoinId(expr->id());
8130     if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
8131   } else {
8132     set_current_block(NULL);
8133   }
8134 }
8135
8136
8137 void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target,
8138                                          Handle<JSFunction> caller,
8139                                          const char* reason) {
8140   if (FLAG_trace_inlining) {
8141     base::SmartArrayPointer<char> target_name =
8142         target->shared()->DebugName()->ToCString();
8143     base::SmartArrayPointer<char> caller_name =
8144         caller->shared()->DebugName()->ToCString();
8145     if (reason == NULL) {
8146       PrintF("Inlined %s called from %s.\n", target_name.get(),
8147              caller_name.get());
8148     } else {
8149       PrintF("Did not inline %s called from %s (%s).\n",
8150              target_name.get(), caller_name.get(), reason);
8151     }
8152   }
8153 }
8154
8155
8156 static const int kNotInlinable = 1000000000;
8157
8158
8159 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) {
8160   if (!FLAG_use_inlining) return kNotInlinable;
8161
8162   // Precondition: call is monomorphic and we have found a target with the
8163   // appropriate arity.
8164   Handle<JSFunction> caller = current_info()->closure();
8165   Handle<SharedFunctionInfo> target_shared(target->shared());
8166
8167   // Always inline functions that force inlining.
8168   if (target_shared->force_inline()) {
8169     return 0;
8170   }
8171   if (target->IsBuiltin()) {
8172     return kNotInlinable;
8173   }
8174
8175   if (target_shared->IsApiFunction()) {
8176     TraceInline(target, caller, "target is api function");
8177     return kNotInlinable;
8178   }
8179
8180   // Do a quick check on source code length to avoid parsing large
8181   // inlining candidates.
8182   if (target_shared->SourceSize() >
8183       Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) {
8184     TraceInline(target, caller, "target text too big");
8185     return kNotInlinable;
8186   }
8187
8188   // Target must be inlineable.
8189   if (!target_shared->IsInlineable()) {
8190     TraceInline(target, caller, "target not inlineable");
8191     return kNotInlinable;
8192   }
8193   if (target_shared->disable_optimization_reason() != kNoReason) {
8194     TraceInline(target, caller, "target contains unsupported syntax [early]");
8195     return kNotInlinable;
8196   }
8197
8198   int nodes_added = target_shared->ast_node_count();
8199   return nodes_added;
8200 }
8201
8202
8203 bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
8204                                        int arguments_count,
8205                                        HValue* implicit_return_value,
8206                                        BailoutId ast_id, BailoutId return_id,
8207                                        InliningKind inlining_kind) {
8208   if (target->context()->native_context() !=
8209       top_info()->closure()->context()->native_context()) {
8210     return false;
8211   }
8212   int nodes_added = InliningAstSize(target);
8213   if (nodes_added == kNotInlinable) return false;
8214
8215   Handle<JSFunction> caller = current_info()->closure();
8216
8217   if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
8218     TraceInline(target, caller, "target AST is too large [early]");
8219     return false;
8220   }
8221
8222   // Don't inline deeper than the maximum number of inlining levels.
8223   HEnvironment* env = environment();
8224   int current_level = 1;
8225   while (env->outer() != NULL) {
8226     if (current_level == FLAG_max_inlining_levels) {
8227       TraceInline(target, caller, "inline depth limit reached");
8228       return false;
8229     }
8230     if (env->outer()->frame_type() == JS_FUNCTION) {
8231       current_level++;
8232     }
8233     env = env->outer();
8234   }
8235
8236   // Don't inline recursive functions.
8237   for (FunctionState* state = function_state();
8238        state != NULL;
8239        state = state->outer()) {
8240     if (*state->compilation_info()->closure() == *target) {
8241       TraceInline(target, caller, "target is recursive");
8242       return false;
8243     }
8244   }
8245
8246   // We don't want to add more than a certain number of nodes from inlining.
8247   // Always inline small methods (<= 10 nodes).
8248   if (inlined_count_ > Min(FLAG_max_inlined_nodes_cumulative,
8249                            kUnlimitedMaxInlinedNodesCumulative)) {
8250     TraceInline(target, caller, "cumulative AST node limit reached");
8251     return false;
8252   }
8253
8254   // Parse and allocate variables.
8255   // Use the same AstValueFactory for creating strings in the sub-compilation
8256   // step, but don't transfer ownership to target_info.
8257   ParseInfo parse_info(zone(), target);
8258   parse_info.set_ast_value_factory(
8259       top_info()->parse_info()->ast_value_factory());
8260   parse_info.set_ast_value_factory_owned(false);
8261
8262   CompilationInfo target_info(&parse_info);
8263   Handle<SharedFunctionInfo> target_shared(target->shared());
8264   if (target_shared->HasDebugInfo()) {
8265     TraceInline(target, caller, "target is being debugged");
8266     return false;
8267   }
8268   if (!Compiler::ParseAndAnalyze(target_info.parse_info())) {
8269     if (target_info.isolate()->has_pending_exception()) {
8270       // Parse or scope error, never optimize this function.
8271       SetStackOverflow();
8272       target_shared->DisableOptimization(kParseScopeError);
8273     }
8274     TraceInline(target, caller, "parse failure");
8275     return false;
8276   }
8277
8278   if (target_info.scope()->num_heap_slots() > 0) {
8279     TraceInline(target, caller, "target has context-allocated variables");
8280     return false;
8281   }
8282   FunctionLiteral* function = target_info.literal();
8283
8284   // The following conditions must be checked again after re-parsing, because
8285   // earlier the information might not have been complete due to lazy parsing.
8286   nodes_added = function->ast_node_count();
8287   if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
8288     TraceInline(target, caller, "target AST is too large [late]");
8289     return false;
8290   }
8291   if (function->dont_optimize()) {
8292     TraceInline(target, caller, "target contains unsupported syntax [late]");
8293     return false;
8294   }
8295
8296   // If the function uses the arguments object check that inlining of functions
8297   // with arguments object is enabled and the arguments-variable is
8298   // stack allocated.
8299   if (function->scope()->arguments() != NULL) {
8300     if (!FLAG_inline_arguments) {
8301       TraceInline(target, caller, "target uses arguments object");
8302       return false;
8303     }
8304   }
8305
8306   // All declarations must be inlineable.
8307   ZoneList<Declaration*>* decls = target_info.scope()->declarations();
8308   int decl_count = decls->length();
8309   for (int i = 0; i < decl_count; ++i) {
8310     if (!decls->at(i)->IsInlineable()) {
8311       TraceInline(target, caller, "target has non-trivial declaration");
8312       return false;
8313     }
8314   }
8315
8316   // Generate the deoptimization data for the unoptimized version of
8317   // the target function if we don't already have it.
8318   if (!Compiler::EnsureDeoptimizationSupport(&target_info)) {
8319     TraceInline(target, caller, "could not generate deoptimization info");
8320     return false;
8321   }
8322
8323   // In strong mode it is an error to call a function with too few arguments.
8324   // In that case do not inline because then the arity check would be skipped.
8325   if (is_strong(function->language_mode()) &&
8326       arguments_count < function->parameter_count()) {
8327     TraceInline(target, caller,
8328                 "too few arguments passed to a strong function");
8329     return false;
8330   }
8331
8332   // ----------------------------------------------------------------
8333   // After this point, we've made a decision to inline this function (so
8334   // TryInline should always return true).
8335
8336   // Type-check the inlined function.
8337   DCHECK(target_shared->has_deoptimization_support());
8338   AstTyper(&target_info).Run();
8339
8340   int inlining_id = 0;
8341   if (top_info()->is_tracking_positions()) {
8342     inlining_id = top_info()->TraceInlinedFunction(
8343         target_shared, source_position(), function_state()->inlining_id());
8344   }
8345
8346   // Save the pending call context. Set up new one for the inlined function.
8347   // The function state is new-allocated because we need to delete it
8348   // in two different places.
8349   FunctionState* target_state =
8350       new FunctionState(this, &target_info, inlining_kind, inlining_id);
8351
8352   HConstant* undefined = graph()->GetConstantUndefined();
8353
8354   HEnvironment* inner_env =
8355       environment()->CopyForInlining(target,
8356                                      arguments_count,
8357                                      function,
8358                                      undefined,
8359                                      function_state()->inlining_kind());
8360
8361   HConstant* context = Add<HConstant>(Handle<Context>(target->context()));
8362   inner_env->BindContext(context);
8363
8364   // Create a dematerialized arguments object for the function, also copy the
8365   // current arguments values to use them for materialization.
8366   HEnvironment* arguments_env = inner_env->arguments_environment();
8367   int parameter_count = arguments_env->parameter_count();
8368   HArgumentsObject* arguments_object = Add<HArgumentsObject>(parameter_count);
8369   for (int i = 0; i < parameter_count; i++) {
8370     arguments_object->AddArgument(arguments_env->Lookup(i), zone());
8371   }
8372
8373   // If the function uses arguments object then bind bind one.
8374   if (function->scope()->arguments() != NULL) {
8375     DCHECK(function->scope()->arguments()->IsStackAllocated());
8376     inner_env->Bind(function->scope()->arguments(), arguments_object);
8377   }
8378
8379   // Capture the state before invoking the inlined function for deopt in the
8380   // inlined function. This simulate has no bailout-id since it's not directly
8381   // reachable for deopt, and is only used to capture the state. If the simulate
8382   // becomes reachable by merging, the ast id of the simulate merged into it is
8383   // adopted.
8384   Add<HSimulate>(BailoutId::None());
8385
8386   current_block()->UpdateEnvironment(inner_env);
8387   Scope* saved_scope = scope();
8388   set_scope(target_info.scope());
8389   HEnterInlined* enter_inlined =
8390       Add<HEnterInlined>(return_id, target, context, arguments_count, function,
8391                          function_state()->inlining_kind(),
8392                          function->scope()->arguments(), arguments_object);
8393   if (top_info()->is_tracking_positions()) {
8394     enter_inlined->set_inlining_id(inlining_id);
8395   }
8396   function_state()->set_entry(enter_inlined);
8397
8398   VisitDeclarations(target_info.scope()->declarations());
8399   VisitStatements(function->body());
8400   set_scope(saved_scope);
8401   if (HasStackOverflow()) {
8402     // Bail out if the inline function did, as we cannot residualize a call
8403     // instead, but do not disable optimization for the outer function.
8404     TraceInline(target, caller, "inline graph construction failed");
8405     target_shared->DisableOptimization(kInliningBailedOut);
8406     current_info()->RetryOptimization(kInliningBailedOut);
8407     delete target_state;
8408     return true;
8409   }
8410
8411   // Update inlined nodes count.
8412   inlined_count_ += nodes_added;
8413
8414   Handle<Code> unoptimized_code(target_shared->code());
8415   DCHECK(unoptimized_code->kind() == Code::FUNCTION);
8416   Handle<TypeFeedbackInfo> type_info(
8417       TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
8418   graph()->update_type_change_checksum(type_info->own_type_change_checksum());
8419
8420   TraceInline(target, caller, NULL);
8421
8422   if (current_block() != NULL) {
8423     FunctionState* state = function_state();
8424     if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
8425       // Falling off the end of an inlined construct call. In a test context the
8426       // return value will always evaluate to true, in a value context the
8427       // return value is the newly allocated receiver.
8428       if (call_context()->IsTest()) {
8429         Goto(inlined_test_context()->if_true(), state);
8430       } else if (call_context()->IsEffect()) {
8431         Goto(function_return(), state);
8432       } else {
8433         DCHECK(call_context()->IsValue());
8434         AddLeaveInlined(implicit_return_value, state);
8435       }
8436     } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
8437       // Falling off the end of an inlined setter call. The returned value is
8438       // never used, the value of an assignment is always the value of the RHS
8439       // of the assignment.
8440       if (call_context()->IsTest()) {
8441         inlined_test_context()->ReturnValue(implicit_return_value);
8442       } else if (call_context()->IsEffect()) {
8443         Goto(function_return(), state);
8444       } else {
8445         DCHECK(call_context()->IsValue());
8446         AddLeaveInlined(implicit_return_value, state);
8447       }
8448     } else {
8449       // Falling off the end of a normal inlined function. This basically means
8450       // returning undefined.
8451       if (call_context()->IsTest()) {
8452         Goto(inlined_test_context()->if_false(), state);
8453       } else if (call_context()->IsEffect()) {
8454         Goto(function_return(), state);
8455       } else {
8456         DCHECK(call_context()->IsValue());
8457         AddLeaveInlined(undefined, state);
8458       }
8459     }
8460   }
8461
8462   // Fix up the function exits.
8463   if (inlined_test_context() != NULL) {
8464     HBasicBlock* if_true = inlined_test_context()->if_true();
8465     HBasicBlock* if_false = inlined_test_context()->if_false();
8466
8467     HEnterInlined* entry = function_state()->entry();
8468
8469     // Pop the return test context from the expression context stack.
8470     DCHECK(ast_context() == inlined_test_context());
8471     ClearInlinedTestContext();
8472     delete target_state;
8473
8474     // Forward to the real test context.
8475     if (if_true->HasPredecessor()) {
8476       entry->RegisterReturnTarget(if_true, zone());
8477       if_true->SetJoinId(ast_id);
8478       HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
8479       Goto(if_true, true_target, function_state());
8480     }
8481     if (if_false->HasPredecessor()) {
8482       entry->RegisterReturnTarget(if_false, zone());
8483       if_false->SetJoinId(ast_id);
8484       HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
8485       Goto(if_false, false_target, function_state());
8486     }
8487     set_current_block(NULL);
8488     return true;
8489
8490   } else if (function_return()->HasPredecessor()) {
8491     function_state()->entry()->RegisterReturnTarget(function_return(), zone());
8492     function_return()->SetJoinId(ast_id);
8493     set_current_block(function_return());
8494   } else {
8495     set_current_block(NULL);
8496   }
8497   delete target_state;
8498   return true;
8499 }
8500
8501
8502 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) {
8503   return TryInline(expr->target(), expr->arguments()->length(), NULL,
8504                    expr->id(), expr->ReturnId(), NORMAL_RETURN);
8505 }
8506
8507
8508 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr,
8509                                                 HValue* implicit_return_value) {
8510   return TryInline(expr->target(), expr->arguments()->length(),
8511                    implicit_return_value, expr->id(), expr->ReturnId(),
8512                    CONSTRUCT_CALL_RETURN);
8513 }
8514
8515
8516 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
8517                                              Handle<Map> receiver_map,
8518                                              BailoutId ast_id,
8519                                              BailoutId return_id) {
8520   if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true;
8521   return TryInline(getter, 0, NULL, ast_id, return_id, GETTER_CALL_RETURN);
8522 }
8523
8524
8525 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
8526                                              Handle<Map> receiver_map,
8527                                              BailoutId id,
8528                                              BailoutId assignment_id,
8529                                              HValue* implicit_return_value) {
8530   if (TryInlineApiSetter(setter, receiver_map, id)) return true;
8531   return TryInline(setter, 1, implicit_return_value, id, assignment_id,
8532                    SETTER_CALL_RETURN);
8533 }
8534
8535
8536 bool HOptimizedGraphBuilder::TryInlineIndirectCall(Handle<JSFunction> function,
8537                                                    Call* expr,
8538                                                    int arguments_count) {
8539   return TryInline(function, arguments_count, NULL, expr->id(),
8540                    expr->ReturnId(), NORMAL_RETURN);
8541 }
8542
8543
8544 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) {
8545   if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
8546   BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
8547   switch (id) {
8548     case kMathExp:
8549       if (!FLAG_fast_math) break;
8550       // Fall through if FLAG_fast_math.
8551     case kMathRound:
8552     case kMathFround:
8553     case kMathFloor:
8554     case kMathAbs:
8555     case kMathSqrt:
8556     case kMathLog:
8557     case kMathClz32:
8558       if (expr->arguments()->length() == 1) {
8559         HValue* argument = Pop();
8560         Drop(2);  // Receiver and function.
8561         HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
8562         ast_context()->ReturnInstruction(op, expr->id());
8563         return true;
8564       }
8565       break;
8566     case kMathImul:
8567       if (expr->arguments()->length() == 2) {
8568         HValue* right = Pop();
8569         HValue* left = Pop();
8570         Drop(2);  // Receiver and function.
8571         HInstruction* op =
8572             HMul::NewImul(isolate(), zone(), context(), left, right);
8573         ast_context()->ReturnInstruction(op, expr->id());
8574         return true;
8575       }
8576       break;
8577     default:
8578       // Not supported for inlining yet.
8579       break;
8580   }
8581   return false;
8582 }
8583
8584
8585 // static
8586 bool HOptimizedGraphBuilder::IsReadOnlyLengthDescriptor(
8587     Handle<Map> jsarray_map) {
8588   DCHECK(!jsarray_map->is_dictionary_map());
8589   Isolate* isolate = jsarray_map->GetIsolate();
8590   Handle<Name> length_string = isolate->factory()->length_string();
8591   DescriptorArray* descriptors = jsarray_map->instance_descriptors();
8592   int number = descriptors->SearchWithCache(*length_string, *jsarray_map);
8593   DCHECK_NE(DescriptorArray::kNotFound, number);
8594   return descriptors->GetDetails(number).IsReadOnly();
8595 }
8596
8597
8598 // static
8599 bool HOptimizedGraphBuilder::CanInlineArrayResizeOperation(
8600     Handle<Map> receiver_map) {
8601   return !receiver_map.is_null() &&
8602          receiver_map->instance_type() == JS_ARRAY_TYPE &&
8603          IsFastElementsKind(receiver_map->elements_kind()) &&
8604          !receiver_map->is_dictionary_map() &&
8605          !IsReadOnlyLengthDescriptor(receiver_map) &&
8606          !receiver_map->is_observed() && receiver_map->is_extensible();
8607 }
8608
8609
8610 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
8611     Call* expr, Handle<JSFunction> function, Handle<Map> receiver_map,
8612     int args_count_no_receiver) {
8613   if (!function->shared()->HasBuiltinFunctionId()) return false;
8614   BuiltinFunctionId id = function->shared()->builtin_function_id();
8615   int argument_count = args_count_no_receiver + 1;  // Plus receiver.
8616
8617   if (receiver_map.is_null()) {
8618     HValue* receiver = environment()->ExpressionStackAt(args_count_no_receiver);
8619     if (receiver->IsConstant() &&
8620         HConstant::cast(receiver)->handle(isolate())->IsHeapObject()) {
8621       receiver_map =
8622           handle(Handle<HeapObject>::cast(
8623                      HConstant::cast(receiver)->handle(isolate()))->map());
8624     }
8625   }
8626   // Try to inline calls like Math.* as operations in the calling function.
8627   switch (id) {
8628     case kStringCharCodeAt:
8629     case kStringCharAt:
8630       if (argument_count == 2) {
8631         HValue* index = Pop();
8632         HValue* string = Pop();
8633         Drop(1);  // Function.
8634         HInstruction* char_code =
8635             BuildStringCharCodeAt(string, index);
8636         if (id == kStringCharCodeAt) {
8637           ast_context()->ReturnInstruction(char_code, expr->id());
8638           return true;
8639         }
8640         AddInstruction(char_code);
8641         HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
8642         ast_context()->ReturnInstruction(result, expr->id());
8643         return true;
8644       }
8645       break;
8646     case kStringFromCharCode:
8647       if (argument_count == 2) {
8648         HValue* argument = Pop();
8649         Drop(2);  // Receiver and function.
8650         HInstruction* result = NewUncasted<HStringCharFromCode>(argument);
8651         ast_context()->ReturnInstruction(result, expr->id());
8652         return true;
8653       }
8654       break;
8655     case kMathExp:
8656       if (!FLAG_fast_math) break;
8657       // Fall through if FLAG_fast_math.
8658     case kMathRound:
8659     case kMathFround:
8660     case kMathFloor:
8661     case kMathAbs:
8662     case kMathSqrt:
8663     case kMathLog:
8664     case kMathClz32:
8665       if (argument_count == 2) {
8666         HValue* argument = Pop();
8667         Drop(2);  // Receiver and function.
8668         HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
8669         ast_context()->ReturnInstruction(op, expr->id());
8670         return true;
8671       }
8672       break;
8673     case kMathPow:
8674       if (argument_count == 3) {
8675         HValue* right = Pop();
8676         HValue* left = Pop();
8677         Drop(2);  // Receiver and function.
8678         HInstruction* result = NULL;
8679         // Use sqrt() if exponent is 0.5 or -0.5.
8680         if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
8681           double exponent = HConstant::cast(right)->DoubleValue();
8682           if (exponent == 0.5) {
8683             result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf);
8684           } else if (exponent == -0.5) {
8685             HValue* one = graph()->GetConstant1();
8686             HInstruction* sqrt = AddUncasted<HUnaryMathOperation>(
8687                 left, kMathPowHalf);
8688             // MathPowHalf doesn't have side effects so there's no need for
8689             // an environment simulation here.
8690             DCHECK(!sqrt->HasObservableSideEffects());
8691             result = NewUncasted<HDiv>(one, sqrt);
8692           } else if (exponent == 2.0) {
8693             result = NewUncasted<HMul>(left, left);
8694           }
8695         }
8696
8697         if (result == NULL) {
8698           result = NewUncasted<HPower>(left, right);
8699         }
8700         ast_context()->ReturnInstruction(result, expr->id());
8701         return true;
8702       }
8703       break;
8704     case kMathMax:
8705     case kMathMin:
8706       if (argument_count == 3) {
8707         HValue* right = Pop();
8708         HValue* left = Pop();
8709         Drop(2);  // Receiver and function.
8710         HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
8711                                                      : HMathMinMax::kMathMax;
8712         HInstruction* result = NewUncasted<HMathMinMax>(left, right, op);
8713         ast_context()->ReturnInstruction(result, expr->id());
8714         return true;
8715       }
8716       break;
8717     case kMathImul:
8718       if (argument_count == 3) {
8719         HValue* right = Pop();
8720         HValue* left = Pop();
8721         Drop(2);  // Receiver and function.
8722         HInstruction* result =
8723             HMul::NewImul(isolate(), zone(), context(), left, right);
8724         ast_context()->ReturnInstruction(result, expr->id());
8725         return true;
8726       }
8727       break;
8728     case kArrayPop: {
8729       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
8730       ElementsKind elements_kind = receiver_map->elements_kind();
8731
8732       Drop(args_count_no_receiver);
8733       HValue* result;
8734       HValue* reduced_length;
8735       HValue* receiver = Pop();
8736
8737       HValue* checked_object = AddCheckMap(receiver, receiver_map);
8738       HValue* length =
8739           Add<HLoadNamedField>(checked_object, nullptr,
8740                                HObjectAccess::ForArrayLength(elements_kind));
8741
8742       Drop(1);  // Function.
8743
8744       { NoObservableSideEffectsScope scope(this);
8745         IfBuilder length_checker(this);
8746
8747         HValue* bounds_check = length_checker.If<HCompareNumericAndBranch>(
8748             length, graph()->GetConstant0(), Token::EQ);
8749         length_checker.Then();
8750
8751         if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
8752
8753         length_checker.Else();
8754         HValue* elements = AddLoadElements(checked_object);
8755         // Ensure that we aren't popping from a copy-on-write array.
8756         if (IsFastSmiOrObjectElementsKind(elements_kind)) {
8757           elements = BuildCopyElementsOnWrite(checked_object, elements,
8758                                               elements_kind, length);
8759         }
8760         reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1());
8761         result = AddElementAccess(elements, reduced_length, NULL,
8762                                   bounds_check, elements_kind, LOAD);
8763         HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
8764                            ? graph()->GetConstantHole()
8765                            : Add<HConstant>(HConstant::kHoleNaN);
8766         if (IsFastSmiOrObjectElementsKind(elements_kind)) {
8767           elements_kind = FAST_HOLEY_ELEMENTS;
8768         }
8769         AddElementAccess(
8770             elements, reduced_length, hole, bounds_check, elements_kind, STORE);
8771         Add<HStoreNamedField>(
8772             checked_object, HObjectAccess::ForArrayLength(elements_kind),
8773             reduced_length, STORE_TO_INITIALIZED_ENTRY);
8774
8775         if (!ast_context()->IsEffect()) Push(result);
8776
8777         length_checker.End();
8778       }
8779       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
8780       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8781       if (!ast_context()->IsEffect()) Drop(1);
8782
8783       ast_context()->ReturnValue(result);
8784       return true;
8785     }
8786     case kArrayPush: {
8787       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
8788       ElementsKind elements_kind = receiver_map->elements_kind();
8789
8790       // If there may be elements accessors in the prototype chain, the fast
8791       // inlined version can't be used.
8792       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
8793       // If there currently can be no elements accessors on the prototype chain,
8794       // it doesn't mean that there won't be any later. Install a full prototype
8795       // chain check to trap element accessors being installed on the prototype
8796       // chain, which would cause elements to go to dictionary mode and result
8797       // in a map change.
8798       Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
8799       BuildCheckPrototypeMaps(prototype, Handle<JSObject>());
8800
8801       // Protect against adding elements to the Array prototype, which needs to
8802       // route through appropriate bottlenecks.
8803       if (isolate()->IsFastArrayConstructorPrototypeChainIntact() &&
8804           !prototype->IsJSArray()) {
8805         return false;
8806       }
8807
8808       const int argc = args_count_no_receiver;
8809       if (argc != 1) return false;
8810
8811       HValue* value_to_push = Pop();
8812       HValue* array = Pop();
8813       Drop(1);  // Drop function.
8814
8815       HInstruction* new_size = NULL;
8816       HValue* length = NULL;
8817
8818       {
8819         NoObservableSideEffectsScope scope(this);
8820
8821         length = Add<HLoadNamedField>(
8822             array, nullptr, HObjectAccess::ForArrayLength(elements_kind));
8823
8824         new_size = AddUncasted<HAdd>(length, graph()->GetConstant1());
8825
8826         bool is_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
8827         HValue* checked_array = Add<HCheckMaps>(array, receiver_map);
8828         BuildUncheckedMonomorphicElementAccess(
8829             checked_array, length, value_to_push, is_array, elements_kind,
8830             STORE, NEVER_RETURN_HOLE, STORE_AND_GROW_NO_TRANSITION);
8831
8832         if (!ast_context()->IsEffect()) Push(new_size);
8833         Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8834         if (!ast_context()->IsEffect()) Drop(1);
8835       }
8836
8837       ast_context()->ReturnValue(new_size);
8838       return true;
8839     }
8840     case kArrayShift: {
8841       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
8842       ElementsKind kind = receiver_map->elements_kind();
8843
8844       // If there may be elements accessors in the prototype chain, the fast
8845       // inlined version can't be used.
8846       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
8847
8848       // If there currently can be no elements accessors on the prototype chain,
8849       // it doesn't mean that there won't be any later. Install a full prototype
8850       // chain check to trap element accessors being installed on the prototype
8851       // chain, which would cause elements to go to dictionary mode and result
8852       // in a map change.
8853       BuildCheckPrototypeMaps(
8854           handle(JSObject::cast(receiver_map->prototype()), isolate()),
8855           Handle<JSObject>::null());
8856
8857       // Threshold for fast inlined Array.shift().
8858       HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16));
8859
8860       Drop(args_count_no_receiver);
8861       HValue* receiver = Pop();
8862       HValue* function = Pop();
8863       HValue* result;
8864
8865       {
8866         NoObservableSideEffectsScope scope(this);
8867
8868         HValue* length = Add<HLoadNamedField>(
8869             receiver, nullptr, HObjectAccess::ForArrayLength(kind));
8870
8871         IfBuilder if_lengthiszero(this);
8872         HValue* lengthiszero = if_lengthiszero.If<HCompareNumericAndBranch>(
8873             length, graph()->GetConstant0(), Token::EQ);
8874         if_lengthiszero.Then();
8875         {
8876           if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
8877         }
8878         if_lengthiszero.Else();
8879         {
8880           HValue* elements = AddLoadElements(receiver);
8881
8882           // Check if we can use the fast inlined Array.shift().
8883           IfBuilder if_inline(this);
8884           if_inline.If<HCompareNumericAndBranch>(
8885               length, inline_threshold, Token::LTE);
8886           if (IsFastSmiOrObjectElementsKind(kind)) {
8887             // We cannot handle copy-on-write backing stores here.
8888             if_inline.AndIf<HCompareMap>(
8889                 elements, isolate()->factory()->fixed_array_map());
8890           }
8891           if_inline.Then();
8892           {
8893             // Remember the result.
8894             if (!ast_context()->IsEffect()) {
8895               Push(AddElementAccess(elements, graph()->GetConstant0(), NULL,
8896                                     lengthiszero, kind, LOAD));
8897             }
8898
8899             // Compute the new length.
8900             HValue* new_length = AddUncasted<HSub>(
8901                 length, graph()->GetConstant1());
8902             new_length->ClearFlag(HValue::kCanOverflow);
8903
8904             // Copy the remaining elements.
8905             LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
8906             {
8907               HValue* new_key = loop.BeginBody(
8908                   graph()->GetConstant0(), new_length, Token::LT);
8909               HValue* key = AddUncasted<HAdd>(new_key, graph()->GetConstant1());
8910               key->ClearFlag(HValue::kCanOverflow);
8911               ElementsKind copy_kind =
8912                   kind == FAST_HOLEY_SMI_ELEMENTS ? FAST_HOLEY_ELEMENTS : kind;
8913               HValue* element = AddUncasted<HLoadKeyed>(
8914                   elements, key, lengthiszero, copy_kind, ALLOW_RETURN_HOLE);
8915               HStoreKeyed* store =
8916                   Add<HStoreKeyed>(elements, new_key, element, copy_kind);
8917               store->SetFlag(HValue::kAllowUndefinedAsNaN);
8918             }
8919             loop.EndBody();
8920
8921             // Put a hole at the end.
8922             HValue* hole = IsFastSmiOrObjectElementsKind(kind)
8923                                ? graph()->GetConstantHole()
8924                                : Add<HConstant>(HConstant::kHoleNaN);
8925             if (IsFastSmiOrObjectElementsKind(kind)) kind = FAST_HOLEY_ELEMENTS;
8926             Add<HStoreKeyed>(
8927                 elements, new_length, hole, kind, INITIALIZING_STORE);
8928
8929             // Remember new length.
8930             Add<HStoreNamedField>(
8931                 receiver, HObjectAccess::ForArrayLength(kind),
8932                 new_length, STORE_TO_INITIALIZED_ENTRY);
8933           }
8934           if_inline.Else();
8935           {
8936             Add<HPushArguments>(receiver);
8937             result = Add<HCallJSFunction>(function, 1, true);
8938             if (!ast_context()->IsEffect()) Push(result);
8939           }
8940           if_inline.End();
8941         }
8942         if_lengthiszero.End();
8943       }
8944       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
8945       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8946       if (!ast_context()->IsEffect()) Drop(1);
8947       ast_context()->ReturnValue(result);
8948       return true;
8949     }
8950     case kArrayIndexOf:
8951     case kArrayLastIndexOf: {
8952       if (receiver_map.is_null()) return false;
8953       if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
8954       ElementsKind kind = receiver_map->elements_kind();
8955       if (!IsFastElementsKind(kind)) return false;
8956       if (receiver_map->is_observed()) return false;
8957       if (argument_count != 2) return false;
8958       if (!receiver_map->is_extensible()) return false;
8959
8960       // If there may be elements accessors in the prototype chain, the fast
8961       // inlined version can't be used.
8962       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
8963
8964       // If there currently can be no elements accessors on the prototype chain,
8965       // it doesn't mean that there won't be any later. Install a full prototype
8966       // chain check to trap element accessors being installed on the prototype
8967       // chain, which would cause elements to go to dictionary mode and result
8968       // in a map change.
8969       BuildCheckPrototypeMaps(
8970           handle(JSObject::cast(receiver_map->prototype()), isolate()),
8971           Handle<JSObject>::null());
8972
8973       HValue* search_element = Pop();
8974       HValue* receiver = Pop();
8975       Drop(1);  // Drop function.
8976
8977       ArrayIndexOfMode mode = (id == kArrayIndexOf)
8978           ? kFirstIndexOf : kLastIndexOf;
8979       HValue* index = BuildArrayIndexOf(receiver, search_element, kind, mode);
8980
8981       if (!ast_context()->IsEffect()) Push(index);
8982       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8983       if (!ast_context()->IsEffect()) Drop(1);
8984       ast_context()->ReturnValue(index);
8985       return true;
8986     }
8987     default:
8988       // Not yet supported for inlining.
8989       break;
8990   }
8991   return false;
8992 }
8993
8994
8995 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr,
8996                                                       HValue* receiver) {
8997   Handle<JSFunction> function = expr->target();
8998   int argc = expr->arguments()->length();
8999   SmallMapList receiver_maps;
9000   return TryInlineApiCall(function,
9001                           receiver,
9002                           &receiver_maps,
9003                           argc,
9004                           expr->id(),
9005                           kCallApiFunction);
9006 }
9007
9008
9009 bool HOptimizedGraphBuilder::TryInlineApiMethodCall(
9010     Call* expr,
9011     HValue* receiver,
9012     SmallMapList* receiver_maps) {
9013   Handle<JSFunction> function = expr->target();
9014   int argc = expr->arguments()->length();
9015   return TryInlineApiCall(function,
9016                           receiver,
9017                           receiver_maps,
9018                           argc,
9019                           expr->id(),
9020                           kCallApiMethod);
9021 }
9022
9023
9024 bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<JSFunction> function,
9025                                                 Handle<Map> receiver_map,
9026                                                 BailoutId ast_id) {
9027   SmallMapList receiver_maps(1, zone());
9028   receiver_maps.Add(receiver_map, zone());
9029   return TryInlineApiCall(function,
9030                           NULL,  // Receiver is on expression stack.
9031                           &receiver_maps,
9032                           0,
9033                           ast_id,
9034                           kCallApiGetter);
9035 }
9036
9037
9038 bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<JSFunction> function,
9039                                                 Handle<Map> receiver_map,
9040                                                 BailoutId ast_id) {
9041   SmallMapList receiver_maps(1, zone());
9042   receiver_maps.Add(receiver_map, zone());
9043   return TryInlineApiCall(function,
9044                           NULL,  // Receiver is on expression stack.
9045                           &receiver_maps,
9046                           1,
9047                           ast_id,
9048                           kCallApiSetter);
9049 }
9050
9051
9052 bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function,
9053                                                HValue* receiver,
9054                                                SmallMapList* receiver_maps,
9055                                                int argc,
9056                                                BailoutId ast_id,
9057                                                ApiCallType call_type) {
9058   if (function->context()->native_context() !=
9059       top_info()->closure()->context()->native_context()) {
9060     return false;
9061   }
9062   CallOptimization optimization(function);
9063   if (!optimization.is_simple_api_call()) return false;
9064   Handle<Map> holder_map;
9065   for (int i = 0; i < receiver_maps->length(); ++i) {
9066     auto map = receiver_maps->at(i);
9067     // Don't inline calls to receivers requiring accesschecks.
9068     if (map->is_access_check_needed()) return false;
9069   }
9070   if (call_type == kCallApiFunction) {
9071     // Cannot embed a direct reference to the global proxy map
9072     // as it maybe dropped on deserialization.
9073     CHECK(!isolate()->serializer_enabled());
9074     DCHECK_EQ(0, receiver_maps->length());
9075     receiver_maps->Add(handle(function->global_proxy()->map()), zone());
9076   }
9077   CallOptimization::HolderLookup holder_lookup =
9078       CallOptimization::kHolderNotFound;
9079   Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
9080       receiver_maps->first(), &holder_lookup);
9081   if (holder_lookup == CallOptimization::kHolderNotFound) return false;
9082
9083   if (FLAG_trace_inlining) {
9084     PrintF("Inlining api function ");
9085     function->ShortPrint();
9086     PrintF("\n");
9087   }
9088
9089   bool is_function = false;
9090   bool is_store = false;
9091   switch (call_type) {
9092     case kCallApiFunction:
9093     case kCallApiMethod:
9094       // Need to check that none of the receiver maps could have changed.
9095       Add<HCheckMaps>(receiver, receiver_maps);
9096       // Need to ensure the chain between receiver and api_holder is intact.
9097       if (holder_lookup == CallOptimization::kHolderFound) {
9098         AddCheckPrototypeMaps(api_holder, receiver_maps->first());
9099       } else {
9100         DCHECK_EQ(holder_lookup, CallOptimization::kHolderIsReceiver);
9101       }
9102       // Includes receiver.
9103       PushArgumentsFromEnvironment(argc + 1);
9104       is_function = true;
9105       break;
9106     case kCallApiGetter:
9107       // Receiver and prototype chain cannot have changed.
9108       DCHECK_EQ(0, argc);
9109       DCHECK_NULL(receiver);
9110       // Receiver is on expression stack.
9111       receiver = Pop();
9112       Add<HPushArguments>(receiver);
9113       break;
9114     case kCallApiSetter:
9115       {
9116         is_store = true;
9117         // Receiver and prototype chain cannot have changed.
9118         DCHECK_EQ(1, argc);
9119         DCHECK_NULL(receiver);
9120         // Receiver and value are on expression stack.
9121         HValue* value = Pop();
9122         receiver = Pop();
9123         Add<HPushArguments>(receiver, value);
9124         break;
9125      }
9126   }
9127
9128   HValue* holder = NULL;
9129   switch (holder_lookup) {
9130     case CallOptimization::kHolderFound:
9131       holder = Add<HConstant>(api_holder);
9132       break;
9133     case CallOptimization::kHolderIsReceiver:
9134       holder = receiver;
9135       break;
9136     case CallOptimization::kHolderNotFound:
9137       UNREACHABLE();
9138       break;
9139   }
9140   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
9141   Handle<Object> call_data_obj(api_call_info->data(), isolate());
9142   bool call_data_undefined = call_data_obj->IsUndefined();
9143   HValue* call_data = Add<HConstant>(call_data_obj);
9144   ApiFunction fun(v8::ToCData<Address>(api_call_info->callback()));
9145   ExternalReference ref = ExternalReference(&fun,
9146                                             ExternalReference::DIRECT_API_CALL,
9147                                             isolate());
9148   HValue* api_function_address = Add<HConstant>(ExternalReference(ref));
9149
9150   HValue* op_vals[] = {context(), Add<HConstant>(function), call_data, holder,
9151                        api_function_address, nullptr};
9152
9153   HInstruction* call = nullptr;
9154   if (!is_function) {
9155     CallApiAccessorStub stub(isolate(), is_store, call_data_undefined);
9156     Handle<Code> code = stub.GetCode();
9157     HConstant* code_value = Add<HConstant>(code);
9158     ApiAccessorDescriptor descriptor(isolate());
9159     call = New<HCallWithDescriptor>(
9160         code_value, argc + 1, descriptor,
9161         Vector<HValue*>(op_vals, arraysize(op_vals) - 1));
9162   } else if (argc <= CallApiFunctionWithFixedArgsStub::kMaxFixedArgs) {
9163     CallApiFunctionWithFixedArgsStub stub(isolate(), argc, call_data_undefined);
9164     Handle<Code> code = stub.GetCode();
9165     HConstant* code_value = Add<HConstant>(code);
9166     ApiFunctionWithFixedArgsDescriptor descriptor(isolate());
9167     call = New<HCallWithDescriptor>(
9168         code_value, argc + 1, descriptor,
9169         Vector<HValue*>(op_vals, arraysize(op_vals) - 1));
9170     Drop(1);  // Drop function.
9171   } else {
9172     op_vals[arraysize(op_vals) - 1] = Add<HConstant>(argc);
9173     CallApiFunctionStub stub(isolate(), call_data_undefined);
9174     Handle<Code> code = stub.GetCode();
9175     HConstant* code_value = Add<HConstant>(code);
9176     ApiFunctionDescriptor descriptor(isolate());
9177     call =
9178         New<HCallWithDescriptor>(code_value, argc + 1, descriptor,
9179                                  Vector<HValue*>(op_vals, arraysize(op_vals)));
9180     Drop(1);  // Drop function.
9181   }
9182
9183   ast_context()->ReturnInstruction(call, ast_id);
9184   return true;
9185 }
9186
9187
9188 void HOptimizedGraphBuilder::HandleIndirectCall(Call* expr, HValue* function,
9189                                                 int arguments_count) {
9190   Handle<JSFunction> known_function;
9191   int args_count_no_receiver = arguments_count - 1;
9192   if (function->IsConstant() &&
9193       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
9194     known_function =
9195         Handle<JSFunction>::cast(HConstant::cast(function)->handle(isolate()));
9196     if (TryInlineBuiltinMethodCall(expr, known_function, Handle<Map>(),
9197                                    args_count_no_receiver)) {
9198       if (FLAG_trace_inlining) {
9199         PrintF("Inlining builtin ");
9200         known_function->ShortPrint();
9201         PrintF("\n");
9202       }
9203       return;
9204     }
9205
9206     if (TryInlineIndirectCall(known_function, expr, args_count_no_receiver)) {
9207       return;
9208     }
9209   }
9210
9211   PushArgumentsFromEnvironment(arguments_count);
9212   HInvokeFunction* call =
9213       New<HInvokeFunction>(function, known_function, arguments_count);
9214   Drop(1);  // Function
9215   ast_context()->ReturnInstruction(call, expr->id());
9216 }
9217
9218
9219 bool HOptimizedGraphBuilder::TryIndirectCall(Call* expr) {
9220   DCHECK(expr->expression()->IsProperty());
9221
9222   if (!expr->IsMonomorphic()) {
9223     return false;
9224   }
9225   Handle<Map> function_map = expr->GetReceiverTypes()->first();
9226   if (function_map->instance_type() != JS_FUNCTION_TYPE ||
9227       !expr->target()->shared()->HasBuiltinFunctionId()) {
9228     return false;
9229   }
9230
9231   switch (expr->target()->shared()->builtin_function_id()) {
9232     case kFunctionCall: {
9233       if (expr->arguments()->length() == 0) return false;
9234       BuildFunctionCall(expr);
9235       return true;
9236     }
9237     case kFunctionApply: {
9238       // For .apply, only the pattern f.apply(receiver, arguments)
9239       // is supported.
9240       if (current_info()->scope()->arguments() == NULL) return false;
9241
9242       if (!CanBeFunctionApplyArguments(expr)) return false;
9243
9244       BuildFunctionApply(expr);
9245       return true;
9246     }
9247     default: { return false; }
9248   }
9249   UNREACHABLE();
9250 }
9251
9252
9253 void HOptimizedGraphBuilder::BuildFunctionApply(Call* expr) {
9254   ZoneList<Expression*>* args = expr->arguments();
9255   CHECK_ALIVE(VisitForValue(args->at(0)));
9256   HValue* receiver = Pop();  // receiver
9257   HValue* function = Pop();  // f
9258   Drop(1);  // apply
9259
9260   Handle<Map> function_map = expr->GetReceiverTypes()->first();
9261   HValue* checked_function = AddCheckMap(function, function_map);
9262
9263   if (function_state()->outer() == NULL) {
9264     HInstruction* elements = Add<HArgumentsElements>(false);
9265     HInstruction* length = Add<HArgumentsLength>(elements);
9266     HValue* wrapped_receiver = BuildWrapReceiver(receiver, checked_function);
9267     HInstruction* result = New<HApplyArguments>(function,
9268                                                 wrapped_receiver,
9269                                                 length,
9270                                                 elements);
9271     ast_context()->ReturnInstruction(result, expr->id());
9272   } else {
9273     // We are inside inlined function and we know exactly what is inside
9274     // arguments object. But we need to be able to materialize at deopt.
9275     DCHECK_EQ(environment()->arguments_environment()->parameter_count(),
9276               function_state()->entry()->arguments_object()->arguments_count());
9277     HArgumentsObject* args = function_state()->entry()->arguments_object();
9278     const ZoneList<HValue*>* arguments_values = args->arguments_values();
9279     int arguments_count = arguments_values->length();
9280     Push(function);
9281     Push(BuildWrapReceiver(receiver, checked_function));
9282     for (int i = 1; i < arguments_count; i++) {
9283       Push(arguments_values->at(i));
9284     }
9285     HandleIndirectCall(expr, function, arguments_count);
9286   }
9287 }
9288
9289
9290 // f.call(...)
9291 void HOptimizedGraphBuilder::BuildFunctionCall(Call* expr) {
9292   HValue* function = Top();  // f
9293   Handle<Map> function_map = expr->GetReceiverTypes()->first();
9294   HValue* checked_function = AddCheckMap(function, function_map);
9295
9296   // f and call are on the stack in the unoptimized code
9297   // during evaluation of the arguments.
9298   CHECK_ALIVE(VisitExpressions(expr->arguments()));
9299
9300   int args_length = expr->arguments()->length();
9301   int receiver_index = args_length - 1;
9302   // Patch the receiver.
9303   HValue* receiver = BuildWrapReceiver(
9304       environment()->ExpressionStackAt(receiver_index), checked_function);
9305   environment()->SetExpressionStackAt(receiver_index, receiver);
9306
9307   // Call must not be on the stack from now on.
9308   int call_index = args_length + 1;
9309   environment()->RemoveExpressionStackAt(call_index);
9310
9311   HandleIndirectCall(expr, function, args_length);
9312 }
9313
9314
9315 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function,
9316                                                     Handle<JSFunction> target) {
9317   SharedFunctionInfo* shared = target->shared();
9318   if (is_sloppy(shared->language_mode()) && !shared->native()) {
9319     // Cannot embed a direct reference to the global proxy
9320     // as is it dropped on deserialization.
9321     CHECK(!isolate()->serializer_enabled());
9322     Handle<JSObject> global_proxy(target->context()->global_proxy());
9323     return Add<HConstant>(global_proxy);
9324   }
9325   return graph()->GetConstantUndefined();
9326 }
9327
9328
9329 void HOptimizedGraphBuilder::BuildArrayCall(Expression* expression,
9330                                             int arguments_count,
9331                                             HValue* function,
9332                                             Handle<AllocationSite> site) {
9333   Add<HCheckValue>(function, array_function());
9334
9335   if (IsCallArrayInlineable(arguments_count, site)) {
9336     BuildInlinedCallArray(expression, arguments_count, site);
9337     return;
9338   }
9339
9340   HInstruction* call = PreProcessCall(New<HCallNewArray>(
9341       function, arguments_count + 1, site->GetElementsKind(), site));
9342   if (expression->IsCall()) {
9343     Drop(1);
9344   }
9345   ast_context()->ReturnInstruction(call, expression->id());
9346 }
9347
9348
9349 HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver,
9350                                                   HValue* search_element,
9351                                                   ElementsKind kind,
9352                                                   ArrayIndexOfMode mode) {
9353   DCHECK(IsFastElementsKind(kind));
9354
9355   NoObservableSideEffectsScope no_effects(this);
9356
9357   HValue* elements = AddLoadElements(receiver);
9358   HValue* length = AddLoadArrayLength(receiver, kind);
9359
9360   HValue* initial;
9361   HValue* terminating;
9362   Token::Value token;
9363   LoopBuilder::Direction direction;
9364   if (mode == kFirstIndexOf) {
9365     initial = graph()->GetConstant0();
9366     terminating = length;
9367     token = Token::LT;
9368     direction = LoopBuilder::kPostIncrement;
9369   } else {
9370     DCHECK_EQ(kLastIndexOf, mode);
9371     initial = length;
9372     terminating = graph()->GetConstant0();
9373     token = Token::GT;
9374     direction = LoopBuilder::kPreDecrement;
9375   }
9376
9377   Push(graph()->GetConstantMinus1());
9378   if (IsFastDoubleElementsKind(kind) || IsFastSmiElementsKind(kind)) {
9379     // Make sure that we can actually compare numbers correctly below, see
9380     // https://code.google.com/p/chromium/issues/detail?id=407946 for details.
9381     search_element = AddUncasted<HForceRepresentation>(
9382         search_element, IsFastSmiElementsKind(kind) ? Representation::Smi()
9383                                                     : Representation::Double());
9384
9385     LoopBuilder loop(this, context(), direction);
9386     {
9387       HValue* index = loop.BeginBody(initial, terminating, token);
9388       HValue* element = AddUncasted<HLoadKeyed>(elements, index, nullptr, kind,
9389                                                 ALLOW_RETURN_HOLE);
9390       IfBuilder if_issame(this);
9391       if_issame.If<HCompareNumericAndBranch>(element, search_element,
9392                                              Token::EQ_STRICT);
9393       if_issame.Then();
9394       {
9395         Drop(1);
9396         Push(index);
9397         loop.Break();
9398       }
9399       if_issame.End();
9400     }
9401     loop.EndBody();
9402   } else {
9403     IfBuilder if_isstring(this);
9404     if_isstring.If<HIsStringAndBranch>(search_element);
9405     if_isstring.Then();
9406     {
9407       LoopBuilder loop(this, context(), direction);
9408       {
9409         HValue* index = loop.BeginBody(initial, terminating, token);
9410         HValue* element = AddUncasted<HLoadKeyed>(elements, index, nullptr,
9411                                                   kind, ALLOW_RETURN_HOLE);
9412         IfBuilder if_issame(this);
9413         if_issame.If<HIsStringAndBranch>(element);
9414         if_issame.AndIf<HStringCompareAndBranch>(
9415             element, search_element, Token::EQ_STRICT);
9416         if_issame.Then();
9417         {
9418           Drop(1);
9419           Push(index);
9420           loop.Break();
9421         }
9422         if_issame.End();
9423       }
9424       loop.EndBody();
9425     }
9426     if_isstring.Else();
9427     {
9428       IfBuilder if_isnumber(this);
9429       if_isnumber.If<HIsSmiAndBranch>(search_element);
9430       if_isnumber.OrIf<HCompareMap>(
9431           search_element, isolate()->factory()->heap_number_map());
9432       if_isnumber.Then();
9433       {
9434         HValue* search_number =
9435             AddUncasted<HForceRepresentation>(search_element,
9436                                               Representation::Double());
9437         LoopBuilder loop(this, context(), direction);
9438         {
9439           HValue* index = loop.BeginBody(initial, terminating, token);
9440           HValue* element = AddUncasted<HLoadKeyed>(elements, index, nullptr,
9441                                                     kind, ALLOW_RETURN_HOLE);
9442
9443           IfBuilder if_element_isnumber(this);
9444           if_element_isnumber.If<HIsSmiAndBranch>(element);
9445           if_element_isnumber.OrIf<HCompareMap>(
9446               element, isolate()->factory()->heap_number_map());
9447           if_element_isnumber.Then();
9448           {
9449             HValue* number =
9450                 AddUncasted<HForceRepresentation>(element,
9451                                                   Representation::Double());
9452             IfBuilder if_issame(this);
9453             if_issame.If<HCompareNumericAndBranch>(
9454                 number, search_number, Token::EQ_STRICT);
9455             if_issame.Then();
9456             {
9457               Drop(1);
9458               Push(index);
9459               loop.Break();
9460             }
9461             if_issame.End();
9462           }
9463           if_element_isnumber.End();
9464         }
9465         loop.EndBody();
9466       }
9467       if_isnumber.Else();
9468       {
9469         LoopBuilder loop(this, context(), direction);
9470         {
9471           HValue* index = loop.BeginBody(initial, terminating, token);
9472           HValue* element = AddUncasted<HLoadKeyed>(elements, index, nullptr,
9473                                                     kind, ALLOW_RETURN_HOLE);
9474           IfBuilder if_issame(this);
9475           if_issame.If<HCompareObjectEqAndBranch>(
9476               element, search_element);
9477           if_issame.Then();
9478           {
9479             Drop(1);
9480             Push(index);
9481             loop.Break();
9482           }
9483           if_issame.End();
9484         }
9485         loop.EndBody();
9486       }
9487       if_isnumber.End();
9488     }
9489     if_isstring.End();
9490   }
9491
9492   return Pop();
9493 }
9494
9495
9496 bool HOptimizedGraphBuilder::TryHandleArrayCall(Call* expr, HValue* function) {
9497   if (!array_function().is_identical_to(expr->target())) {
9498     return false;
9499   }
9500
9501   Handle<AllocationSite> site = expr->allocation_site();
9502   if (site.is_null()) return false;
9503
9504   BuildArrayCall(expr,
9505                  expr->arguments()->length(),
9506                  function,
9507                  site);
9508   return true;
9509 }
9510
9511
9512 bool HOptimizedGraphBuilder::TryHandleArrayCallNew(CallNew* expr,
9513                                                    HValue* function) {
9514   if (!array_function().is_identical_to(expr->target())) {
9515     return false;
9516   }
9517
9518   Handle<AllocationSite> site = expr->allocation_site();
9519   if (site.is_null()) return false;
9520
9521   BuildArrayCall(expr, expr->arguments()->length(), function, site);
9522   return true;
9523 }
9524
9525
9526 bool HOptimizedGraphBuilder::CanBeFunctionApplyArguments(Call* expr) {
9527   ZoneList<Expression*>* args = expr->arguments();
9528   if (args->length() != 2) return false;
9529   VariableProxy* arg_two = args->at(1)->AsVariableProxy();
9530   if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
9531   HValue* arg_two_value = LookupAndMakeLive(arg_two->var());
9532   if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
9533   return true;
9534 }
9535
9536
9537 void HOptimizedGraphBuilder::VisitCall(Call* expr) {
9538   DCHECK(!HasStackOverflow());
9539   DCHECK(current_block() != NULL);
9540   DCHECK(current_block()->HasPredecessor());
9541   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
9542   Expression* callee = expr->expression();
9543   int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
9544   HInstruction* call = NULL;
9545
9546   Property* prop = callee->AsProperty();
9547   if (prop != NULL) {
9548     CHECK_ALIVE(VisitForValue(prop->obj()));
9549     HValue* receiver = Top();
9550
9551     SmallMapList* maps;
9552     ComputeReceiverTypes(expr, receiver, &maps, zone());
9553
9554     if (prop->key()->IsPropertyName() && maps->length() > 0) {
9555       Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
9556       PropertyAccessInfo info(this, LOAD, maps->first(), name);
9557       if (!info.CanAccessAsMonomorphic(maps)) {
9558         HandlePolymorphicCallNamed(expr, receiver, maps, name);
9559         return;
9560       }
9561     }
9562     HValue* key = NULL;
9563     if (!prop->key()->IsPropertyName()) {
9564       CHECK_ALIVE(VisitForValue(prop->key()));
9565       key = Pop();
9566     }
9567
9568     CHECK_ALIVE(PushLoad(prop, receiver, key));
9569     HValue* function = Pop();
9570
9571     if (function->IsConstant() &&
9572         HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
9573       // Push the function under the receiver.
9574       environment()->SetExpressionStackAt(0, function);
9575       Push(receiver);
9576
9577       Handle<JSFunction> known_function = Handle<JSFunction>::cast(
9578           HConstant::cast(function)->handle(isolate()));
9579       expr->set_target(known_function);
9580
9581       if (TryIndirectCall(expr)) return;
9582       CHECK_ALIVE(VisitExpressions(expr->arguments()));
9583
9584       Handle<Map> map = maps->length() == 1 ? maps->first() : Handle<Map>();
9585       if (TryInlineBuiltinMethodCall(expr, known_function, map,
9586                                      expr->arguments()->length())) {
9587         if (FLAG_trace_inlining) {
9588           PrintF("Inlining builtin ");
9589           known_function->ShortPrint();
9590           PrintF("\n");
9591         }
9592         return;
9593       }
9594       if (TryInlineApiMethodCall(expr, receiver, maps)) return;
9595
9596       // Wrap the receiver if necessary.
9597       if (NeedsWrapping(maps->first(), known_function)) {
9598         // Since HWrapReceiver currently cannot actually wrap numbers and
9599         // strings, use the regular CallFunctionStub for method calls to wrap
9600         // the receiver.
9601         // TODO(verwaest): Support creation of value wrappers directly in
9602         // HWrapReceiver.
9603         call = New<HCallFunction>(
9604             function, argument_count, WRAP_AND_CALL);
9605       } else if (TryInlineCall(expr)) {
9606         return;
9607       } else {
9608         call = BuildCallConstantFunction(known_function, argument_count);
9609       }
9610
9611     } else {
9612       ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED;
9613       if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) {
9614         // We have to use EAGER deoptimization here because Deoptimizer::SOFT
9615         // gets ignored by the always-opt flag, which leads to incorrect code.
9616         Add<HDeoptimize>(
9617             Deoptimizer::kInsufficientTypeFeedbackForCallWithArguments,
9618             Deoptimizer::EAGER);
9619         arguments_flag = ARGUMENTS_FAKED;
9620       }
9621
9622       // Push the function under the receiver.
9623       environment()->SetExpressionStackAt(0, function);
9624       Push(receiver);
9625
9626       CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag));
9627       CallFunctionFlags flags = receiver->type().IsJSObject()
9628           ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD;
9629       call = New<HCallFunction>(function, argument_count, flags);
9630     }
9631     PushArgumentsFromEnvironment(argument_count);
9632
9633   } else {
9634     VariableProxy* proxy = expr->expression()->AsVariableProxy();
9635     if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
9636       return Bailout(kPossibleDirectCallToEval);
9637     }
9638
9639     // The function is on the stack in the unoptimized code during
9640     // evaluation of the arguments.
9641     CHECK_ALIVE(VisitForValue(expr->expression()));
9642     HValue* function = Top();
9643     if (function->IsConstant() &&
9644         HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
9645       Handle<Object> constant = HConstant::cast(function)->handle(isolate());
9646       Handle<JSFunction> target = Handle<JSFunction>::cast(constant);
9647       expr->SetKnownGlobalTarget(target);
9648     }
9649
9650     // Placeholder for the receiver.
9651     Push(graph()->GetConstantUndefined());
9652     CHECK_ALIVE(VisitExpressions(expr->arguments()));
9653
9654     if (expr->IsMonomorphic()) {
9655       Add<HCheckValue>(function, expr->target());
9656
9657       // Patch the global object on the stack by the expected receiver.
9658       HValue* receiver = ImplicitReceiverFor(function, expr->target());
9659       const int receiver_index = argument_count - 1;
9660       environment()->SetExpressionStackAt(receiver_index, receiver);
9661
9662       if (TryInlineBuiltinFunctionCall(expr)) {
9663         if (FLAG_trace_inlining) {
9664           PrintF("Inlining builtin ");
9665           expr->target()->ShortPrint();
9666           PrintF("\n");
9667         }
9668         return;
9669       }
9670       if (TryInlineApiFunctionCall(expr, receiver)) return;
9671       if (TryHandleArrayCall(expr, function)) return;
9672       if (TryInlineCall(expr)) return;
9673
9674       PushArgumentsFromEnvironment(argument_count);
9675       call = BuildCallConstantFunction(expr->target(), argument_count);
9676     } else {
9677       PushArgumentsFromEnvironment(argument_count);
9678       HCallFunction* call_function =
9679           New<HCallFunction>(function, argument_count);
9680       call = call_function;
9681       if (expr->is_uninitialized() &&
9682           expr->IsUsingCallFeedbackICSlot(isolate())) {
9683         // We've never seen this call before, so let's have Crankshaft learn
9684         // through the type vector.
9685         Handle<TypeFeedbackVector> vector =
9686             handle(current_feedback_vector(), isolate());
9687         FeedbackVectorICSlot slot = expr->CallFeedbackICSlot();
9688         call_function->SetVectorAndSlot(vector, slot);
9689       }
9690     }
9691   }
9692
9693   Drop(1);  // Drop the function.
9694   return ast_context()->ReturnInstruction(call, expr->id());
9695 }
9696
9697
9698 void HOptimizedGraphBuilder::BuildInlinedCallArray(
9699     Expression* expression,
9700     int argument_count,
9701     Handle<AllocationSite> site) {
9702   DCHECK(!site.is_null());
9703   DCHECK(argument_count >= 0 && argument_count <= 1);
9704   NoObservableSideEffectsScope no_effects(this);
9705
9706   // We should at least have the constructor on the expression stack.
9707   HValue* constructor = environment()->ExpressionStackAt(argument_count);
9708
9709   // Register on the site for deoptimization if the transition feedback changes.
9710   top_info()->dependencies()->AssumeTransitionStable(site);
9711   ElementsKind kind = site->GetElementsKind();
9712   HInstruction* site_instruction = Add<HConstant>(site);
9713
9714   // In the single constant argument case, we may have to adjust elements kind
9715   // to avoid creating a packed non-empty array.
9716   if (argument_count == 1 && !IsHoleyElementsKind(kind)) {
9717     HValue* argument = environment()->Top();
9718     if (argument->IsConstant()) {
9719       HConstant* constant_argument = HConstant::cast(argument);
9720       DCHECK(constant_argument->HasSmiValue());
9721       int constant_array_size = constant_argument->Integer32Value();
9722       if (constant_array_size != 0) {
9723         kind = GetHoleyElementsKind(kind);
9724       }
9725     }
9726   }
9727
9728   // Build the array.
9729   JSArrayBuilder array_builder(this,
9730                                kind,
9731                                site_instruction,
9732                                constructor,
9733                                DISABLE_ALLOCATION_SITES);
9734   HValue* new_object = argument_count == 0
9735       ? array_builder.AllocateEmptyArray()
9736       : BuildAllocateArrayFromLength(&array_builder, Top());
9737
9738   int args_to_drop = argument_count + (expression->IsCall() ? 2 : 1);
9739   Drop(args_to_drop);
9740   ast_context()->ReturnValue(new_object);
9741 }
9742
9743
9744 // Checks whether allocation using the given constructor can be inlined.
9745 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
9746   return constructor->has_initial_map() &&
9747          constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
9748          constructor->initial_map()->instance_size() <
9749              HAllocate::kMaxInlineSize;
9750 }
9751
9752
9753 bool HOptimizedGraphBuilder::IsCallArrayInlineable(
9754     int argument_count,
9755     Handle<AllocationSite> site) {
9756   Handle<JSFunction> caller = current_info()->closure();
9757   Handle<JSFunction> target = array_function();
9758   // We should have the function plus array arguments on the environment stack.
9759   DCHECK(environment()->length() >= (argument_count + 1));
9760   DCHECK(!site.is_null());
9761
9762   bool inline_ok = false;
9763   if (site->CanInlineCall()) {
9764     // We also want to avoid inlining in certain 1 argument scenarios.
9765     if (argument_count == 1) {
9766       HValue* argument = Top();
9767       if (argument->IsConstant()) {
9768         // Do not inline if the constant length argument is not a smi or
9769         // outside the valid range for unrolled loop initialization.
9770         HConstant* constant_argument = HConstant::cast(argument);
9771         if (constant_argument->HasSmiValue()) {
9772           int value = constant_argument->Integer32Value();
9773           inline_ok = value >= 0 && value <= kElementLoopUnrollThreshold;
9774           if (!inline_ok) {
9775             TraceInline(target, caller,
9776                         "Constant length outside of valid inlining range.");
9777           }
9778         }
9779       } else {
9780         TraceInline(target, caller,
9781                     "Dont inline [new] Array(n) where n isn't constant.");
9782       }
9783     } else if (argument_count == 0) {
9784       inline_ok = true;
9785     } else {
9786       TraceInline(target, caller, "Too many arguments to inline.");
9787     }
9788   } else {
9789     TraceInline(target, caller, "AllocationSite requested no inlining.");
9790   }
9791
9792   if (inline_ok) {
9793     TraceInline(target, caller, NULL);
9794   }
9795   return inline_ok;
9796 }
9797
9798
9799 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
9800   DCHECK(!HasStackOverflow());
9801   DCHECK(current_block() != NULL);
9802   DCHECK(current_block()->HasPredecessor());
9803   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
9804   int argument_count = expr->arguments()->length() + 1;  // Plus constructor.
9805   Factory* factory = isolate()->factory();
9806
9807   // The constructor function is on the stack in the unoptimized code
9808   // during evaluation of the arguments.
9809   CHECK_ALIVE(VisitForValue(expr->expression()));
9810   HValue* function = Top();
9811   CHECK_ALIVE(VisitExpressions(expr->arguments()));
9812
9813   if (function->IsConstant() &&
9814       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
9815     Handle<Object> constant = HConstant::cast(function)->handle(isolate());
9816     expr->SetKnownGlobalTarget(Handle<JSFunction>::cast(constant));
9817   }
9818
9819   if (FLAG_inline_construct &&
9820       expr->IsMonomorphic() &&
9821       IsAllocationInlineable(expr->target())) {
9822     Handle<JSFunction> constructor = expr->target();
9823     HValue* check = Add<HCheckValue>(function, constructor);
9824
9825     // Force completion of inobject slack tracking before generating
9826     // allocation code to finalize instance size.
9827     if (constructor->IsInobjectSlackTrackingInProgress()) {
9828       constructor->CompleteInobjectSlackTracking();
9829     }
9830
9831     // Calculate instance size from initial map of constructor.
9832     DCHECK(constructor->has_initial_map());
9833     Handle<Map> initial_map(constructor->initial_map());
9834     int instance_size = initial_map->instance_size();
9835
9836     // Allocate an instance of the implicit receiver object.
9837     HValue* size_in_bytes = Add<HConstant>(instance_size);
9838     HAllocationMode allocation_mode;
9839     if (FLAG_pretenuring_call_new) {
9840       if (FLAG_allocation_site_pretenuring) {
9841         // Try to use pretenuring feedback.
9842         Handle<AllocationSite> allocation_site = expr->allocation_site();
9843         allocation_mode = HAllocationMode(allocation_site);
9844         // Take a dependency on allocation site.
9845         top_info()->dependencies()->AssumeTenuringDecision(allocation_site);
9846       }
9847     }
9848
9849     HAllocate* receiver = BuildAllocate(
9850         size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode);
9851     receiver->set_known_initial_map(initial_map);
9852
9853     // Initialize map and fields of the newly allocated object.
9854     { NoObservableSideEffectsScope no_effects(this);
9855       DCHECK(initial_map->instance_type() == JS_OBJECT_TYPE);
9856       Add<HStoreNamedField>(receiver,
9857           HObjectAccess::ForMapAndOffset(initial_map, JSObject::kMapOffset),
9858           Add<HConstant>(initial_map));
9859       HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array());
9860       Add<HStoreNamedField>(receiver,
9861           HObjectAccess::ForMapAndOffset(initial_map,
9862                                          JSObject::kPropertiesOffset),
9863           empty_fixed_array);
9864       Add<HStoreNamedField>(receiver,
9865           HObjectAccess::ForMapAndOffset(initial_map,
9866                                          JSObject::kElementsOffset),
9867           empty_fixed_array);
9868       BuildInitializeInobjectProperties(receiver, initial_map);
9869     }
9870
9871     // Replace the constructor function with a newly allocated receiver using
9872     // the index of the receiver from the top of the expression stack.
9873     const int receiver_index = argument_count - 1;
9874     DCHECK(environment()->ExpressionStackAt(receiver_index) == function);
9875     environment()->SetExpressionStackAt(receiver_index, receiver);
9876
9877     if (TryInlineConstruct(expr, receiver)) {
9878       // Inlining worked, add a dependency on the initial map to make sure that
9879       // this code is deoptimized whenever the initial map of the constructor
9880       // changes.
9881       top_info()->dependencies()->AssumeInitialMapCantChange(initial_map);
9882       return;
9883     }
9884
9885     // TODO(mstarzinger): For now we remove the previous HAllocate and all
9886     // corresponding instructions and instead add HPushArguments for the
9887     // arguments in case inlining failed.  What we actually should do is for
9888     // inlining to try to build a subgraph without mutating the parent graph.
9889     HInstruction* instr = current_block()->last();
9890     do {
9891       HInstruction* prev_instr = instr->previous();
9892       instr->DeleteAndReplaceWith(NULL);
9893       instr = prev_instr;
9894     } while (instr != check);
9895     environment()->SetExpressionStackAt(receiver_index, function);
9896     HInstruction* call =
9897       PreProcessCall(New<HCallNew>(function, argument_count));
9898     return ast_context()->ReturnInstruction(call, expr->id());
9899   } else {
9900     // The constructor function is both an operand to the instruction and an
9901     // argument to the construct call.
9902     if (TryHandleArrayCallNew(expr, function)) return;
9903
9904     HInstruction* call =
9905         PreProcessCall(New<HCallNew>(function, argument_count));
9906     return ast_context()->ReturnInstruction(call, expr->id());
9907   }
9908 }
9909
9910
9911 void HOptimizedGraphBuilder::BuildInitializeInobjectProperties(
9912     HValue* receiver, Handle<Map> initial_map) {
9913   if (initial_map->GetInObjectProperties() != 0) {
9914     HConstant* undefined = graph()->GetConstantUndefined();
9915     for (int i = 0; i < initial_map->GetInObjectProperties(); i++) {
9916       int property_offset = initial_map->GetInObjectPropertyOffset(i);
9917       Add<HStoreNamedField>(receiver, HObjectAccess::ForMapAndOffset(
9918                                           initial_map, property_offset),
9919                             undefined);
9920     }
9921   }
9922 }
9923
9924
9925 HValue* HGraphBuilder::BuildAllocateEmptyArrayBuffer(HValue* byte_length) {
9926   // We HForceRepresentation here to avoid allocations during an *-to-tagged
9927   // HChange that could cause GC while the array buffer object is not fully
9928   // initialized.
9929   HObjectAccess byte_length_access(HObjectAccess::ForJSArrayBufferByteLength());
9930   byte_length = AddUncasted<HForceRepresentation>(
9931       byte_length, byte_length_access.representation());
9932   HAllocate* result =
9933       BuildAllocate(Add<HConstant>(JSArrayBuffer::kSizeWithInternalFields),
9934                     HType::JSObject(), JS_ARRAY_BUFFER_TYPE, HAllocationMode());
9935
9936   HValue* global_object = Add<HLoadNamedField>(
9937       context(), nullptr,
9938       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
9939   HValue* native_context = Add<HLoadNamedField>(
9940       global_object, nullptr, HObjectAccess::ForGlobalObjectNativeContext());
9941   Add<HStoreNamedField>(
9942       result, HObjectAccess::ForMap(),
9943       Add<HLoadNamedField>(
9944           native_context, nullptr,
9945           HObjectAccess::ForContextSlot(Context::ARRAY_BUFFER_MAP_INDEX)));
9946
9947   HConstant* empty_fixed_array =
9948       Add<HConstant>(isolate()->factory()->empty_fixed_array());
9949   Add<HStoreNamedField>(
9950       result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset),
9951       empty_fixed_array);
9952   Add<HStoreNamedField>(
9953       result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
9954       empty_fixed_array);
9955   Add<HStoreNamedField>(
9956       result, HObjectAccess::ForJSArrayBufferBackingStore().WithRepresentation(
9957                   Representation::Smi()),
9958       graph()->GetConstant0());
9959   Add<HStoreNamedField>(result, byte_length_access, byte_length);
9960   Add<HStoreNamedField>(result, HObjectAccess::ForJSArrayBufferBitFieldSlot(),
9961                         graph()->GetConstant0());
9962   Add<HStoreNamedField>(
9963       result, HObjectAccess::ForJSArrayBufferBitField(),
9964       Add<HConstant>((1 << JSArrayBuffer::IsExternal::kShift) |
9965                      (1 << JSArrayBuffer::IsNeuterable::kShift)));
9966
9967   for (int field = 0; field < v8::ArrayBuffer::kInternalFieldCount; ++field) {
9968     Add<HStoreNamedField>(
9969         result,
9970         HObjectAccess::ForObservableJSObjectOffset(
9971             JSArrayBuffer::kSize + field * kPointerSize, Representation::Smi()),
9972         graph()->GetConstant0());
9973   }
9974
9975   return result;
9976 }
9977
9978
9979 template <class ViewClass>
9980 void HGraphBuilder::BuildArrayBufferViewInitialization(
9981     HValue* obj,
9982     HValue* buffer,
9983     HValue* byte_offset,
9984     HValue* byte_length) {
9985
9986   for (int offset = ViewClass::kSize;
9987        offset < ViewClass::kSizeWithInternalFields;
9988        offset += kPointerSize) {
9989     Add<HStoreNamedField>(obj,
9990         HObjectAccess::ForObservableJSObjectOffset(offset),
9991         graph()->GetConstant0());
9992   }
9993
9994   Add<HStoreNamedField>(
9995       obj,
9996       HObjectAccess::ForJSArrayBufferViewByteOffset(),
9997       byte_offset);
9998   Add<HStoreNamedField>(
9999       obj,
10000       HObjectAccess::ForJSArrayBufferViewByteLength(),
10001       byte_length);
10002   Add<HStoreNamedField>(obj, HObjectAccess::ForJSArrayBufferViewBuffer(),
10003                         buffer);
10004 }
10005
10006
10007 void HOptimizedGraphBuilder::GenerateDataViewInitialize(
10008     CallRuntime* expr) {
10009   ZoneList<Expression*>* arguments = expr->arguments();
10010
10011   DCHECK(arguments->length()== 4);
10012   CHECK_ALIVE(VisitForValue(arguments->at(0)));
10013   HValue* obj = Pop();
10014
10015   CHECK_ALIVE(VisitForValue(arguments->at(1)));
10016   HValue* buffer = Pop();
10017
10018   CHECK_ALIVE(VisitForValue(arguments->at(2)));
10019   HValue* byte_offset = Pop();
10020
10021   CHECK_ALIVE(VisitForValue(arguments->at(3)));
10022   HValue* byte_length = Pop();
10023
10024   {
10025     NoObservableSideEffectsScope scope(this);
10026     BuildArrayBufferViewInitialization<JSDataView>(
10027         obj, buffer, byte_offset, byte_length);
10028   }
10029 }
10030
10031
10032 static Handle<Map> TypedArrayMap(Isolate* isolate,
10033                                  ExternalArrayType array_type,
10034                                  ElementsKind target_kind) {
10035   Handle<Context> native_context = isolate->native_context();
10036   Handle<JSFunction> fun;
10037   switch (array_type) {
10038 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
10039     case kExternal##Type##Array:                                              \
10040       fun = Handle<JSFunction>(native_context->type##_array_fun());           \
10041       break;
10042
10043     TYPED_ARRAYS(TYPED_ARRAY_CASE)
10044 #undef TYPED_ARRAY_CASE
10045   }
10046   Handle<Map> map(fun->initial_map());
10047   return Map::AsElementsKind(map, target_kind);
10048 }
10049
10050
10051 HValue* HOptimizedGraphBuilder::BuildAllocateExternalElements(
10052     ExternalArrayType array_type,
10053     bool is_zero_byte_offset,
10054     HValue* buffer, HValue* byte_offset, HValue* length) {
10055   Handle<Map> external_array_map(
10056       isolate()->heap()->MapForFixedTypedArray(array_type));
10057
10058   // The HForceRepresentation is to prevent possible deopt on int-smi
10059   // conversion after allocation but before the new object fields are set.
10060   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
10061   HValue* elements = Add<HAllocate>(
10062       Add<HConstant>(FixedTypedArrayBase::kHeaderSize), HType::HeapObject(),
10063       NOT_TENURED, external_array_map->instance_type());
10064
10065   AddStoreMapConstant(elements, external_array_map);
10066   Add<HStoreNamedField>(elements,
10067       HObjectAccess::ForFixedArrayLength(), length);
10068
10069   HValue* backing_store = Add<HLoadNamedField>(
10070       buffer, nullptr, HObjectAccess::ForJSArrayBufferBackingStore());
10071
10072   HValue* typed_array_start;
10073   if (is_zero_byte_offset) {
10074     typed_array_start = backing_store;
10075   } else {
10076     HInstruction* external_pointer =
10077         AddUncasted<HAdd>(backing_store, byte_offset);
10078     // Arguments are checked prior to call to TypedArrayInitialize,
10079     // including byte_offset.
10080     external_pointer->ClearFlag(HValue::kCanOverflow);
10081     typed_array_start = external_pointer;
10082   }
10083
10084   Add<HStoreNamedField>(elements,
10085                         HObjectAccess::ForFixedTypedArrayBaseBasePointer(),
10086                         graph()->GetConstant0());
10087   Add<HStoreNamedField>(elements,
10088                         HObjectAccess::ForFixedTypedArrayBaseExternalPointer(),
10089                         typed_array_start);
10090
10091   return elements;
10092 }
10093
10094
10095 HValue* HOptimizedGraphBuilder::BuildAllocateFixedTypedArray(
10096     ExternalArrayType array_type, size_t element_size,
10097     ElementsKind fixed_elements_kind, HValue* byte_length, HValue* length,
10098     bool initialize) {
10099   STATIC_ASSERT(
10100       (FixedTypedArrayBase::kHeaderSize & kObjectAlignmentMask) == 0);
10101   HValue* total_size;
10102
10103   // if fixed array's elements are not aligned to object's alignment,
10104   // we need to align the whole array to object alignment.
10105   if (element_size % kObjectAlignment != 0) {
10106     total_size = BuildObjectSizeAlignment(
10107         byte_length, FixedTypedArrayBase::kHeaderSize);
10108   } else {
10109     total_size = AddUncasted<HAdd>(byte_length,
10110         Add<HConstant>(FixedTypedArrayBase::kHeaderSize));
10111     total_size->ClearFlag(HValue::kCanOverflow);
10112   }
10113
10114   // The HForceRepresentation is to prevent possible deopt on int-smi
10115   // conversion after allocation but before the new object fields are set.
10116   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
10117   Handle<Map> fixed_typed_array_map(
10118       isolate()->heap()->MapForFixedTypedArray(array_type));
10119   HAllocate* elements =
10120       Add<HAllocate>(total_size, HType::HeapObject(), NOT_TENURED,
10121                      fixed_typed_array_map->instance_type());
10122
10123 #ifndef V8_HOST_ARCH_64_BIT
10124   if (array_type == kExternalFloat64Array) {
10125     elements->MakeDoubleAligned();
10126   }
10127 #endif
10128
10129   AddStoreMapConstant(elements, fixed_typed_array_map);
10130
10131   Add<HStoreNamedField>(elements,
10132       HObjectAccess::ForFixedArrayLength(),
10133       length);
10134   Add<HStoreNamedField>(
10135       elements, HObjectAccess::ForFixedTypedArrayBaseBasePointer(), elements);
10136
10137   Add<HStoreNamedField>(
10138       elements, HObjectAccess::ForFixedTypedArrayBaseExternalPointer(),
10139       Add<HConstant>(ExternalReference::fixed_typed_array_base_data_offset()));
10140
10141   HValue* filler = Add<HConstant>(static_cast<int32_t>(0));
10142
10143   if (initialize) {
10144     LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
10145
10146     HValue* backing_store = AddUncasted<HAdd>(
10147         Add<HConstant>(ExternalReference::fixed_typed_array_base_data_offset()),
10148         elements, Strength::WEAK, AddOfExternalAndTagged);
10149
10150     HValue* key = builder.BeginBody(
10151         Add<HConstant>(static_cast<int32_t>(0)),
10152         length, Token::LT);
10153     Add<HStoreKeyed>(backing_store, key, filler, fixed_elements_kind);
10154
10155     builder.EndBody();
10156   }
10157   return elements;
10158 }
10159
10160
10161 void HOptimizedGraphBuilder::GenerateTypedArrayInitialize(
10162     CallRuntime* expr) {
10163   ZoneList<Expression*>* arguments = expr->arguments();
10164
10165   static const int kObjectArg = 0;
10166   static const int kArrayIdArg = 1;
10167   static const int kBufferArg = 2;
10168   static const int kByteOffsetArg = 3;
10169   static const int kByteLengthArg = 4;
10170   static const int kInitializeArg = 5;
10171   static const int kArgsLength = 6;
10172   DCHECK(arguments->length() == kArgsLength);
10173
10174
10175   CHECK_ALIVE(VisitForValue(arguments->at(kObjectArg)));
10176   HValue* obj = Pop();
10177
10178   if (!arguments->at(kArrayIdArg)->IsLiteral()) {
10179     // This should never happen in real use, but can happen when fuzzing.
10180     // Just bail out.
10181     Bailout(kNeedSmiLiteral);
10182     return;
10183   }
10184   Handle<Object> value =
10185       static_cast<Literal*>(arguments->at(kArrayIdArg))->value();
10186   if (!value->IsSmi()) {
10187     // This should never happen in real use, but can happen when fuzzing.
10188     // Just bail out.
10189     Bailout(kNeedSmiLiteral);
10190     return;
10191   }
10192   int array_id = Smi::cast(*value)->value();
10193
10194   HValue* buffer;
10195   if (!arguments->at(kBufferArg)->IsNullLiteral()) {
10196     CHECK_ALIVE(VisitForValue(arguments->at(kBufferArg)));
10197     buffer = Pop();
10198   } else {
10199     buffer = NULL;
10200   }
10201
10202   HValue* byte_offset;
10203   bool is_zero_byte_offset;
10204
10205   if (arguments->at(kByteOffsetArg)->IsLiteral()
10206       && Smi::FromInt(0) ==
10207       *static_cast<Literal*>(arguments->at(kByteOffsetArg))->value()) {
10208     byte_offset = Add<HConstant>(static_cast<int32_t>(0));
10209     is_zero_byte_offset = true;
10210   } else {
10211     CHECK_ALIVE(VisitForValue(arguments->at(kByteOffsetArg)));
10212     byte_offset = Pop();
10213     is_zero_byte_offset = false;
10214     DCHECK(buffer != NULL);
10215   }
10216
10217   CHECK_ALIVE(VisitForValue(arguments->at(kByteLengthArg)));
10218   HValue* byte_length = Pop();
10219
10220   CHECK(arguments->at(kInitializeArg)->IsLiteral());
10221   bool initialize = static_cast<Literal*>(arguments->at(kInitializeArg))
10222                         ->value()
10223                         ->BooleanValue();
10224
10225   NoObservableSideEffectsScope scope(this);
10226   IfBuilder byte_offset_smi(this);
10227
10228   if (!is_zero_byte_offset) {
10229     byte_offset_smi.If<HIsSmiAndBranch>(byte_offset);
10230     byte_offset_smi.Then();
10231   }
10232
10233   ExternalArrayType array_type =
10234       kExternalInt8Array;  // Bogus initialization.
10235   size_t element_size = 1;  // Bogus initialization.
10236   ElementsKind fixed_elements_kind =  // Bogus initialization.
10237       INT8_ELEMENTS;
10238   Runtime::ArrayIdToTypeAndSize(array_id,
10239       &array_type,
10240       &fixed_elements_kind,
10241       &element_size);
10242
10243
10244   { //  byte_offset is Smi.
10245     HValue* allocated_buffer = buffer;
10246     if (buffer == NULL) {
10247       allocated_buffer = BuildAllocateEmptyArrayBuffer(byte_length);
10248     }
10249     BuildArrayBufferViewInitialization<JSTypedArray>(obj, allocated_buffer,
10250                                                      byte_offset, byte_length);
10251
10252
10253     HInstruction* length = AddUncasted<HDiv>(byte_length,
10254         Add<HConstant>(static_cast<int32_t>(element_size)));
10255
10256     Add<HStoreNamedField>(obj,
10257         HObjectAccess::ForJSTypedArrayLength(),
10258         length);
10259
10260     HValue* elements;
10261     if (buffer != NULL) {
10262       elements = BuildAllocateExternalElements(
10263           array_type, is_zero_byte_offset, buffer, byte_offset, length);
10264       Handle<Map> obj_map =
10265           TypedArrayMap(isolate(), array_type, fixed_elements_kind);
10266       AddStoreMapConstant(obj, obj_map);
10267     } else {
10268       DCHECK(is_zero_byte_offset);
10269       elements = BuildAllocateFixedTypedArray(array_type, element_size,
10270                                               fixed_elements_kind, byte_length,
10271                                               length, initialize);
10272     }
10273     Add<HStoreNamedField>(
10274         obj, HObjectAccess::ForElementsPointer(), elements);
10275   }
10276
10277   if (!is_zero_byte_offset) {
10278     byte_offset_smi.Else();
10279     { //  byte_offset is not Smi.
10280       Push(obj);
10281       CHECK_ALIVE(VisitForValue(arguments->at(kArrayIdArg)));
10282       Push(buffer);
10283       Push(byte_offset);
10284       Push(byte_length);
10285       CHECK_ALIVE(VisitForValue(arguments->at(kInitializeArg)));
10286       PushArgumentsFromEnvironment(kArgsLength);
10287       Add<HCallRuntime>(expr->name(), expr->function(), kArgsLength);
10288     }
10289   }
10290   byte_offset_smi.End();
10291 }
10292
10293
10294 void HOptimizedGraphBuilder::GenerateMaxSmi(CallRuntime* expr) {
10295   DCHECK(expr->arguments()->length() == 0);
10296   HConstant* max_smi = New<HConstant>(static_cast<int32_t>(Smi::kMaxValue));
10297   return ast_context()->ReturnInstruction(max_smi, expr->id());
10298 }
10299
10300
10301 void HOptimizedGraphBuilder::GenerateTypedArrayMaxSizeInHeap(
10302     CallRuntime* expr) {
10303   DCHECK(expr->arguments()->length() == 0);
10304   HConstant* result = New<HConstant>(static_cast<int32_t>(
10305         FLAG_typed_array_max_size_in_heap));
10306   return ast_context()->ReturnInstruction(result, expr->id());
10307 }
10308
10309
10310 void HOptimizedGraphBuilder::GenerateArrayBufferGetByteLength(
10311     CallRuntime* expr) {
10312   DCHECK(expr->arguments()->length() == 1);
10313   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
10314   HValue* buffer = Pop();
10315   HInstruction* result = New<HLoadNamedField>(
10316       buffer, nullptr, HObjectAccess::ForJSArrayBufferByteLength());
10317   return ast_context()->ReturnInstruction(result, expr->id());
10318 }
10319
10320
10321 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength(
10322     CallRuntime* expr) {
10323   NoObservableSideEffectsScope scope(this);
10324   DCHECK(expr->arguments()->length() == 1);
10325   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
10326   HValue* view = Pop();
10327
10328   return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
10329       view, nullptr,
10330       FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteLengthOffset)));
10331 }
10332
10333
10334 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset(
10335     CallRuntime* expr) {
10336   NoObservableSideEffectsScope scope(this);
10337   DCHECK(expr->arguments()->length() == 1);
10338   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
10339   HValue* view = Pop();
10340
10341   return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
10342       view, nullptr,
10343       FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteOffsetOffset)));
10344 }
10345
10346
10347 void HOptimizedGraphBuilder::GenerateTypedArrayGetLength(
10348     CallRuntime* expr) {
10349   NoObservableSideEffectsScope scope(this);
10350   DCHECK(expr->arguments()->length() == 1);
10351   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
10352   HValue* view = Pop();
10353
10354   return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
10355       view, nullptr,
10356       FieldIndex::ForInObjectOffset(JSTypedArray::kLengthOffset)));
10357 }
10358
10359
10360 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
10361   DCHECK(!HasStackOverflow());
10362   DCHECK(current_block() != NULL);
10363   DCHECK(current_block()->HasPredecessor());
10364   if (expr->is_jsruntime()) {
10365     return Bailout(kCallToAJavaScriptRuntimeFunction);
10366   }
10367
10368   const Runtime::Function* function = expr->function();
10369   DCHECK(function != NULL);
10370   switch (function->function_id) {
10371 #define CALL_INTRINSIC_GENERATOR(Name) \
10372   case Runtime::kInline##Name:         \
10373     return Generate##Name(expr);
10374
10375     FOR_EACH_HYDROGEN_INTRINSIC(CALL_INTRINSIC_GENERATOR)
10376 #undef CALL_INTRINSIC_GENERATOR
10377     default: {
10378       Handle<String> name = expr->name();
10379       int argument_count = expr->arguments()->length();
10380       CHECK_ALIVE(VisitExpressions(expr->arguments()));
10381       PushArgumentsFromEnvironment(argument_count);
10382       HCallRuntime* call = New<HCallRuntime>(name, function, argument_count);
10383       return ast_context()->ReturnInstruction(call, expr->id());
10384     }
10385   }
10386 }
10387
10388
10389 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
10390   DCHECK(!HasStackOverflow());
10391   DCHECK(current_block() != NULL);
10392   DCHECK(current_block()->HasPredecessor());
10393   switch (expr->op()) {
10394     case Token::DELETE: return VisitDelete(expr);
10395     case Token::VOID: return VisitVoid(expr);
10396     case Token::TYPEOF: return VisitTypeof(expr);
10397     case Token::NOT: return VisitNot(expr);
10398     default: UNREACHABLE();
10399   }
10400 }
10401
10402
10403 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
10404   Property* prop = expr->expression()->AsProperty();
10405   VariableProxy* proxy = expr->expression()->AsVariableProxy();
10406   if (prop != NULL) {
10407     CHECK_ALIVE(VisitForValue(prop->obj()));
10408     CHECK_ALIVE(VisitForValue(prop->key()));
10409     HValue* key = Pop();
10410     HValue* obj = Pop();
10411     Add<HPushArguments>(obj, key);
10412     HInstruction* instr = New<HCallRuntime>(
10413         isolate()->factory()->empty_string(),
10414         Runtime::FunctionForId(is_strict(function_language_mode())
10415                                    ? Runtime::kDeleteProperty_Strict
10416                                    : Runtime::kDeleteProperty_Sloppy),
10417         2);
10418     return ast_context()->ReturnInstruction(instr, expr->id());
10419   } else if (proxy != NULL) {
10420     Variable* var = proxy->var();
10421     if (var->IsUnallocatedOrGlobalSlot()) {
10422       Bailout(kDeleteWithGlobalVariable);
10423     } else if (var->IsStackAllocated() || var->IsContextSlot()) {
10424       // Result of deleting non-global variables is false.  'this' is not really
10425       // a variable, though we implement it as one.  The subexpression does not
10426       // have side effects.
10427       HValue* value = var->HasThisName(isolate()) ? graph()->GetConstantTrue()
10428                                                   : graph()->GetConstantFalse();
10429       return ast_context()->ReturnValue(value);
10430     } else {
10431       Bailout(kDeleteWithNonGlobalVariable);
10432     }
10433   } else {
10434     // Result of deleting non-property, non-variable reference is true.
10435     // Evaluate the subexpression for side effects.
10436     CHECK_ALIVE(VisitForEffect(expr->expression()));
10437     return ast_context()->ReturnValue(graph()->GetConstantTrue());
10438   }
10439 }
10440
10441
10442 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) {
10443   CHECK_ALIVE(VisitForEffect(expr->expression()));
10444   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
10445 }
10446
10447
10448 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
10449   CHECK_ALIVE(VisitForTypeOf(expr->expression()));
10450   HValue* value = Pop();
10451   HInstruction* instr = New<HTypeof>(value);
10452   return ast_context()->ReturnInstruction(instr, expr->id());
10453 }
10454
10455
10456 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) {
10457   if (ast_context()->IsTest()) {
10458     TestContext* context = TestContext::cast(ast_context());
10459     VisitForControl(expr->expression(),
10460                     context->if_false(),
10461                     context->if_true());
10462     return;
10463   }
10464
10465   if (ast_context()->IsEffect()) {
10466     VisitForEffect(expr->expression());
10467     return;
10468   }
10469
10470   DCHECK(ast_context()->IsValue());
10471   HBasicBlock* materialize_false = graph()->CreateBasicBlock();
10472   HBasicBlock* materialize_true = graph()->CreateBasicBlock();
10473   CHECK_BAILOUT(VisitForControl(expr->expression(),
10474                                 materialize_false,
10475                                 materialize_true));
10476
10477   if (materialize_false->HasPredecessor()) {
10478     materialize_false->SetJoinId(expr->MaterializeFalseId());
10479     set_current_block(materialize_false);
10480     Push(graph()->GetConstantFalse());
10481   } else {
10482     materialize_false = NULL;
10483   }
10484
10485   if (materialize_true->HasPredecessor()) {
10486     materialize_true->SetJoinId(expr->MaterializeTrueId());
10487     set_current_block(materialize_true);
10488     Push(graph()->GetConstantTrue());
10489   } else {
10490     materialize_true = NULL;
10491   }
10492
10493   HBasicBlock* join =
10494     CreateJoin(materialize_false, materialize_true, expr->id());
10495   set_current_block(join);
10496   if (join != NULL) return ast_context()->ReturnValue(Pop());
10497 }
10498
10499
10500 static Representation RepresentationFor(Type* type) {
10501   DisallowHeapAllocation no_allocation;
10502   if (type->Is(Type::None())) return Representation::None();
10503   if (type->Is(Type::SignedSmall())) return Representation::Smi();
10504   if (type->Is(Type::Signed32())) return Representation::Integer32();
10505   if (type->Is(Type::Number())) return Representation::Double();
10506   return Representation::Tagged();
10507 }
10508
10509
10510 HInstruction* HOptimizedGraphBuilder::BuildIncrement(
10511     bool returns_original_input,
10512     CountOperation* expr) {
10513   // The input to the count operation is on top of the expression stack.
10514   Representation rep = RepresentationFor(expr->type());
10515   if (rep.IsNone() || rep.IsTagged()) {
10516     rep = Representation::Smi();
10517   }
10518
10519   if (returns_original_input && !is_strong(function_language_mode())) {
10520     // We need an explicit HValue representing ToNumber(input).  The
10521     // actual HChange instruction we need is (sometimes) added in a later
10522     // phase, so it is not available now to be used as an input to HAdd and
10523     // as the return value.
10524     HInstruction* number_input = AddUncasted<HForceRepresentation>(Pop(), rep);
10525     if (!rep.IsDouble()) {
10526       number_input->SetFlag(HInstruction::kFlexibleRepresentation);
10527       number_input->SetFlag(HInstruction::kCannotBeTagged);
10528     }
10529     Push(number_input);
10530   }
10531
10532   // The addition has no side effects, so we do not need
10533   // to simulate the expression stack after this instruction.
10534   // Any later failures deopt to the load of the input or earlier.
10535   HConstant* delta = (expr->op() == Token::INC)
10536       ? graph()->GetConstant1()
10537       : graph()->GetConstantMinus1();
10538   HInstruction* instr =
10539       AddUncasted<HAdd>(Top(), delta, strength(function_language_mode()));
10540   if (instr->IsAdd()) {
10541     HAdd* add = HAdd::cast(instr);
10542     add->set_observed_input_representation(1, rep);
10543     add->set_observed_input_representation(2, Representation::Smi());
10544   }
10545   if (!is_strong(function_language_mode())) {
10546     instr->ClearAllSideEffects();
10547   } else {
10548     Add<HSimulate>(expr->ToNumberId(), REMOVABLE_SIMULATE);
10549   }
10550   instr->SetFlag(HInstruction::kCannotBeTagged);
10551   return instr;
10552 }
10553
10554
10555 void HOptimizedGraphBuilder::BuildStoreForEffect(
10556     Expression* expr, Property* prop, FeedbackVectorICSlot slot,
10557     BailoutId ast_id, BailoutId return_id, HValue* object, HValue* key,
10558     HValue* value) {
10559   EffectContext for_effect(this);
10560   Push(object);
10561   if (key != NULL) Push(key);
10562   Push(value);
10563   BuildStore(expr, prop, slot, ast_id, return_id);
10564 }
10565
10566
10567 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
10568   DCHECK(!HasStackOverflow());
10569   DCHECK(current_block() != NULL);
10570   DCHECK(current_block()->HasPredecessor());
10571   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
10572   Expression* target = expr->expression();
10573   VariableProxy* proxy = target->AsVariableProxy();
10574   Property* prop = target->AsProperty();
10575   if (proxy == NULL && prop == NULL) {
10576     return Bailout(kInvalidLhsInCountOperation);
10577   }
10578
10579   // Match the full code generator stack by simulating an extra stack
10580   // element for postfix operations in a non-effect context.  The return
10581   // value is ToNumber(input).
10582   bool returns_original_input =
10583       expr->is_postfix() && !ast_context()->IsEffect();
10584   HValue* input = NULL;  // ToNumber(original_input).
10585   HValue* after = NULL;  // The result after incrementing or decrementing.
10586
10587   if (proxy != NULL) {
10588     Variable* var = proxy->var();
10589     if (var->mode() == CONST_LEGACY)  {
10590       return Bailout(kUnsupportedCountOperationWithConst);
10591     }
10592     if (var->mode() == CONST) {
10593       return Bailout(kNonInitializerAssignmentToConst);
10594     }
10595     // Argument of the count operation is a variable, not a property.
10596     DCHECK(prop == NULL);
10597     CHECK_ALIVE(VisitForValue(target));
10598
10599     after = BuildIncrement(returns_original_input, expr);
10600     input = returns_original_input ? Top() : Pop();
10601     Push(after);
10602
10603     switch (var->location()) {
10604       case VariableLocation::GLOBAL:
10605       case VariableLocation::UNALLOCATED:
10606         HandleGlobalVariableAssignment(var, after, expr->CountSlot(),
10607                                        expr->AssignmentId());
10608         break;
10609
10610       case VariableLocation::PARAMETER:
10611       case VariableLocation::LOCAL:
10612         BindIfLive(var, after);
10613         break;
10614
10615       case VariableLocation::CONTEXT: {
10616         // Bail out if we try to mutate a parameter value in a function
10617         // using the arguments object.  We do not (yet) correctly handle the
10618         // arguments property of the function.
10619         if (current_info()->scope()->arguments() != NULL) {
10620           // Parameters will rewrite to context slots.  We have no direct
10621           // way to detect that the variable is a parameter so we use a
10622           // linear search of the parameter list.
10623           int count = current_info()->scope()->num_parameters();
10624           for (int i = 0; i < count; ++i) {
10625             if (var == current_info()->scope()->parameter(i)) {
10626               return Bailout(kAssignmentToParameterInArgumentsObject);
10627             }
10628           }
10629         }
10630
10631         HValue* context = BuildContextChainWalk(var);
10632         HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode())
10633             ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck;
10634         HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
10635                                                           mode, after);
10636         if (instr->HasObservableSideEffects()) {
10637           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
10638         }
10639         break;
10640       }
10641
10642       case VariableLocation::LOOKUP:
10643         return Bailout(kLookupVariableInCountOperation);
10644     }
10645
10646     Drop(returns_original_input ? 2 : 1);
10647     return ast_context()->ReturnValue(expr->is_postfix() ? input : after);
10648   }
10649
10650   // Argument of the count operation is a property.
10651   DCHECK(prop != NULL);
10652   if (returns_original_input) Push(graph()->GetConstantUndefined());
10653
10654   CHECK_ALIVE(VisitForValue(prop->obj()));
10655   HValue* object = Top();
10656
10657   HValue* key = NULL;
10658   if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
10659     CHECK_ALIVE(VisitForValue(prop->key()));
10660     key = Top();
10661   }
10662
10663   CHECK_ALIVE(PushLoad(prop, object, key));
10664
10665   after = BuildIncrement(returns_original_input, expr);
10666
10667   if (returns_original_input) {
10668     input = Pop();
10669     // Drop object and key to push it again in the effect context below.
10670     Drop(key == NULL ? 1 : 2);
10671     environment()->SetExpressionStackAt(0, input);
10672     CHECK_ALIVE(BuildStoreForEffect(expr, prop, expr->CountSlot(), expr->id(),
10673                                     expr->AssignmentId(), object, key, after));
10674     return ast_context()->ReturnValue(Pop());
10675   }
10676
10677   environment()->SetExpressionStackAt(0, after);
10678   return BuildStore(expr, prop, expr->CountSlot(), expr->id(),
10679                     expr->AssignmentId());
10680 }
10681
10682
10683 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt(
10684     HValue* string,
10685     HValue* index) {
10686   if (string->IsConstant() && index->IsConstant()) {
10687     HConstant* c_string = HConstant::cast(string);
10688     HConstant* c_index = HConstant::cast(index);
10689     if (c_string->HasStringValue() && c_index->HasNumberValue()) {
10690       int32_t i = c_index->NumberValueAsInteger32();
10691       Handle<String> s = c_string->StringValue();
10692       if (i < 0 || i >= s->length()) {
10693         return New<HConstant>(std::numeric_limits<double>::quiet_NaN());
10694       }
10695       return New<HConstant>(s->Get(i));
10696     }
10697   }
10698   string = BuildCheckString(string);
10699   index = Add<HBoundsCheck>(index, AddLoadStringLength(string));
10700   return New<HStringCharCodeAt>(string, index);
10701 }
10702
10703
10704 // Checks if the given shift amounts have following forms:
10705 // (N1) and (N2) with N1 + N2 = 32; (sa) and (32 - sa).
10706 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa,
10707                                              HValue* const32_minus_sa) {
10708   if (sa->IsConstant() && const32_minus_sa->IsConstant()) {
10709     const HConstant* c1 = HConstant::cast(sa);
10710     const HConstant* c2 = HConstant::cast(const32_minus_sa);
10711     return c1->HasInteger32Value() && c2->HasInteger32Value() &&
10712         (c1->Integer32Value() + c2->Integer32Value() == 32);
10713   }
10714   if (!const32_minus_sa->IsSub()) return false;
10715   HSub* sub = HSub::cast(const32_minus_sa);
10716   return sub->left()->EqualsInteger32Constant(32) && sub->right() == sa;
10717 }
10718
10719
10720 // Checks if the left and the right are shift instructions with the oposite
10721 // directions that can be replaced by one rotate right instruction or not.
10722 // Returns the operand and the shift amount for the rotate instruction in the
10723 // former case.
10724 bool HGraphBuilder::MatchRotateRight(HValue* left,
10725                                      HValue* right,
10726                                      HValue** operand,
10727                                      HValue** shift_amount) {
10728   HShl* shl;
10729   HShr* shr;
10730   if (left->IsShl() && right->IsShr()) {
10731     shl = HShl::cast(left);
10732     shr = HShr::cast(right);
10733   } else if (left->IsShr() && right->IsShl()) {
10734     shl = HShl::cast(right);
10735     shr = HShr::cast(left);
10736   } else {
10737     return false;
10738   }
10739   if (shl->left() != shr->left()) return false;
10740
10741   if (!ShiftAmountsAllowReplaceByRotate(shl->right(), shr->right()) &&
10742       !ShiftAmountsAllowReplaceByRotate(shr->right(), shl->right())) {
10743     return false;
10744   }
10745   *operand = shr->left();
10746   *shift_amount = shr->right();
10747   return true;
10748 }
10749
10750
10751 bool CanBeZero(HValue* right) {
10752   if (right->IsConstant()) {
10753     HConstant* right_const = HConstant::cast(right);
10754     if (right_const->HasInteger32Value() &&
10755        (right_const->Integer32Value() & 0x1f) != 0) {
10756       return false;
10757     }
10758   }
10759   return true;
10760 }
10761
10762
10763 HValue* HGraphBuilder::EnforceNumberType(HValue* number,
10764                                          Type* expected) {
10765   if (expected->Is(Type::SignedSmall())) {
10766     return AddUncasted<HForceRepresentation>(number, Representation::Smi());
10767   }
10768   if (expected->Is(Type::Signed32())) {
10769     return AddUncasted<HForceRepresentation>(number,
10770                                              Representation::Integer32());
10771   }
10772   return number;
10773 }
10774
10775
10776 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Type** expected) {
10777   if (value->IsConstant()) {
10778     HConstant* constant = HConstant::cast(value);
10779     Maybe<HConstant*> number =
10780         constant->CopyToTruncatedNumber(isolate(), zone());
10781     if (number.IsJust()) {
10782       *expected = Type::Number(zone());
10783       return AddInstruction(number.FromJust());
10784     }
10785   }
10786
10787   // We put temporary values on the stack, which don't correspond to anything
10788   // in baseline code. Since nothing is observable we avoid recording those
10789   // pushes with a NoObservableSideEffectsScope.
10790   NoObservableSideEffectsScope no_effects(this);
10791
10792   Type* expected_type = *expected;
10793
10794   // Separate the number type from the rest.
10795   Type* expected_obj =
10796       Type::Intersect(expected_type, Type::NonNumber(zone()), zone());
10797   Type* expected_number =
10798       Type::Intersect(expected_type, Type::Number(zone()), zone());
10799
10800   // We expect to get a number.
10801   // (We need to check first, since Type::None->Is(Type::Any()) == true.
10802   if (expected_obj->Is(Type::None())) {
10803     DCHECK(!expected_number->Is(Type::None(zone())));
10804     return value;
10805   }
10806
10807   if (expected_obj->Is(Type::Undefined(zone()))) {
10808     // This is already done by HChange.
10809     *expected = Type::Union(expected_number, Type::Number(zone()), zone());
10810     return value;
10811   }
10812
10813   return value;
10814 }
10815
10816
10817 HValue* HOptimizedGraphBuilder::BuildBinaryOperation(
10818     BinaryOperation* expr,
10819     HValue* left,
10820     HValue* right,
10821     PushBeforeSimulateBehavior push_sim_result) {
10822   Type* left_type = expr->left()->bounds().lower;
10823   Type* right_type = expr->right()->bounds().lower;
10824   Type* result_type = expr->bounds().lower;
10825   Maybe<int> fixed_right_arg = expr->fixed_right_arg();
10826   Handle<AllocationSite> allocation_site = expr->allocation_site();
10827
10828   HAllocationMode allocation_mode;
10829   if (FLAG_allocation_site_pretenuring && !allocation_site.is_null()) {
10830     allocation_mode = HAllocationMode(allocation_site);
10831   }
10832   HValue* result = HGraphBuilder::BuildBinaryOperation(
10833       expr->op(), left, right, left_type, right_type, result_type,
10834       fixed_right_arg, allocation_mode, strength(function_language_mode()),
10835       expr->id());
10836   // Add a simulate after instructions with observable side effects, and
10837   // after phis, which are the result of BuildBinaryOperation when we
10838   // inlined some complex subgraph.
10839   if (result->HasObservableSideEffects() || result->IsPhi()) {
10840     if (push_sim_result == PUSH_BEFORE_SIMULATE) {
10841       Push(result);
10842       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
10843       Drop(1);
10844     } else {
10845       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
10846     }
10847   }
10848   return result;
10849 }
10850
10851
10852 HValue* HGraphBuilder::BuildBinaryOperation(
10853     Token::Value op, HValue* left, HValue* right, Type* left_type,
10854     Type* right_type, Type* result_type, Maybe<int> fixed_right_arg,
10855     HAllocationMode allocation_mode, Strength strength, BailoutId opt_id) {
10856   bool maybe_string_add = false;
10857   if (op == Token::ADD) {
10858     // If we are adding constant string with something for which we don't have
10859     // a feedback yet, assume that it's also going to be a string and don't
10860     // generate deopt instructions.
10861     if (!left_type->IsInhabited() && right->IsConstant() &&
10862         HConstant::cast(right)->HasStringValue()) {
10863       left_type = Type::String();
10864     }
10865
10866     if (!right_type->IsInhabited() && left->IsConstant() &&
10867         HConstant::cast(left)->HasStringValue()) {
10868       right_type = Type::String();
10869     }
10870
10871     maybe_string_add = (left_type->Maybe(Type::String()) ||
10872                         left_type->Maybe(Type::Receiver()) ||
10873                         right_type->Maybe(Type::String()) ||
10874                         right_type->Maybe(Type::Receiver()));
10875   }
10876
10877   Representation left_rep = RepresentationFor(left_type);
10878   Representation right_rep = RepresentationFor(right_type);
10879
10880   if (!left_type->IsInhabited()) {
10881     Add<HDeoptimize>(
10882         Deoptimizer::kInsufficientTypeFeedbackForLHSOfBinaryOperation,
10883         Deoptimizer::SOFT);
10884     left_type = Type::Any(zone());
10885     left_rep = RepresentationFor(left_type);
10886     maybe_string_add = op == Token::ADD;
10887   }
10888
10889   if (!right_type->IsInhabited()) {
10890     Add<HDeoptimize>(
10891         Deoptimizer::kInsufficientTypeFeedbackForRHSOfBinaryOperation,
10892         Deoptimizer::SOFT);
10893     right_type = Type::Any(zone());
10894     right_rep = RepresentationFor(right_type);
10895     maybe_string_add = op == Token::ADD;
10896   }
10897
10898   if (!maybe_string_add && !is_strong(strength)) {
10899     left = TruncateToNumber(left, &left_type);
10900     right = TruncateToNumber(right, &right_type);
10901   }
10902
10903   // Special case for string addition here.
10904   if (op == Token::ADD &&
10905       (left_type->Is(Type::String()) || right_type->Is(Type::String()))) {
10906     if (is_strong(strength)) {
10907       // In strong mode, if the one side of an addition is a string,
10908       // the other side must be a string too.
10909       left = BuildCheckString(left);
10910       right = BuildCheckString(right);
10911     } else {
10912       // Validate type feedback for left argument.
10913       if (left_type->Is(Type::String())) {
10914         left = BuildCheckString(left);
10915       }
10916
10917       // Validate type feedback for right argument.
10918       if (right_type->Is(Type::String())) {
10919         right = BuildCheckString(right);
10920       }
10921
10922       // Convert left argument as necessary.
10923       if (left_type->Is(Type::Number())) {
10924         DCHECK(right_type->Is(Type::String()));
10925         left = BuildNumberToString(left, left_type);
10926       } else if (!left_type->Is(Type::String())) {
10927         DCHECK(right_type->Is(Type::String()));
10928         HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_RIGHT);
10929         Add<HPushArguments>(left, right);
10930         return AddUncasted<HInvokeFunction>(function, 2);
10931       }
10932
10933       // Convert right argument as necessary.
10934       if (right_type->Is(Type::Number())) {
10935         DCHECK(left_type->Is(Type::String()));
10936         right = BuildNumberToString(right, right_type);
10937       } else if (!right_type->Is(Type::String())) {
10938         DCHECK(left_type->Is(Type::String()));
10939         HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT);
10940         Add<HPushArguments>(left, right);
10941         return AddUncasted<HInvokeFunction>(function, 2);
10942       }
10943     }
10944
10945     // Fast paths for empty constant strings.
10946     Handle<String> left_string =
10947         left->IsConstant() && HConstant::cast(left)->HasStringValue()
10948             ? HConstant::cast(left)->StringValue()
10949             : Handle<String>();
10950     Handle<String> right_string =
10951         right->IsConstant() && HConstant::cast(right)->HasStringValue()
10952             ? HConstant::cast(right)->StringValue()
10953             : Handle<String>();
10954     if (!left_string.is_null() && left_string->length() == 0) return right;
10955     if (!right_string.is_null() && right_string->length() == 0) return left;
10956     if (!left_string.is_null() && !right_string.is_null()) {
10957       return AddUncasted<HStringAdd>(
10958           left, right, strength, allocation_mode.GetPretenureMode(),
10959           STRING_ADD_CHECK_NONE, allocation_mode.feedback_site());
10960     }
10961
10962     // Register the dependent code with the allocation site.
10963     if (!allocation_mode.feedback_site().is_null()) {
10964       DCHECK(!graph()->info()->IsStub());
10965       Handle<AllocationSite> site(allocation_mode.feedback_site());
10966       top_info()->dependencies()->AssumeTenuringDecision(site);
10967     }
10968
10969     // Inline the string addition into the stub when creating allocation
10970     // mementos to gather allocation site feedback, or if we can statically
10971     // infer that we're going to create a cons string.
10972     if ((graph()->info()->IsStub() &&
10973          allocation_mode.CreateAllocationMementos()) ||
10974         (left->IsConstant() &&
10975          HConstant::cast(left)->HasStringValue() &&
10976          HConstant::cast(left)->StringValue()->length() + 1 >=
10977            ConsString::kMinLength) ||
10978         (right->IsConstant() &&
10979          HConstant::cast(right)->HasStringValue() &&
10980          HConstant::cast(right)->StringValue()->length() + 1 >=
10981            ConsString::kMinLength)) {
10982       return BuildStringAdd(left, right, allocation_mode);
10983     }
10984
10985     // Fallback to using the string add stub.
10986     return AddUncasted<HStringAdd>(
10987         left, right, strength, allocation_mode.GetPretenureMode(),
10988         STRING_ADD_CHECK_NONE, allocation_mode.feedback_site());
10989   }
10990
10991   if (graph()->info()->IsStub()) {
10992     left = EnforceNumberType(left, left_type);
10993     right = EnforceNumberType(right, right_type);
10994   }
10995
10996   Representation result_rep = RepresentationFor(result_type);
10997
10998   bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) ||
10999                           (right_rep.IsTagged() && !right_rep.IsSmi());
11000
11001   HInstruction* instr = NULL;
11002   // Only the stub is allowed to call into the runtime, since otherwise we would
11003   // inline several instructions (including the two pushes) for every tagged
11004   // operation in optimized code, which is more expensive, than a stub call.
11005   if (graph()->info()->IsStub() && is_non_primitive) {
11006     HValue* function =
11007         AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op, strength));
11008     Add<HPushArguments>(left, right);
11009     instr = AddUncasted<HInvokeFunction>(function, 2);
11010   } else {
11011     if (is_strong(strength) && Token::IsBitOp(op)) {
11012       // TODO(conradw): This is not efficient, but is necessary to prevent
11013       // conversion of oddball values to numbers in strong mode. It would be
11014       // better to prevent the conversion rather than adding a runtime check.
11015       IfBuilder if_builder(this);
11016       if_builder.If<HHasInstanceTypeAndBranch>(left, ODDBALL_TYPE);
11017       if_builder.OrIf<HHasInstanceTypeAndBranch>(right, ODDBALL_TYPE);
11018       if_builder.Then();
11019       Add<HCallRuntime>(
11020           isolate()->factory()->empty_string(),
11021           Runtime::FunctionForId(Runtime::kThrowStrongModeImplicitConversion),
11022           0);
11023       if (!graph()->info()->IsStub()) {
11024         Add<HSimulate>(opt_id, REMOVABLE_SIMULATE);
11025       }
11026       if_builder.End();
11027     }
11028     switch (op) {
11029       case Token::ADD:
11030         instr = AddUncasted<HAdd>(left, right, strength);
11031         break;
11032       case Token::SUB:
11033         instr = AddUncasted<HSub>(left, right, strength);
11034         break;
11035       case Token::MUL:
11036         instr = AddUncasted<HMul>(left, right, strength);
11037         break;
11038       case Token::MOD: {
11039         if (fixed_right_arg.IsJust() &&
11040             !right->EqualsInteger32Constant(fixed_right_arg.FromJust())) {
11041           HConstant* fixed_right =
11042               Add<HConstant>(static_cast<int>(fixed_right_arg.FromJust()));
11043           IfBuilder if_same(this);
11044           if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ);
11045           if_same.Then();
11046           if_same.ElseDeopt(Deoptimizer::kUnexpectedRHSOfBinaryOperation);
11047           right = fixed_right;
11048         }
11049         instr = AddUncasted<HMod>(left, right, strength);
11050         break;
11051       }
11052       case Token::DIV:
11053         instr = AddUncasted<HDiv>(left, right, strength);
11054         break;
11055       case Token::BIT_XOR:
11056       case Token::BIT_AND:
11057         instr = AddUncasted<HBitwise>(op, left, right, strength);
11058         break;
11059       case Token::BIT_OR: {
11060         HValue* operand, *shift_amount;
11061         if (left_type->Is(Type::Signed32()) &&
11062             right_type->Is(Type::Signed32()) &&
11063             MatchRotateRight(left, right, &operand, &shift_amount)) {
11064           instr = AddUncasted<HRor>(operand, shift_amount, strength);
11065         } else {
11066           instr = AddUncasted<HBitwise>(op, left, right, strength);
11067         }
11068         break;
11069       }
11070       case Token::SAR:
11071         instr = AddUncasted<HSar>(left, right, strength);
11072         break;
11073       case Token::SHR:
11074         instr = AddUncasted<HShr>(left, right, strength);
11075         if (instr->IsShr() && CanBeZero(right)) {
11076           graph()->RecordUint32Instruction(instr);
11077         }
11078         break;
11079       case Token::SHL:
11080         instr = AddUncasted<HShl>(left, right, strength);
11081         break;
11082       default:
11083         UNREACHABLE();
11084     }
11085   }
11086
11087   if (instr->IsBinaryOperation()) {
11088     HBinaryOperation* binop = HBinaryOperation::cast(instr);
11089     binop->set_observed_input_representation(1, left_rep);
11090     binop->set_observed_input_representation(2, right_rep);
11091     binop->initialize_output_representation(result_rep);
11092     if (graph()->info()->IsStub()) {
11093       // Stub should not call into stub.
11094       instr->SetFlag(HValue::kCannotBeTagged);
11095       // And should truncate on HForceRepresentation already.
11096       if (left->IsForceRepresentation()) {
11097         left->CopyFlag(HValue::kTruncatingToSmi, instr);
11098         left->CopyFlag(HValue::kTruncatingToInt32, instr);
11099       }
11100       if (right->IsForceRepresentation()) {
11101         right->CopyFlag(HValue::kTruncatingToSmi, instr);
11102         right->CopyFlag(HValue::kTruncatingToInt32, instr);
11103       }
11104     }
11105   }
11106   return instr;
11107 }
11108
11109
11110 // Check for the form (%_ClassOf(foo) === 'BarClass').
11111 static bool IsClassOfTest(CompareOperation* expr) {
11112   if (expr->op() != Token::EQ_STRICT) return false;
11113   CallRuntime* call = expr->left()->AsCallRuntime();
11114   if (call == NULL) return false;
11115   Literal* literal = expr->right()->AsLiteral();
11116   if (literal == NULL) return false;
11117   if (!literal->value()->IsString()) return false;
11118   if (!call->name()->IsOneByteEqualTo(STATIC_CHAR_VECTOR("_ClassOf"))) {
11119     return false;
11120   }
11121   DCHECK(call->arguments()->length() == 1);
11122   return true;
11123 }
11124
11125
11126 void HOptimizedGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
11127   DCHECK(!HasStackOverflow());
11128   DCHECK(current_block() != NULL);
11129   DCHECK(current_block()->HasPredecessor());
11130   switch (expr->op()) {
11131     case Token::COMMA:
11132       return VisitComma(expr);
11133     case Token::OR:
11134     case Token::AND:
11135       return VisitLogicalExpression(expr);
11136     default:
11137       return VisitArithmeticExpression(expr);
11138   }
11139 }
11140
11141
11142 void HOptimizedGraphBuilder::VisitComma(BinaryOperation* expr) {
11143   CHECK_ALIVE(VisitForEffect(expr->left()));
11144   // Visit the right subexpression in the same AST context as the entire
11145   // expression.
11146   Visit(expr->right());
11147 }
11148
11149
11150 void HOptimizedGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
11151   bool is_logical_and = expr->op() == Token::AND;
11152   if (ast_context()->IsTest()) {
11153     TestContext* context = TestContext::cast(ast_context());
11154     // Translate left subexpression.
11155     HBasicBlock* eval_right = graph()->CreateBasicBlock();
11156     if (is_logical_and) {
11157       CHECK_BAILOUT(VisitForControl(expr->left(),
11158                                     eval_right,
11159                                     context->if_false()));
11160     } else {
11161       CHECK_BAILOUT(VisitForControl(expr->left(),
11162                                     context->if_true(),
11163                                     eval_right));
11164     }
11165
11166     // Translate right subexpression by visiting it in the same AST
11167     // context as the entire expression.
11168     if (eval_right->HasPredecessor()) {
11169       eval_right->SetJoinId(expr->RightId());
11170       set_current_block(eval_right);
11171       Visit(expr->right());
11172     }
11173
11174   } else if (ast_context()->IsValue()) {
11175     CHECK_ALIVE(VisitForValue(expr->left()));
11176     DCHECK(current_block() != NULL);
11177     HValue* left_value = Top();
11178
11179     // Short-circuit left values that always evaluate to the same boolean value.
11180     if (expr->left()->ToBooleanIsTrue() || expr->left()->ToBooleanIsFalse()) {
11181       // l (evals true)  && r -> r
11182       // l (evals true)  || r -> l
11183       // l (evals false) && r -> l
11184       // l (evals false) || r -> r
11185       if (is_logical_and == expr->left()->ToBooleanIsTrue()) {
11186         Drop(1);
11187         CHECK_ALIVE(VisitForValue(expr->right()));
11188       }
11189       return ast_context()->ReturnValue(Pop());
11190     }
11191
11192     // We need an extra block to maintain edge-split form.
11193     HBasicBlock* empty_block = graph()->CreateBasicBlock();
11194     HBasicBlock* eval_right = graph()->CreateBasicBlock();
11195     ToBooleanStub::Types expected(expr->left()->to_boolean_types());
11196     HBranch* test = is_logical_and
11197         ? New<HBranch>(left_value, expected, eval_right, empty_block)
11198         : New<HBranch>(left_value, expected, empty_block, eval_right);
11199     FinishCurrentBlock(test);
11200
11201     set_current_block(eval_right);
11202     Drop(1);  // Value of the left subexpression.
11203     CHECK_BAILOUT(VisitForValue(expr->right()));
11204
11205     HBasicBlock* join_block =
11206       CreateJoin(empty_block, current_block(), expr->id());
11207     set_current_block(join_block);
11208     return ast_context()->ReturnValue(Pop());
11209
11210   } else {
11211     DCHECK(ast_context()->IsEffect());
11212     // In an effect context, we don't need the value of the left subexpression,
11213     // only its control flow and side effects.  We need an extra block to
11214     // maintain edge-split form.
11215     HBasicBlock* empty_block = graph()->CreateBasicBlock();
11216     HBasicBlock* right_block = graph()->CreateBasicBlock();
11217     if (is_logical_and) {
11218       CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
11219     } else {
11220       CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
11221     }
11222
11223     // TODO(kmillikin): Find a way to fix this.  It's ugly that there are
11224     // actually two empty blocks (one here and one inserted by
11225     // TestContext::BuildBranch, and that they both have an HSimulate though the
11226     // second one is not a merge node, and that we really have no good AST ID to
11227     // put on that first HSimulate.
11228
11229     if (empty_block->HasPredecessor()) {
11230       empty_block->SetJoinId(expr->id());
11231     } else {
11232       empty_block = NULL;
11233     }
11234
11235     if (right_block->HasPredecessor()) {
11236       right_block->SetJoinId(expr->RightId());
11237       set_current_block(right_block);
11238       CHECK_BAILOUT(VisitForEffect(expr->right()));
11239       right_block = current_block();
11240     } else {
11241       right_block = NULL;
11242     }
11243
11244     HBasicBlock* join_block =
11245       CreateJoin(empty_block, right_block, expr->id());
11246     set_current_block(join_block);
11247     // We did not materialize any value in the predecessor environments,
11248     // so there is no need to handle it here.
11249   }
11250 }
11251
11252
11253 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
11254   CHECK_ALIVE(VisitForValue(expr->left()));
11255   CHECK_ALIVE(VisitForValue(expr->right()));
11256   SetSourcePosition(expr->position());
11257   HValue* right = Pop();
11258   HValue* left = Pop();
11259   HValue* result =
11260       BuildBinaryOperation(expr, left, right,
11261           ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
11262                                     : PUSH_BEFORE_SIMULATE);
11263   if (top_info()->is_tracking_positions() && result->IsBinaryOperation()) {
11264     HBinaryOperation::cast(result)->SetOperandPositions(
11265         zone(),
11266         ScriptPositionToSourcePosition(expr->left()->position()),
11267         ScriptPositionToSourcePosition(expr->right()->position()));
11268   }
11269   return ast_context()->ReturnValue(result);
11270 }
11271
11272
11273 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
11274                                                         Expression* sub_expr,
11275                                                         Handle<String> check) {
11276   CHECK_ALIVE(VisitForTypeOf(sub_expr));
11277   SetSourcePosition(expr->position());
11278   HValue* value = Pop();
11279   HTypeofIsAndBranch* instr = New<HTypeofIsAndBranch>(value, check);
11280   return ast_context()->ReturnControl(instr, expr->id());
11281 }
11282
11283
11284 static bool IsLiteralCompareBool(Isolate* isolate,
11285                                  HValue* left,
11286                                  Token::Value op,
11287                                  HValue* right) {
11288   return op == Token::EQ_STRICT &&
11289       ((left->IsConstant() &&
11290           HConstant::cast(left)->handle(isolate)->IsBoolean()) ||
11291        (right->IsConstant() &&
11292            HConstant::cast(right)->handle(isolate)->IsBoolean()));
11293 }
11294
11295
11296 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
11297   DCHECK(!HasStackOverflow());
11298   DCHECK(current_block() != NULL);
11299   DCHECK(current_block()->HasPredecessor());
11300
11301   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
11302
11303   // Check for a few fast cases. The AST visiting behavior must be in sync
11304   // with the full codegen: We don't push both left and right values onto
11305   // the expression stack when one side is a special-case literal.
11306   Expression* sub_expr = NULL;
11307   Handle<String> check;
11308   if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
11309     return HandleLiteralCompareTypeof(expr, sub_expr, check);
11310   }
11311   if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) {
11312     return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
11313   }
11314   if (expr->IsLiteralCompareNull(&sub_expr)) {
11315     return HandleLiteralCompareNil(expr, sub_expr, kNullValue);
11316   }
11317
11318   if (IsClassOfTest(expr)) {
11319     CallRuntime* call = expr->left()->AsCallRuntime();
11320     DCHECK(call->arguments()->length() == 1);
11321     CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11322     HValue* value = Pop();
11323     Literal* literal = expr->right()->AsLiteral();
11324     Handle<String> rhs = Handle<String>::cast(literal->value());
11325     HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs);
11326     return ast_context()->ReturnControl(instr, expr->id());
11327   }
11328
11329   Type* left_type = expr->left()->bounds().lower;
11330   Type* right_type = expr->right()->bounds().lower;
11331   Type* combined_type = expr->combined_type();
11332
11333   CHECK_ALIVE(VisitForValue(expr->left()));
11334   CHECK_ALIVE(VisitForValue(expr->right()));
11335
11336   HValue* right = Pop();
11337   HValue* left = Pop();
11338   Token::Value op = expr->op();
11339
11340   if (IsLiteralCompareBool(isolate(), left, op, right)) {
11341     HCompareObjectEqAndBranch* result =
11342         New<HCompareObjectEqAndBranch>(left, right);
11343     return ast_context()->ReturnControl(result, expr->id());
11344   }
11345
11346   if (op == Token::INSTANCEOF) {
11347     // Check to see if the rhs of the instanceof is a known function.
11348     if (right->IsConstant() &&
11349         HConstant::cast(right)->handle(isolate())->IsJSFunction()) {
11350       Handle<JSFunction> constructor =
11351           Handle<JSFunction>::cast(HConstant::cast(right)->handle(isolate()));
11352       if (!constructor->map()->has_non_instance_prototype()) {
11353         JSFunction::EnsureHasInitialMap(constructor);
11354         DCHECK(constructor->has_initial_map());
11355         Handle<Map> initial_map(constructor->initial_map(), isolate());
11356         top_info()->dependencies()->AssumeInitialMapCantChange(initial_map);
11357         HInstruction* prototype =
11358             Add<HConstant>(handle(initial_map->prototype(), isolate()));
11359         HHasInPrototypeChainAndBranch* result =
11360             New<HHasInPrototypeChainAndBranch>(left, prototype);
11361         return ast_context()->ReturnControl(result, expr->id());
11362       }
11363     }
11364
11365     HInstanceOf* result = New<HInstanceOf>(left, right);
11366     return ast_context()->ReturnInstruction(result, expr->id());
11367
11368   } else if (op == Token::IN) {
11369     HValue* function = AddLoadJSBuiltin(Builtins::IN);
11370     Add<HPushArguments>(left, right);
11371     // TODO(olivf) InvokeFunction produces a check for the parameter count,
11372     // even though we are certain to pass the correct number of arguments here.
11373     HInstruction* result = New<HInvokeFunction>(function, 2);
11374     return ast_context()->ReturnInstruction(result, expr->id());
11375   }
11376
11377   PushBeforeSimulateBehavior push_behavior =
11378     ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
11379                               : PUSH_BEFORE_SIMULATE;
11380   HControlInstruction* compare = BuildCompareInstruction(
11381       op, left, right, left_type, right_type, combined_type,
11382       ScriptPositionToSourcePosition(expr->left()->position()),
11383       ScriptPositionToSourcePosition(expr->right()->position()),
11384       push_behavior, expr->id());
11385   if (compare == NULL) return;  // Bailed out.
11386   return ast_context()->ReturnControl(compare, expr->id());
11387 }
11388
11389
11390 HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
11391     Token::Value op, HValue* left, HValue* right, Type* left_type,
11392     Type* right_type, Type* combined_type, SourcePosition left_position,
11393     SourcePosition right_position, PushBeforeSimulateBehavior push_sim_result,
11394     BailoutId bailout_id) {
11395   // Cases handled below depend on collected type feedback. They should
11396   // soft deoptimize when there is no type feedback.
11397   if (!combined_type->IsInhabited()) {
11398     Add<HDeoptimize>(
11399         Deoptimizer::kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation,
11400         Deoptimizer::SOFT);
11401     combined_type = left_type = right_type = Type::Any(zone());
11402   }
11403
11404   Representation left_rep = RepresentationFor(left_type);
11405   Representation right_rep = RepresentationFor(right_type);
11406   Representation combined_rep = RepresentationFor(combined_type);
11407
11408   if (combined_type->Is(Type::Receiver())) {
11409     if (Token::IsEqualityOp(op)) {
11410       // HCompareObjectEqAndBranch can only deal with object, so
11411       // exclude numbers.
11412       if ((left->IsConstant() &&
11413            HConstant::cast(left)->HasNumberValue()) ||
11414           (right->IsConstant() &&
11415            HConstant::cast(right)->HasNumberValue())) {
11416         Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant,
11417                          Deoptimizer::SOFT);
11418         // The caller expects a branch instruction, so make it happy.
11419         return New<HBranch>(graph()->GetConstantTrue());
11420       }
11421       // Can we get away with map check and not instance type check?
11422       HValue* operand_to_check =
11423           left->block()->block_id() < right->block()->block_id() ? left : right;
11424       if (combined_type->IsClass()) {
11425         Handle<Map> map = combined_type->AsClass()->Map();
11426         AddCheckMap(operand_to_check, map);
11427         HCompareObjectEqAndBranch* result =
11428             New<HCompareObjectEqAndBranch>(left, right);
11429         if (top_info()->is_tracking_positions()) {
11430           result->set_operand_position(zone(), 0, left_position);
11431           result->set_operand_position(zone(), 1, right_position);
11432         }
11433         return result;
11434       } else {
11435         BuildCheckHeapObject(operand_to_check);
11436         Add<HCheckInstanceType>(operand_to_check,
11437                                 HCheckInstanceType::IS_SPEC_OBJECT);
11438         HCompareObjectEqAndBranch* result =
11439             New<HCompareObjectEqAndBranch>(left, right);
11440         return result;
11441       }
11442     } else {
11443       Bailout(kUnsupportedNonPrimitiveCompare);
11444       return NULL;
11445     }
11446   } else if (combined_type->Is(Type::InternalizedString()) &&
11447              Token::IsEqualityOp(op)) {
11448     // If we have a constant argument, it should be consistent with the type
11449     // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch).
11450     if ((left->IsConstant() &&
11451          !HConstant::cast(left)->HasInternalizedStringValue()) ||
11452         (right->IsConstant() &&
11453          !HConstant::cast(right)->HasInternalizedStringValue())) {
11454       Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant,
11455                        Deoptimizer::SOFT);
11456       // The caller expects a branch instruction, so make it happy.
11457       return New<HBranch>(graph()->GetConstantTrue());
11458     }
11459     BuildCheckHeapObject(left);
11460     Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING);
11461     BuildCheckHeapObject(right);
11462     Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING);
11463     HCompareObjectEqAndBranch* result =
11464         New<HCompareObjectEqAndBranch>(left, right);
11465     return result;
11466   } else if (combined_type->Is(Type::String())) {
11467     BuildCheckHeapObject(left);
11468     Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING);
11469     BuildCheckHeapObject(right);
11470     Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING);
11471     HStringCompareAndBranch* result =
11472         New<HStringCompareAndBranch>(left, right, op);
11473     return result;
11474   } else {
11475     if (combined_rep.IsTagged() || combined_rep.IsNone()) {
11476       HCompareGeneric* result = Add<HCompareGeneric>(
11477           left, right, op, strength(function_language_mode()));
11478       result->set_observed_input_representation(1, left_rep);
11479       result->set_observed_input_representation(2, right_rep);
11480       if (result->HasObservableSideEffects()) {
11481         if (push_sim_result == PUSH_BEFORE_SIMULATE) {
11482           Push(result);
11483           AddSimulate(bailout_id, REMOVABLE_SIMULATE);
11484           Drop(1);
11485         } else {
11486           AddSimulate(bailout_id, REMOVABLE_SIMULATE);
11487         }
11488       }
11489       // TODO(jkummerow): Can we make this more efficient?
11490       HBranch* branch = New<HBranch>(result);
11491       return branch;
11492     } else {
11493       HCompareNumericAndBranch* result = New<HCompareNumericAndBranch>(
11494           left, right, op, strength(function_language_mode()));
11495       result->set_observed_input_representation(left_rep, right_rep);
11496       if (top_info()->is_tracking_positions()) {
11497         result->SetOperandPositions(zone(), left_position, right_position);
11498       }
11499       return result;
11500     }
11501   }
11502 }
11503
11504
11505 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
11506                                                      Expression* sub_expr,
11507                                                      NilValue nil) {
11508   DCHECK(!HasStackOverflow());
11509   DCHECK(current_block() != NULL);
11510   DCHECK(current_block()->HasPredecessor());
11511   DCHECK(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
11512   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
11513   CHECK_ALIVE(VisitForValue(sub_expr));
11514   HValue* value = Pop();
11515   if (expr->op() == Token::EQ_STRICT) {
11516     HConstant* nil_constant = nil == kNullValue
11517         ? graph()->GetConstantNull()
11518         : graph()->GetConstantUndefined();
11519     HCompareObjectEqAndBranch* instr =
11520         New<HCompareObjectEqAndBranch>(value, nil_constant);
11521     return ast_context()->ReturnControl(instr, expr->id());
11522   } else {
11523     DCHECK_EQ(Token::EQ, expr->op());
11524     Type* type = expr->combined_type()->Is(Type::None())
11525         ? Type::Any(zone()) : expr->combined_type();
11526     HIfContinuation continuation;
11527     BuildCompareNil(value, type, &continuation);
11528     return ast_context()->ReturnContinuation(&continuation, expr->id());
11529   }
11530 }
11531
11532
11533 void HOptimizedGraphBuilder::VisitSpread(Spread* expr) { UNREACHABLE(); }
11534
11535
11536 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
11537   // If we share optimized code between different closures, the
11538   // this-function is not a constant, except inside an inlined body.
11539   if (function_state()->outer() != NULL) {
11540       return New<HConstant>(
11541           function_state()->compilation_info()->closure());
11542   } else {
11543       return New<HThisFunction>();
11544   }
11545 }
11546
11547
11548 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
11549     Handle<JSObject> boilerplate_object,
11550     AllocationSiteUsageContext* site_context) {
11551   NoObservableSideEffectsScope no_effects(this);
11552   Handle<Map> initial_map(boilerplate_object->map());
11553   InstanceType instance_type = initial_map->instance_type();
11554   DCHECK(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE);
11555
11556   HType type = instance_type == JS_ARRAY_TYPE
11557       ? HType::JSArray() : HType::JSObject();
11558   HValue* object_size_constant = Add<HConstant>(initial_map->instance_size());
11559
11560   PretenureFlag pretenure_flag = NOT_TENURED;
11561   Handle<AllocationSite> top_site(*site_context->top(), isolate());
11562   if (FLAG_allocation_site_pretenuring) {
11563     pretenure_flag = top_site->GetPretenureMode();
11564   }
11565
11566   Handle<AllocationSite> current_site(*site_context->current(), isolate());
11567   if (*top_site == *current_site) {
11568     // We install a dependency for pretenuring only on the outermost literal.
11569     top_info()->dependencies()->AssumeTenuringDecision(top_site);
11570   }
11571   top_info()->dependencies()->AssumeTransitionStable(current_site);
11572
11573   HInstruction* object = Add<HAllocate>(
11574       object_size_constant, type, pretenure_flag, instance_type, top_site);
11575
11576   // If allocation folding reaches Page::kMaxRegularHeapObjectSize the
11577   // elements array may not get folded into the object. Hence, we set the
11578   // elements pointer to empty fixed array and let store elimination remove
11579   // this store in the folding case.
11580   HConstant* empty_fixed_array = Add<HConstant>(
11581       isolate()->factory()->empty_fixed_array());
11582   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
11583       empty_fixed_array);
11584
11585   BuildEmitObjectHeader(boilerplate_object, object);
11586
11587   // Similarly to the elements pointer, there is no guarantee that all
11588   // property allocations can get folded, so pre-initialize all in-object
11589   // properties to a safe value.
11590   BuildInitializeInobjectProperties(object, initial_map);
11591
11592   Handle<FixedArrayBase> elements(boilerplate_object->elements());
11593   int elements_size = (elements->length() > 0 &&
11594       elements->map() != isolate()->heap()->fixed_cow_array_map()) ?
11595           elements->Size() : 0;
11596
11597   if (pretenure_flag == TENURED &&
11598       elements->map() == isolate()->heap()->fixed_cow_array_map() &&
11599       isolate()->heap()->InNewSpace(*elements)) {
11600     // If we would like to pretenure a fixed cow array, we must ensure that the
11601     // array is already in old space, otherwise we'll create too many old-to-
11602     // new-space pointers (overflowing the store buffer).
11603     elements = Handle<FixedArrayBase>(
11604         isolate()->factory()->CopyAndTenureFixedCOWArray(
11605             Handle<FixedArray>::cast(elements)));
11606     boilerplate_object->set_elements(*elements);
11607   }
11608
11609   HInstruction* object_elements = NULL;
11610   if (elements_size > 0) {
11611     HValue* object_elements_size = Add<HConstant>(elements_size);
11612     InstanceType instance_type = boilerplate_object->HasFastDoubleElements()
11613         ? FIXED_DOUBLE_ARRAY_TYPE : FIXED_ARRAY_TYPE;
11614     object_elements = Add<HAllocate>(object_elements_size, HType::HeapObject(),
11615                                      pretenure_flag, instance_type, top_site);
11616     BuildEmitElements(boilerplate_object, elements, object_elements,
11617                       site_context);
11618     Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
11619                           object_elements);
11620   } else {
11621     Handle<Object> elements_field =
11622         Handle<Object>(boilerplate_object->elements(), isolate());
11623     HInstruction* object_elements_cow = Add<HConstant>(elements_field);
11624     Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
11625                           object_elements_cow);
11626   }
11627
11628   // Copy in-object properties.
11629   if (initial_map->NumberOfFields() != 0 ||
11630       initial_map->unused_property_fields() > 0) {
11631     BuildEmitInObjectProperties(boilerplate_object, object, site_context,
11632                                 pretenure_flag);
11633   }
11634   return object;
11635 }
11636
11637
11638 void HOptimizedGraphBuilder::BuildEmitObjectHeader(
11639     Handle<JSObject> boilerplate_object,
11640     HInstruction* object) {
11641   DCHECK(boilerplate_object->properties()->length() == 0);
11642
11643   Handle<Map> boilerplate_object_map(boilerplate_object->map());
11644   AddStoreMapConstant(object, boilerplate_object_map);
11645
11646   Handle<Object> properties_field =
11647       Handle<Object>(boilerplate_object->properties(), isolate());
11648   DCHECK(*properties_field == isolate()->heap()->empty_fixed_array());
11649   HInstruction* properties = Add<HConstant>(properties_field);
11650   HObjectAccess access = HObjectAccess::ForPropertiesPointer();
11651   Add<HStoreNamedField>(object, access, properties);
11652
11653   if (boilerplate_object->IsJSArray()) {
11654     Handle<JSArray> boilerplate_array =
11655         Handle<JSArray>::cast(boilerplate_object);
11656     Handle<Object> length_field =
11657         Handle<Object>(boilerplate_array->length(), isolate());
11658     HInstruction* length = Add<HConstant>(length_field);
11659
11660     DCHECK(boilerplate_array->length()->IsSmi());
11661     Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(
11662         boilerplate_array->GetElementsKind()), length);
11663   }
11664 }
11665
11666
11667 void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
11668     Handle<JSObject> boilerplate_object,
11669     HInstruction* object,
11670     AllocationSiteUsageContext* site_context,
11671     PretenureFlag pretenure_flag) {
11672   Handle<Map> boilerplate_map(boilerplate_object->map());
11673   Handle<DescriptorArray> descriptors(boilerplate_map->instance_descriptors());
11674   int limit = boilerplate_map->NumberOfOwnDescriptors();
11675
11676   int copied_fields = 0;
11677   for (int i = 0; i < limit; i++) {
11678     PropertyDetails details = descriptors->GetDetails(i);
11679     if (details.type() != DATA) continue;
11680     copied_fields++;
11681     FieldIndex field_index = FieldIndex::ForDescriptor(*boilerplate_map, i);
11682
11683
11684     int property_offset = field_index.offset();
11685     Handle<Name> name(descriptors->GetKey(i));
11686
11687     // The access for the store depends on the type of the boilerplate.
11688     HObjectAccess access = boilerplate_object->IsJSArray() ?
11689         HObjectAccess::ForJSArrayOffset(property_offset) :
11690         HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
11691
11692     if (boilerplate_object->IsUnboxedDoubleField(field_index)) {
11693       CHECK(!boilerplate_object->IsJSArray());
11694       double value = boilerplate_object->RawFastDoublePropertyAt(field_index);
11695       access = access.WithRepresentation(Representation::Double());
11696       Add<HStoreNamedField>(object, access, Add<HConstant>(value));
11697       continue;
11698     }
11699     Handle<Object> value(boilerplate_object->RawFastPropertyAt(field_index),
11700                          isolate());
11701
11702     if (value->IsJSObject()) {
11703       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
11704       Handle<AllocationSite> current_site = site_context->EnterNewScope();
11705       HInstruction* result =
11706           BuildFastLiteral(value_object, site_context);
11707       site_context->ExitScope(current_site, value_object);
11708       Add<HStoreNamedField>(object, access, result);
11709     } else {
11710       Representation representation = details.representation();
11711       HInstruction* value_instruction;
11712
11713       if (representation.IsDouble()) {
11714         // Allocate a HeapNumber box and store the value into it.
11715         HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize);
11716         HInstruction* double_box =
11717             Add<HAllocate>(heap_number_constant, HType::HeapObject(),
11718                 pretenure_flag, MUTABLE_HEAP_NUMBER_TYPE);
11719         AddStoreMapConstant(double_box,
11720             isolate()->factory()->mutable_heap_number_map());
11721         // Unwrap the mutable heap number from the boilerplate.
11722         HValue* double_value =
11723             Add<HConstant>(Handle<HeapNumber>::cast(value)->value());
11724         Add<HStoreNamedField>(
11725             double_box, HObjectAccess::ForHeapNumberValue(), double_value);
11726         value_instruction = double_box;
11727       } else if (representation.IsSmi()) {
11728         value_instruction = value->IsUninitialized()
11729             ? graph()->GetConstant0()
11730             : Add<HConstant>(value);
11731         // Ensure that value is stored as smi.
11732         access = access.WithRepresentation(representation);
11733       } else {
11734         value_instruction = Add<HConstant>(value);
11735       }
11736
11737       Add<HStoreNamedField>(object, access, value_instruction);
11738     }
11739   }
11740
11741   int inobject_properties = boilerplate_object->map()->GetInObjectProperties();
11742   HInstruction* value_instruction =
11743       Add<HConstant>(isolate()->factory()->one_pointer_filler_map());
11744   for (int i = copied_fields; i < inobject_properties; i++) {
11745     DCHECK(boilerplate_object->IsJSObject());
11746     int property_offset = boilerplate_object->GetInObjectPropertyOffset(i);
11747     HObjectAccess access =
11748         HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
11749     Add<HStoreNamedField>(object, access, value_instruction);
11750   }
11751 }
11752
11753
11754 void HOptimizedGraphBuilder::BuildEmitElements(
11755     Handle<JSObject> boilerplate_object,
11756     Handle<FixedArrayBase> elements,
11757     HValue* object_elements,
11758     AllocationSiteUsageContext* site_context) {
11759   ElementsKind kind = boilerplate_object->map()->elements_kind();
11760   int elements_length = elements->length();
11761   HValue* object_elements_length = Add<HConstant>(elements_length);
11762   BuildInitializeElementsHeader(object_elements, kind, object_elements_length);
11763
11764   // Copy elements backing store content.
11765   if (elements->IsFixedDoubleArray()) {
11766     BuildEmitFixedDoubleArray(elements, kind, object_elements);
11767   } else if (elements->IsFixedArray()) {
11768     BuildEmitFixedArray(elements, kind, object_elements,
11769                         site_context);
11770   } else {
11771     UNREACHABLE();
11772   }
11773 }
11774
11775
11776 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray(
11777     Handle<FixedArrayBase> elements,
11778     ElementsKind kind,
11779     HValue* object_elements) {
11780   HInstruction* boilerplate_elements = Add<HConstant>(elements);
11781   int elements_length = elements->length();
11782   for (int i = 0; i < elements_length; i++) {
11783     HValue* key_constant = Add<HConstant>(i);
11784     HInstruction* value_instruction = Add<HLoadKeyed>(
11785         boilerplate_elements, key_constant, nullptr, kind, ALLOW_RETURN_HOLE);
11786     HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant,
11787                                            value_instruction, kind);
11788     store->SetFlag(HValue::kAllowUndefinedAsNaN);
11789   }
11790 }
11791
11792
11793 void HOptimizedGraphBuilder::BuildEmitFixedArray(
11794     Handle<FixedArrayBase> elements,
11795     ElementsKind kind,
11796     HValue* object_elements,
11797     AllocationSiteUsageContext* site_context) {
11798   HInstruction* boilerplate_elements = Add<HConstant>(elements);
11799   int elements_length = elements->length();
11800   Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
11801   for (int i = 0; i < elements_length; i++) {
11802     Handle<Object> value(fast_elements->get(i), isolate());
11803     HValue* key_constant = Add<HConstant>(i);
11804     if (value->IsJSObject()) {
11805       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
11806       Handle<AllocationSite> current_site = site_context->EnterNewScope();
11807       HInstruction* result =
11808           BuildFastLiteral(value_object, site_context);
11809       site_context->ExitScope(current_site, value_object);
11810       Add<HStoreKeyed>(object_elements, key_constant, result, kind);
11811     } else {
11812       ElementsKind copy_kind =
11813           kind == FAST_HOLEY_SMI_ELEMENTS ? FAST_HOLEY_ELEMENTS : kind;
11814       HInstruction* value_instruction =
11815           Add<HLoadKeyed>(boilerplate_elements, key_constant, nullptr,
11816                           copy_kind, ALLOW_RETURN_HOLE);
11817       Add<HStoreKeyed>(object_elements, key_constant, value_instruction,
11818                        copy_kind);
11819     }
11820   }
11821 }
11822
11823
11824 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
11825   DCHECK(!HasStackOverflow());
11826   DCHECK(current_block() != NULL);
11827   DCHECK(current_block()->HasPredecessor());
11828   HInstruction* instr = BuildThisFunction();
11829   return ast_context()->ReturnInstruction(instr, expr->id());
11830 }
11831
11832
11833 void HOptimizedGraphBuilder::VisitSuperPropertyReference(
11834     SuperPropertyReference* expr) {
11835   DCHECK(!HasStackOverflow());
11836   DCHECK(current_block() != NULL);
11837   DCHECK(current_block()->HasPredecessor());
11838   return Bailout(kSuperReference);
11839 }
11840
11841
11842 void HOptimizedGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
11843   DCHECK(!HasStackOverflow());
11844   DCHECK(current_block() != NULL);
11845   DCHECK(current_block()->HasPredecessor());
11846   return Bailout(kSuperReference);
11847 }
11848
11849
11850 void HOptimizedGraphBuilder::VisitDeclarations(
11851     ZoneList<Declaration*>* declarations) {
11852   DCHECK(globals_.is_empty());
11853   AstVisitor::VisitDeclarations(declarations);
11854   if (!globals_.is_empty()) {
11855     Handle<FixedArray> array =
11856        isolate()->factory()->NewFixedArray(globals_.length(), TENURED);
11857     for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i));
11858     int flags =
11859         DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) |
11860         DeclareGlobalsNativeFlag::encode(current_info()->is_native()) |
11861         DeclareGlobalsLanguageMode::encode(current_info()->language_mode());
11862     Add<HDeclareGlobals>(array, flags);
11863     globals_.Rewind(0);
11864   }
11865 }
11866
11867
11868 void HOptimizedGraphBuilder::VisitVariableDeclaration(
11869     VariableDeclaration* declaration) {
11870   VariableProxy* proxy = declaration->proxy();
11871   VariableMode mode = declaration->mode();
11872   Variable* variable = proxy->var();
11873   bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
11874   switch (variable->location()) {
11875     case VariableLocation::GLOBAL:
11876     case VariableLocation::UNALLOCATED:
11877       globals_.Add(variable->name(), zone());
11878       globals_.Add(variable->binding_needs_init()
11879                        ? isolate()->factory()->the_hole_value()
11880                        : isolate()->factory()->undefined_value(), zone());
11881       return;
11882     case VariableLocation::PARAMETER:
11883     case VariableLocation::LOCAL:
11884       if (hole_init) {
11885         HValue* value = graph()->GetConstantHole();
11886         environment()->Bind(variable, value);
11887       }
11888       break;
11889     case VariableLocation::CONTEXT:
11890       if (hole_init) {
11891         HValue* value = graph()->GetConstantHole();
11892         HValue* context = environment()->context();
11893         HStoreContextSlot* store = Add<HStoreContextSlot>(
11894             context, variable->index(), HStoreContextSlot::kNoCheck, value);
11895         if (store->HasObservableSideEffects()) {
11896           Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
11897         }
11898       }
11899       break;
11900     case VariableLocation::LOOKUP:
11901       return Bailout(kUnsupportedLookupSlotInDeclaration);
11902   }
11903 }
11904
11905
11906 void HOptimizedGraphBuilder::VisitFunctionDeclaration(
11907     FunctionDeclaration* declaration) {
11908   VariableProxy* proxy = declaration->proxy();
11909   Variable* variable = proxy->var();
11910   switch (variable->location()) {
11911     case VariableLocation::GLOBAL:
11912     case VariableLocation::UNALLOCATED: {
11913       globals_.Add(variable->name(), zone());
11914       Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
11915           declaration->fun(), current_info()->script(), top_info());
11916       // Check for stack-overflow exception.
11917       if (function.is_null()) return SetStackOverflow();
11918       globals_.Add(function, zone());
11919       return;
11920     }
11921     case VariableLocation::PARAMETER:
11922     case VariableLocation::LOCAL: {
11923       CHECK_ALIVE(VisitForValue(declaration->fun()));
11924       HValue* value = Pop();
11925       BindIfLive(variable, value);
11926       break;
11927     }
11928     case VariableLocation::CONTEXT: {
11929       CHECK_ALIVE(VisitForValue(declaration->fun()));
11930       HValue* value = Pop();
11931       HValue* context = environment()->context();
11932       HStoreContextSlot* store = Add<HStoreContextSlot>(
11933           context, variable->index(), HStoreContextSlot::kNoCheck, value);
11934       if (store->HasObservableSideEffects()) {
11935         Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
11936       }
11937       break;
11938     }
11939     case VariableLocation::LOOKUP:
11940       return Bailout(kUnsupportedLookupSlotInDeclaration);
11941   }
11942 }
11943
11944
11945 void HOptimizedGraphBuilder::VisitImportDeclaration(
11946     ImportDeclaration* declaration) {
11947   UNREACHABLE();
11948 }
11949
11950
11951 void HOptimizedGraphBuilder::VisitExportDeclaration(
11952     ExportDeclaration* declaration) {
11953   UNREACHABLE();
11954 }
11955
11956
11957 // Generators for inline runtime functions.
11958 // Support for types.
11959 void HOptimizedGraphBuilder::GenerateIsSmi(CallRuntime* call) {
11960   DCHECK(call->arguments()->length() == 1);
11961   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11962   HValue* value = Pop();
11963   HIsSmiAndBranch* result = New<HIsSmiAndBranch>(value);
11964   return ast_context()->ReturnControl(result, call->id());
11965 }
11966
11967
11968 void HOptimizedGraphBuilder::GenerateIsSpecObject(CallRuntime* call) {
11969   DCHECK(call->arguments()->length() == 1);
11970   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11971   HValue* value = Pop();
11972   HHasInstanceTypeAndBranch* result =
11973       New<HHasInstanceTypeAndBranch>(value,
11974                                      FIRST_SPEC_OBJECT_TYPE,
11975                                      LAST_SPEC_OBJECT_TYPE);
11976   return ast_context()->ReturnControl(result, call->id());
11977 }
11978
11979
11980 void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) {
11981   DCHECK(call->arguments()->length() == 1);
11982   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11983   HValue* value = Pop();
11984   HHasInstanceTypeAndBranch* result =
11985       New<HHasInstanceTypeAndBranch>(value, JS_FUNCTION_TYPE);
11986   return ast_context()->ReturnControl(result, call->id());
11987 }
11988
11989
11990 void HOptimizedGraphBuilder::GenerateIsMinusZero(CallRuntime* call) {
11991   DCHECK(call->arguments()->length() == 1);
11992   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11993   HValue* value = Pop();
11994   HCompareMinusZeroAndBranch* result = New<HCompareMinusZeroAndBranch>(value);
11995   return ast_context()->ReturnControl(result, call->id());
11996 }
11997
11998
11999 void HOptimizedGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
12000   DCHECK(call->arguments()->length() == 1);
12001   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12002   HValue* value = Pop();
12003   HHasCachedArrayIndexAndBranch* result =
12004       New<HHasCachedArrayIndexAndBranch>(value);
12005   return ast_context()->ReturnControl(result, call->id());
12006 }
12007
12008
12009 void HOptimizedGraphBuilder::GenerateIsArray(CallRuntime* call) {
12010   DCHECK(call->arguments()->length() == 1);
12011   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12012   HValue* value = Pop();
12013   HHasInstanceTypeAndBranch* result =
12014       New<HHasInstanceTypeAndBranch>(value, JS_ARRAY_TYPE);
12015   return ast_context()->ReturnControl(result, call->id());
12016 }
12017
12018
12019 void HOptimizedGraphBuilder::GenerateIsTypedArray(CallRuntime* call) {
12020   DCHECK(call->arguments()->length() == 1);
12021   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12022   HValue* value = Pop();
12023   HHasInstanceTypeAndBranch* result =
12024       New<HHasInstanceTypeAndBranch>(value, JS_TYPED_ARRAY_TYPE);
12025   return ast_context()->ReturnControl(result, call->id());
12026 }
12027
12028
12029 void HOptimizedGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
12030   DCHECK(call->arguments()->length() == 1);
12031   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12032   HValue* value = Pop();
12033   HHasInstanceTypeAndBranch* result =
12034       New<HHasInstanceTypeAndBranch>(value, JS_REGEXP_TYPE);
12035   return ast_context()->ReturnControl(result, call->id());
12036 }
12037
12038
12039 void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) {
12040   DCHECK(call->arguments()->length() == 1);
12041   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12042   HValue* value = Pop();
12043   HIsObjectAndBranch* result = New<HIsObjectAndBranch>(value);
12044   return ast_context()->ReturnControl(result, call->id());
12045 }
12046
12047
12048 void HOptimizedGraphBuilder::GenerateToObject(CallRuntime* call) {
12049   DCHECK_EQ(1, call->arguments()->length());
12050   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12051   HValue* value = Pop();
12052   HValue* result = BuildToObject(value);
12053   return ast_context()->ReturnValue(result);
12054 }
12055
12056
12057 void HOptimizedGraphBuilder::GenerateIsJSProxy(CallRuntime* call) {
12058   DCHECK(call->arguments()->length() == 1);
12059   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12060   HValue* value = Pop();
12061   HIfContinuation continuation;
12062   IfBuilder if_proxy(this);
12063
12064   HValue* smicheck = if_proxy.IfNot<HIsSmiAndBranch>(value);
12065   if_proxy.And();
12066   HValue* map = Add<HLoadNamedField>(value, smicheck, HObjectAccess::ForMap());
12067   HValue* instance_type =
12068       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
12069   if_proxy.If<HCompareNumericAndBranch>(
12070       instance_type, Add<HConstant>(FIRST_JS_PROXY_TYPE), Token::GTE);
12071   if_proxy.And();
12072   if_proxy.If<HCompareNumericAndBranch>(
12073       instance_type, Add<HConstant>(LAST_JS_PROXY_TYPE), Token::LTE);
12074
12075   if_proxy.CaptureContinuation(&continuation);
12076   return ast_context()->ReturnContinuation(&continuation, call->id());
12077 }
12078
12079
12080 void HOptimizedGraphBuilder::GenerateHasFastPackedElements(CallRuntime* call) {
12081   DCHECK(call->arguments()->length() == 1);
12082   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12083   HValue* object = Pop();
12084   HIfContinuation continuation(graph()->CreateBasicBlock(),
12085                                graph()->CreateBasicBlock());
12086   IfBuilder if_not_smi(this);
12087   if_not_smi.IfNot<HIsSmiAndBranch>(object);
12088   if_not_smi.Then();
12089   {
12090     NoObservableSideEffectsScope no_effects(this);
12091
12092     IfBuilder if_fast_packed(this);
12093     HValue* elements_kind = BuildGetElementsKind(object);
12094     if_fast_packed.If<HCompareNumericAndBranch>(
12095         elements_kind, Add<HConstant>(FAST_SMI_ELEMENTS), Token::EQ);
12096     if_fast_packed.Or();
12097     if_fast_packed.If<HCompareNumericAndBranch>(
12098         elements_kind, Add<HConstant>(FAST_ELEMENTS), Token::EQ);
12099     if_fast_packed.Or();
12100     if_fast_packed.If<HCompareNumericAndBranch>(
12101         elements_kind, Add<HConstant>(FAST_DOUBLE_ELEMENTS), Token::EQ);
12102     if_fast_packed.JoinContinuation(&continuation);
12103   }
12104   if_not_smi.JoinContinuation(&continuation);
12105   return ast_context()->ReturnContinuation(&continuation, call->id());
12106 }
12107
12108
12109 // Support for construct call checks.
12110 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
12111   DCHECK(call->arguments()->length() == 0);
12112   if (function_state()->outer() != NULL) {
12113     // We are generating graph for inlined function.
12114     HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN
12115         ? graph()->GetConstantTrue()
12116         : graph()->GetConstantFalse();
12117     return ast_context()->ReturnValue(value);
12118   } else {
12119     return ast_context()->ReturnControl(New<HIsConstructCallAndBranch>(),
12120                                         call->id());
12121   }
12122 }
12123
12124
12125 // Support for arguments.length and arguments[?].
12126 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
12127   DCHECK(call->arguments()->length() == 0);
12128   HInstruction* result = NULL;
12129   if (function_state()->outer() == NULL) {
12130     HInstruction* elements = Add<HArgumentsElements>(false);
12131     result = New<HArgumentsLength>(elements);
12132   } else {
12133     // Number of arguments without receiver.
12134     int argument_count = environment()->
12135         arguments_environment()->parameter_count() - 1;
12136     result = New<HConstant>(argument_count);
12137   }
12138   return ast_context()->ReturnInstruction(result, call->id());
12139 }
12140
12141
12142 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) {
12143   DCHECK(call->arguments()->length() == 1);
12144   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12145   HValue* index = Pop();
12146   HInstruction* result = NULL;
12147   if (function_state()->outer() == NULL) {
12148     HInstruction* elements = Add<HArgumentsElements>(false);
12149     HInstruction* length = Add<HArgumentsLength>(elements);
12150     HInstruction* checked_index = Add<HBoundsCheck>(index, length);
12151     result = New<HAccessArgumentsAt>(elements, length, checked_index);
12152   } else {
12153     EnsureArgumentsArePushedForAccess();
12154
12155     // Number of arguments without receiver.
12156     HInstruction* elements = function_state()->arguments_elements();
12157     int argument_count = environment()->
12158         arguments_environment()->parameter_count() - 1;
12159     HInstruction* length = Add<HConstant>(argument_count);
12160     HInstruction* checked_key = Add<HBoundsCheck>(index, length);
12161     result = New<HAccessArgumentsAt>(elements, length, checked_key);
12162   }
12163   return ast_context()->ReturnInstruction(result, call->id());
12164 }
12165
12166
12167 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) {
12168   DCHECK(call->arguments()->length() == 1);
12169   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12170   HValue* object = Pop();
12171
12172   IfBuilder if_objectisvalue(this);
12173   HValue* objectisvalue = if_objectisvalue.If<HHasInstanceTypeAndBranch>(
12174       object, JS_VALUE_TYPE);
12175   if_objectisvalue.Then();
12176   {
12177     // Return the actual value.
12178     Push(Add<HLoadNamedField>(
12179             object, objectisvalue,
12180             HObjectAccess::ForObservableJSObjectOffset(
12181                 JSValue::kValueOffset)));
12182     Add<HSimulate>(call->id(), FIXED_SIMULATE);
12183   }
12184   if_objectisvalue.Else();
12185   {
12186     // If the object is not a value return the object.
12187     Push(object);
12188     Add<HSimulate>(call->id(), FIXED_SIMULATE);
12189   }
12190   if_objectisvalue.End();
12191   return ast_context()->ReturnValue(Pop());
12192 }
12193
12194
12195 void HOptimizedGraphBuilder::GenerateJSValueGetValue(CallRuntime* call) {
12196   DCHECK(call->arguments()->length() == 1);
12197   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12198   HValue* value = Pop();
12199   HInstruction* result = Add<HLoadNamedField>(
12200       value, nullptr,
12201       HObjectAccess::ForObservableJSObjectOffset(JSValue::kValueOffset));
12202   return ast_context()->ReturnInstruction(result, call->id());
12203 }
12204
12205
12206 void HOptimizedGraphBuilder::GenerateIsDate(CallRuntime* call) {
12207   DCHECK_EQ(1, call->arguments()->length());
12208   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12209   HValue* value = Pop();
12210   HHasInstanceTypeAndBranch* result =
12211       New<HHasInstanceTypeAndBranch>(value, JS_DATE_TYPE);
12212   return ast_context()->ReturnControl(result, call->id());
12213 }
12214
12215
12216 void HOptimizedGraphBuilder::GenerateThrowNotDateError(CallRuntime* call) {
12217   DCHECK_EQ(0, call->arguments()->length());
12218   Add<HDeoptimize>(Deoptimizer::kNotADateObject, Deoptimizer::EAGER);
12219   Add<HSimulate>(call->id(), FIXED_SIMULATE);
12220   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
12221 }
12222
12223
12224 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) {
12225   DCHECK(call->arguments()->length() == 2);
12226   DCHECK_NOT_NULL(call->arguments()->at(1)->AsLiteral());
12227   Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->value()));
12228   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12229   HValue* date = Pop();
12230   HDateField* result = New<HDateField>(date, index);
12231   return ast_context()->ReturnInstruction(result, call->id());
12232 }
12233
12234
12235 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar(
12236     CallRuntime* call) {
12237   DCHECK(call->arguments()->length() == 3);
12238   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12239   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12240   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
12241   HValue* string = Pop();
12242   HValue* value = Pop();
12243   HValue* index = Pop();
12244   Add<HSeqStringSetChar>(String::ONE_BYTE_ENCODING, string,
12245                          index, value);
12246   Add<HSimulate>(call->id(), FIXED_SIMULATE);
12247   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
12248 }
12249
12250
12251 void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar(
12252     CallRuntime* call) {
12253   DCHECK(call->arguments()->length() == 3);
12254   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12255   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12256   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
12257   HValue* string = Pop();
12258   HValue* value = Pop();
12259   HValue* index = Pop();
12260   Add<HSeqStringSetChar>(String::TWO_BYTE_ENCODING, string,
12261                          index, value);
12262   Add<HSimulate>(call->id(), FIXED_SIMULATE);
12263   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
12264 }
12265
12266
12267 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
12268   DCHECK(call->arguments()->length() == 2);
12269   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12270   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12271   HValue* value = Pop();
12272   HValue* object = Pop();
12273
12274   // Check if object is a JSValue.
12275   IfBuilder if_objectisvalue(this);
12276   if_objectisvalue.If<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE);
12277   if_objectisvalue.Then();
12278   {
12279     // Create in-object property store to kValueOffset.
12280     Add<HStoreNamedField>(object,
12281         HObjectAccess::ForObservableJSObjectOffset(JSValue::kValueOffset),
12282         value);
12283     if (!ast_context()->IsEffect()) {
12284       Push(value);
12285     }
12286     Add<HSimulate>(call->id(), FIXED_SIMULATE);
12287   }
12288   if_objectisvalue.Else();
12289   {
12290     // Nothing to do in this case.
12291     if (!ast_context()->IsEffect()) {
12292       Push(value);
12293     }
12294     Add<HSimulate>(call->id(), FIXED_SIMULATE);
12295   }
12296   if_objectisvalue.End();
12297   if (!ast_context()->IsEffect()) {
12298     Drop(1);
12299   }
12300   return ast_context()->ReturnValue(value);
12301 }
12302
12303
12304 // Fast support for charCodeAt(n).
12305 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
12306   DCHECK(call->arguments()->length() == 2);
12307   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12308   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12309   HValue* index = Pop();
12310   HValue* string = Pop();
12311   HInstruction* result = BuildStringCharCodeAt(string, index);
12312   return ast_context()->ReturnInstruction(result, call->id());
12313 }
12314
12315
12316 // Fast support for string.charAt(n) and string[n].
12317 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
12318   DCHECK(call->arguments()->length() == 1);
12319   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12320   HValue* char_code = Pop();
12321   HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
12322   return ast_context()->ReturnInstruction(result, call->id());
12323 }
12324
12325
12326 // Fast support for string.charAt(n) and string[n].
12327 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
12328   DCHECK(call->arguments()->length() == 2);
12329   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12330   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12331   HValue* index = Pop();
12332   HValue* string = Pop();
12333   HInstruction* char_code = BuildStringCharCodeAt(string, index);
12334   AddInstruction(char_code);
12335   HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
12336   return ast_context()->ReturnInstruction(result, call->id());
12337 }
12338
12339
12340 // Fast support for object equality testing.
12341 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
12342   DCHECK(call->arguments()->length() == 2);
12343   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12344   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12345   HValue* right = Pop();
12346   HValue* left = Pop();
12347   HCompareObjectEqAndBranch* result =
12348       New<HCompareObjectEqAndBranch>(left, right);
12349   return ast_context()->ReturnControl(result, call->id());
12350 }
12351
12352
12353 // Fast support for StringAdd.
12354 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) {
12355   DCHECK_EQ(2, call->arguments()->length());
12356   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12357   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12358   HValue* right = Pop();
12359   HValue* left = Pop();
12360   HInstruction* result =
12361       NewUncasted<HStringAdd>(left, right, strength(function_language_mode()));
12362   return ast_context()->ReturnInstruction(result, call->id());
12363 }
12364
12365
12366 // Fast support for SubString.
12367 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) {
12368   DCHECK_EQ(3, call->arguments()->length());
12369   CHECK_ALIVE(VisitExpressions(call->arguments()));
12370   PushArgumentsFromEnvironment(call->arguments()->length());
12371   HCallStub* result = New<HCallStub>(CodeStub::SubString, 3);
12372   return ast_context()->ReturnInstruction(result, call->id());
12373 }
12374
12375
12376 // Fast support for StringCompare.
12377 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) {
12378   DCHECK_EQ(2, call->arguments()->length());
12379   CHECK_ALIVE(VisitExpressions(call->arguments()));
12380   PushArgumentsFromEnvironment(call->arguments()->length());
12381   HCallStub* result = New<HCallStub>(CodeStub::StringCompare, 2);
12382   return ast_context()->ReturnInstruction(result, call->id());
12383 }
12384
12385
12386 void HOptimizedGraphBuilder::GenerateStringGetLength(CallRuntime* call) {
12387   DCHECK(call->arguments()->length() == 1);
12388   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12389   HValue* string = Pop();
12390   HInstruction* result = BuildLoadStringLength(string);
12391   return ast_context()->ReturnInstruction(result, call->id());
12392 }
12393
12394
12395 // Support for direct calls from JavaScript to native RegExp code.
12396 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
12397   DCHECK_EQ(4, call->arguments()->length());
12398   CHECK_ALIVE(VisitExpressions(call->arguments()));
12399   PushArgumentsFromEnvironment(call->arguments()->length());
12400   HCallStub* result = New<HCallStub>(CodeStub::RegExpExec, 4);
12401   return ast_context()->ReturnInstruction(result, call->id());
12402 }
12403
12404
12405 void HOptimizedGraphBuilder::GenerateDoubleLo(CallRuntime* call) {
12406   DCHECK_EQ(1, call->arguments()->length());
12407   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12408   HValue* value = Pop();
12409   HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::LOW);
12410   return ast_context()->ReturnInstruction(result, call->id());
12411 }
12412
12413
12414 void HOptimizedGraphBuilder::GenerateDoubleHi(CallRuntime* call) {
12415   DCHECK_EQ(1, call->arguments()->length());
12416   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12417   HValue* value = Pop();
12418   HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::HIGH);
12419   return ast_context()->ReturnInstruction(result, call->id());
12420 }
12421
12422
12423 void HOptimizedGraphBuilder::GenerateConstructDouble(CallRuntime* call) {
12424   DCHECK_EQ(2, call->arguments()->length());
12425   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12426   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12427   HValue* lo = Pop();
12428   HValue* hi = Pop();
12429   HInstruction* result = NewUncasted<HConstructDouble>(hi, lo);
12430   return ast_context()->ReturnInstruction(result, call->id());
12431 }
12432
12433
12434 // Construct a RegExp exec result with two in-object properties.
12435 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
12436   DCHECK_EQ(3, call->arguments()->length());
12437   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12438   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12439   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
12440   HValue* input = Pop();
12441   HValue* index = Pop();
12442   HValue* length = Pop();
12443   HValue* result = BuildRegExpConstructResult(length, index, input);
12444   return ast_context()->ReturnValue(result);
12445 }
12446
12447
12448 // Fast support for number to string.
12449 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) {
12450   DCHECK_EQ(1, call->arguments()->length());
12451   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12452   HValue* number = Pop();
12453   HValue* result = BuildNumberToString(number, Type::Any(zone()));
12454   return ast_context()->ReturnValue(result);
12455 }
12456
12457
12458 // Fast call for custom callbacks.
12459 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) {
12460   // 1 ~ The function to call is not itself an argument to the call.
12461   int arg_count = call->arguments()->length() - 1;
12462   DCHECK(arg_count >= 1);  // There's always at least a receiver.
12463
12464   CHECK_ALIVE(VisitExpressions(call->arguments()));
12465   // The function is the last argument
12466   HValue* function = Pop();
12467   // Push the arguments to the stack
12468   PushArgumentsFromEnvironment(arg_count);
12469
12470   IfBuilder if_is_jsfunction(this);
12471   if_is_jsfunction.If<HHasInstanceTypeAndBranch>(function, JS_FUNCTION_TYPE);
12472
12473   if_is_jsfunction.Then();
12474   {
12475     HInstruction* invoke_result =
12476         Add<HInvokeFunction>(function, arg_count);
12477     if (!ast_context()->IsEffect()) {
12478       Push(invoke_result);
12479     }
12480     Add<HSimulate>(call->id(), FIXED_SIMULATE);
12481   }
12482
12483   if_is_jsfunction.Else();
12484   {
12485     HInstruction* call_result =
12486         Add<HCallFunction>(function, arg_count);
12487     if (!ast_context()->IsEffect()) {
12488       Push(call_result);
12489     }
12490     Add<HSimulate>(call->id(), FIXED_SIMULATE);
12491   }
12492   if_is_jsfunction.End();
12493
12494   if (ast_context()->IsEffect()) {
12495     // EffectContext::ReturnValue ignores the value, so we can just pass
12496     // 'undefined' (as we do not have the call result anymore).
12497     return ast_context()->ReturnValue(graph()->GetConstantUndefined());
12498   } else {
12499     return ast_context()->ReturnValue(Pop());
12500   }
12501 }
12502
12503
12504 // Fast call to math functions.
12505 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) {
12506   DCHECK_EQ(2, call->arguments()->length());
12507   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12508   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12509   HValue* right = Pop();
12510   HValue* left = Pop();
12511   HInstruction* result = NewUncasted<HPower>(left, right);
12512   return ast_context()->ReturnInstruction(result, call->id());
12513 }
12514
12515
12516 void HOptimizedGraphBuilder::GenerateMathClz32(CallRuntime* call) {
12517   DCHECK(call->arguments()->length() == 1);
12518   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12519   HValue* value = Pop();
12520   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathClz32);
12521   return ast_context()->ReturnInstruction(result, call->id());
12522 }
12523
12524
12525 void HOptimizedGraphBuilder::GenerateMathFloor(CallRuntime* call) {
12526   DCHECK(call->arguments()->length() == 1);
12527   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12528   HValue* value = Pop();
12529   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathFloor);
12530   return ast_context()->ReturnInstruction(result, call->id());
12531 }
12532
12533
12534 void HOptimizedGraphBuilder::GenerateMathLogRT(CallRuntime* call) {
12535   DCHECK(call->arguments()->length() == 1);
12536   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12537   HValue* value = Pop();
12538   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathLog);
12539   return ast_context()->ReturnInstruction(result, call->id());
12540 }
12541
12542
12543 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
12544   DCHECK(call->arguments()->length() == 1);
12545   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12546   HValue* value = Pop();
12547   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt);
12548   return ast_context()->ReturnInstruction(result, call->id());
12549 }
12550
12551
12552 void HOptimizedGraphBuilder::GenerateLikely(CallRuntime* call) {
12553   DCHECK(call->arguments()->length() == 1);
12554   Visit(call->arguments()->at(0));
12555 }
12556
12557
12558 void HOptimizedGraphBuilder::GenerateUnlikely(CallRuntime* call) {
12559   return GenerateLikely(call);
12560 }
12561
12562
12563 void HOptimizedGraphBuilder::GenerateHasInPrototypeChain(CallRuntime* call) {
12564   DCHECK_EQ(2, call->arguments()->length());
12565   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12566   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12567   HValue* prototype = Pop();
12568   HValue* object = Pop();
12569   HHasInPrototypeChainAndBranch* result =
12570       New<HHasInPrototypeChainAndBranch>(object, prototype);
12571   return ast_context()->ReturnControl(result, call->id());
12572 }
12573
12574
12575 void HOptimizedGraphBuilder::GenerateFixedArrayGet(CallRuntime* call) {
12576   DCHECK(call->arguments()->length() == 2);
12577   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12578   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12579   HValue* index = Pop();
12580   HValue* object = Pop();
12581   HInstruction* result = New<HLoadKeyed>(
12582       object, index, nullptr, FAST_HOLEY_ELEMENTS, ALLOW_RETURN_HOLE);
12583   return ast_context()->ReturnInstruction(result, call->id());
12584 }
12585
12586
12587 void HOptimizedGraphBuilder::GenerateFixedArraySet(CallRuntime* call) {
12588   DCHECK(call->arguments()->length() == 3);
12589   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12590   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12591   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
12592   HValue* value = Pop();
12593   HValue* index = Pop();
12594   HValue* object = Pop();
12595   NoObservableSideEffectsScope no_effects(this);
12596   Add<HStoreKeyed>(object, index, value, FAST_HOLEY_ELEMENTS);
12597   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
12598 }
12599
12600
12601 void HOptimizedGraphBuilder::GenerateTheHole(CallRuntime* call) {
12602   DCHECK(call->arguments()->length() == 0);
12603   return ast_context()->ReturnValue(graph()->GetConstantHole());
12604 }
12605
12606
12607 void HOptimizedGraphBuilder::GenerateJSCollectionGetTable(CallRuntime* call) {
12608   DCHECK(call->arguments()->length() == 1);
12609   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12610   HValue* receiver = Pop();
12611   HInstruction* result = New<HLoadNamedField>(
12612       receiver, nullptr, HObjectAccess::ForJSCollectionTable());
12613   return ast_context()->ReturnInstruction(result, call->id());
12614 }
12615
12616
12617 void HOptimizedGraphBuilder::GenerateStringGetRawHashField(CallRuntime* call) {
12618   DCHECK(call->arguments()->length() == 1);
12619   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12620   HValue* object = Pop();
12621   HInstruction* result = New<HLoadNamedField>(
12622       object, nullptr, HObjectAccess::ForStringHashField());
12623   return ast_context()->ReturnInstruction(result, call->id());
12624 }
12625
12626
12627 template <typename CollectionType>
12628 HValue* HOptimizedGraphBuilder::BuildAllocateOrderedHashTable() {
12629   static const int kCapacity = CollectionType::kMinCapacity;
12630   static const int kBucketCount = kCapacity / CollectionType::kLoadFactor;
12631   static const int kFixedArrayLength = CollectionType::kHashTableStartIndex +
12632                                        kBucketCount +
12633                                        (kCapacity * CollectionType::kEntrySize);
12634   static const int kSizeInBytes =
12635       FixedArray::kHeaderSize + (kFixedArrayLength * kPointerSize);
12636
12637   // Allocate the table and add the proper map.
12638   HValue* table =
12639       Add<HAllocate>(Add<HConstant>(kSizeInBytes), HType::HeapObject(),
12640                      NOT_TENURED, FIXED_ARRAY_TYPE);
12641   AddStoreMapConstant(table, isolate()->factory()->ordered_hash_table_map());
12642
12643   // Initialize the FixedArray...
12644   HValue* length = Add<HConstant>(kFixedArrayLength);
12645   Add<HStoreNamedField>(table, HObjectAccess::ForFixedArrayLength(), length);
12646
12647   // ...and the OrderedHashTable fields.
12648   Add<HStoreNamedField>(
12649       table,
12650       HObjectAccess::ForOrderedHashTableNumberOfBuckets<CollectionType>(),
12651       Add<HConstant>(kBucketCount));
12652   Add<HStoreNamedField>(
12653       table,
12654       HObjectAccess::ForOrderedHashTableNumberOfElements<CollectionType>(),
12655       graph()->GetConstant0());
12656   Add<HStoreNamedField>(
12657       table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
12658                  CollectionType>(),
12659       graph()->GetConstant0());
12660
12661   // Fill the buckets with kNotFound.
12662   HValue* not_found = Add<HConstant>(CollectionType::kNotFound);
12663   for (int i = 0; i < kBucketCount; ++i) {
12664     Add<HStoreNamedField>(
12665         table, HObjectAccess::ForOrderedHashTableBucket<CollectionType>(i),
12666         not_found);
12667   }
12668
12669   // Fill the data table with undefined.
12670   HValue* undefined = graph()->GetConstantUndefined();
12671   for (int i = 0; i < (kCapacity * CollectionType::kEntrySize); ++i) {
12672     Add<HStoreNamedField>(table,
12673                           HObjectAccess::ForOrderedHashTableDataTableIndex<
12674                               CollectionType, kBucketCount>(i),
12675                           undefined);
12676   }
12677
12678   return table;
12679 }
12680
12681
12682 void HOptimizedGraphBuilder::GenerateSetInitialize(CallRuntime* call) {
12683   DCHECK(call->arguments()->length() == 1);
12684   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12685   HValue* receiver = Pop();
12686
12687   NoObservableSideEffectsScope no_effects(this);
12688   HValue* table = BuildAllocateOrderedHashTable<OrderedHashSet>();
12689   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(), table);
12690   return ast_context()->ReturnValue(receiver);
12691 }
12692
12693
12694 void HOptimizedGraphBuilder::GenerateMapInitialize(CallRuntime* call) {
12695   DCHECK(call->arguments()->length() == 1);
12696   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12697   HValue* receiver = Pop();
12698
12699   NoObservableSideEffectsScope no_effects(this);
12700   HValue* table = BuildAllocateOrderedHashTable<OrderedHashMap>();
12701   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(), table);
12702   return ast_context()->ReturnValue(receiver);
12703 }
12704
12705
12706 template <typename CollectionType>
12707 void HOptimizedGraphBuilder::BuildOrderedHashTableClear(HValue* receiver) {
12708   HValue* old_table = Add<HLoadNamedField>(
12709       receiver, nullptr, HObjectAccess::ForJSCollectionTable());
12710   HValue* new_table = BuildAllocateOrderedHashTable<CollectionType>();
12711   Add<HStoreNamedField>(
12712       old_table, HObjectAccess::ForOrderedHashTableNextTable<CollectionType>(),
12713       new_table);
12714   Add<HStoreNamedField>(
12715       old_table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
12716                      CollectionType>(),
12717       Add<HConstant>(CollectionType::kClearedTableSentinel));
12718   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(),
12719                         new_table);
12720 }
12721
12722
12723 void HOptimizedGraphBuilder::GenerateSetClear(CallRuntime* call) {
12724   DCHECK(call->arguments()->length() == 1);
12725   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12726   HValue* receiver = Pop();
12727
12728   NoObservableSideEffectsScope no_effects(this);
12729   BuildOrderedHashTableClear<OrderedHashSet>(receiver);
12730   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
12731 }
12732
12733
12734 void HOptimizedGraphBuilder::GenerateMapClear(CallRuntime* call) {
12735   DCHECK(call->arguments()->length() == 1);
12736   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12737   HValue* receiver = Pop();
12738
12739   NoObservableSideEffectsScope no_effects(this);
12740   BuildOrderedHashTableClear<OrderedHashMap>(receiver);
12741   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
12742 }
12743
12744
12745 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
12746   DCHECK(call->arguments()->length() == 1);
12747   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12748   HValue* value = Pop();
12749   HGetCachedArrayIndex* result = New<HGetCachedArrayIndex>(value);
12750   return ast_context()->ReturnInstruction(result, call->id());
12751 }
12752
12753
12754 void HOptimizedGraphBuilder::GenerateFastOneByteArrayJoin(CallRuntime* call) {
12755   // Simply returning undefined here would be semantically correct and even
12756   // avoid the bailout. Nevertheless, some ancient benchmarks like SunSpider's
12757   // string-fasta would tank, because fullcode contains an optimized version.
12758   // Obviously the fullcode => Crankshaft => bailout => fullcode dance is
12759   // faster... *sigh*
12760   return Bailout(kInlinedRuntimeFunctionFastOneByteArrayJoin);
12761 }
12762
12763
12764 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode(
12765     CallRuntime* call) {
12766   Add<HDebugBreak>();
12767   return ast_context()->ReturnValue(graph()->GetConstant0());
12768 }
12769
12770
12771 void HOptimizedGraphBuilder::GenerateDebugIsActive(CallRuntime* call) {
12772   DCHECK(call->arguments()->length() == 0);
12773   HValue* ref =
12774       Add<HConstant>(ExternalReference::debug_is_active_address(isolate()));
12775   HValue* value =
12776       Add<HLoadNamedField>(ref, nullptr, HObjectAccess::ForExternalUInteger8());
12777   return ast_context()->ReturnValue(value);
12778 }
12779
12780
12781 void HOptimizedGraphBuilder::GenerateGetPrototype(CallRuntime* call) {
12782   DCHECK(call->arguments()->length() == 1);
12783   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12784   HValue* object = Pop();
12785
12786   NoObservableSideEffectsScope no_effects(this);
12787
12788   HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap());
12789   HValue* bit_field =
12790       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField());
12791   HValue* is_access_check_needed_mask =
12792       Add<HConstant>(1 << Map::kIsAccessCheckNeeded);
12793   HValue* is_access_check_needed_test = AddUncasted<HBitwise>(
12794       Token::BIT_AND, bit_field, is_access_check_needed_mask);
12795
12796   HValue* proto =
12797       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForPrototype());
12798   HValue* proto_map =
12799       Add<HLoadNamedField>(proto, nullptr, HObjectAccess::ForMap());
12800   HValue* proto_bit_field =
12801       Add<HLoadNamedField>(proto_map, nullptr, HObjectAccess::ForMapBitField());
12802   HValue* is_hidden_prototype_mask =
12803       Add<HConstant>(1 << Map::kIsHiddenPrototype);
12804   HValue* is_hidden_prototype_test = AddUncasted<HBitwise>(
12805       Token::BIT_AND, proto_bit_field, is_hidden_prototype_mask);
12806
12807   {
12808     IfBuilder needs_runtime(this);
12809     needs_runtime.If<HCompareNumericAndBranch>(
12810         is_access_check_needed_test, graph()->GetConstant0(), Token::NE);
12811     needs_runtime.OrIf<HCompareNumericAndBranch>(
12812         is_hidden_prototype_test, graph()->GetConstant0(), Token::NE);
12813
12814     needs_runtime.Then();
12815     {
12816       Add<HPushArguments>(object);
12817       Push(Add<HCallRuntime>(
12818           call->name(), Runtime::FunctionForId(Runtime::kGetPrototype), 1));
12819     }
12820
12821     needs_runtime.Else();
12822     Push(proto);
12823   }
12824   return ast_context()->ReturnValue(Pop());
12825 }
12826
12827
12828 #undef CHECK_BAILOUT
12829 #undef CHECK_ALIVE
12830
12831
12832 HEnvironment::HEnvironment(HEnvironment* outer,
12833                            Scope* scope,
12834                            Handle<JSFunction> closure,
12835                            Zone* zone)
12836     : closure_(closure),
12837       values_(0, zone),
12838       frame_type_(JS_FUNCTION),
12839       parameter_count_(0),
12840       specials_count_(1),
12841       local_count_(0),
12842       outer_(outer),
12843       entry_(NULL),
12844       pop_count_(0),
12845       push_count_(0),
12846       ast_id_(BailoutId::None()),
12847       zone_(zone) {
12848   Scope* declaration_scope = scope->DeclarationScope();
12849   Initialize(declaration_scope->num_parameters() + 1,
12850              declaration_scope->num_stack_slots(), 0);
12851 }
12852
12853
12854 HEnvironment::HEnvironment(Zone* zone, int parameter_count)
12855     : values_(0, zone),
12856       frame_type_(STUB),
12857       parameter_count_(parameter_count),
12858       specials_count_(1),
12859       local_count_(0),
12860       outer_(NULL),
12861       entry_(NULL),
12862       pop_count_(0),
12863       push_count_(0),
12864       ast_id_(BailoutId::None()),
12865       zone_(zone) {
12866   Initialize(parameter_count, 0, 0);
12867 }
12868
12869
12870 HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone)
12871     : values_(0, zone),
12872       frame_type_(JS_FUNCTION),
12873       parameter_count_(0),
12874       specials_count_(0),
12875       local_count_(0),
12876       outer_(NULL),
12877       entry_(NULL),
12878       pop_count_(0),
12879       push_count_(0),
12880       ast_id_(other->ast_id()),
12881       zone_(zone) {
12882   Initialize(other);
12883 }
12884
12885
12886 HEnvironment::HEnvironment(HEnvironment* outer,
12887                            Handle<JSFunction> closure,
12888                            FrameType frame_type,
12889                            int arguments,
12890                            Zone* zone)
12891     : closure_(closure),
12892       values_(arguments, zone),
12893       frame_type_(frame_type),
12894       parameter_count_(arguments),
12895       specials_count_(0),
12896       local_count_(0),
12897       outer_(outer),
12898       entry_(NULL),
12899       pop_count_(0),
12900       push_count_(0),
12901       ast_id_(BailoutId::None()),
12902       zone_(zone) {
12903 }
12904
12905
12906 void HEnvironment::Initialize(int parameter_count,
12907                               int local_count,
12908                               int stack_height) {
12909   parameter_count_ = parameter_count;
12910   local_count_ = local_count;
12911
12912   // Avoid reallocating the temporaries' backing store on the first Push.
12913   int total = parameter_count + specials_count_ + local_count + stack_height;
12914   values_.Initialize(total + 4, zone());
12915   for (int i = 0; i < total; ++i) values_.Add(NULL, zone());
12916 }
12917
12918
12919 void HEnvironment::Initialize(const HEnvironment* other) {
12920   closure_ = other->closure();
12921   values_.AddAll(other->values_, zone());
12922   assigned_variables_.Union(other->assigned_variables_, zone());
12923   frame_type_ = other->frame_type_;
12924   parameter_count_ = other->parameter_count_;
12925   local_count_ = other->local_count_;
12926   if (other->outer_ != NULL) outer_ = other->outer_->Copy();  // Deep copy.
12927   entry_ = other->entry_;
12928   pop_count_ = other->pop_count_;
12929   push_count_ = other->push_count_;
12930   specials_count_ = other->specials_count_;
12931   ast_id_ = other->ast_id_;
12932 }
12933
12934
12935 void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
12936   DCHECK(!block->IsLoopHeader());
12937   DCHECK(values_.length() == other->values_.length());
12938
12939   int length = values_.length();
12940   for (int i = 0; i < length; ++i) {
12941     HValue* value = values_[i];
12942     if (value != NULL && value->IsPhi() && value->block() == block) {
12943       // There is already a phi for the i'th value.
12944       HPhi* phi = HPhi::cast(value);
12945       // Assert index is correct and that we haven't missed an incoming edge.
12946       DCHECK(phi->merged_index() == i || !phi->HasMergedIndex());
12947       DCHECK(phi->OperandCount() == block->predecessors()->length());
12948       phi->AddInput(other->values_[i]);
12949     } else if (values_[i] != other->values_[i]) {
12950       // There is a fresh value on the incoming edge, a phi is needed.
12951       DCHECK(values_[i] != NULL && other->values_[i] != NULL);
12952       HPhi* phi = block->AddNewPhi(i);
12953       HValue* old_value = values_[i];
12954       for (int j = 0; j < block->predecessors()->length(); j++) {
12955         phi->AddInput(old_value);
12956       }
12957       phi->AddInput(other->values_[i]);
12958       this->values_[i] = phi;
12959     }
12960   }
12961 }
12962
12963
12964 void HEnvironment::Bind(int index, HValue* value) {
12965   DCHECK(value != NULL);
12966   assigned_variables_.Add(index, zone());
12967   values_[index] = value;
12968 }
12969
12970
12971 bool HEnvironment::HasExpressionAt(int index) const {
12972   return index >= parameter_count_ + specials_count_ + local_count_;
12973 }
12974
12975
12976 bool HEnvironment::ExpressionStackIsEmpty() const {
12977   DCHECK(length() >= first_expression_index());
12978   return length() == first_expression_index();
12979 }
12980
12981
12982 void HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) {
12983   int count = index_from_top + 1;
12984   int index = values_.length() - count;
12985   DCHECK(HasExpressionAt(index));
12986   // The push count must include at least the element in question or else
12987   // the new value will not be included in this environment's history.
12988   if (push_count_ < count) {
12989     // This is the same effect as popping then re-pushing 'count' elements.
12990     pop_count_ += (count - push_count_);
12991     push_count_ = count;
12992   }
12993   values_[index] = value;
12994 }
12995
12996
12997 HValue* HEnvironment::RemoveExpressionStackAt(int index_from_top) {
12998   int count = index_from_top + 1;
12999   int index = values_.length() - count;
13000   DCHECK(HasExpressionAt(index));
13001   // Simulate popping 'count' elements and then
13002   // pushing 'count - 1' elements back.
13003   pop_count_ += Max(count - push_count_, 0);
13004   push_count_ = Max(push_count_ - count, 0) + (count - 1);
13005   return values_.Remove(index);
13006 }
13007
13008
13009 void HEnvironment::Drop(int count) {
13010   for (int i = 0; i < count; ++i) {
13011     Pop();
13012   }
13013 }
13014
13015
13016 HEnvironment* HEnvironment::Copy() const {
13017   return new(zone()) HEnvironment(this, zone());
13018 }
13019
13020
13021 HEnvironment* HEnvironment::CopyWithoutHistory() const {
13022   HEnvironment* result = Copy();
13023   result->ClearHistory();
13024   return result;
13025 }
13026
13027
13028 HEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const {
13029   HEnvironment* new_env = Copy();
13030   for (int i = 0; i < values_.length(); ++i) {
13031     HPhi* phi = loop_header->AddNewPhi(i);
13032     phi->AddInput(values_[i]);
13033     new_env->values_[i] = phi;
13034   }
13035   new_env->ClearHistory();
13036   return new_env;
13037 }
13038
13039
13040 HEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer,
13041                                                   Handle<JSFunction> target,
13042                                                   FrameType frame_type,
13043                                                   int arguments) const {
13044   HEnvironment* new_env =
13045       new(zone()) HEnvironment(outer, target, frame_type,
13046                                arguments + 1, zone());
13047   for (int i = 0; i <= arguments; ++i) {  // Include receiver.
13048     new_env->Push(ExpressionStackAt(arguments - i));
13049   }
13050   new_env->ClearHistory();
13051   return new_env;
13052 }
13053
13054
13055 HEnvironment* HEnvironment::CopyForInlining(
13056     Handle<JSFunction> target,
13057     int arguments,
13058     FunctionLiteral* function,
13059     HConstant* undefined,
13060     InliningKind inlining_kind) const {
13061   DCHECK(frame_type() == JS_FUNCTION);
13062
13063   // Outer environment is a copy of this one without the arguments.
13064   int arity = function->scope()->num_parameters();
13065
13066   HEnvironment* outer = Copy();
13067   outer->Drop(arguments + 1);  // Including receiver.
13068   outer->ClearHistory();
13069
13070   if (inlining_kind == CONSTRUCT_CALL_RETURN) {
13071     // Create artificial constructor stub environment.  The receiver should
13072     // actually be the constructor function, but we pass the newly allocated
13073     // object instead, DoComputeConstructStubFrame() relies on that.
13074     outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments);
13075   } else if (inlining_kind == GETTER_CALL_RETURN) {
13076     // We need an additional StackFrame::INTERNAL frame for restoring the
13077     // correct context.
13078     outer = CreateStubEnvironment(outer, target, JS_GETTER, arguments);
13079   } else if (inlining_kind == SETTER_CALL_RETURN) {
13080     // We need an additional StackFrame::INTERNAL frame for temporarily saving
13081     // the argument of the setter, see StoreStubCompiler::CompileStoreViaSetter.
13082     outer = CreateStubEnvironment(outer, target, JS_SETTER, arguments);
13083   }
13084
13085   if (arity != arguments) {
13086     // Create artificial arguments adaptation environment.
13087     outer = CreateStubEnvironment(outer, target, ARGUMENTS_ADAPTOR, arguments);
13088   }
13089
13090   HEnvironment* inner =
13091       new(zone()) HEnvironment(outer, function->scope(), target, zone());
13092   // Get the argument values from the original environment.
13093   for (int i = 0; i <= arity; ++i) {  // Include receiver.
13094     HValue* push = (i <= arguments) ?
13095         ExpressionStackAt(arguments - i) : undefined;
13096     inner->SetValueAt(i, push);
13097   }
13098   inner->SetValueAt(arity + 1, context());
13099   for (int i = arity + 2; i < inner->length(); ++i) {
13100     inner->SetValueAt(i, undefined);
13101   }
13102
13103   inner->set_ast_id(BailoutId::FunctionEntry());
13104   return inner;
13105 }
13106
13107
13108 std::ostream& operator<<(std::ostream& os, const HEnvironment& env) {
13109   for (int i = 0; i < env.length(); i++) {
13110     if (i == 0) os << "parameters\n";
13111     if (i == env.parameter_count()) os << "specials\n";
13112     if (i == env.parameter_count() + env.specials_count()) os << "locals\n";
13113     if (i == env.parameter_count() + env.specials_count() + env.local_count()) {
13114       os << "expressions\n";
13115     }
13116     HValue* val = env.values()->at(i);
13117     os << i << ": ";
13118     if (val != NULL) {
13119       os << val;
13120     } else {
13121       os << "NULL";
13122     }
13123     os << "\n";
13124   }
13125   return os << "\n";
13126 }
13127
13128
13129 void HTracer::TraceCompilation(CompilationInfo* info) {
13130   Tag tag(this, "compilation");
13131   base::SmartArrayPointer<char> name = info->GetDebugName();
13132   if (info->IsOptimizing()) {
13133     PrintStringProperty("name", name.get());
13134     PrintIndent();
13135     trace_.Add("method \"%s:%d\"\n", name.get(), info->optimization_id());
13136   } else {
13137     PrintStringProperty("name", name.get());
13138     PrintStringProperty("method", "stub");
13139   }
13140   PrintLongProperty("date",
13141                     static_cast<int64_t>(base::OS::TimeCurrentMillis()));
13142 }
13143
13144
13145 void HTracer::TraceLithium(const char* name, LChunk* chunk) {
13146   DCHECK(!chunk->isolate()->concurrent_recompilation_enabled());
13147   AllowHandleDereference allow_deref;
13148   AllowDeferredHandleDereference allow_deferred_deref;
13149   Trace(name, chunk->graph(), chunk);
13150 }
13151
13152
13153 void HTracer::TraceHydrogen(const char* name, HGraph* graph) {
13154   DCHECK(!graph->isolate()->concurrent_recompilation_enabled());
13155   AllowHandleDereference allow_deref;
13156   AllowDeferredHandleDereference allow_deferred_deref;
13157   Trace(name, graph, NULL);
13158 }
13159
13160
13161 void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
13162   Tag tag(this, "cfg");
13163   PrintStringProperty("name", name);
13164   const ZoneList<HBasicBlock*>* blocks = graph->blocks();
13165   for (int i = 0; i < blocks->length(); i++) {
13166     HBasicBlock* current = blocks->at(i);
13167     Tag block_tag(this, "block");
13168     PrintBlockProperty("name", current->block_id());
13169     PrintIntProperty("from_bci", -1);
13170     PrintIntProperty("to_bci", -1);
13171
13172     if (!current->predecessors()->is_empty()) {
13173       PrintIndent();
13174       trace_.Add("predecessors");
13175       for (int j = 0; j < current->predecessors()->length(); ++j) {
13176         trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id());
13177       }
13178       trace_.Add("\n");
13179     } else {
13180       PrintEmptyProperty("predecessors");
13181     }
13182
13183     if (current->end()->SuccessorCount() == 0) {
13184       PrintEmptyProperty("successors");
13185     } else  {
13186       PrintIndent();
13187       trace_.Add("successors");
13188       for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) {
13189         trace_.Add(" \"B%d\"", it.Current()->block_id());
13190       }
13191       trace_.Add("\n");
13192     }
13193
13194     PrintEmptyProperty("xhandlers");
13195
13196     {
13197       PrintIndent();
13198       trace_.Add("flags");
13199       if (current->IsLoopSuccessorDominator()) {
13200         trace_.Add(" \"dom-loop-succ\"");
13201       }
13202       if (current->IsUnreachable()) {
13203         trace_.Add(" \"dead\"");
13204       }
13205       if (current->is_osr_entry()) {
13206         trace_.Add(" \"osr\"");
13207       }
13208       trace_.Add("\n");
13209     }
13210
13211     if (current->dominator() != NULL) {
13212       PrintBlockProperty("dominator", current->dominator()->block_id());
13213     }
13214
13215     PrintIntProperty("loop_depth", current->LoopNestingDepth());
13216
13217     if (chunk != NULL) {
13218       int first_index = current->first_instruction_index();
13219       int last_index = current->last_instruction_index();
13220       PrintIntProperty(
13221           "first_lir_id",
13222           LifetimePosition::FromInstructionIndex(first_index).Value());
13223       PrintIntProperty(
13224           "last_lir_id",
13225           LifetimePosition::FromInstructionIndex(last_index).Value());
13226     }
13227
13228     {
13229       Tag states_tag(this, "states");
13230       Tag locals_tag(this, "locals");
13231       int total = current->phis()->length();
13232       PrintIntProperty("size", current->phis()->length());
13233       PrintStringProperty("method", "None");
13234       for (int j = 0; j < total; ++j) {
13235         HPhi* phi = current->phis()->at(j);
13236         PrintIndent();
13237         std::ostringstream os;
13238         os << phi->merged_index() << " " << NameOf(phi) << " " << *phi << "\n";
13239         trace_.Add(os.str().c_str());
13240       }
13241     }
13242
13243     {
13244       Tag HIR_tag(this, "HIR");
13245       for (HInstructionIterator it(current); !it.Done(); it.Advance()) {
13246         HInstruction* instruction = it.Current();
13247         int uses = instruction->UseCount();
13248         PrintIndent();
13249         std::ostringstream os;
13250         os << "0 " << uses << " " << NameOf(instruction) << " " << *instruction;
13251         if (graph->info()->is_tracking_positions() &&
13252             instruction->has_position() && instruction->position().raw() != 0) {
13253           const SourcePosition pos = instruction->position();
13254           os << " pos:";
13255           if (pos.inlining_id() != 0) os << pos.inlining_id() << "_";
13256           os << pos.position();
13257         }
13258         os << " <|@\n";
13259         trace_.Add(os.str().c_str());
13260       }
13261     }
13262
13263
13264     if (chunk != NULL) {
13265       Tag LIR_tag(this, "LIR");
13266       int first_index = current->first_instruction_index();
13267       int last_index = current->last_instruction_index();
13268       if (first_index != -1 && last_index != -1) {
13269         const ZoneList<LInstruction*>* instructions = chunk->instructions();
13270         for (int i = first_index; i <= last_index; ++i) {
13271           LInstruction* linstr = instructions->at(i);
13272           if (linstr != NULL) {
13273             PrintIndent();
13274             trace_.Add("%d ",
13275                        LifetimePosition::FromInstructionIndex(i).Value());
13276             linstr->PrintTo(&trace_);
13277             std::ostringstream os;
13278             os << " [hir:" << NameOf(linstr->hydrogen_value()) << "] <|@\n";
13279             trace_.Add(os.str().c_str());
13280           }
13281         }
13282       }
13283     }
13284   }
13285 }
13286
13287
13288 void HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) {
13289   Tag tag(this, "intervals");
13290   PrintStringProperty("name", name);
13291
13292   const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
13293   for (int i = 0; i < fixed_d->length(); ++i) {
13294     TraceLiveRange(fixed_d->at(i), "fixed", allocator->zone());
13295   }
13296
13297   const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges();
13298   for (int i = 0; i < fixed->length(); ++i) {
13299     TraceLiveRange(fixed->at(i), "fixed", allocator->zone());
13300   }
13301
13302   const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges();
13303   for (int i = 0; i < live_ranges->length(); ++i) {
13304     TraceLiveRange(live_ranges->at(i), "object", allocator->zone());
13305   }
13306 }
13307
13308
13309 void HTracer::TraceLiveRange(LiveRange* range, const char* type,
13310                              Zone* zone) {
13311   if (range != NULL && !range->IsEmpty()) {
13312     PrintIndent();
13313     trace_.Add("%d %s", range->id(), type);
13314     if (range->HasRegisterAssigned()) {
13315       LOperand* op = range->CreateAssignedOperand(zone);
13316       int assigned_reg = op->index();
13317       if (op->IsDoubleRegister()) {
13318         trace_.Add(" \"%s\"",
13319                    DoubleRegister::AllocationIndexToString(assigned_reg));
13320       } else {
13321         DCHECK(op->IsRegister());
13322         trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg));
13323       }
13324     } else if (range->IsSpilled()) {
13325       LOperand* op = range->TopLevel()->GetSpillOperand();
13326       if (op->IsDoubleStackSlot()) {
13327         trace_.Add(" \"double_stack:%d\"", op->index());
13328       } else {
13329         DCHECK(op->IsStackSlot());
13330         trace_.Add(" \"stack:%d\"", op->index());
13331       }
13332     }
13333     int parent_index = -1;
13334     if (range->IsChild()) {
13335       parent_index = range->parent()->id();
13336     } else {
13337       parent_index = range->id();
13338     }
13339     LOperand* op = range->FirstHint();
13340     int hint_index = -1;
13341     if (op != NULL && op->IsUnallocated()) {
13342       hint_index = LUnallocated::cast(op)->virtual_register();
13343     }
13344     trace_.Add(" %d %d", parent_index, hint_index);
13345     UseInterval* cur_interval = range->first_interval();
13346     while (cur_interval != NULL && range->Covers(cur_interval->start())) {
13347       trace_.Add(" [%d, %d[",
13348                  cur_interval->start().Value(),
13349                  cur_interval->end().Value());
13350       cur_interval = cur_interval->next();
13351     }
13352
13353     UsePosition* current_pos = range->first_pos();
13354     while (current_pos != NULL) {
13355       if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
13356         trace_.Add(" %d M", current_pos->pos().Value());
13357       }
13358       current_pos = current_pos->next();
13359     }
13360
13361     trace_.Add(" \"\"\n");
13362   }
13363 }
13364
13365
13366 void HTracer::FlushToFile() {
13367   AppendChars(filename_.start(), trace_.ToCString().get(), trace_.length(),
13368               false);
13369   trace_.Reset();
13370 }
13371
13372
13373 void HStatistics::Initialize(CompilationInfo* info) {
13374   if (info->shared_info().is_null()) return;
13375   source_size_ += info->shared_info()->SourceSize();
13376 }
13377
13378
13379 void HStatistics::Print() {
13380   PrintF(
13381       "\n"
13382       "----------------------------------------"
13383       "----------------------------------------\n"
13384       "--- Hydrogen timing results:\n"
13385       "----------------------------------------"
13386       "----------------------------------------\n");
13387   base::TimeDelta sum;
13388   for (int i = 0; i < times_.length(); ++i) {
13389     sum += times_[i];
13390   }
13391
13392   for (int i = 0; i < names_.length(); ++i) {
13393     PrintF("%33s", names_[i]);
13394     double ms = times_[i].InMillisecondsF();
13395     double percent = times_[i].PercentOf(sum);
13396     PrintF(" %8.3f ms / %4.1f %% ", ms, percent);
13397
13398     size_t size = sizes_[i];
13399     double size_percent = static_cast<double>(size) * 100 / total_size_;
13400     PrintF(" %9zu bytes / %4.1f %%\n", size, size_percent);
13401   }
13402
13403   PrintF(
13404       "----------------------------------------"
13405       "----------------------------------------\n");
13406   base::TimeDelta total = create_graph_ + optimize_graph_ + generate_code_;
13407   PrintF("%33s %8.3f ms / %4.1f %% \n", "Create graph",
13408          create_graph_.InMillisecondsF(), create_graph_.PercentOf(total));
13409   PrintF("%33s %8.3f ms / %4.1f %% \n", "Optimize graph",
13410          optimize_graph_.InMillisecondsF(), optimize_graph_.PercentOf(total));
13411   PrintF("%33s %8.3f ms / %4.1f %% \n", "Generate and install code",
13412          generate_code_.InMillisecondsF(), generate_code_.PercentOf(total));
13413   PrintF(
13414       "----------------------------------------"
13415       "----------------------------------------\n");
13416   PrintF("%33s %8.3f ms           %9zu bytes\n", "Total",
13417          total.InMillisecondsF(), total_size_);
13418   PrintF("%33s     (%.1f times slower than full code gen)\n", "",
13419          total.TimesOf(full_code_gen_));
13420
13421   double source_size_in_kb = static_cast<double>(source_size_) / 1024;
13422   double normalized_time =  source_size_in_kb > 0
13423       ? total.InMillisecondsF() / source_size_in_kb
13424       : 0;
13425   double normalized_size_in_kb =
13426       source_size_in_kb > 0
13427           ? static_cast<double>(total_size_) / 1024 / source_size_in_kb
13428           : 0;
13429   PrintF("%33s %8.3f ms           %7.3f kB allocated\n",
13430          "Average per kB source", normalized_time, normalized_size_in_kb);
13431 }
13432
13433
13434 void HStatistics::SaveTiming(const char* name, base::TimeDelta time,
13435                              size_t size) {
13436   total_size_ += size;
13437   for (int i = 0; i < names_.length(); ++i) {
13438     if (strcmp(names_[i], name) == 0) {
13439       times_[i] += time;
13440       sizes_[i] += size;
13441       return;
13442     }
13443   }
13444   names_.Add(name);
13445   times_.Add(time);
13446   sizes_.Add(size);
13447 }
13448
13449
13450 HPhase::~HPhase() {
13451   if (ShouldProduceTraceOutput()) {
13452     isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
13453   }
13454
13455 #ifdef DEBUG
13456   graph_->Verify(false);  // No full verify.
13457 #endif
13458 }
13459
13460 }  // namespace internal
13461 }  // namespace v8