[ic] Also collect known map for relational comparison.
[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/isolate-inl.h"
39 #include "src/lithium-allocator.h"
40 #include "src/parser.h"
41 #include "src/runtime/runtime.h"
42 #include "src/scopeinfo.h"
43 #include "src/typing.h"
44
45 #if V8_TARGET_ARCH_IA32
46 #include "src/ia32/lithium-codegen-ia32.h"  // NOLINT
47 #elif V8_TARGET_ARCH_X64
48 #include "src/x64/lithium-codegen-x64.h"  // NOLINT
49 #elif V8_TARGET_ARCH_ARM64
50 #include "src/arm64/lithium-codegen-arm64.h"  // NOLINT
51 #elif V8_TARGET_ARCH_ARM
52 #include "src/arm/lithium-codegen-arm.h"  // NOLINT
53 #elif V8_TARGET_ARCH_PPC
54 #include "src/ppc/lithium-codegen-ppc.h"  // NOLINT
55 #elif V8_TARGET_ARCH_MIPS
56 #include "src/mips/lithium-codegen-mips.h"  // NOLINT
57 #elif V8_TARGET_ARCH_MIPS64
58 #include "src/mips64/lithium-codegen-mips64.h"  // NOLINT
59 #elif V8_TARGET_ARCH_X87
60 #include "src/x87/lithium-codegen-x87.h"  // NOLINT
61 #else
62 #error Unsupported target architecture.
63 #endif
64
65 namespace v8 {
66 namespace internal {
67
68 HBasicBlock::HBasicBlock(HGraph* graph)
69     : block_id_(graph->GetNextBlockID()),
70       graph_(graph),
71       phis_(4, graph->zone()),
72       first_(NULL),
73       last_(NULL),
74       end_(NULL),
75       loop_information_(NULL),
76       predecessors_(2, graph->zone()),
77       dominator_(NULL),
78       dominated_blocks_(4, graph->zone()),
79       last_environment_(NULL),
80       argument_count_(-1),
81       first_instruction_index_(-1),
82       last_instruction_index_(-1),
83       deleted_phis_(4, graph->zone()),
84       parent_loop_header_(NULL),
85       inlined_entry_block_(NULL),
86       is_inline_return_target_(false),
87       is_reachable_(true),
88       dominates_loop_successors_(false),
89       is_osr_entry_(false),
90       is_ordered_(false) { }
91
92
93 Isolate* HBasicBlock::isolate() const {
94   return graph_->isolate();
95 }
96
97
98 void HBasicBlock::MarkUnreachable() {
99   is_reachable_ = false;
100 }
101
102
103 void HBasicBlock::AttachLoopInformation() {
104   DCHECK(!IsLoopHeader());
105   loop_information_ = new(zone()) HLoopInformation(this, zone());
106 }
107
108
109 void HBasicBlock::DetachLoopInformation() {
110   DCHECK(IsLoopHeader());
111   loop_information_ = NULL;
112 }
113
114
115 void HBasicBlock::AddPhi(HPhi* phi) {
116   DCHECK(!IsStartBlock());
117   phis_.Add(phi, zone());
118   phi->SetBlock(this);
119 }
120
121
122 void HBasicBlock::RemovePhi(HPhi* phi) {
123   DCHECK(phi->block() == this);
124   DCHECK(phis_.Contains(phi));
125   phi->Kill();
126   phis_.RemoveElement(phi);
127   phi->SetBlock(NULL);
128 }
129
130
131 void HBasicBlock::AddInstruction(HInstruction* instr, SourcePosition position) {
132   DCHECK(!IsStartBlock() || !IsFinished());
133   DCHECK(!instr->IsLinked());
134   DCHECK(!IsFinished());
135
136   if (!position.IsUnknown()) {
137     instr->set_position(position);
138   }
139   if (first_ == NULL) {
140     DCHECK(last_environment() != NULL);
141     DCHECK(!last_environment()->ast_id().IsNone());
142     HBlockEntry* entry = new(zone()) HBlockEntry();
143     entry->InitializeAsFirst(this);
144     if (!position.IsUnknown()) {
145       entry->set_position(position);
146     } else {
147       DCHECK(!FLAG_hydrogen_track_positions ||
148              !graph()->info()->IsOptimizing() || instr->IsAbnormalExit());
149     }
150     first_ = last_ = entry;
151   }
152   instr->InsertAfter(last_);
153 }
154
155
156 HPhi* HBasicBlock::AddNewPhi(int merged_index) {
157   if (graph()->IsInsideNoSideEffectsScope()) {
158     merged_index = HPhi::kInvalidMergedIndex;
159   }
160   HPhi* phi = new(zone()) HPhi(merged_index, zone());
161   AddPhi(phi);
162   return phi;
163 }
164
165
166 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id,
167                                        RemovableSimulate removable) {
168   DCHECK(HasEnvironment());
169   HEnvironment* environment = last_environment();
170   DCHECK(ast_id.IsNone() ||
171          ast_id == BailoutId::StubEntry() ||
172          environment->closure()->shared()->VerifyBailoutId(ast_id));
173
174   int push_count = environment->push_count();
175   int pop_count = environment->pop_count();
176
177   HSimulate* instr =
178       new(zone()) HSimulate(ast_id, pop_count, zone(), removable);
179 #ifdef DEBUG
180   instr->set_closure(environment->closure());
181 #endif
182   // Order of pushed values: newest (top of stack) first. This allows
183   // HSimulate::MergeWith() to easily append additional pushed values
184   // that are older (from further down the stack).
185   for (int i = 0; i < push_count; ++i) {
186     instr->AddPushedValue(environment->ExpressionStackAt(i));
187   }
188   for (GrowableBitVector::Iterator it(environment->assigned_variables(),
189                                       zone());
190        !it.Done();
191        it.Advance()) {
192     int index = it.Current();
193     instr->AddAssignedValue(index, environment->Lookup(index));
194   }
195   environment->ClearHistory();
196   return instr;
197 }
198
199
200 void HBasicBlock::Finish(HControlInstruction* end, SourcePosition position) {
201   DCHECK(!IsFinished());
202   AddInstruction(end, position);
203   end_ = end;
204   for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
205     it.Current()->RegisterPredecessor(this);
206   }
207 }
208
209
210 void HBasicBlock::Goto(HBasicBlock* block, SourcePosition position,
211                        FunctionState* state, bool add_simulate) {
212   bool drop_extra = state != NULL &&
213       state->inlining_kind() == NORMAL_RETURN;
214
215   if (block->IsInlineReturnTarget()) {
216     HEnvironment* env = last_environment();
217     int argument_count = env->arguments_environment()->parameter_count();
218     AddInstruction(new(zone())
219                    HLeaveInlined(state->entry(), argument_count),
220                    position);
221     UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
222   }
223
224   if (add_simulate) AddNewSimulate(BailoutId::None(), position);
225   HGoto* instr = new(zone()) HGoto(block);
226   Finish(instr, position);
227 }
228
229
230 void HBasicBlock::AddLeaveInlined(HValue* return_value, FunctionState* state,
231                                   SourcePosition position) {
232   HBasicBlock* target = state->function_return();
233   bool drop_extra = state->inlining_kind() == NORMAL_RETURN;
234
235   DCHECK(target->IsInlineReturnTarget());
236   DCHECK(return_value != NULL);
237   HEnvironment* env = last_environment();
238   int argument_count = env->arguments_environment()->parameter_count();
239   AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count),
240                  position);
241   UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
242   last_environment()->Push(return_value);
243   AddNewSimulate(BailoutId::None(), position);
244   HGoto* instr = new(zone()) HGoto(target);
245   Finish(instr, position);
246 }
247
248
249 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
250   DCHECK(!HasEnvironment());
251   DCHECK(first() == NULL);
252   UpdateEnvironment(env);
253 }
254
255
256 void HBasicBlock::UpdateEnvironment(HEnvironment* env) {
257   last_environment_ = env;
258   graph()->update_maximum_environment_size(env->first_expression_index());
259 }
260
261
262 void HBasicBlock::SetJoinId(BailoutId ast_id) {
263   int length = predecessors_.length();
264   DCHECK(length > 0);
265   for (int i = 0; i < length; i++) {
266     HBasicBlock* predecessor = predecessors_[i];
267     DCHECK(predecessor->end()->IsGoto());
268     HSimulate* simulate = HSimulate::cast(predecessor->end()->previous());
269     DCHECK(i != 0 ||
270            (predecessor->last_environment()->closure().is_null() ||
271             predecessor->last_environment()->closure()->shared()
272               ->VerifyBailoutId(ast_id)));
273     simulate->set_ast_id(ast_id);
274     predecessor->last_environment()->set_ast_id(ast_id);
275   }
276 }
277
278
279 bool HBasicBlock::Dominates(HBasicBlock* other) const {
280   HBasicBlock* current = other->dominator();
281   while (current != NULL) {
282     if (current == this) return true;
283     current = current->dominator();
284   }
285   return false;
286 }
287
288
289 bool HBasicBlock::EqualToOrDominates(HBasicBlock* other) const {
290   if (this == other) return true;
291   return Dominates(other);
292 }
293
294
295 int HBasicBlock::LoopNestingDepth() const {
296   const HBasicBlock* current = this;
297   int result  = (current->IsLoopHeader()) ? 1 : 0;
298   while (current->parent_loop_header() != NULL) {
299     current = current->parent_loop_header();
300     result++;
301   }
302   return result;
303 }
304
305
306 void HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) {
307   DCHECK(IsLoopHeader());
308
309   SetJoinId(stmt->EntryId());
310   if (predecessors()->length() == 1) {
311     // This is a degenerated loop.
312     DetachLoopInformation();
313     return;
314   }
315
316   // Only the first entry into the loop is from outside the loop. All other
317   // entries must be back edges.
318   for (int i = 1; i < predecessors()->length(); ++i) {
319     loop_information()->RegisterBackEdge(predecessors()->at(i));
320   }
321 }
322
323
324 void HBasicBlock::MarkSuccEdgeUnreachable(int succ) {
325   DCHECK(IsFinished());
326   HBasicBlock* succ_block = end()->SuccessorAt(succ);
327
328   DCHECK(succ_block->predecessors()->length() == 1);
329   succ_block->MarkUnreachable();
330 }
331
332
333 void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
334   if (HasPredecessor()) {
335     // Only loop header blocks can have a predecessor added after
336     // instructions have been added to the block (they have phis for all
337     // values in the environment, these phis may be eliminated later).
338     DCHECK(IsLoopHeader() || first_ == NULL);
339     HEnvironment* incoming_env = pred->last_environment();
340     if (IsLoopHeader()) {
341       DCHECK_EQ(phis()->length(), incoming_env->length());
342       for (int i = 0; i < phis_.length(); ++i) {
343         phis_[i]->AddInput(incoming_env->values()->at(i));
344       }
345     } else {
346       last_environment()->AddIncomingEdge(this, pred->last_environment());
347     }
348   } else if (!HasEnvironment() && !IsFinished()) {
349     DCHECK(!IsLoopHeader());
350     SetInitialEnvironment(pred->last_environment()->Copy());
351   }
352
353   predecessors_.Add(pred, zone());
354 }
355
356
357 void HBasicBlock::AddDominatedBlock(HBasicBlock* block) {
358   DCHECK(!dominated_blocks_.Contains(block));
359   // Keep the list of dominated blocks sorted such that if there is two
360   // succeeding block in this list, the predecessor is before the successor.
361   int index = 0;
362   while (index < dominated_blocks_.length() &&
363          dominated_blocks_[index]->block_id() < block->block_id()) {
364     ++index;
365   }
366   dominated_blocks_.InsertAt(index, block, zone());
367 }
368
369
370 void HBasicBlock::AssignCommonDominator(HBasicBlock* other) {
371   if (dominator_ == NULL) {
372     dominator_ = other;
373     other->AddDominatedBlock(this);
374   } else if (other->dominator() != NULL) {
375     HBasicBlock* first = dominator_;
376     HBasicBlock* second = other;
377
378     while (first != second) {
379       if (first->block_id() > second->block_id()) {
380         first = first->dominator();
381       } else {
382         second = second->dominator();
383       }
384       DCHECK(first != NULL && second != NULL);
385     }
386
387     if (dominator_ != first) {
388       DCHECK(dominator_->dominated_blocks_.Contains(this));
389       dominator_->dominated_blocks_.RemoveElement(this);
390       dominator_ = first;
391       first->AddDominatedBlock(this);
392     }
393   }
394 }
395
396
397 void HBasicBlock::AssignLoopSuccessorDominators() {
398   // Mark blocks that dominate all subsequent reachable blocks inside their
399   // loop. Exploit the fact that blocks are sorted in reverse post order. When
400   // the loop is visited in increasing block id order, if the number of
401   // non-loop-exiting successor edges at the dominator_candidate block doesn't
402   // exceed the number of previously encountered predecessor edges, there is no
403   // path from the loop header to any block with higher id that doesn't go
404   // through the dominator_candidate block. In this case, the
405   // dominator_candidate block is guaranteed to dominate all blocks reachable
406   // from it with higher ids.
407   HBasicBlock* last = loop_information()->GetLastBackEdge();
408   int outstanding_successors = 1;  // one edge from the pre-header
409   // Header always dominates everything.
410   MarkAsLoopSuccessorDominator();
411   for (int j = block_id(); j <= last->block_id(); ++j) {
412     HBasicBlock* dominator_candidate = graph_->blocks()->at(j);
413     for (HPredecessorIterator it(dominator_candidate); !it.Done();
414          it.Advance()) {
415       HBasicBlock* predecessor = it.Current();
416       // Don't count back edges.
417       if (predecessor->block_id() < dominator_candidate->block_id()) {
418         outstanding_successors--;
419       }
420     }
421
422     // If more successors than predecessors have been seen in the loop up to
423     // now, it's not possible to guarantee that the current block dominates
424     // all of the blocks with higher IDs. In this case, assume conservatively
425     // that those paths through loop that don't go through the current block
426     // contain all of the loop's dependencies. Also be careful to record
427     // dominator information about the current loop that's being processed,
428     // and not nested loops, which will be processed when
429     // AssignLoopSuccessorDominators gets called on their header.
430     DCHECK(outstanding_successors >= 0);
431     HBasicBlock* parent_loop_header = dominator_candidate->parent_loop_header();
432     if (outstanding_successors == 0 &&
433         (parent_loop_header == this && !dominator_candidate->IsLoopHeader())) {
434       dominator_candidate->MarkAsLoopSuccessorDominator();
435     }
436     HControlInstruction* end = dominator_candidate->end();
437     for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
438       HBasicBlock* successor = it.Current();
439       // Only count successors that remain inside the loop and don't loop back
440       // to a loop header.
441       if (successor->block_id() > dominator_candidate->block_id() &&
442           successor->block_id() <= last->block_id()) {
443         // Backwards edges must land on loop headers.
444         DCHECK(successor->block_id() > dominator_candidate->block_id() ||
445                successor->IsLoopHeader());
446         outstanding_successors++;
447       }
448     }
449   }
450 }
451
452
453 int HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const {
454   for (int i = 0; i < predecessors_.length(); ++i) {
455     if (predecessors_[i] == predecessor) return i;
456   }
457   UNREACHABLE();
458   return -1;
459 }
460
461
462 #ifdef DEBUG
463 void HBasicBlock::Verify() {
464   // Check that every block is finished.
465   DCHECK(IsFinished());
466   DCHECK(block_id() >= 0);
467
468   // Check that the incoming edges are in edge split form.
469   if (predecessors_.length() > 1) {
470     for (int i = 0; i < predecessors_.length(); ++i) {
471       DCHECK(predecessors_[i]->end()->SecondSuccessor() == NULL);
472     }
473   }
474 }
475 #endif
476
477
478 void HLoopInformation::RegisterBackEdge(HBasicBlock* block) {
479   this->back_edges_.Add(block, block->zone());
480   AddBlock(block);
481 }
482
483
484 HBasicBlock* HLoopInformation::GetLastBackEdge() const {
485   int max_id = -1;
486   HBasicBlock* result = NULL;
487   for (int i = 0; i < back_edges_.length(); ++i) {
488     HBasicBlock* cur = back_edges_[i];
489     if (cur->block_id() > max_id) {
490       max_id = cur->block_id();
491       result = cur;
492     }
493   }
494   return result;
495 }
496
497
498 void HLoopInformation::AddBlock(HBasicBlock* block) {
499   if (block == loop_header()) return;
500   if (block->parent_loop_header() == loop_header()) return;
501   if (block->parent_loop_header() != NULL) {
502     AddBlock(block->parent_loop_header());
503   } else {
504     block->set_parent_loop_header(loop_header());
505     blocks_.Add(block, block->zone());
506     for (int i = 0; i < block->predecessors()->length(); ++i) {
507       AddBlock(block->predecessors()->at(i));
508     }
509   }
510 }
511
512
513 #ifdef DEBUG
514
515 // Checks reachability of the blocks in this graph and stores a bit in
516 // the BitVector "reachable()" for every block that can be reached
517 // from the start block of the graph. If "dont_visit" is non-null, the given
518 // block is treated as if it would not be part of the graph. "visited_count()"
519 // returns the number of reachable blocks.
520 class ReachabilityAnalyzer BASE_EMBEDDED {
521  public:
522   ReachabilityAnalyzer(HBasicBlock* entry_block,
523                        int block_count,
524                        HBasicBlock* dont_visit)
525       : visited_count_(0),
526         stack_(16, entry_block->zone()),
527         reachable_(block_count, entry_block->zone()),
528         dont_visit_(dont_visit) {
529     PushBlock(entry_block);
530     Analyze();
531   }
532
533   int visited_count() const { return visited_count_; }
534   const BitVector* reachable() const { return &reachable_; }
535
536  private:
537   void PushBlock(HBasicBlock* block) {
538     if (block != NULL && block != dont_visit_ &&
539         !reachable_.Contains(block->block_id())) {
540       reachable_.Add(block->block_id());
541       stack_.Add(block, block->zone());
542       visited_count_++;
543     }
544   }
545
546   void Analyze() {
547     while (!stack_.is_empty()) {
548       HControlInstruction* end = stack_.RemoveLast()->end();
549       for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
550         PushBlock(it.Current());
551       }
552     }
553   }
554
555   int visited_count_;
556   ZoneList<HBasicBlock*> stack_;
557   BitVector reachable_;
558   HBasicBlock* dont_visit_;
559 };
560
561
562 void HGraph::Verify(bool do_full_verify) const {
563   Heap::RelocationLock relocation_lock(isolate()->heap());
564   AllowHandleDereference allow_deref;
565   AllowDeferredHandleDereference allow_deferred_deref;
566   for (int i = 0; i < blocks_.length(); i++) {
567     HBasicBlock* block = blocks_.at(i);
568
569     block->Verify();
570
571     // Check that every block contains at least one node and that only the last
572     // node is a control instruction.
573     HInstruction* current = block->first();
574     DCHECK(current != NULL && current->IsBlockEntry());
575     while (current != NULL) {
576       DCHECK((current->next() == NULL) == current->IsControlInstruction());
577       DCHECK(current->block() == block);
578       current->Verify();
579       current = current->next();
580     }
581
582     // Check that successors are correctly set.
583     HBasicBlock* first = block->end()->FirstSuccessor();
584     HBasicBlock* second = block->end()->SecondSuccessor();
585     DCHECK(second == NULL || first != NULL);
586
587     // Check that the predecessor array is correct.
588     if (first != NULL) {
589       DCHECK(first->predecessors()->Contains(block));
590       if (second != NULL) {
591         DCHECK(second->predecessors()->Contains(block));
592       }
593     }
594
595     // Check that phis have correct arguments.
596     for (int j = 0; j < block->phis()->length(); j++) {
597       HPhi* phi = block->phis()->at(j);
598       phi->Verify();
599     }
600
601     // Check that all join blocks have predecessors that end with an
602     // unconditional goto and agree on their environment node id.
603     if (block->predecessors()->length() >= 2) {
604       BailoutId id =
605           block->predecessors()->first()->last_environment()->ast_id();
606       for (int k = 0; k < block->predecessors()->length(); k++) {
607         HBasicBlock* predecessor = block->predecessors()->at(k);
608         DCHECK(predecessor->end()->IsGoto() ||
609                predecessor->end()->IsDeoptimize());
610         DCHECK(predecessor->last_environment()->ast_id() == id);
611       }
612     }
613   }
614
615   // Check special property of first block to have no predecessors.
616   DCHECK(blocks_.at(0)->predecessors()->is_empty());
617
618   if (do_full_verify) {
619     // Check that the graph is fully connected.
620     ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL);
621     DCHECK(analyzer.visited_count() == blocks_.length());
622
623     // Check that entry block dominator is NULL.
624     DCHECK(entry_block_->dominator() == NULL);
625
626     // Check dominators.
627     for (int i = 0; i < blocks_.length(); ++i) {
628       HBasicBlock* block = blocks_.at(i);
629       if (block->dominator() == NULL) {
630         // Only start block may have no dominator assigned to.
631         DCHECK(i == 0);
632       } else {
633         // Assert that block is unreachable if dominator must not be visited.
634         ReachabilityAnalyzer dominator_analyzer(entry_block_,
635                                                 blocks_.length(),
636                                                 block->dominator());
637         DCHECK(!dominator_analyzer.reachable()->Contains(block->block_id()));
638       }
639     }
640   }
641 }
642
643 #endif
644
645
646 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
647                                int32_t value) {
648   if (!pointer->is_set()) {
649     // Can't pass GetInvalidContext() to HConstant::New, because that will
650     // recursively call GetConstant
651     HConstant* constant = HConstant::New(isolate(), zone(), NULL, value);
652     constant->InsertAfter(entry_block()->first());
653     pointer->set(constant);
654     return constant;
655   }
656   return ReinsertConstantIfNecessary(pointer->get());
657 }
658
659
660 HConstant* HGraph::ReinsertConstantIfNecessary(HConstant* constant) {
661   if (!constant->IsLinked()) {
662     // The constant was removed from the graph. Reinsert.
663     constant->ClearFlag(HValue::kIsDead);
664     constant->InsertAfter(entry_block()->first());
665   }
666   return constant;
667 }
668
669
670 HConstant* HGraph::GetConstant0() {
671   return GetConstant(&constant_0_, 0);
672 }
673
674
675 HConstant* HGraph::GetConstant1() {
676   return GetConstant(&constant_1_, 1);
677 }
678
679
680 HConstant* HGraph::GetConstantMinus1() {
681   return GetConstant(&constant_minus1_, -1);
682 }
683
684
685 HConstant* HGraph::GetConstantBool(bool value) {
686   return value ? GetConstantTrue() : GetConstantFalse();
687 }
688
689
690 #define DEFINE_GET_CONSTANT(Name, name, type, htype, boolean_value)            \
691 HConstant* HGraph::GetConstant##Name() {                                       \
692   if (!constant_##name##_.is_set()) {                                          \
693     HConstant* constant = new(zone()) HConstant(                               \
694         Unique<Object>::CreateImmovable(isolate()->factory()->name##_value()), \
695         Unique<Map>::CreateImmovable(isolate()->factory()->type##_map()),      \
696         false,                                                                 \
697         Representation::Tagged(),                                              \
698         htype,                                                                 \
699         true,                                                                  \
700         boolean_value,                                                         \
701         false,                                                                 \
702         ODDBALL_TYPE);                                                         \
703     constant->InsertAfter(entry_block()->first());                             \
704     constant_##name##_.set(constant);                                          \
705   }                                                                            \
706   return ReinsertConstantIfNecessary(constant_##name##_.get());                \
707 }
708
709
710 DEFINE_GET_CONSTANT(Undefined, undefined, undefined, HType::Undefined(), false)
711 DEFINE_GET_CONSTANT(True, true, boolean, HType::Boolean(), true)
712 DEFINE_GET_CONSTANT(False, false, boolean, HType::Boolean(), false)
713 DEFINE_GET_CONSTANT(Hole, the_hole, the_hole, HType::None(), false)
714 DEFINE_GET_CONSTANT(Null, null, null, HType::Null(), false)
715
716
717 #undef DEFINE_GET_CONSTANT
718
719 #define DEFINE_IS_CONSTANT(Name, name)                                         \
720 bool HGraph::IsConstant##Name(HConstant* constant) {                           \
721   return constant_##name##_.is_set() && constant == constant_##name##_.get();  \
722 }
723 DEFINE_IS_CONSTANT(Undefined, undefined)
724 DEFINE_IS_CONSTANT(0, 0)
725 DEFINE_IS_CONSTANT(1, 1)
726 DEFINE_IS_CONSTANT(Minus1, minus1)
727 DEFINE_IS_CONSTANT(True, true)
728 DEFINE_IS_CONSTANT(False, false)
729 DEFINE_IS_CONSTANT(Hole, the_hole)
730 DEFINE_IS_CONSTANT(Null, null)
731
732 #undef DEFINE_IS_CONSTANT
733
734
735 HConstant* HGraph::GetInvalidContext() {
736   return GetConstant(&constant_invalid_context_, 0xFFFFC0C7);
737 }
738
739
740 bool HGraph::IsStandardConstant(HConstant* constant) {
741   if (IsConstantUndefined(constant)) return true;
742   if (IsConstant0(constant)) return true;
743   if (IsConstant1(constant)) return true;
744   if (IsConstantMinus1(constant)) return true;
745   if (IsConstantTrue(constant)) return true;
746   if (IsConstantFalse(constant)) return true;
747   if (IsConstantHole(constant)) return true;
748   if (IsConstantNull(constant)) return true;
749   return false;
750 }
751
752
753 HGraphBuilder::IfBuilder::IfBuilder() : builder_(NULL), needs_compare_(true) {}
754
755
756 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder)
757     : needs_compare_(true) {
758   Initialize(builder);
759 }
760
761
762 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder,
763                                     HIfContinuation* continuation)
764     : needs_compare_(false), first_true_block_(NULL), first_false_block_(NULL) {
765   InitializeDontCreateBlocks(builder);
766   continuation->Continue(&first_true_block_, &first_false_block_);
767 }
768
769
770 void HGraphBuilder::IfBuilder::InitializeDontCreateBlocks(
771     HGraphBuilder* builder) {
772   builder_ = builder;
773   finished_ = false;
774   did_then_ = false;
775   did_else_ = false;
776   did_else_if_ = false;
777   did_and_ = false;
778   did_or_ = false;
779   captured_ = false;
780   pending_merge_block_ = false;
781   split_edge_merge_block_ = NULL;
782   merge_at_join_blocks_ = NULL;
783   normal_merge_at_join_block_count_ = 0;
784   deopt_merge_at_join_block_count_ = 0;
785 }
786
787
788 void HGraphBuilder::IfBuilder::Initialize(HGraphBuilder* builder) {
789   InitializeDontCreateBlocks(builder);
790   HEnvironment* env = builder->environment();
791   first_true_block_ = builder->CreateBasicBlock(env->Copy());
792   first_false_block_ = builder->CreateBasicBlock(env->Copy());
793 }
794
795
796 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare(
797     HControlInstruction* compare) {
798   DCHECK(did_then_ == did_else_);
799   if (did_else_) {
800     // Handle if-then-elseif
801     did_else_if_ = true;
802     did_else_ = false;
803     did_then_ = false;
804     did_and_ = false;
805     did_or_ = false;
806     pending_merge_block_ = false;
807     split_edge_merge_block_ = NULL;
808     HEnvironment* env = builder()->environment();
809     first_true_block_ = builder()->CreateBasicBlock(env->Copy());
810     first_false_block_ = builder()->CreateBasicBlock(env->Copy());
811   }
812   if (split_edge_merge_block_ != NULL) {
813     HEnvironment* env = first_false_block_->last_environment();
814     HBasicBlock* split_edge = builder()->CreateBasicBlock(env->Copy());
815     if (did_or_) {
816       compare->SetSuccessorAt(0, split_edge);
817       compare->SetSuccessorAt(1, first_false_block_);
818     } else {
819       compare->SetSuccessorAt(0, first_true_block_);
820       compare->SetSuccessorAt(1, split_edge);
821     }
822     builder()->GotoNoSimulate(split_edge, split_edge_merge_block_);
823   } else {
824     compare->SetSuccessorAt(0, first_true_block_);
825     compare->SetSuccessorAt(1, first_false_block_);
826   }
827   builder()->FinishCurrentBlock(compare);
828   needs_compare_ = false;
829   return compare;
830 }
831
832
833 void HGraphBuilder::IfBuilder::Or() {
834   DCHECK(!needs_compare_);
835   DCHECK(!did_and_);
836   did_or_ = true;
837   HEnvironment* env = first_false_block_->last_environment();
838   if (split_edge_merge_block_ == NULL) {
839     split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
840     builder()->GotoNoSimulate(first_true_block_, split_edge_merge_block_);
841     first_true_block_ = split_edge_merge_block_;
842   }
843   builder()->set_current_block(first_false_block_);
844   first_false_block_ = builder()->CreateBasicBlock(env->Copy());
845 }
846
847
848 void HGraphBuilder::IfBuilder::And() {
849   DCHECK(!needs_compare_);
850   DCHECK(!did_or_);
851   did_and_ = true;
852   HEnvironment* env = first_false_block_->last_environment();
853   if (split_edge_merge_block_ == NULL) {
854     split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
855     builder()->GotoNoSimulate(first_false_block_, split_edge_merge_block_);
856     first_false_block_ = split_edge_merge_block_;
857   }
858   builder()->set_current_block(first_true_block_);
859   first_true_block_ = builder()->CreateBasicBlock(env->Copy());
860 }
861
862
863 void HGraphBuilder::IfBuilder::CaptureContinuation(
864     HIfContinuation* continuation) {
865   DCHECK(!did_else_if_);
866   DCHECK(!finished_);
867   DCHECK(!captured_);
868
869   HBasicBlock* true_block = NULL;
870   HBasicBlock* false_block = NULL;
871   Finish(&true_block, &false_block);
872   DCHECK(true_block != NULL);
873   DCHECK(false_block != NULL);
874   continuation->Capture(true_block, false_block);
875   captured_ = true;
876   builder()->set_current_block(NULL);
877   End();
878 }
879
880
881 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) {
882   DCHECK(!did_else_if_);
883   DCHECK(!finished_);
884   DCHECK(!captured_);
885   HBasicBlock* true_block = NULL;
886   HBasicBlock* false_block = NULL;
887   Finish(&true_block, &false_block);
888   merge_at_join_blocks_ = NULL;
889   if (true_block != NULL && !true_block->IsFinished()) {
890     DCHECK(continuation->IsTrueReachable());
891     builder()->GotoNoSimulate(true_block, continuation->true_branch());
892   }
893   if (false_block != NULL && !false_block->IsFinished()) {
894     DCHECK(continuation->IsFalseReachable());
895     builder()->GotoNoSimulate(false_block, continuation->false_branch());
896   }
897   captured_ = true;
898   End();
899 }
900
901
902 void HGraphBuilder::IfBuilder::Then() {
903   DCHECK(!captured_);
904   DCHECK(!finished_);
905   did_then_ = true;
906   if (needs_compare_) {
907     // Handle if's without any expressions, they jump directly to the "else"
908     // branch. However, we must pretend that the "then" branch is reachable,
909     // so that the graph builder visits it and sees any live range extending
910     // constructs within it.
911     HConstant* constant_false = builder()->graph()->GetConstantFalse();
912     ToBooleanStub::Types boolean_type = ToBooleanStub::Types();
913     boolean_type.Add(ToBooleanStub::BOOLEAN);
914     HBranch* branch = builder()->New<HBranch>(
915         constant_false, boolean_type, first_true_block_, first_false_block_);
916     builder()->FinishCurrentBlock(branch);
917   }
918   builder()->set_current_block(first_true_block_);
919   pending_merge_block_ = true;
920 }
921
922
923 void HGraphBuilder::IfBuilder::Else() {
924   DCHECK(did_then_);
925   DCHECK(!captured_);
926   DCHECK(!finished_);
927   AddMergeAtJoinBlock(false);
928   builder()->set_current_block(first_false_block_);
929   pending_merge_block_ = true;
930   did_else_ = true;
931 }
932
933
934 void HGraphBuilder::IfBuilder::Deopt(Deoptimizer::DeoptReason reason) {
935   DCHECK(did_then_);
936   builder()->Add<HDeoptimize>(reason, Deoptimizer::EAGER);
937   AddMergeAtJoinBlock(true);
938 }
939
940
941 void HGraphBuilder::IfBuilder::Return(HValue* value) {
942   HValue* parameter_count = builder()->graph()->GetConstantMinus1();
943   builder()->FinishExitCurrentBlock(
944       builder()->New<HReturn>(value, parameter_count));
945   AddMergeAtJoinBlock(false);
946 }
947
948
949 void HGraphBuilder::IfBuilder::AddMergeAtJoinBlock(bool deopt) {
950   if (!pending_merge_block_) return;
951   HBasicBlock* block = builder()->current_block();
952   DCHECK(block == NULL || !block->IsFinished());
953   MergeAtJoinBlock* record = new (builder()->zone())
954       MergeAtJoinBlock(block, deopt, merge_at_join_blocks_);
955   merge_at_join_blocks_ = record;
956   if (block != NULL) {
957     DCHECK(block->end() == NULL);
958     if (deopt) {
959       normal_merge_at_join_block_count_++;
960     } else {
961       deopt_merge_at_join_block_count_++;
962     }
963   }
964   builder()->set_current_block(NULL);
965   pending_merge_block_ = false;
966 }
967
968
969 void HGraphBuilder::IfBuilder::Finish() {
970   DCHECK(!finished_);
971   if (!did_then_) {
972     Then();
973   }
974   AddMergeAtJoinBlock(false);
975   if (!did_else_) {
976     Else();
977     AddMergeAtJoinBlock(false);
978   }
979   finished_ = true;
980 }
981
982
983 void HGraphBuilder::IfBuilder::Finish(HBasicBlock** then_continuation,
984                                       HBasicBlock** else_continuation) {
985   Finish();
986
987   MergeAtJoinBlock* else_record = merge_at_join_blocks_;
988   if (else_continuation != NULL) {
989     *else_continuation = else_record->block_;
990   }
991   MergeAtJoinBlock* then_record = else_record->next_;
992   if (then_continuation != NULL) {
993     *then_continuation = then_record->block_;
994   }
995   DCHECK(then_record->next_ == NULL);
996 }
997
998
999 void HGraphBuilder::IfBuilder::EndUnreachable() {
1000   if (captured_) return;
1001   Finish();
1002   builder()->set_current_block(nullptr);
1003 }
1004
1005
1006 void HGraphBuilder::IfBuilder::End() {
1007   if (captured_) return;
1008   Finish();
1009
1010   int total_merged_blocks = normal_merge_at_join_block_count_ +
1011     deopt_merge_at_join_block_count_;
1012   DCHECK(total_merged_blocks >= 1);
1013   HBasicBlock* merge_block =
1014       total_merged_blocks == 1 ? NULL : builder()->graph()->CreateBasicBlock();
1015
1016   // Merge non-deopt blocks first to ensure environment has right size for
1017   // padding.
1018   MergeAtJoinBlock* current = merge_at_join_blocks_;
1019   while (current != NULL) {
1020     if (!current->deopt_ && current->block_ != NULL) {
1021       // If there is only one block that makes it through to the end of the
1022       // if, then just set it as the current block and continue rather then
1023       // creating an unnecessary merge block.
1024       if (total_merged_blocks == 1) {
1025         builder()->set_current_block(current->block_);
1026         return;
1027       }
1028       builder()->GotoNoSimulate(current->block_, merge_block);
1029     }
1030     current = current->next_;
1031   }
1032
1033   // Merge deopt blocks, padding when necessary.
1034   current = merge_at_join_blocks_;
1035   while (current != NULL) {
1036     if (current->deopt_ && current->block_ != NULL) {
1037       current->block_->FinishExit(
1038           HAbnormalExit::New(builder()->isolate(), builder()->zone(), NULL),
1039           SourcePosition::Unknown());
1040     }
1041     current = current->next_;
1042   }
1043   builder()->set_current_block(merge_block);
1044 }
1045
1046
1047 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder) {
1048   Initialize(builder, NULL, kWhileTrue, NULL);
1049 }
1050
1051
1052 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
1053                                         LoopBuilder::Direction direction) {
1054   Initialize(builder, context, direction, builder->graph()->GetConstant1());
1055 }
1056
1057
1058 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
1059                                         LoopBuilder::Direction direction,
1060                                         HValue* increment_amount) {
1061   Initialize(builder, context, direction, increment_amount);
1062   increment_amount_ = increment_amount;
1063 }
1064
1065
1066 void HGraphBuilder::LoopBuilder::Initialize(HGraphBuilder* builder,
1067                                             HValue* context,
1068                                             Direction direction,
1069                                             HValue* increment_amount) {
1070   builder_ = builder;
1071   context_ = context;
1072   direction_ = direction;
1073   increment_amount_ = increment_amount;
1074
1075   finished_ = false;
1076   header_block_ = builder->CreateLoopHeaderBlock();
1077   body_block_ = NULL;
1078   exit_block_ = NULL;
1079   exit_trampoline_block_ = NULL;
1080 }
1081
1082
1083 HValue* HGraphBuilder::LoopBuilder::BeginBody(
1084     HValue* initial,
1085     HValue* terminating,
1086     Token::Value token) {
1087   DCHECK(direction_ != kWhileTrue);
1088   HEnvironment* env = builder_->environment();
1089   phi_ = header_block_->AddNewPhi(env->values()->length());
1090   phi_->AddInput(initial);
1091   env->Push(initial);
1092   builder_->GotoNoSimulate(header_block_);
1093
1094   HEnvironment* body_env = env->Copy();
1095   HEnvironment* exit_env = env->Copy();
1096   // Remove the phi from the expression stack
1097   body_env->Pop();
1098   exit_env->Pop();
1099   body_block_ = builder_->CreateBasicBlock(body_env);
1100   exit_block_ = builder_->CreateBasicBlock(exit_env);
1101
1102   builder_->set_current_block(header_block_);
1103   env->Pop();
1104   builder_->FinishCurrentBlock(builder_->New<HCompareNumericAndBranch>(
1105           phi_, terminating, token, body_block_, exit_block_));
1106
1107   builder_->set_current_block(body_block_);
1108   if (direction_ == kPreIncrement || direction_ == kPreDecrement) {
1109     Isolate* isolate = builder_->isolate();
1110     HValue* one = builder_->graph()->GetConstant1();
1111     if (direction_ == kPreIncrement) {
1112       increment_ = HAdd::New(isolate, zone(), context_, phi_, one);
1113     } else {
1114       increment_ = HSub::New(isolate, zone(), context_, phi_, one);
1115     }
1116     increment_->ClearFlag(HValue::kCanOverflow);
1117     builder_->AddInstruction(increment_);
1118     return increment_;
1119   } else {
1120     return phi_;
1121   }
1122 }
1123
1124
1125 void HGraphBuilder::LoopBuilder::BeginBody(int drop_count) {
1126   DCHECK(direction_ == kWhileTrue);
1127   HEnvironment* env = builder_->environment();
1128   builder_->GotoNoSimulate(header_block_);
1129   builder_->set_current_block(header_block_);
1130   env->Drop(drop_count);
1131 }
1132
1133
1134 void HGraphBuilder::LoopBuilder::Break() {
1135   if (exit_trampoline_block_ == NULL) {
1136     // Its the first time we saw a break.
1137     if (direction_ == kWhileTrue) {
1138       HEnvironment* env = builder_->environment()->Copy();
1139       exit_trampoline_block_ = builder_->CreateBasicBlock(env);
1140     } else {
1141       HEnvironment* env = exit_block_->last_environment()->Copy();
1142       exit_trampoline_block_ = builder_->CreateBasicBlock(env);
1143       builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_);
1144     }
1145   }
1146
1147   builder_->GotoNoSimulate(exit_trampoline_block_);
1148   builder_->set_current_block(NULL);
1149 }
1150
1151
1152 void HGraphBuilder::LoopBuilder::EndBody() {
1153   DCHECK(!finished_);
1154
1155   if (direction_ == kPostIncrement || direction_ == kPostDecrement) {
1156     Isolate* isolate = builder_->isolate();
1157     if (direction_ == kPostIncrement) {
1158       increment_ =
1159           HAdd::New(isolate, zone(), context_, phi_, increment_amount_);
1160     } else {
1161       increment_ =
1162           HSub::New(isolate, zone(), context_, phi_, increment_amount_);
1163     }
1164     increment_->ClearFlag(HValue::kCanOverflow);
1165     builder_->AddInstruction(increment_);
1166   }
1167
1168   if (direction_ != kWhileTrue) {
1169     // Push the new increment value on the expression stack to merge into
1170     // the phi.
1171     builder_->environment()->Push(increment_);
1172   }
1173   HBasicBlock* last_block = builder_->current_block();
1174   builder_->GotoNoSimulate(last_block, header_block_);
1175   header_block_->loop_information()->RegisterBackEdge(last_block);
1176
1177   if (exit_trampoline_block_ != NULL) {
1178     builder_->set_current_block(exit_trampoline_block_);
1179   } else {
1180     builder_->set_current_block(exit_block_);
1181   }
1182   finished_ = true;
1183 }
1184
1185
1186 HGraph* HGraphBuilder::CreateGraph() {
1187   graph_ = new(zone()) HGraph(info_);
1188   if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_);
1189   CompilationPhase phase("H_Block building", info_);
1190   set_current_block(graph()->entry_block());
1191   if (!BuildGraph()) return NULL;
1192   graph()->FinalizeUniqueness();
1193   return graph_;
1194 }
1195
1196
1197 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
1198   DCHECK(current_block() != NULL);
1199   DCHECK(!FLAG_hydrogen_track_positions ||
1200          !position_.IsUnknown() ||
1201          !info_->IsOptimizing());
1202   current_block()->AddInstruction(instr, source_position());
1203   if (graph()->IsInsideNoSideEffectsScope()) {
1204     instr->SetFlag(HValue::kHasNoObservableSideEffects);
1205   }
1206   return instr;
1207 }
1208
1209
1210 void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) {
1211   DCHECK(!FLAG_hydrogen_track_positions ||
1212          !info_->IsOptimizing() ||
1213          !position_.IsUnknown());
1214   current_block()->Finish(last, source_position());
1215   if (last->IsReturn() || last->IsAbnormalExit()) {
1216     set_current_block(NULL);
1217   }
1218 }
1219
1220
1221 void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) {
1222   DCHECK(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() ||
1223          !position_.IsUnknown());
1224   current_block()->FinishExit(instruction, source_position());
1225   if (instruction->IsReturn() || instruction->IsAbnormalExit()) {
1226     set_current_block(NULL);
1227   }
1228 }
1229
1230
1231 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) {
1232   if (FLAG_native_code_counters && counter->Enabled()) {
1233     HValue* reference = Add<HConstant>(ExternalReference(counter));
1234     HValue* old_value =
1235         Add<HLoadNamedField>(reference, nullptr, HObjectAccess::ForCounter());
1236     HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1());
1237     new_value->ClearFlag(HValue::kCanOverflow);  // Ignore counter overflow
1238     Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(),
1239                           new_value, STORE_TO_INITIALIZED_ENTRY);
1240   }
1241 }
1242
1243
1244 void HGraphBuilder::AddSimulate(BailoutId id,
1245                                 RemovableSimulate removable) {
1246   DCHECK(current_block() != NULL);
1247   DCHECK(!graph()->IsInsideNoSideEffectsScope());
1248   current_block()->AddNewSimulate(id, source_position(), removable);
1249 }
1250
1251
1252 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
1253   HBasicBlock* b = graph()->CreateBasicBlock();
1254   b->SetInitialEnvironment(env);
1255   return b;
1256 }
1257
1258
1259 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
1260   HBasicBlock* header = graph()->CreateBasicBlock();
1261   HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
1262   header->SetInitialEnvironment(entry_env);
1263   header->AttachLoopInformation();
1264   return header;
1265 }
1266
1267
1268 HValue* HGraphBuilder::BuildGetElementsKind(HValue* object) {
1269   HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap());
1270
1271   HValue* bit_field2 =
1272       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2());
1273   return BuildDecodeField<Map::ElementsKindBits>(bit_field2);
1274 }
1275
1276
1277 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) {
1278   if (obj->type().IsHeapObject()) return obj;
1279   return Add<HCheckHeapObject>(obj);
1280 }
1281
1282
1283 void HGraphBuilder::FinishExitWithHardDeoptimization(
1284     Deoptimizer::DeoptReason reason) {
1285   Add<HDeoptimize>(reason, Deoptimizer::EAGER);
1286   FinishExitCurrentBlock(New<HAbnormalExit>());
1287 }
1288
1289
1290 HValue* HGraphBuilder::BuildCheckString(HValue* string) {
1291   if (!string->type().IsString()) {
1292     DCHECK(!string->IsConstant() ||
1293            !HConstant::cast(string)->HasStringValue());
1294     BuildCheckHeapObject(string);
1295     return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
1296   }
1297   return string;
1298 }
1299
1300
1301 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) {
1302   if (object->type().IsJSObject()) return object;
1303   if (function->IsConstant() &&
1304       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
1305     Handle<JSFunction> f = Handle<JSFunction>::cast(
1306         HConstant::cast(function)->handle(isolate()));
1307     SharedFunctionInfo* shared = f->shared();
1308     if (is_strict(shared->language_mode()) || shared->native()) return object;
1309   }
1310   return Add<HWrapReceiver>(object, function);
1311 }
1312
1313
1314 HValue* HGraphBuilder::BuildCheckAndGrowElementsCapacity(
1315     HValue* object, HValue* elements, ElementsKind kind, HValue* length,
1316     HValue* capacity, HValue* key) {
1317   HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
1318   HValue* max_capacity = AddUncasted<HAdd>(capacity, max_gap);
1319   Add<HBoundsCheck>(key, max_capacity);
1320
1321   HValue* new_capacity = BuildNewElementsCapacity(key);
1322   HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind, kind,
1323                                                    length, new_capacity);
1324   return new_elements;
1325 }
1326
1327
1328 HValue* HGraphBuilder::BuildCheckForCapacityGrow(
1329     HValue* object,
1330     HValue* elements,
1331     ElementsKind kind,
1332     HValue* length,
1333     HValue* key,
1334     bool is_js_array,
1335     PropertyAccessType access_type) {
1336   IfBuilder length_checker(this);
1337
1338   Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
1339   length_checker.If<HCompareNumericAndBranch>(key, length, token);
1340
1341   length_checker.Then();
1342
1343   HValue* current_capacity = AddLoadFixedArrayLength(elements);
1344
1345   if (top_info()->IsStub()) {
1346     IfBuilder capacity_checker(this);
1347     capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity,
1348                                                   Token::GTE);
1349     capacity_checker.Then();
1350     HValue* new_elements = BuildCheckAndGrowElementsCapacity(
1351         object, elements, kind, length, current_capacity, key);
1352     environment()->Push(new_elements);
1353     capacity_checker.Else();
1354     environment()->Push(elements);
1355     capacity_checker.End();
1356   } else {
1357     HValue* result = Add<HMaybeGrowElements>(
1358         object, elements, key, current_capacity, is_js_array, kind);
1359     environment()->Push(result);
1360   }
1361
1362   if (is_js_array) {
1363     HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1());
1364     new_length->ClearFlag(HValue::kCanOverflow);
1365
1366     Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind),
1367                           new_length);
1368   }
1369
1370   if (access_type == STORE && kind == FAST_SMI_ELEMENTS) {
1371     HValue* checked_elements = environment()->Top();
1372
1373     // Write zero to ensure that the new element is initialized with some smi.
1374     Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), kind);
1375   }
1376
1377   length_checker.Else();
1378   Add<HBoundsCheck>(key, length);
1379
1380   environment()->Push(elements);
1381   length_checker.End();
1382
1383   return environment()->Pop();
1384 }
1385
1386
1387 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
1388                                                 HValue* elements,
1389                                                 ElementsKind kind,
1390                                                 HValue* length) {
1391   Factory* factory = isolate()->factory();
1392
1393   IfBuilder cow_checker(this);
1394
1395   cow_checker.If<HCompareMap>(elements, factory->fixed_cow_array_map());
1396   cow_checker.Then();
1397
1398   HValue* capacity = AddLoadFixedArrayLength(elements);
1399
1400   HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind,
1401                                                    kind, length, capacity);
1402
1403   environment()->Push(new_elements);
1404
1405   cow_checker.Else();
1406
1407   environment()->Push(elements);
1408
1409   cow_checker.End();
1410
1411   return environment()->Pop();
1412 }
1413
1414
1415 void HGraphBuilder::BuildTransitionElementsKind(HValue* object,
1416                                                 HValue* map,
1417                                                 ElementsKind from_kind,
1418                                                 ElementsKind to_kind,
1419                                                 bool is_jsarray) {
1420   DCHECK(!IsFastHoleyElementsKind(from_kind) ||
1421          IsFastHoleyElementsKind(to_kind));
1422
1423   if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) {
1424     Add<HTrapAllocationMemento>(object);
1425   }
1426
1427   if (!IsSimpleMapChangeTransition(from_kind, to_kind)) {
1428     HInstruction* elements = AddLoadElements(object);
1429
1430     HInstruction* empty_fixed_array = Add<HConstant>(
1431         isolate()->factory()->empty_fixed_array());
1432
1433     IfBuilder if_builder(this);
1434
1435     if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array);
1436
1437     if_builder.Then();
1438
1439     HInstruction* elements_length = AddLoadFixedArrayLength(elements);
1440
1441     HInstruction* array_length =
1442         is_jsarray
1443             ? Add<HLoadNamedField>(object, nullptr,
1444                                    HObjectAccess::ForArrayLength(from_kind))
1445             : elements_length;
1446
1447     BuildGrowElementsCapacity(object, elements, from_kind, to_kind,
1448                               array_length, elements_length);
1449
1450     if_builder.End();
1451   }
1452
1453   Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map);
1454 }
1455
1456
1457 void HGraphBuilder::BuildJSObjectCheck(HValue* receiver,
1458                                        int bit_field_mask) {
1459   // Check that the object isn't a smi.
1460   Add<HCheckHeapObject>(receiver);
1461
1462   // Get the map of the receiver.
1463   HValue* map =
1464       Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
1465
1466   // Check the instance type and if an access check is needed, this can be
1467   // done with a single load, since both bytes are adjacent in the map.
1468   HObjectAccess access(HObjectAccess::ForMapInstanceTypeAndBitField());
1469   HValue* instance_type_and_bit_field =
1470       Add<HLoadNamedField>(map, nullptr, access);
1471
1472   HValue* mask = Add<HConstant>(0x00FF | (bit_field_mask << 8));
1473   HValue* and_result = AddUncasted<HBitwise>(Token::BIT_AND,
1474                                              instance_type_and_bit_field,
1475                                              mask);
1476   HValue* sub_result = AddUncasted<HSub>(and_result,
1477                                          Add<HConstant>(JS_OBJECT_TYPE));
1478   Add<HBoundsCheck>(sub_result,
1479                     Add<HConstant>(LAST_JS_OBJECT_TYPE + 1 - JS_OBJECT_TYPE));
1480 }
1481
1482
1483 void HGraphBuilder::BuildKeyedIndexCheck(HValue* key,
1484                                          HIfContinuation* join_continuation) {
1485   // The sometimes unintuitively backward ordering of the ifs below is
1486   // convoluted, but necessary.  All of the paths must guarantee that the
1487   // if-true of the continuation returns a smi element index and the if-false of
1488   // the continuation returns either a symbol or a unique string key. All other
1489   // object types cause a deopt to fall back to the runtime.
1490
1491   IfBuilder key_smi_if(this);
1492   key_smi_if.If<HIsSmiAndBranch>(key);
1493   key_smi_if.Then();
1494   {
1495     Push(key);  // Nothing to do, just continue to true of continuation.
1496   }
1497   key_smi_if.Else();
1498   {
1499     HValue* map = Add<HLoadNamedField>(key, nullptr, HObjectAccess::ForMap());
1500     HValue* instance_type =
1501         Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
1502
1503     // Non-unique string, check for a string with a hash code that is actually
1504     // an index.
1505     STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE);
1506     IfBuilder not_string_or_name_if(this);
1507     not_string_or_name_if.If<HCompareNumericAndBranch>(
1508         instance_type,
1509         Add<HConstant>(LAST_UNIQUE_NAME_TYPE),
1510         Token::GT);
1511
1512     not_string_or_name_if.Then();
1513     {
1514       // Non-smi, non-Name, non-String: Try to convert to smi in case of
1515       // HeapNumber.
1516       // TODO(danno): This could call some variant of ToString
1517       Push(AddUncasted<HForceRepresentation>(key, Representation::Smi()));
1518     }
1519     not_string_or_name_if.Else();
1520     {
1521       // String or Name: check explicitly for Name, they can short-circuit
1522       // directly to unique non-index key path.
1523       IfBuilder not_symbol_if(this);
1524       not_symbol_if.If<HCompareNumericAndBranch>(
1525           instance_type,
1526           Add<HConstant>(SYMBOL_TYPE),
1527           Token::NE);
1528
1529       not_symbol_if.Then();
1530       {
1531         // String: check whether the String is a String of an index. If it is,
1532         // extract the index value from the hash.
1533         HValue* hash = Add<HLoadNamedField>(key, nullptr,
1534                                             HObjectAccess::ForNameHashField());
1535         HValue* not_index_mask = Add<HConstant>(static_cast<int>(
1536             String::kContainsCachedArrayIndexMask));
1537
1538         HValue* not_index_test = AddUncasted<HBitwise>(
1539             Token::BIT_AND, hash, not_index_mask);
1540
1541         IfBuilder string_index_if(this);
1542         string_index_if.If<HCompareNumericAndBranch>(not_index_test,
1543                                                      graph()->GetConstant0(),
1544                                                      Token::EQ);
1545         string_index_if.Then();
1546         {
1547           // String with index in hash: extract string and merge to index path.
1548           Push(BuildDecodeField<String::ArrayIndexValueBits>(hash));
1549         }
1550         string_index_if.Else();
1551         {
1552           // Key is a non-index String, check for uniqueness/internalization.
1553           // If it's not internalized yet, internalize it now.
1554           HValue* not_internalized_bit = AddUncasted<HBitwise>(
1555               Token::BIT_AND,
1556               instance_type,
1557               Add<HConstant>(static_cast<int>(kIsNotInternalizedMask)));
1558
1559           IfBuilder internalized(this);
1560           internalized.If<HCompareNumericAndBranch>(not_internalized_bit,
1561                                                     graph()->GetConstant0(),
1562                                                     Token::EQ);
1563           internalized.Then();
1564           Push(key);
1565
1566           internalized.Else();
1567           Add<HPushArguments>(key);
1568           HValue* intern_key = Add<HCallRuntime>(
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         Runtime::FunctionForId(is_strong(language_mode)
1727                                    ? Runtime::kKeyedGetPropertyStrong
1728                                    : Runtime::kKeyedGetProperty),
1729         2));
1730   }
1731   if_undefined.Else();
1732   {
1733     IfBuilder if_match(this);
1734     if_match.If<HCompareObjectEqAndBranch>(candidate_key, key);
1735     if_match.Then();
1736     if_match.Else();
1737
1738     // Update non-internalized string in the dictionary with internalized key?
1739     IfBuilder if_update_with_internalized(this);
1740     HValue* smi_check =
1741         if_update_with_internalized.IfNot<HIsSmiAndBranch>(candidate_key);
1742     if_update_with_internalized.And();
1743     HValue* map = AddLoadMap(candidate_key, smi_check);
1744     HValue* instance_type =
1745         Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
1746     HValue* not_internalized_bit = AddUncasted<HBitwise>(
1747         Token::BIT_AND, instance_type,
1748         Add<HConstant>(static_cast<int>(kIsNotInternalizedMask)));
1749     if_update_with_internalized.If<HCompareNumericAndBranch>(
1750         not_internalized_bit, graph()->GetConstant0(), Token::NE);
1751     if_update_with_internalized.And();
1752     if_update_with_internalized.IfNot<HCompareObjectEqAndBranch>(
1753         candidate_key, graph()->GetConstantHole());
1754     if_update_with_internalized.AndIf<HStringCompareAndBranch>(candidate_key,
1755                                                                key, Token::EQ);
1756     if_update_with_internalized.Then();
1757     // Replace a key that is a non-internalized string by the equivalent
1758     // internalized string for faster further lookups.
1759     Add<HStoreKeyed>(elements, key_index, key, FAST_ELEMENTS);
1760     if_update_with_internalized.Else();
1761
1762     if_update_with_internalized.JoinContinuation(&found_key_match_continuation);
1763     if_match.JoinContinuation(&found_key_match_continuation);
1764
1765     IfBuilder found_key_match(this, &found_key_match_continuation);
1766     found_key_match.Then();
1767     // Key at current probe matches. Relevant bits in the |details| field must
1768     // be zero, otherwise the dictionary element requires special handling.
1769     HValue* details_index =
1770         AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 2));
1771     details_index->ClearFlag(HValue::kCanOverflow);
1772     HValue* details =
1773         Add<HLoadKeyed>(elements, details_index, nullptr, FAST_ELEMENTS);
1774     int details_mask = PropertyDetails::TypeField::kMask;
1775     details = AddUncasted<HBitwise>(Token::BIT_AND, details,
1776                                     Add<HConstant>(details_mask));
1777     IfBuilder details_compare(this);
1778     details_compare.If<HCompareNumericAndBranch>(
1779         details, graph()->GetConstant0(), Token::EQ);
1780     details_compare.Then();
1781     HValue* result_index =
1782         AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 1));
1783     result_index->ClearFlag(HValue::kCanOverflow);
1784     Push(Add<HLoadKeyed>(elements, result_index, nullptr, FAST_ELEMENTS));
1785     details_compare.Else();
1786     Add<HPushArguments>(receiver, key);
1787     Push(Add<HCallRuntime>(
1788         Runtime::FunctionForId(is_strong(language_mode)
1789                                    ? Runtime::kKeyedGetPropertyStrong
1790                                    : Runtime::kKeyedGetProperty),
1791         2));
1792     details_compare.End();
1793
1794     found_key_match.Else();
1795     found_key_match.JoinContinuation(&return_or_loop_continuation);
1796   }
1797   if_undefined.JoinContinuation(&return_or_loop_continuation);
1798
1799   IfBuilder return_or_loop(this, &return_or_loop_continuation);
1800   return_or_loop.Then();
1801   probe_loop.Break();
1802
1803   return_or_loop.Else();
1804   entry = AddUncasted<HAdd>(entry, count);
1805   entry->ClearFlag(HValue::kCanOverflow);
1806   count = AddUncasted<HAdd>(count, graph()->GetConstant1());
1807   count->ClearFlag(HValue::kCanOverflow);
1808   Push(entry);
1809   Push(count);
1810
1811   probe_loop.EndBody();
1812
1813   return_or_loop.End();
1814
1815   return Pop();
1816 }
1817
1818
1819 HValue* HGraphBuilder::BuildCreateIterResultObject(HValue* value,
1820                                                    HValue* done) {
1821   NoObservableSideEffectsScope scope(this);
1822
1823   // Allocate the JSIteratorResult object.
1824   HValue* result =
1825       Add<HAllocate>(Add<HConstant>(JSIteratorResult::kSize), HType::JSObject(),
1826                      NOT_TENURED, JS_ITERATOR_RESULT_TYPE);
1827
1828   // Initialize the JSIteratorResult object.
1829   HValue* native_context = BuildGetNativeContext();
1830   HValue* map = Add<HLoadNamedField>(
1831       native_context, nullptr,
1832       HObjectAccess::ForContextSlot(Context::ITERATOR_RESULT_MAP_INDEX));
1833   Add<HStoreNamedField>(result, HObjectAccess::ForMap(), map);
1834   HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
1835   Add<HStoreNamedField>(result, HObjectAccess::ForPropertiesPointer(),
1836                         empty_fixed_array);
1837   Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(),
1838                         empty_fixed_array);
1839   Add<HStoreNamedField>(result, HObjectAccess::ForObservableJSObjectOffset(
1840                                     JSIteratorResult::kValueOffset),
1841                         value);
1842   Add<HStoreNamedField>(result, HObjectAccess::ForObservableJSObjectOffset(
1843                                     JSIteratorResult::kDoneOffset),
1844                         done);
1845   STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
1846   return result;
1847 }
1848
1849
1850 HValue* HGraphBuilder::BuildRegExpConstructResult(HValue* length,
1851                                                   HValue* index,
1852                                                   HValue* input) {
1853   NoObservableSideEffectsScope scope(this);
1854   HConstant* max_length = Add<HConstant>(JSObject::kInitialMaxFastElementArray);
1855   Add<HBoundsCheck>(length, max_length);
1856
1857   // Generate size calculation code here in order to make it dominate
1858   // the JSRegExpResult allocation.
1859   ElementsKind elements_kind = FAST_ELEMENTS;
1860   HValue* size = BuildCalculateElementsSize(elements_kind, length);
1861
1862   // Allocate the JSRegExpResult and the FixedArray in one step.
1863   HValue* result = Add<HAllocate>(
1864       Add<HConstant>(JSRegExpResult::kSize), HType::JSArray(),
1865       NOT_TENURED, JS_ARRAY_TYPE);
1866
1867   // Initialize the JSRegExpResult header.
1868   HValue* global_object = Add<HLoadNamedField>(
1869       context(), nullptr,
1870       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
1871   HValue* native_context = Add<HLoadNamedField>(
1872       global_object, nullptr, HObjectAccess::ForGlobalObjectNativeContext());
1873   Add<HStoreNamedField>(
1874       result, HObjectAccess::ForMap(),
1875       Add<HLoadNamedField>(
1876           native_context, nullptr,
1877           HObjectAccess::ForContextSlot(Context::REGEXP_RESULT_MAP_INDEX)));
1878   HConstant* empty_fixed_array =
1879       Add<HConstant>(isolate()->factory()->empty_fixed_array());
1880   Add<HStoreNamedField>(
1881       result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset),
1882       empty_fixed_array);
1883   Add<HStoreNamedField>(
1884       result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
1885       empty_fixed_array);
1886   Add<HStoreNamedField>(
1887       result, HObjectAccess::ForJSArrayOffset(JSArray::kLengthOffset), length);
1888
1889   // Initialize the additional fields.
1890   Add<HStoreNamedField>(
1891       result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kIndexOffset),
1892       index);
1893   Add<HStoreNamedField>(
1894       result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kInputOffset),
1895       input);
1896
1897   // Allocate and initialize the elements header.
1898   HAllocate* elements = BuildAllocateElements(elements_kind, size);
1899   BuildInitializeElementsHeader(elements, elements_kind, length);
1900
1901   if (!elements->has_size_upper_bound()) {
1902     HConstant* size_in_bytes_upper_bound = EstablishElementsAllocationSize(
1903         elements_kind, max_length->Integer32Value());
1904     elements->set_size_upper_bound(size_in_bytes_upper_bound);
1905   }
1906
1907   Add<HStoreNamedField>(
1908       result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
1909       elements);
1910
1911   // Initialize the elements contents with undefined.
1912   BuildFillElementsWithValue(
1913       elements, elements_kind, graph()->GetConstant0(), length,
1914       graph()->GetConstantUndefined());
1915
1916   return result;
1917 }
1918
1919
1920 HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) {
1921   NoObservableSideEffectsScope scope(this);
1922
1923   // Convert constant numbers at compile time.
1924   if (object->IsConstant() && HConstant::cast(object)->HasNumberValue()) {
1925     Handle<Object> number = HConstant::cast(object)->handle(isolate());
1926     Handle<String> result = isolate()->factory()->NumberToString(number);
1927     return Add<HConstant>(result);
1928   }
1929
1930   // Create a joinable continuation.
1931   HIfContinuation found(graph()->CreateBasicBlock(),
1932                         graph()->CreateBasicBlock());
1933
1934   // Load the number string cache.
1935   HValue* number_string_cache =
1936       Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex);
1937
1938   // Make the hash mask from the length of the number string cache. It
1939   // contains two elements (number and string) for each cache entry.
1940   HValue* mask = AddLoadFixedArrayLength(number_string_cache);
1941   mask->set_type(HType::Smi());
1942   mask = AddUncasted<HSar>(mask, graph()->GetConstant1());
1943   mask = AddUncasted<HSub>(mask, graph()->GetConstant1());
1944
1945   // Check whether object is a smi.
1946   IfBuilder if_objectissmi(this);
1947   if_objectissmi.If<HIsSmiAndBranch>(object);
1948   if_objectissmi.Then();
1949   {
1950     // Compute hash for smi similar to smi_get_hash().
1951     HValue* hash = AddUncasted<HBitwise>(Token::BIT_AND, object, mask);
1952
1953     // Load the key.
1954     HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
1955     HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, nullptr,
1956                                   FAST_ELEMENTS, ALLOW_RETURN_HOLE);
1957
1958     // Check if object == key.
1959     IfBuilder if_objectiskey(this);
1960     if_objectiskey.If<HCompareObjectEqAndBranch>(object, key);
1961     if_objectiskey.Then();
1962     {
1963       // Make the key_index available.
1964       Push(key_index);
1965     }
1966     if_objectiskey.JoinContinuation(&found);
1967   }
1968   if_objectissmi.Else();
1969   {
1970     if (type->Is(Type::SignedSmall())) {
1971       if_objectissmi.Deopt(Deoptimizer::kExpectedSmi);
1972     } else {
1973       // Check if the object is a heap number.
1974       IfBuilder if_objectisnumber(this);
1975       HValue* objectisnumber = if_objectisnumber.If<HCompareMap>(
1976           object, isolate()->factory()->heap_number_map());
1977       if_objectisnumber.Then();
1978       {
1979         // Compute hash for heap number similar to double_get_hash().
1980         HValue* low = Add<HLoadNamedField>(
1981             object, objectisnumber,
1982             HObjectAccess::ForHeapNumberValueLowestBits());
1983         HValue* high = Add<HLoadNamedField>(
1984             object, objectisnumber,
1985             HObjectAccess::ForHeapNumberValueHighestBits());
1986         HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, low, high);
1987         hash = AddUncasted<HBitwise>(Token::BIT_AND, hash, mask);
1988
1989         // Load the key.
1990         HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
1991         HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, nullptr,
1992                                       FAST_ELEMENTS, ALLOW_RETURN_HOLE);
1993
1994         // Check if the key is a heap number and compare it with the object.
1995         IfBuilder if_keyisnotsmi(this);
1996         HValue* keyisnotsmi = if_keyisnotsmi.IfNot<HIsSmiAndBranch>(key);
1997         if_keyisnotsmi.Then();
1998         {
1999           IfBuilder if_keyisheapnumber(this);
2000           if_keyisheapnumber.If<HCompareMap>(
2001               key, isolate()->factory()->heap_number_map());
2002           if_keyisheapnumber.Then();
2003           {
2004             // Check if values of key and object match.
2005             IfBuilder if_keyeqobject(this);
2006             if_keyeqobject.If<HCompareNumericAndBranch>(
2007                 Add<HLoadNamedField>(key, keyisnotsmi,
2008                                      HObjectAccess::ForHeapNumberValue()),
2009                 Add<HLoadNamedField>(object, objectisnumber,
2010                                      HObjectAccess::ForHeapNumberValue()),
2011                 Token::EQ);
2012             if_keyeqobject.Then();
2013             {
2014               // Make the key_index available.
2015               Push(key_index);
2016             }
2017             if_keyeqobject.JoinContinuation(&found);
2018           }
2019           if_keyisheapnumber.JoinContinuation(&found);
2020         }
2021         if_keyisnotsmi.JoinContinuation(&found);
2022       }
2023       if_objectisnumber.Else();
2024       {
2025         if (type->Is(Type::Number())) {
2026           if_objectisnumber.Deopt(Deoptimizer::kExpectedHeapNumber);
2027         }
2028       }
2029       if_objectisnumber.JoinContinuation(&found);
2030     }
2031   }
2032   if_objectissmi.JoinContinuation(&found);
2033
2034   // Check for cache hit.
2035   IfBuilder if_found(this, &found);
2036   if_found.Then();
2037   {
2038     // Count number to string operation in native code.
2039     AddIncrementCounter(isolate()->counters()->number_to_string_native());
2040
2041     // Load the value in case of cache hit.
2042     HValue* key_index = Pop();
2043     HValue* value_index = AddUncasted<HAdd>(key_index, graph()->GetConstant1());
2044     Push(Add<HLoadKeyed>(number_string_cache, value_index, nullptr,
2045                          FAST_ELEMENTS, ALLOW_RETURN_HOLE));
2046   }
2047   if_found.Else();
2048   {
2049     // Cache miss, fallback to runtime.
2050     Add<HPushArguments>(object);
2051     Push(Add<HCallRuntime>(
2052             Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
2053             1));
2054   }
2055   if_found.End();
2056
2057   return Pop();
2058 }
2059
2060
2061 HValue* HGraphBuilder::BuildToObject(HValue* receiver) {
2062   NoObservableSideEffectsScope scope(this);
2063
2064   // Create a joinable continuation.
2065   HIfContinuation wrap(graph()->CreateBasicBlock(),
2066                        graph()->CreateBasicBlock());
2067
2068   // Determine the proper global constructor function required to wrap
2069   // {receiver} into a JSValue, unless {receiver} is already a {JSReceiver}, in
2070   // which case we just return it.  Deopts to Runtime::kToObject if {receiver}
2071   // is undefined or null.
2072   IfBuilder receiver_is_smi(this);
2073   receiver_is_smi.If<HIsSmiAndBranch>(receiver);
2074   receiver_is_smi.Then();
2075   {
2076     // Use global Number function.
2077     Push(Add<HConstant>(Context::NUMBER_FUNCTION_INDEX));
2078   }
2079   receiver_is_smi.Else();
2080   {
2081     // Determine {receiver} map and instance type.
2082     HValue* receiver_map =
2083         Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
2084     HValue* receiver_instance_type = Add<HLoadNamedField>(
2085         receiver_map, nullptr, HObjectAccess::ForMapInstanceType());
2086
2087     // First check whether {receiver} is already a spec object (fast case).
2088     IfBuilder receiver_is_not_spec_object(this);
2089     receiver_is_not_spec_object.If<HCompareNumericAndBranch>(
2090         receiver_instance_type, Add<HConstant>(FIRST_SPEC_OBJECT_TYPE),
2091         Token::LT);
2092     receiver_is_not_spec_object.Then();
2093     {
2094       // Load the constructor function index from the {receiver} map.
2095       HValue* constructor_function_index = Add<HLoadNamedField>(
2096           receiver_map, nullptr,
2097           HObjectAccess::ForMapInObjectPropertiesOrConstructorFunctionIndex());
2098
2099       // Check if {receiver} has a constructor (null and undefined have no
2100       // constructors, so we deoptimize to the runtime to throw an exception).
2101       IfBuilder constructor_function_index_is_invalid(this);
2102       constructor_function_index_is_invalid.If<HCompareNumericAndBranch>(
2103           constructor_function_index,
2104           Add<HConstant>(Map::kNoConstructorFunctionIndex), Token::EQ);
2105       constructor_function_index_is_invalid.ThenDeopt(
2106           Deoptimizer::kUndefinedOrNullInToObject);
2107       constructor_function_index_is_invalid.End();
2108
2109       // Use the global constructor function.
2110       Push(constructor_function_index);
2111     }
2112     receiver_is_not_spec_object.JoinContinuation(&wrap);
2113   }
2114   receiver_is_smi.JoinContinuation(&wrap);
2115
2116   // Wrap the receiver if necessary.
2117   IfBuilder if_wrap(this, &wrap);
2118   if_wrap.Then();
2119   {
2120     // Grab the constructor function index.
2121     HValue* constructor_index = Pop();
2122
2123     // Load native context.
2124     HValue* native_context = BuildGetNativeContext();
2125
2126     // Determine the initial map for the global constructor.
2127     HValue* constructor = Add<HLoadKeyed>(native_context, constructor_index,
2128                                           nullptr, FAST_ELEMENTS);
2129     HValue* constructor_initial_map = Add<HLoadNamedField>(
2130         constructor, nullptr, HObjectAccess::ForPrototypeOrInitialMap());
2131     // Allocate and initialize a JSValue wrapper.
2132     HValue* value =
2133         BuildAllocate(Add<HConstant>(JSValue::kSize), HType::JSObject(),
2134                       JS_VALUE_TYPE, HAllocationMode());
2135     Add<HStoreNamedField>(value, HObjectAccess::ForMap(),
2136                           constructor_initial_map);
2137     HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
2138     Add<HStoreNamedField>(value, HObjectAccess::ForPropertiesPointer(),
2139                           empty_fixed_array);
2140     Add<HStoreNamedField>(value, HObjectAccess::ForElementsPointer(),
2141                           empty_fixed_array);
2142     Add<HStoreNamedField>(value, HObjectAccess::ForObservableJSObjectOffset(
2143                                      JSValue::kValueOffset),
2144                           receiver);
2145     Push(value);
2146   }
2147   if_wrap.Else();
2148   { Push(receiver); }
2149   if_wrap.End();
2150   return Pop();
2151 }
2152
2153
2154 HAllocate* HGraphBuilder::BuildAllocate(
2155     HValue* object_size,
2156     HType type,
2157     InstanceType instance_type,
2158     HAllocationMode allocation_mode) {
2159   // Compute the effective allocation size.
2160   HValue* size = object_size;
2161   if (allocation_mode.CreateAllocationMementos()) {
2162     size = AddUncasted<HAdd>(size, Add<HConstant>(AllocationMemento::kSize));
2163     size->ClearFlag(HValue::kCanOverflow);
2164   }
2165
2166   // Perform the actual allocation.
2167   HAllocate* object = Add<HAllocate>(
2168       size, type, allocation_mode.GetPretenureMode(),
2169       instance_type, allocation_mode.feedback_site());
2170
2171   // Setup the allocation memento.
2172   if (allocation_mode.CreateAllocationMementos()) {
2173     BuildCreateAllocationMemento(
2174         object, object_size, allocation_mode.current_site());
2175   }
2176
2177   return object;
2178 }
2179
2180
2181 HValue* HGraphBuilder::BuildAddStringLengths(HValue* left_length,
2182                                              HValue* right_length) {
2183   // Compute the combined string length and check against max string length.
2184   HValue* length = AddUncasted<HAdd>(left_length, right_length);
2185   // Check that length <= kMaxLength <=> length < MaxLength + 1.
2186   HValue* max_length = Add<HConstant>(String::kMaxLength + 1);
2187   Add<HBoundsCheck>(length, max_length);
2188   return length;
2189 }
2190
2191
2192 HValue* HGraphBuilder::BuildCreateConsString(
2193     HValue* length,
2194     HValue* left,
2195     HValue* right,
2196     HAllocationMode allocation_mode) {
2197   // Determine the string instance types.
2198   HInstruction* left_instance_type = AddLoadStringInstanceType(left);
2199   HInstruction* right_instance_type = AddLoadStringInstanceType(right);
2200
2201   // Allocate the cons string object. HAllocate does not care whether we
2202   // pass CONS_STRING_TYPE or CONS_ONE_BYTE_STRING_TYPE here, so we just use
2203   // CONS_STRING_TYPE here. Below we decide whether the cons string is
2204   // one-byte or two-byte and set the appropriate map.
2205   DCHECK(HAllocate::CompatibleInstanceTypes(CONS_STRING_TYPE,
2206                                             CONS_ONE_BYTE_STRING_TYPE));
2207   HAllocate* result = BuildAllocate(Add<HConstant>(ConsString::kSize),
2208                                     HType::String(), CONS_STRING_TYPE,
2209                                     allocation_mode);
2210
2211   // Compute intersection and difference of instance types.
2212   HValue* anded_instance_types = AddUncasted<HBitwise>(
2213       Token::BIT_AND, left_instance_type, right_instance_type);
2214   HValue* xored_instance_types = AddUncasted<HBitwise>(
2215       Token::BIT_XOR, left_instance_type, right_instance_type);
2216
2217   // We create a one-byte cons string if
2218   // 1. both strings are one-byte, or
2219   // 2. at least one of the strings is two-byte, but happens to contain only
2220   //    one-byte characters.
2221   // To do this, we check
2222   // 1. if both strings are one-byte, or if the one-byte data hint is set in
2223   //    both strings, or
2224   // 2. if one of the strings has the one-byte data hint set and the other
2225   //    string is one-byte.
2226   IfBuilder if_onebyte(this);
2227   STATIC_ASSERT(kOneByteStringTag != 0);
2228   STATIC_ASSERT(kOneByteDataHintMask != 0);
2229   if_onebyte.If<HCompareNumericAndBranch>(
2230       AddUncasted<HBitwise>(
2231           Token::BIT_AND, anded_instance_types,
2232           Add<HConstant>(static_cast<int32_t>(
2233                   kStringEncodingMask | kOneByteDataHintMask))),
2234       graph()->GetConstant0(), Token::NE);
2235   if_onebyte.Or();
2236   STATIC_ASSERT(kOneByteStringTag != 0 &&
2237                 kOneByteDataHintTag != 0 &&
2238                 kOneByteDataHintTag != kOneByteStringTag);
2239   if_onebyte.If<HCompareNumericAndBranch>(
2240       AddUncasted<HBitwise>(
2241           Token::BIT_AND, xored_instance_types,
2242           Add<HConstant>(static_cast<int32_t>(
2243                   kOneByteStringTag | kOneByteDataHintTag))),
2244       Add<HConstant>(static_cast<int32_t>(
2245               kOneByteStringTag | kOneByteDataHintTag)), Token::EQ);
2246   if_onebyte.Then();
2247   {
2248     // We can safely skip the write barrier for storing the map here.
2249     Add<HStoreNamedField>(
2250         result, HObjectAccess::ForMap(),
2251         Add<HConstant>(isolate()->factory()->cons_one_byte_string_map()));
2252   }
2253   if_onebyte.Else();
2254   {
2255     // We can safely skip the write barrier for storing the map here.
2256     Add<HStoreNamedField>(
2257         result, HObjectAccess::ForMap(),
2258         Add<HConstant>(isolate()->factory()->cons_string_map()));
2259   }
2260   if_onebyte.End();
2261
2262   // Initialize the cons string fields.
2263   Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
2264                         Add<HConstant>(String::kEmptyHashField));
2265   Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
2266   Add<HStoreNamedField>(result, HObjectAccess::ForConsStringFirst(), left);
2267   Add<HStoreNamedField>(result, HObjectAccess::ForConsStringSecond(), right);
2268
2269   // Count the native string addition.
2270   AddIncrementCounter(isolate()->counters()->string_add_native());
2271
2272   return result;
2273 }
2274
2275
2276 void HGraphBuilder::BuildCopySeqStringChars(HValue* src,
2277                                             HValue* src_offset,
2278                                             String::Encoding src_encoding,
2279                                             HValue* dst,
2280                                             HValue* dst_offset,
2281                                             String::Encoding dst_encoding,
2282                                             HValue* length) {
2283   DCHECK(dst_encoding != String::ONE_BYTE_ENCODING ||
2284          src_encoding == String::ONE_BYTE_ENCODING);
2285   LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
2286   HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT);
2287   {
2288     HValue* src_index = AddUncasted<HAdd>(src_offset, index);
2289     HValue* value =
2290         AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index);
2291     HValue* dst_index = AddUncasted<HAdd>(dst_offset, index);
2292     Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value);
2293   }
2294   loop.EndBody();
2295 }
2296
2297
2298 HValue* HGraphBuilder::BuildObjectSizeAlignment(
2299     HValue* unaligned_size, int header_size) {
2300   DCHECK((header_size & kObjectAlignmentMask) == 0);
2301   HValue* size = AddUncasted<HAdd>(
2302       unaligned_size, Add<HConstant>(static_cast<int32_t>(
2303           header_size + kObjectAlignmentMask)));
2304   size->ClearFlag(HValue::kCanOverflow);
2305   return AddUncasted<HBitwise>(
2306       Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>(
2307           ~kObjectAlignmentMask)));
2308 }
2309
2310
2311 HValue* HGraphBuilder::BuildUncheckedStringAdd(
2312     HValue* left,
2313     HValue* right,
2314     HAllocationMode allocation_mode) {
2315   // Determine the string lengths.
2316   HValue* left_length = AddLoadStringLength(left);
2317   HValue* right_length = AddLoadStringLength(right);
2318
2319   // Compute the combined string length.
2320   HValue* length = BuildAddStringLengths(left_length, right_length);
2321
2322   // Do some manual constant folding here.
2323   if (left_length->IsConstant()) {
2324     HConstant* c_left_length = HConstant::cast(left_length);
2325     DCHECK_NE(0, c_left_length->Integer32Value());
2326     if (c_left_length->Integer32Value() + 1 >= ConsString::kMinLength) {
2327       // The right string contains at least one character.
2328       return BuildCreateConsString(length, left, right, allocation_mode);
2329     }
2330   } else if (right_length->IsConstant()) {
2331     HConstant* c_right_length = HConstant::cast(right_length);
2332     DCHECK_NE(0, c_right_length->Integer32Value());
2333     if (c_right_length->Integer32Value() + 1 >= ConsString::kMinLength) {
2334       // The left string contains at least one character.
2335       return BuildCreateConsString(length, left, right, allocation_mode);
2336     }
2337   }
2338
2339   // Check if we should create a cons string.
2340   IfBuilder if_createcons(this);
2341   if_createcons.If<HCompareNumericAndBranch>(
2342       length, Add<HConstant>(ConsString::kMinLength), Token::GTE);
2343   if_createcons.Then();
2344   {
2345     // Create a cons string.
2346     Push(BuildCreateConsString(length, left, right, allocation_mode));
2347   }
2348   if_createcons.Else();
2349   {
2350     // Determine the string instance types.
2351     HValue* left_instance_type = AddLoadStringInstanceType(left);
2352     HValue* right_instance_type = AddLoadStringInstanceType(right);
2353
2354     // Compute union and difference of instance types.
2355     HValue* ored_instance_types = AddUncasted<HBitwise>(
2356         Token::BIT_OR, left_instance_type, right_instance_type);
2357     HValue* xored_instance_types = AddUncasted<HBitwise>(
2358         Token::BIT_XOR, left_instance_type, right_instance_type);
2359
2360     // Check if both strings have the same encoding and both are
2361     // sequential.
2362     IfBuilder if_sameencodingandsequential(this);
2363     if_sameencodingandsequential.If<HCompareNumericAndBranch>(
2364         AddUncasted<HBitwise>(
2365             Token::BIT_AND, xored_instance_types,
2366             Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
2367         graph()->GetConstant0(), Token::EQ);
2368     if_sameencodingandsequential.And();
2369     STATIC_ASSERT(kSeqStringTag == 0);
2370     if_sameencodingandsequential.If<HCompareNumericAndBranch>(
2371         AddUncasted<HBitwise>(
2372             Token::BIT_AND, ored_instance_types,
2373             Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))),
2374         graph()->GetConstant0(), Token::EQ);
2375     if_sameencodingandsequential.Then();
2376     {
2377       HConstant* string_map =
2378           Add<HConstant>(isolate()->factory()->string_map());
2379       HConstant* one_byte_string_map =
2380           Add<HConstant>(isolate()->factory()->one_byte_string_map());
2381
2382       // Determine map and size depending on whether result is one-byte string.
2383       IfBuilder if_onebyte(this);
2384       STATIC_ASSERT(kOneByteStringTag != 0);
2385       if_onebyte.If<HCompareNumericAndBranch>(
2386           AddUncasted<HBitwise>(
2387               Token::BIT_AND, ored_instance_types,
2388               Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
2389           graph()->GetConstant0(), Token::NE);
2390       if_onebyte.Then();
2391       {
2392         // Allocate sequential one-byte string object.
2393         Push(length);
2394         Push(one_byte_string_map);
2395       }
2396       if_onebyte.Else();
2397       {
2398         // Allocate sequential two-byte string object.
2399         HValue* size = AddUncasted<HShl>(length, graph()->GetConstant1());
2400         size->ClearFlag(HValue::kCanOverflow);
2401         size->SetFlag(HValue::kUint32);
2402         Push(size);
2403         Push(string_map);
2404       }
2405       if_onebyte.End();
2406       HValue* map = Pop();
2407
2408       // Calculate the number of bytes needed for the characters in the
2409       // string while observing object alignment.
2410       STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0);
2411       HValue* size = BuildObjectSizeAlignment(Pop(), SeqString::kHeaderSize);
2412
2413       // Allocate the string object. HAllocate does not care whether we pass
2414       // STRING_TYPE or ONE_BYTE_STRING_TYPE here, so we just use STRING_TYPE.
2415       HAllocate* result = BuildAllocate(
2416           size, HType::String(), STRING_TYPE, allocation_mode);
2417       Add<HStoreNamedField>(result, HObjectAccess::ForMap(), map);
2418
2419       // Initialize the string fields.
2420       Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
2421                             Add<HConstant>(String::kEmptyHashField));
2422       Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
2423
2424       // Copy characters to the result string.
2425       IfBuilder if_twobyte(this);
2426       if_twobyte.If<HCompareObjectEqAndBranch>(map, string_map);
2427       if_twobyte.Then();
2428       {
2429         // Copy characters from the left string.
2430         BuildCopySeqStringChars(
2431             left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
2432             result, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
2433             left_length);
2434
2435         // Copy characters from the right string.
2436         BuildCopySeqStringChars(
2437             right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
2438             result, left_length, String::TWO_BYTE_ENCODING,
2439             right_length);
2440       }
2441       if_twobyte.Else();
2442       {
2443         // Copy characters from the left string.
2444         BuildCopySeqStringChars(
2445             left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
2446             result, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
2447             left_length);
2448
2449         // Copy characters from the right string.
2450         BuildCopySeqStringChars(
2451             right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
2452             result, left_length, String::ONE_BYTE_ENCODING,
2453             right_length);
2454       }
2455       if_twobyte.End();
2456
2457       // Count the native string addition.
2458       AddIncrementCounter(isolate()->counters()->string_add_native());
2459
2460       // Return the sequential string.
2461       Push(result);
2462     }
2463     if_sameencodingandsequential.Else();
2464     {
2465       // Fallback to the runtime to add the two strings.
2466       Add<HPushArguments>(left, right);
2467       Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kStringAdd), 2));
2468     }
2469     if_sameencodingandsequential.End();
2470   }
2471   if_createcons.End();
2472
2473   return Pop();
2474 }
2475
2476
2477 HValue* HGraphBuilder::BuildStringAdd(
2478     HValue* left,
2479     HValue* right,
2480     HAllocationMode allocation_mode) {
2481   NoObservableSideEffectsScope no_effects(this);
2482
2483   // Determine string lengths.
2484   HValue* left_length = AddLoadStringLength(left);
2485   HValue* right_length = AddLoadStringLength(right);
2486
2487   // Check if left string is empty.
2488   IfBuilder if_leftempty(this);
2489   if_leftempty.If<HCompareNumericAndBranch>(
2490       left_length, graph()->GetConstant0(), Token::EQ);
2491   if_leftempty.Then();
2492   {
2493     // Count the native string addition.
2494     AddIncrementCounter(isolate()->counters()->string_add_native());
2495
2496     // Just return the right string.
2497     Push(right);
2498   }
2499   if_leftempty.Else();
2500   {
2501     // Check if right string is empty.
2502     IfBuilder if_rightempty(this);
2503     if_rightempty.If<HCompareNumericAndBranch>(
2504         right_length, graph()->GetConstant0(), Token::EQ);
2505     if_rightempty.Then();
2506     {
2507       // Count the native string addition.
2508       AddIncrementCounter(isolate()->counters()->string_add_native());
2509
2510       // Just return the left string.
2511       Push(left);
2512     }
2513     if_rightempty.Else();
2514     {
2515       // Add the two non-empty strings.
2516       Push(BuildUncheckedStringAdd(left, right, allocation_mode));
2517     }
2518     if_rightempty.End();
2519   }
2520   if_leftempty.End();
2521
2522   return Pop();
2523 }
2524
2525
2526 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
2527     HValue* checked_object,
2528     HValue* key,
2529     HValue* val,
2530     bool is_js_array,
2531     ElementsKind elements_kind,
2532     PropertyAccessType access_type,
2533     LoadKeyedHoleMode load_mode,
2534     KeyedAccessStoreMode store_mode) {
2535   DCHECK(top_info()->IsStub() || checked_object->IsCompareMap() ||
2536          checked_object->IsCheckMaps());
2537   DCHECK(!IsFixedTypedArrayElementsKind(elements_kind) || !is_js_array);
2538   // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
2539   // on a HElementsTransition instruction. The flag can also be removed if the
2540   // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
2541   // ElementsKind transitions. Finally, the dependency can be removed for stores
2542   // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
2543   // generated store code.
2544   if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
2545       (elements_kind == FAST_ELEMENTS && access_type == STORE)) {
2546     checked_object->ClearDependsOnFlag(kElementsKind);
2547   }
2548
2549   bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
2550   bool fast_elements = IsFastObjectElementsKind(elements_kind);
2551   HValue* elements = AddLoadElements(checked_object);
2552   if (access_type == STORE && (fast_elements || fast_smi_only_elements) &&
2553       store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
2554     HCheckMaps* check_cow_map = Add<HCheckMaps>(
2555         elements, isolate()->factory()->fixed_array_map());
2556     check_cow_map->ClearDependsOnFlag(kElementsKind);
2557   }
2558   HInstruction* length = NULL;
2559   if (is_js_array) {
2560     length = Add<HLoadNamedField>(
2561         checked_object->ActualValue(), checked_object,
2562         HObjectAccess::ForArrayLength(elements_kind));
2563   } else {
2564     length = AddLoadFixedArrayLength(elements);
2565   }
2566   length->set_type(HType::Smi());
2567   HValue* checked_key = NULL;
2568   if (IsFixedTypedArrayElementsKind(elements_kind)) {
2569     checked_object = Add<HCheckArrayBufferNotNeutered>(checked_object);
2570
2571     HValue* external_pointer = Add<HLoadNamedField>(
2572         elements, nullptr,
2573         HObjectAccess::ForFixedTypedArrayBaseExternalPointer());
2574     HValue* base_pointer = Add<HLoadNamedField>(
2575         elements, nullptr, HObjectAccess::ForFixedTypedArrayBaseBasePointer());
2576     HValue* backing_store = AddUncasted<HAdd>(
2577         external_pointer, base_pointer, Strength::WEAK, AddOfExternalAndTagged);
2578
2579     if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
2580       NoObservableSideEffectsScope no_effects(this);
2581       IfBuilder length_checker(this);
2582       length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
2583       length_checker.Then();
2584       IfBuilder negative_checker(this);
2585       HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
2586           key, graph()->GetConstant0(), Token::GTE);
2587       negative_checker.Then();
2588       HInstruction* result = AddElementAccess(
2589           backing_store, key, val, bounds_check, elements_kind, access_type);
2590       negative_checker.ElseDeopt(Deoptimizer::kNegativeKeyEncountered);
2591       negative_checker.End();
2592       length_checker.End();
2593       return result;
2594     } else {
2595       DCHECK(store_mode == STANDARD_STORE);
2596       checked_key = Add<HBoundsCheck>(key, length);
2597       return AddElementAccess(
2598           backing_store, checked_key, val,
2599           checked_object, elements_kind, access_type);
2600     }
2601   }
2602   DCHECK(fast_smi_only_elements ||
2603          fast_elements ||
2604          IsFastDoubleElementsKind(elements_kind));
2605
2606   // In case val is stored into a fast smi array, assure that the value is a smi
2607   // before manipulating the backing store. Otherwise the actual store may
2608   // deopt, leaving the backing store in an invalid state.
2609   if (access_type == STORE && IsFastSmiElementsKind(elements_kind) &&
2610       !val->type().IsSmi()) {
2611     val = AddUncasted<HForceRepresentation>(val, Representation::Smi());
2612   }
2613
2614   if (IsGrowStoreMode(store_mode)) {
2615     NoObservableSideEffectsScope no_effects(this);
2616     Representation representation = HStoreKeyed::RequiredValueRepresentation(
2617         elements_kind, STORE_TO_INITIALIZED_ENTRY);
2618     val = AddUncasted<HForceRepresentation>(val, representation);
2619     elements = BuildCheckForCapacityGrow(checked_object, elements,
2620                                          elements_kind, length, key,
2621                                          is_js_array, access_type);
2622     checked_key = key;
2623   } else {
2624     checked_key = Add<HBoundsCheck>(key, length);
2625
2626     if (access_type == STORE && (fast_elements || fast_smi_only_elements)) {
2627       if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
2628         NoObservableSideEffectsScope no_effects(this);
2629         elements = BuildCopyElementsOnWrite(checked_object, elements,
2630                                             elements_kind, length);
2631       } else {
2632         HCheckMaps* check_cow_map = Add<HCheckMaps>(
2633             elements, isolate()->factory()->fixed_array_map());
2634         check_cow_map->ClearDependsOnFlag(kElementsKind);
2635       }
2636     }
2637   }
2638   return AddElementAccess(elements, checked_key, val, checked_object,
2639                           elements_kind, access_type, load_mode);
2640 }
2641
2642
2643 HValue* HGraphBuilder::BuildAllocateArrayFromLength(
2644     JSArrayBuilder* array_builder,
2645     HValue* length_argument) {
2646   if (length_argument->IsConstant() &&
2647       HConstant::cast(length_argument)->HasSmiValue()) {
2648     int array_length = HConstant::cast(length_argument)->Integer32Value();
2649     if (array_length == 0) {
2650       return array_builder->AllocateEmptyArray();
2651     } else {
2652       return array_builder->AllocateArray(length_argument,
2653                                           array_length,
2654                                           length_argument);
2655     }
2656   }
2657
2658   HValue* constant_zero = graph()->GetConstant0();
2659   HConstant* max_alloc_length =
2660       Add<HConstant>(JSObject::kInitialMaxFastElementArray);
2661   HInstruction* checked_length = Add<HBoundsCheck>(length_argument,
2662                                                    max_alloc_length);
2663   IfBuilder if_builder(this);
2664   if_builder.If<HCompareNumericAndBranch>(checked_length, constant_zero,
2665                                           Token::EQ);
2666   if_builder.Then();
2667   const int initial_capacity = JSArray::kPreallocatedArrayElements;
2668   HConstant* initial_capacity_node = Add<HConstant>(initial_capacity);
2669   Push(initial_capacity_node);  // capacity
2670   Push(constant_zero);          // length
2671   if_builder.Else();
2672   if (!(top_info()->IsStub()) &&
2673       IsFastPackedElementsKind(array_builder->kind())) {
2674     // We'll come back later with better (holey) feedback.
2675     if_builder.Deopt(
2676         Deoptimizer::kHoleyArrayDespitePackedElements_kindFeedback);
2677   } else {
2678     Push(checked_length);         // capacity
2679     Push(checked_length);         // length
2680   }
2681   if_builder.End();
2682
2683   // Figure out total size
2684   HValue* length = Pop();
2685   HValue* capacity = Pop();
2686   return array_builder->AllocateArray(capacity, max_alloc_length, length);
2687 }
2688
2689
2690 HValue* HGraphBuilder::BuildCalculateElementsSize(ElementsKind kind,
2691                                                   HValue* capacity) {
2692   int elements_size = IsFastDoubleElementsKind(kind)
2693       ? kDoubleSize
2694       : kPointerSize;
2695
2696   HConstant* elements_size_value = Add<HConstant>(elements_size);
2697   HInstruction* mul =
2698       HMul::NewImul(isolate(), zone(), context(), capacity->ActualValue(),
2699                     elements_size_value);
2700   AddInstruction(mul);
2701   mul->ClearFlag(HValue::kCanOverflow);
2702
2703   STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize);
2704
2705   HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize);
2706   HValue* total_size = AddUncasted<HAdd>(mul, header_size);
2707   total_size->ClearFlag(HValue::kCanOverflow);
2708   return total_size;
2709 }
2710
2711
2712 HAllocate* HGraphBuilder::AllocateJSArrayObject(AllocationSiteMode mode) {
2713   int base_size = JSArray::kSize;
2714   if (mode == TRACK_ALLOCATION_SITE) {
2715     base_size += AllocationMemento::kSize;
2716   }
2717   HConstant* size_in_bytes = Add<HConstant>(base_size);
2718   return Add<HAllocate>(
2719       size_in_bytes, HType::JSArray(), NOT_TENURED, JS_OBJECT_TYPE);
2720 }
2721
2722
2723 HConstant* HGraphBuilder::EstablishElementsAllocationSize(
2724     ElementsKind kind,
2725     int capacity) {
2726   int base_size = IsFastDoubleElementsKind(kind)
2727       ? FixedDoubleArray::SizeFor(capacity)
2728       : FixedArray::SizeFor(capacity);
2729
2730   return Add<HConstant>(base_size);
2731 }
2732
2733
2734 HAllocate* HGraphBuilder::BuildAllocateElements(ElementsKind kind,
2735                                                 HValue* size_in_bytes) {
2736   InstanceType instance_type = IsFastDoubleElementsKind(kind)
2737       ? FIXED_DOUBLE_ARRAY_TYPE
2738       : FIXED_ARRAY_TYPE;
2739
2740   return Add<HAllocate>(size_in_bytes, HType::HeapObject(), NOT_TENURED,
2741                         instance_type);
2742 }
2743
2744
2745 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements,
2746                                                   ElementsKind kind,
2747                                                   HValue* capacity) {
2748   Factory* factory = isolate()->factory();
2749   Handle<Map> map = IsFastDoubleElementsKind(kind)
2750       ? factory->fixed_double_array_map()
2751       : factory->fixed_array_map();
2752
2753   Add<HStoreNamedField>(elements, HObjectAccess::ForMap(), Add<HConstant>(map));
2754   Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(),
2755                         capacity);
2756 }
2757
2758
2759 HValue* HGraphBuilder::BuildAllocateAndInitializeArray(ElementsKind kind,
2760                                                        HValue* capacity) {
2761   // The HForceRepresentation is to prevent possible deopt on int-smi
2762   // conversion after allocation but before the new object fields are set.
2763   capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi());
2764   HValue* size_in_bytes = BuildCalculateElementsSize(kind, capacity);
2765   HValue* new_array = BuildAllocateElements(kind, size_in_bytes);
2766   BuildInitializeElementsHeader(new_array, kind, capacity);
2767   return new_array;
2768 }
2769
2770
2771 void HGraphBuilder::BuildJSArrayHeader(HValue* array,
2772                                        HValue* array_map,
2773                                        HValue* elements,
2774                                        AllocationSiteMode mode,
2775                                        ElementsKind elements_kind,
2776                                        HValue* allocation_site_payload,
2777                                        HValue* length_field) {
2778   Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map);
2779
2780   HConstant* empty_fixed_array =
2781     Add<HConstant>(isolate()->factory()->empty_fixed_array());
2782
2783   Add<HStoreNamedField>(
2784       array, HObjectAccess::ForPropertiesPointer(), empty_fixed_array);
2785
2786   Add<HStoreNamedField>(
2787       array, HObjectAccess::ForElementsPointer(),
2788       elements != NULL ? elements : empty_fixed_array);
2789
2790   Add<HStoreNamedField>(
2791       array, HObjectAccess::ForArrayLength(elements_kind), length_field);
2792
2793   if (mode == TRACK_ALLOCATION_SITE) {
2794     BuildCreateAllocationMemento(
2795         array, Add<HConstant>(JSArray::kSize), allocation_site_payload);
2796   }
2797 }
2798
2799
2800 HInstruction* HGraphBuilder::AddElementAccess(
2801     HValue* elements,
2802     HValue* checked_key,
2803     HValue* val,
2804     HValue* dependency,
2805     ElementsKind elements_kind,
2806     PropertyAccessType access_type,
2807     LoadKeyedHoleMode load_mode) {
2808   if (access_type == STORE) {
2809     DCHECK(val != NULL);
2810     if (elements_kind == UINT8_CLAMPED_ELEMENTS) {
2811       val = Add<HClampToUint8>(val);
2812     }
2813     return Add<HStoreKeyed>(elements, checked_key, val, elements_kind,
2814                             STORE_TO_INITIALIZED_ENTRY);
2815   }
2816
2817   DCHECK(access_type == LOAD);
2818   DCHECK(val == NULL);
2819   HLoadKeyed* load = Add<HLoadKeyed>(
2820       elements, checked_key, dependency, elements_kind, load_mode);
2821   if (elements_kind == UINT32_ELEMENTS) {
2822     graph()->RecordUint32Instruction(load);
2823   }
2824   return load;
2825 }
2826
2827
2828 HLoadNamedField* HGraphBuilder::AddLoadMap(HValue* object,
2829                                            HValue* dependency) {
2830   return Add<HLoadNamedField>(object, dependency, HObjectAccess::ForMap());
2831 }
2832
2833
2834 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object,
2835                                                 HValue* dependency) {
2836   return Add<HLoadNamedField>(
2837       object, dependency, HObjectAccess::ForElementsPointer());
2838 }
2839
2840
2841 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(
2842     HValue* array,
2843     HValue* dependency) {
2844   return Add<HLoadNamedField>(
2845       array, dependency, HObjectAccess::ForFixedArrayLength());
2846 }
2847
2848
2849 HLoadNamedField* HGraphBuilder::AddLoadArrayLength(HValue* array,
2850                                                    ElementsKind kind,
2851                                                    HValue* dependency) {
2852   return Add<HLoadNamedField>(
2853       array, dependency, HObjectAccess::ForArrayLength(kind));
2854 }
2855
2856
2857 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) {
2858   HValue* half_old_capacity = AddUncasted<HShr>(old_capacity,
2859                                                 graph_->GetConstant1());
2860
2861   HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity);
2862   new_capacity->ClearFlag(HValue::kCanOverflow);
2863
2864   HValue* min_growth = Add<HConstant>(16);
2865
2866   new_capacity = AddUncasted<HAdd>(new_capacity, min_growth);
2867   new_capacity->ClearFlag(HValue::kCanOverflow);
2868
2869   return new_capacity;
2870 }
2871
2872
2873 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
2874                                                  HValue* elements,
2875                                                  ElementsKind kind,
2876                                                  ElementsKind new_kind,
2877                                                  HValue* length,
2878                                                  HValue* new_capacity) {
2879   Add<HBoundsCheck>(new_capacity, Add<HConstant>(
2880           (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >>
2881           ElementsKindToShiftSize(new_kind)));
2882
2883   HValue* new_elements =
2884       BuildAllocateAndInitializeArray(new_kind, new_capacity);
2885
2886   BuildCopyElements(elements, kind, new_elements,
2887                     new_kind, length, new_capacity);
2888
2889   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
2890                         new_elements);
2891
2892   return new_elements;
2893 }
2894
2895
2896 void HGraphBuilder::BuildFillElementsWithValue(HValue* elements,
2897                                                ElementsKind elements_kind,
2898                                                HValue* from,
2899                                                HValue* to,
2900                                                HValue* value) {
2901   if (to == NULL) {
2902     to = AddLoadFixedArrayLength(elements);
2903   }
2904
2905   // Special loop unfolding case
2906   STATIC_ASSERT(JSArray::kPreallocatedArrayElements <=
2907                 kElementLoopUnrollThreshold);
2908   int initial_capacity = -1;
2909   if (from->IsInteger32Constant() && to->IsInteger32Constant()) {
2910     int constant_from = from->GetInteger32Constant();
2911     int constant_to = to->GetInteger32Constant();
2912
2913     if (constant_from == 0 && constant_to <= kElementLoopUnrollThreshold) {
2914       initial_capacity = constant_to;
2915     }
2916   }
2917
2918   if (initial_capacity >= 0) {
2919     for (int i = 0; i < initial_capacity; i++) {
2920       HInstruction* key = Add<HConstant>(i);
2921       Add<HStoreKeyed>(elements, key, value, elements_kind);
2922     }
2923   } else {
2924     // Carefully loop backwards so that the "from" remains live through the loop
2925     // rather than the to. This often corresponds to keeping length live rather
2926     // then capacity, which helps register allocation, since length is used more
2927     // other than capacity after filling with holes.
2928     LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
2929
2930     HValue* key = builder.BeginBody(to, from, Token::GT);
2931
2932     HValue* adjusted_key = AddUncasted<HSub>(key, graph()->GetConstant1());
2933     adjusted_key->ClearFlag(HValue::kCanOverflow);
2934
2935     Add<HStoreKeyed>(elements, adjusted_key, value, elements_kind);
2936
2937     builder.EndBody();
2938   }
2939 }
2940
2941
2942 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements,
2943                                               ElementsKind elements_kind,
2944                                               HValue* from,
2945                                               HValue* to) {
2946   // Fast elements kinds need to be initialized in case statements below cause a
2947   // garbage collection.
2948
2949   HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
2950                      ? graph()->GetConstantHole()
2951                      : Add<HConstant>(HConstant::kHoleNaN);
2952
2953   // Since we're about to store a hole value, the store instruction below must
2954   // assume an elements kind that supports heap object values.
2955   if (IsFastSmiOrObjectElementsKind(elements_kind)) {
2956     elements_kind = FAST_HOLEY_ELEMENTS;
2957   }
2958
2959   BuildFillElementsWithValue(elements, elements_kind, from, to, hole);
2960 }
2961
2962
2963 void HGraphBuilder::BuildCopyProperties(HValue* from_properties,
2964                                         HValue* to_properties, HValue* length,
2965                                         HValue* capacity) {
2966   ElementsKind kind = FAST_ELEMENTS;
2967
2968   BuildFillElementsWithValue(to_properties, kind, length, capacity,
2969                              graph()->GetConstantUndefined());
2970
2971   LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
2972
2973   HValue* key = builder.BeginBody(length, graph()->GetConstant0(), Token::GT);
2974
2975   key = AddUncasted<HSub>(key, graph()->GetConstant1());
2976   key->ClearFlag(HValue::kCanOverflow);
2977
2978   HValue* element = Add<HLoadKeyed>(from_properties, key, nullptr, kind);
2979
2980   Add<HStoreKeyed>(to_properties, key, element, kind);
2981
2982   builder.EndBody();
2983 }
2984
2985
2986 void HGraphBuilder::BuildCopyElements(HValue* from_elements,
2987                                       ElementsKind from_elements_kind,
2988                                       HValue* to_elements,
2989                                       ElementsKind to_elements_kind,
2990                                       HValue* length,
2991                                       HValue* capacity) {
2992   int constant_capacity = -1;
2993   if (capacity != NULL &&
2994       capacity->IsConstant() &&
2995       HConstant::cast(capacity)->HasInteger32Value()) {
2996     int constant_candidate = HConstant::cast(capacity)->Integer32Value();
2997     if (constant_candidate <= kElementLoopUnrollThreshold) {
2998       constant_capacity = constant_candidate;
2999     }
3000   }
3001
3002   bool pre_fill_with_holes =
3003     IsFastDoubleElementsKind(from_elements_kind) &&
3004     IsFastObjectElementsKind(to_elements_kind);
3005   if (pre_fill_with_holes) {
3006     // If the copy might trigger a GC, make sure that the FixedArray is
3007     // pre-initialized with holes to make sure that it's always in a
3008     // consistent state.
3009     BuildFillElementsWithHole(to_elements, to_elements_kind,
3010                               graph()->GetConstant0(), NULL);
3011   }
3012
3013   if (constant_capacity != -1) {
3014     // Unroll the loop for small elements kinds.
3015     for (int i = 0; i < constant_capacity; i++) {
3016       HValue* key_constant = Add<HConstant>(i);
3017       HInstruction* value = Add<HLoadKeyed>(from_elements, key_constant,
3018                                             nullptr, from_elements_kind);
3019       Add<HStoreKeyed>(to_elements, key_constant, value, to_elements_kind);
3020     }
3021   } else {
3022     if (!pre_fill_with_holes &&
3023         (capacity == NULL || !length->Equals(capacity))) {
3024       BuildFillElementsWithHole(to_elements, to_elements_kind,
3025                                 length, NULL);
3026     }
3027
3028     LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
3029
3030     HValue* key = builder.BeginBody(length, graph()->GetConstant0(),
3031                                     Token::GT);
3032
3033     key = AddUncasted<HSub>(key, graph()->GetConstant1());
3034     key->ClearFlag(HValue::kCanOverflow);
3035
3036     HValue* element = Add<HLoadKeyed>(from_elements, key, nullptr,
3037                                       from_elements_kind, ALLOW_RETURN_HOLE);
3038
3039     ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) &&
3040                          IsFastSmiElementsKind(to_elements_kind))
3041       ? FAST_HOLEY_ELEMENTS : to_elements_kind;
3042
3043     if (IsHoleyElementsKind(from_elements_kind) &&
3044         from_elements_kind != to_elements_kind) {
3045       IfBuilder if_hole(this);
3046       if_hole.If<HCompareHoleAndBranch>(element);
3047       if_hole.Then();
3048       HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind)
3049                                      ? Add<HConstant>(HConstant::kHoleNaN)
3050                                      : graph()->GetConstantHole();
3051       Add<HStoreKeyed>(to_elements, key, hole_constant, kind);
3052       if_hole.Else();
3053       HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind);
3054       store->SetFlag(HValue::kAllowUndefinedAsNaN);
3055       if_hole.End();
3056     } else {
3057       HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind);
3058       store->SetFlag(HValue::kAllowUndefinedAsNaN);
3059     }
3060
3061     builder.EndBody();
3062   }
3063
3064   Counters* counters = isolate()->counters();
3065   AddIncrementCounter(counters->inlined_copied_elements());
3066 }
3067
3068
3069 HValue* HGraphBuilder::BuildCloneShallowArrayCow(HValue* boilerplate,
3070                                                  HValue* allocation_site,
3071                                                  AllocationSiteMode mode,
3072                                                  ElementsKind kind) {
3073   HAllocate* array = AllocateJSArrayObject(mode);
3074
3075   HValue* map = AddLoadMap(boilerplate);
3076   HValue* elements = AddLoadElements(boilerplate);
3077   HValue* length = AddLoadArrayLength(boilerplate, kind);
3078
3079   BuildJSArrayHeader(array,
3080                      map,
3081                      elements,
3082                      mode,
3083                      FAST_ELEMENTS,
3084                      allocation_site,
3085                      length);
3086   return array;
3087 }
3088
3089
3090 HValue* HGraphBuilder::BuildCloneShallowArrayEmpty(HValue* boilerplate,
3091                                                    HValue* allocation_site,
3092                                                    AllocationSiteMode mode) {
3093   HAllocate* array = AllocateJSArrayObject(mode);
3094
3095   HValue* map = AddLoadMap(boilerplate);
3096
3097   BuildJSArrayHeader(array,
3098                      map,
3099                      NULL,  // set elements to empty fixed array
3100                      mode,
3101                      FAST_ELEMENTS,
3102                      allocation_site,
3103                      graph()->GetConstant0());
3104   return array;
3105 }
3106
3107
3108 HValue* HGraphBuilder::BuildCloneShallowArrayNonEmpty(HValue* boilerplate,
3109                                                       HValue* allocation_site,
3110                                                       AllocationSiteMode mode,
3111                                                       ElementsKind kind) {
3112   HValue* boilerplate_elements = AddLoadElements(boilerplate);
3113   HValue* capacity = AddLoadFixedArrayLength(boilerplate_elements);
3114
3115   // Generate size calculation code here in order to make it dominate
3116   // the JSArray allocation.
3117   HValue* elements_size = BuildCalculateElementsSize(kind, capacity);
3118
3119   // Create empty JSArray object for now, store elimination should remove
3120   // redundant initialization of elements and length fields and at the same
3121   // time the object will be fully prepared for GC if it happens during
3122   // elements allocation.
3123   HValue* result = BuildCloneShallowArrayEmpty(
3124       boilerplate, allocation_site, mode);
3125
3126   HAllocate* elements = BuildAllocateElements(kind, elements_size);
3127
3128   // This function implicitly relies on the fact that the
3129   // FastCloneShallowArrayStub is called only for literals shorter than
3130   // JSObject::kInitialMaxFastElementArray.
3131   // Can't add HBoundsCheck here because otherwise the stub will eager a frame.
3132   HConstant* size_upper_bound = EstablishElementsAllocationSize(
3133       kind, JSObject::kInitialMaxFastElementArray);
3134   elements->set_size_upper_bound(size_upper_bound);
3135
3136   Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(), elements);
3137
3138   // The allocation for the cloned array above causes register pressure on
3139   // machines with low register counts. Force a reload of the boilerplate
3140   // elements here to free up a register for the allocation to avoid unnecessary
3141   // spillage.
3142   boilerplate_elements = AddLoadElements(boilerplate);
3143   boilerplate_elements->SetFlag(HValue::kCantBeReplaced);
3144
3145   // Copy the elements array header.
3146   for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) {
3147     HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i);
3148     Add<HStoreNamedField>(
3149         elements, access,
3150         Add<HLoadNamedField>(boilerplate_elements, nullptr, access));
3151   }
3152
3153   // And the result of the length
3154   HValue* length = AddLoadArrayLength(boilerplate, kind);
3155   Add<HStoreNamedField>(result, HObjectAccess::ForArrayLength(kind), length);
3156
3157   BuildCopyElements(boilerplate_elements, kind, elements,
3158                     kind, length, NULL);
3159   return result;
3160 }
3161
3162
3163 void HGraphBuilder::BuildCompareNil(HValue* value, Type* type,
3164                                     HIfContinuation* continuation,
3165                                     MapEmbedding map_embedding) {
3166   IfBuilder if_nil(this);
3167   bool some_case_handled = false;
3168   bool some_case_missing = false;
3169
3170   if (type->Maybe(Type::Null())) {
3171     if (some_case_handled) if_nil.Or();
3172     if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull());
3173     some_case_handled = true;
3174   } else {
3175     some_case_missing = true;
3176   }
3177
3178   if (type->Maybe(Type::Undefined())) {
3179     if (some_case_handled) if_nil.Or();
3180     if_nil.If<HCompareObjectEqAndBranch>(value,
3181                                          graph()->GetConstantUndefined());
3182     some_case_handled = true;
3183   } else {
3184     some_case_missing = true;
3185   }
3186
3187   if (type->Maybe(Type::Undetectable())) {
3188     if (some_case_handled) if_nil.Or();
3189     if_nil.If<HIsUndetectableAndBranch>(value);
3190     some_case_handled = true;
3191   } else {
3192     some_case_missing = true;
3193   }
3194
3195   if (some_case_missing) {
3196     if_nil.Then();
3197     if_nil.Else();
3198     if (type->NumClasses() == 1) {
3199       BuildCheckHeapObject(value);
3200       // For ICs, the map checked below is a sentinel map that gets replaced by
3201       // the monomorphic map when the code is used as a template to generate a
3202       // new IC. For optimized functions, there is no sentinel map, the map
3203       // emitted below is the actual monomorphic map.
3204       if (map_embedding == kEmbedMapsViaWeakCells) {
3205         HValue* cell =
3206             Add<HConstant>(Map::WeakCellForMap(type->Classes().Current()));
3207         HValue* expected_map = Add<HLoadNamedField>(
3208             cell, nullptr, HObjectAccess::ForWeakCellValue());
3209         HValue* map =
3210             Add<HLoadNamedField>(value, nullptr, HObjectAccess::ForMap());
3211         IfBuilder map_check(this);
3212         map_check.IfNot<HCompareObjectEqAndBranch>(expected_map, map);
3213         map_check.ThenDeopt(Deoptimizer::kUnknownMap);
3214         map_check.End();
3215       } else {
3216         DCHECK(map_embedding == kEmbedMapsDirectly);
3217         Add<HCheckMaps>(value, type->Classes().Current());
3218       }
3219     } else {
3220       if_nil.Deopt(Deoptimizer::kTooManyUndetectableTypes);
3221     }
3222   }
3223
3224   if_nil.CaptureContinuation(continuation);
3225 }
3226
3227
3228 void HGraphBuilder::BuildCreateAllocationMemento(
3229     HValue* previous_object,
3230     HValue* previous_object_size,
3231     HValue* allocation_site) {
3232   DCHECK(allocation_site != NULL);
3233   HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>(
3234       previous_object, previous_object_size, HType::HeapObject());
3235   AddStoreMapConstant(
3236       allocation_memento, isolate()->factory()->allocation_memento_map());
3237   Add<HStoreNamedField>(
3238       allocation_memento,
3239       HObjectAccess::ForAllocationMementoSite(),
3240       allocation_site);
3241   if (FLAG_allocation_site_pretenuring) {
3242     HValue* memento_create_count =
3243         Add<HLoadNamedField>(allocation_site, nullptr,
3244                              HObjectAccess::ForAllocationSiteOffset(
3245                                  AllocationSite::kPretenureCreateCountOffset));
3246     memento_create_count = AddUncasted<HAdd>(
3247         memento_create_count, graph()->GetConstant1());
3248     // This smi value is reset to zero after every gc, overflow isn't a problem
3249     // since the counter is bounded by the new space size.
3250     memento_create_count->ClearFlag(HValue::kCanOverflow);
3251     Add<HStoreNamedField>(
3252         allocation_site, HObjectAccess::ForAllocationSiteOffset(
3253             AllocationSite::kPretenureCreateCountOffset), memento_create_count);
3254   }
3255 }
3256
3257
3258 HInstruction* HGraphBuilder::BuildGetNativeContext() {
3259   // Get the global object, then the native context
3260   HValue* global_object = Add<HLoadNamedField>(
3261       context(), nullptr,
3262       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
3263   return Add<HLoadNamedField>(global_object, nullptr,
3264                               HObjectAccess::ForObservableJSObjectOffset(
3265                                   GlobalObject::kNativeContextOffset));
3266 }
3267
3268
3269 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* closure) {
3270   // Get the global object, then the native context
3271   HInstruction* context = Add<HLoadNamedField>(
3272       closure, nullptr, HObjectAccess::ForFunctionContextPointer());
3273   HInstruction* global_object = Add<HLoadNamedField>(
3274       context, nullptr,
3275       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
3276   HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
3277       GlobalObject::kNativeContextOffset);
3278   return Add<HLoadNamedField>(global_object, nullptr, access);
3279 }
3280
3281
3282 HInstruction* HGraphBuilder::BuildGetScriptContext(int context_index) {
3283   HValue* native_context = BuildGetNativeContext();
3284   HValue* script_context_table = Add<HLoadNamedField>(
3285       native_context, nullptr,
3286       HObjectAccess::ForContextSlot(Context::SCRIPT_CONTEXT_TABLE_INDEX));
3287   return Add<HLoadNamedField>(script_context_table, nullptr,
3288                               HObjectAccess::ForScriptContext(context_index));
3289 }
3290
3291
3292 HValue* HGraphBuilder::BuildGetParentContext(HValue* depth, int depth_value) {
3293   HValue* script_context = context();
3294   if (depth != NULL) {
3295     HValue* zero = graph()->GetConstant0();
3296
3297     Push(script_context);
3298     Push(depth);
3299
3300     LoopBuilder loop(this);
3301     loop.BeginBody(2);  // Drop script_context and depth from last environment
3302                         // to appease live range building without simulates.
3303     depth = Pop();
3304     script_context = Pop();
3305
3306     script_context = Add<HLoadNamedField>(
3307         script_context, nullptr,
3308         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
3309     depth = AddUncasted<HSub>(depth, graph()->GetConstant1());
3310     depth->ClearFlag(HValue::kCanOverflow);
3311
3312     IfBuilder if_break(this);
3313     if_break.If<HCompareNumericAndBranch, HValue*>(depth, zero, Token::EQ);
3314     if_break.Then();
3315     {
3316       Push(script_context);  // The result.
3317       loop.Break();
3318     }
3319     if_break.Else();
3320     {
3321       Push(script_context);
3322       Push(depth);
3323     }
3324     loop.EndBody();
3325     if_break.End();
3326
3327     script_context = Pop();
3328   } else if (depth_value > 0) {
3329     // Unroll the above loop.
3330     for (int i = 0; i < depth_value; i++) {
3331       script_context = Add<HLoadNamedField>(
3332           script_context, nullptr,
3333           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
3334     }
3335   }
3336   return script_context;
3337 }
3338
3339
3340 HInstruction* HGraphBuilder::BuildGetArrayFunction() {
3341   HInstruction* native_context = BuildGetNativeContext();
3342   HInstruction* index =
3343       Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX));
3344   return Add<HLoadKeyed>(native_context, index, nullptr, FAST_ELEMENTS);
3345 }
3346
3347
3348 HValue* HGraphBuilder::BuildArrayBufferViewFieldAccessor(HValue* object,
3349                                                          HValue* checked_object,
3350                                                          FieldIndex index) {
3351   NoObservableSideEffectsScope scope(this);
3352   HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
3353       index.offset(), Representation::Tagged());
3354   HInstruction* buffer = Add<HLoadNamedField>(
3355       object, checked_object, HObjectAccess::ForJSArrayBufferViewBuffer());
3356   HInstruction* field = Add<HLoadNamedField>(object, checked_object, access);
3357
3358   HInstruction* flags = Add<HLoadNamedField>(
3359       buffer, nullptr, HObjectAccess::ForJSArrayBufferBitField());
3360   HValue* was_neutered_mask =
3361       Add<HConstant>(1 << JSArrayBuffer::WasNeutered::kShift);
3362   HValue* was_neutered_test =
3363       AddUncasted<HBitwise>(Token::BIT_AND, flags, was_neutered_mask);
3364
3365   IfBuilder if_was_neutered(this);
3366   if_was_neutered.If<HCompareNumericAndBranch>(
3367       was_neutered_test, graph()->GetConstant0(), Token::NE);
3368   if_was_neutered.Then();
3369   Push(graph()->GetConstant0());
3370   if_was_neutered.Else();
3371   Push(field);
3372   if_was_neutered.End();
3373
3374   return Pop();
3375 }
3376
3377
3378 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
3379     ElementsKind kind,
3380     HValue* allocation_site_payload,
3381     HValue* constructor_function,
3382     AllocationSiteOverrideMode override_mode) :
3383         builder_(builder),
3384         kind_(kind),
3385         allocation_site_payload_(allocation_site_payload),
3386         constructor_function_(constructor_function) {
3387   DCHECK(!allocation_site_payload->IsConstant() ||
3388          HConstant::cast(allocation_site_payload)->handle(
3389              builder_->isolate())->IsAllocationSite());
3390   mode_ = override_mode == DISABLE_ALLOCATION_SITES
3391       ? DONT_TRACK_ALLOCATION_SITE
3392       : AllocationSite::GetMode(kind);
3393 }
3394
3395
3396 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
3397                                               ElementsKind kind,
3398                                               HValue* constructor_function) :
3399     builder_(builder),
3400     kind_(kind),
3401     mode_(DONT_TRACK_ALLOCATION_SITE),
3402     allocation_site_payload_(NULL),
3403     constructor_function_(constructor_function) {
3404 }
3405
3406
3407 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
3408   if (!builder()->top_info()->IsStub()) {
3409     // A constant map is fine.
3410     Handle<Map> map(builder()->isolate()->get_initial_js_array_map(kind_),
3411                     builder()->isolate());
3412     return builder()->Add<HConstant>(map);
3413   }
3414
3415   if (constructor_function_ != NULL && kind_ == GetInitialFastElementsKind()) {
3416     // No need for a context lookup if the kind_ matches the initial
3417     // map, because we can just load the map in that case.
3418     HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
3419     return builder()->Add<HLoadNamedField>(constructor_function_, nullptr,
3420                                            access);
3421   }
3422
3423   // TODO(mvstanton): we should always have a constructor function if we
3424   // are creating a stub.
3425   HInstruction* native_context = constructor_function_ != NULL
3426       ? builder()->BuildGetNativeContext(constructor_function_)
3427       : builder()->BuildGetNativeContext();
3428
3429   HInstruction* index = builder()->Add<HConstant>(
3430       static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX));
3431
3432   HInstruction* map_array =
3433       builder()->Add<HLoadKeyed>(native_context, index, nullptr, FAST_ELEMENTS);
3434
3435   HInstruction* kind_index = builder()->Add<HConstant>(kind_);
3436
3437   return builder()->Add<HLoadKeyed>(map_array, kind_index, nullptr,
3438                                     FAST_ELEMENTS);
3439 }
3440
3441
3442 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
3443   // Find the map near the constructor function
3444   HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
3445   return builder()->Add<HLoadNamedField>(constructor_function_, nullptr,
3446                                          access);
3447 }
3448
3449
3450 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() {
3451   HConstant* capacity = builder()->Add<HConstant>(initial_capacity());
3452   return AllocateArray(capacity,
3453                        capacity,
3454                        builder()->graph()->GetConstant0());
3455 }
3456
3457
3458 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
3459     HValue* capacity,
3460     HConstant* capacity_upper_bound,
3461     HValue* length_field,
3462     FillMode fill_mode) {
3463   return AllocateArray(capacity,
3464                        capacity_upper_bound->GetInteger32Constant(),
3465                        length_field,
3466                        fill_mode);
3467 }
3468
3469
3470 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
3471     HValue* capacity,
3472     int capacity_upper_bound,
3473     HValue* length_field,
3474     FillMode fill_mode) {
3475   HConstant* elememts_size_upper_bound = capacity->IsInteger32Constant()
3476       ? HConstant::cast(capacity)
3477       : builder()->EstablishElementsAllocationSize(kind_, capacity_upper_bound);
3478
3479   HAllocate* array = AllocateArray(capacity, length_field, fill_mode);
3480   if (!elements_location_->has_size_upper_bound()) {
3481     elements_location_->set_size_upper_bound(elememts_size_upper_bound);
3482   }
3483   return array;
3484 }
3485
3486
3487 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
3488     HValue* capacity,
3489     HValue* length_field,
3490     FillMode fill_mode) {
3491   // These HForceRepresentations are because we store these as fields in the
3492   // objects we construct, and an int32-to-smi HChange could deopt. Accept
3493   // the deopt possibility now, before allocation occurs.
3494   capacity =
3495       builder()->AddUncasted<HForceRepresentation>(capacity,
3496                                                    Representation::Smi());
3497   length_field =
3498       builder()->AddUncasted<HForceRepresentation>(length_field,
3499                                                    Representation::Smi());
3500
3501   // Generate size calculation code here in order to make it dominate
3502   // the JSArray allocation.
3503   HValue* elements_size =
3504       builder()->BuildCalculateElementsSize(kind_, capacity);
3505
3506   // Allocate (dealing with failure appropriately)
3507   HAllocate* array_object = builder()->AllocateJSArrayObject(mode_);
3508
3509   // Fill in the fields: map, properties, length
3510   HValue* map;
3511   if (allocation_site_payload_ == NULL) {
3512     map = EmitInternalMapCode();
3513   } else {
3514     map = EmitMapCode();
3515   }
3516
3517   builder()->BuildJSArrayHeader(array_object,
3518                                 map,
3519                                 NULL,  // set elements to empty fixed array
3520                                 mode_,
3521                                 kind_,
3522                                 allocation_site_payload_,
3523                                 length_field);
3524
3525   // Allocate and initialize the elements
3526   elements_location_ = builder()->BuildAllocateElements(kind_, elements_size);
3527
3528   builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity);
3529
3530   // Set the elements
3531   builder()->Add<HStoreNamedField>(
3532       array_object, HObjectAccess::ForElementsPointer(), elements_location_);
3533
3534   if (fill_mode == FILL_WITH_HOLE) {
3535     builder()->BuildFillElementsWithHole(elements_location_, kind_,
3536                                          graph()->GetConstant0(), capacity);
3537   }
3538
3539   return array_object;
3540 }
3541
3542
3543 HValue* HGraphBuilder::AddLoadJSBuiltin(int context_index) {
3544   HValue* global_object = Add<HLoadNamedField>(
3545       context(), nullptr,
3546       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
3547   HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
3548       GlobalObject::kNativeContextOffset);
3549   HValue* native_context = Add<HLoadNamedField>(global_object, nullptr, access);
3550   HObjectAccess function_access = HObjectAccess::ForContextSlot(context_index);
3551   return Add<HLoadNamedField>(native_context, nullptr, function_access);
3552 }
3553
3554
3555 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
3556     : HGraphBuilder(info),
3557       function_state_(NULL),
3558       initial_function_state_(this, info, NORMAL_RETURN, 0),
3559       ast_context_(NULL),
3560       break_scope_(NULL),
3561       inlined_count_(0),
3562       globals_(10, info->zone()),
3563       osr_(new(info->zone()) HOsrBuilder(this)) {
3564   // This is not initialized in the initializer list because the
3565   // constructor for the initial state relies on function_state_ == NULL
3566   // to know it's the initial state.
3567   function_state_ = &initial_function_state_;
3568   InitializeAstVisitor(info->isolate(), info->zone());
3569   if (top_info()->is_tracking_positions()) {
3570     SetSourcePosition(info->shared_info()->start_position());
3571   }
3572 }
3573
3574
3575 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first,
3576                                                 HBasicBlock* second,
3577                                                 BailoutId join_id) {
3578   if (first == NULL) {
3579     return second;
3580   } else if (second == NULL) {
3581     return first;
3582   } else {
3583     HBasicBlock* join_block = graph()->CreateBasicBlock();
3584     Goto(first, join_block);
3585     Goto(second, join_block);
3586     join_block->SetJoinId(join_id);
3587     return join_block;
3588   }
3589 }
3590
3591
3592 HBasicBlock* HOptimizedGraphBuilder::JoinContinue(IterationStatement* statement,
3593                                                   HBasicBlock* exit_block,
3594                                                   HBasicBlock* continue_block) {
3595   if (continue_block != NULL) {
3596     if (exit_block != NULL) Goto(exit_block, continue_block);
3597     continue_block->SetJoinId(statement->ContinueId());
3598     return continue_block;
3599   }
3600   return exit_block;
3601 }
3602
3603
3604 HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement,
3605                                                 HBasicBlock* loop_entry,
3606                                                 HBasicBlock* body_exit,
3607                                                 HBasicBlock* loop_successor,
3608                                                 HBasicBlock* break_block) {
3609   if (body_exit != NULL) Goto(body_exit, loop_entry);
3610   loop_entry->PostProcessLoopHeader(statement);
3611   if (break_block != NULL) {
3612     if (loop_successor != NULL) Goto(loop_successor, break_block);
3613     break_block->SetJoinId(statement->ExitId());
3614     return break_block;
3615   }
3616   return loop_successor;
3617 }
3618
3619
3620 // Build a new loop header block and set it as the current block.
3621 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() {
3622   HBasicBlock* loop_entry = CreateLoopHeaderBlock();
3623   Goto(loop_entry);
3624   set_current_block(loop_entry);
3625   return loop_entry;
3626 }
3627
3628
3629 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry(
3630     IterationStatement* statement) {
3631   HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement)
3632       ? osr()->BuildOsrLoopEntry(statement)
3633       : BuildLoopEntry();
3634   return loop_entry;
3635 }
3636
3637
3638 void HBasicBlock::FinishExit(HControlInstruction* instruction,
3639                              SourcePosition position) {
3640   Finish(instruction, position);
3641   ClearEnvironment();
3642 }
3643
3644
3645 std::ostream& operator<<(std::ostream& os, const HBasicBlock& b) {
3646   return os << "B" << b.block_id();
3647 }
3648
3649
3650 HGraph::HGraph(CompilationInfo* info)
3651     : isolate_(info->isolate()),
3652       next_block_id_(0),
3653       entry_block_(NULL),
3654       blocks_(8, info->zone()),
3655       values_(16, info->zone()),
3656       phi_list_(NULL),
3657       uint32_instructions_(NULL),
3658       osr_(NULL),
3659       info_(info),
3660       zone_(info->zone()),
3661       is_recursive_(false),
3662       use_optimistic_licm_(false),
3663       depends_on_empty_array_proto_elements_(false),
3664       type_change_checksum_(0),
3665       maximum_environment_size_(0),
3666       no_side_effects_scope_count_(0),
3667       disallow_adding_new_values_(false) {
3668   if (info->IsStub()) {
3669     CallInterfaceDescriptor descriptor =
3670         info->code_stub()->GetCallInterfaceDescriptor();
3671     start_environment_ =
3672         new (zone_) HEnvironment(zone_, descriptor.GetRegisterParameterCount());
3673   } else {
3674     if (info->is_tracking_positions()) {
3675       info->TraceInlinedFunction(info->shared_info(), SourcePosition::Unknown(),
3676                                  InlinedFunctionInfo::kNoParentId);
3677     }
3678     start_environment_ =
3679         new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
3680   }
3681   start_environment_->set_ast_id(BailoutId::Prologue());
3682   entry_block_ = CreateBasicBlock();
3683   entry_block_->SetInitialEnvironment(start_environment_);
3684 }
3685
3686
3687 HBasicBlock* HGraph::CreateBasicBlock() {
3688   HBasicBlock* result = new(zone()) HBasicBlock(this);
3689   blocks_.Add(result, zone());
3690   return result;
3691 }
3692
3693
3694 void HGraph::FinalizeUniqueness() {
3695   DisallowHeapAllocation no_gc;
3696   for (int i = 0; i < blocks()->length(); ++i) {
3697     for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
3698       it.Current()->FinalizeUniqueness();
3699     }
3700   }
3701 }
3702
3703
3704 int HGraph::SourcePositionToScriptPosition(SourcePosition pos) {
3705   return (FLAG_hydrogen_track_positions && !pos.IsUnknown())
3706              ? info()->start_position_for(pos.inlining_id()) + pos.position()
3707              : pos.raw();
3708 }
3709
3710
3711 // Block ordering was implemented with two mutually recursive methods,
3712 // HGraph::Postorder and HGraph::PostorderLoopBlocks.
3713 // The recursion could lead to stack overflow so the algorithm has been
3714 // implemented iteratively.
3715 // At a high level the algorithm looks like this:
3716 //
3717 // Postorder(block, loop_header) : {
3718 //   if (block has already been visited or is of another loop) return;
3719 //   mark block as visited;
3720 //   if (block is a loop header) {
3721 //     VisitLoopMembers(block, loop_header);
3722 //     VisitSuccessorsOfLoopHeader(block);
3723 //   } else {
3724 //     VisitSuccessors(block)
3725 //   }
3726 //   put block in result list;
3727 // }
3728 //
3729 // VisitLoopMembers(block, outer_loop_header) {
3730 //   foreach (block b in block loop members) {
3731 //     VisitSuccessorsOfLoopMember(b, outer_loop_header);
3732 //     if (b is loop header) VisitLoopMembers(b);
3733 //   }
3734 // }
3735 //
3736 // VisitSuccessorsOfLoopMember(block, outer_loop_header) {
3737 //   foreach (block b in block successors) Postorder(b, outer_loop_header)
3738 // }
3739 //
3740 // VisitSuccessorsOfLoopHeader(block) {
3741 //   foreach (block b in block successors) Postorder(b, block)
3742 // }
3743 //
3744 // VisitSuccessors(block, loop_header) {
3745 //   foreach (block b in block successors) Postorder(b, loop_header)
3746 // }
3747 //
3748 // The ordering is started calling Postorder(entry, NULL).
3749 //
3750 // Each instance of PostorderProcessor represents the "stack frame" of the
3751 // recursion, and particularly keeps the state of the loop (iteration) of the
3752 // "Visit..." function it represents.
3753 // To recycle memory we keep all the frames in a double linked list but
3754 // this means that we cannot use constructors to initialize the frames.
3755 //
3756 class PostorderProcessor : public ZoneObject {
3757  public:
3758   // Back link (towards the stack bottom).
3759   PostorderProcessor* parent() {return father_; }
3760   // Forward link (towards the stack top).
3761   PostorderProcessor* child() {return child_; }
3762   HBasicBlock* block() { return block_; }
3763   HLoopInformation* loop() { return loop_; }
3764   HBasicBlock* loop_header() { return loop_header_; }
3765
3766   static PostorderProcessor* CreateEntryProcessor(Zone* zone,
3767                                                   HBasicBlock* block) {
3768     PostorderProcessor* result = new(zone) PostorderProcessor(NULL);
3769     return result->SetupSuccessors(zone, block, NULL);
3770   }
3771
3772   PostorderProcessor* PerformStep(Zone* zone,
3773                                   ZoneList<HBasicBlock*>* order) {
3774     PostorderProcessor* next =
3775         PerformNonBacktrackingStep(zone, order);
3776     if (next != NULL) {
3777       return next;
3778     } else {
3779       return Backtrack(zone, order);
3780     }
3781   }
3782
3783  private:
3784   explicit PostorderProcessor(PostorderProcessor* father)
3785       : father_(father), child_(NULL), successor_iterator(NULL) { }
3786
3787   // Each enum value states the cycle whose state is kept by this instance.
3788   enum LoopKind {
3789     NONE,
3790     SUCCESSORS,
3791     SUCCESSORS_OF_LOOP_HEADER,
3792     LOOP_MEMBERS,
3793     SUCCESSORS_OF_LOOP_MEMBER
3794   };
3795
3796   // Each "Setup..." method is like a constructor for a cycle state.
3797   PostorderProcessor* SetupSuccessors(Zone* zone,
3798                                       HBasicBlock* block,
3799                                       HBasicBlock* loop_header) {
3800     if (block == NULL || block->IsOrdered() ||
3801         block->parent_loop_header() != loop_header) {
3802       kind_ = NONE;
3803       block_ = NULL;
3804       loop_ = NULL;
3805       loop_header_ = NULL;
3806       return this;
3807     } else {
3808       block_ = block;
3809       loop_ = NULL;
3810       block->MarkAsOrdered();
3811
3812       if (block->IsLoopHeader()) {
3813         kind_ = SUCCESSORS_OF_LOOP_HEADER;
3814         loop_header_ = block;
3815         InitializeSuccessors();
3816         PostorderProcessor* result = Push(zone);
3817         return result->SetupLoopMembers(zone, block, block->loop_information(),
3818                                         loop_header);
3819       } else {
3820         DCHECK(block->IsFinished());
3821         kind_ = SUCCESSORS;
3822         loop_header_ = loop_header;
3823         InitializeSuccessors();
3824         return this;
3825       }
3826     }
3827   }
3828
3829   PostorderProcessor* SetupLoopMembers(Zone* zone,
3830                                        HBasicBlock* block,
3831                                        HLoopInformation* loop,
3832                                        HBasicBlock* loop_header) {
3833     kind_ = LOOP_MEMBERS;
3834     block_ = block;
3835     loop_ = loop;
3836     loop_header_ = loop_header;
3837     InitializeLoopMembers();
3838     return this;
3839   }
3840
3841   PostorderProcessor* SetupSuccessorsOfLoopMember(
3842       HBasicBlock* block,
3843       HLoopInformation* loop,
3844       HBasicBlock* loop_header) {
3845     kind_ = SUCCESSORS_OF_LOOP_MEMBER;
3846     block_ = block;
3847     loop_ = loop;
3848     loop_header_ = loop_header;
3849     InitializeSuccessors();
3850     return this;
3851   }
3852
3853   // This method "allocates" a new stack frame.
3854   PostorderProcessor* Push(Zone* zone) {
3855     if (child_ == NULL) {
3856       child_ = new(zone) PostorderProcessor(this);
3857     }
3858     return child_;
3859   }
3860
3861   void ClosePostorder(ZoneList<HBasicBlock*>* order, Zone* zone) {
3862     DCHECK(block_->end()->FirstSuccessor() == NULL ||
3863            order->Contains(block_->end()->FirstSuccessor()) ||
3864            block_->end()->FirstSuccessor()->IsLoopHeader());
3865     DCHECK(block_->end()->SecondSuccessor() == NULL ||
3866            order->Contains(block_->end()->SecondSuccessor()) ||
3867            block_->end()->SecondSuccessor()->IsLoopHeader());
3868     order->Add(block_, zone);
3869   }
3870
3871   // This method is the basic block to walk up the stack.
3872   PostorderProcessor* Pop(Zone* zone,
3873                           ZoneList<HBasicBlock*>* order) {
3874     switch (kind_) {
3875       case SUCCESSORS:
3876       case SUCCESSORS_OF_LOOP_HEADER:
3877         ClosePostorder(order, zone);
3878         return father_;
3879       case LOOP_MEMBERS:
3880         return father_;
3881       case SUCCESSORS_OF_LOOP_MEMBER:
3882         if (block()->IsLoopHeader() && block() != loop_->loop_header()) {
3883           // In this case we need to perform a LOOP_MEMBERS cycle so we
3884           // initialize it and return this instead of father.
3885           return SetupLoopMembers(zone, block(),
3886                                   block()->loop_information(), loop_header_);
3887         } else {
3888           return father_;
3889         }
3890       case NONE:
3891         return father_;
3892     }
3893     UNREACHABLE();
3894     return NULL;
3895   }
3896
3897   // Walks up the stack.
3898   PostorderProcessor* Backtrack(Zone* zone,
3899                                 ZoneList<HBasicBlock*>* order) {
3900     PostorderProcessor* parent = Pop(zone, order);
3901     while (parent != NULL) {
3902       PostorderProcessor* next =
3903           parent->PerformNonBacktrackingStep(zone, order);
3904       if (next != NULL) {
3905         return next;
3906       } else {
3907         parent = parent->Pop(zone, order);
3908       }
3909     }
3910     return NULL;
3911   }
3912
3913   PostorderProcessor* PerformNonBacktrackingStep(
3914       Zone* zone,
3915       ZoneList<HBasicBlock*>* order) {
3916     HBasicBlock* next_block;
3917     switch (kind_) {
3918       case SUCCESSORS:
3919         next_block = AdvanceSuccessors();
3920         if (next_block != NULL) {
3921           PostorderProcessor* result = Push(zone);
3922           return result->SetupSuccessors(zone, next_block, loop_header_);
3923         }
3924         break;
3925       case SUCCESSORS_OF_LOOP_HEADER:
3926         next_block = AdvanceSuccessors();
3927         if (next_block != NULL) {
3928           PostorderProcessor* result = Push(zone);
3929           return result->SetupSuccessors(zone, next_block, block());
3930         }
3931         break;
3932       case LOOP_MEMBERS:
3933         next_block = AdvanceLoopMembers();
3934         if (next_block != NULL) {
3935           PostorderProcessor* result = Push(zone);
3936           return result->SetupSuccessorsOfLoopMember(next_block,
3937                                                      loop_, loop_header_);
3938         }
3939         break;
3940       case SUCCESSORS_OF_LOOP_MEMBER:
3941         next_block = AdvanceSuccessors();
3942         if (next_block != NULL) {
3943           PostorderProcessor* result = Push(zone);
3944           return result->SetupSuccessors(zone, next_block, loop_header_);
3945         }
3946         break;
3947       case NONE:
3948         return NULL;
3949     }
3950     return NULL;
3951   }
3952
3953   // The following two methods implement a "foreach b in successors" cycle.
3954   void InitializeSuccessors() {
3955     loop_index = 0;
3956     loop_length = 0;
3957     successor_iterator = HSuccessorIterator(block_->end());
3958   }
3959
3960   HBasicBlock* AdvanceSuccessors() {
3961     if (!successor_iterator.Done()) {
3962       HBasicBlock* result = successor_iterator.Current();
3963       successor_iterator.Advance();
3964       return result;
3965     }
3966     return NULL;
3967   }
3968
3969   // The following two methods implement a "foreach b in loop members" cycle.
3970   void InitializeLoopMembers() {
3971     loop_index = 0;
3972     loop_length = loop_->blocks()->length();
3973   }
3974
3975   HBasicBlock* AdvanceLoopMembers() {
3976     if (loop_index < loop_length) {
3977       HBasicBlock* result = loop_->blocks()->at(loop_index);
3978       loop_index++;
3979       return result;
3980     } else {
3981       return NULL;
3982     }
3983   }
3984
3985   LoopKind kind_;
3986   PostorderProcessor* father_;
3987   PostorderProcessor* child_;
3988   HLoopInformation* loop_;
3989   HBasicBlock* block_;
3990   HBasicBlock* loop_header_;
3991   int loop_index;
3992   int loop_length;
3993   HSuccessorIterator successor_iterator;
3994 };
3995
3996
3997 void HGraph::OrderBlocks() {
3998   CompilationPhase phase("H_Block ordering", info());
3999
4000 #ifdef DEBUG
4001   // Initially the blocks must not be ordered.
4002   for (int i = 0; i < blocks_.length(); ++i) {
4003     DCHECK(!blocks_[i]->IsOrdered());
4004   }
4005 #endif
4006
4007   PostorderProcessor* postorder =
4008       PostorderProcessor::CreateEntryProcessor(zone(), blocks_[0]);
4009   blocks_.Rewind(0);
4010   while (postorder) {
4011     postorder = postorder->PerformStep(zone(), &blocks_);
4012   }
4013
4014 #ifdef DEBUG
4015   // Now all blocks must be marked as ordered.
4016   for (int i = 0; i < blocks_.length(); ++i) {
4017     DCHECK(blocks_[i]->IsOrdered());
4018   }
4019 #endif
4020
4021   // Reverse block list and assign block IDs.
4022   for (int i = 0, j = blocks_.length(); --j >= i; ++i) {
4023     HBasicBlock* bi = blocks_[i];
4024     HBasicBlock* bj = blocks_[j];
4025     bi->set_block_id(j);
4026     bj->set_block_id(i);
4027     blocks_[i] = bj;
4028     blocks_[j] = bi;
4029   }
4030 }
4031
4032
4033 void HGraph::AssignDominators() {
4034   HPhase phase("H_Assign dominators", this);
4035   for (int i = 0; i < blocks_.length(); ++i) {
4036     HBasicBlock* block = blocks_[i];
4037     if (block->IsLoopHeader()) {
4038       // Only the first predecessor of a loop header is from outside the loop.
4039       // All others are back edges, and thus cannot dominate the loop header.
4040       block->AssignCommonDominator(block->predecessors()->first());
4041       block->AssignLoopSuccessorDominators();
4042     } else {
4043       for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) {
4044         blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
4045       }
4046     }
4047   }
4048 }
4049
4050
4051 bool HGraph::CheckArgumentsPhiUses() {
4052   int block_count = blocks_.length();
4053   for (int i = 0; i < block_count; ++i) {
4054     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
4055       HPhi* phi = blocks_[i]->phis()->at(j);
4056       // We don't support phi uses of arguments for now.
4057       if (phi->CheckFlag(HValue::kIsArguments)) return false;
4058     }
4059   }
4060   return true;
4061 }
4062
4063
4064 bool HGraph::CheckConstPhiUses() {
4065   int block_count = blocks_.length();
4066   for (int i = 0; i < block_count; ++i) {
4067     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
4068       HPhi* phi = blocks_[i]->phis()->at(j);
4069       // Check for the hole value (from an uninitialized const).
4070       for (int k = 0; k < phi->OperandCount(); k++) {
4071         if (phi->OperandAt(k) == GetConstantHole()) return false;
4072       }
4073     }
4074   }
4075   return true;
4076 }
4077
4078
4079 void HGraph::CollectPhis() {
4080   int block_count = blocks_.length();
4081   phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone());
4082   for (int i = 0; i < block_count; ++i) {
4083     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
4084       HPhi* phi = blocks_[i]->phis()->at(j);
4085       phi_list_->Add(phi, zone());
4086     }
4087   }
4088 }
4089
4090
4091 // Implementation of utility class to encapsulate the translation state for
4092 // a (possibly inlined) function.
4093 FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
4094                              CompilationInfo* info, InliningKind inlining_kind,
4095                              int inlining_id)
4096     : owner_(owner),
4097       compilation_info_(info),
4098       call_context_(NULL),
4099       inlining_kind_(inlining_kind),
4100       function_return_(NULL),
4101       test_context_(NULL),
4102       entry_(NULL),
4103       arguments_object_(NULL),
4104       arguments_elements_(NULL),
4105       inlining_id_(inlining_id),
4106       outer_source_position_(SourcePosition::Unknown()),
4107       outer_(owner->function_state()) {
4108   if (outer_ != NULL) {
4109     // State for an inline function.
4110     if (owner->ast_context()->IsTest()) {
4111       HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
4112       HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
4113       if_true->MarkAsInlineReturnTarget(owner->current_block());
4114       if_false->MarkAsInlineReturnTarget(owner->current_block());
4115       TestContext* outer_test_context = TestContext::cast(owner->ast_context());
4116       Expression* cond = outer_test_context->condition();
4117       // The AstContext constructor pushed on the context stack.  This newed
4118       // instance is the reason that AstContext can't be BASE_EMBEDDED.
4119       test_context_ = new TestContext(owner, cond, if_true, if_false);
4120     } else {
4121       function_return_ = owner->graph()->CreateBasicBlock();
4122       function_return()->MarkAsInlineReturnTarget(owner->current_block());
4123     }
4124     // Set this after possibly allocating a new TestContext above.
4125     call_context_ = owner->ast_context();
4126   }
4127
4128   // Push on the state stack.
4129   owner->set_function_state(this);
4130
4131   if (compilation_info_->is_tracking_positions()) {
4132     outer_source_position_ = owner->source_position();
4133     owner->EnterInlinedSource(
4134       info->shared_info()->start_position(),
4135       inlining_id);
4136     owner->SetSourcePosition(info->shared_info()->start_position());
4137   }
4138 }
4139
4140
4141 FunctionState::~FunctionState() {
4142   delete test_context_;
4143   owner_->set_function_state(outer_);
4144
4145   if (compilation_info_->is_tracking_positions()) {
4146     owner_->set_source_position(outer_source_position_);
4147     owner_->EnterInlinedSource(
4148       outer_->compilation_info()->shared_info()->start_position(),
4149       outer_->inlining_id());
4150   }
4151 }
4152
4153
4154 // Implementation of utility classes to represent an expression's context in
4155 // the AST.
4156 AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind)
4157     : owner_(owner),
4158       kind_(kind),
4159       outer_(owner->ast_context()),
4160       typeof_mode_(NOT_INSIDE_TYPEOF) {
4161   owner->set_ast_context(this);  // Push.
4162 #ifdef DEBUG
4163   DCHECK(owner->environment()->frame_type() == JS_FUNCTION);
4164   original_length_ = owner->environment()->length();
4165 #endif
4166 }
4167
4168
4169 AstContext::~AstContext() {
4170   owner_->set_ast_context(outer_);  // Pop.
4171 }
4172
4173
4174 EffectContext::~EffectContext() {
4175   DCHECK(owner()->HasStackOverflow() ||
4176          owner()->current_block() == NULL ||
4177          (owner()->environment()->length() == original_length_ &&
4178           owner()->environment()->frame_type() == JS_FUNCTION));
4179 }
4180
4181
4182 ValueContext::~ValueContext() {
4183   DCHECK(owner()->HasStackOverflow() ||
4184          owner()->current_block() == NULL ||
4185          (owner()->environment()->length() == original_length_ + 1 &&
4186           owner()->environment()->frame_type() == JS_FUNCTION));
4187 }
4188
4189
4190 void EffectContext::ReturnValue(HValue* value) {
4191   // The value is simply ignored.
4192 }
4193
4194
4195 void ValueContext::ReturnValue(HValue* value) {
4196   // The value is tracked in the bailout environment, and communicated
4197   // through the environment as the result of the expression.
4198   if (value->CheckFlag(HValue::kIsArguments)) {
4199     if (flag_ == ARGUMENTS_FAKED) {
4200       value = owner()->graph()->GetConstantUndefined();
4201     } else if (!arguments_allowed()) {
4202       owner()->Bailout(kBadValueContextForArgumentsValue);
4203     }
4204   }
4205   owner()->Push(value);
4206 }
4207
4208
4209 void TestContext::ReturnValue(HValue* value) {
4210   BuildBranch(value);
4211 }
4212
4213
4214 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
4215   DCHECK(!instr->IsControlInstruction());
4216   owner()->AddInstruction(instr);
4217   if (instr->HasObservableSideEffects()) {
4218     owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
4219   }
4220 }
4221
4222
4223 void EffectContext::ReturnControl(HControlInstruction* instr,
4224                                   BailoutId ast_id) {
4225   DCHECK(!instr->HasObservableSideEffects());
4226   HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
4227   HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
4228   instr->SetSuccessorAt(0, empty_true);
4229   instr->SetSuccessorAt(1, empty_false);
4230   owner()->FinishCurrentBlock(instr);
4231   HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id);
4232   owner()->set_current_block(join);
4233 }
4234
4235
4236 void EffectContext::ReturnContinuation(HIfContinuation* continuation,
4237                                        BailoutId ast_id) {
4238   HBasicBlock* true_branch = NULL;
4239   HBasicBlock* false_branch = NULL;
4240   continuation->Continue(&true_branch, &false_branch);
4241   if (!continuation->IsTrueReachable()) {
4242     owner()->set_current_block(false_branch);
4243   } else if (!continuation->IsFalseReachable()) {
4244     owner()->set_current_block(true_branch);
4245   } else {
4246     HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id);
4247     owner()->set_current_block(join);
4248   }
4249 }
4250
4251
4252 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
4253   DCHECK(!instr->IsControlInstruction());
4254   if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
4255     return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
4256   }
4257   owner()->AddInstruction(instr);
4258   owner()->Push(instr);
4259   if (instr->HasObservableSideEffects()) {
4260     owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
4261   }
4262 }
4263
4264
4265 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
4266   DCHECK(!instr->HasObservableSideEffects());
4267   if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
4268     return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
4269   }
4270   HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
4271   HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
4272   instr->SetSuccessorAt(0, materialize_true);
4273   instr->SetSuccessorAt(1, materialize_false);
4274   owner()->FinishCurrentBlock(instr);
4275   owner()->set_current_block(materialize_true);
4276   owner()->Push(owner()->graph()->GetConstantTrue());
4277   owner()->set_current_block(materialize_false);
4278   owner()->Push(owner()->graph()->GetConstantFalse());
4279   HBasicBlock* join =
4280     owner()->CreateJoin(materialize_true, materialize_false, ast_id);
4281   owner()->set_current_block(join);
4282 }
4283
4284
4285 void ValueContext::ReturnContinuation(HIfContinuation* continuation,
4286                                       BailoutId ast_id) {
4287   HBasicBlock* materialize_true = NULL;
4288   HBasicBlock* materialize_false = NULL;
4289   continuation->Continue(&materialize_true, &materialize_false);
4290   if (continuation->IsTrueReachable()) {
4291     owner()->set_current_block(materialize_true);
4292     owner()->Push(owner()->graph()->GetConstantTrue());
4293     owner()->set_current_block(materialize_true);
4294   }
4295   if (continuation->IsFalseReachable()) {
4296     owner()->set_current_block(materialize_false);
4297     owner()->Push(owner()->graph()->GetConstantFalse());
4298     owner()->set_current_block(materialize_false);
4299   }
4300   if (continuation->TrueAndFalseReachable()) {
4301     HBasicBlock* join =
4302         owner()->CreateJoin(materialize_true, materialize_false, ast_id);
4303     owner()->set_current_block(join);
4304   }
4305 }
4306
4307
4308 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
4309   DCHECK(!instr->IsControlInstruction());
4310   HOptimizedGraphBuilder* builder = owner();
4311   builder->AddInstruction(instr);
4312   // We expect a simulate after every expression with side effects, though
4313   // this one isn't actually needed (and wouldn't work if it were targeted).
4314   if (instr->HasObservableSideEffects()) {
4315     builder->Push(instr);
4316     builder->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
4317     builder->Pop();
4318   }
4319   BuildBranch(instr);
4320 }
4321
4322
4323 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
4324   DCHECK(!instr->HasObservableSideEffects());
4325   HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
4326   HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
4327   instr->SetSuccessorAt(0, empty_true);
4328   instr->SetSuccessorAt(1, empty_false);
4329   owner()->FinishCurrentBlock(instr);
4330   owner()->Goto(empty_true, if_true(), owner()->function_state());
4331   owner()->Goto(empty_false, if_false(), owner()->function_state());
4332   owner()->set_current_block(NULL);
4333 }
4334
4335
4336 void TestContext::ReturnContinuation(HIfContinuation* continuation,
4337                                      BailoutId ast_id) {
4338   HBasicBlock* true_branch = NULL;
4339   HBasicBlock* false_branch = NULL;
4340   continuation->Continue(&true_branch, &false_branch);
4341   if (continuation->IsTrueReachable()) {
4342     owner()->Goto(true_branch, if_true(), owner()->function_state());
4343   }
4344   if (continuation->IsFalseReachable()) {
4345     owner()->Goto(false_branch, if_false(), owner()->function_state());
4346   }
4347   owner()->set_current_block(NULL);
4348 }
4349
4350
4351 void TestContext::BuildBranch(HValue* value) {
4352   // We expect the graph to be in edge-split form: there is no edge that
4353   // connects a branch node to a join node.  We conservatively ensure that
4354   // property by always adding an empty block on the outgoing edges of this
4355   // branch.
4356   HOptimizedGraphBuilder* builder = owner();
4357   if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
4358     builder->Bailout(kArgumentsObjectValueInATestContext);
4359   }
4360   ToBooleanStub::Types expected(condition()->to_boolean_types());
4361   ReturnControl(owner()->New<HBranch>(value, expected), BailoutId::None());
4362 }
4363
4364
4365 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts.
4366 #define CHECK_BAILOUT(call)                     \
4367   do {                                          \
4368     call;                                       \
4369     if (HasStackOverflow()) return;             \
4370   } while (false)
4371
4372
4373 #define CHECK_ALIVE(call)                                       \
4374   do {                                                          \
4375     call;                                                       \
4376     if (HasStackOverflow() || current_block() == NULL) return;  \
4377   } while (false)
4378
4379
4380 #define CHECK_ALIVE_OR_RETURN(call, value)                            \
4381   do {                                                                \
4382     call;                                                             \
4383     if (HasStackOverflow() || current_block() == NULL) return value;  \
4384   } while (false)
4385
4386
4387 void HOptimizedGraphBuilder::Bailout(BailoutReason reason) {
4388   current_info()->AbortOptimization(reason);
4389   SetStackOverflow();
4390 }
4391
4392
4393 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) {
4394   EffectContext for_effect(this);
4395   Visit(expr);
4396 }
4397
4398
4399 void HOptimizedGraphBuilder::VisitForValue(Expression* expr,
4400                                            ArgumentsAllowedFlag flag) {
4401   ValueContext for_value(this, flag);
4402   Visit(expr);
4403 }
4404
4405
4406 void HOptimizedGraphBuilder::VisitForTypeOf(Expression* expr) {
4407   ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
4408   for_value.set_typeof_mode(INSIDE_TYPEOF);
4409   Visit(expr);
4410 }
4411
4412
4413 void HOptimizedGraphBuilder::VisitForControl(Expression* expr,
4414                                              HBasicBlock* true_block,
4415                                              HBasicBlock* false_block) {
4416   TestContext for_test(this, expr, true_block, false_block);
4417   Visit(expr);
4418 }
4419
4420
4421 void HOptimizedGraphBuilder::VisitExpressions(
4422     ZoneList<Expression*>* exprs) {
4423   for (int i = 0; i < exprs->length(); ++i) {
4424     CHECK_ALIVE(VisitForValue(exprs->at(i)));
4425   }
4426 }
4427
4428
4429 void HOptimizedGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs,
4430                                               ArgumentsAllowedFlag flag) {
4431   for (int i = 0; i < exprs->length(); ++i) {
4432     CHECK_ALIVE(VisitForValue(exprs->at(i), flag));
4433   }
4434 }
4435
4436
4437 bool HOptimizedGraphBuilder::BuildGraph() {
4438   if (IsSubclassConstructor(current_info()->literal()->kind())) {
4439     Bailout(kSuperReference);
4440     return false;
4441   }
4442
4443   Scope* scope = current_info()->scope();
4444   SetUpScope(scope);
4445
4446   // Add an edge to the body entry.  This is warty: the graph's start
4447   // environment will be used by the Lithium translation as the initial
4448   // environment on graph entry, but it has now been mutated by the
4449   // Hydrogen translation of the instructions in the start block.  This
4450   // environment uses values which have not been defined yet.  These
4451   // Hydrogen instructions will then be replayed by the Lithium
4452   // translation, so they cannot have an environment effect.  The edge to
4453   // the body's entry block (along with some special logic for the start
4454   // block in HInstruction::InsertAfter) seals the start block from
4455   // getting unwanted instructions inserted.
4456   //
4457   // TODO(kmillikin): Fix this.  Stop mutating the initial environment.
4458   // Make the Hydrogen instructions in the initial block into Hydrogen
4459   // values (but not instructions), present in the initial environment and
4460   // not replayed by the Lithium translation.
4461   HEnvironment* initial_env = environment()->CopyWithoutHistory();
4462   HBasicBlock* body_entry = CreateBasicBlock(initial_env);
4463   Goto(body_entry);
4464   body_entry->SetJoinId(BailoutId::FunctionEntry());
4465   set_current_block(body_entry);
4466
4467   VisitDeclarations(scope->declarations());
4468   Add<HSimulate>(BailoutId::Declarations());
4469
4470   Add<HStackCheck>(HStackCheck::kFunctionEntry);
4471
4472   VisitStatements(current_info()->literal()->body());
4473   if (HasStackOverflow()) return false;
4474
4475   if (current_block() != NULL) {
4476     Add<HReturn>(graph()->GetConstantUndefined());
4477     set_current_block(NULL);
4478   }
4479
4480   // If the checksum of the number of type info changes is the same as the
4481   // last time this function was compiled, then this recompile is likely not
4482   // due to missing/inadequate type feedback, but rather too aggressive
4483   // optimization. Disable optimistic LICM in that case.
4484   Handle<Code> unoptimized_code(current_info()->shared_info()->code());
4485   DCHECK(unoptimized_code->kind() == Code::FUNCTION);
4486   Handle<TypeFeedbackInfo> type_info(
4487       TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
4488   int checksum = type_info->own_type_change_checksum();
4489   int composite_checksum = graph()->update_type_change_checksum(checksum);
4490   graph()->set_use_optimistic_licm(
4491       !type_info->matches_inlined_type_change_checksum(composite_checksum));
4492   type_info->set_inlined_type_change_checksum(composite_checksum);
4493
4494   // Perform any necessary OSR-specific cleanups or changes to the graph.
4495   osr()->FinishGraph();
4496
4497   return true;
4498 }
4499
4500
4501 bool HGraph::Optimize(BailoutReason* bailout_reason) {
4502   OrderBlocks();
4503   AssignDominators();
4504
4505   // We need to create a HConstant "zero" now so that GVN will fold every
4506   // zero-valued constant in the graph together.
4507   // The constant is needed to make idef-based bounds check work: the pass
4508   // evaluates relations with "zero" and that zero cannot be created after GVN.
4509   GetConstant0();
4510
4511 #ifdef DEBUG
4512   // Do a full verify after building the graph and computing dominators.
4513   Verify(true);
4514 #endif
4515
4516   if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) {
4517     Run<HEnvironmentLivenessAnalysisPhase>();
4518   }
4519
4520   if (!CheckConstPhiUses()) {
4521     *bailout_reason = kUnsupportedPhiUseOfConstVariable;
4522     return false;
4523   }
4524   Run<HRedundantPhiEliminationPhase>();
4525   if (!CheckArgumentsPhiUses()) {
4526     *bailout_reason = kUnsupportedPhiUseOfArguments;
4527     return false;
4528   }
4529
4530   // Find and mark unreachable code to simplify optimizations, especially gvn,
4531   // where unreachable code could unnecessarily defeat LICM.
4532   Run<HMarkUnreachableBlocksPhase>();
4533
4534   if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
4535   if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
4536
4537   if (FLAG_load_elimination) Run<HLoadEliminationPhase>();
4538
4539   CollectPhis();
4540
4541   if (has_osr()) osr()->FinishOsrValues();
4542
4543   Run<HInferRepresentationPhase>();
4544
4545   // Remove HSimulate instructions that have turned out not to be needed
4546   // after all by folding them into the following HSimulate.
4547   // This must happen after inferring representations.
4548   Run<HMergeRemovableSimulatesPhase>();
4549
4550   Run<HMarkDeoptimizeOnUndefinedPhase>();
4551   Run<HRepresentationChangesPhase>();
4552
4553   Run<HInferTypesPhase>();
4554
4555   // Must be performed before canonicalization to ensure that Canonicalize
4556   // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with
4557   // zero.
4558   Run<HUint32AnalysisPhase>();
4559
4560   if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>();
4561
4562   if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>();
4563
4564   if (FLAG_check_elimination) Run<HCheckEliminationPhase>();
4565
4566   if (FLAG_store_elimination) Run<HStoreEliminationPhase>();
4567
4568   Run<HRangeAnalysisPhase>();
4569
4570   Run<HComputeChangeUndefinedToNaN>();
4571
4572   // Eliminate redundant stack checks on backwards branches.
4573   Run<HStackCheckEliminationPhase>();
4574
4575   if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>();
4576   if (FLAG_array_bounds_checks_hoisting) Run<HBoundsCheckHoistingPhase>();
4577   if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
4578   if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
4579
4580   RestoreActualValues();
4581
4582   // Find unreachable code a second time, GVN and other optimizations may have
4583   // made blocks unreachable that were previously reachable.
4584   Run<HMarkUnreachableBlocksPhase>();
4585
4586   return true;
4587 }
4588
4589
4590 void HGraph::RestoreActualValues() {
4591   HPhase phase("H_Restore actual values", this);
4592
4593   for (int block_index = 0; block_index < blocks()->length(); block_index++) {
4594     HBasicBlock* block = blocks()->at(block_index);
4595
4596 #ifdef DEBUG
4597     for (int i = 0; i < block->phis()->length(); i++) {
4598       HPhi* phi = block->phis()->at(i);
4599       DCHECK(phi->ActualValue() == phi);
4600     }
4601 #endif
4602
4603     for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
4604       HInstruction* instruction = it.Current();
4605       if (instruction->ActualValue() == instruction) continue;
4606       if (instruction->CheckFlag(HValue::kIsDead)) {
4607         // The instruction was marked as deleted but left in the graph
4608         // as a control flow dependency point for subsequent
4609         // instructions.
4610         instruction->DeleteAndReplaceWith(instruction->ActualValue());
4611       } else {
4612         DCHECK(instruction->IsInformativeDefinition());
4613         if (instruction->IsPurelyInformativeDefinition()) {
4614           instruction->DeleteAndReplaceWith(instruction->RedefinedOperand());
4615         } else {
4616           instruction->ReplaceAllUsesWith(instruction->ActualValue());
4617         }
4618       }
4619     }
4620   }
4621 }
4622
4623
4624 void HOptimizedGraphBuilder::PushArgumentsFromEnvironment(int count) {
4625   ZoneList<HValue*> arguments(count, zone());
4626   for (int i = 0; i < count; ++i) {
4627     arguments.Add(Pop(), zone());
4628   }
4629
4630   HPushArguments* push_args = New<HPushArguments>();
4631   while (!arguments.is_empty()) {
4632     push_args->AddInput(arguments.RemoveLast());
4633   }
4634   AddInstruction(push_args);
4635 }
4636
4637
4638 template <class Instruction>
4639 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
4640   PushArgumentsFromEnvironment(call->argument_count());
4641   return call;
4642 }
4643
4644
4645 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) {
4646   HEnvironment* prolog_env = environment();
4647   int parameter_count = environment()->parameter_count();
4648   ZoneList<HValue*> parameters(parameter_count, zone());
4649   for (int i = 0; i < parameter_count; ++i) {
4650     HInstruction* parameter = Add<HParameter>(static_cast<unsigned>(i));
4651     parameters.Add(parameter, zone());
4652     environment()->Bind(i, parameter);
4653   }
4654
4655   HConstant* undefined_constant = graph()->GetConstantUndefined();
4656   // Initialize specials and locals to undefined.
4657   for (int i = parameter_count + 1; i < environment()->length(); ++i) {
4658     environment()->Bind(i, undefined_constant);
4659   }
4660   Add<HPrologue>();
4661
4662   HEnvironment* initial_env = environment()->CopyWithoutHistory();
4663   HBasicBlock* body_entry = CreateBasicBlock(initial_env);
4664   GotoNoSimulate(body_entry);
4665   set_current_block(body_entry);
4666
4667   // Initialize context of prolog environment to undefined.
4668   prolog_env->BindContext(undefined_constant);
4669
4670   // First special is HContext.
4671   HInstruction* context = Add<HContext>();
4672   environment()->BindContext(context);
4673
4674   // Create an arguments object containing the initial parameters.  Set the
4675   // initial values of parameters including "this" having parameter index 0.
4676   DCHECK_EQ(scope->num_parameters() + 1, parameter_count);
4677   HArgumentsObject* arguments_object = New<HArgumentsObject>(parameter_count);
4678   for (int i = 0; i < parameter_count; ++i) {
4679     HValue* parameter = parameters.at(i);
4680     arguments_object->AddArgument(parameter, zone());
4681   }
4682
4683   AddInstruction(arguments_object);
4684   graph()->SetArgumentsObject(arguments_object);
4685
4686   // Handle the arguments and arguments shadow variables specially (they do
4687   // not have declarations).
4688   if (scope->arguments() != NULL) {
4689     environment()->Bind(scope->arguments(), graph()->GetArgumentsObject());
4690   }
4691
4692   if (scope->this_function_var() != nullptr ||
4693       scope->new_target_var() != nullptr) {
4694     return Bailout(kSuperReference);
4695   }
4696
4697   // Trace the call.
4698   if (FLAG_trace && top_info()->IsOptimizing()) {
4699     Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kTraceEnter), 0);
4700   }
4701 }
4702
4703
4704 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
4705   for (int i = 0; i < statements->length(); i++) {
4706     Statement* stmt = statements->at(i);
4707     CHECK_ALIVE(Visit(stmt));
4708     if (stmt->IsJump()) break;
4709   }
4710 }
4711
4712
4713 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
4714   DCHECK(!HasStackOverflow());
4715   DCHECK(current_block() != NULL);
4716   DCHECK(current_block()->HasPredecessor());
4717
4718   Scope* outer_scope = scope();
4719   Scope* scope = stmt->scope();
4720   BreakAndContinueInfo break_info(stmt, outer_scope);
4721
4722   { BreakAndContinueScope push(&break_info, this);
4723     if (scope != NULL) {
4724       if (scope->NeedsContext()) {
4725         // Load the function object.
4726         Scope* declaration_scope = scope->DeclarationScope();
4727         HInstruction* function;
4728         HValue* outer_context = environment()->context();
4729         if (declaration_scope->is_script_scope() ||
4730             declaration_scope->is_eval_scope()) {
4731           function = new (zone())
4732               HLoadContextSlot(outer_context, Context::CLOSURE_INDEX,
4733                                HLoadContextSlot::kNoCheck);
4734         } else {
4735           function = New<HThisFunction>();
4736         }
4737         AddInstruction(function);
4738         // Allocate a block context and store it to the stack frame.
4739         HInstruction* inner_context = Add<HAllocateBlockContext>(
4740             outer_context, function, scope->GetScopeInfo(isolate()));
4741         HInstruction* instr = Add<HStoreFrameContext>(inner_context);
4742         set_scope(scope);
4743         environment()->BindContext(inner_context);
4744         if (instr->HasObservableSideEffects()) {
4745           AddSimulate(stmt->EntryId(), REMOVABLE_SIMULATE);
4746         }
4747       }
4748       VisitDeclarations(scope->declarations());
4749       AddSimulate(stmt->DeclsId(), REMOVABLE_SIMULATE);
4750     }
4751     CHECK_BAILOUT(VisitStatements(stmt->statements()));
4752   }
4753   set_scope(outer_scope);
4754   if (scope != NULL && current_block() != NULL &&
4755       scope->ContextLocalCount() > 0) {
4756     HValue* inner_context = environment()->context();
4757     HValue* outer_context = Add<HLoadNamedField>(
4758         inner_context, nullptr,
4759         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
4760
4761     HInstruction* instr = Add<HStoreFrameContext>(outer_context);
4762     environment()->BindContext(outer_context);
4763     if (instr->HasObservableSideEffects()) {
4764       AddSimulate(stmt->ExitId(), REMOVABLE_SIMULATE);
4765     }
4766   }
4767   HBasicBlock* break_block = break_info.break_block();
4768   if (break_block != NULL) {
4769     if (current_block() != NULL) Goto(break_block);
4770     break_block->SetJoinId(stmt->ExitId());
4771     set_current_block(break_block);
4772   }
4773 }
4774
4775
4776 void HOptimizedGraphBuilder::VisitExpressionStatement(
4777     ExpressionStatement* stmt) {
4778   DCHECK(!HasStackOverflow());
4779   DCHECK(current_block() != NULL);
4780   DCHECK(current_block()->HasPredecessor());
4781   VisitForEffect(stmt->expression());
4782 }
4783
4784
4785 void HOptimizedGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
4786   DCHECK(!HasStackOverflow());
4787   DCHECK(current_block() != NULL);
4788   DCHECK(current_block()->HasPredecessor());
4789 }
4790
4791
4792 void HOptimizedGraphBuilder::VisitSloppyBlockFunctionStatement(
4793     SloppyBlockFunctionStatement* stmt) {
4794   Visit(stmt->statement());
4795 }
4796
4797
4798 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) {
4799   DCHECK(!HasStackOverflow());
4800   DCHECK(current_block() != NULL);
4801   DCHECK(current_block()->HasPredecessor());
4802   if (stmt->condition()->ToBooleanIsTrue()) {
4803     Add<HSimulate>(stmt->ThenId());
4804     Visit(stmt->then_statement());
4805   } else if (stmt->condition()->ToBooleanIsFalse()) {
4806     Add<HSimulate>(stmt->ElseId());
4807     Visit(stmt->else_statement());
4808   } else {
4809     HBasicBlock* cond_true = graph()->CreateBasicBlock();
4810     HBasicBlock* cond_false = graph()->CreateBasicBlock();
4811     CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false));
4812
4813     if (cond_true->HasPredecessor()) {
4814       cond_true->SetJoinId(stmt->ThenId());
4815       set_current_block(cond_true);
4816       CHECK_BAILOUT(Visit(stmt->then_statement()));
4817       cond_true = current_block();
4818     } else {
4819       cond_true = NULL;
4820     }
4821
4822     if (cond_false->HasPredecessor()) {
4823       cond_false->SetJoinId(stmt->ElseId());
4824       set_current_block(cond_false);
4825       CHECK_BAILOUT(Visit(stmt->else_statement()));
4826       cond_false = current_block();
4827     } else {
4828       cond_false = NULL;
4829     }
4830
4831     HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId());
4832     set_current_block(join);
4833   }
4834 }
4835
4836
4837 HBasicBlock* HOptimizedGraphBuilder::BreakAndContinueScope::Get(
4838     BreakableStatement* stmt,
4839     BreakType type,
4840     Scope** scope,
4841     int* drop_extra) {
4842   *drop_extra = 0;
4843   BreakAndContinueScope* current = this;
4844   while (current != NULL && current->info()->target() != stmt) {
4845     *drop_extra += current->info()->drop_extra();
4846     current = current->next();
4847   }
4848   DCHECK(current != NULL);  // Always found (unless stack is malformed).
4849   *scope = current->info()->scope();
4850
4851   if (type == BREAK) {
4852     *drop_extra += current->info()->drop_extra();
4853   }
4854
4855   HBasicBlock* block = NULL;
4856   switch (type) {
4857     case BREAK:
4858       block = current->info()->break_block();
4859       if (block == NULL) {
4860         block = current->owner()->graph()->CreateBasicBlock();
4861         current->info()->set_break_block(block);
4862       }
4863       break;
4864
4865     case CONTINUE:
4866       block = current->info()->continue_block();
4867       if (block == NULL) {
4868         block = current->owner()->graph()->CreateBasicBlock();
4869         current->info()->set_continue_block(block);
4870       }
4871       break;
4872   }
4873
4874   return block;
4875 }
4876
4877
4878 void HOptimizedGraphBuilder::VisitContinueStatement(
4879     ContinueStatement* stmt) {
4880   DCHECK(!HasStackOverflow());
4881   DCHECK(current_block() != NULL);
4882   DCHECK(current_block()->HasPredecessor());
4883   Scope* outer_scope = NULL;
4884   Scope* inner_scope = scope();
4885   int drop_extra = 0;
4886   HBasicBlock* continue_block = break_scope()->Get(
4887       stmt->target(), BreakAndContinueScope::CONTINUE,
4888       &outer_scope, &drop_extra);
4889   HValue* context = environment()->context();
4890   Drop(drop_extra);
4891   int context_pop_count = inner_scope->ContextChainLength(outer_scope);
4892   if (context_pop_count > 0) {
4893     while (context_pop_count-- > 0) {
4894       HInstruction* context_instruction = Add<HLoadNamedField>(
4895           context, nullptr,
4896           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
4897       context = context_instruction;
4898     }
4899     HInstruction* instr = Add<HStoreFrameContext>(context);
4900     if (instr->HasObservableSideEffects()) {
4901       AddSimulate(stmt->target()->EntryId(), REMOVABLE_SIMULATE);
4902     }
4903     environment()->BindContext(context);
4904   }
4905
4906   Goto(continue_block);
4907   set_current_block(NULL);
4908 }
4909
4910
4911 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
4912   DCHECK(!HasStackOverflow());
4913   DCHECK(current_block() != NULL);
4914   DCHECK(current_block()->HasPredecessor());
4915   Scope* outer_scope = NULL;
4916   Scope* inner_scope = scope();
4917   int drop_extra = 0;
4918   HBasicBlock* break_block = break_scope()->Get(
4919       stmt->target(), BreakAndContinueScope::BREAK,
4920       &outer_scope, &drop_extra);
4921   HValue* context = environment()->context();
4922   Drop(drop_extra);
4923   int context_pop_count = inner_scope->ContextChainLength(outer_scope);
4924   if (context_pop_count > 0) {
4925     while (context_pop_count-- > 0) {
4926       HInstruction* context_instruction = Add<HLoadNamedField>(
4927           context, nullptr,
4928           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
4929       context = context_instruction;
4930     }
4931     HInstruction* instr = Add<HStoreFrameContext>(context);
4932     if (instr->HasObservableSideEffects()) {
4933       AddSimulate(stmt->target()->ExitId(), REMOVABLE_SIMULATE);
4934     }
4935     environment()->BindContext(context);
4936   }
4937   Goto(break_block);
4938   set_current_block(NULL);
4939 }
4940
4941
4942 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
4943   DCHECK(!HasStackOverflow());
4944   DCHECK(current_block() != NULL);
4945   DCHECK(current_block()->HasPredecessor());
4946   FunctionState* state = function_state();
4947   AstContext* context = call_context();
4948   if (context == NULL) {
4949     // Not an inlined return, so an actual one.
4950     CHECK_ALIVE(VisitForValue(stmt->expression()));
4951     HValue* result = environment()->Pop();
4952     Add<HReturn>(result);
4953   } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
4954     // Return from an inlined construct call. In a test context the return value
4955     // will always evaluate to true, in a value context the return value needs
4956     // to be a JSObject.
4957     if (context->IsTest()) {
4958       TestContext* test = TestContext::cast(context);
4959       CHECK_ALIVE(VisitForEffect(stmt->expression()));
4960       Goto(test->if_true(), state);
4961     } else if (context->IsEffect()) {
4962       CHECK_ALIVE(VisitForEffect(stmt->expression()));
4963       Goto(function_return(), state);
4964     } else {
4965       DCHECK(context->IsValue());
4966       CHECK_ALIVE(VisitForValue(stmt->expression()));
4967       HValue* return_value = Pop();
4968       HValue* receiver = environment()->arguments_environment()->Lookup(0);
4969       HHasInstanceTypeAndBranch* typecheck =
4970           New<HHasInstanceTypeAndBranch>(return_value,
4971                                          FIRST_SPEC_OBJECT_TYPE,
4972                                          LAST_SPEC_OBJECT_TYPE);
4973       HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
4974       HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
4975       typecheck->SetSuccessorAt(0, if_spec_object);
4976       typecheck->SetSuccessorAt(1, not_spec_object);
4977       FinishCurrentBlock(typecheck);
4978       AddLeaveInlined(if_spec_object, return_value, state);
4979       AddLeaveInlined(not_spec_object, receiver, state);
4980     }
4981   } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
4982     // Return from an inlined setter call. The returned value is never used, the
4983     // value of an assignment is always the value of the RHS of the assignment.
4984     CHECK_ALIVE(VisitForEffect(stmt->expression()));
4985     if (context->IsTest()) {
4986       HValue* rhs = environment()->arguments_environment()->Lookup(1);
4987       context->ReturnValue(rhs);
4988     } else if (context->IsEffect()) {
4989       Goto(function_return(), state);
4990     } else {
4991       DCHECK(context->IsValue());
4992       HValue* rhs = environment()->arguments_environment()->Lookup(1);
4993       AddLeaveInlined(rhs, state);
4994     }
4995   } else {
4996     // Return from a normal inlined function. Visit the subexpression in the
4997     // expression context of the call.
4998     if (context->IsTest()) {
4999       TestContext* test = TestContext::cast(context);
5000       VisitForControl(stmt->expression(), test->if_true(), test->if_false());
5001     } else if (context->IsEffect()) {
5002       // Visit in value context and ignore the result. This is needed to keep
5003       // environment in sync with full-codegen since some visitors (e.g.
5004       // VisitCountOperation) use the operand stack differently depending on
5005       // context.
5006       CHECK_ALIVE(VisitForValue(stmt->expression()));
5007       Pop();
5008       Goto(function_return(), state);
5009     } else {
5010       DCHECK(context->IsValue());
5011       CHECK_ALIVE(VisitForValue(stmt->expression()));
5012       AddLeaveInlined(Pop(), state);
5013     }
5014   }
5015   set_current_block(NULL);
5016 }
5017
5018
5019 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) {
5020   DCHECK(!HasStackOverflow());
5021   DCHECK(current_block() != NULL);
5022   DCHECK(current_block()->HasPredecessor());
5023   return Bailout(kWithStatement);
5024 }
5025
5026
5027 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
5028   DCHECK(!HasStackOverflow());
5029   DCHECK(current_block() != NULL);
5030   DCHECK(current_block()->HasPredecessor());
5031
5032   ZoneList<CaseClause*>* clauses = stmt->cases();
5033   int clause_count = clauses->length();
5034   ZoneList<HBasicBlock*> body_blocks(clause_count, zone());
5035
5036   CHECK_ALIVE(VisitForValue(stmt->tag()));
5037   Add<HSimulate>(stmt->EntryId());
5038   HValue* tag_value = Top();
5039   Type* tag_type = stmt->tag()->bounds().lower;
5040
5041   // 1. Build all the tests, with dangling true branches
5042   BailoutId default_id = BailoutId::None();
5043   for (int i = 0; i < clause_count; ++i) {
5044     CaseClause* clause = clauses->at(i);
5045     if (clause->is_default()) {
5046       body_blocks.Add(NULL, zone());
5047       if (default_id.IsNone()) default_id = clause->EntryId();
5048       continue;
5049     }
5050
5051     // Generate a compare and branch.
5052     CHECK_ALIVE(VisitForValue(clause->label()));
5053     HValue* label_value = Pop();
5054
5055     Type* label_type = clause->label()->bounds().lower;
5056     Type* combined_type = clause->compare_type();
5057     HControlInstruction* compare = BuildCompareInstruction(
5058         Token::EQ_STRICT, tag_value, label_value, tag_type, label_type,
5059         combined_type,
5060         ScriptPositionToSourcePosition(stmt->tag()->position()),
5061         ScriptPositionToSourcePosition(clause->label()->position()),
5062         PUSH_BEFORE_SIMULATE, clause->id());
5063
5064     HBasicBlock* next_test_block = graph()->CreateBasicBlock();
5065     HBasicBlock* body_block = graph()->CreateBasicBlock();
5066     body_blocks.Add(body_block, zone());
5067     compare->SetSuccessorAt(0, body_block);
5068     compare->SetSuccessorAt(1, next_test_block);
5069     FinishCurrentBlock(compare);
5070
5071     set_current_block(body_block);
5072     Drop(1);  // tag_value
5073
5074     set_current_block(next_test_block);
5075   }
5076
5077   // Save the current block to use for the default or to join with the
5078   // exit.
5079   HBasicBlock* last_block = current_block();
5080   Drop(1);  // tag_value
5081
5082   // 2. Loop over the clauses and the linked list of tests in lockstep,
5083   // translating the clause bodies.
5084   HBasicBlock* fall_through_block = NULL;
5085
5086   BreakAndContinueInfo break_info(stmt, scope());
5087   { BreakAndContinueScope push(&break_info, this);
5088     for (int i = 0; i < clause_count; ++i) {
5089       CaseClause* clause = clauses->at(i);
5090
5091       // Identify the block where normal (non-fall-through) control flow
5092       // goes to.
5093       HBasicBlock* normal_block = NULL;
5094       if (clause->is_default()) {
5095         if (last_block == NULL) continue;
5096         normal_block = last_block;
5097         last_block = NULL;  // Cleared to indicate we've handled it.
5098       } else {
5099         normal_block = body_blocks[i];
5100       }
5101
5102       if (fall_through_block == NULL) {
5103         set_current_block(normal_block);
5104       } else {
5105         HBasicBlock* join = CreateJoin(fall_through_block,
5106                                        normal_block,
5107                                        clause->EntryId());
5108         set_current_block(join);
5109       }
5110
5111       CHECK_BAILOUT(VisitStatements(clause->statements()));
5112       fall_through_block = current_block();
5113     }
5114   }
5115
5116   // Create an up-to-3-way join.  Use the break block if it exists since
5117   // it's already a join block.
5118   HBasicBlock* break_block = break_info.break_block();
5119   if (break_block == NULL) {
5120     set_current_block(CreateJoin(fall_through_block,
5121                                  last_block,
5122                                  stmt->ExitId()));
5123   } else {
5124     if (fall_through_block != NULL) Goto(fall_through_block, break_block);
5125     if (last_block != NULL) Goto(last_block, break_block);
5126     break_block->SetJoinId(stmt->ExitId());
5127     set_current_block(break_block);
5128   }
5129 }
5130
5131
5132 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt,
5133                                            HBasicBlock* loop_entry) {
5134   Add<HSimulate>(stmt->StackCheckId());
5135   HStackCheck* stack_check =
5136       HStackCheck::cast(Add<HStackCheck>(HStackCheck::kBackwardsBranch));
5137   DCHECK(loop_entry->IsLoopHeader());
5138   loop_entry->loop_information()->set_stack_check(stack_check);
5139   CHECK_BAILOUT(Visit(stmt->body()));
5140 }
5141
5142
5143 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
5144   DCHECK(!HasStackOverflow());
5145   DCHECK(current_block() != NULL);
5146   DCHECK(current_block()->HasPredecessor());
5147   DCHECK(current_block() != NULL);
5148   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
5149
5150   BreakAndContinueInfo break_info(stmt, scope());
5151   {
5152     BreakAndContinueScope push(&break_info, this);
5153     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
5154   }
5155   HBasicBlock* body_exit =
5156       JoinContinue(stmt, current_block(), break_info.continue_block());
5157   HBasicBlock* loop_successor = NULL;
5158   if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) {
5159     set_current_block(body_exit);
5160     loop_successor = graph()->CreateBasicBlock();
5161     if (stmt->cond()->ToBooleanIsFalse()) {
5162       loop_entry->loop_information()->stack_check()->Eliminate();
5163       Goto(loop_successor);
5164       body_exit = NULL;
5165     } else {
5166       // The block for a true condition, the actual predecessor block of the
5167       // back edge.
5168       body_exit = graph()->CreateBasicBlock();
5169       CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor));
5170     }
5171     if (body_exit != NULL && body_exit->HasPredecessor()) {
5172       body_exit->SetJoinId(stmt->BackEdgeId());
5173     } else {
5174       body_exit = NULL;
5175     }
5176     if (loop_successor->HasPredecessor()) {
5177       loop_successor->SetJoinId(stmt->ExitId());
5178     } else {
5179       loop_successor = NULL;
5180     }
5181   }
5182   HBasicBlock* loop_exit = CreateLoop(stmt,
5183                                       loop_entry,
5184                                       body_exit,
5185                                       loop_successor,
5186                                       break_info.break_block());
5187   set_current_block(loop_exit);
5188 }
5189
5190
5191 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
5192   DCHECK(!HasStackOverflow());
5193   DCHECK(current_block() != NULL);
5194   DCHECK(current_block()->HasPredecessor());
5195   DCHECK(current_block() != NULL);
5196   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
5197
5198   // If the condition is constant true, do not generate a branch.
5199   HBasicBlock* loop_successor = NULL;
5200   if (!stmt->cond()->ToBooleanIsTrue()) {
5201     HBasicBlock* body_entry = graph()->CreateBasicBlock();
5202     loop_successor = graph()->CreateBasicBlock();
5203     CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
5204     if (body_entry->HasPredecessor()) {
5205       body_entry->SetJoinId(stmt->BodyId());
5206       set_current_block(body_entry);
5207     }
5208     if (loop_successor->HasPredecessor()) {
5209       loop_successor->SetJoinId(stmt->ExitId());
5210     } else {
5211       loop_successor = NULL;
5212     }
5213   }
5214
5215   BreakAndContinueInfo break_info(stmt, scope());
5216   if (current_block() != NULL) {
5217     BreakAndContinueScope push(&break_info, this);
5218     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
5219   }
5220   HBasicBlock* body_exit =
5221       JoinContinue(stmt, current_block(), break_info.continue_block());
5222   HBasicBlock* loop_exit = CreateLoop(stmt,
5223                                       loop_entry,
5224                                       body_exit,
5225                                       loop_successor,
5226                                       break_info.break_block());
5227   set_current_block(loop_exit);
5228 }
5229
5230
5231 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) {
5232   DCHECK(!HasStackOverflow());
5233   DCHECK(current_block() != NULL);
5234   DCHECK(current_block()->HasPredecessor());
5235   if (stmt->init() != NULL) {
5236     CHECK_ALIVE(Visit(stmt->init()));
5237   }
5238   DCHECK(current_block() != NULL);
5239   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
5240
5241   HBasicBlock* loop_successor = NULL;
5242   if (stmt->cond() != NULL) {
5243     HBasicBlock* body_entry = graph()->CreateBasicBlock();
5244     loop_successor = graph()->CreateBasicBlock();
5245     CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
5246     if (body_entry->HasPredecessor()) {
5247       body_entry->SetJoinId(stmt->BodyId());
5248       set_current_block(body_entry);
5249     }
5250     if (loop_successor->HasPredecessor()) {
5251       loop_successor->SetJoinId(stmt->ExitId());
5252     } else {
5253       loop_successor = NULL;
5254     }
5255   }
5256
5257   BreakAndContinueInfo break_info(stmt, scope());
5258   if (current_block() != NULL) {
5259     BreakAndContinueScope push(&break_info, this);
5260     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
5261   }
5262   HBasicBlock* body_exit =
5263       JoinContinue(stmt, current_block(), break_info.continue_block());
5264
5265   if (stmt->next() != NULL && body_exit != NULL) {
5266     set_current_block(body_exit);
5267     CHECK_BAILOUT(Visit(stmt->next()));
5268     body_exit = current_block();
5269   }
5270
5271   HBasicBlock* loop_exit = CreateLoop(stmt,
5272                                       loop_entry,
5273                                       body_exit,
5274                                       loop_successor,
5275                                       break_info.break_block());
5276   set_current_block(loop_exit);
5277 }
5278
5279
5280 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
5281   DCHECK(!HasStackOverflow());
5282   DCHECK(current_block() != NULL);
5283   DCHECK(current_block()->HasPredecessor());
5284
5285   if (!FLAG_optimize_for_in) {
5286     return Bailout(kForInStatementOptimizationIsDisabled);
5287   }
5288
5289   if (!stmt->each()->IsVariableProxy() ||
5290       !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
5291     return Bailout(kForInStatementWithNonLocalEachVariable);
5292   }
5293
5294   Variable* each_var = stmt->each()->AsVariableProxy()->var();
5295
5296   CHECK_ALIVE(VisitForValue(stmt->enumerable()));
5297   HValue* enumerable = Top();  // Leave enumerable at the top.
5298
5299   IfBuilder if_undefined_or_null(this);
5300   if_undefined_or_null.If<HCompareObjectEqAndBranch>(
5301       enumerable, graph()->GetConstantUndefined());
5302   if_undefined_or_null.Or();
5303   if_undefined_or_null.If<HCompareObjectEqAndBranch>(
5304       enumerable, graph()->GetConstantNull());
5305   if_undefined_or_null.ThenDeopt(Deoptimizer::kUndefinedOrNullInForIn);
5306   if_undefined_or_null.End();
5307   BuildForInBody(stmt, each_var, enumerable);
5308 }
5309
5310
5311 void HOptimizedGraphBuilder::BuildForInBody(ForInStatement* stmt,
5312                                             Variable* each_var,
5313                                             HValue* enumerable) {
5314   HInstruction* map;
5315   HInstruction* array;
5316   HInstruction* enum_length;
5317   bool fast = stmt->for_in_type() == ForInStatement::FAST_FOR_IN;
5318   if (fast) {
5319     map = Add<HForInPrepareMap>(enumerable);
5320     Add<HSimulate>(stmt->PrepareId());
5321
5322     array = Add<HForInCacheArray>(enumerable, map,
5323                                   DescriptorArray::kEnumCacheBridgeCacheIndex);
5324     enum_length = Add<HMapEnumLength>(map);
5325
5326     HInstruction* index_cache = Add<HForInCacheArray>(
5327         enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex);
5328     HForInCacheArray::cast(array)
5329         ->set_index_cache(HForInCacheArray::cast(index_cache));
5330   } else {
5331     Add<HSimulate>(stmt->PrepareId());
5332     {
5333       NoObservableSideEffectsScope no_effects(this);
5334       BuildJSObjectCheck(enumerable, 0);
5335     }
5336     Add<HSimulate>(stmt->ToObjectId());
5337
5338     map = graph()->GetConstant1();
5339     Runtime::FunctionId function_id = Runtime::kGetPropertyNamesFast;
5340     Add<HPushArguments>(enumerable);
5341     array = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 1);
5342     Push(array);
5343     Add<HSimulate>(stmt->EnumId());
5344     Drop(1);
5345     Handle<Map> array_map = isolate()->factory()->fixed_array_map();
5346     HValue* check = Add<HCheckMaps>(array, array_map);
5347     enum_length = AddLoadFixedArrayLength(array, check);
5348   }
5349
5350   HInstruction* start_index = Add<HConstant>(0);
5351
5352   Push(map);
5353   Push(array);
5354   Push(enum_length);
5355   Push(start_index);
5356
5357   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
5358
5359   // Reload the values to ensure we have up-to-date values inside of the loop.
5360   // This is relevant especially for OSR where the values don't come from the
5361   // computation above, but from the OSR entry block.
5362   enumerable = environment()->ExpressionStackAt(4);
5363   HValue* index = environment()->ExpressionStackAt(0);
5364   HValue* limit = environment()->ExpressionStackAt(1);
5365
5366   // Check that we still have more keys.
5367   HCompareNumericAndBranch* compare_index =
5368       New<HCompareNumericAndBranch>(index, limit, Token::LT);
5369   compare_index->set_observed_input_representation(
5370       Representation::Smi(), Representation::Smi());
5371
5372   HBasicBlock* loop_body = graph()->CreateBasicBlock();
5373   HBasicBlock* loop_successor = graph()->CreateBasicBlock();
5374
5375   compare_index->SetSuccessorAt(0, loop_body);
5376   compare_index->SetSuccessorAt(1, loop_successor);
5377   FinishCurrentBlock(compare_index);
5378
5379   set_current_block(loop_successor);
5380   Drop(5);
5381
5382   set_current_block(loop_body);
5383
5384   HValue* key =
5385       Add<HLoadKeyed>(environment()->ExpressionStackAt(2),  // Enum cache.
5386                       index, index, FAST_ELEMENTS);
5387
5388   if (fast) {
5389     // Check if the expected map still matches that of the enumerable.
5390     // If not just deoptimize.
5391     Add<HCheckMapValue>(enumerable, environment()->ExpressionStackAt(3));
5392     Bind(each_var, key);
5393   } else {
5394     Add<HPushArguments>(enumerable, key);
5395     Runtime::FunctionId function_id = Runtime::kForInFilter;
5396     key = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 2);
5397     Push(key);
5398     Add<HSimulate>(stmt->FilterId());
5399     key = Pop();
5400     Bind(each_var, key);
5401     IfBuilder if_undefined(this);
5402     if_undefined.If<HCompareObjectEqAndBranch>(key,
5403                                                graph()->GetConstantUndefined());
5404     if_undefined.ThenDeopt(Deoptimizer::kUndefined);
5405     if_undefined.End();
5406     Add<HSimulate>(stmt->AssignmentId());
5407   }
5408
5409   BreakAndContinueInfo break_info(stmt, scope(), 5);
5410   {
5411     BreakAndContinueScope push(&break_info, this);
5412     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
5413   }
5414
5415   HBasicBlock* body_exit =
5416       JoinContinue(stmt, current_block(), break_info.continue_block());
5417
5418   if (body_exit != NULL) {
5419     set_current_block(body_exit);
5420
5421     HValue* current_index = Pop();
5422     Push(AddUncasted<HAdd>(current_index, graph()->GetConstant1()));
5423     body_exit = current_block();
5424   }
5425
5426   HBasicBlock* loop_exit = CreateLoop(stmt,
5427                                       loop_entry,
5428                                       body_exit,
5429                                       loop_successor,
5430                                       break_info.break_block());
5431
5432   set_current_block(loop_exit);
5433 }
5434
5435
5436 void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
5437   DCHECK(!HasStackOverflow());
5438   DCHECK(current_block() != NULL);
5439   DCHECK(current_block()->HasPredecessor());
5440   return Bailout(kForOfStatement);
5441 }
5442
5443
5444 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
5445   DCHECK(!HasStackOverflow());
5446   DCHECK(current_block() != NULL);
5447   DCHECK(current_block()->HasPredecessor());
5448   return Bailout(kTryCatchStatement);
5449 }
5450
5451
5452 void HOptimizedGraphBuilder::VisitTryFinallyStatement(
5453     TryFinallyStatement* stmt) {
5454   DCHECK(!HasStackOverflow());
5455   DCHECK(current_block() != NULL);
5456   DCHECK(current_block()->HasPredecessor());
5457   return Bailout(kTryFinallyStatement);
5458 }
5459
5460
5461 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
5462   DCHECK(!HasStackOverflow());
5463   DCHECK(current_block() != NULL);
5464   DCHECK(current_block()->HasPredecessor());
5465   return Bailout(kDebuggerStatement);
5466 }
5467
5468
5469 void HOptimizedGraphBuilder::VisitCaseClause(CaseClause* clause) {
5470   UNREACHABLE();
5471 }
5472
5473
5474 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
5475   DCHECK(!HasStackOverflow());
5476   DCHECK(current_block() != NULL);
5477   DCHECK(current_block()->HasPredecessor());
5478   Handle<SharedFunctionInfo> shared_info = Compiler::GetSharedFunctionInfo(
5479       expr, current_info()->script(), top_info());
5480   // We also have a stack overflow if the recursive compilation did.
5481   if (HasStackOverflow()) return;
5482   // Use the fast case closure allocation code that allocates in new
5483   // space for nested functions that don't need literals cloning.
5484   HConstant* shared_info_value = Add<HConstant>(shared_info);
5485   HInstruction* instr;
5486   if (!expr->pretenure() && shared_info->num_literals() == 0) {
5487     FastNewClosureStub stub(isolate(), shared_info->language_mode(),
5488                             shared_info->kind());
5489     FastNewClosureDescriptor descriptor(isolate());
5490     HValue* values[] = {context(), shared_info_value};
5491     HConstant* stub_value = Add<HConstant>(stub.GetCode());
5492     instr = New<HCallWithDescriptor>(stub_value, 0, descriptor,
5493                                      Vector<HValue*>(values, arraysize(values)),
5494                                      NORMAL_CALL);
5495   } else {
5496     Add<HPushArguments>(shared_info_value);
5497     Runtime::FunctionId function_id =
5498         expr->pretenure() ? Runtime::kNewClosure_Tenured : Runtime::kNewClosure;
5499     instr = New<HCallRuntime>(Runtime::FunctionForId(function_id), 1);
5500   }
5501   return ast_context()->ReturnInstruction(instr, expr->id());
5502 }
5503
5504
5505 void HOptimizedGraphBuilder::VisitClassLiteral(ClassLiteral* lit) {
5506   DCHECK(!HasStackOverflow());
5507   DCHECK(current_block() != NULL);
5508   DCHECK(current_block()->HasPredecessor());
5509   return Bailout(kClassLiteral);
5510 }
5511
5512
5513 void HOptimizedGraphBuilder::VisitNativeFunctionLiteral(
5514     NativeFunctionLiteral* expr) {
5515   DCHECK(!HasStackOverflow());
5516   DCHECK(current_block() != NULL);
5517   DCHECK(current_block()->HasPredecessor());
5518   return Bailout(kNativeFunctionLiteral);
5519 }
5520
5521
5522 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) {
5523   DCHECK(!HasStackOverflow());
5524   DCHECK(current_block() != NULL);
5525   DCHECK(current_block()->HasPredecessor());
5526   HBasicBlock* cond_true = graph()->CreateBasicBlock();
5527   HBasicBlock* cond_false = graph()->CreateBasicBlock();
5528   CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false));
5529
5530   // Visit the true and false subexpressions in the same AST context as the
5531   // whole expression.
5532   if (cond_true->HasPredecessor()) {
5533     cond_true->SetJoinId(expr->ThenId());
5534     set_current_block(cond_true);
5535     CHECK_BAILOUT(Visit(expr->then_expression()));
5536     cond_true = current_block();
5537   } else {
5538     cond_true = NULL;
5539   }
5540
5541   if (cond_false->HasPredecessor()) {
5542     cond_false->SetJoinId(expr->ElseId());
5543     set_current_block(cond_false);
5544     CHECK_BAILOUT(Visit(expr->else_expression()));
5545     cond_false = current_block();
5546   } else {
5547     cond_false = NULL;
5548   }
5549
5550   if (!ast_context()->IsTest()) {
5551     HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id());
5552     set_current_block(join);
5553     if (join != NULL && !ast_context()->IsEffect()) {
5554       return ast_context()->ReturnValue(Pop());
5555     }
5556   }
5557 }
5558
5559
5560 HOptimizedGraphBuilder::GlobalPropertyAccess
5561 HOptimizedGraphBuilder::LookupGlobalProperty(Variable* var, LookupIterator* it,
5562                                              PropertyAccessType access_type) {
5563   if (var->is_this() || !current_info()->has_global_object()) {
5564     return kUseGeneric;
5565   }
5566
5567   switch (it->state()) {
5568     case LookupIterator::ACCESSOR:
5569     case LookupIterator::ACCESS_CHECK:
5570     case LookupIterator::INTERCEPTOR:
5571     case LookupIterator::INTEGER_INDEXED_EXOTIC:
5572     case LookupIterator::NOT_FOUND:
5573       return kUseGeneric;
5574     case LookupIterator::DATA:
5575       if (access_type == STORE && it->IsReadOnly()) return kUseGeneric;
5576       return kUseCell;
5577     case LookupIterator::JSPROXY:
5578     case LookupIterator::TRANSITION:
5579       UNREACHABLE();
5580   }
5581   UNREACHABLE();
5582   return kUseGeneric;
5583 }
5584
5585
5586 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
5587   DCHECK(var->IsContextSlot());
5588   HValue* context = environment()->context();
5589   int length = scope()->ContextChainLength(var->scope());
5590   while (length-- > 0) {
5591     context = Add<HLoadNamedField>(
5592         context, nullptr,
5593         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
5594   }
5595   return context;
5596 }
5597
5598
5599 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
5600   DCHECK(!HasStackOverflow());
5601   DCHECK(current_block() != NULL);
5602   DCHECK(current_block()->HasPredecessor());
5603   Variable* variable = expr->var();
5604   switch (variable->location()) {
5605     case VariableLocation::GLOBAL:
5606     case VariableLocation::UNALLOCATED: {
5607       if (IsLexicalVariableMode(variable->mode())) {
5608         // TODO(rossberg): should this be an DCHECK?
5609         return Bailout(kReferenceToGlobalLexicalVariable);
5610       }
5611       // Handle known global constants like 'undefined' specially to avoid a
5612       // load from a global cell for them.
5613       Handle<Object> constant_value =
5614           isolate()->factory()->GlobalConstantFor(variable->name());
5615       if (!constant_value.is_null()) {
5616         HConstant* instr = New<HConstant>(constant_value);
5617         return ast_context()->ReturnInstruction(instr, expr->id());
5618       }
5619
5620       Handle<GlobalObject> global(current_info()->global_object());
5621
5622       // Lookup in script contexts.
5623       {
5624         Handle<ScriptContextTable> script_contexts(
5625             global->native_context()->script_context_table());
5626         ScriptContextTable::LookupResult lookup;
5627         if (ScriptContextTable::Lookup(script_contexts, variable->name(),
5628                                        &lookup)) {
5629           Handle<Context> script_context = ScriptContextTable::GetContext(
5630               script_contexts, lookup.context_index);
5631           Handle<Object> current_value =
5632               FixedArray::get(script_context, lookup.slot_index);
5633
5634           // If the values is not the hole, it will stay initialized,
5635           // so no need to generate a check.
5636           if (*current_value == *isolate()->factory()->the_hole_value()) {
5637             return Bailout(kReferenceToUninitializedVariable);
5638           }
5639           HInstruction* result = New<HLoadNamedField>(
5640               Add<HConstant>(script_context), nullptr,
5641               HObjectAccess::ForContextSlot(lookup.slot_index));
5642           return ast_context()->ReturnInstruction(result, expr->id());
5643         }
5644       }
5645
5646       LookupIterator it(global, variable->name(), LookupIterator::OWN);
5647       GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD);
5648
5649       if (type == kUseCell) {
5650         Handle<PropertyCell> cell = it.GetPropertyCell();
5651         top_info()->dependencies()->AssumePropertyCell(cell);
5652         auto cell_type = it.property_details().cell_type();
5653         if (cell_type == PropertyCellType::kConstant ||
5654             cell_type == PropertyCellType::kUndefined) {
5655           Handle<Object> constant_object(cell->value(), isolate());
5656           if (constant_object->IsConsString()) {
5657             constant_object =
5658                 String::Flatten(Handle<String>::cast(constant_object));
5659           }
5660           HConstant* constant = New<HConstant>(constant_object);
5661           return ast_context()->ReturnInstruction(constant, expr->id());
5662         } else {
5663           auto access = HObjectAccess::ForPropertyCellValue();
5664           UniqueSet<Map>* field_maps = nullptr;
5665           if (cell_type == PropertyCellType::kConstantType) {
5666             switch (cell->GetConstantType()) {
5667               case PropertyCellConstantType::kSmi:
5668                 access = access.WithRepresentation(Representation::Smi());
5669                 break;
5670               case PropertyCellConstantType::kStableMap: {
5671                 // Check that the map really is stable. The heap object could
5672                 // have mutated without the cell updating state. In that case,
5673                 // make no promises about the loaded value except that it's a
5674                 // heap object.
5675                 access =
5676                     access.WithRepresentation(Representation::HeapObject());
5677                 Handle<Map> map(HeapObject::cast(cell->value())->map());
5678                 if (map->is_stable()) {
5679                   field_maps = new (zone())
5680                       UniqueSet<Map>(Unique<Map>::CreateImmovable(map), zone());
5681                 }
5682                 break;
5683               }
5684             }
5685           }
5686           HConstant* cell_constant = Add<HConstant>(cell);
5687           HLoadNamedField* instr;
5688           if (field_maps == nullptr) {
5689             instr = New<HLoadNamedField>(cell_constant, nullptr, access);
5690           } else {
5691             instr = New<HLoadNamedField>(cell_constant, nullptr, access,
5692                                          field_maps, HType::HeapObject());
5693           }
5694           instr->ClearDependsOnFlag(kInobjectFields);
5695           instr->SetDependsOnFlag(kGlobalVars);
5696           return ast_context()->ReturnInstruction(instr, expr->id());
5697         }
5698       } else if (variable->IsGlobalSlot()) {
5699         DCHECK(variable->index() > 0);
5700         DCHECK(variable->IsStaticGlobalObjectProperty());
5701         int slot_index = variable->index();
5702         int depth = scope()->ContextChainLength(variable->scope());
5703
5704         HLoadGlobalViaContext* instr =
5705             New<HLoadGlobalViaContext>(depth, slot_index);
5706         return ast_context()->ReturnInstruction(instr, expr->id());
5707
5708       } else {
5709         HValue* global_object = Add<HLoadNamedField>(
5710             context(), nullptr,
5711             HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
5712         HLoadGlobalGeneric* instr = New<HLoadGlobalGeneric>(
5713             global_object, variable->name(), ast_context()->typeof_mode());
5714         instr->SetVectorAndSlot(handle(current_feedback_vector(), isolate()),
5715                                 expr->VariableFeedbackSlot());
5716         return ast_context()->ReturnInstruction(instr, expr->id());
5717       }
5718     }
5719
5720     case VariableLocation::PARAMETER:
5721     case VariableLocation::LOCAL: {
5722       HValue* value = LookupAndMakeLive(variable);
5723       if (value == graph()->GetConstantHole()) {
5724         DCHECK(IsDeclaredVariableMode(variable->mode()) &&
5725                variable->mode() != VAR);
5726         return Bailout(kReferenceToUninitializedVariable);
5727       }
5728       return ast_context()->ReturnValue(value);
5729     }
5730
5731     case VariableLocation::CONTEXT: {
5732       HValue* context = BuildContextChainWalk(variable);
5733       HLoadContextSlot::Mode mode;
5734       switch (variable->mode()) {
5735         case LET:
5736         case CONST:
5737           mode = HLoadContextSlot::kCheckDeoptimize;
5738           break;
5739         case CONST_LEGACY:
5740           mode = HLoadContextSlot::kCheckReturnUndefined;
5741           break;
5742         default:
5743           mode = HLoadContextSlot::kNoCheck;
5744           break;
5745       }
5746       HLoadContextSlot* instr =
5747           new(zone()) HLoadContextSlot(context, variable->index(), mode);
5748       return ast_context()->ReturnInstruction(instr, expr->id());
5749     }
5750
5751     case VariableLocation::LOOKUP:
5752       return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup);
5753   }
5754 }
5755
5756
5757 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) {
5758   DCHECK(!HasStackOverflow());
5759   DCHECK(current_block() != NULL);
5760   DCHECK(current_block()->HasPredecessor());
5761   HConstant* instr = New<HConstant>(expr->value());
5762   return ast_context()->ReturnInstruction(instr, expr->id());
5763 }
5764
5765
5766 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
5767   DCHECK(!HasStackOverflow());
5768   DCHECK(current_block() != NULL);
5769   DCHECK(current_block()->HasPredecessor());
5770   Handle<JSFunction> closure = function_state()->compilation_info()->closure();
5771   Handle<FixedArray> literals(closure->literals());
5772   HRegExpLiteral* instr = New<HRegExpLiteral>(literals,
5773                                               expr->pattern(),
5774                                               expr->flags(),
5775                                               expr->literal_index());
5776   return ast_context()->ReturnInstruction(instr, expr->id());
5777 }
5778
5779
5780 static bool CanInlinePropertyAccess(Handle<Map> map) {
5781   if (map->instance_type() == HEAP_NUMBER_TYPE) return true;
5782   if (map->instance_type() < FIRST_NONSTRING_TYPE) return true;
5783   return map->IsJSObjectMap() && !map->is_dictionary_map() &&
5784          !map->has_named_interceptor() &&
5785          // TODO(verwaest): Whitelist contexts to which we have access.
5786          !map->is_access_check_needed();
5787 }
5788
5789
5790 // Determines whether the given array or object literal boilerplate satisfies
5791 // all limits to be considered for fast deep-copying and computes the total
5792 // size of all objects that are part of the graph.
5793 static bool IsFastLiteral(Handle<JSObject> boilerplate,
5794                           int max_depth,
5795                           int* max_properties) {
5796   if (boilerplate->map()->is_deprecated() &&
5797       !JSObject::TryMigrateInstance(boilerplate)) {
5798     return false;
5799   }
5800
5801   DCHECK(max_depth >= 0 && *max_properties >= 0);
5802   if (max_depth == 0) return false;
5803
5804   Isolate* isolate = boilerplate->GetIsolate();
5805   Handle<FixedArrayBase> elements(boilerplate->elements());
5806   if (elements->length() > 0 &&
5807       elements->map() != isolate->heap()->fixed_cow_array_map()) {
5808     if (boilerplate->HasFastSmiOrObjectElements()) {
5809       Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
5810       int length = elements->length();
5811       for (int i = 0; i < length; i++) {
5812         if ((*max_properties)-- == 0) return false;
5813         Handle<Object> value(fast_elements->get(i), isolate);
5814         if (value->IsJSObject()) {
5815           Handle<JSObject> value_object = Handle<JSObject>::cast(value);
5816           if (!IsFastLiteral(value_object,
5817                              max_depth - 1,
5818                              max_properties)) {
5819             return false;
5820           }
5821         }
5822       }
5823     } else if (!boilerplate->HasFastDoubleElements()) {
5824       return false;
5825     }
5826   }
5827
5828   Handle<FixedArray> properties(boilerplate->properties());
5829   if (properties->length() > 0) {
5830     return false;
5831   } else {
5832     Handle<DescriptorArray> descriptors(
5833         boilerplate->map()->instance_descriptors());
5834     int limit = boilerplate->map()->NumberOfOwnDescriptors();
5835     for (int i = 0; i < limit; i++) {
5836       PropertyDetails details = descriptors->GetDetails(i);
5837       if (details.type() != DATA) continue;
5838       if ((*max_properties)-- == 0) return false;
5839       FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
5840       if (boilerplate->IsUnboxedDoubleField(field_index)) continue;
5841       Handle<Object> value(boilerplate->RawFastPropertyAt(field_index),
5842                            isolate);
5843       if (value->IsJSObject()) {
5844         Handle<JSObject> value_object = Handle<JSObject>::cast(value);
5845         if (!IsFastLiteral(value_object,
5846                            max_depth - 1,
5847                            max_properties)) {
5848           return false;
5849         }
5850       }
5851     }
5852   }
5853   return true;
5854 }
5855
5856
5857 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
5858   DCHECK(!HasStackOverflow());
5859   DCHECK(current_block() != NULL);
5860   DCHECK(current_block()->HasPredecessor());
5861
5862   Handle<JSFunction> closure = function_state()->compilation_info()->closure();
5863   HInstruction* literal;
5864
5865   // Check whether to use fast or slow deep-copying for boilerplate.
5866   int max_properties = kMaxFastLiteralProperties;
5867   Handle<Object> literals_cell(closure->literals()->get(expr->literal_index()),
5868                                isolate());
5869   Handle<AllocationSite> site;
5870   Handle<JSObject> boilerplate;
5871   if (!literals_cell->IsUndefined()) {
5872     // Retrieve the boilerplate
5873     site = Handle<AllocationSite>::cast(literals_cell);
5874     boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()),
5875                                    isolate());
5876   }
5877
5878   if (!boilerplate.is_null() &&
5879       IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
5880     AllocationSiteUsageContext site_context(isolate(), site, false);
5881     site_context.EnterNewScope();
5882     literal = BuildFastLiteral(boilerplate, &site_context);
5883     site_context.ExitScope(site, boilerplate);
5884   } else {
5885     NoObservableSideEffectsScope no_effects(this);
5886     Handle<FixedArray> closure_literals(closure->literals(), isolate());
5887     Handle<FixedArray> constant_properties = expr->constant_properties();
5888     int literal_index = expr->literal_index();
5889     int flags = expr->ComputeFlags(true);
5890
5891     Add<HPushArguments>(Add<HConstant>(closure_literals),
5892                         Add<HConstant>(literal_index),
5893                         Add<HConstant>(constant_properties),
5894                         Add<HConstant>(flags));
5895
5896     Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral;
5897     literal = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 4);
5898   }
5899
5900   // The object is expected in the bailout environment during computation
5901   // of the property values and is the value of the entire expression.
5902   Push(literal);
5903   for (int i = 0; i < expr->properties()->length(); i++) {
5904     ObjectLiteral::Property* property = expr->properties()->at(i);
5905     if (property->is_computed_name()) return Bailout(kComputedPropertyName);
5906     if (property->IsCompileTimeValue()) continue;
5907
5908     Literal* key = property->key()->AsLiteral();
5909     Expression* value = property->value();
5910
5911     switch (property->kind()) {
5912       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
5913         DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
5914         // Fall through.
5915       case ObjectLiteral::Property::COMPUTED:
5916         // It is safe to use [[Put]] here because the boilerplate already
5917         // contains computed properties with an uninitialized value.
5918         if (key->value()->IsInternalizedString()) {
5919           if (property->emit_store()) {
5920             CHECK_ALIVE(VisitForValue(value));
5921             HValue* value = Pop();
5922
5923             Handle<Map> map = property->GetReceiverType();
5924             Handle<String> name = key->AsPropertyName();
5925             HValue* store;
5926             FeedbackVectorICSlot slot = property->GetSlot();
5927             if (map.is_null()) {
5928               // If we don't know the monomorphic type, do a generic store.
5929               CHECK_ALIVE(store = BuildNamedGeneric(STORE, NULL, slot, literal,
5930                                                     name, value));
5931             } else {
5932               PropertyAccessInfo info(this, STORE, map, name);
5933               if (info.CanAccessMonomorphic()) {
5934                 HValue* checked_literal = Add<HCheckMaps>(literal, map);
5935                 DCHECK(!info.IsAccessorConstant());
5936                 store = BuildMonomorphicAccess(
5937                     &info, literal, checked_literal, value,
5938                     BailoutId::None(), BailoutId::None());
5939               } else {
5940                 CHECK_ALIVE(store = BuildNamedGeneric(STORE, NULL, slot,
5941                                                       literal, name, value));
5942               }
5943             }
5944             if (store->IsInstruction()) {
5945               AddInstruction(HInstruction::cast(store));
5946             }
5947             DCHECK(store->HasObservableSideEffects());
5948             Add<HSimulate>(key->id(), REMOVABLE_SIMULATE);
5949
5950             // Add [[HomeObject]] to function literals.
5951             if (FunctionLiteral::NeedsHomeObject(property->value())) {
5952               Handle<Symbol> sym = isolate()->factory()->home_object_symbol();
5953               HInstruction* store_home = BuildNamedGeneric(
5954                   STORE, NULL, property->GetSlot(1), value, sym, literal);
5955               AddInstruction(store_home);
5956               DCHECK(store_home->HasObservableSideEffects());
5957               Add<HSimulate>(property->value()->id(), REMOVABLE_SIMULATE);
5958             }
5959           } else {
5960             CHECK_ALIVE(VisitForEffect(value));
5961           }
5962           break;
5963         }
5964         // Fall through.
5965       case ObjectLiteral::Property::PROTOTYPE:
5966       case ObjectLiteral::Property::SETTER:
5967       case ObjectLiteral::Property::GETTER:
5968         return Bailout(kObjectLiteralWithComplexProperty);
5969       default: UNREACHABLE();
5970     }
5971   }
5972
5973   if (expr->has_function()) {
5974     // Return the result of the transformation to fast properties
5975     // instead of the original since this operation changes the map
5976     // of the object. This makes sure that the original object won't
5977     // be used by other optimized code before it is transformed
5978     // (e.g. because of code motion).
5979     HToFastProperties* result = Add<HToFastProperties>(Pop());
5980     return ast_context()->ReturnValue(result);
5981   } else {
5982     return ast_context()->ReturnValue(Pop());
5983   }
5984 }
5985
5986
5987 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
5988   DCHECK(!HasStackOverflow());
5989   DCHECK(current_block() != NULL);
5990   DCHECK(current_block()->HasPredecessor());
5991   expr->BuildConstantElements(isolate());
5992   ZoneList<Expression*>* subexprs = expr->values();
5993   int length = subexprs->length();
5994   HInstruction* literal;
5995
5996   Handle<AllocationSite> site;
5997   Handle<FixedArray> literals(environment()->closure()->literals(), isolate());
5998   bool uninitialized = false;
5999   Handle<Object> literals_cell(literals->get(expr->literal_index()),
6000                                isolate());
6001   Handle<JSObject> boilerplate_object;
6002   if (literals_cell->IsUndefined()) {
6003     uninitialized = true;
6004     Handle<Object> raw_boilerplate;
6005     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
6006         isolate(), raw_boilerplate,
6007         Runtime::CreateArrayLiteralBoilerplate(
6008             isolate(), literals, expr->constant_elements(),
6009             is_strong(function_language_mode())),
6010         Bailout(kArrayBoilerplateCreationFailed));
6011
6012     boilerplate_object = Handle<JSObject>::cast(raw_boilerplate);
6013     AllocationSiteCreationContext creation_context(isolate());
6014     site = creation_context.EnterNewScope();
6015     if (JSObject::DeepWalk(boilerplate_object, &creation_context).is_null()) {
6016       return Bailout(kArrayBoilerplateCreationFailed);
6017     }
6018     creation_context.ExitScope(site, boilerplate_object);
6019     literals->set(expr->literal_index(), *site);
6020
6021     if (boilerplate_object->elements()->map() ==
6022         isolate()->heap()->fixed_cow_array_map()) {
6023       isolate()->counters()->cow_arrays_created_runtime()->Increment();
6024     }
6025   } else {
6026     DCHECK(literals_cell->IsAllocationSite());
6027     site = Handle<AllocationSite>::cast(literals_cell);
6028     boilerplate_object = Handle<JSObject>(
6029         JSObject::cast(site->transition_info()), isolate());
6030   }
6031
6032   DCHECK(!boilerplate_object.is_null());
6033   DCHECK(site->SitePointsToLiteral());
6034
6035   ElementsKind boilerplate_elements_kind =
6036       boilerplate_object->GetElementsKind();
6037
6038   // Check whether to use fast or slow deep-copying for boilerplate.
6039   int max_properties = kMaxFastLiteralProperties;
6040   if (IsFastLiteral(boilerplate_object,
6041                     kMaxFastLiteralDepth,
6042                     &max_properties)) {
6043     AllocationSiteUsageContext site_context(isolate(), site, false);
6044     site_context.EnterNewScope();
6045     literal = BuildFastLiteral(boilerplate_object, &site_context);
6046     site_context.ExitScope(site, boilerplate_object);
6047   } else {
6048     NoObservableSideEffectsScope no_effects(this);
6049     // Boilerplate already exists and constant elements are never accessed,
6050     // pass an empty fixed array to the runtime function instead.
6051     Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array();
6052     int literal_index = expr->literal_index();
6053     int flags = expr->ComputeFlags(true);
6054
6055     Add<HPushArguments>(Add<HConstant>(literals),
6056                         Add<HConstant>(literal_index),
6057                         Add<HConstant>(constants),
6058                         Add<HConstant>(flags));
6059
6060     Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral;
6061     literal = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 4);
6062
6063     // Register to deopt if the boilerplate ElementsKind changes.
6064     top_info()->dependencies()->AssumeTransitionStable(site);
6065   }
6066
6067   // The array is expected in the bailout environment during computation
6068   // of the property values and is the value of the entire expression.
6069   Push(literal);
6070   // The literal index is on the stack, too.
6071   Push(Add<HConstant>(expr->literal_index()));
6072
6073   HInstruction* elements = NULL;
6074
6075   for (int i = 0; i < length; i++) {
6076     Expression* subexpr = subexprs->at(i);
6077     if (subexpr->IsSpread()) {
6078       return Bailout(kSpread);
6079     }
6080
6081     // If the subexpression is a literal or a simple materialized literal it
6082     // is already set in the cloned array.
6083     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
6084
6085     CHECK_ALIVE(VisitForValue(subexpr));
6086     HValue* value = Pop();
6087     if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral);
6088
6089     elements = AddLoadElements(literal);
6090
6091     HValue* key = Add<HConstant>(i);
6092
6093     switch (boilerplate_elements_kind) {
6094       case FAST_SMI_ELEMENTS:
6095       case FAST_HOLEY_SMI_ELEMENTS:
6096       case FAST_ELEMENTS:
6097       case FAST_HOLEY_ELEMENTS:
6098       case FAST_DOUBLE_ELEMENTS:
6099       case FAST_HOLEY_DOUBLE_ELEMENTS: {
6100         HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value,
6101                                               boilerplate_elements_kind);
6102         instr->SetUninitialized(uninitialized);
6103         break;
6104       }
6105       default:
6106         UNREACHABLE();
6107         break;
6108     }
6109
6110     Add<HSimulate>(expr->GetIdForElement(i));
6111   }
6112
6113   Drop(1);  // array literal index
6114   return ast_context()->ReturnValue(Pop());
6115 }
6116
6117
6118 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object,
6119                                                 Handle<Map> map) {
6120   BuildCheckHeapObject(object);
6121   return Add<HCheckMaps>(object, map);
6122 }
6123
6124
6125 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField(
6126     PropertyAccessInfo* info,
6127     HValue* checked_object) {
6128   // See if this is a load for an immutable property
6129   if (checked_object->ActualValue()->IsConstant()) {
6130     Handle<Object> object(
6131         HConstant::cast(checked_object->ActualValue())->handle(isolate()));
6132
6133     if (object->IsJSObject()) {
6134       LookupIterator it(object, info->name(),
6135                         LookupIterator::OWN_SKIP_INTERCEPTOR);
6136       Handle<Object> value = JSReceiver::GetDataProperty(&it);
6137       if (it.IsFound() && it.IsReadOnly() && !it.IsConfigurable()) {
6138         return New<HConstant>(value);
6139       }
6140     }
6141   }
6142
6143   HObjectAccess access = info->access();
6144   if (access.representation().IsDouble() &&
6145       (!FLAG_unbox_double_fields || !access.IsInobject())) {
6146     // Load the heap number.
6147     checked_object = Add<HLoadNamedField>(
6148         checked_object, nullptr,
6149         access.WithRepresentation(Representation::Tagged()));
6150     // Load the double value from it.
6151     access = HObjectAccess::ForHeapNumberValue();
6152   }
6153
6154   SmallMapList* map_list = info->field_maps();
6155   if (map_list->length() == 0) {
6156     return New<HLoadNamedField>(checked_object, checked_object, access);
6157   }
6158
6159   UniqueSet<Map>* maps = new(zone()) UniqueSet<Map>(map_list->length(), zone());
6160   for (int i = 0; i < map_list->length(); ++i) {
6161     maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone());
6162   }
6163   return New<HLoadNamedField>(
6164       checked_object, checked_object, access, maps, info->field_type());
6165 }
6166
6167
6168 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
6169     PropertyAccessInfo* info,
6170     HValue* checked_object,
6171     HValue* value) {
6172   bool transition_to_field = info->IsTransition();
6173   // TODO(verwaest): Move this logic into PropertyAccessInfo.
6174   HObjectAccess field_access = info->access();
6175
6176   HStoreNamedField *instr;
6177   if (field_access.representation().IsDouble() &&
6178       (!FLAG_unbox_double_fields || !field_access.IsInobject())) {
6179     HObjectAccess heap_number_access =
6180         field_access.WithRepresentation(Representation::Tagged());
6181     if (transition_to_field) {
6182       // The store requires a mutable HeapNumber to be allocated.
6183       NoObservableSideEffectsScope no_side_effects(this);
6184       HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
6185
6186       // TODO(hpayer): Allocation site pretenuring support.
6187       HInstruction* heap_number = Add<HAllocate>(heap_number_size,
6188           HType::HeapObject(),
6189           NOT_TENURED,
6190           MUTABLE_HEAP_NUMBER_TYPE);
6191       AddStoreMapConstant(
6192           heap_number, isolate()->factory()->mutable_heap_number_map());
6193       Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
6194                             value);
6195       instr = New<HStoreNamedField>(checked_object->ActualValue(),
6196                                     heap_number_access,
6197                                     heap_number);
6198     } else {
6199       // Already holds a HeapNumber; load the box and write its value field.
6200       HInstruction* heap_number =
6201           Add<HLoadNamedField>(checked_object, nullptr, heap_number_access);
6202       instr = New<HStoreNamedField>(heap_number,
6203                                     HObjectAccess::ForHeapNumberValue(),
6204                                     value, STORE_TO_INITIALIZED_ENTRY);
6205     }
6206   } else {
6207     if (field_access.representation().IsHeapObject()) {
6208       BuildCheckHeapObject(value);
6209     }
6210
6211     if (!info->field_maps()->is_empty()) {
6212       DCHECK(field_access.representation().IsHeapObject());
6213       value = Add<HCheckMaps>(value, info->field_maps());
6214     }
6215
6216     // This is a normal store.
6217     instr = New<HStoreNamedField>(
6218         checked_object->ActualValue(), field_access, value,
6219         transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY);
6220   }
6221
6222   if (transition_to_field) {
6223     Handle<Map> transition(info->transition());
6224     DCHECK(!transition->is_deprecated());
6225     instr->SetTransition(Add<HConstant>(transition));
6226   }
6227   return instr;
6228 }
6229
6230
6231 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible(
6232     PropertyAccessInfo* info) {
6233   if (!CanInlinePropertyAccess(map_)) return false;
6234
6235   // Currently only handle Type::Number as a polymorphic case.
6236   // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
6237   // instruction.
6238   if (IsNumberType()) return false;
6239
6240   // Values are only compatible for monomorphic load if they all behave the same
6241   // regarding value wrappers.
6242   if (IsValueWrapped() != info->IsValueWrapped()) return false;
6243
6244   if (!LookupDescriptor()) return false;
6245
6246   if (!IsFound()) {
6247     return (!info->IsFound() || info->has_holder()) &&
6248            map()->prototype() == info->map()->prototype();
6249   }
6250
6251   // Mismatch if the other access info found the property in the prototype
6252   // chain.
6253   if (info->has_holder()) return false;
6254
6255   if (IsAccessorConstant()) {
6256     return accessor_.is_identical_to(info->accessor_) &&
6257         api_holder_.is_identical_to(info->api_holder_);
6258   }
6259
6260   if (IsDataConstant()) {
6261     return constant_.is_identical_to(info->constant_);
6262   }
6263
6264   DCHECK(IsData());
6265   if (!info->IsData()) return false;
6266
6267   Representation r = access_.representation();
6268   if (IsLoad()) {
6269     if (!info->access_.representation().IsCompatibleForLoad(r)) return false;
6270   } else {
6271     if (!info->access_.representation().IsCompatibleForStore(r)) return false;
6272   }
6273   if (info->access_.offset() != access_.offset()) return false;
6274   if (info->access_.IsInobject() != access_.IsInobject()) return false;
6275   if (IsLoad()) {
6276     if (field_maps_.is_empty()) {
6277       info->field_maps_.Clear();
6278     } else if (!info->field_maps_.is_empty()) {
6279       for (int i = 0; i < field_maps_.length(); ++i) {
6280         info->field_maps_.AddMapIfMissing(field_maps_.at(i), info->zone());
6281       }
6282       info->field_maps_.Sort();
6283     }
6284   } else {
6285     // We can only merge stores that agree on their field maps. The comparison
6286     // below is safe, since we keep the field maps sorted.
6287     if (field_maps_.length() != info->field_maps_.length()) return false;
6288     for (int i = 0; i < field_maps_.length(); ++i) {
6289       if (!field_maps_.at(i).is_identical_to(info->field_maps_.at(i))) {
6290         return false;
6291       }
6292     }
6293   }
6294   info->GeneralizeRepresentation(r);
6295   info->field_type_ = info->field_type_.Combine(field_type_);
6296   return true;
6297 }
6298
6299
6300 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() {
6301   if (!map_->IsJSObjectMap()) return true;
6302   LookupDescriptor(*map_, *name_);
6303   return LoadResult(map_);
6304 }
6305
6306
6307 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
6308   if (!IsLoad() && IsProperty() && IsReadOnly()) {
6309     return false;
6310   }
6311
6312   if (IsData()) {
6313     // Construct the object field access.
6314     int index = GetLocalFieldIndexFromMap(map);
6315     access_ = HObjectAccess::ForField(map, index, representation(), name_);
6316
6317     // Load field map for heap objects.
6318     return LoadFieldMaps(map);
6319   } else if (IsAccessorConstant()) {
6320     Handle<Object> accessors = GetAccessorsFromMap(map);
6321     if (!accessors->IsAccessorPair()) return false;
6322     Object* raw_accessor =
6323         IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter()
6324                  : Handle<AccessorPair>::cast(accessors)->setter();
6325     if (!raw_accessor->IsJSFunction()) return false;
6326     Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor));
6327     if (accessor->shared()->IsApiFunction()) {
6328       CallOptimization call_optimization(accessor);
6329       if (call_optimization.is_simple_api_call()) {
6330         CallOptimization::HolderLookup holder_lookup;
6331         api_holder_ =
6332             call_optimization.LookupHolderOfExpectedType(map_, &holder_lookup);
6333       }
6334     }
6335     accessor_ = accessor;
6336   } else if (IsDataConstant()) {
6337     constant_ = GetConstantFromMap(map);
6338   }
6339
6340   return true;
6341 }
6342
6343
6344 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps(
6345     Handle<Map> map) {
6346   // Clear any previously collected field maps/type.
6347   field_maps_.Clear();
6348   field_type_ = HType::Tagged();
6349
6350   // Figure out the field type from the accessor map.
6351   Handle<HeapType> field_type = GetFieldTypeFromMap(map);
6352
6353   // Collect the (stable) maps from the field type.
6354   int num_field_maps = field_type->NumClasses();
6355   if (num_field_maps > 0) {
6356     DCHECK(access_.representation().IsHeapObject());
6357     field_maps_.Reserve(num_field_maps, zone());
6358     HeapType::Iterator<Map> it = field_type->Classes();
6359     while (!it.Done()) {
6360       Handle<Map> field_map = it.Current();
6361       if (!field_map->is_stable()) {
6362         field_maps_.Clear();
6363         break;
6364       }
6365       field_maps_.Add(field_map, zone());
6366       it.Advance();
6367     }
6368   }
6369
6370   if (field_maps_.is_empty()) {
6371     // Store is not safe if the field map was cleared.
6372     return IsLoad() || !field_type->Is(HeapType::None());
6373   }
6374
6375   field_maps_.Sort();
6376   DCHECK_EQ(num_field_maps, field_maps_.length());
6377
6378   // Determine field HType from field HeapType.
6379   field_type_ = HType::FromType<HeapType>(field_type);
6380   DCHECK(field_type_.IsHeapObject());
6381
6382   // Add dependency on the map that introduced the field.
6383   top_info()->dependencies()->AssumeFieldType(GetFieldOwnerFromMap(map));
6384   return true;
6385 }
6386
6387
6388 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
6389   Handle<Map> map = this->map();
6390
6391   while (map->prototype()->IsJSObject()) {
6392     holder_ = handle(JSObject::cast(map->prototype()));
6393     if (holder_->map()->is_deprecated()) {
6394       JSObject::TryMigrateInstance(holder_);
6395     }
6396     map = Handle<Map>(holder_->map());
6397     if (!CanInlinePropertyAccess(map)) {
6398       NotFound();
6399       return false;
6400     }
6401     LookupDescriptor(*map, *name_);
6402     if (IsFound()) return LoadResult(map);
6403   }
6404
6405   NotFound();
6406   return !map->prototype()->IsJSReceiver();
6407 }
6408
6409
6410 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsIntegerIndexedExotic() {
6411   InstanceType instance_type = map_->instance_type();
6412   return instance_type == JS_TYPED_ARRAY_TYPE && name_->IsString() &&
6413          IsSpecialIndex(isolate()->unicode_cache(), String::cast(*name_));
6414 }
6415
6416
6417 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
6418   if (!CanInlinePropertyAccess(map_)) return false;
6419   if (IsJSObjectFieldAccessor()) return IsLoad();
6420   if (IsJSArrayBufferViewFieldAccessor()) return IsLoad();
6421   if (map_->function_with_prototype() && !map_->has_non_instance_prototype() &&
6422       name_.is_identical_to(isolate()->factory()->prototype_string())) {
6423     return IsLoad();
6424   }
6425   if (!LookupDescriptor()) return false;
6426   if (IsFound()) return IsLoad() || !IsReadOnly();
6427   if (IsIntegerIndexedExotic()) return false;
6428   if (!LookupInPrototypes()) return false;
6429   if (IsLoad()) return true;
6430
6431   if (IsAccessorConstant()) return true;
6432   LookupTransition(*map_, *name_, NONE);
6433   if (IsTransitionToData() && map_->unused_property_fields() > 0) {
6434     // Construct the object field access.
6435     int descriptor = transition()->LastAdded();
6436     int index =
6437         transition()->instance_descriptors()->GetFieldIndex(descriptor) -
6438         map_->GetInObjectProperties();
6439     PropertyDetails details =
6440         transition()->instance_descriptors()->GetDetails(descriptor);
6441     Representation representation = details.representation();
6442     access_ = HObjectAccess::ForField(map_, index, representation, name_);
6443
6444     // Load field map for heap objects.
6445     return LoadFieldMaps(transition());
6446   }
6447   return false;
6448 }
6449
6450
6451 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic(
6452     SmallMapList* maps) {
6453   DCHECK(map_.is_identical_to(maps->first()));
6454   if (!CanAccessMonomorphic()) return false;
6455   STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
6456   if (maps->length() > kMaxLoadPolymorphism) return false;
6457   HObjectAccess access = HObjectAccess::ForMap();  // bogus default
6458   if (GetJSObjectFieldAccess(&access)) {
6459     for (int i = 1; i < maps->length(); ++i) {
6460       PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
6461       HObjectAccess test_access = HObjectAccess::ForMap();  // bogus default
6462       if (!test_info.GetJSObjectFieldAccess(&test_access)) return false;
6463       if (!access.Equals(test_access)) return false;
6464     }
6465     return true;
6466   }
6467   if (GetJSArrayBufferViewFieldAccess(&access)) {
6468     for (int i = 1; i < maps->length(); ++i) {
6469       PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
6470       HObjectAccess test_access = HObjectAccess::ForMap();  // bogus default
6471       if (!test_info.GetJSArrayBufferViewFieldAccess(&test_access)) {
6472         return false;
6473       }
6474       if (!access.Equals(test_access)) return false;
6475     }
6476     return true;
6477   }
6478
6479   // Currently only handle numbers as a polymorphic case.
6480   // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
6481   // instruction.
6482   if (IsNumberType()) return false;
6483
6484   // Multiple maps cannot transition to the same target map.
6485   DCHECK(!IsLoad() || !IsTransition());
6486   if (IsTransition() && maps->length() > 1) return false;
6487
6488   for (int i = 1; i < maps->length(); ++i) {
6489     PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
6490     if (!test_info.IsCompatible(this)) return false;
6491   }
6492
6493   return true;
6494 }
6495
6496
6497 Handle<Map> HOptimizedGraphBuilder::PropertyAccessInfo::map() {
6498   JSFunction* ctor = IC::GetRootConstructor(
6499       *map_, current_info()->closure()->context()->native_context());
6500   if (ctor != NULL) return handle(ctor->initial_map());
6501   return map_;
6502 }
6503
6504
6505 static bool NeedsWrapping(Handle<Map> map, Handle<JSFunction> target) {
6506   return !map->IsJSObjectMap() &&
6507          is_sloppy(target->shared()->language_mode()) &&
6508          !target->shared()->native();
6509 }
6510
6511
6512 bool HOptimizedGraphBuilder::PropertyAccessInfo::NeedsWrappingFor(
6513     Handle<JSFunction> target) const {
6514   return NeedsWrapping(map_, target);
6515 }
6516
6517
6518 HValue* HOptimizedGraphBuilder::BuildMonomorphicAccess(
6519     PropertyAccessInfo* info, HValue* object, HValue* checked_object,
6520     HValue* value, BailoutId ast_id, BailoutId return_id,
6521     bool can_inline_accessor) {
6522   HObjectAccess access = HObjectAccess::ForMap();  // bogus default
6523   if (info->GetJSObjectFieldAccess(&access)) {
6524     DCHECK(info->IsLoad());
6525     return New<HLoadNamedField>(object, checked_object, access);
6526   }
6527
6528   if (info->GetJSArrayBufferViewFieldAccess(&access)) {
6529     DCHECK(info->IsLoad());
6530     checked_object = Add<HCheckArrayBufferNotNeutered>(checked_object);
6531     return New<HLoadNamedField>(object, checked_object, access);
6532   }
6533
6534   if (info->name().is_identical_to(isolate()->factory()->prototype_string()) &&
6535       info->map()->function_with_prototype()) {
6536     DCHECK(!info->map()->has_non_instance_prototype());
6537     return New<HLoadFunctionPrototype>(checked_object);
6538   }
6539
6540   HValue* checked_holder = checked_object;
6541   if (info->has_holder()) {
6542     Handle<JSObject> prototype(JSObject::cast(info->map()->prototype()));
6543     checked_holder = BuildCheckPrototypeMaps(prototype, info->holder());
6544   }
6545
6546   if (!info->IsFound()) {
6547     DCHECK(info->IsLoad());
6548     if (is_strong(function_language_mode())) {
6549       return New<HCallRuntime>(
6550           Runtime::FunctionForId(Runtime::kThrowStrongModeImplicitConversion),
6551           0);
6552     } else {
6553       return graph()->GetConstantUndefined();
6554     }
6555   }
6556
6557   if (info->IsData()) {
6558     if (info->IsLoad()) {
6559       return BuildLoadNamedField(info, checked_holder);
6560     } else {
6561       return BuildStoreNamedField(info, checked_object, value);
6562     }
6563   }
6564
6565   if (info->IsTransition()) {
6566     DCHECK(!info->IsLoad());
6567     return BuildStoreNamedField(info, checked_object, value);
6568   }
6569
6570   if (info->IsAccessorConstant()) {
6571     Push(checked_object);
6572     int argument_count = 1;
6573     if (!info->IsLoad()) {
6574       argument_count = 2;
6575       Push(value);
6576     }
6577
6578     if (info->NeedsWrappingFor(info->accessor())) {
6579       HValue* function = Add<HConstant>(info->accessor());
6580       PushArgumentsFromEnvironment(argument_count);
6581       return New<HCallFunction>(function, argument_count, WRAP_AND_CALL);
6582     } else if (FLAG_inline_accessors && can_inline_accessor) {
6583       bool success = info->IsLoad()
6584           ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id)
6585           : TryInlineSetter(
6586               info->accessor(), info->map(), ast_id, return_id, value);
6587       if (success || HasStackOverflow()) return NULL;
6588     }
6589
6590     PushArgumentsFromEnvironment(argument_count);
6591     return BuildCallConstantFunction(info->accessor(), argument_count);
6592   }
6593
6594   DCHECK(info->IsDataConstant());
6595   if (info->IsLoad()) {
6596     return New<HConstant>(info->constant());
6597   } else {
6598     return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant()));
6599   }
6600 }
6601
6602
6603 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
6604     PropertyAccessType access_type, Expression* expr, FeedbackVectorICSlot slot,
6605     BailoutId ast_id, BailoutId return_id, HValue* object, HValue* value,
6606     SmallMapList* maps, Handle<String> name) {
6607   // Something did not match; must use a polymorphic load.
6608   int count = 0;
6609   HBasicBlock* join = NULL;
6610   HBasicBlock* number_block = NULL;
6611   bool handled_string = false;
6612
6613   bool handle_smi = false;
6614   STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
6615   int i;
6616   for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) {
6617     PropertyAccessInfo info(this, access_type, maps->at(i), name);
6618     if (info.IsStringType()) {
6619       if (handled_string) continue;
6620       handled_string = true;
6621     }
6622     if (info.CanAccessMonomorphic()) {
6623       count++;
6624       if (info.IsNumberType()) {
6625         handle_smi = true;
6626         break;
6627       }
6628     }
6629   }
6630
6631   if (i < maps->length()) {
6632     count = -1;
6633     maps->Clear();
6634   } else {
6635     count = 0;
6636   }
6637   HControlInstruction* smi_check = NULL;
6638   handled_string = false;
6639
6640   for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) {
6641     PropertyAccessInfo info(this, access_type, maps->at(i), name);
6642     if (info.IsStringType()) {
6643       if (handled_string) continue;
6644       handled_string = true;
6645     }
6646     if (!info.CanAccessMonomorphic()) continue;
6647
6648     if (count == 0) {
6649       join = graph()->CreateBasicBlock();
6650       if (handle_smi) {
6651         HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
6652         HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
6653         number_block = graph()->CreateBasicBlock();
6654         smi_check = New<HIsSmiAndBranch>(
6655             object, empty_smi_block, not_smi_block);
6656         FinishCurrentBlock(smi_check);
6657         GotoNoSimulate(empty_smi_block, number_block);
6658         set_current_block(not_smi_block);
6659       } else {
6660         BuildCheckHeapObject(object);
6661       }
6662     }
6663     ++count;
6664     HBasicBlock* if_true = graph()->CreateBasicBlock();
6665     HBasicBlock* if_false = graph()->CreateBasicBlock();
6666     HUnaryControlInstruction* compare;
6667
6668     HValue* dependency;
6669     if (info.IsNumberType()) {
6670       Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
6671       compare = New<HCompareMap>(object, heap_number_map, if_true, if_false);
6672       dependency = smi_check;
6673     } else if (info.IsStringType()) {
6674       compare = New<HIsStringAndBranch>(object, if_true, if_false);
6675       dependency = compare;
6676     } else {
6677       compare = New<HCompareMap>(object, info.map(), if_true, if_false);
6678       dependency = compare;
6679     }
6680     FinishCurrentBlock(compare);
6681
6682     if (info.IsNumberType()) {
6683       GotoNoSimulate(if_true, number_block);
6684       if_true = number_block;
6685     }
6686
6687     set_current_block(if_true);
6688
6689     HValue* access =
6690         BuildMonomorphicAccess(&info, object, dependency, value, ast_id,
6691                                return_id, FLAG_polymorphic_inlining);
6692
6693     HValue* result = NULL;
6694     switch (access_type) {
6695       case LOAD:
6696         result = access;
6697         break;
6698       case STORE:
6699         result = value;
6700         break;
6701     }
6702
6703     if (access == NULL) {
6704       if (HasStackOverflow()) return;
6705     } else {
6706       if (access->IsInstruction()) {
6707         HInstruction* instr = HInstruction::cast(access);
6708         if (!instr->IsLinked()) AddInstruction(instr);
6709       }
6710       if (!ast_context()->IsEffect()) Push(result);
6711     }
6712
6713     if (current_block() != NULL) Goto(join);
6714     set_current_block(if_false);
6715   }
6716
6717   // Finish up.  Unconditionally deoptimize if we've handled all the maps we
6718   // know about and do not want to handle ones we've never seen.  Otherwise
6719   // use a generic IC.
6720   if (count == maps->length() && FLAG_deoptimize_uncommon_cases) {
6721     FinishExitWithHardDeoptimization(
6722         Deoptimizer::kUnknownMapInPolymorphicAccess);
6723   } else {
6724     HInstruction* instr =
6725         BuildNamedGeneric(access_type, expr, slot, object, name, value);
6726     AddInstruction(instr);
6727     if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value);
6728
6729     if (join != NULL) {
6730       Goto(join);
6731     } else {
6732       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6733       if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
6734       return;
6735     }
6736   }
6737
6738   DCHECK(join != NULL);
6739   if (join->HasPredecessor()) {
6740     join->SetJoinId(ast_id);
6741     set_current_block(join);
6742     if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
6743   } else {
6744     set_current_block(NULL);
6745   }
6746 }
6747
6748
6749 static bool ComputeReceiverTypes(Expression* expr,
6750                                  HValue* receiver,
6751                                  SmallMapList** t,
6752                                  Zone* zone) {
6753   SmallMapList* maps = expr->GetReceiverTypes();
6754   *t = maps;
6755   bool monomorphic = expr->IsMonomorphic();
6756   if (maps != NULL && receiver->HasMonomorphicJSObjectType()) {
6757     Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
6758     maps->FilterForPossibleTransitions(root_map);
6759     monomorphic = maps->length() == 1;
6760   }
6761   return monomorphic && CanInlinePropertyAccess(maps->first());
6762 }
6763
6764
6765 static bool AreStringTypes(SmallMapList* maps) {
6766   for (int i = 0; i < maps->length(); i++) {
6767     if (maps->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
6768   }
6769   return true;
6770 }
6771
6772
6773 void HOptimizedGraphBuilder::BuildStore(Expression* expr, Property* prop,
6774                                         FeedbackVectorICSlot slot,
6775                                         BailoutId ast_id, BailoutId return_id,
6776                                         bool is_uninitialized) {
6777   if (!prop->key()->IsPropertyName()) {
6778     // Keyed store.
6779     HValue* value = Pop();
6780     HValue* key = Pop();
6781     HValue* object = Pop();
6782     bool has_side_effects = false;
6783     HValue* result =
6784         HandleKeyedElementAccess(object, key, value, expr, slot, ast_id,
6785                                  return_id, STORE, &has_side_effects);
6786     if (has_side_effects) {
6787       if (!ast_context()->IsEffect()) Push(value);
6788       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6789       if (!ast_context()->IsEffect()) Drop(1);
6790     }
6791     if (result == NULL) return;
6792     return ast_context()->ReturnValue(value);
6793   }
6794
6795   // Named store.
6796   HValue* value = Pop();
6797   HValue* object = Pop();
6798
6799   Literal* key = prop->key()->AsLiteral();
6800   Handle<String> name = Handle<String>::cast(key->value());
6801   DCHECK(!name.is_null());
6802
6803   HValue* access = BuildNamedAccess(STORE, ast_id, return_id, expr, slot,
6804                                     object, name, value, is_uninitialized);
6805   if (access == NULL) return;
6806
6807   if (!ast_context()->IsEffect()) Push(value);
6808   if (access->IsInstruction()) AddInstruction(HInstruction::cast(access));
6809   if (access->HasObservableSideEffects()) {
6810     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6811   }
6812   if (!ast_context()->IsEffect()) Drop(1);
6813   return ast_context()->ReturnValue(value);
6814 }
6815
6816
6817 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
6818   Property* prop = expr->target()->AsProperty();
6819   DCHECK(prop != NULL);
6820   CHECK_ALIVE(VisitForValue(prop->obj()));
6821   if (!prop->key()->IsPropertyName()) {
6822     CHECK_ALIVE(VisitForValue(prop->key()));
6823   }
6824   CHECK_ALIVE(VisitForValue(expr->value()));
6825   BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(),
6826              expr->AssignmentId(), expr->IsUninitialized());
6827 }
6828
6829
6830 // Because not every expression has a position and there is not common
6831 // superclass of Assignment and CountOperation, we cannot just pass the
6832 // owning expression instead of position and ast_id separately.
6833 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
6834     Variable* var, HValue* value, FeedbackVectorICSlot ic_slot,
6835     BailoutId ast_id) {
6836   Handle<GlobalObject> global(current_info()->global_object());
6837
6838   // Lookup in script contexts.
6839   {
6840     Handle<ScriptContextTable> script_contexts(
6841         global->native_context()->script_context_table());
6842     ScriptContextTable::LookupResult lookup;
6843     if (ScriptContextTable::Lookup(script_contexts, var->name(), &lookup)) {
6844       if (lookup.mode == CONST) {
6845         return Bailout(kNonInitializerAssignmentToConst);
6846       }
6847       Handle<Context> script_context =
6848           ScriptContextTable::GetContext(script_contexts, lookup.context_index);
6849
6850       Handle<Object> current_value =
6851           FixedArray::get(script_context, lookup.slot_index);
6852
6853       // If the values is not the hole, it will stay initialized,
6854       // so no need to generate a check.
6855       if (*current_value == *isolate()->factory()->the_hole_value()) {
6856         return Bailout(kReferenceToUninitializedVariable);
6857       }
6858
6859       HStoreNamedField* instr = Add<HStoreNamedField>(
6860           Add<HConstant>(script_context),
6861           HObjectAccess::ForContextSlot(lookup.slot_index), value);
6862       USE(instr);
6863       DCHECK(instr->HasObservableSideEffects());
6864       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6865       return;
6866     }
6867   }
6868
6869   LookupIterator it(global, var->name(), LookupIterator::OWN);
6870   GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE);
6871   if (type == kUseCell) {
6872     Handle<PropertyCell> cell = it.GetPropertyCell();
6873     top_info()->dependencies()->AssumePropertyCell(cell);
6874     auto cell_type = it.property_details().cell_type();
6875     if (cell_type == PropertyCellType::kConstant ||
6876         cell_type == PropertyCellType::kUndefined) {
6877       Handle<Object> constant(cell->value(), isolate());
6878       if (value->IsConstant()) {
6879         HConstant* c_value = HConstant::cast(value);
6880         if (!constant.is_identical_to(c_value->handle(isolate()))) {
6881           Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment,
6882                            Deoptimizer::EAGER);
6883         }
6884       } else {
6885         HValue* c_constant = Add<HConstant>(constant);
6886         IfBuilder builder(this);
6887         if (constant->IsNumber()) {
6888           builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ);
6889         } else {
6890           builder.If<HCompareObjectEqAndBranch>(value, c_constant);
6891         }
6892         builder.Then();
6893         builder.Else();
6894         Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment,
6895                          Deoptimizer::EAGER);
6896         builder.End();
6897       }
6898     }
6899     HConstant* cell_constant = Add<HConstant>(cell);
6900     auto access = HObjectAccess::ForPropertyCellValue();
6901     if (cell_type == PropertyCellType::kConstantType) {
6902       switch (cell->GetConstantType()) {
6903         case PropertyCellConstantType::kSmi:
6904           access = access.WithRepresentation(Representation::Smi());
6905           break;
6906         case PropertyCellConstantType::kStableMap: {
6907           // The map may no longer be stable, deopt if it's ever different from
6908           // what is currently there, which will allow for restablization.
6909           Handle<Map> map(HeapObject::cast(cell->value())->map());
6910           Add<HCheckHeapObject>(value);
6911           value = Add<HCheckMaps>(value, map);
6912           access = access.WithRepresentation(Representation::HeapObject());
6913           break;
6914         }
6915       }
6916     }
6917     HInstruction* instr = Add<HStoreNamedField>(cell_constant, access, value);
6918     instr->ClearChangesFlag(kInobjectFields);
6919     instr->SetChangesFlag(kGlobalVars);
6920     if (instr->HasObservableSideEffects()) {
6921       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6922     }
6923   } else if (var->IsGlobalSlot()) {
6924     DCHECK(var->index() > 0);
6925     DCHECK(var->IsStaticGlobalObjectProperty());
6926     int slot_index = var->index();
6927     int depth = scope()->ContextChainLength(var->scope());
6928
6929     HStoreGlobalViaContext* instr = Add<HStoreGlobalViaContext>(
6930         value, depth, slot_index, function_language_mode());
6931     USE(instr);
6932     DCHECK(instr->HasObservableSideEffects());
6933     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6934
6935   } else {
6936     HValue* global_object = Add<HLoadNamedField>(
6937         context(), nullptr,
6938         HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
6939     HStoreNamedGeneric* instr =
6940         Add<HStoreNamedGeneric>(global_object, var->name(), value,
6941                                 function_language_mode(), PREMONOMORPHIC);
6942     if (FLAG_vector_stores) {
6943       Handle<TypeFeedbackVector> vector =
6944           handle(current_feedback_vector(), isolate());
6945       instr->SetVectorAndSlot(vector, ic_slot);
6946     }
6947     USE(instr);
6948     DCHECK(instr->HasObservableSideEffects());
6949     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6950   }
6951 }
6952
6953
6954 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
6955   Expression* target = expr->target();
6956   VariableProxy* proxy = target->AsVariableProxy();
6957   Property* prop = target->AsProperty();
6958   DCHECK(proxy == NULL || prop == NULL);
6959
6960   // We have a second position recorded in the FullCodeGenerator to have
6961   // type feedback for the binary operation.
6962   BinaryOperation* operation = expr->binary_operation();
6963
6964   if (proxy != NULL) {
6965     Variable* var = proxy->var();
6966     if (var->mode() == LET)  {
6967       return Bailout(kUnsupportedLetCompoundAssignment);
6968     }
6969
6970     CHECK_ALIVE(VisitForValue(operation));
6971
6972     switch (var->location()) {
6973       case VariableLocation::GLOBAL:
6974       case VariableLocation::UNALLOCATED:
6975         HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(),
6976                                        expr->AssignmentId());
6977         break;
6978
6979       case VariableLocation::PARAMETER:
6980       case VariableLocation::LOCAL:
6981         if (var->mode() == CONST_LEGACY)  {
6982           return Bailout(kUnsupportedConstCompoundAssignment);
6983         }
6984         if (var->mode() == CONST) {
6985           return Bailout(kNonInitializerAssignmentToConst);
6986         }
6987         BindIfLive(var, Top());
6988         break;
6989
6990       case VariableLocation::CONTEXT: {
6991         // Bail out if we try to mutate a parameter value in a function
6992         // using the arguments object.  We do not (yet) correctly handle the
6993         // arguments property of the function.
6994         if (current_info()->scope()->arguments() != NULL) {
6995           // Parameters will be allocated to context slots.  We have no
6996           // direct way to detect that the variable is a parameter so we do
6997           // a linear search of the parameter variables.
6998           int count = current_info()->scope()->num_parameters();
6999           for (int i = 0; i < count; ++i) {
7000             if (var == current_info()->scope()->parameter(i)) {
7001               Bailout(kAssignmentToParameterFunctionUsesArgumentsObject);
7002             }
7003           }
7004         }
7005
7006         HStoreContextSlot::Mode mode;
7007
7008         switch (var->mode()) {
7009           case LET:
7010             mode = HStoreContextSlot::kCheckDeoptimize;
7011             break;
7012           case CONST:
7013             return Bailout(kNonInitializerAssignmentToConst);
7014           case CONST_LEGACY:
7015             return ast_context()->ReturnValue(Pop());
7016           default:
7017             mode = HStoreContextSlot::kNoCheck;
7018         }
7019
7020         HValue* context = BuildContextChainWalk(var);
7021         HStoreContextSlot* instr = Add<HStoreContextSlot>(
7022             context, var->index(), mode, Top());
7023         if (instr->HasObservableSideEffects()) {
7024           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
7025         }
7026         break;
7027       }
7028
7029       case VariableLocation::LOOKUP:
7030         return Bailout(kCompoundAssignmentToLookupSlot);
7031     }
7032     return ast_context()->ReturnValue(Pop());
7033
7034   } else if (prop != NULL) {
7035     CHECK_ALIVE(VisitForValue(prop->obj()));
7036     HValue* object = Top();
7037     HValue* key = NULL;
7038     if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
7039       CHECK_ALIVE(VisitForValue(prop->key()));
7040       key = Top();
7041     }
7042
7043     CHECK_ALIVE(PushLoad(prop, object, key));
7044
7045     CHECK_ALIVE(VisitForValue(expr->value()));
7046     HValue* right = Pop();
7047     HValue* left = Pop();
7048
7049     Push(BuildBinaryOperation(operation, left, right, PUSH_BEFORE_SIMULATE));
7050
7051     BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(),
7052                expr->AssignmentId(), expr->IsUninitialized());
7053   } else {
7054     return Bailout(kInvalidLhsInCompoundAssignment);
7055   }
7056 }
7057
7058
7059 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
7060   DCHECK(!HasStackOverflow());
7061   DCHECK(current_block() != NULL);
7062   DCHECK(current_block()->HasPredecessor());
7063   VariableProxy* proxy = expr->target()->AsVariableProxy();
7064   Property* prop = expr->target()->AsProperty();
7065   DCHECK(proxy == NULL || prop == NULL);
7066
7067   if (expr->is_compound()) {
7068     HandleCompoundAssignment(expr);
7069     return;
7070   }
7071
7072   if (prop != NULL) {
7073     HandlePropertyAssignment(expr);
7074   } else if (proxy != NULL) {
7075     Variable* var = proxy->var();
7076
7077     if (var->mode() == CONST) {
7078       if (expr->op() != Token::INIT_CONST) {
7079         return Bailout(kNonInitializerAssignmentToConst);
7080       }
7081     } else if (var->mode() == CONST_LEGACY) {
7082       if (expr->op() != Token::INIT_CONST_LEGACY) {
7083         CHECK_ALIVE(VisitForValue(expr->value()));
7084         return ast_context()->ReturnValue(Pop());
7085       }
7086
7087       if (var->IsStackAllocated()) {
7088         // We insert a use of the old value to detect unsupported uses of const
7089         // variables (e.g. initialization inside a loop).
7090         HValue* old_value = environment()->Lookup(var);
7091         Add<HUseConst>(old_value);
7092       }
7093     }
7094
7095     if (proxy->IsArguments()) return Bailout(kAssignmentToArguments);
7096
7097     // Handle the assignment.
7098     switch (var->location()) {
7099       case VariableLocation::GLOBAL:
7100       case VariableLocation::UNALLOCATED:
7101         CHECK_ALIVE(VisitForValue(expr->value()));
7102         HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(),
7103                                        expr->AssignmentId());
7104         return ast_context()->ReturnValue(Pop());
7105
7106       case VariableLocation::PARAMETER:
7107       case VariableLocation::LOCAL: {
7108         // Perform an initialization check for let declared variables
7109         // or parameters.
7110         if (var->mode() == LET && expr->op() == Token::ASSIGN) {
7111           HValue* env_value = environment()->Lookup(var);
7112           if (env_value == graph()->GetConstantHole()) {
7113             return Bailout(kAssignmentToLetVariableBeforeInitialization);
7114           }
7115         }
7116         // We do not allow the arguments object to occur in a context where it
7117         // may escape, but assignments to stack-allocated locals are
7118         // permitted.
7119         CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
7120         HValue* value = Pop();
7121         BindIfLive(var, value);
7122         return ast_context()->ReturnValue(value);
7123       }
7124
7125       case VariableLocation::CONTEXT: {
7126         // Bail out if we try to mutate a parameter value in a function using
7127         // the arguments object.  We do not (yet) correctly handle the
7128         // arguments property of the function.
7129         if (current_info()->scope()->arguments() != NULL) {
7130           // Parameters will rewrite to context slots.  We have no direct way
7131           // to detect that the variable is a parameter.
7132           int count = current_info()->scope()->num_parameters();
7133           for (int i = 0; i < count; ++i) {
7134             if (var == current_info()->scope()->parameter(i)) {
7135               return Bailout(kAssignmentToParameterInArgumentsObject);
7136             }
7137           }
7138         }
7139
7140         CHECK_ALIVE(VisitForValue(expr->value()));
7141         HStoreContextSlot::Mode mode;
7142         if (expr->op() == Token::ASSIGN) {
7143           switch (var->mode()) {
7144             case LET:
7145               mode = HStoreContextSlot::kCheckDeoptimize;
7146               break;
7147             case CONST:
7148               // This case is checked statically so no need to
7149               // perform checks here
7150               UNREACHABLE();
7151             case CONST_LEGACY:
7152               return ast_context()->ReturnValue(Pop());
7153             default:
7154               mode = HStoreContextSlot::kNoCheck;
7155           }
7156         } else if (expr->op() == Token::INIT_VAR ||
7157                    expr->op() == Token::INIT_LET ||
7158                    expr->op() == Token::INIT_CONST) {
7159           mode = HStoreContextSlot::kNoCheck;
7160         } else {
7161           DCHECK(expr->op() == Token::INIT_CONST_LEGACY);
7162
7163           mode = HStoreContextSlot::kCheckIgnoreAssignment;
7164         }
7165
7166         HValue* context = BuildContextChainWalk(var);
7167         HStoreContextSlot* instr = Add<HStoreContextSlot>(
7168             context, var->index(), mode, Top());
7169         if (instr->HasObservableSideEffects()) {
7170           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
7171         }
7172         return ast_context()->ReturnValue(Pop());
7173       }
7174
7175       case VariableLocation::LOOKUP:
7176         return Bailout(kAssignmentToLOOKUPVariable);
7177     }
7178   } else {
7179     return Bailout(kInvalidLeftHandSideInAssignment);
7180   }
7181 }
7182
7183
7184 void HOptimizedGraphBuilder::VisitYield(Yield* expr) {
7185   // Generators are not optimized, so we should never get here.
7186   UNREACHABLE();
7187 }
7188
7189
7190 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
7191   DCHECK(!HasStackOverflow());
7192   DCHECK(current_block() != NULL);
7193   DCHECK(current_block()->HasPredecessor());
7194   if (!ast_context()->IsEffect()) {
7195     // The parser turns invalid left-hand sides in assignments into throw
7196     // statements, which may not be in effect contexts. We might still try
7197     // to optimize such functions; bail out now if we do.
7198     return Bailout(kInvalidLeftHandSideInAssignment);
7199   }
7200   CHECK_ALIVE(VisitForValue(expr->exception()));
7201
7202   HValue* value = environment()->Pop();
7203   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
7204   Add<HPushArguments>(value);
7205   Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kThrow), 1);
7206   Add<HSimulate>(expr->id());
7207
7208   // If the throw definitely exits the function, we can finish with a dummy
7209   // control flow at this point.  This is not the case if the throw is inside
7210   // an inlined function which may be replaced.
7211   if (call_context() == NULL) {
7212     FinishExitCurrentBlock(New<HAbnormalExit>());
7213   }
7214 }
7215
7216
7217 HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) {
7218   if (string->IsConstant()) {
7219     HConstant* c_string = HConstant::cast(string);
7220     if (c_string->HasStringValue()) {
7221       return Add<HConstant>(c_string->StringValue()->map()->instance_type());
7222     }
7223   }
7224   return Add<HLoadNamedField>(
7225       Add<HLoadNamedField>(string, nullptr, HObjectAccess::ForMap()), nullptr,
7226       HObjectAccess::ForMapInstanceType());
7227 }
7228
7229
7230 HInstruction* HGraphBuilder::AddLoadStringLength(HValue* string) {
7231   return AddInstruction(BuildLoadStringLength(string));
7232 }
7233
7234
7235 HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* string) {
7236   if (string->IsConstant()) {
7237     HConstant* c_string = HConstant::cast(string);
7238     if (c_string->HasStringValue()) {
7239       return New<HConstant>(c_string->StringValue()->length());
7240     }
7241   }
7242   return New<HLoadNamedField>(string, nullptr,
7243                               HObjectAccess::ForStringLength());
7244 }
7245
7246
7247 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric(
7248     PropertyAccessType access_type, Expression* expr, FeedbackVectorICSlot slot,
7249     HValue* object, Handle<Name> name, HValue* value, bool is_uninitialized) {
7250   if (is_uninitialized) {
7251     Add<HDeoptimize>(
7252         Deoptimizer::kInsufficientTypeFeedbackForGenericNamedAccess,
7253         Deoptimizer::SOFT);
7254   }
7255   if (access_type == LOAD) {
7256     Handle<TypeFeedbackVector> vector =
7257         handle(current_feedback_vector(), isolate());
7258
7259     if (!expr->AsProperty()->key()->IsPropertyName()) {
7260       // It's possible that a keyed load of a constant string was converted
7261       // to a named load. Here, at the last minute, we need to make sure to
7262       // use a generic Keyed Load if we are using the type vector, because
7263       // it has to share information with full code.
7264       HConstant* key = Add<HConstant>(name);
7265       HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(
7266           object, key, function_language_mode(), PREMONOMORPHIC);
7267       result->SetVectorAndSlot(vector, slot);
7268       return result;
7269     }
7270
7271     HLoadNamedGeneric* result = New<HLoadNamedGeneric>(
7272         object, name, function_language_mode(), PREMONOMORPHIC);
7273     result->SetVectorAndSlot(vector, slot);
7274     return result;
7275   } else {
7276     if (FLAG_vector_stores &&
7277         current_feedback_vector()->GetKind(slot) == Code::KEYED_STORE_IC) {
7278       // It's possible that a keyed store of a constant string was converted
7279       // to a named store. Here, at the last minute, we need to make sure to
7280       // use a generic Keyed Store if we are using the type vector, because
7281       // it has to share information with full code.
7282       HConstant* key = Add<HConstant>(name);
7283       HStoreKeyedGeneric* result = New<HStoreKeyedGeneric>(
7284           object, key, value, function_language_mode(), PREMONOMORPHIC);
7285       Handle<TypeFeedbackVector> vector =
7286           handle(current_feedback_vector(), isolate());
7287       result->SetVectorAndSlot(vector, slot);
7288       return result;
7289     }
7290
7291     HStoreNamedGeneric* result = New<HStoreNamedGeneric>(
7292         object, name, value, function_language_mode(), PREMONOMORPHIC);
7293     if (FLAG_vector_stores) {
7294       Handle<TypeFeedbackVector> vector =
7295           handle(current_feedback_vector(), isolate());
7296       result->SetVectorAndSlot(vector, slot);
7297     }
7298     return result;
7299   }
7300 }
7301
7302
7303 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric(
7304     PropertyAccessType access_type, Expression* expr, FeedbackVectorICSlot slot,
7305     HValue* object, HValue* key, HValue* value) {
7306   if (access_type == LOAD) {
7307     InlineCacheState initial_state = expr->AsProperty()->GetInlineCacheState();
7308     HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(
7309         object, key, function_language_mode(), initial_state);
7310     // HLoadKeyedGeneric with vector ics benefits from being encoded as
7311     // MEGAMORPHIC because the vector/slot combo becomes unnecessary.
7312     if (initial_state != MEGAMORPHIC) {
7313       // We need to pass vector information.
7314       Handle<TypeFeedbackVector> vector =
7315           handle(current_feedback_vector(), isolate());
7316       result->SetVectorAndSlot(vector, slot);
7317     }
7318     return result;
7319   } else {
7320     HStoreKeyedGeneric* result = New<HStoreKeyedGeneric>(
7321         object, key, value, function_language_mode(), PREMONOMORPHIC);
7322     if (FLAG_vector_stores) {
7323       Handle<TypeFeedbackVector> vector =
7324           handle(current_feedback_vector(), isolate());
7325       result->SetVectorAndSlot(vector, slot);
7326     }
7327     return result;
7328   }
7329 }
7330
7331
7332 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) {
7333   // Loads from a "stock" fast holey double arrays can elide the hole check.
7334   // Loads from a "stock" fast holey array can convert the hole to undefined
7335   // with impunity.
7336   LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
7337   bool holey_double_elements =
7338       *map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS);
7339   bool holey_elements =
7340       *map == isolate()->get_initial_js_array_map(FAST_HOLEY_ELEMENTS);
7341   if ((holey_double_elements || holey_elements) &&
7342       isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
7343     load_mode =
7344         holey_double_elements ? ALLOW_RETURN_HOLE : CONVERT_HOLE_TO_UNDEFINED;
7345
7346     Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
7347     Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
7348     BuildCheckPrototypeMaps(prototype, object_prototype);
7349     graph()->MarkDependsOnEmptyArrayProtoElements();
7350   }
7351   return load_mode;
7352 }
7353
7354
7355 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
7356     HValue* object,
7357     HValue* key,
7358     HValue* val,
7359     HValue* dependency,
7360     Handle<Map> map,
7361     PropertyAccessType access_type,
7362     KeyedAccessStoreMode store_mode) {
7363   HCheckMaps* checked_object = Add<HCheckMaps>(object, map, dependency);
7364
7365   if (access_type == STORE && map->prototype()->IsJSObject()) {
7366     // monomorphic stores need a prototype chain check because shape
7367     // changes could allow callbacks on elements in the chain that
7368     // aren't compatible with monomorphic keyed stores.
7369     PrototypeIterator iter(map);
7370     JSObject* holder = NULL;
7371     while (!iter.IsAtEnd()) {
7372       holder = *PrototypeIterator::GetCurrent<JSObject>(iter);
7373       iter.Advance();
7374     }
7375     DCHECK(holder && holder->IsJSObject());
7376
7377     BuildCheckPrototypeMaps(handle(JSObject::cast(map->prototype())),
7378                             Handle<JSObject>(holder));
7379   }
7380
7381   LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
7382   return BuildUncheckedMonomorphicElementAccess(
7383       checked_object, key, val,
7384       map->instance_type() == JS_ARRAY_TYPE,
7385       map->elements_kind(), access_type,
7386       load_mode, store_mode);
7387 }
7388
7389
7390 static bool CanInlineElementAccess(Handle<Map> map) {
7391   return map->IsJSObjectMap() && !map->has_dictionary_elements() &&
7392          !map->has_sloppy_arguments_elements() &&
7393          !map->has_indexed_interceptor() && !map->is_access_check_needed();
7394 }
7395
7396
7397 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
7398     HValue* object,
7399     HValue* key,
7400     HValue* val,
7401     SmallMapList* maps) {
7402   // For polymorphic loads of similar elements kinds (i.e. all tagged or all
7403   // double), always use the "worst case" code without a transition.  This is
7404   // much faster than transitioning the elements to the worst case, trading a
7405   // HTransitionElements for a HCheckMaps, and avoiding mutation of the array.
7406   bool has_double_maps = false;
7407   bool has_smi_or_object_maps = false;
7408   bool has_js_array_access = false;
7409   bool has_non_js_array_access = false;
7410   bool has_seen_holey_elements = false;
7411   Handle<Map> most_general_consolidated_map;
7412   for (int i = 0; i < maps->length(); ++i) {
7413     Handle<Map> map = maps->at(i);
7414     if (!CanInlineElementAccess(map)) return NULL;
7415     // Don't allow mixing of JSArrays with JSObjects.
7416     if (map->instance_type() == JS_ARRAY_TYPE) {
7417       if (has_non_js_array_access) return NULL;
7418       has_js_array_access = true;
7419     } else if (has_js_array_access) {
7420       return NULL;
7421     } else {
7422       has_non_js_array_access = true;
7423     }
7424     // Don't allow mixed, incompatible elements kinds.
7425     if (map->has_fast_double_elements()) {
7426       if (has_smi_or_object_maps) return NULL;
7427       has_double_maps = true;
7428     } else if (map->has_fast_smi_or_object_elements()) {
7429       if (has_double_maps) return NULL;
7430       has_smi_or_object_maps = true;
7431     } else {
7432       return NULL;
7433     }
7434     // Remember if we've ever seen holey elements.
7435     if (IsHoleyElementsKind(map->elements_kind())) {
7436       has_seen_holey_elements = true;
7437     }
7438     // Remember the most general elements kind, the code for its load will
7439     // properly handle all of the more specific cases.
7440     if ((i == 0) || IsMoreGeneralElementsKindTransition(
7441             most_general_consolidated_map->elements_kind(),
7442             map->elements_kind())) {
7443       most_general_consolidated_map = map;
7444     }
7445   }
7446   if (!has_double_maps && !has_smi_or_object_maps) return NULL;
7447
7448   HCheckMaps* checked_object = Add<HCheckMaps>(object, maps);
7449   // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS.
7450   // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS.
7451   ElementsKind consolidated_elements_kind = has_seen_holey_elements
7452       ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind())
7453       : most_general_consolidated_map->elements_kind();
7454   LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
7455   if (has_seen_holey_elements) {
7456     // Make sure that all of the maps we are handling have the initial array
7457     // prototype.
7458     bool saw_non_array_prototype = false;
7459     for (int i = 0; i < maps->length(); ++i) {
7460       Handle<Map> map = maps->at(i);
7461       if (map->prototype() != *isolate()->initial_array_prototype()) {
7462         // We can't guarantee that loading the hole is safe. The prototype may
7463         // have an element at this position.
7464         saw_non_array_prototype = true;
7465         break;
7466       }
7467     }
7468
7469     if (!saw_non_array_prototype) {
7470       Handle<Map> holey_map = handle(
7471           isolate()->get_initial_js_array_map(consolidated_elements_kind));
7472       load_mode = BuildKeyedHoleMode(holey_map);
7473       if (load_mode != NEVER_RETURN_HOLE) {
7474         for (int i = 0; i < maps->length(); ++i) {
7475           Handle<Map> map = maps->at(i);
7476           // The prototype check was already done for the holey map in
7477           // BuildKeyedHoleMode.
7478           if (!map.is_identical_to(holey_map)) {
7479             Handle<JSObject> prototype(JSObject::cast(map->prototype()),
7480                                        isolate());
7481             Handle<JSObject> object_prototype =
7482                 isolate()->initial_object_prototype();
7483             BuildCheckPrototypeMaps(prototype, object_prototype);
7484           }
7485         }
7486       }
7487     }
7488   }
7489   HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
7490       checked_object, key, val,
7491       most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
7492       consolidated_elements_kind, LOAD, load_mode, STANDARD_STORE);
7493   return instr;
7494 }
7495
7496
7497 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
7498     Expression* expr, FeedbackVectorICSlot slot, HValue* object, HValue* key,
7499     HValue* val, SmallMapList* maps, PropertyAccessType access_type,
7500     KeyedAccessStoreMode store_mode, bool* has_side_effects) {
7501   *has_side_effects = false;
7502   BuildCheckHeapObject(object);
7503
7504   if (access_type == LOAD) {
7505     HInstruction* consolidated_load =
7506         TryBuildConsolidatedElementLoad(object, key, val, maps);
7507     if (consolidated_load != NULL) {
7508       *has_side_effects |= consolidated_load->HasObservableSideEffects();
7509       return consolidated_load;
7510     }
7511   }
7512
7513   // Elements_kind transition support.
7514   MapHandleList transition_target(maps->length());
7515   // Collect possible transition targets.
7516   MapHandleList possible_transitioned_maps(maps->length());
7517   for (int i = 0; i < maps->length(); ++i) {
7518     Handle<Map> map = maps->at(i);
7519     // Loads from strings or loads with a mix of string and non-string maps
7520     // shouldn't be handled polymorphically.
7521     DCHECK(access_type != LOAD || !map->IsStringMap());
7522     ElementsKind elements_kind = map->elements_kind();
7523     if (CanInlineElementAccess(map) && IsFastElementsKind(elements_kind) &&
7524         elements_kind != GetInitialFastElementsKind()) {
7525       possible_transitioned_maps.Add(map);
7526     }
7527     if (IsSloppyArgumentsElements(elements_kind)) {
7528       HInstruction* result =
7529           BuildKeyedGeneric(access_type, expr, slot, object, key, val);
7530       *has_side_effects = result->HasObservableSideEffects();
7531       return AddInstruction(result);
7532     }
7533   }
7534   // Get transition target for each map (NULL == no transition).
7535   for (int i = 0; i < maps->length(); ++i) {
7536     Handle<Map> map = maps->at(i);
7537     Handle<Map> transitioned_map =
7538         Map::FindTransitionedMap(map, &possible_transitioned_maps);
7539     transition_target.Add(transitioned_map);
7540   }
7541
7542   MapHandleList untransitionable_maps(maps->length());
7543   HTransitionElementsKind* transition = NULL;
7544   for (int i = 0; i < maps->length(); ++i) {
7545     Handle<Map> map = maps->at(i);
7546     DCHECK(map->IsMap());
7547     if (!transition_target.at(i).is_null()) {
7548       DCHECK(Map::IsValidElementsTransition(
7549           map->elements_kind(),
7550           transition_target.at(i)->elements_kind()));
7551       transition = Add<HTransitionElementsKind>(object, map,
7552                                                 transition_target.at(i));
7553     } else {
7554       untransitionable_maps.Add(map);
7555     }
7556   }
7557
7558   // If only one map is left after transitioning, handle this case
7559   // monomorphically.
7560   DCHECK(untransitionable_maps.length() >= 1);
7561   if (untransitionable_maps.length() == 1) {
7562     Handle<Map> untransitionable_map = untransitionable_maps[0];
7563     HInstruction* instr = NULL;
7564     if (!CanInlineElementAccess(untransitionable_map)) {
7565       instr = AddInstruction(
7566           BuildKeyedGeneric(access_type, expr, slot, object, key, val));
7567     } else {
7568       instr = BuildMonomorphicElementAccess(
7569           object, key, val, transition, untransitionable_map, access_type,
7570           store_mode);
7571     }
7572     *has_side_effects |= instr->HasObservableSideEffects();
7573     return access_type == STORE ? val : instr;
7574   }
7575
7576   HBasicBlock* join = graph()->CreateBasicBlock();
7577
7578   for (int i = 0; i < untransitionable_maps.length(); ++i) {
7579     Handle<Map> map = untransitionable_maps[i];
7580     ElementsKind elements_kind = map->elements_kind();
7581     HBasicBlock* this_map = graph()->CreateBasicBlock();
7582     HBasicBlock* other_map = graph()->CreateBasicBlock();
7583     HCompareMap* mapcompare =
7584         New<HCompareMap>(object, map, this_map, other_map);
7585     FinishCurrentBlock(mapcompare);
7586
7587     set_current_block(this_map);
7588     HInstruction* access = NULL;
7589     if (!CanInlineElementAccess(map)) {
7590       access = AddInstruction(
7591           BuildKeyedGeneric(access_type, expr, slot, object, key, val));
7592     } else {
7593       DCHECK(IsFastElementsKind(elements_kind) ||
7594              IsFixedTypedArrayElementsKind(elements_kind));
7595       LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
7596       // Happily, mapcompare is a checked object.
7597       access = BuildUncheckedMonomorphicElementAccess(
7598           mapcompare, key, val,
7599           map->instance_type() == JS_ARRAY_TYPE,
7600           elements_kind, access_type,
7601           load_mode,
7602           store_mode);
7603     }
7604     *has_side_effects |= access->HasObservableSideEffects();
7605     // The caller will use has_side_effects and add a correct Simulate.
7606     access->SetFlag(HValue::kHasNoObservableSideEffects);
7607     if (access_type == LOAD) {
7608       Push(access);
7609     }
7610     NoObservableSideEffectsScope scope(this);
7611     GotoNoSimulate(join);
7612     set_current_block(other_map);
7613   }
7614
7615   // Ensure that we visited at least one map above that goes to join. This is
7616   // necessary because FinishExitWithHardDeoptimization does an AbnormalExit
7617   // rather than joining the join block. If this becomes an issue, insert a
7618   // generic access in the case length() == 0.
7619   DCHECK(join->predecessors()->length() > 0);
7620   // Deopt if none of the cases matched.
7621   NoObservableSideEffectsScope scope(this);
7622   FinishExitWithHardDeoptimization(
7623       Deoptimizer::kUnknownMapInPolymorphicElementAccess);
7624   set_current_block(join);
7625   return access_type == STORE ? val : Pop();
7626 }
7627
7628
7629 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
7630     HValue* obj, HValue* key, HValue* val, Expression* expr,
7631     FeedbackVectorICSlot slot, BailoutId ast_id, BailoutId return_id,
7632     PropertyAccessType access_type, bool* has_side_effects) {
7633   if (key->ActualValue()->IsConstant()) {
7634     Handle<Object> constant =
7635         HConstant::cast(key->ActualValue())->handle(isolate());
7636     uint32_t array_index;
7637     if (constant->IsString() &&
7638         !Handle<String>::cast(constant)->AsArrayIndex(&array_index)) {
7639       if (!constant->IsUniqueName()) {
7640         constant = isolate()->factory()->InternalizeString(
7641             Handle<String>::cast(constant));
7642       }
7643       HValue* access =
7644           BuildNamedAccess(access_type, ast_id, return_id, expr, slot, obj,
7645                            Handle<String>::cast(constant), val, false);
7646       if (access == NULL || access->IsPhi() ||
7647           HInstruction::cast(access)->IsLinked()) {
7648         *has_side_effects = false;
7649       } else {
7650         HInstruction* instr = HInstruction::cast(access);
7651         AddInstruction(instr);
7652         *has_side_effects = instr->HasObservableSideEffects();
7653       }
7654       return access;
7655     }
7656   }
7657
7658   DCHECK(!expr->IsPropertyName());
7659   HInstruction* instr = NULL;
7660
7661   SmallMapList* maps;
7662   bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, zone());
7663
7664   bool force_generic = false;
7665   if (expr->GetKeyType() == PROPERTY) {
7666     // Non-Generic accesses assume that elements are being accessed, and will
7667     // deopt for non-index keys, which the IC knows will occur.
7668     // TODO(jkummerow): Consider adding proper support for property accesses.
7669     force_generic = true;
7670     monomorphic = false;
7671   } else if (access_type == STORE &&
7672              (monomorphic || (maps != NULL && !maps->is_empty()))) {
7673     // Stores can't be mono/polymorphic if their prototype chain has dictionary
7674     // elements. However a receiver map that has dictionary elements itself
7675     // should be left to normal mono/poly behavior (the other maps may benefit
7676     // from highly optimized stores).
7677     for (int i = 0; i < maps->length(); i++) {
7678       Handle<Map> current_map = maps->at(i);
7679       if (current_map->DictionaryElementsInPrototypeChainOnly()) {
7680         force_generic = true;
7681         monomorphic = false;
7682         break;
7683       }
7684     }
7685   } else if (access_type == LOAD && !monomorphic &&
7686              (maps != NULL && !maps->is_empty())) {
7687     // Polymorphic loads have to go generic if any of the maps are strings.
7688     // If some, but not all of the maps are strings, we should go generic
7689     // because polymorphic access wants to key on ElementsKind and isn't
7690     // compatible with strings.
7691     for (int i = 0; i < maps->length(); i++) {
7692       Handle<Map> current_map = maps->at(i);
7693       if (current_map->IsStringMap()) {
7694         force_generic = true;
7695         break;
7696       }
7697     }
7698   }
7699
7700   if (monomorphic) {
7701     Handle<Map> map = maps->first();
7702     if (!CanInlineElementAccess(map)) {
7703       instr = AddInstruction(
7704           BuildKeyedGeneric(access_type, expr, slot, obj, key, val));
7705     } else {
7706       BuildCheckHeapObject(obj);
7707       instr = BuildMonomorphicElementAccess(
7708           obj, key, val, NULL, map, access_type, expr->GetStoreMode());
7709     }
7710   } else if (!force_generic && (maps != NULL && !maps->is_empty())) {
7711     return HandlePolymorphicElementAccess(expr, slot, obj, key, val, maps,
7712                                           access_type, expr->GetStoreMode(),
7713                                           has_side_effects);
7714   } else {
7715     if (access_type == STORE) {
7716       if (expr->IsAssignment() &&
7717           expr->AsAssignment()->HasNoTypeInformation()) {
7718         Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedStore,
7719                          Deoptimizer::SOFT);
7720       }
7721     } else {
7722       if (expr->AsProperty()->HasNoTypeInformation()) {
7723         Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedLoad,
7724                          Deoptimizer::SOFT);
7725       }
7726     }
7727     instr = AddInstruction(
7728         BuildKeyedGeneric(access_type, expr, slot, obj, key, val));
7729   }
7730   *has_side_effects = instr->HasObservableSideEffects();
7731   return instr;
7732 }
7733
7734
7735 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() {
7736   // Outermost function already has arguments on the stack.
7737   if (function_state()->outer() == NULL) return;
7738
7739   if (function_state()->arguments_pushed()) return;
7740
7741   // Push arguments when entering inlined function.
7742   HEnterInlined* entry = function_state()->entry();
7743   entry->set_arguments_pushed();
7744
7745   HArgumentsObject* arguments = entry->arguments_object();
7746   const ZoneList<HValue*>* arguments_values = arguments->arguments_values();
7747
7748   HInstruction* insert_after = entry;
7749   for (int i = 0; i < arguments_values->length(); i++) {
7750     HValue* argument = arguments_values->at(i);
7751     HInstruction* push_argument = New<HPushArguments>(argument);
7752     push_argument->InsertAfter(insert_after);
7753     insert_after = push_argument;
7754   }
7755
7756   HArgumentsElements* arguments_elements = New<HArgumentsElements>(true);
7757   arguments_elements->ClearFlag(HValue::kUseGVN);
7758   arguments_elements->InsertAfter(insert_after);
7759   function_state()->set_arguments_elements(arguments_elements);
7760 }
7761
7762
7763 bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) {
7764   VariableProxy* proxy = expr->obj()->AsVariableProxy();
7765   if (proxy == NULL) return false;
7766   if (!proxy->var()->IsStackAllocated()) return false;
7767   if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
7768     return false;
7769   }
7770
7771   HInstruction* result = NULL;
7772   if (expr->key()->IsPropertyName()) {
7773     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
7774     if (!String::Equals(name, isolate()->factory()->length_string())) {
7775       return false;
7776     }
7777
7778     if (function_state()->outer() == NULL) {
7779       HInstruction* elements = Add<HArgumentsElements>(false);
7780       result = New<HArgumentsLength>(elements);
7781     } else {
7782       // Number of arguments without receiver.
7783       int argument_count = environment()->
7784           arguments_environment()->parameter_count() - 1;
7785       result = New<HConstant>(argument_count);
7786     }
7787   } else {
7788     Push(graph()->GetArgumentsObject());
7789     CHECK_ALIVE_OR_RETURN(VisitForValue(expr->key()), true);
7790     HValue* key = Pop();
7791     Drop(1);  // Arguments object.
7792     if (function_state()->outer() == NULL) {
7793       HInstruction* elements = Add<HArgumentsElements>(false);
7794       HInstruction* length = Add<HArgumentsLength>(elements);
7795       HInstruction* checked_key = Add<HBoundsCheck>(key, length);
7796       result = New<HAccessArgumentsAt>(elements, length, checked_key);
7797     } else {
7798       EnsureArgumentsArePushedForAccess();
7799
7800       // Number of arguments without receiver.
7801       HInstruction* elements = function_state()->arguments_elements();
7802       int argument_count = environment()->
7803           arguments_environment()->parameter_count() - 1;
7804       HInstruction* length = Add<HConstant>(argument_count);
7805       HInstruction* checked_key = Add<HBoundsCheck>(key, length);
7806       result = New<HAccessArgumentsAt>(elements, length, checked_key);
7807     }
7808   }
7809   ast_context()->ReturnInstruction(result, expr->id());
7810   return true;
7811 }
7812
7813
7814 HValue* HOptimizedGraphBuilder::BuildNamedAccess(
7815     PropertyAccessType access, BailoutId ast_id, BailoutId return_id,
7816     Expression* expr, FeedbackVectorICSlot slot, HValue* object,
7817     Handle<String> name, HValue* value, bool is_uninitialized) {
7818   SmallMapList* maps;
7819   ComputeReceiverTypes(expr, object, &maps, zone());
7820   DCHECK(maps != NULL);
7821
7822   if (maps->length() > 0) {
7823     PropertyAccessInfo info(this, access, maps->first(), name);
7824     if (!info.CanAccessAsMonomorphic(maps)) {
7825       HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id,
7826                                         object, value, maps, name);
7827       return NULL;
7828     }
7829
7830     HValue* checked_object;
7831     // Type::Number() is only supported by polymorphic load/call handling.
7832     DCHECK(!info.IsNumberType());
7833     BuildCheckHeapObject(object);
7834     if (AreStringTypes(maps)) {
7835       checked_object =
7836           Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
7837     } else {
7838       checked_object = Add<HCheckMaps>(object, maps);
7839     }
7840     return BuildMonomorphicAccess(
7841         &info, object, checked_object, value, ast_id, return_id);
7842   }
7843
7844   return BuildNamedGeneric(access, expr, slot, object, name, value,
7845                            is_uninitialized);
7846 }
7847
7848
7849 void HOptimizedGraphBuilder::PushLoad(Property* expr,
7850                                       HValue* object,
7851                                       HValue* key) {
7852   ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
7853   Push(object);
7854   if (key != NULL) Push(key);
7855   BuildLoad(expr, expr->LoadId());
7856 }
7857
7858
7859 void HOptimizedGraphBuilder::BuildLoad(Property* expr,
7860                                        BailoutId ast_id) {
7861   HInstruction* instr = NULL;
7862   if (expr->IsStringAccess()) {
7863     HValue* index = Pop();
7864     HValue* string = Pop();
7865     HInstruction* char_code = BuildStringCharCodeAt(string, index);
7866     AddInstruction(char_code);
7867     instr = NewUncasted<HStringCharFromCode>(char_code);
7868
7869   } else if (expr->key()->IsPropertyName()) {
7870     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
7871     HValue* object = Pop();
7872
7873     HValue* value = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr,
7874                                      expr->PropertyFeedbackSlot(), object, name,
7875                                      NULL, expr->IsUninitialized());
7876     if (value == NULL) return;
7877     if (value->IsPhi()) return ast_context()->ReturnValue(value);
7878     instr = HInstruction::cast(value);
7879     if (instr->IsLinked()) return ast_context()->ReturnValue(instr);
7880
7881   } else {
7882     HValue* key = Pop();
7883     HValue* obj = Pop();
7884
7885     bool has_side_effects = false;
7886     HValue* load = HandleKeyedElementAccess(
7887         obj, key, NULL, expr, expr->PropertyFeedbackSlot(), ast_id,
7888         expr->LoadId(), LOAD, &has_side_effects);
7889     if (has_side_effects) {
7890       if (ast_context()->IsEffect()) {
7891         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
7892       } else {
7893         Push(load);
7894         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
7895         Drop(1);
7896       }
7897     }
7898     if (load == NULL) return;
7899     return ast_context()->ReturnValue(load);
7900   }
7901   return ast_context()->ReturnInstruction(instr, ast_id);
7902 }
7903
7904
7905 void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
7906   DCHECK(!HasStackOverflow());
7907   DCHECK(current_block() != NULL);
7908   DCHECK(current_block()->HasPredecessor());
7909
7910   if (TryArgumentsAccess(expr)) return;
7911
7912   CHECK_ALIVE(VisitForValue(expr->obj()));
7913   if (!expr->key()->IsPropertyName() || expr->IsStringAccess()) {
7914     CHECK_ALIVE(VisitForValue(expr->key()));
7915   }
7916
7917   BuildLoad(expr, expr->id());
7918 }
7919
7920
7921 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant) {
7922   HCheckMaps* check = Add<HCheckMaps>(
7923       Add<HConstant>(constant), handle(constant->map()));
7924   check->ClearDependsOnFlag(kElementsKind);
7925   return check;
7926 }
7927
7928
7929 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
7930                                                      Handle<JSObject> holder) {
7931   PrototypeIterator iter(isolate(), prototype,
7932                          PrototypeIterator::START_AT_RECEIVER);
7933   while (holder.is_null() ||
7934          !PrototypeIterator::GetCurrent(iter).is_identical_to(holder)) {
7935     BuildConstantMapCheck(PrototypeIterator::GetCurrent<JSObject>(iter));
7936     iter.Advance();
7937     if (iter.IsAtEnd()) {
7938       return NULL;
7939     }
7940   }
7941   return BuildConstantMapCheck(PrototypeIterator::GetCurrent<JSObject>(iter));
7942 }
7943
7944
7945 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
7946                                                    Handle<Map> receiver_map) {
7947   if (!holder.is_null()) {
7948     Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
7949     BuildCheckPrototypeMaps(prototype, holder);
7950   }
7951 }
7952
7953
7954 HInstruction* HOptimizedGraphBuilder::NewPlainFunctionCall(HValue* fun,
7955                                                            int argument_count) {
7956   return New<HCallJSFunction>(fun, argument_count);
7957 }
7958
7959
7960 HInstruction* HOptimizedGraphBuilder::NewArgumentAdaptorCall(
7961     HValue* fun, HValue* context,
7962     int argument_count, HValue* expected_param_count) {
7963   ArgumentAdaptorDescriptor descriptor(isolate());
7964   HValue* arity = Add<HConstant>(argument_count - 1);
7965
7966   HValue* op_vals[] = { context, fun, arity, expected_param_count };
7967
7968   Handle<Code> adaptor =
7969       isolate()->builtins()->ArgumentsAdaptorTrampoline();
7970   HConstant* adaptor_value = Add<HConstant>(adaptor);
7971
7972   return New<HCallWithDescriptor>(adaptor_value, argument_count, descriptor,
7973                                   Vector<HValue*>(op_vals, arraysize(op_vals)));
7974 }
7975
7976
7977 HInstruction* HOptimizedGraphBuilder::BuildCallConstantFunction(
7978     Handle<JSFunction> jsfun, int argument_count) {
7979   HValue* target = Add<HConstant>(jsfun);
7980   // For constant functions, we try to avoid calling the
7981   // argument adaptor and instead call the function directly
7982   int formal_parameter_count =
7983       jsfun->shared()->internal_formal_parameter_count();
7984   bool dont_adapt_arguments =
7985       (formal_parameter_count ==
7986        SharedFunctionInfo::kDontAdaptArgumentsSentinel);
7987   int arity = argument_count - 1;
7988   bool can_invoke_directly =
7989       dont_adapt_arguments || formal_parameter_count == arity;
7990   if (can_invoke_directly) {
7991     if (jsfun.is_identical_to(current_info()->closure())) {
7992       graph()->MarkRecursive();
7993     }
7994     return NewPlainFunctionCall(target, argument_count);
7995   } else {
7996     HValue* param_count_value = Add<HConstant>(formal_parameter_count);
7997     HValue* context = Add<HLoadNamedField>(
7998         target, nullptr, HObjectAccess::ForFunctionContextPointer());
7999     return NewArgumentAdaptorCall(target, context,
8000         argument_count, param_count_value);
8001   }
8002   UNREACHABLE();
8003   return NULL;
8004 }
8005
8006
8007 class FunctionSorter {
8008  public:
8009   explicit FunctionSorter(int index = 0, int ticks = 0, int size = 0)
8010       : index_(index), ticks_(ticks), size_(size) {}
8011
8012   int index() const { return index_; }
8013   int ticks() const { return ticks_; }
8014   int size() const { return size_; }
8015
8016  private:
8017   int index_;
8018   int ticks_;
8019   int size_;
8020 };
8021
8022
8023 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) {
8024   int diff = lhs.ticks() - rhs.ticks();
8025   if (diff != 0) return diff > 0;
8026   return lhs.size() < rhs.size();
8027 }
8028
8029
8030 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
8031                                                         HValue* receiver,
8032                                                         SmallMapList* maps,
8033                                                         Handle<String> name) {
8034   int argument_count = expr->arguments()->length() + 1;  // Includes receiver.
8035   FunctionSorter order[kMaxCallPolymorphism];
8036
8037   bool handle_smi = false;
8038   bool handled_string = false;
8039   int ordered_functions = 0;
8040
8041   int i;
8042   for (i = 0; i < maps->length() && ordered_functions < kMaxCallPolymorphism;
8043        ++i) {
8044     PropertyAccessInfo info(this, LOAD, maps->at(i), name);
8045     if (info.CanAccessMonomorphic() && info.IsDataConstant() &&
8046         info.constant()->IsJSFunction()) {
8047       if (info.IsStringType()) {
8048         if (handled_string) continue;
8049         handled_string = true;
8050       }
8051       Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
8052       if (info.IsNumberType()) {
8053         handle_smi = true;
8054       }
8055       expr->set_target(target);
8056       order[ordered_functions++] = FunctionSorter(
8057           i, target->shared()->profiler_ticks(), InliningAstSize(target));
8058     }
8059   }
8060
8061   std::sort(order, order + ordered_functions);
8062
8063   if (i < maps->length()) {
8064     maps->Clear();
8065     ordered_functions = -1;
8066   }
8067
8068   HBasicBlock* number_block = NULL;
8069   HBasicBlock* join = NULL;
8070   handled_string = false;
8071   int count = 0;
8072
8073   for (int fn = 0; fn < ordered_functions; ++fn) {
8074     int i = order[fn].index();
8075     PropertyAccessInfo info(this, LOAD, maps->at(i), name);
8076     if (info.IsStringType()) {
8077       if (handled_string) continue;
8078       handled_string = true;
8079     }
8080     // Reloads the target.
8081     info.CanAccessMonomorphic();
8082     Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
8083
8084     expr->set_target(target);
8085     if (count == 0) {
8086       // Only needed once.
8087       join = graph()->CreateBasicBlock();
8088       if (handle_smi) {
8089         HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
8090         HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
8091         number_block = graph()->CreateBasicBlock();
8092         FinishCurrentBlock(New<HIsSmiAndBranch>(
8093                 receiver, empty_smi_block, not_smi_block));
8094         GotoNoSimulate(empty_smi_block, number_block);
8095         set_current_block(not_smi_block);
8096       } else {
8097         BuildCheckHeapObject(receiver);
8098       }
8099     }
8100     ++count;
8101     HBasicBlock* if_true = graph()->CreateBasicBlock();
8102     HBasicBlock* if_false = graph()->CreateBasicBlock();
8103     HUnaryControlInstruction* compare;
8104
8105     Handle<Map> map = info.map();
8106     if (info.IsNumberType()) {
8107       Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
8108       compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
8109     } else if (info.IsStringType()) {
8110       compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
8111     } else {
8112       compare = New<HCompareMap>(receiver, map, if_true, if_false);
8113     }
8114     FinishCurrentBlock(compare);
8115
8116     if (info.IsNumberType()) {
8117       GotoNoSimulate(if_true, number_block);
8118       if_true = number_block;
8119     }
8120
8121     set_current_block(if_true);
8122
8123     AddCheckPrototypeMaps(info.holder(), map);
8124
8125     HValue* function = Add<HConstant>(expr->target());
8126     environment()->SetExpressionStackAt(0, function);
8127     Push(receiver);
8128     CHECK_ALIVE(VisitExpressions(expr->arguments()));
8129     bool needs_wrapping = info.NeedsWrappingFor(target);
8130     bool try_inline = FLAG_polymorphic_inlining && !needs_wrapping;
8131     if (FLAG_trace_inlining && try_inline) {
8132       Handle<JSFunction> caller = current_info()->closure();
8133       base::SmartArrayPointer<char> caller_name =
8134           caller->shared()->DebugName()->ToCString();
8135       PrintF("Trying to inline the polymorphic call to %s from %s\n",
8136              name->ToCString().get(),
8137              caller_name.get());
8138     }
8139     if (try_inline && TryInlineCall(expr)) {
8140       // Trying to inline will signal that we should bailout from the
8141       // entire compilation by setting stack overflow on the visitor.
8142       if (HasStackOverflow()) return;
8143     } else {
8144       // Since HWrapReceiver currently cannot actually wrap numbers and strings,
8145       // use the regular CallFunctionStub for method calls to wrap the receiver.
8146       // TODO(verwaest): Support creation of value wrappers directly in
8147       // HWrapReceiver.
8148       HInstruction* call = needs_wrapping
8149           ? NewUncasted<HCallFunction>(
8150               function, argument_count, WRAP_AND_CALL)
8151           : BuildCallConstantFunction(target, argument_count);
8152       PushArgumentsFromEnvironment(argument_count);
8153       AddInstruction(call);
8154       Drop(1);  // Drop the function.
8155       if (!ast_context()->IsEffect()) Push(call);
8156     }
8157
8158     if (current_block() != NULL) Goto(join);
8159     set_current_block(if_false);
8160   }
8161
8162   // Finish up.  Unconditionally deoptimize if we've handled all the maps we
8163   // know about and do not want to handle ones we've never seen.  Otherwise
8164   // use a generic IC.
8165   if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) {
8166     FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall);
8167   } else {
8168     Property* prop = expr->expression()->AsProperty();
8169     HInstruction* function =
8170         BuildNamedGeneric(LOAD, prop, prop->PropertyFeedbackSlot(), receiver,
8171                           name, NULL, prop->IsUninitialized());
8172     AddInstruction(function);
8173     Push(function);
8174     AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
8175
8176     environment()->SetExpressionStackAt(1, function);
8177     environment()->SetExpressionStackAt(0, receiver);
8178     CHECK_ALIVE(VisitExpressions(expr->arguments()));
8179
8180     CallFunctionFlags flags = receiver->type().IsJSObject()
8181         ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD;
8182     HInstruction* call = New<HCallFunction>(
8183         function, argument_count, flags);
8184
8185     PushArgumentsFromEnvironment(argument_count);
8186
8187     Drop(1);  // Function.
8188
8189     if (join != NULL) {
8190       AddInstruction(call);
8191       if (!ast_context()->IsEffect()) Push(call);
8192       Goto(join);
8193     } else {
8194       return ast_context()->ReturnInstruction(call, expr->id());
8195     }
8196   }
8197
8198   // We assume that control flow is always live after an expression.  So
8199   // even without predecessors to the join block, we set it as the exit
8200   // block and continue by adding instructions there.
8201   DCHECK(join != NULL);
8202   if (join->HasPredecessor()) {
8203     set_current_block(join);
8204     join->SetJoinId(expr->id());
8205     if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
8206   } else {
8207     set_current_block(NULL);
8208   }
8209 }
8210
8211
8212 void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target,
8213                                          Handle<JSFunction> caller,
8214                                          const char* reason) {
8215   if (FLAG_trace_inlining) {
8216     base::SmartArrayPointer<char> target_name =
8217         target->shared()->DebugName()->ToCString();
8218     base::SmartArrayPointer<char> caller_name =
8219         caller->shared()->DebugName()->ToCString();
8220     if (reason == NULL) {
8221       PrintF("Inlined %s called from %s.\n", target_name.get(),
8222              caller_name.get());
8223     } else {
8224       PrintF("Did not inline %s called from %s (%s).\n",
8225              target_name.get(), caller_name.get(), reason);
8226     }
8227   }
8228 }
8229
8230
8231 static const int kNotInlinable = 1000000000;
8232
8233
8234 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) {
8235   if (!FLAG_use_inlining) return kNotInlinable;
8236
8237   // Precondition: call is monomorphic and we have found a target with the
8238   // appropriate arity.
8239   Handle<JSFunction> caller = current_info()->closure();
8240   Handle<SharedFunctionInfo> target_shared(target->shared());
8241
8242   // Always inline functions that force inlining.
8243   if (target_shared->force_inline()) {
8244     return 0;
8245   }
8246   if (target->IsBuiltin()) {
8247     return kNotInlinable;
8248   }
8249
8250   if (target_shared->IsApiFunction()) {
8251     TraceInline(target, caller, "target is api function");
8252     return kNotInlinable;
8253   }
8254
8255   // Do a quick check on source code length to avoid parsing large
8256   // inlining candidates.
8257   if (target_shared->SourceSize() >
8258       Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) {
8259     TraceInline(target, caller, "target text too big");
8260     return kNotInlinable;
8261   }
8262
8263   // Target must be inlineable.
8264   if (!target_shared->IsInlineable()) {
8265     TraceInline(target, caller, "target not inlineable");
8266     return kNotInlinable;
8267   }
8268   if (target_shared->disable_optimization_reason() != kNoReason) {
8269     TraceInline(target, caller, "target contains unsupported syntax [early]");
8270     return kNotInlinable;
8271   }
8272
8273   int nodes_added = target_shared->ast_node_count();
8274   return nodes_added;
8275 }
8276
8277
8278 bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
8279                                        int arguments_count,
8280                                        HValue* implicit_return_value,
8281                                        BailoutId ast_id, BailoutId return_id,
8282                                        InliningKind inlining_kind) {
8283   if (target->context()->native_context() !=
8284       top_info()->closure()->context()->native_context()) {
8285     return false;
8286   }
8287   int nodes_added = InliningAstSize(target);
8288   if (nodes_added == kNotInlinable) return false;
8289
8290   Handle<JSFunction> caller = current_info()->closure();
8291
8292   if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
8293     TraceInline(target, caller, "target AST is too large [early]");
8294     return false;
8295   }
8296
8297   // Don't inline deeper than the maximum number of inlining levels.
8298   HEnvironment* env = environment();
8299   int current_level = 1;
8300   while (env->outer() != NULL) {
8301     if (current_level == FLAG_max_inlining_levels) {
8302       TraceInline(target, caller, "inline depth limit reached");
8303       return false;
8304     }
8305     if (env->outer()->frame_type() == JS_FUNCTION) {
8306       current_level++;
8307     }
8308     env = env->outer();
8309   }
8310
8311   // Don't inline recursive functions.
8312   for (FunctionState* state = function_state();
8313        state != NULL;
8314        state = state->outer()) {
8315     if (*state->compilation_info()->closure() == *target) {
8316       TraceInline(target, caller, "target is recursive");
8317       return false;
8318     }
8319   }
8320
8321   // We don't want to add more than a certain number of nodes from inlining.
8322   // Always inline small methods (<= 10 nodes).
8323   if (inlined_count_ > Min(FLAG_max_inlined_nodes_cumulative,
8324                            kUnlimitedMaxInlinedNodesCumulative)) {
8325     TraceInline(target, caller, "cumulative AST node limit reached");
8326     return false;
8327   }
8328
8329   // Parse and allocate variables.
8330   // Use the same AstValueFactory for creating strings in the sub-compilation
8331   // step, but don't transfer ownership to target_info.
8332   ParseInfo parse_info(zone(), target);
8333   parse_info.set_ast_value_factory(
8334       top_info()->parse_info()->ast_value_factory());
8335   parse_info.set_ast_value_factory_owned(false);
8336
8337   CompilationInfo target_info(&parse_info);
8338   Handle<SharedFunctionInfo> target_shared(target->shared());
8339   if (target_shared->HasDebugInfo()) {
8340     TraceInline(target, caller, "target is being debugged");
8341     return false;
8342   }
8343   if (!Compiler::ParseAndAnalyze(target_info.parse_info())) {
8344     if (target_info.isolate()->has_pending_exception()) {
8345       // Parse or scope error, never optimize this function.
8346       SetStackOverflow();
8347       target_shared->DisableOptimization(kParseScopeError);
8348     }
8349     TraceInline(target, caller, "parse failure");
8350     return false;
8351   }
8352
8353   if (target_info.scope()->num_heap_slots() > 0) {
8354     TraceInline(target, caller, "target has context-allocated variables");
8355     return false;
8356   }
8357   FunctionLiteral* function = target_info.literal();
8358
8359   // The following conditions must be checked again after re-parsing, because
8360   // earlier the information might not have been complete due to lazy parsing.
8361   nodes_added = function->ast_node_count();
8362   if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
8363     TraceInline(target, caller, "target AST is too large [late]");
8364     return false;
8365   }
8366   if (function->dont_optimize()) {
8367     TraceInline(target, caller, "target contains unsupported syntax [late]");
8368     return false;
8369   }
8370
8371   // If the function uses the arguments object check that inlining of functions
8372   // with arguments object is enabled and the arguments-variable is
8373   // stack allocated.
8374   if (function->scope()->arguments() != NULL) {
8375     if (!FLAG_inline_arguments) {
8376       TraceInline(target, caller, "target uses arguments object");
8377       return false;
8378     }
8379   }
8380
8381   // All declarations must be inlineable.
8382   ZoneList<Declaration*>* decls = target_info.scope()->declarations();
8383   int decl_count = decls->length();
8384   for (int i = 0; i < decl_count; ++i) {
8385     if (!decls->at(i)->IsInlineable()) {
8386       TraceInline(target, caller, "target has non-trivial declaration");
8387       return false;
8388     }
8389   }
8390
8391   // Generate the deoptimization data for the unoptimized version of
8392   // the target function if we don't already have it.
8393   if (!Compiler::EnsureDeoptimizationSupport(&target_info)) {
8394     TraceInline(target, caller, "could not generate deoptimization info");
8395     return false;
8396   }
8397
8398   // In strong mode it is an error to call a function with too few arguments.
8399   // In that case do not inline because then the arity check would be skipped.
8400   if (is_strong(function->language_mode()) &&
8401       arguments_count < function->parameter_count()) {
8402     TraceInline(target, caller,
8403                 "too few arguments passed to a strong function");
8404     return false;
8405   }
8406
8407   // ----------------------------------------------------------------
8408   // After this point, we've made a decision to inline this function (so
8409   // TryInline should always return true).
8410
8411   // Type-check the inlined function.
8412   DCHECK(target_shared->has_deoptimization_support());
8413   AstTyper(target_info.isolate(), target_info.zone(), target_info.closure(),
8414            target_info.scope(), target_info.osr_ast_id(), target_info.literal())
8415       .Run();
8416
8417   int inlining_id = 0;
8418   if (top_info()->is_tracking_positions()) {
8419     inlining_id = top_info()->TraceInlinedFunction(
8420         target_shared, source_position(), function_state()->inlining_id());
8421   }
8422
8423   // Save the pending call context. Set up new one for the inlined function.
8424   // The function state is new-allocated because we need to delete it
8425   // in two different places.
8426   FunctionState* target_state =
8427       new FunctionState(this, &target_info, inlining_kind, inlining_id);
8428
8429   HConstant* undefined = graph()->GetConstantUndefined();
8430
8431   HEnvironment* inner_env =
8432       environment()->CopyForInlining(target,
8433                                      arguments_count,
8434                                      function,
8435                                      undefined,
8436                                      function_state()->inlining_kind());
8437
8438   HConstant* context = Add<HConstant>(Handle<Context>(target->context()));
8439   inner_env->BindContext(context);
8440
8441   // Create a dematerialized arguments object for the function, also copy the
8442   // current arguments values to use them for materialization.
8443   HEnvironment* arguments_env = inner_env->arguments_environment();
8444   int parameter_count = arguments_env->parameter_count();
8445   HArgumentsObject* arguments_object = Add<HArgumentsObject>(parameter_count);
8446   for (int i = 0; i < parameter_count; i++) {
8447     arguments_object->AddArgument(arguments_env->Lookup(i), zone());
8448   }
8449
8450   // If the function uses arguments object then bind bind one.
8451   if (function->scope()->arguments() != NULL) {
8452     DCHECK(function->scope()->arguments()->IsStackAllocated());
8453     inner_env->Bind(function->scope()->arguments(), arguments_object);
8454   }
8455
8456   // Capture the state before invoking the inlined function for deopt in the
8457   // inlined function. This simulate has no bailout-id since it's not directly
8458   // reachable for deopt, and is only used to capture the state. If the simulate
8459   // becomes reachable by merging, the ast id of the simulate merged into it is
8460   // adopted.
8461   Add<HSimulate>(BailoutId::None());
8462
8463   current_block()->UpdateEnvironment(inner_env);
8464   Scope* saved_scope = scope();
8465   set_scope(target_info.scope());
8466   HEnterInlined* enter_inlined =
8467       Add<HEnterInlined>(return_id, target, context, arguments_count, function,
8468                          function_state()->inlining_kind(),
8469                          function->scope()->arguments(), arguments_object);
8470   if (top_info()->is_tracking_positions()) {
8471     enter_inlined->set_inlining_id(inlining_id);
8472   }
8473   function_state()->set_entry(enter_inlined);
8474
8475   VisitDeclarations(target_info.scope()->declarations());
8476   VisitStatements(function->body());
8477   set_scope(saved_scope);
8478   if (HasStackOverflow()) {
8479     // Bail out if the inline function did, as we cannot residualize a call
8480     // instead, but do not disable optimization for the outer function.
8481     TraceInline(target, caller, "inline graph construction failed");
8482     target_shared->DisableOptimization(kInliningBailedOut);
8483     current_info()->RetryOptimization(kInliningBailedOut);
8484     delete target_state;
8485     return true;
8486   }
8487
8488   // Update inlined nodes count.
8489   inlined_count_ += nodes_added;
8490
8491   Handle<Code> unoptimized_code(target_shared->code());
8492   DCHECK(unoptimized_code->kind() == Code::FUNCTION);
8493   Handle<TypeFeedbackInfo> type_info(
8494       TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
8495   graph()->update_type_change_checksum(type_info->own_type_change_checksum());
8496
8497   TraceInline(target, caller, NULL);
8498
8499   if (current_block() != NULL) {
8500     FunctionState* state = function_state();
8501     if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
8502       // Falling off the end of an inlined construct call. In a test context the
8503       // return value will always evaluate to true, in a value context the
8504       // return value is the newly allocated receiver.
8505       if (call_context()->IsTest()) {
8506         Goto(inlined_test_context()->if_true(), state);
8507       } else if (call_context()->IsEffect()) {
8508         Goto(function_return(), state);
8509       } else {
8510         DCHECK(call_context()->IsValue());
8511         AddLeaveInlined(implicit_return_value, state);
8512       }
8513     } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
8514       // Falling off the end of an inlined setter call. The returned value is
8515       // never used, the value of an assignment is always the value of the RHS
8516       // of the assignment.
8517       if (call_context()->IsTest()) {
8518         inlined_test_context()->ReturnValue(implicit_return_value);
8519       } else if (call_context()->IsEffect()) {
8520         Goto(function_return(), state);
8521       } else {
8522         DCHECK(call_context()->IsValue());
8523         AddLeaveInlined(implicit_return_value, state);
8524       }
8525     } else {
8526       // Falling off the end of a normal inlined function. This basically means
8527       // returning undefined.
8528       if (call_context()->IsTest()) {
8529         Goto(inlined_test_context()->if_false(), state);
8530       } else if (call_context()->IsEffect()) {
8531         Goto(function_return(), state);
8532       } else {
8533         DCHECK(call_context()->IsValue());
8534         AddLeaveInlined(undefined, state);
8535       }
8536     }
8537   }
8538
8539   // Fix up the function exits.
8540   if (inlined_test_context() != NULL) {
8541     HBasicBlock* if_true = inlined_test_context()->if_true();
8542     HBasicBlock* if_false = inlined_test_context()->if_false();
8543
8544     HEnterInlined* entry = function_state()->entry();
8545
8546     // Pop the return test context from the expression context stack.
8547     DCHECK(ast_context() == inlined_test_context());
8548     ClearInlinedTestContext();
8549     delete target_state;
8550
8551     // Forward to the real test context.
8552     if (if_true->HasPredecessor()) {
8553       entry->RegisterReturnTarget(if_true, zone());
8554       if_true->SetJoinId(ast_id);
8555       HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
8556       Goto(if_true, true_target, function_state());
8557     }
8558     if (if_false->HasPredecessor()) {
8559       entry->RegisterReturnTarget(if_false, zone());
8560       if_false->SetJoinId(ast_id);
8561       HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
8562       Goto(if_false, false_target, function_state());
8563     }
8564     set_current_block(NULL);
8565     return true;
8566
8567   } else if (function_return()->HasPredecessor()) {
8568     function_state()->entry()->RegisterReturnTarget(function_return(), zone());
8569     function_return()->SetJoinId(ast_id);
8570     set_current_block(function_return());
8571   } else {
8572     set_current_block(NULL);
8573   }
8574   delete target_state;
8575   return true;
8576 }
8577
8578
8579 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) {
8580   return TryInline(expr->target(), expr->arguments()->length(), NULL,
8581                    expr->id(), expr->ReturnId(), NORMAL_RETURN);
8582 }
8583
8584
8585 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr,
8586                                                 HValue* implicit_return_value) {
8587   return TryInline(expr->target(), expr->arguments()->length(),
8588                    implicit_return_value, expr->id(), expr->ReturnId(),
8589                    CONSTRUCT_CALL_RETURN);
8590 }
8591
8592
8593 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
8594                                              Handle<Map> receiver_map,
8595                                              BailoutId ast_id,
8596                                              BailoutId return_id) {
8597   if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true;
8598   return TryInline(getter, 0, NULL, ast_id, return_id, GETTER_CALL_RETURN);
8599 }
8600
8601
8602 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
8603                                              Handle<Map> receiver_map,
8604                                              BailoutId id,
8605                                              BailoutId assignment_id,
8606                                              HValue* implicit_return_value) {
8607   if (TryInlineApiSetter(setter, receiver_map, id)) return true;
8608   return TryInline(setter, 1, implicit_return_value, id, assignment_id,
8609                    SETTER_CALL_RETURN);
8610 }
8611
8612
8613 bool HOptimizedGraphBuilder::TryInlineIndirectCall(Handle<JSFunction> function,
8614                                                    Call* expr,
8615                                                    int arguments_count) {
8616   return TryInline(function, arguments_count, NULL, expr->id(),
8617                    expr->ReturnId(), NORMAL_RETURN);
8618 }
8619
8620
8621 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) {
8622   if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
8623   BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
8624   switch (id) {
8625     case kMathExp:
8626       if (!FLAG_fast_math) break;
8627       // Fall through if FLAG_fast_math.
8628     case kMathRound:
8629     case kMathFround:
8630     case kMathFloor:
8631     case kMathAbs:
8632     case kMathSqrt:
8633     case kMathLog:
8634     case kMathClz32:
8635       if (expr->arguments()->length() == 1) {
8636         HValue* argument = Pop();
8637         Drop(2);  // Receiver and function.
8638         HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
8639         ast_context()->ReturnInstruction(op, expr->id());
8640         return true;
8641       }
8642       break;
8643     case kMathImul:
8644       if (expr->arguments()->length() == 2) {
8645         HValue* right = Pop();
8646         HValue* left = Pop();
8647         Drop(2);  // Receiver and function.
8648         HInstruction* op =
8649             HMul::NewImul(isolate(), zone(), context(), left, right);
8650         ast_context()->ReturnInstruction(op, expr->id());
8651         return true;
8652       }
8653       break;
8654     default:
8655       // Not supported for inlining yet.
8656       break;
8657   }
8658   return false;
8659 }
8660
8661
8662 // static
8663 bool HOptimizedGraphBuilder::IsReadOnlyLengthDescriptor(
8664     Handle<Map> jsarray_map) {
8665   DCHECK(!jsarray_map->is_dictionary_map());
8666   Isolate* isolate = jsarray_map->GetIsolate();
8667   Handle<Name> length_string = isolate->factory()->length_string();
8668   DescriptorArray* descriptors = jsarray_map->instance_descriptors();
8669   int number = descriptors->SearchWithCache(*length_string, *jsarray_map);
8670   DCHECK_NE(DescriptorArray::kNotFound, number);
8671   return descriptors->GetDetails(number).IsReadOnly();
8672 }
8673
8674
8675 // static
8676 bool HOptimizedGraphBuilder::CanInlineArrayResizeOperation(
8677     Handle<Map> receiver_map) {
8678   return !receiver_map.is_null() &&
8679          receiver_map->instance_type() == JS_ARRAY_TYPE &&
8680          IsFastElementsKind(receiver_map->elements_kind()) &&
8681          !receiver_map->is_dictionary_map() && !receiver_map->is_observed() &&
8682          receiver_map->is_extensible() &&
8683          (!receiver_map->is_prototype_map() || receiver_map->is_stable()) &&
8684          !IsReadOnlyLengthDescriptor(receiver_map);
8685 }
8686
8687
8688 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
8689     Call* expr, Handle<JSFunction> function, Handle<Map> receiver_map,
8690     int args_count_no_receiver) {
8691   if (!function->shared()->HasBuiltinFunctionId()) return false;
8692   BuiltinFunctionId id = function->shared()->builtin_function_id();
8693   int argument_count = args_count_no_receiver + 1;  // Plus receiver.
8694
8695   if (receiver_map.is_null()) {
8696     HValue* receiver = environment()->ExpressionStackAt(args_count_no_receiver);
8697     if (receiver->IsConstant() &&
8698         HConstant::cast(receiver)->handle(isolate())->IsHeapObject()) {
8699       receiver_map =
8700           handle(Handle<HeapObject>::cast(
8701                      HConstant::cast(receiver)->handle(isolate()))->map());
8702     }
8703   }
8704   // Try to inline calls like Math.* as operations in the calling function.
8705   switch (id) {
8706     case kStringCharCodeAt:
8707     case kStringCharAt:
8708       if (argument_count == 2) {
8709         HValue* index = Pop();
8710         HValue* string = Pop();
8711         Drop(1);  // Function.
8712         HInstruction* char_code =
8713             BuildStringCharCodeAt(string, index);
8714         if (id == kStringCharCodeAt) {
8715           ast_context()->ReturnInstruction(char_code, expr->id());
8716           return true;
8717         }
8718         AddInstruction(char_code);
8719         HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
8720         ast_context()->ReturnInstruction(result, expr->id());
8721         return true;
8722       }
8723       break;
8724     case kStringFromCharCode:
8725       if (argument_count == 2) {
8726         HValue* argument = Pop();
8727         Drop(2);  // Receiver and function.
8728         HInstruction* result = NewUncasted<HStringCharFromCode>(argument);
8729         ast_context()->ReturnInstruction(result, expr->id());
8730         return true;
8731       }
8732       break;
8733     case kMathExp:
8734       if (!FLAG_fast_math) break;
8735       // Fall through if FLAG_fast_math.
8736     case kMathRound:
8737     case kMathFround:
8738     case kMathFloor:
8739     case kMathAbs:
8740     case kMathSqrt:
8741     case kMathLog:
8742     case kMathClz32:
8743       if (argument_count == 2) {
8744         HValue* argument = Pop();
8745         Drop(2);  // Receiver and function.
8746         HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
8747         ast_context()->ReturnInstruction(op, expr->id());
8748         return true;
8749       }
8750       break;
8751     case kMathPow:
8752       if (argument_count == 3) {
8753         HValue* right = Pop();
8754         HValue* left = Pop();
8755         Drop(2);  // Receiver and function.
8756         HInstruction* result = NULL;
8757         // Use sqrt() if exponent is 0.5 or -0.5.
8758         if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
8759           double exponent = HConstant::cast(right)->DoubleValue();
8760           if (exponent == 0.5) {
8761             result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf);
8762           } else if (exponent == -0.5) {
8763             HValue* one = graph()->GetConstant1();
8764             HInstruction* sqrt = AddUncasted<HUnaryMathOperation>(
8765                 left, kMathPowHalf);
8766             // MathPowHalf doesn't have side effects so there's no need for
8767             // an environment simulation here.
8768             DCHECK(!sqrt->HasObservableSideEffects());
8769             result = NewUncasted<HDiv>(one, sqrt);
8770           } else if (exponent == 2.0) {
8771             result = NewUncasted<HMul>(left, left);
8772           }
8773         }
8774
8775         if (result == NULL) {
8776           result = NewUncasted<HPower>(left, right);
8777         }
8778         ast_context()->ReturnInstruction(result, expr->id());
8779         return true;
8780       }
8781       break;
8782     case kMathMax:
8783     case kMathMin:
8784       if (argument_count == 3) {
8785         HValue* right = Pop();
8786         HValue* left = Pop();
8787         Drop(2);  // Receiver and function.
8788         HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
8789                                                      : HMathMinMax::kMathMax;
8790         HInstruction* result = NewUncasted<HMathMinMax>(left, right, op);
8791         ast_context()->ReturnInstruction(result, expr->id());
8792         return true;
8793       }
8794       break;
8795     case kMathImul:
8796       if (argument_count == 3) {
8797         HValue* right = Pop();
8798         HValue* left = Pop();
8799         Drop(2);  // Receiver and function.
8800         HInstruction* result =
8801             HMul::NewImul(isolate(), zone(), context(), left, right);
8802         ast_context()->ReturnInstruction(result, expr->id());
8803         return true;
8804       }
8805       break;
8806     case kArrayPop: {
8807       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
8808       ElementsKind elements_kind = receiver_map->elements_kind();
8809
8810       Drop(args_count_no_receiver);
8811       HValue* result;
8812       HValue* reduced_length;
8813       HValue* receiver = Pop();
8814
8815       HValue* checked_object = AddCheckMap(receiver, receiver_map);
8816       HValue* length =
8817           Add<HLoadNamedField>(checked_object, nullptr,
8818                                HObjectAccess::ForArrayLength(elements_kind));
8819
8820       Drop(1);  // Function.
8821
8822       { NoObservableSideEffectsScope scope(this);
8823         IfBuilder length_checker(this);
8824
8825         HValue* bounds_check = length_checker.If<HCompareNumericAndBranch>(
8826             length, graph()->GetConstant0(), Token::EQ);
8827         length_checker.Then();
8828
8829         if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
8830
8831         length_checker.Else();
8832         HValue* elements = AddLoadElements(checked_object);
8833         // Ensure that we aren't popping from a copy-on-write array.
8834         if (IsFastSmiOrObjectElementsKind(elements_kind)) {
8835           elements = BuildCopyElementsOnWrite(checked_object, elements,
8836                                               elements_kind, length);
8837         }
8838         reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1());
8839         result = AddElementAccess(elements, reduced_length, NULL,
8840                                   bounds_check, elements_kind, LOAD);
8841         HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
8842                            ? graph()->GetConstantHole()
8843                            : Add<HConstant>(HConstant::kHoleNaN);
8844         if (IsFastSmiOrObjectElementsKind(elements_kind)) {
8845           elements_kind = FAST_HOLEY_ELEMENTS;
8846         }
8847         AddElementAccess(
8848             elements, reduced_length, hole, bounds_check, elements_kind, STORE);
8849         Add<HStoreNamedField>(
8850             checked_object, HObjectAccess::ForArrayLength(elements_kind),
8851             reduced_length, STORE_TO_INITIALIZED_ENTRY);
8852
8853         if (!ast_context()->IsEffect()) Push(result);
8854
8855         length_checker.End();
8856       }
8857       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
8858       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8859       if (!ast_context()->IsEffect()) Drop(1);
8860
8861       ast_context()->ReturnValue(result);
8862       return true;
8863     }
8864     case kArrayPush: {
8865       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
8866       ElementsKind elements_kind = receiver_map->elements_kind();
8867
8868       // If there may be elements accessors in the prototype chain, the fast
8869       // inlined version can't be used.
8870       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
8871       // If there currently can be no elements accessors on the prototype chain,
8872       // it doesn't mean that there won't be any later. Install a full prototype
8873       // chain check to trap element accessors being installed on the prototype
8874       // chain, which would cause elements to go to dictionary mode and result
8875       // in a map change.
8876       Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
8877       BuildCheckPrototypeMaps(prototype, Handle<JSObject>());
8878
8879       // Protect against adding elements to the Array prototype, which needs to
8880       // route through appropriate bottlenecks.
8881       if (isolate()->IsFastArrayConstructorPrototypeChainIntact() &&
8882           !prototype->IsJSArray()) {
8883         return false;
8884       }
8885
8886       const int argc = args_count_no_receiver;
8887       if (argc != 1) return false;
8888
8889       HValue* value_to_push = Pop();
8890       HValue* array = Pop();
8891       Drop(1);  // Drop function.
8892
8893       HInstruction* new_size = NULL;
8894       HValue* length = NULL;
8895
8896       {
8897         NoObservableSideEffectsScope scope(this);
8898
8899         length = Add<HLoadNamedField>(
8900             array, nullptr, HObjectAccess::ForArrayLength(elements_kind));
8901
8902         new_size = AddUncasted<HAdd>(length, graph()->GetConstant1());
8903
8904         bool is_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
8905         HValue* checked_array = Add<HCheckMaps>(array, receiver_map);
8906         BuildUncheckedMonomorphicElementAccess(
8907             checked_array, length, value_to_push, is_array, elements_kind,
8908             STORE, NEVER_RETURN_HOLE, STORE_AND_GROW_NO_TRANSITION);
8909
8910         if (!ast_context()->IsEffect()) Push(new_size);
8911         Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
8912         if (!ast_context()->IsEffect()) Drop(1);
8913       }
8914
8915       ast_context()->ReturnValue(new_size);
8916       return true;
8917     }
8918     case kArrayShift: {
8919       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
8920       ElementsKind kind = receiver_map->elements_kind();
8921
8922       // If there may be elements accessors in the prototype chain, the fast
8923       // inlined version can't be used.
8924       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
8925
8926       // If there currently can be no elements accessors on the prototype chain,
8927       // it doesn't mean that there won't be any later. Install a full prototype
8928       // chain check to trap element accessors being installed on the prototype
8929       // chain, which would cause elements to go to dictionary mode and result
8930       // in a map change.
8931       BuildCheckPrototypeMaps(
8932           handle(JSObject::cast(receiver_map->prototype()), isolate()),
8933           Handle<JSObject>::null());
8934
8935       // Threshold for fast inlined Array.shift().
8936       HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16));
8937
8938       Drop(args_count_no_receiver);
8939       HValue* receiver = Pop();
8940       HValue* function = Pop();
8941       HValue* result;
8942
8943       {
8944         NoObservableSideEffectsScope scope(this);
8945
8946         HValue* length = Add<HLoadNamedField>(
8947             receiver, nullptr, HObjectAccess::ForArrayLength(kind));
8948
8949         IfBuilder if_lengthiszero(this);
8950         HValue* lengthiszero = if_lengthiszero.If<HCompareNumericAndBranch>(
8951             length, graph()->GetConstant0(), Token::EQ);
8952         if_lengthiszero.Then();
8953         {
8954           if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
8955         }
8956         if_lengthiszero.Else();
8957         {
8958           HValue* elements = AddLoadElements(receiver);
8959
8960           // Check if we can use the fast inlined Array.shift().
8961           IfBuilder if_inline(this);
8962           if_inline.If<HCompareNumericAndBranch>(
8963               length, inline_threshold, Token::LTE);
8964           if (IsFastSmiOrObjectElementsKind(kind)) {
8965             // We cannot handle copy-on-write backing stores here.
8966             if_inline.AndIf<HCompareMap>(
8967                 elements, isolate()->factory()->fixed_array_map());
8968           }
8969           if_inline.Then();
8970           {
8971             // Remember the result.
8972             if (!ast_context()->IsEffect()) {
8973               Push(AddElementAccess(elements, graph()->GetConstant0(), NULL,
8974                                     lengthiszero, kind, LOAD));
8975             }
8976
8977             // Compute the new length.
8978             HValue* new_length = AddUncasted<HSub>(
8979                 length, graph()->GetConstant1());
8980             new_length->ClearFlag(HValue::kCanOverflow);
8981
8982             // Copy the remaining elements.
8983             LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
8984             {
8985               HValue* new_key = loop.BeginBody(
8986                   graph()->GetConstant0(), new_length, Token::LT);
8987               HValue* key = AddUncasted<HAdd>(new_key, graph()->GetConstant1());
8988               key->ClearFlag(HValue::kCanOverflow);
8989               ElementsKind copy_kind =
8990                   kind == FAST_HOLEY_SMI_ELEMENTS ? FAST_HOLEY_ELEMENTS : kind;
8991               HValue* element = AddUncasted<HLoadKeyed>(
8992                   elements, key, lengthiszero, copy_kind, ALLOW_RETURN_HOLE);
8993               HStoreKeyed* store =
8994                   Add<HStoreKeyed>(elements, new_key, element, copy_kind);
8995               store->SetFlag(HValue::kAllowUndefinedAsNaN);
8996             }
8997             loop.EndBody();
8998
8999             // Put a hole at the end.
9000             HValue* hole = IsFastSmiOrObjectElementsKind(kind)
9001                                ? graph()->GetConstantHole()
9002                                : Add<HConstant>(HConstant::kHoleNaN);
9003             if (IsFastSmiOrObjectElementsKind(kind)) kind = FAST_HOLEY_ELEMENTS;
9004             Add<HStoreKeyed>(
9005                 elements, new_length, hole, kind, INITIALIZING_STORE);
9006
9007             // Remember new length.
9008             Add<HStoreNamedField>(
9009                 receiver, HObjectAccess::ForArrayLength(kind),
9010                 new_length, STORE_TO_INITIALIZED_ENTRY);
9011           }
9012           if_inline.Else();
9013           {
9014             Add<HPushArguments>(receiver);
9015             result = Add<HCallJSFunction>(function, 1);
9016             if (!ast_context()->IsEffect()) Push(result);
9017           }
9018           if_inline.End();
9019         }
9020         if_lengthiszero.End();
9021       }
9022       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
9023       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
9024       if (!ast_context()->IsEffect()) Drop(1);
9025       ast_context()->ReturnValue(result);
9026       return true;
9027     }
9028     case kArrayIndexOf:
9029     case kArrayLastIndexOf: {
9030       if (receiver_map.is_null()) return false;
9031       if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
9032       ElementsKind kind = receiver_map->elements_kind();
9033       if (!IsFastElementsKind(kind)) return false;
9034       if (receiver_map->is_observed()) return false;
9035       if (argument_count != 2) return false;
9036       if (!receiver_map->is_extensible()) return false;
9037
9038       // If there may be elements accessors in the prototype chain, the fast
9039       // inlined version can't be used.
9040       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
9041
9042       // If there currently can be no elements accessors on the prototype chain,
9043       // it doesn't mean that there won't be any later. Install a full prototype
9044       // chain check to trap element accessors being installed on the prototype
9045       // chain, which would cause elements to go to dictionary mode and result
9046       // in a map change.
9047       BuildCheckPrototypeMaps(
9048           handle(JSObject::cast(receiver_map->prototype()), isolate()),
9049           Handle<JSObject>::null());
9050
9051       HValue* search_element = Pop();
9052       HValue* receiver = Pop();
9053       Drop(1);  // Drop function.
9054
9055       ArrayIndexOfMode mode = (id == kArrayIndexOf)
9056           ? kFirstIndexOf : kLastIndexOf;
9057       HValue* index = BuildArrayIndexOf(receiver, search_element, kind, mode);
9058
9059       if (!ast_context()->IsEffect()) Push(index);
9060       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
9061       if (!ast_context()->IsEffect()) Drop(1);
9062       ast_context()->ReturnValue(index);
9063       return true;
9064     }
9065     default:
9066       // Not yet supported for inlining.
9067       break;
9068   }
9069   return false;
9070 }
9071
9072
9073 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr,
9074                                                       HValue* receiver) {
9075   Handle<JSFunction> function = expr->target();
9076   int argc = expr->arguments()->length();
9077   SmallMapList receiver_maps;
9078   return TryInlineApiCall(function,
9079                           receiver,
9080                           &receiver_maps,
9081                           argc,
9082                           expr->id(),
9083                           kCallApiFunction);
9084 }
9085
9086
9087 bool HOptimizedGraphBuilder::TryInlineApiMethodCall(
9088     Call* expr,
9089     HValue* receiver,
9090     SmallMapList* receiver_maps) {
9091   Handle<JSFunction> function = expr->target();
9092   int argc = expr->arguments()->length();
9093   return TryInlineApiCall(function,
9094                           receiver,
9095                           receiver_maps,
9096                           argc,
9097                           expr->id(),
9098                           kCallApiMethod);
9099 }
9100
9101
9102 bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<JSFunction> function,
9103                                                 Handle<Map> receiver_map,
9104                                                 BailoutId ast_id) {
9105   SmallMapList receiver_maps(1, zone());
9106   receiver_maps.Add(receiver_map, zone());
9107   return TryInlineApiCall(function,
9108                           NULL,  // Receiver is on expression stack.
9109                           &receiver_maps,
9110                           0,
9111                           ast_id,
9112                           kCallApiGetter);
9113 }
9114
9115
9116 bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<JSFunction> function,
9117                                                 Handle<Map> receiver_map,
9118                                                 BailoutId ast_id) {
9119   SmallMapList receiver_maps(1, zone());
9120   receiver_maps.Add(receiver_map, zone());
9121   return TryInlineApiCall(function,
9122                           NULL,  // Receiver is on expression stack.
9123                           &receiver_maps,
9124                           1,
9125                           ast_id,
9126                           kCallApiSetter);
9127 }
9128
9129
9130 bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function,
9131                                                HValue* receiver,
9132                                                SmallMapList* receiver_maps,
9133                                                int argc,
9134                                                BailoutId ast_id,
9135                                                ApiCallType call_type) {
9136   if (function->context()->native_context() !=
9137       top_info()->closure()->context()->native_context()) {
9138     return false;
9139   }
9140   CallOptimization optimization(function);
9141   if (!optimization.is_simple_api_call()) return false;
9142   Handle<Map> holder_map;
9143   for (int i = 0; i < receiver_maps->length(); ++i) {
9144     auto map = receiver_maps->at(i);
9145     // Don't inline calls to receivers requiring accesschecks.
9146     if (map->is_access_check_needed()) return false;
9147   }
9148   if (call_type == kCallApiFunction) {
9149     // Cannot embed a direct reference to the global proxy map
9150     // as it maybe dropped on deserialization.
9151     CHECK(!isolate()->serializer_enabled());
9152     DCHECK_EQ(0, receiver_maps->length());
9153     receiver_maps->Add(handle(function->global_proxy()->map()), zone());
9154   }
9155   CallOptimization::HolderLookup holder_lookup =
9156       CallOptimization::kHolderNotFound;
9157   Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
9158       receiver_maps->first(), &holder_lookup);
9159   if (holder_lookup == CallOptimization::kHolderNotFound) return false;
9160
9161   if (FLAG_trace_inlining) {
9162     PrintF("Inlining api function ");
9163     function->ShortPrint();
9164     PrintF("\n");
9165   }
9166
9167   bool is_function = false;
9168   bool is_store = false;
9169   switch (call_type) {
9170     case kCallApiFunction:
9171     case kCallApiMethod:
9172       // Need to check that none of the receiver maps could have changed.
9173       Add<HCheckMaps>(receiver, receiver_maps);
9174       // Need to ensure the chain between receiver and api_holder is intact.
9175       if (holder_lookup == CallOptimization::kHolderFound) {
9176         AddCheckPrototypeMaps(api_holder, receiver_maps->first());
9177       } else {
9178         DCHECK_EQ(holder_lookup, CallOptimization::kHolderIsReceiver);
9179       }
9180       // Includes receiver.
9181       PushArgumentsFromEnvironment(argc + 1);
9182       is_function = true;
9183       break;
9184     case kCallApiGetter:
9185       // Receiver and prototype chain cannot have changed.
9186       DCHECK_EQ(0, argc);
9187       DCHECK_NULL(receiver);
9188       // Receiver is on expression stack.
9189       receiver = Pop();
9190       Add<HPushArguments>(receiver);
9191       break;
9192     case kCallApiSetter:
9193       {
9194         is_store = true;
9195         // Receiver and prototype chain cannot have changed.
9196         DCHECK_EQ(1, argc);
9197         DCHECK_NULL(receiver);
9198         // Receiver and value are on expression stack.
9199         HValue* value = Pop();
9200         receiver = Pop();
9201         Add<HPushArguments>(receiver, value);
9202         break;
9203      }
9204   }
9205
9206   HValue* holder = NULL;
9207   switch (holder_lookup) {
9208     case CallOptimization::kHolderFound:
9209       holder = Add<HConstant>(api_holder);
9210       break;
9211     case CallOptimization::kHolderIsReceiver:
9212       holder = receiver;
9213       break;
9214     case CallOptimization::kHolderNotFound:
9215       UNREACHABLE();
9216       break;
9217   }
9218   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
9219   Handle<Object> call_data_obj(api_call_info->data(), isolate());
9220   bool call_data_undefined = call_data_obj->IsUndefined();
9221   HValue* call_data = Add<HConstant>(call_data_obj);
9222   ApiFunction fun(v8::ToCData<Address>(api_call_info->callback()));
9223   ExternalReference ref = ExternalReference(&fun,
9224                                             ExternalReference::DIRECT_API_CALL,
9225                                             isolate());
9226   HValue* api_function_address = Add<HConstant>(ExternalReference(ref));
9227
9228   HValue* op_vals[] = {context(), Add<HConstant>(function), call_data, holder,
9229                        api_function_address, nullptr};
9230
9231   HInstruction* call = nullptr;
9232   if (!is_function) {
9233     CallApiAccessorStub stub(isolate(), is_store, call_data_undefined);
9234     Handle<Code> code = stub.GetCode();
9235     HConstant* code_value = Add<HConstant>(code);
9236     ApiAccessorDescriptor descriptor(isolate());
9237     call = New<HCallWithDescriptor>(
9238         code_value, argc + 1, descriptor,
9239         Vector<HValue*>(op_vals, arraysize(op_vals) - 1));
9240   } else if (argc <= CallApiFunctionWithFixedArgsStub::kMaxFixedArgs) {
9241     CallApiFunctionWithFixedArgsStub stub(isolate(), argc, call_data_undefined);
9242     Handle<Code> code = stub.GetCode();
9243     HConstant* code_value = Add<HConstant>(code);
9244     ApiFunctionWithFixedArgsDescriptor descriptor(isolate());
9245     call = New<HCallWithDescriptor>(
9246         code_value, argc + 1, descriptor,
9247         Vector<HValue*>(op_vals, arraysize(op_vals) - 1));
9248     Drop(1);  // Drop function.
9249   } else {
9250     op_vals[arraysize(op_vals) - 1] = Add<HConstant>(argc);
9251     CallApiFunctionStub stub(isolate(), call_data_undefined);
9252     Handle<Code> code = stub.GetCode();
9253     HConstant* code_value = Add<HConstant>(code);
9254     ApiFunctionDescriptor descriptor(isolate());
9255     call =
9256         New<HCallWithDescriptor>(code_value, argc + 1, descriptor,
9257                                  Vector<HValue*>(op_vals, arraysize(op_vals)));
9258     Drop(1);  // Drop function.
9259   }
9260
9261   ast_context()->ReturnInstruction(call, ast_id);
9262   return true;
9263 }
9264
9265
9266 void HOptimizedGraphBuilder::HandleIndirectCall(Call* expr, HValue* function,
9267                                                 int arguments_count) {
9268   Handle<JSFunction> known_function;
9269   int args_count_no_receiver = arguments_count - 1;
9270   if (function->IsConstant() &&
9271       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
9272     known_function =
9273         Handle<JSFunction>::cast(HConstant::cast(function)->handle(isolate()));
9274     if (TryInlineBuiltinMethodCall(expr, known_function, Handle<Map>(),
9275                                    args_count_no_receiver)) {
9276       if (FLAG_trace_inlining) {
9277         PrintF("Inlining builtin ");
9278         known_function->ShortPrint();
9279         PrintF("\n");
9280       }
9281       return;
9282     }
9283
9284     if (TryInlineIndirectCall(known_function, expr, args_count_no_receiver)) {
9285       return;
9286     }
9287   }
9288
9289   PushArgumentsFromEnvironment(arguments_count);
9290   HInvokeFunction* call =
9291       New<HInvokeFunction>(function, known_function, arguments_count);
9292   Drop(1);  // Function
9293   ast_context()->ReturnInstruction(call, expr->id());
9294 }
9295
9296
9297 bool HOptimizedGraphBuilder::TryIndirectCall(Call* expr) {
9298   DCHECK(expr->expression()->IsProperty());
9299
9300   if (!expr->IsMonomorphic()) {
9301     return false;
9302   }
9303   Handle<Map> function_map = expr->GetReceiverTypes()->first();
9304   if (function_map->instance_type() != JS_FUNCTION_TYPE ||
9305       !expr->target()->shared()->HasBuiltinFunctionId()) {
9306     return false;
9307   }
9308
9309   switch (expr->target()->shared()->builtin_function_id()) {
9310     case kFunctionCall: {
9311       if (expr->arguments()->length() == 0) return false;
9312       BuildFunctionCall(expr);
9313       return true;
9314     }
9315     case kFunctionApply: {
9316       // For .apply, only the pattern f.apply(receiver, arguments)
9317       // is supported.
9318       if (current_info()->scope()->arguments() == NULL) return false;
9319
9320       if (!CanBeFunctionApplyArguments(expr)) return false;
9321
9322       BuildFunctionApply(expr);
9323       return true;
9324     }
9325     default: { return false; }
9326   }
9327   UNREACHABLE();
9328 }
9329
9330
9331 void HOptimizedGraphBuilder::BuildFunctionApply(Call* expr) {
9332   ZoneList<Expression*>* args = expr->arguments();
9333   CHECK_ALIVE(VisitForValue(args->at(0)));
9334   HValue* receiver = Pop();  // receiver
9335   HValue* function = Pop();  // f
9336   Drop(1);  // apply
9337
9338   Handle<Map> function_map = expr->GetReceiverTypes()->first();
9339   HValue* checked_function = AddCheckMap(function, function_map);
9340
9341   if (function_state()->outer() == NULL) {
9342     HInstruction* elements = Add<HArgumentsElements>(false);
9343     HInstruction* length = Add<HArgumentsLength>(elements);
9344     HValue* wrapped_receiver = BuildWrapReceiver(receiver, checked_function);
9345     HInstruction* result = New<HApplyArguments>(function,
9346                                                 wrapped_receiver,
9347                                                 length,
9348                                                 elements);
9349     ast_context()->ReturnInstruction(result, expr->id());
9350   } else {
9351     // We are inside inlined function and we know exactly what is inside
9352     // arguments object. But we need to be able to materialize at deopt.
9353     DCHECK_EQ(environment()->arguments_environment()->parameter_count(),
9354               function_state()->entry()->arguments_object()->arguments_count());
9355     HArgumentsObject* args = function_state()->entry()->arguments_object();
9356     const ZoneList<HValue*>* arguments_values = args->arguments_values();
9357     int arguments_count = arguments_values->length();
9358     Push(function);
9359     Push(BuildWrapReceiver(receiver, checked_function));
9360     for (int i = 1; i < arguments_count; i++) {
9361       Push(arguments_values->at(i));
9362     }
9363     HandleIndirectCall(expr, function, arguments_count);
9364   }
9365 }
9366
9367
9368 // f.call(...)
9369 void HOptimizedGraphBuilder::BuildFunctionCall(Call* expr) {
9370   HValue* function = Top();  // f
9371   Handle<Map> function_map = expr->GetReceiverTypes()->first();
9372   HValue* checked_function = AddCheckMap(function, function_map);
9373
9374   // f and call are on the stack in the unoptimized code
9375   // during evaluation of the arguments.
9376   CHECK_ALIVE(VisitExpressions(expr->arguments()));
9377
9378   int args_length = expr->arguments()->length();
9379   int receiver_index = args_length - 1;
9380   // Patch the receiver.
9381   HValue* receiver = BuildWrapReceiver(
9382       environment()->ExpressionStackAt(receiver_index), checked_function);
9383   environment()->SetExpressionStackAt(receiver_index, receiver);
9384
9385   // Call must not be on the stack from now on.
9386   int call_index = args_length + 1;
9387   environment()->RemoveExpressionStackAt(call_index);
9388
9389   HandleIndirectCall(expr, function, args_length);
9390 }
9391
9392
9393 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function,
9394                                                     Handle<JSFunction> target) {
9395   SharedFunctionInfo* shared = target->shared();
9396   if (is_sloppy(shared->language_mode()) && !shared->native()) {
9397     // Cannot embed a direct reference to the global proxy
9398     // as is it dropped on deserialization.
9399     CHECK(!isolate()->serializer_enabled());
9400     Handle<JSObject> global_proxy(target->context()->global_proxy());
9401     return Add<HConstant>(global_proxy);
9402   }
9403   return graph()->GetConstantUndefined();
9404 }
9405
9406
9407 void HOptimizedGraphBuilder::BuildArrayCall(Expression* expression,
9408                                             int arguments_count,
9409                                             HValue* function,
9410                                             Handle<AllocationSite> site) {
9411   Add<HCheckValue>(function, array_function());
9412
9413   if (IsCallArrayInlineable(arguments_count, site)) {
9414     BuildInlinedCallArray(expression, arguments_count, site);
9415     return;
9416   }
9417
9418   HInstruction* call = PreProcessCall(New<HCallNewArray>(
9419       function, arguments_count + 1, site->GetElementsKind(), site));
9420   if (expression->IsCall()) {
9421     Drop(1);
9422   }
9423   ast_context()->ReturnInstruction(call, expression->id());
9424 }
9425
9426
9427 HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver,
9428                                                   HValue* search_element,
9429                                                   ElementsKind kind,
9430                                                   ArrayIndexOfMode mode) {
9431   DCHECK(IsFastElementsKind(kind));
9432
9433   NoObservableSideEffectsScope no_effects(this);
9434
9435   HValue* elements = AddLoadElements(receiver);
9436   HValue* length = AddLoadArrayLength(receiver, kind);
9437
9438   HValue* initial;
9439   HValue* terminating;
9440   Token::Value token;
9441   LoopBuilder::Direction direction;
9442   if (mode == kFirstIndexOf) {
9443     initial = graph()->GetConstant0();
9444     terminating = length;
9445     token = Token::LT;
9446     direction = LoopBuilder::kPostIncrement;
9447   } else {
9448     DCHECK_EQ(kLastIndexOf, mode);
9449     initial = length;
9450     terminating = graph()->GetConstant0();
9451     token = Token::GT;
9452     direction = LoopBuilder::kPreDecrement;
9453   }
9454
9455   Push(graph()->GetConstantMinus1());
9456   if (IsFastDoubleElementsKind(kind) || IsFastSmiElementsKind(kind)) {
9457     // Make sure that we can actually compare numbers correctly below, see
9458     // https://code.google.com/p/chromium/issues/detail?id=407946 for details.
9459     search_element = AddUncasted<HForceRepresentation>(
9460         search_element, IsFastSmiElementsKind(kind) ? Representation::Smi()
9461                                                     : Representation::Double());
9462
9463     LoopBuilder loop(this, context(), direction);
9464     {
9465       HValue* index = loop.BeginBody(initial, terminating, token);
9466       HValue* element = AddUncasted<HLoadKeyed>(elements, index, nullptr, kind,
9467                                                 ALLOW_RETURN_HOLE);
9468       IfBuilder if_issame(this);
9469       if_issame.If<HCompareNumericAndBranch>(element, search_element,
9470                                              Token::EQ_STRICT);
9471       if_issame.Then();
9472       {
9473         Drop(1);
9474         Push(index);
9475         loop.Break();
9476       }
9477       if_issame.End();
9478     }
9479     loop.EndBody();
9480   } else {
9481     IfBuilder if_isstring(this);
9482     if_isstring.If<HIsStringAndBranch>(search_element);
9483     if_isstring.Then();
9484     {
9485       LoopBuilder loop(this, context(), direction);
9486       {
9487         HValue* index = loop.BeginBody(initial, terminating, token);
9488         HValue* element = AddUncasted<HLoadKeyed>(elements, index, nullptr,
9489                                                   kind, ALLOW_RETURN_HOLE);
9490         IfBuilder if_issame(this);
9491         if_issame.If<HIsStringAndBranch>(element);
9492         if_issame.AndIf<HStringCompareAndBranch>(
9493             element, search_element, Token::EQ_STRICT);
9494         if_issame.Then();
9495         {
9496           Drop(1);
9497           Push(index);
9498           loop.Break();
9499         }
9500         if_issame.End();
9501       }
9502       loop.EndBody();
9503     }
9504     if_isstring.Else();
9505     {
9506       IfBuilder if_isnumber(this);
9507       if_isnumber.If<HIsSmiAndBranch>(search_element);
9508       if_isnumber.OrIf<HCompareMap>(
9509           search_element, isolate()->factory()->heap_number_map());
9510       if_isnumber.Then();
9511       {
9512         HValue* search_number =
9513             AddUncasted<HForceRepresentation>(search_element,
9514                                               Representation::Double());
9515         LoopBuilder loop(this, context(), direction);
9516         {
9517           HValue* index = loop.BeginBody(initial, terminating, token);
9518           HValue* element = AddUncasted<HLoadKeyed>(elements, index, nullptr,
9519                                                     kind, ALLOW_RETURN_HOLE);
9520
9521           IfBuilder if_element_isnumber(this);
9522           if_element_isnumber.If<HIsSmiAndBranch>(element);
9523           if_element_isnumber.OrIf<HCompareMap>(
9524               element, isolate()->factory()->heap_number_map());
9525           if_element_isnumber.Then();
9526           {
9527             HValue* number =
9528                 AddUncasted<HForceRepresentation>(element,
9529                                                   Representation::Double());
9530             IfBuilder if_issame(this);
9531             if_issame.If<HCompareNumericAndBranch>(
9532                 number, search_number, Token::EQ_STRICT);
9533             if_issame.Then();
9534             {
9535               Drop(1);
9536               Push(index);
9537               loop.Break();
9538             }
9539             if_issame.End();
9540           }
9541           if_element_isnumber.End();
9542         }
9543         loop.EndBody();
9544       }
9545       if_isnumber.Else();
9546       {
9547         LoopBuilder loop(this, context(), direction);
9548         {
9549           HValue* index = loop.BeginBody(initial, terminating, token);
9550           HValue* element = AddUncasted<HLoadKeyed>(elements, index, nullptr,
9551                                                     kind, ALLOW_RETURN_HOLE);
9552           IfBuilder if_issame(this);
9553           if_issame.If<HCompareObjectEqAndBranch>(
9554               element, search_element);
9555           if_issame.Then();
9556           {
9557             Drop(1);
9558             Push(index);
9559             loop.Break();
9560           }
9561           if_issame.End();
9562         }
9563         loop.EndBody();
9564       }
9565       if_isnumber.End();
9566     }
9567     if_isstring.End();
9568   }
9569
9570   return Pop();
9571 }
9572
9573
9574 bool HOptimizedGraphBuilder::TryHandleArrayCall(Call* expr, HValue* function) {
9575   if (!array_function().is_identical_to(expr->target())) {
9576     return false;
9577   }
9578
9579   Handle<AllocationSite> site = expr->allocation_site();
9580   if (site.is_null()) return false;
9581
9582   BuildArrayCall(expr,
9583                  expr->arguments()->length(),
9584                  function,
9585                  site);
9586   return true;
9587 }
9588
9589
9590 bool HOptimizedGraphBuilder::TryHandleArrayCallNew(CallNew* expr,
9591                                                    HValue* function) {
9592   if (!array_function().is_identical_to(expr->target())) {
9593     return false;
9594   }
9595
9596   Handle<AllocationSite> site = expr->allocation_site();
9597   if (site.is_null()) return false;
9598
9599   BuildArrayCall(expr, expr->arguments()->length(), function, site);
9600   return true;
9601 }
9602
9603
9604 bool HOptimizedGraphBuilder::CanBeFunctionApplyArguments(Call* expr) {
9605   ZoneList<Expression*>* args = expr->arguments();
9606   if (args->length() != 2) return false;
9607   VariableProxy* arg_two = args->at(1)->AsVariableProxy();
9608   if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
9609   HValue* arg_two_value = LookupAndMakeLive(arg_two->var());
9610   if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
9611   return true;
9612 }
9613
9614
9615 void HOptimizedGraphBuilder::VisitCall(Call* expr) {
9616   DCHECK(!HasStackOverflow());
9617   DCHECK(current_block() != NULL);
9618   DCHECK(current_block()->HasPredecessor());
9619   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
9620   Expression* callee = expr->expression();
9621   int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
9622   HInstruction* call = NULL;
9623
9624   Property* prop = callee->AsProperty();
9625   if (prop != NULL) {
9626     CHECK_ALIVE(VisitForValue(prop->obj()));
9627     HValue* receiver = Top();
9628
9629     // Sanity check: The receiver must be a JS-exposed kind of object,
9630     // not something internal (like a Map, or FixedArray). Check this here
9631     // to chase after a rare but recurring crash bug. It seems to always
9632     // occur for functions beginning with "this.foo.bar()", so be selective
9633     // and only insert the check for the first call (identified by slot).
9634     // TODO(chromium:527994): Remove this when we have a few crash reports.
9635     if (prop->key()->IsPropertyName() &&
9636         prop->PropertyFeedbackSlot().ToInt() == 2) {
9637       IfBuilder if_heapobject(this);
9638       if_heapobject.IfNot<HIsSmiAndBranch>(receiver);
9639       if_heapobject.Then();
9640       {
9641         IfBuilder special_map(this);
9642         Factory* factory = isolate()->factory();
9643         special_map.If<HCompareMap>(receiver, factory->fixed_array_map());
9644         special_map.OrIf<HCompareMap>(receiver, factory->meta_map());
9645         special_map.Then();
9646         Add<HDebugBreak>();
9647         special_map.End();
9648       }
9649       if_heapobject.End();
9650     }
9651
9652     SmallMapList* maps;
9653     ComputeReceiverTypes(expr, receiver, &maps, zone());
9654
9655     if (prop->key()->IsPropertyName() && maps->length() > 0) {
9656       Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
9657       PropertyAccessInfo info(this, LOAD, maps->first(), name);
9658       if (!info.CanAccessAsMonomorphic(maps)) {
9659         HandlePolymorphicCallNamed(expr, receiver, maps, name);
9660         return;
9661       }
9662     }
9663     HValue* key = NULL;
9664     if (!prop->key()->IsPropertyName()) {
9665       CHECK_ALIVE(VisitForValue(prop->key()));
9666       key = Pop();
9667     }
9668
9669     CHECK_ALIVE(PushLoad(prop, receiver, key));
9670     HValue* function = Pop();
9671
9672     if (function->IsConstant() &&
9673         HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
9674       // Push the function under the receiver.
9675       environment()->SetExpressionStackAt(0, function);
9676       Push(receiver);
9677
9678       Handle<JSFunction> known_function = Handle<JSFunction>::cast(
9679           HConstant::cast(function)->handle(isolate()));
9680       expr->set_target(known_function);
9681
9682       if (TryIndirectCall(expr)) return;
9683       CHECK_ALIVE(VisitExpressions(expr->arguments()));
9684
9685       Handle<Map> map = maps->length() == 1 ? maps->first() : Handle<Map>();
9686       if (TryInlineBuiltinMethodCall(expr, known_function, map,
9687                                      expr->arguments()->length())) {
9688         if (FLAG_trace_inlining) {
9689           PrintF("Inlining builtin ");
9690           known_function->ShortPrint();
9691           PrintF("\n");
9692         }
9693         return;
9694       }
9695       if (TryInlineApiMethodCall(expr, receiver, maps)) return;
9696
9697       // Wrap the receiver if necessary.
9698       if (NeedsWrapping(maps->first(), known_function)) {
9699         // Since HWrapReceiver currently cannot actually wrap numbers and
9700         // strings, use the regular CallFunctionStub for method calls to wrap
9701         // the receiver.
9702         // TODO(verwaest): Support creation of value wrappers directly in
9703         // HWrapReceiver.
9704         call = New<HCallFunction>(
9705             function, argument_count, WRAP_AND_CALL);
9706       } else if (TryInlineCall(expr)) {
9707         return;
9708       } else {
9709         call = BuildCallConstantFunction(known_function, argument_count);
9710       }
9711
9712     } else {
9713       ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED;
9714       if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) {
9715         // We have to use EAGER deoptimization here because Deoptimizer::SOFT
9716         // gets ignored by the always-opt flag, which leads to incorrect code.
9717         Add<HDeoptimize>(
9718             Deoptimizer::kInsufficientTypeFeedbackForCallWithArguments,
9719             Deoptimizer::EAGER);
9720         arguments_flag = ARGUMENTS_FAKED;
9721       }
9722
9723       // Push the function under the receiver.
9724       environment()->SetExpressionStackAt(0, function);
9725       Push(receiver);
9726
9727       CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag));
9728       CallFunctionFlags flags = receiver->type().IsJSObject()
9729           ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD;
9730       call = New<HCallFunction>(function, argument_count, flags);
9731     }
9732     PushArgumentsFromEnvironment(argument_count);
9733
9734   } else {
9735     VariableProxy* proxy = expr->expression()->AsVariableProxy();
9736     if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
9737       return Bailout(kPossibleDirectCallToEval);
9738     }
9739
9740     // The function is on the stack in the unoptimized code during
9741     // evaluation of the arguments.
9742     CHECK_ALIVE(VisitForValue(expr->expression()));
9743     HValue* function = Top();
9744     if (function->IsConstant() &&
9745         HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
9746       Handle<Object> constant = HConstant::cast(function)->handle(isolate());
9747       Handle<JSFunction> target = Handle<JSFunction>::cast(constant);
9748       expr->SetKnownGlobalTarget(target);
9749     }
9750
9751     // Placeholder for the receiver.
9752     Push(graph()->GetConstantUndefined());
9753     CHECK_ALIVE(VisitExpressions(expr->arguments()));
9754
9755     if (expr->IsMonomorphic()) {
9756       Add<HCheckValue>(function, expr->target());
9757
9758       // Patch the global object on the stack by the expected receiver.
9759       HValue* receiver = ImplicitReceiverFor(function, expr->target());
9760       const int receiver_index = argument_count - 1;
9761       environment()->SetExpressionStackAt(receiver_index, receiver);
9762
9763       if (TryInlineBuiltinFunctionCall(expr)) {
9764         if (FLAG_trace_inlining) {
9765           PrintF("Inlining builtin ");
9766           expr->target()->ShortPrint();
9767           PrintF("\n");
9768         }
9769         return;
9770       }
9771       if (TryInlineApiFunctionCall(expr, receiver)) return;
9772       if (TryHandleArrayCall(expr, function)) return;
9773       if (TryInlineCall(expr)) return;
9774
9775       PushArgumentsFromEnvironment(argument_count);
9776       call = BuildCallConstantFunction(expr->target(), argument_count);
9777     } else {
9778       PushArgumentsFromEnvironment(argument_count);
9779       HCallFunction* call_function =
9780           New<HCallFunction>(function, argument_count);
9781       call = call_function;
9782       if (expr->is_uninitialized() &&
9783           expr->IsUsingCallFeedbackICSlot(isolate())) {
9784         // We've never seen this call before, so let's have Crankshaft learn
9785         // through the type vector.
9786         Handle<TypeFeedbackVector> vector =
9787             handle(current_feedback_vector(), isolate());
9788         FeedbackVectorICSlot slot = expr->CallFeedbackICSlot();
9789         call_function->SetVectorAndSlot(vector, slot);
9790       }
9791     }
9792   }
9793
9794   Drop(1);  // Drop the function.
9795   return ast_context()->ReturnInstruction(call, expr->id());
9796 }
9797
9798
9799 void HOptimizedGraphBuilder::BuildInlinedCallArray(
9800     Expression* expression,
9801     int argument_count,
9802     Handle<AllocationSite> site) {
9803   DCHECK(!site.is_null());
9804   DCHECK(argument_count >= 0 && argument_count <= 1);
9805   NoObservableSideEffectsScope no_effects(this);
9806
9807   // We should at least have the constructor on the expression stack.
9808   HValue* constructor = environment()->ExpressionStackAt(argument_count);
9809
9810   // Register on the site for deoptimization if the transition feedback changes.
9811   top_info()->dependencies()->AssumeTransitionStable(site);
9812   ElementsKind kind = site->GetElementsKind();
9813   HInstruction* site_instruction = Add<HConstant>(site);
9814
9815   // In the single constant argument case, we may have to adjust elements kind
9816   // to avoid creating a packed non-empty array.
9817   if (argument_count == 1 && !IsHoleyElementsKind(kind)) {
9818     HValue* argument = environment()->Top();
9819     if (argument->IsConstant()) {
9820       HConstant* constant_argument = HConstant::cast(argument);
9821       DCHECK(constant_argument->HasSmiValue());
9822       int constant_array_size = constant_argument->Integer32Value();
9823       if (constant_array_size != 0) {
9824         kind = GetHoleyElementsKind(kind);
9825       }
9826     }
9827   }
9828
9829   // Build the array.
9830   JSArrayBuilder array_builder(this,
9831                                kind,
9832                                site_instruction,
9833                                constructor,
9834                                DISABLE_ALLOCATION_SITES);
9835   HValue* new_object = argument_count == 0
9836       ? array_builder.AllocateEmptyArray()
9837       : BuildAllocateArrayFromLength(&array_builder, Top());
9838
9839   int args_to_drop = argument_count + (expression->IsCall() ? 2 : 1);
9840   Drop(args_to_drop);
9841   ast_context()->ReturnValue(new_object);
9842 }
9843
9844
9845 // Checks whether allocation using the given constructor can be inlined.
9846 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
9847   return constructor->has_initial_map() &&
9848          constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
9849          constructor->initial_map()->instance_size() <
9850              HAllocate::kMaxInlineSize;
9851 }
9852
9853
9854 bool HOptimizedGraphBuilder::IsCallArrayInlineable(
9855     int argument_count,
9856     Handle<AllocationSite> site) {
9857   Handle<JSFunction> caller = current_info()->closure();
9858   Handle<JSFunction> target = array_function();
9859   // We should have the function plus array arguments on the environment stack.
9860   DCHECK(environment()->length() >= (argument_count + 1));
9861   DCHECK(!site.is_null());
9862
9863   bool inline_ok = false;
9864   if (site->CanInlineCall()) {
9865     // We also want to avoid inlining in certain 1 argument scenarios.
9866     if (argument_count == 1) {
9867       HValue* argument = Top();
9868       if (argument->IsConstant()) {
9869         // Do not inline if the constant length argument is not a smi or
9870         // outside the valid range for unrolled loop initialization.
9871         HConstant* constant_argument = HConstant::cast(argument);
9872         if (constant_argument->HasSmiValue()) {
9873           int value = constant_argument->Integer32Value();
9874           inline_ok = value >= 0 && value <= kElementLoopUnrollThreshold;
9875           if (!inline_ok) {
9876             TraceInline(target, caller,
9877                         "Constant length outside of valid inlining range.");
9878           }
9879         }
9880       } else {
9881         TraceInline(target, caller,
9882                     "Dont inline [new] Array(n) where n isn't constant.");
9883       }
9884     } else if (argument_count == 0) {
9885       inline_ok = true;
9886     } else {
9887       TraceInline(target, caller, "Too many arguments to inline.");
9888     }
9889   } else {
9890     TraceInline(target, caller, "AllocationSite requested no inlining.");
9891   }
9892
9893   if (inline_ok) {
9894     TraceInline(target, caller, NULL);
9895   }
9896   return inline_ok;
9897 }
9898
9899
9900 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
9901   DCHECK(!HasStackOverflow());
9902   DCHECK(current_block() != NULL);
9903   DCHECK(current_block()->HasPredecessor());
9904   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
9905   int argument_count = expr->arguments()->length() + 1;  // Plus constructor.
9906   Factory* factory = isolate()->factory();
9907
9908   // The constructor function is on the stack in the unoptimized code
9909   // during evaluation of the arguments.
9910   CHECK_ALIVE(VisitForValue(expr->expression()));
9911   HValue* function = Top();
9912   CHECK_ALIVE(VisitExpressions(expr->arguments()));
9913
9914   if (function->IsConstant() &&
9915       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
9916     Handle<Object> constant = HConstant::cast(function)->handle(isolate());
9917     expr->SetKnownGlobalTarget(Handle<JSFunction>::cast(constant));
9918   }
9919
9920   if (FLAG_inline_construct &&
9921       expr->IsMonomorphic() &&
9922       IsAllocationInlineable(expr->target())) {
9923     Handle<JSFunction> constructor = expr->target();
9924     HValue* check = Add<HCheckValue>(function, constructor);
9925
9926     // Force completion of inobject slack tracking before generating
9927     // allocation code to finalize instance size.
9928     if (constructor->IsInobjectSlackTrackingInProgress()) {
9929       constructor->CompleteInobjectSlackTracking();
9930     }
9931
9932     // Calculate instance size from initial map of constructor.
9933     DCHECK(constructor->has_initial_map());
9934     Handle<Map> initial_map(constructor->initial_map());
9935     int instance_size = initial_map->instance_size();
9936
9937     // Allocate an instance of the implicit receiver object.
9938     HValue* size_in_bytes = Add<HConstant>(instance_size);
9939     HAllocationMode allocation_mode;
9940     HAllocate* receiver = BuildAllocate(
9941         size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode);
9942     receiver->set_known_initial_map(initial_map);
9943
9944     // Initialize map and fields of the newly allocated object.
9945     { NoObservableSideEffectsScope no_effects(this);
9946       DCHECK(initial_map->instance_type() == JS_OBJECT_TYPE);
9947       Add<HStoreNamedField>(receiver,
9948           HObjectAccess::ForMapAndOffset(initial_map, JSObject::kMapOffset),
9949           Add<HConstant>(initial_map));
9950       HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array());
9951       Add<HStoreNamedField>(receiver,
9952           HObjectAccess::ForMapAndOffset(initial_map,
9953                                          JSObject::kPropertiesOffset),
9954           empty_fixed_array);
9955       Add<HStoreNamedField>(receiver,
9956           HObjectAccess::ForMapAndOffset(initial_map,
9957                                          JSObject::kElementsOffset),
9958           empty_fixed_array);
9959       BuildInitializeInobjectProperties(receiver, initial_map);
9960     }
9961
9962     // Replace the constructor function with a newly allocated receiver using
9963     // the index of the receiver from the top of the expression stack.
9964     const int receiver_index = argument_count - 1;
9965     DCHECK(environment()->ExpressionStackAt(receiver_index) == function);
9966     environment()->SetExpressionStackAt(receiver_index, receiver);
9967
9968     if (TryInlineConstruct(expr, receiver)) {
9969       // Inlining worked, add a dependency on the initial map to make sure that
9970       // this code is deoptimized whenever the initial map of the constructor
9971       // changes.
9972       top_info()->dependencies()->AssumeInitialMapCantChange(initial_map);
9973       return;
9974     }
9975
9976     // TODO(mstarzinger): For now we remove the previous HAllocate and all
9977     // corresponding instructions and instead add HPushArguments for the
9978     // arguments in case inlining failed.  What we actually should do is for
9979     // inlining to try to build a subgraph without mutating the parent graph.
9980     HInstruction* instr = current_block()->last();
9981     do {
9982       HInstruction* prev_instr = instr->previous();
9983       instr->DeleteAndReplaceWith(NULL);
9984       instr = prev_instr;
9985     } while (instr != check);
9986     environment()->SetExpressionStackAt(receiver_index, function);
9987     HInstruction* call =
9988       PreProcessCall(New<HCallNew>(function, argument_count));
9989     return ast_context()->ReturnInstruction(call, expr->id());
9990   } else {
9991     // The constructor function is both an operand to the instruction and an
9992     // argument to the construct call.
9993     if (TryHandleArrayCallNew(expr, function)) return;
9994
9995     HInstruction* call =
9996         PreProcessCall(New<HCallNew>(function, argument_count));
9997     return ast_context()->ReturnInstruction(call, expr->id());
9998   }
9999 }
10000
10001
10002 void HOptimizedGraphBuilder::BuildInitializeInobjectProperties(
10003     HValue* receiver, Handle<Map> initial_map) {
10004   if (initial_map->GetInObjectProperties() != 0) {
10005     HConstant* undefined = graph()->GetConstantUndefined();
10006     for (int i = 0; i < initial_map->GetInObjectProperties(); i++) {
10007       int property_offset = initial_map->GetInObjectPropertyOffset(i);
10008       Add<HStoreNamedField>(receiver, HObjectAccess::ForMapAndOffset(
10009                                           initial_map, property_offset),
10010                             undefined);
10011     }
10012   }
10013 }
10014
10015
10016 HValue* HGraphBuilder::BuildAllocateEmptyArrayBuffer(HValue* byte_length) {
10017   // We HForceRepresentation here to avoid allocations during an *-to-tagged
10018   // HChange that could cause GC while the array buffer object is not fully
10019   // initialized.
10020   HObjectAccess byte_length_access(HObjectAccess::ForJSArrayBufferByteLength());
10021   byte_length = AddUncasted<HForceRepresentation>(
10022       byte_length, byte_length_access.representation());
10023   HAllocate* result =
10024       BuildAllocate(Add<HConstant>(JSArrayBuffer::kSizeWithInternalFields),
10025                     HType::JSObject(), JS_ARRAY_BUFFER_TYPE, HAllocationMode());
10026
10027   HValue* global_object = Add<HLoadNamedField>(
10028       context(), nullptr,
10029       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
10030   HValue* native_context = Add<HLoadNamedField>(
10031       global_object, nullptr, HObjectAccess::ForGlobalObjectNativeContext());
10032   Add<HStoreNamedField>(
10033       result, HObjectAccess::ForMap(),
10034       Add<HLoadNamedField>(
10035           native_context, nullptr,
10036           HObjectAccess::ForContextSlot(Context::ARRAY_BUFFER_MAP_INDEX)));
10037
10038   HConstant* empty_fixed_array =
10039       Add<HConstant>(isolate()->factory()->empty_fixed_array());
10040   Add<HStoreNamedField>(
10041       result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset),
10042       empty_fixed_array);
10043   Add<HStoreNamedField>(
10044       result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
10045       empty_fixed_array);
10046   Add<HStoreNamedField>(
10047       result, HObjectAccess::ForJSArrayBufferBackingStore().WithRepresentation(
10048                   Representation::Smi()),
10049       graph()->GetConstant0());
10050   Add<HStoreNamedField>(result, byte_length_access, byte_length);
10051   Add<HStoreNamedField>(result, HObjectAccess::ForJSArrayBufferBitFieldSlot(),
10052                         graph()->GetConstant0());
10053   Add<HStoreNamedField>(
10054       result, HObjectAccess::ForJSArrayBufferBitField(),
10055       Add<HConstant>((1 << JSArrayBuffer::IsExternal::kShift) |
10056                      (1 << JSArrayBuffer::IsNeuterable::kShift)));
10057
10058   for (int field = 0; field < v8::ArrayBuffer::kInternalFieldCount; ++field) {
10059     Add<HStoreNamedField>(
10060         result,
10061         HObjectAccess::ForObservableJSObjectOffset(
10062             JSArrayBuffer::kSize + field * kPointerSize, Representation::Smi()),
10063         graph()->GetConstant0());
10064   }
10065
10066   return result;
10067 }
10068
10069
10070 template <class ViewClass>
10071 void HGraphBuilder::BuildArrayBufferViewInitialization(
10072     HValue* obj,
10073     HValue* buffer,
10074     HValue* byte_offset,
10075     HValue* byte_length) {
10076
10077   for (int offset = ViewClass::kSize;
10078        offset < ViewClass::kSizeWithInternalFields;
10079        offset += kPointerSize) {
10080     Add<HStoreNamedField>(obj,
10081         HObjectAccess::ForObservableJSObjectOffset(offset),
10082         graph()->GetConstant0());
10083   }
10084
10085   Add<HStoreNamedField>(
10086       obj,
10087       HObjectAccess::ForJSArrayBufferViewByteOffset(),
10088       byte_offset);
10089   Add<HStoreNamedField>(
10090       obj,
10091       HObjectAccess::ForJSArrayBufferViewByteLength(),
10092       byte_length);
10093   Add<HStoreNamedField>(obj, HObjectAccess::ForJSArrayBufferViewBuffer(),
10094                         buffer);
10095 }
10096
10097
10098 void HOptimizedGraphBuilder::GenerateDataViewInitialize(
10099     CallRuntime* expr) {
10100   ZoneList<Expression*>* arguments = expr->arguments();
10101
10102   DCHECK(arguments->length()== 4);
10103   CHECK_ALIVE(VisitForValue(arguments->at(0)));
10104   HValue* obj = Pop();
10105
10106   CHECK_ALIVE(VisitForValue(arguments->at(1)));
10107   HValue* buffer = Pop();
10108
10109   CHECK_ALIVE(VisitForValue(arguments->at(2)));
10110   HValue* byte_offset = Pop();
10111
10112   CHECK_ALIVE(VisitForValue(arguments->at(3)));
10113   HValue* byte_length = Pop();
10114
10115   {
10116     NoObservableSideEffectsScope scope(this);
10117     BuildArrayBufferViewInitialization<JSDataView>(
10118         obj, buffer, byte_offset, byte_length);
10119   }
10120 }
10121
10122
10123 static Handle<Map> TypedArrayMap(Isolate* isolate,
10124                                  ExternalArrayType array_type,
10125                                  ElementsKind target_kind) {
10126   Handle<Context> native_context = isolate->native_context();
10127   Handle<JSFunction> fun;
10128   switch (array_type) {
10129 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
10130     case kExternal##Type##Array:                                              \
10131       fun = Handle<JSFunction>(native_context->type##_array_fun());           \
10132       break;
10133
10134     TYPED_ARRAYS(TYPED_ARRAY_CASE)
10135 #undef TYPED_ARRAY_CASE
10136   }
10137   Handle<Map> map(fun->initial_map());
10138   return Map::AsElementsKind(map, target_kind);
10139 }
10140
10141
10142 HValue* HOptimizedGraphBuilder::BuildAllocateExternalElements(
10143     ExternalArrayType array_type,
10144     bool is_zero_byte_offset,
10145     HValue* buffer, HValue* byte_offset, HValue* length) {
10146   Handle<Map> external_array_map(
10147       isolate()->heap()->MapForFixedTypedArray(array_type));
10148
10149   // The HForceRepresentation is to prevent possible deopt on int-smi
10150   // conversion after allocation but before the new object fields are set.
10151   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
10152   HValue* elements = Add<HAllocate>(
10153       Add<HConstant>(FixedTypedArrayBase::kHeaderSize), HType::HeapObject(),
10154       NOT_TENURED, external_array_map->instance_type());
10155
10156   AddStoreMapConstant(elements, external_array_map);
10157   Add<HStoreNamedField>(elements,
10158       HObjectAccess::ForFixedArrayLength(), length);
10159
10160   HValue* backing_store = Add<HLoadNamedField>(
10161       buffer, nullptr, HObjectAccess::ForJSArrayBufferBackingStore());
10162
10163   HValue* typed_array_start;
10164   if (is_zero_byte_offset) {
10165     typed_array_start = backing_store;
10166   } else {
10167     HInstruction* external_pointer =
10168         AddUncasted<HAdd>(backing_store, byte_offset);
10169     // Arguments are checked prior to call to TypedArrayInitialize,
10170     // including byte_offset.
10171     external_pointer->ClearFlag(HValue::kCanOverflow);
10172     typed_array_start = external_pointer;
10173   }
10174
10175   Add<HStoreNamedField>(elements,
10176                         HObjectAccess::ForFixedTypedArrayBaseBasePointer(),
10177                         graph()->GetConstant0());
10178   Add<HStoreNamedField>(elements,
10179                         HObjectAccess::ForFixedTypedArrayBaseExternalPointer(),
10180                         typed_array_start);
10181
10182   return elements;
10183 }
10184
10185
10186 HValue* HOptimizedGraphBuilder::BuildAllocateFixedTypedArray(
10187     ExternalArrayType array_type, size_t element_size,
10188     ElementsKind fixed_elements_kind, HValue* byte_length, HValue* length,
10189     bool initialize) {
10190   STATIC_ASSERT(
10191       (FixedTypedArrayBase::kHeaderSize & kObjectAlignmentMask) == 0);
10192   HValue* total_size;
10193
10194   // if fixed array's elements are not aligned to object's alignment,
10195   // we need to align the whole array to object alignment.
10196   if (element_size % kObjectAlignment != 0) {
10197     total_size = BuildObjectSizeAlignment(
10198         byte_length, FixedTypedArrayBase::kHeaderSize);
10199   } else {
10200     total_size = AddUncasted<HAdd>(byte_length,
10201         Add<HConstant>(FixedTypedArrayBase::kHeaderSize));
10202     total_size->ClearFlag(HValue::kCanOverflow);
10203   }
10204
10205   // The HForceRepresentation is to prevent possible deopt on int-smi
10206   // conversion after allocation but before the new object fields are set.
10207   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
10208   Handle<Map> fixed_typed_array_map(
10209       isolate()->heap()->MapForFixedTypedArray(array_type));
10210   HAllocate* elements =
10211       Add<HAllocate>(total_size, HType::HeapObject(), NOT_TENURED,
10212                      fixed_typed_array_map->instance_type());
10213
10214 #ifndef V8_HOST_ARCH_64_BIT
10215   if (array_type == kExternalFloat64Array) {
10216     elements->MakeDoubleAligned();
10217   }
10218 #endif
10219
10220   AddStoreMapConstant(elements, fixed_typed_array_map);
10221
10222   Add<HStoreNamedField>(elements,
10223       HObjectAccess::ForFixedArrayLength(),
10224       length);
10225   Add<HStoreNamedField>(
10226       elements, HObjectAccess::ForFixedTypedArrayBaseBasePointer(), elements);
10227
10228   Add<HStoreNamedField>(
10229       elements, HObjectAccess::ForFixedTypedArrayBaseExternalPointer(),
10230       Add<HConstant>(ExternalReference::fixed_typed_array_base_data_offset()));
10231
10232   HValue* filler = Add<HConstant>(static_cast<int32_t>(0));
10233
10234   if (initialize) {
10235     LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
10236
10237     HValue* backing_store = AddUncasted<HAdd>(
10238         Add<HConstant>(ExternalReference::fixed_typed_array_base_data_offset()),
10239         elements, Strength::WEAK, AddOfExternalAndTagged);
10240
10241     HValue* key = builder.BeginBody(
10242         Add<HConstant>(static_cast<int32_t>(0)),
10243         length, Token::LT);
10244     Add<HStoreKeyed>(backing_store, key, filler, fixed_elements_kind);
10245
10246     builder.EndBody();
10247   }
10248   return elements;
10249 }
10250
10251
10252 void HOptimizedGraphBuilder::GenerateTypedArrayInitialize(
10253     CallRuntime* expr) {
10254   ZoneList<Expression*>* arguments = expr->arguments();
10255
10256   static const int kObjectArg = 0;
10257   static const int kArrayIdArg = 1;
10258   static const int kBufferArg = 2;
10259   static const int kByteOffsetArg = 3;
10260   static const int kByteLengthArg = 4;
10261   static const int kInitializeArg = 5;
10262   static const int kArgsLength = 6;
10263   DCHECK(arguments->length() == kArgsLength);
10264
10265
10266   CHECK_ALIVE(VisitForValue(arguments->at(kObjectArg)));
10267   HValue* obj = Pop();
10268
10269   if (!arguments->at(kArrayIdArg)->IsLiteral()) {
10270     // This should never happen in real use, but can happen when fuzzing.
10271     // Just bail out.
10272     Bailout(kNeedSmiLiteral);
10273     return;
10274   }
10275   Handle<Object> value =
10276       static_cast<Literal*>(arguments->at(kArrayIdArg))->value();
10277   if (!value->IsSmi()) {
10278     // This should never happen in real use, but can happen when fuzzing.
10279     // Just bail out.
10280     Bailout(kNeedSmiLiteral);
10281     return;
10282   }
10283   int array_id = Smi::cast(*value)->value();
10284
10285   HValue* buffer;
10286   if (!arguments->at(kBufferArg)->IsNullLiteral()) {
10287     CHECK_ALIVE(VisitForValue(arguments->at(kBufferArg)));
10288     buffer = Pop();
10289   } else {
10290     buffer = NULL;
10291   }
10292
10293   HValue* byte_offset;
10294   bool is_zero_byte_offset;
10295
10296   if (arguments->at(kByteOffsetArg)->IsLiteral()
10297       && Smi::FromInt(0) ==
10298       *static_cast<Literal*>(arguments->at(kByteOffsetArg))->value()) {
10299     byte_offset = Add<HConstant>(static_cast<int32_t>(0));
10300     is_zero_byte_offset = true;
10301   } else {
10302     CHECK_ALIVE(VisitForValue(arguments->at(kByteOffsetArg)));
10303     byte_offset = Pop();
10304     is_zero_byte_offset = false;
10305     DCHECK(buffer != NULL);
10306   }
10307
10308   CHECK_ALIVE(VisitForValue(arguments->at(kByteLengthArg)));
10309   HValue* byte_length = Pop();
10310
10311   CHECK(arguments->at(kInitializeArg)->IsLiteral());
10312   bool initialize = static_cast<Literal*>(arguments->at(kInitializeArg))
10313                         ->value()
10314                         ->BooleanValue();
10315
10316   NoObservableSideEffectsScope scope(this);
10317   IfBuilder byte_offset_smi(this);
10318
10319   if (!is_zero_byte_offset) {
10320     byte_offset_smi.If<HIsSmiAndBranch>(byte_offset);
10321     byte_offset_smi.Then();
10322   }
10323
10324   ExternalArrayType array_type =
10325       kExternalInt8Array;  // Bogus initialization.
10326   size_t element_size = 1;  // Bogus initialization.
10327   ElementsKind fixed_elements_kind =  // Bogus initialization.
10328       INT8_ELEMENTS;
10329   Runtime::ArrayIdToTypeAndSize(array_id,
10330       &array_type,
10331       &fixed_elements_kind,
10332       &element_size);
10333
10334
10335   { //  byte_offset is Smi.
10336     HValue* allocated_buffer = buffer;
10337     if (buffer == NULL) {
10338       allocated_buffer = BuildAllocateEmptyArrayBuffer(byte_length);
10339     }
10340     BuildArrayBufferViewInitialization<JSTypedArray>(obj, allocated_buffer,
10341                                                      byte_offset, byte_length);
10342
10343
10344     HInstruction* length = AddUncasted<HDiv>(byte_length,
10345         Add<HConstant>(static_cast<int32_t>(element_size)));
10346
10347     Add<HStoreNamedField>(obj,
10348         HObjectAccess::ForJSTypedArrayLength(),
10349         length);
10350
10351     HValue* elements;
10352     if (buffer != NULL) {
10353       elements = BuildAllocateExternalElements(
10354           array_type, is_zero_byte_offset, buffer, byte_offset, length);
10355       Handle<Map> obj_map =
10356           TypedArrayMap(isolate(), array_type, fixed_elements_kind);
10357       AddStoreMapConstant(obj, obj_map);
10358     } else {
10359       DCHECK(is_zero_byte_offset);
10360       elements = BuildAllocateFixedTypedArray(array_type, element_size,
10361                                               fixed_elements_kind, byte_length,
10362                                               length, initialize);
10363     }
10364     Add<HStoreNamedField>(
10365         obj, HObjectAccess::ForElementsPointer(), elements);
10366   }
10367
10368   if (!is_zero_byte_offset) {
10369     byte_offset_smi.Else();
10370     { //  byte_offset is not Smi.
10371       Push(obj);
10372       CHECK_ALIVE(VisitForValue(arguments->at(kArrayIdArg)));
10373       Push(buffer);
10374       Push(byte_offset);
10375       Push(byte_length);
10376       CHECK_ALIVE(VisitForValue(arguments->at(kInitializeArg)));
10377       PushArgumentsFromEnvironment(kArgsLength);
10378       Add<HCallRuntime>(expr->function(), kArgsLength);
10379     }
10380   }
10381   byte_offset_smi.End();
10382 }
10383
10384
10385 void HOptimizedGraphBuilder::GenerateMaxSmi(CallRuntime* expr) {
10386   DCHECK(expr->arguments()->length() == 0);
10387   HConstant* max_smi = New<HConstant>(static_cast<int32_t>(Smi::kMaxValue));
10388   return ast_context()->ReturnInstruction(max_smi, expr->id());
10389 }
10390
10391
10392 void HOptimizedGraphBuilder::GenerateTypedArrayMaxSizeInHeap(
10393     CallRuntime* expr) {
10394   DCHECK(expr->arguments()->length() == 0);
10395   HConstant* result = New<HConstant>(static_cast<int32_t>(
10396         FLAG_typed_array_max_size_in_heap));
10397   return ast_context()->ReturnInstruction(result, expr->id());
10398 }
10399
10400
10401 void HOptimizedGraphBuilder::GenerateArrayBufferGetByteLength(
10402     CallRuntime* expr) {
10403   DCHECK(expr->arguments()->length() == 1);
10404   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
10405   HValue* buffer = Pop();
10406   HInstruction* result = New<HLoadNamedField>(
10407       buffer, nullptr, HObjectAccess::ForJSArrayBufferByteLength());
10408   return ast_context()->ReturnInstruction(result, expr->id());
10409 }
10410
10411
10412 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength(
10413     CallRuntime* expr) {
10414   NoObservableSideEffectsScope scope(this);
10415   DCHECK(expr->arguments()->length() == 1);
10416   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
10417   HValue* view = Pop();
10418
10419   return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
10420       view, nullptr,
10421       FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteLengthOffset)));
10422 }
10423
10424
10425 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset(
10426     CallRuntime* expr) {
10427   NoObservableSideEffectsScope scope(this);
10428   DCHECK(expr->arguments()->length() == 1);
10429   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
10430   HValue* view = Pop();
10431
10432   return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
10433       view, nullptr,
10434       FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteOffsetOffset)));
10435 }
10436
10437
10438 void HOptimizedGraphBuilder::GenerateTypedArrayGetLength(
10439     CallRuntime* expr) {
10440   NoObservableSideEffectsScope scope(this);
10441   DCHECK(expr->arguments()->length() == 1);
10442   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
10443   HValue* view = Pop();
10444
10445   return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
10446       view, nullptr,
10447       FieldIndex::ForInObjectOffset(JSTypedArray::kLengthOffset)));
10448 }
10449
10450
10451 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
10452   DCHECK(!HasStackOverflow());
10453   DCHECK(current_block() != NULL);
10454   DCHECK(current_block()->HasPredecessor());
10455   if (expr->is_jsruntime()) {
10456     return Bailout(kCallToAJavaScriptRuntimeFunction);
10457   }
10458
10459   const Runtime::Function* function = expr->function();
10460   DCHECK(function != NULL);
10461   switch (function->function_id) {
10462 #define CALL_INTRINSIC_GENERATOR(Name) \
10463   case Runtime::kInline##Name:         \
10464     return Generate##Name(expr);
10465
10466     FOR_EACH_HYDROGEN_INTRINSIC(CALL_INTRINSIC_GENERATOR)
10467 #undef CALL_INTRINSIC_GENERATOR
10468     default: {
10469       int argument_count = expr->arguments()->length();
10470       CHECK_ALIVE(VisitExpressions(expr->arguments()));
10471       PushArgumentsFromEnvironment(argument_count);
10472       HCallRuntime* call = New<HCallRuntime>(function, argument_count);
10473       return ast_context()->ReturnInstruction(call, expr->id());
10474     }
10475   }
10476 }
10477
10478
10479 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
10480   DCHECK(!HasStackOverflow());
10481   DCHECK(current_block() != NULL);
10482   DCHECK(current_block()->HasPredecessor());
10483   switch (expr->op()) {
10484     case Token::DELETE: return VisitDelete(expr);
10485     case Token::VOID: return VisitVoid(expr);
10486     case Token::TYPEOF: return VisitTypeof(expr);
10487     case Token::NOT: return VisitNot(expr);
10488     default: UNREACHABLE();
10489   }
10490 }
10491
10492
10493 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
10494   Property* prop = expr->expression()->AsProperty();
10495   VariableProxy* proxy = expr->expression()->AsVariableProxy();
10496   if (prop != NULL) {
10497     CHECK_ALIVE(VisitForValue(prop->obj()));
10498     CHECK_ALIVE(VisitForValue(prop->key()));
10499     HValue* key = Pop();
10500     HValue* obj = Pop();
10501     Add<HPushArguments>(obj, key);
10502     HInstruction* instr = New<HCallRuntime>(
10503         Runtime::FunctionForId(is_strict(function_language_mode())
10504                                    ? Runtime::kDeleteProperty_Strict
10505                                    : Runtime::kDeleteProperty_Sloppy),
10506         2);
10507     return ast_context()->ReturnInstruction(instr, expr->id());
10508   } else if (proxy != NULL) {
10509     Variable* var = proxy->var();
10510     if (var->IsUnallocatedOrGlobalSlot()) {
10511       Bailout(kDeleteWithGlobalVariable);
10512     } else if (var->IsStackAllocated() || var->IsContextSlot()) {
10513       // Result of deleting non-global variables is false.  'this' is not really
10514       // a variable, though we implement it as one.  The subexpression does not
10515       // have side effects.
10516       HValue* value = var->HasThisName(isolate()) ? graph()->GetConstantTrue()
10517                                                   : graph()->GetConstantFalse();
10518       return ast_context()->ReturnValue(value);
10519     } else {
10520       Bailout(kDeleteWithNonGlobalVariable);
10521     }
10522   } else {
10523     // Result of deleting non-property, non-variable reference is true.
10524     // Evaluate the subexpression for side effects.
10525     CHECK_ALIVE(VisitForEffect(expr->expression()));
10526     return ast_context()->ReturnValue(graph()->GetConstantTrue());
10527   }
10528 }
10529
10530
10531 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) {
10532   CHECK_ALIVE(VisitForEffect(expr->expression()));
10533   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
10534 }
10535
10536
10537 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
10538   CHECK_ALIVE(VisitForTypeOf(expr->expression()));
10539   HValue* value = Pop();
10540   HInstruction* instr = New<HTypeof>(value);
10541   return ast_context()->ReturnInstruction(instr, expr->id());
10542 }
10543
10544
10545 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) {
10546   if (ast_context()->IsTest()) {
10547     TestContext* context = TestContext::cast(ast_context());
10548     VisitForControl(expr->expression(),
10549                     context->if_false(),
10550                     context->if_true());
10551     return;
10552   }
10553
10554   if (ast_context()->IsEffect()) {
10555     VisitForEffect(expr->expression());
10556     return;
10557   }
10558
10559   DCHECK(ast_context()->IsValue());
10560   HBasicBlock* materialize_false = graph()->CreateBasicBlock();
10561   HBasicBlock* materialize_true = graph()->CreateBasicBlock();
10562   CHECK_BAILOUT(VisitForControl(expr->expression(),
10563                                 materialize_false,
10564                                 materialize_true));
10565
10566   if (materialize_false->HasPredecessor()) {
10567     materialize_false->SetJoinId(expr->MaterializeFalseId());
10568     set_current_block(materialize_false);
10569     Push(graph()->GetConstantFalse());
10570   } else {
10571     materialize_false = NULL;
10572   }
10573
10574   if (materialize_true->HasPredecessor()) {
10575     materialize_true->SetJoinId(expr->MaterializeTrueId());
10576     set_current_block(materialize_true);
10577     Push(graph()->GetConstantTrue());
10578   } else {
10579     materialize_true = NULL;
10580   }
10581
10582   HBasicBlock* join =
10583     CreateJoin(materialize_false, materialize_true, expr->id());
10584   set_current_block(join);
10585   if (join != NULL) return ast_context()->ReturnValue(Pop());
10586 }
10587
10588
10589 static Representation RepresentationFor(Type* type) {
10590   DisallowHeapAllocation no_allocation;
10591   if (type->Is(Type::None())) return Representation::None();
10592   if (type->Is(Type::SignedSmall())) return Representation::Smi();
10593   if (type->Is(Type::Signed32())) return Representation::Integer32();
10594   if (type->Is(Type::Number())) return Representation::Double();
10595   return Representation::Tagged();
10596 }
10597
10598
10599 HInstruction* HOptimizedGraphBuilder::BuildIncrement(
10600     bool returns_original_input,
10601     CountOperation* expr) {
10602   // The input to the count operation is on top of the expression stack.
10603   Representation rep = RepresentationFor(expr->type());
10604   if (rep.IsNone() || rep.IsTagged()) {
10605     rep = Representation::Smi();
10606   }
10607
10608   if (returns_original_input && !is_strong(function_language_mode())) {
10609     // We need an explicit HValue representing ToNumber(input).  The
10610     // actual HChange instruction we need is (sometimes) added in a later
10611     // phase, so it is not available now to be used as an input to HAdd and
10612     // as the return value.
10613     HInstruction* number_input = AddUncasted<HForceRepresentation>(Pop(), rep);
10614     if (!rep.IsDouble()) {
10615       number_input->SetFlag(HInstruction::kFlexibleRepresentation);
10616       number_input->SetFlag(HInstruction::kCannotBeTagged);
10617     }
10618     Push(number_input);
10619   }
10620
10621   // The addition has no side effects, so we do not need
10622   // to simulate the expression stack after this instruction.
10623   // Any later failures deopt to the load of the input or earlier.
10624   HConstant* delta = (expr->op() == Token::INC)
10625       ? graph()->GetConstant1()
10626       : graph()->GetConstantMinus1();
10627   HInstruction* instr =
10628       AddUncasted<HAdd>(Top(), delta, strength(function_language_mode()));
10629   if (instr->IsAdd()) {
10630     HAdd* add = HAdd::cast(instr);
10631     add->set_observed_input_representation(1, rep);
10632     add->set_observed_input_representation(2, Representation::Smi());
10633   }
10634   if (!is_strong(function_language_mode())) {
10635     instr->ClearAllSideEffects();
10636   } else {
10637     Add<HSimulate>(expr->ToNumberId(), REMOVABLE_SIMULATE);
10638   }
10639   instr->SetFlag(HInstruction::kCannotBeTagged);
10640   return instr;
10641 }
10642
10643
10644 void HOptimizedGraphBuilder::BuildStoreForEffect(
10645     Expression* expr, Property* prop, FeedbackVectorICSlot slot,
10646     BailoutId ast_id, BailoutId return_id, HValue* object, HValue* key,
10647     HValue* value) {
10648   EffectContext for_effect(this);
10649   Push(object);
10650   if (key != NULL) Push(key);
10651   Push(value);
10652   BuildStore(expr, prop, slot, ast_id, return_id);
10653 }
10654
10655
10656 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
10657   DCHECK(!HasStackOverflow());
10658   DCHECK(current_block() != NULL);
10659   DCHECK(current_block()->HasPredecessor());
10660   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
10661   Expression* target = expr->expression();
10662   VariableProxy* proxy = target->AsVariableProxy();
10663   Property* prop = target->AsProperty();
10664   if (proxy == NULL && prop == NULL) {
10665     return Bailout(kInvalidLhsInCountOperation);
10666   }
10667
10668   // Match the full code generator stack by simulating an extra stack
10669   // element for postfix operations in a non-effect context.  The return
10670   // value is ToNumber(input).
10671   bool returns_original_input =
10672       expr->is_postfix() && !ast_context()->IsEffect();
10673   HValue* input = NULL;  // ToNumber(original_input).
10674   HValue* after = NULL;  // The result after incrementing or decrementing.
10675
10676   if (proxy != NULL) {
10677     Variable* var = proxy->var();
10678     if (var->mode() == CONST_LEGACY)  {
10679       return Bailout(kUnsupportedCountOperationWithConst);
10680     }
10681     if (var->mode() == CONST) {
10682       return Bailout(kNonInitializerAssignmentToConst);
10683     }
10684     // Argument of the count operation is a variable, not a property.
10685     DCHECK(prop == NULL);
10686     CHECK_ALIVE(VisitForValue(target));
10687
10688     after = BuildIncrement(returns_original_input, expr);
10689     input = returns_original_input ? Top() : Pop();
10690     Push(after);
10691
10692     switch (var->location()) {
10693       case VariableLocation::GLOBAL:
10694       case VariableLocation::UNALLOCATED:
10695         HandleGlobalVariableAssignment(var, after, expr->CountSlot(),
10696                                        expr->AssignmentId());
10697         break;
10698
10699       case VariableLocation::PARAMETER:
10700       case VariableLocation::LOCAL:
10701         BindIfLive(var, after);
10702         break;
10703
10704       case VariableLocation::CONTEXT: {
10705         // Bail out if we try to mutate a parameter value in a function
10706         // using the arguments object.  We do not (yet) correctly handle the
10707         // arguments property of the function.
10708         if (current_info()->scope()->arguments() != NULL) {
10709           // Parameters will rewrite to context slots.  We have no direct
10710           // way to detect that the variable is a parameter so we use a
10711           // linear search of the parameter list.
10712           int count = current_info()->scope()->num_parameters();
10713           for (int i = 0; i < count; ++i) {
10714             if (var == current_info()->scope()->parameter(i)) {
10715               return Bailout(kAssignmentToParameterInArgumentsObject);
10716             }
10717           }
10718         }
10719
10720         HValue* context = BuildContextChainWalk(var);
10721         HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode())
10722             ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck;
10723         HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
10724                                                           mode, after);
10725         if (instr->HasObservableSideEffects()) {
10726           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
10727         }
10728         break;
10729       }
10730
10731       case VariableLocation::LOOKUP:
10732         return Bailout(kLookupVariableInCountOperation);
10733     }
10734
10735     Drop(returns_original_input ? 2 : 1);
10736     return ast_context()->ReturnValue(expr->is_postfix() ? input : after);
10737   }
10738
10739   // Argument of the count operation is a property.
10740   DCHECK(prop != NULL);
10741   if (returns_original_input) Push(graph()->GetConstantUndefined());
10742
10743   CHECK_ALIVE(VisitForValue(prop->obj()));
10744   HValue* object = Top();
10745
10746   HValue* key = NULL;
10747   if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
10748     CHECK_ALIVE(VisitForValue(prop->key()));
10749     key = Top();
10750   }
10751
10752   CHECK_ALIVE(PushLoad(prop, object, key));
10753
10754   after = BuildIncrement(returns_original_input, expr);
10755
10756   if (returns_original_input) {
10757     input = Pop();
10758     // Drop object and key to push it again in the effect context below.
10759     Drop(key == NULL ? 1 : 2);
10760     environment()->SetExpressionStackAt(0, input);
10761     CHECK_ALIVE(BuildStoreForEffect(expr, prop, expr->CountSlot(), expr->id(),
10762                                     expr->AssignmentId(), object, key, after));
10763     return ast_context()->ReturnValue(Pop());
10764   }
10765
10766   environment()->SetExpressionStackAt(0, after);
10767   return BuildStore(expr, prop, expr->CountSlot(), expr->id(),
10768                     expr->AssignmentId());
10769 }
10770
10771
10772 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt(
10773     HValue* string,
10774     HValue* index) {
10775   if (string->IsConstant() && index->IsConstant()) {
10776     HConstant* c_string = HConstant::cast(string);
10777     HConstant* c_index = HConstant::cast(index);
10778     if (c_string->HasStringValue() && c_index->HasNumberValue()) {
10779       int32_t i = c_index->NumberValueAsInteger32();
10780       Handle<String> s = c_string->StringValue();
10781       if (i < 0 || i >= s->length()) {
10782         return New<HConstant>(std::numeric_limits<double>::quiet_NaN());
10783       }
10784       return New<HConstant>(s->Get(i));
10785     }
10786   }
10787   string = BuildCheckString(string);
10788   index = Add<HBoundsCheck>(index, AddLoadStringLength(string));
10789   return New<HStringCharCodeAt>(string, index);
10790 }
10791
10792
10793 // Checks if the given shift amounts have following forms:
10794 // (N1) and (N2) with N1 + N2 = 32; (sa) and (32 - sa).
10795 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa,
10796                                              HValue* const32_minus_sa) {
10797   if (sa->IsConstant() && const32_minus_sa->IsConstant()) {
10798     const HConstant* c1 = HConstant::cast(sa);
10799     const HConstant* c2 = HConstant::cast(const32_minus_sa);
10800     return c1->HasInteger32Value() && c2->HasInteger32Value() &&
10801         (c1->Integer32Value() + c2->Integer32Value() == 32);
10802   }
10803   if (!const32_minus_sa->IsSub()) return false;
10804   HSub* sub = HSub::cast(const32_minus_sa);
10805   return sub->left()->EqualsInteger32Constant(32) && sub->right() == sa;
10806 }
10807
10808
10809 // Checks if the left and the right are shift instructions with the oposite
10810 // directions that can be replaced by one rotate right instruction or not.
10811 // Returns the operand and the shift amount for the rotate instruction in the
10812 // former case.
10813 bool HGraphBuilder::MatchRotateRight(HValue* left,
10814                                      HValue* right,
10815                                      HValue** operand,
10816                                      HValue** shift_amount) {
10817   HShl* shl;
10818   HShr* shr;
10819   if (left->IsShl() && right->IsShr()) {
10820     shl = HShl::cast(left);
10821     shr = HShr::cast(right);
10822   } else if (left->IsShr() && right->IsShl()) {
10823     shl = HShl::cast(right);
10824     shr = HShr::cast(left);
10825   } else {
10826     return false;
10827   }
10828   if (shl->left() != shr->left()) return false;
10829
10830   if (!ShiftAmountsAllowReplaceByRotate(shl->right(), shr->right()) &&
10831       !ShiftAmountsAllowReplaceByRotate(shr->right(), shl->right())) {
10832     return false;
10833   }
10834   *operand = shr->left();
10835   *shift_amount = shr->right();
10836   return true;
10837 }
10838
10839
10840 bool CanBeZero(HValue* right) {
10841   if (right->IsConstant()) {
10842     HConstant* right_const = HConstant::cast(right);
10843     if (right_const->HasInteger32Value() &&
10844        (right_const->Integer32Value() & 0x1f) != 0) {
10845       return false;
10846     }
10847   }
10848   return true;
10849 }
10850
10851
10852 HValue* HGraphBuilder::EnforceNumberType(HValue* number,
10853                                          Type* expected) {
10854   if (expected->Is(Type::SignedSmall())) {
10855     return AddUncasted<HForceRepresentation>(number, Representation::Smi());
10856   }
10857   if (expected->Is(Type::Signed32())) {
10858     return AddUncasted<HForceRepresentation>(number,
10859                                              Representation::Integer32());
10860   }
10861   return number;
10862 }
10863
10864
10865 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Type** expected) {
10866   if (value->IsConstant()) {
10867     HConstant* constant = HConstant::cast(value);
10868     Maybe<HConstant*> number =
10869         constant->CopyToTruncatedNumber(isolate(), zone());
10870     if (number.IsJust()) {
10871       *expected = Type::Number(zone());
10872       return AddInstruction(number.FromJust());
10873     }
10874   }
10875
10876   // We put temporary values on the stack, which don't correspond to anything
10877   // in baseline code. Since nothing is observable we avoid recording those
10878   // pushes with a NoObservableSideEffectsScope.
10879   NoObservableSideEffectsScope no_effects(this);
10880
10881   Type* expected_type = *expected;
10882
10883   // Separate the number type from the rest.
10884   Type* expected_obj =
10885       Type::Intersect(expected_type, Type::NonNumber(zone()), zone());
10886   Type* expected_number =
10887       Type::Intersect(expected_type, Type::Number(zone()), zone());
10888
10889   // We expect to get a number.
10890   // (We need to check first, since Type::None->Is(Type::Any()) == true.
10891   if (expected_obj->Is(Type::None())) {
10892     DCHECK(!expected_number->Is(Type::None(zone())));
10893     return value;
10894   }
10895
10896   if (expected_obj->Is(Type::Undefined(zone()))) {
10897     // This is already done by HChange.
10898     *expected = Type::Union(expected_number, Type::Number(zone()), zone());
10899     return value;
10900   }
10901
10902   return value;
10903 }
10904
10905
10906 HValue* HOptimizedGraphBuilder::BuildBinaryOperation(
10907     BinaryOperation* expr,
10908     HValue* left,
10909     HValue* right,
10910     PushBeforeSimulateBehavior push_sim_result) {
10911   Type* left_type = expr->left()->bounds().lower;
10912   Type* right_type = expr->right()->bounds().lower;
10913   Type* result_type = expr->bounds().lower;
10914   Maybe<int> fixed_right_arg = expr->fixed_right_arg();
10915   Handle<AllocationSite> allocation_site = expr->allocation_site();
10916
10917   HAllocationMode allocation_mode;
10918   if (FLAG_allocation_site_pretenuring && !allocation_site.is_null()) {
10919     allocation_mode = HAllocationMode(allocation_site);
10920   }
10921   HValue* result = HGraphBuilder::BuildBinaryOperation(
10922       expr->op(), left, right, left_type, right_type, result_type,
10923       fixed_right_arg, allocation_mode, strength(function_language_mode()),
10924       expr->id());
10925   // Add a simulate after instructions with observable side effects, and
10926   // after phis, which are the result of BuildBinaryOperation when we
10927   // inlined some complex subgraph.
10928   if (result->HasObservableSideEffects() || result->IsPhi()) {
10929     if (push_sim_result == PUSH_BEFORE_SIMULATE) {
10930       Push(result);
10931       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
10932       Drop(1);
10933     } else {
10934       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
10935     }
10936   }
10937   return result;
10938 }
10939
10940
10941 HValue* HGraphBuilder::BuildBinaryOperation(
10942     Token::Value op, HValue* left, HValue* right, Type* left_type,
10943     Type* right_type, Type* result_type, Maybe<int> fixed_right_arg,
10944     HAllocationMode allocation_mode, Strength strength, BailoutId opt_id) {
10945   bool maybe_string_add = false;
10946   if (op == Token::ADD) {
10947     // If we are adding constant string with something for which we don't have
10948     // a feedback yet, assume that it's also going to be a string and don't
10949     // generate deopt instructions.
10950     if (!left_type->IsInhabited() && right->IsConstant() &&
10951         HConstant::cast(right)->HasStringValue()) {
10952       left_type = Type::String();
10953     }
10954
10955     if (!right_type->IsInhabited() && left->IsConstant() &&
10956         HConstant::cast(left)->HasStringValue()) {
10957       right_type = Type::String();
10958     }
10959
10960     maybe_string_add = (left_type->Maybe(Type::String()) ||
10961                         left_type->Maybe(Type::Receiver()) ||
10962                         right_type->Maybe(Type::String()) ||
10963                         right_type->Maybe(Type::Receiver()));
10964   }
10965
10966   Representation left_rep = RepresentationFor(left_type);
10967   Representation right_rep = RepresentationFor(right_type);
10968
10969   if (!left_type->IsInhabited()) {
10970     Add<HDeoptimize>(
10971         Deoptimizer::kInsufficientTypeFeedbackForLHSOfBinaryOperation,
10972         Deoptimizer::SOFT);
10973     left_type = Type::Any(zone());
10974     left_rep = RepresentationFor(left_type);
10975     maybe_string_add = op == Token::ADD;
10976   }
10977
10978   if (!right_type->IsInhabited()) {
10979     Add<HDeoptimize>(
10980         Deoptimizer::kInsufficientTypeFeedbackForRHSOfBinaryOperation,
10981         Deoptimizer::SOFT);
10982     right_type = Type::Any(zone());
10983     right_rep = RepresentationFor(right_type);
10984     maybe_string_add = op == Token::ADD;
10985   }
10986
10987   if (!maybe_string_add && !is_strong(strength)) {
10988     left = TruncateToNumber(left, &left_type);
10989     right = TruncateToNumber(right, &right_type);
10990   }
10991
10992   // Special case for string addition here.
10993   if (op == Token::ADD &&
10994       (left_type->Is(Type::String()) || right_type->Is(Type::String()))) {
10995     if (is_strong(strength)) {
10996       // In strong mode, if the one side of an addition is a string,
10997       // the other side must be a string too.
10998       left = BuildCheckString(left);
10999       right = BuildCheckString(right);
11000     } else {
11001       // Validate type feedback for left argument.
11002       if (left_type->Is(Type::String())) {
11003         left = BuildCheckString(left);
11004       }
11005
11006       // Validate type feedback for right argument.
11007       if (right_type->Is(Type::String())) {
11008         right = BuildCheckString(right);
11009       }
11010
11011       // Convert left argument as necessary.
11012       if (left_type->Is(Type::Number())) {
11013         DCHECK(right_type->Is(Type::String()));
11014         left = BuildNumberToString(left, left_type);
11015       } else if (!left_type->Is(Type::String())) {
11016         DCHECK(right_type->Is(Type::String()));
11017         // TODO(bmeurer): We might want to optimize this, because we already
11018         // know that the right hand side is a string.
11019         Add<HPushArguments>(left, right);
11020         return AddUncasted<HCallRuntime>(Runtime::FunctionForId(Runtime::kAdd),
11021                                          2);
11022       }
11023
11024       // Convert right argument as necessary.
11025       if (right_type->Is(Type::Number())) {
11026         DCHECK(left_type->Is(Type::String()));
11027         right = BuildNumberToString(right, right_type);
11028       } else if (!right_type->Is(Type::String())) {
11029         DCHECK(left_type->Is(Type::String()));
11030         // TODO(bmeurer): We might want to optimize this, because we already
11031         // know that the left hand side is a string.
11032         Add<HPushArguments>(left, right);
11033         return AddUncasted<HCallRuntime>(Runtime::FunctionForId(Runtime::kAdd),
11034                                          2);
11035       }
11036     }
11037
11038     // Fast paths for empty constant strings.
11039     Handle<String> left_string =
11040         left->IsConstant() && HConstant::cast(left)->HasStringValue()
11041             ? HConstant::cast(left)->StringValue()
11042             : Handle<String>();
11043     Handle<String> right_string =
11044         right->IsConstant() && HConstant::cast(right)->HasStringValue()
11045             ? HConstant::cast(right)->StringValue()
11046             : Handle<String>();
11047     if (!left_string.is_null() && left_string->length() == 0) return right;
11048     if (!right_string.is_null() && right_string->length() == 0) return left;
11049     if (!left_string.is_null() && !right_string.is_null()) {
11050       return AddUncasted<HStringAdd>(
11051           left, right, strength, allocation_mode.GetPretenureMode(),
11052           STRING_ADD_CHECK_NONE, allocation_mode.feedback_site());
11053     }
11054
11055     // Register the dependent code with the allocation site.
11056     if (!allocation_mode.feedback_site().is_null()) {
11057       DCHECK(!graph()->info()->IsStub());
11058       Handle<AllocationSite> site(allocation_mode.feedback_site());
11059       top_info()->dependencies()->AssumeTenuringDecision(site);
11060     }
11061
11062     // Inline the string addition into the stub when creating allocation
11063     // mementos to gather allocation site feedback, or if we can statically
11064     // infer that we're going to create a cons string.
11065     if ((graph()->info()->IsStub() &&
11066          allocation_mode.CreateAllocationMementos()) ||
11067         (left->IsConstant() &&
11068          HConstant::cast(left)->HasStringValue() &&
11069          HConstant::cast(left)->StringValue()->length() + 1 >=
11070            ConsString::kMinLength) ||
11071         (right->IsConstant() &&
11072          HConstant::cast(right)->HasStringValue() &&
11073          HConstant::cast(right)->StringValue()->length() + 1 >=
11074            ConsString::kMinLength)) {
11075       return BuildStringAdd(left, right, allocation_mode);
11076     }
11077
11078     // Fallback to using the string add stub.
11079     return AddUncasted<HStringAdd>(
11080         left, right, strength, allocation_mode.GetPretenureMode(),
11081         STRING_ADD_CHECK_NONE, allocation_mode.feedback_site());
11082   }
11083
11084   if (graph()->info()->IsStub()) {
11085     left = EnforceNumberType(left, left_type);
11086     right = EnforceNumberType(right, right_type);
11087   }
11088
11089   Representation result_rep = RepresentationFor(result_type);
11090
11091   bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) ||
11092                           (right_rep.IsTagged() && !right_rep.IsSmi());
11093
11094   HInstruction* instr = NULL;
11095   // Only the stub is allowed to call into the runtime, since otherwise we would
11096   // inline several instructions (including the two pushes) for every tagged
11097   // operation in optimized code, which is more expensive, than a stub call.
11098   if (graph()->info()->IsStub() && is_non_primitive) {
11099     Runtime::FunctionId function_id;
11100     switch (op) {
11101       default:
11102         UNREACHABLE();
11103       case Token::ADD:
11104         function_id =
11105             is_strong(strength) ? Runtime::kAdd_Strong : Runtime::kAdd;
11106         break;
11107       case Token::SUB:
11108         function_id = is_strong(strength) ? Runtime::kSubtract_Strong
11109                                           : Runtime::kSubtract;
11110         break;
11111       case Token::MUL:
11112         function_id = is_strong(strength) ? Runtime::kMultiply_Strong
11113                                           : Runtime::kMultiply;
11114         break;
11115       case Token::DIV:
11116         function_id =
11117             is_strong(strength) ? Runtime::kDivide_Strong : Runtime::kDivide;
11118         break;
11119       case Token::MOD:
11120         function_id =
11121             is_strong(strength) ? Runtime::kModulus_Strong : Runtime::kModulus;
11122         break;
11123       case Token::BIT_OR:
11124         function_id = is_strong(strength) ? Runtime::kBitwiseOr_Strong
11125                                           : Runtime::kBitwiseOr;
11126         break;
11127       case Token::BIT_AND:
11128         function_id = is_strong(strength) ? Runtime::kBitwiseAnd_Strong
11129                                           : Runtime::kBitwiseAnd;
11130         break;
11131       case Token::BIT_XOR:
11132         function_id = is_strong(strength) ? Runtime::kBitwiseXor_Strong
11133                                           : Runtime::kBitwiseXor;
11134         break;
11135       case Token::SAR:
11136         function_id = is_strong(strength) ? Runtime::kShiftRight_Strong
11137                                           : Runtime::kShiftRight;
11138         break;
11139       case Token::SHR:
11140         function_id = is_strong(strength) ? Runtime::kShiftRightLogical_Strong
11141                                           : Runtime::kShiftRightLogical;
11142         break;
11143       case Token::SHL:
11144         function_id = is_strong(strength) ? Runtime::kShiftLeft_Strong
11145                                           : Runtime::kShiftLeft;
11146         break;
11147     }
11148     Add<HPushArguments>(left, right);
11149     instr = AddUncasted<HCallRuntime>(Runtime::FunctionForId(function_id), 2);
11150   } else {
11151     if (is_strong(strength) && Token::IsBitOp(op)) {
11152       // TODO(conradw): This is not efficient, but is necessary to prevent
11153       // conversion of oddball values to numbers in strong mode. It would be
11154       // better to prevent the conversion rather than adding a runtime check.
11155       IfBuilder if_builder(this);
11156       if_builder.If<HHasInstanceTypeAndBranch>(left, ODDBALL_TYPE);
11157       if_builder.OrIf<HHasInstanceTypeAndBranch>(right, ODDBALL_TYPE);
11158       if_builder.Then();
11159       Add<HCallRuntime>(
11160           Runtime::FunctionForId(Runtime::kThrowStrongModeImplicitConversion),
11161           0);
11162       if (!graph()->info()->IsStub()) {
11163         Add<HSimulate>(opt_id, REMOVABLE_SIMULATE);
11164       }
11165       if_builder.End();
11166     }
11167     switch (op) {
11168       case Token::ADD:
11169         instr = AddUncasted<HAdd>(left, right, strength);
11170         break;
11171       case Token::SUB:
11172         instr = AddUncasted<HSub>(left, right, strength);
11173         break;
11174       case Token::MUL:
11175         instr = AddUncasted<HMul>(left, right, strength);
11176         break;
11177       case Token::MOD: {
11178         if (fixed_right_arg.IsJust() &&
11179             !right->EqualsInteger32Constant(fixed_right_arg.FromJust())) {
11180           HConstant* fixed_right =
11181               Add<HConstant>(static_cast<int>(fixed_right_arg.FromJust()));
11182           IfBuilder if_same(this);
11183           if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ);
11184           if_same.Then();
11185           if_same.ElseDeopt(Deoptimizer::kUnexpectedRHSOfBinaryOperation);
11186           right = fixed_right;
11187         }
11188         instr = AddUncasted<HMod>(left, right, strength);
11189         break;
11190       }
11191       case Token::DIV:
11192         instr = AddUncasted<HDiv>(left, right, strength);
11193         break;
11194       case Token::BIT_XOR:
11195       case Token::BIT_AND:
11196         instr = AddUncasted<HBitwise>(op, left, right, strength);
11197         break;
11198       case Token::BIT_OR: {
11199         HValue *operand, *shift_amount;
11200         if (left_type->Is(Type::Signed32()) &&
11201             right_type->Is(Type::Signed32()) &&
11202             MatchRotateRight(left, right, &operand, &shift_amount)) {
11203           instr = AddUncasted<HRor>(operand, shift_amount, strength);
11204         } else {
11205           instr = AddUncasted<HBitwise>(op, left, right, strength);
11206         }
11207         break;
11208       }
11209       case Token::SAR:
11210         instr = AddUncasted<HSar>(left, right, strength);
11211         break;
11212       case Token::SHR:
11213         instr = AddUncasted<HShr>(left, right, strength);
11214         if (instr->IsShr() && CanBeZero(right)) {
11215           graph()->RecordUint32Instruction(instr);
11216         }
11217         break;
11218       case Token::SHL:
11219         instr = AddUncasted<HShl>(left, right, strength);
11220         break;
11221       default:
11222         UNREACHABLE();
11223     }
11224   }
11225
11226   if (instr->IsBinaryOperation()) {
11227     HBinaryOperation* binop = HBinaryOperation::cast(instr);
11228     binop->set_observed_input_representation(1, left_rep);
11229     binop->set_observed_input_representation(2, right_rep);
11230     binop->initialize_output_representation(result_rep);
11231     if (graph()->info()->IsStub()) {
11232       // Stub should not call into stub.
11233       instr->SetFlag(HValue::kCannotBeTagged);
11234       // And should truncate on HForceRepresentation already.
11235       if (left->IsForceRepresentation()) {
11236         left->CopyFlag(HValue::kTruncatingToSmi, instr);
11237         left->CopyFlag(HValue::kTruncatingToInt32, instr);
11238       }
11239       if (right->IsForceRepresentation()) {
11240         right->CopyFlag(HValue::kTruncatingToSmi, instr);
11241         right->CopyFlag(HValue::kTruncatingToInt32, instr);
11242       }
11243     }
11244   }
11245   return instr;
11246 }
11247
11248
11249 // Check for the form (%_ClassOf(foo) === 'BarClass').
11250 static bool IsClassOfTest(CompareOperation* expr) {
11251   if (expr->op() != Token::EQ_STRICT) return false;
11252   CallRuntime* call = expr->left()->AsCallRuntime();
11253   if (call == NULL) return false;
11254   Literal* literal = expr->right()->AsLiteral();
11255   if (literal == NULL) return false;
11256   if (!literal->value()->IsString()) return false;
11257   if (!call->is_jsruntime() &&
11258       call->function()->function_id != Runtime::kInlineClassOf) {
11259     return false;
11260   }
11261   DCHECK(call->arguments()->length() == 1);
11262   return true;
11263 }
11264
11265
11266 void HOptimizedGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
11267   DCHECK(!HasStackOverflow());
11268   DCHECK(current_block() != NULL);
11269   DCHECK(current_block()->HasPredecessor());
11270   switch (expr->op()) {
11271     case Token::COMMA:
11272       return VisitComma(expr);
11273     case Token::OR:
11274     case Token::AND:
11275       return VisitLogicalExpression(expr);
11276     default:
11277       return VisitArithmeticExpression(expr);
11278   }
11279 }
11280
11281
11282 void HOptimizedGraphBuilder::VisitComma(BinaryOperation* expr) {
11283   CHECK_ALIVE(VisitForEffect(expr->left()));
11284   // Visit the right subexpression in the same AST context as the entire
11285   // expression.
11286   Visit(expr->right());
11287 }
11288
11289
11290 void HOptimizedGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
11291   bool is_logical_and = expr->op() == Token::AND;
11292   if (ast_context()->IsTest()) {
11293     TestContext* context = TestContext::cast(ast_context());
11294     // Translate left subexpression.
11295     HBasicBlock* eval_right = graph()->CreateBasicBlock();
11296     if (is_logical_and) {
11297       CHECK_BAILOUT(VisitForControl(expr->left(),
11298                                     eval_right,
11299                                     context->if_false()));
11300     } else {
11301       CHECK_BAILOUT(VisitForControl(expr->left(),
11302                                     context->if_true(),
11303                                     eval_right));
11304     }
11305
11306     // Translate right subexpression by visiting it in the same AST
11307     // context as the entire expression.
11308     if (eval_right->HasPredecessor()) {
11309       eval_right->SetJoinId(expr->RightId());
11310       set_current_block(eval_right);
11311       Visit(expr->right());
11312     }
11313
11314   } else if (ast_context()->IsValue()) {
11315     CHECK_ALIVE(VisitForValue(expr->left()));
11316     DCHECK(current_block() != NULL);
11317     HValue* left_value = Top();
11318
11319     // Short-circuit left values that always evaluate to the same boolean value.
11320     if (expr->left()->ToBooleanIsTrue() || expr->left()->ToBooleanIsFalse()) {
11321       // l (evals true)  && r -> r
11322       // l (evals true)  || r -> l
11323       // l (evals false) && r -> l
11324       // l (evals false) || r -> r
11325       if (is_logical_and == expr->left()->ToBooleanIsTrue()) {
11326         Drop(1);
11327         CHECK_ALIVE(VisitForValue(expr->right()));
11328       }
11329       return ast_context()->ReturnValue(Pop());
11330     }
11331
11332     // We need an extra block to maintain edge-split form.
11333     HBasicBlock* empty_block = graph()->CreateBasicBlock();
11334     HBasicBlock* eval_right = graph()->CreateBasicBlock();
11335     ToBooleanStub::Types expected(expr->left()->to_boolean_types());
11336     HBranch* test = is_logical_and
11337         ? New<HBranch>(left_value, expected, eval_right, empty_block)
11338         : New<HBranch>(left_value, expected, empty_block, eval_right);
11339     FinishCurrentBlock(test);
11340
11341     set_current_block(eval_right);
11342     Drop(1);  // Value of the left subexpression.
11343     CHECK_BAILOUT(VisitForValue(expr->right()));
11344
11345     HBasicBlock* join_block =
11346       CreateJoin(empty_block, current_block(), expr->id());
11347     set_current_block(join_block);
11348     return ast_context()->ReturnValue(Pop());
11349
11350   } else {
11351     DCHECK(ast_context()->IsEffect());
11352     // In an effect context, we don't need the value of the left subexpression,
11353     // only its control flow and side effects.  We need an extra block to
11354     // maintain edge-split form.
11355     HBasicBlock* empty_block = graph()->CreateBasicBlock();
11356     HBasicBlock* right_block = graph()->CreateBasicBlock();
11357     if (is_logical_and) {
11358       CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
11359     } else {
11360       CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
11361     }
11362
11363     // TODO(kmillikin): Find a way to fix this.  It's ugly that there are
11364     // actually two empty blocks (one here and one inserted by
11365     // TestContext::BuildBranch, and that they both have an HSimulate though the
11366     // second one is not a merge node, and that we really have no good AST ID to
11367     // put on that first HSimulate.
11368
11369     if (empty_block->HasPredecessor()) {
11370       empty_block->SetJoinId(expr->id());
11371     } else {
11372       empty_block = NULL;
11373     }
11374
11375     if (right_block->HasPredecessor()) {
11376       right_block->SetJoinId(expr->RightId());
11377       set_current_block(right_block);
11378       CHECK_BAILOUT(VisitForEffect(expr->right()));
11379       right_block = current_block();
11380     } else {
11381       right_block = NULL;
11382     }
11383
11384     HBasicBlock* join_block =
11385       CreateJoin(empty_block, right_block, expr->id());
11386     set_current_block(join_block);
11387     // We did not materialize any value in the predecessor environments,
11388     // so there is no need to handle it here.
11389   }
11390 }
11391
11392
11393 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
11394   CHECK_ALIVE(VisitForValue(expr->left()));
11395   CHECK_ALIVE(VisitForValue(expr->right()));
11396   SetSourcePosition(expr->position());
11397   HValue* right = Pop();
11398   HValue* left = Pop();
11399   HValue* result =
11400       BuildBinaryOperation(expr, left, right,
11401           ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
11402                                     : PUSH_BEFORE_SIMULATE);
11403   if (top_info()->is_tracking_positions() && result->IsBinaryOperation()) {
11404     HBinaryOperation::cast(result)->SetOperandPositions(
11405         zone(),
11406         ScriptPositionToSourcePosition(expr->left()->position()),
11407         ScriptPositionToSourcePosition(expr->right()->position()));
11408   }
11409   return ast_context()->ReturnValue(result);
11410 }
11411
11412
11413 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
11414                                                         Expression* sub_expr,
11415                                                         Handle<String> check) {
11416   CHECK_ALIVE(VisitForTypeOf(sub_expr));
11417   SetSourcePosition(expr->position());
11418   HValue* value = Pop();
11419   HTypeofIsAndBranch* instr = New<HTypeofIsAndBranch>(value, check);
11420   return ast_context()->ReturnControl(instr, expr->id());
11421 }
11422
11423
11424 static bool IsLiteralCompareBool(Isolate* isolate,
11425                                  HValue* left,
11426                                  Token::Value op,
11427                                  HValue* right) {
11428   return op == Token::EQ_STRICT &&
11429       ((left->IsConstant() &&
11430           HConstant::cast(left)->handle(isolate)->IsBoolean()) ||
11431        (right->IsConstant() &&
11432            HConstant::cast(right)->handle(isolate)->IsBoolean()));
11433 }
11434
11435
11436 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
11437   DCHECK(!HasStackOverflow());
11438   DCHECK(current_block() != NULL);
11439   DCHECK(current_block()->HasPredecessor());
11440
11441   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
11442
11443   // Check for a few fast cases. The AST visiting behavior must be in sync
11444   // with the full codegen: We don't push both left and right values onto
11445   // the expression stack when one side is a special-case literal.
11446   Expression* sub_expr = NULL;
11447   Handle<String> check;
11448   if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
11449     return HandleLiteralCompareTypeof(expr, sub_expr, check);
11450   }
11451   if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) {
11452     return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
11453   }
11454   if (expr->IsLiteralCompareNull(&sub_expr)) {
11455     return HandleLiteralCompareNil(expr, sub_expr, kNullValue);
11456   }
11457
11458   if (IsClassOfTest(expr)) {
11459     CallRuntime* call = expr->left()->AsCallRuntime();
11460     DCHECK(call->arguments()->length() == 1);
11461     CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
11462     HValue* value = Pop();
11463     Literal* literal = expr->right()->AsLiteral();
11464     Handle<String> rhs = Handle<String>::cast(literal->value());
11465     HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs);
11466     return ast_context()->ReturnControl(instr, expr->id());
11467   }
11468
11469   Type* left_type = expr->left()->bounds().lower;
11470   Type* right_type = expr->right()->bounds().lower;
11471   Type* combined_type = expr->combined_type();
11472
11473   CHECK_ALIVE(VisitForValue(expr->left()));
11474   CHECK_ALIVE(VisitForValue(expr->right()));
11475
11476   HValue* right = Pop();
11477   HValue* left = Pop();
11478   Token::Value op = expr->op();
11479
11480   if (IsLiteralCompareBool(isolate(), left, op, right)) {
11481     HCompareObjectEqAndBranch* result =
11482         New<HCompareObjectEqAndBranch>(left, right);
11483     return ast_context()->ReturnControl(result, expr->id());
11484   }
11485
11486   if (op == Token::INSTANCEOF) {
11487     // Check to see if the rhs of the instanceof is a known function.
11488     if (right->IsConstant() &&
11489         HConstant::cast(right)->handle(isolate())->IsJSFunction()) {
11490       Handle<JSFunction> constructor =
11491           Handle<JSFunction>::cast(HConstant::cast(right)->handle(isolate()));
11492       if (!constructor->map()->has_non_instance_prototype()) {
11493         JSFunction::EnsureHasInitialMap(constructor);
11494         DCHECK(constructor->has_initial_map());
11495         Handle<Map> initial_map(constructor->initial_map(), isolate());
11496         top_info()->dependencies()->AssumeInitialMapCantChange(initial_map);
11497         HInstruction* prototype =
11498             Add<HConstant>(handle(initial_map->prototype(), isolate()));
11499         HHasInPrototypeChainAndBranch* result =
11500             New<HHasInPrototypeChainAndBranch>(left, prototype);
11501         return ast_context()->ReturnControl(result, expr->id());
11502       }
11503     }
11504
11505     HInstanceOf* result = New<HInstanceOf>(left, right);
11506     return ast_context()->ReturnInstruction(result, expr->id());
11507
11508   } else if (op == Token::IN) {
11509     Add<HPushArguments>(left, right);
11510     HInstruction* result =
11511         New<HCallRuntime>(Runtime::FunctionForId(Runtime::kHasProperty), 2);
11512     return ast_context()->ReturnInstruction(result, expr->id());
11513   }
11514
11515   PushBeforeSimulateBehavior push_behavior =
11516     ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
11517                               : PUSH_BEFORE_SIMULATE;
11518   HControlInstruction* compare = BuildCompareInstruction(
11519       op, left, right, left_type, right_type, combined_type,
11520       ScriptPositionToSourcePosition(expr->left()->position()),
11521       ScriptPositionToSourcePosition(expr->right()->position()),
11522       push_behavior, expr->id());
11523   if (compare == NULL) return;  // Bailed out.
11524   return ast_context()->ReturnControl(compare, expr->id());
11525 }
11526
11527
11528 HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
11529     Token::Value op, HValue* left, HValue* right, Type* left_type,
11530     Type* right_type, Type* combined_type, SourcePosition left_position,
11531     SourcePosition right_position, PushBeforeSimulateBehavior push_sim_result,
11532     BailoutId bailout_id) {
11533   // Cases handled below depend on collected type feedback. They should
11534   // soft deoptimize when there is no type feedback.
11535   if (!combined_type->IsInhabited()) {
11536     Add<HDeoptimize>(
11537         Deoptimizer::kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation,
11538         Deoptimizer::SOFT);
11539     combined_type = left_type = right_type = Type::Any(zone());
11540   }
11541
11542   Representation left_rep = RepresentationFor(left_type);
11543   Representation right_rep = RepresentationFor(right_type);
11544   Representation combined_rep = RepresentationFor(combined_type);
11545
11546   if (combined_type->Is(Type::Receiver())) {
11547     if (Token::IsEqualityOp(op)) {
11548       // HCompareObjectEqAndBranch can only deal with object, so
11549       // exclude numbers.
11550       if ((left->IsConstant() &&
11551            HConstant::cast(left)->HasNumberValue()) ||
11552           (right->IsConstant() &&
11553            HConstant::cast(right)->HasNumberValue())) {
11554         Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant,
11555                          Deoptimizer::SOFT);
11556         // The caller expects a branch instruction, so make it happy.
11557         return New<HBranch>(graph()->GetConstantTrue());
11558       }
11559       // Can we get away with map check and not instance type check?
11560       HValue* operand_to_check =
11561           left->block()->block_id() < right->block()->block_id() ? left : right;
11562       if (combined_type->IsClass()) {
11563         Handle<Map> map = combined_type->AsClass()->Map();
11564         AddCheckMap(operand_to_check, map);
11565         HCompareObjectEqAndBranch* result =
11566             New<HCompareObjectEqAndBranch>(left, right);
11567         if (top_info()->is_tracking_positions()) {
11568           result->set_operand_position(zone(), 0, left_position);
11569           result->set_operand_position(zone(), 1, right_position);
11570         }
11571         return result;
11572       } else {
11573         BuildCheckHeapObject(operand_to_check);
11574         Add<HCheckInstanceType>(operand_to_check,
11575                                 HCheckInstanceType::IS_SPEC_OBJECT);
11576         HCompareObjectEqAndBranch* result =
11577             New<HCompareObjectEqAndBranch>(left, right);
11578         return result;
11579       }
11580     } else {
11581       if (combined_type->IsClass()) {
11582         // TODO(bmeurer): This is an optimized version of an x < y, x > y,
11583         // x <= y or x >= y, where both x and y are spec objects with the
11584         // same map. The CompareIC collects this map for us. So if we know
11585         // that there's no @@toPrimitive on the map (including the prototype
11586         // chain), and both valueOf and toString are the default initial
11587         // implementations (on the %ObjectPrototype%), then we can reduce
11588         // the comparison to map checks on x and y, because the comparison
11589         // will turn into a comparison of "[object CLASS]" to itself (the
11590         // default outcome of toString, since valueOf returns a spec object).
11591         // This is pretty much adhoc, so in TurboFan we could do a lot better
11592         // and inline the interesting parts of ToPrimitive (actually we could
11593         // even do that in Crankshaft but we don't want to waste too much
11594         // time on this now).
11595         DCHECK(Token::IsOrderedRelationalCompareOp(op));
11596         Handle<Map> map = combined_type->AsClass()->Map();
11597         PropertyAccessInfo value_of(this, LOAD, map,
11598                                     isolate()->factory()->valueOf_string());
11599         PropertyAccessInfo to_primitive(
11600             this, LOAD, map, isolate()->factory()->to_primitive_symbol());
11601         PropertyAccessInfo to_string(this, LOAD, map,
11602                                      isolate()->factory()->toString_string());
11603         if (to_primitive.CanAccessMonomorphic() && !to_primitive.IsFound() &&
11604             value_of.CanAccessMonomorphic() && value_of.IsDataConstant() &&
11605             value_of.constant().is_identical_to(isolate()->object_value_of()) &&
11606             to_string.CanAccessMonomorphic() && to_string.IsDataConstant() &&
11607             to_string.constant().is_identical_to(
11608                 isolate()->object_to_string())) {
11609           // We depend on the prototype chain to stay the same, because we
11610           // also need to deoptimize when someone installs @@toPrimitive
11611           // somewhere in the prototype chain.
11612           BuildCheckPrototypeMaps(handle(JSObject::cast(map->prototype())),
11613                                   Handle<JSObject>::null());
11614           AddCheckMap(left, map);
11615           AddCheckMap(right, map);
11616           // The caller expects a branch instruction, so make it happy.
11617           return New<HBranch>(
11618               graph()->GetConstantBool(op == Token::LTE || op == Token::GTE));
11619         }
11620       }
11621       Bailout(kUnsupportedNonPrimitiveCompare);
11622       return NULL;
11623     }
11624   } else if (combined_type->Is(Type::InternalizedString()) &&
11625              Token::IsEqualityOp(op)) {
11626     // If we have a constant argument, it should be consistent with the type
11627     // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch).
11628     if ((left->IsConstant() &&
11629          !HConstant::cast(left)->HasInternalizedStringValue()) ||
11630         (right->IsConstant() &&
11631          !HConstant::cast(right)->HasInternalizedStringValue())) {
11632       Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant,
11633                        Deoptimizer::SOFT);
11634       // The caller expects a branch instruction, so make it happy.
11635       return New<HBranch>(graph()->GetConstantTrue());
11636     }
11637     BuildCheckHeapObject(left);
11638     Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING);
11639     BuildCheckHeapObject(right);
11640     Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING);
11641     HCompareObjectEqAndBranch* result =
11642         New<HCompareObjectEqAndBranch>(left, right);
11643     return result;
11644   } else if (combined_type->Is(Type::String())) {
11645     BuildCheckHeapObject(left);
11646     Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING);
11647     BuildCheckHeapObject(right);
11648     Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING);
11649     HStringCompareAndBranch* result =
11650         New<HStringCompareAndBranch>(left, right, op);
11651     return result;
11652   } else {
11653     if (combined_rep.IsTagged() || combined_rep.IsNone()) {
11654       HCompareGeneric* result = Add<HCompareGeneric>(
11655           left, right, op, strength(function_language_mode()));
11656       result->set_observed_input_representation(1, left_rep);
11657       result->set_observed_input_representation(2, right_rep);
11658       if (result->HasObservableSideEffects()) {
11659         if (push_sim_result == PUSH_BEFORE_SIMULATE) {
11660           Push(result);
11661           AddSimulate(bailout_id, REMOVABLE_SIMULATE);
11662           Drop(1);
11663         } else {
11664           AddSimulate(bailout_id, REMOVABLE_SIMULATE);
11665         }
11666       }
11667       // TODO(jkummerow): Can we make this more efficient?
11668       HBranch* branch = New<HBranch>(result);
11669       return branch;
11670     } else {
11671       HCompareNumericAndBranch* result = New<HCompareNumericAndBranch>(
11672           left, right, op, strength(function_language_mode()));
11673       result->set_observed_input_representation(left_rep, right_rep);
11674       if (top_info()->is_tracking_positions()) {
11675         result->SetOperandPositions(zone(), left_position, right_position);
11676       }
11677       return result;
11678     }
11679   }
11680 }
11681
11682
11683 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
11684                                                      Expression* sub_expr,
11685                                                      NilValue nil) {
11686   DCHECK(!HasStackOverflow());
11687   DCHECK(current_block() != NULL);
11688   DCHECK(current_block()->HasPredecessor());
11689   DCHECK(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
11690   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
11691   CHECK_ALIVE(VisitForValue(sub_expr));
11692   HValue* value = Pop();
11693   if (expr->op() == Token::EQ_STRICT) {
11694     HConstant* nil_constant = nil == kNullValue
11695         ? graph()->GetConstantNull()
11696         : graph()->GetConstantUndefined();
11697     HCompareObjectEqAndBranch* instr =
11698         New<HCompareObjectEqAndBranch>(value, nil_constant);
11699     return ast_context()->ReturnControl(instr, expr->id());
11700   } else {
11701     DCHECK_EQ(Token::EQ, expr->op());
11702     Type* type = expr->combined_type()->Is(Type::None())
11703         ? Type::Any(zone()) : expr->combined_type();
11704     HIfContinuation continuation;
11705     BuildCompareNil(value, type, &continuation);
11706     return ast_context()->ReturnContinuation(&continuation, expr->id());
11707   }
11708 }
11709
11710
11711 void HOptimizedGraphBuilder::VisitSpread(Spread* expr) { UNREACHABLE(); }
11712
11713
11714 void HOptimizedGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
11715   UNREACHABLE();
11716 }
11717
11718
11719 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
11720   // If we share optimized code between different closures, the
11721   // this-function is not a constant, except inside an inlined body.
11722   if (function_state()->outer() != NULL) {
11723       return New<HConstant>(
11724           function_state()->compilation_info()->closure());
11725   } else {
11726       return New<HThisFunction>();
11727   }
11728 }
11729
11730
11731 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
11732     Handle<JSObject> boilerplate_object,
11733     AllocationSiteUsageContext* site_context) {
11734   NoObservableSideEffectsScope no_effects(this);
11735   Handle<Map> initial_map(boilerplate_object->map());
11736   InstanceType instance_type = initial_map->instance_type();
11737   DCHECK(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE);
11738
11739   HType type = instance_type == JS_ARRAY_TYPE
11740       ? HType::JSArray() : HType::JSObject();
11741   HValue* object_size_constant = Add<HConstant>(initial_map->instance_size());
11742
11743   PretenureFlag pretenure_flag = NOT_TENURED;
11744   Handle<AllocationSite> top_site(*site_context->top(), isolate());
11745   if (FLAG_allocation_site_pretenuring) {
11746     pretenure_flag = top_site->GetPretenureMode();
11747   }
11748
11749   Handle<AllocationSite> current_site(*site_context->current(), isolate());
11750   if (*top_site == *current_site) {
11751     // We install a dependency for pretenuring only on the outermost literal.
11752     top_info()->dependencies()->AssumeTenuringDecision(top_site);
11753   }
11754   top_info()->dependencies()->AssumeTransitionStable(current_site);
11755
11756   HInstruction* object = Add<HAllocate>(
11757       object_size_constant, type, pretenure_flag, instance_type, top_site);
11758
11759   // If allocation folding reaches Page::kMaxRegularHeapObjectSize the
11760   // elements array may not get folded into the object. Hence, we set the
11761   // elements pointer to empty fixed array and let store elimination remove
11762   // this store in the folding case.
11763   HConstant* empty_fixed_array = Add<HConstant>(
11764       isolate()->factory()->empty_fixed_array());
11765   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
11766       empty_fixed_array);
11767
11768   BuildEmitObjectHeader(boilerplate_object, object);
11769
11770   // Similarly to the elements pointer, there is no guarantee that all
11771   // property allocations can get folded, so pre-initialize all in-object
11772   // properties to a safe value.
11773   BuildInitializeInobjectProperties(object, initial_map);
11774
11775   Handle<FixedArrayBase> elements(boilerplate_object->elements());
11776   int elements_size = (elements->length() > 0 &&
11777       elements->map() != isolate()->heap()->fixed_cow_array_map()) ?
11778           elements->Size() : 0;
11779
11780   if (pretenure_flag == TENURED &&
11781       elements->map() == isolate()->heap()->fixed_cow_array_map() &&
11782       isolate()->heap()->InNewSpace(*elements)) {
11783     // If we would like to pretenure a fixed cow array, we must ensure that the
11784     // array is already in old space, otherwise we'll create too many old-to-
11785     // new-space pointers (overflowing the store buffer).
11786     elements = Handle<FixedArrayBase>(
11787         isolate()->factory()->CopyAndTenureFixedCOWArray(
11788             Handle<FixedArray>::cast(elements)));
11789     boilerplate_object->set_elements(*elements);
11790   }
11791
11792   HInstruction* object_elements = NULL;
11793   if (elements_size > 0) {
11794     HValue* object_elements_size = Add<HConstant>(elements_size);
11795     InstanceType instance_type = boilerplate_object->HasFastDoubleElements()
11796         ? FIXED_DOUBLE_ARRAY_TYPE : FIXED_ARRAY_TYPE;
11797     object_elements = Add<HAllocate>(object_elements_size, HType::HeapObject(),
11798                                      pretenure_flag, instance_type, top_site);
11799     BuildEmitElements(boilerplate_object, elements, object_elements,
11800                       site_context);
11801     Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
11802                           object_elements);
11803   } else {
11804     Handle<Object> elements_field =
11805         Handle<Object>(boilerplate_object->elements(), isolate());
11806     HInstruction* object_elements_cow = Add<HConstant>(elements_field);
11807     Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
11808                           object_elements_cow);
11809   }
11810
11811   // Copy in-object properties.
11812   if (initial_map->NumberOfFields() != 0 ||
11813       initial_map->unused_property_fields() > 0) {
11814     BuildEmitInObjectProperties(boilerplate_object, object, site_context,
11815                                 pretenure_flag);
11816   }
11817   return object;
11818 }
11819
11820
11821 void HOptimizedGraphBuilder::BuildEmitObjectHeader(
11822     Handle<JSObject> boilerplate_object,
11823     HInstruction* object) {
11824   DCHECK(boilerplate_object->properties()->length() == 0);
11825
11826   Handle<Map> boilerplate_object_map(boilerplate_object->map());
11827   AddStoreMapConstant(object, boilerplate_object_map);
11828
11829   Handle<Object> properties_field =
11830       Handle<Object>(boilerplate_object->properties(), isolate());
11831   DCHECK(*properties_field == isolate()->heap()->empty_fixed_array());
11832   HInstruction* properties = Add<HConstant>(properties_field);
11833   HObjectAccess access = HObjectAccess::ForPropertiesPointer();
11834   Add<HStoreNamedField>(object, access, properties);
11835
11836   if (boilerplate_object->IsJSArray()) {
11837     Handle<JSArray> boilerplate_array =
11838         Handle<JSArray>::cast(boilerplate_object);
11839     Handle<Object> length_field =
11840         Handle<Object>(boilerplate_array->length(), isolate());
11841     HInstruction* length = Add<HConstant>(length_field);
11842
11843     DCHECK(boilerplate_array->length()->IsSmi());
11844     Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(
11845         boilerplate_array->GetElementsKind()), length);
11846   }
11847 }
11848
11849
11850 void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
11851     Handle<JSObject> boilerplate_object,
11852     HInstruction* object,
11853     AllocationSiteUsageContext* site_context,
11854     PretenureFlag pretenure_flag) {
11855   Handle<Map> boilerplate_map(boilerplate_object->map());
11856   Handle<DescriptorArray> descriptors(boilerplate_map->instance_descriptors());
11857   int limit = boilerplate_map->NumberOfOwnDescriptors();
11858
11859   int copied_fields = 0;
11860   for (int i = 0; i < limit; i++) {
11861     PropertyDetails details = descriptors->GetDetails(i);
11862     if (details.type() != DATA) continue;
11863     copied_fields++;
11864     FieldIndex field_index = FieldIndex::ForDescriptor(*boilerplate_map, i);
11865
11866
11867     int property_offset = field_index.offset();
11868     Handle<Name> name(descriptors->GetKey(i));
11869
11870     // The access for the store depends on the type of the boilerplate.
11871     HObjectAccess access = boilerplate_object->IsJSArray() ?
11872         HObjectAccess::ForJSArrayOffset(property_offset) :
11873         HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
11874
11875     if (boilerplate_object->IsUnboxedDoubleField(field_index)) {
11876       CHECK(!boilerplate_object->IsJSArray());
11877       double value = boilerplate_object->RawFastDoublePropertyAt(field_index);
11878       access = access.WithRepresentation(Representation::Double());
11879       Add<HStoreNamedField>(object, access, Add<HConstant>(value));
11880       continue;
11881     }
11882     Handle<Object> value(boilerplate_object->RawFastPropertyAt(field_index),
11883                          isolate());
11884
11885     if (value->IsJSObject()) {
11886       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
11887       Handle<AllocationSite> current_site = site_context->EnterNewScope();
11888       HInstruction* result =
11889           BuildFastLiteral(value_object, site_context);
11890       site_context->ExitScope(current_site, value_object);
11891       Add<HStoreNamedField>(object, access, result);
11892     } else {
11893       Representation representation = details.representation();
11894       HInstruction* value_instruction;
11895
11896       if (representation.IsDouble()) {
11897         // Allocate a HeapNumber box and store the value into it.
11898         HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize);
11899         HInstruction* double_box =
11900             Add<HAllocate>(heap_number_constant, HType::HeapObject(),
11901                 pretenure_flag, MUTABLE_HEAP_NUMBER_TYPE);
11902         AddStoreMapConstant(double_box,
11903             isolate()->factory()->mutable_heap_number_map());
11904         // Unwrap the mutable heap number from the boilerplate.
11905         HValue* double_value =
11906             Add<HConstant>(Handle<HeapNumber>::cast(value)->value());
11907         Add<HStoreNamedField>(
11908             double_box, HObjectAccess::ForHeapNumberValue(), double_value);
11909         value_instruction = double_box;
11910       } else if (representation.IsSmi()) {
11911         value_instruction = value->IsUninitialized()
11912             ? graph()->GetConstant0()
11913             : Add<HConstant>(value);
11914         // Ensure that value is stored as smi.
11915         access = access.WithRepresentation(representation);
11916       } else {
11917         value_instruction = Add<HConstant>(value);
11918       }
11919
11920       Add<HStoreNamedField>(object, access, value_instruction);
11921     }
11922   }
11923
11924   int inobject_properties = boilerplate_object->map()->GetInObjectProperties();
11925   HInstruction* value_instruction =
11926       Add<HConstant>(isolate()->factory()->one_pointer_filler_map());
11927   for (int i = copied_fields; i < inobject_properties; i++) {
11928     DCHECK(boilerplate_object->IsJSObject());
11929     int property_offset = boilerplate_object->GetInObjectPropertyOffset(i);
11930     HObjectAccess access =
11931         HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
11932     Add<HStoreNamedField>(object, access, value_instruction);
11933   }
11934 }
11935
11936
11937 void HOptimizedGraphBuilder::BuildEmitElements(
11938     Handle<JSObject> boilerplate_object,
11939     Handle<FixedArrayBase> elements,
11940     HValue* object_elements,
11941     AllocationSiteUsageContext* site_context) {
11942   ElementsKind kind = boilerplate_object->map()->elements_kind();
11943   int elements_length = elements->length();
11944   HValue* object_elements_length = Add<HConstant>(elements_length);
11945   BuildInitializeElementsHeader(object_elements, kind, object_elements_length);
11946
11947   // Copy elements backing store content.
11948   if (elements->IsFixedDoubleArray()) {
11949     BuildEmitFixedDoubleArray(elements, kind, object_elements);
11950   } else if (elements->IsFixedArray()) {
11951     BuildEmitFixedArray(elements, kind, object_elements,
11952                         site_context);
11953   } else {
11954     UNREACHABLE();
11955   }
11956 }
11957
11958
11959 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray(
11960     Handle<FixedArrayBase> elements,
11961     ElementsKind kind,
11962     HValue* object_elements) {
11963   HInstruction* boilerplate_elements = Add<HConstant>(elements);
11964   int elements_length = elements->length();
11965   for (int i = 0; i < elements_length; i++) {
11966     HValue* key_constant = Add<HConstant>(i);
11967     HInstruction* value_instruction = Add<HLoadKeyed>(
11968         boilerplate_elements, key_constant, nullptr, kind, ALLOW_RETURN_HOLE);
11969     HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant,
11970                                            value_instruction, kind);
11971     store->SetFlag(HValue::kAllowUndefinedAsNaN);
11972   }
11973 }
11974
11975
11976 void HOptimizedGraphBuilder::BuildEmitFixedArray(
11977     Handle<FixedArrayBase> elements,
11978     ElementsKind kind,
11979     HValue* object_elements,
11980     AllocationSiteUsageContext* site_context) {
11981   HInstruction* boilerplate_elements = Add<HConstant>(elements);
11982   int elements_length = elements->length();
11983   Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
11984   for (int i = 0; i < elements_length; i++) {
11985     Handle<Object> value(fast_elements->get(i), isolate());
11986     HValue* key_constant = Add<HConstant>(i);
11987     if (value->IsJSObject()) {
11988       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
11989       Handle<AllocationSite> current_site = site_context->EnterNewScope();
11990       HInstruction* result =
11991           BuildFastLiteral(value_object, site_context);
11992       site_context->ExitScope(current_site, value_object);
11993       Add<HStoreKeyed>(object_elements, key_constant, result, kind);
11994     } else {
11995       ElementsKind copy_kind =
11996           kind == FAST_HOLEY_SMI_ELEMENTS ? FAST_HOLEY_ELEMENTS : kind;
11997       HInstruction* value_instruction =
11998           Add<HLoadKeyed>(boilerplate_elements, key_constant, nullptr,
11999                           copy_kind, ALLOW_RETURN_HOLE);
12000       Add<HStoreKeyed>(object_elements, key_constant, value_instruction,
12001                        copy_kind);
12002     }
12003   }
12004 }
12005
12006
12007 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
12008   DCHECK(!HasStackOverflow());
12009   DCHECK(current_block() != NULL);
12010   DCHECK(current_block()->HasPredecessor());
12011   HInstruction* instr = BuildThisFunction();
12012   return ast_context()->ReturnInstruction(instr, expr->id());
12013 }
12014
12015
12016 void HOptimizedGraphBuilder::VisitSuperPropertyReference(
12017     SuperPropertyReference* expr) {
12018   DCHECK(!HasStackOverflow());
12019   DCHECK(current_block() != NULL);
12020   DCHECK(current_block()->HasPredecessor());
12021   return Bailout(kSuperReference);
12022 }
12023
12024
12025 void HOptimizedGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
12026   DCHECK(!HasStackOverflow());
12027   DCHECK(current_block() != NULL);
12028   DCHECK(current_block()->HasPredecessor());
12029   return Bailout(kSuperReference);
12030 }
12031
12032
12033 void HOptimizedGraphBuilder::VisitDeclarations(
12034     ZoneList<Declaration*>* declarations) {
12035   DCHECK(globals_.is_empty());
12036   AstVisitor::VisitDeclarations(declarations);
12037   if (!globals_.is_empty()) {
12038     Handle<FixedArray> array =
12039        isolate()->factory()->NewFixedArray(globals_.length(), TENURED);
12040     for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i));
12041     int flags =
12042         DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) |
12043         DeclareGlobalsNativeFlag::encode(current_info()->is_native()) |
12044         DeclareGlobalsLanguageMode::encode(current_info()->language_mode());
12045     Add<HDeclareGlobals>(array, flags);
12046     globals_.Rewind(0);
12047   }
12048 }
12049
12050
12051 void HOptimizedGraphBuilder::VisitVariableDeclaration(
12052     VariableDeclaration* declaration) {
12053   VariableProxy* proxy = declaration->proxy();
12054   VariableMode mode = declaration->mode();
12055   Variable* variable = proxy->var();
12056   bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
12057   switch (variable->location()) {
12058     case VariableLocation::GLOBAL:
12059     case VariableLocation::UNALLOCATED:
12060       globals_.Add(variable->name(), zone());
12061       globals_.Add(variable->binding_needs_init()
12062                        ? isolate()->factory()->the_hole_value()
12063                        : isolate()->factory()->undefined_value(), zone());
12064       return;
12065     case VariableLocation::PARAMETER:
12066     case VariableLocation::LOCAL:
12067       if (hole_init) {
12068         HValue* value = graph()->GetConstantHole();
12069         environment()->Bind(variable, value);
12070       }
12071       break;
12072     case VariableLocation::CONTEXT:
12073       if (hole_init) {
12074         HValue* value = graph()->GetConstantHole();
12075         HValue* context = environment()->context();
12076         HStoreContextSlot* store = Add<HStoreContextSlot>(
12077             context, variable->index(), HStoreContextSlot::kNoCheck, value);
12078         if (store->HasObservableSideEffects()) {
12079           Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
12080         }
12081       }
12082       break;
12083     case VariableLocation::LOOKUP:
12084       return Bailout(kUnsupportedLookupSlotInDeclaration);
12085   }
12086 }
12087
12088
12089 void HOptimizedGraphBuilder::VisitFunctionDeclaration(
12090     FunctionDeclaration* declaration) {
12091   VariableProxy* proxy = declaration->proxy();
12092   Variable* variable = proxy->var();
12093   switch (variable->location()) {
12094     case VariableLocation::GLOBAL:
12095     case VariableLocation::UNALLOCATED: {
12096       globals_.Add(variable->name(), zone());
12097       Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
12098           declaration->fun(), current_info()->script(), top_info());
12099       // Check for stack-overflow exception.
12100       if (function.is_null()) return SetStackOverflow();
12101       globals_.Add(function, zone());
12102       return;
12103     }
12104     case VariableLocation::PARAMETER:
12105     case VariableLocation::LOCAL: {
12106       CHECK_ALIVE(VisitForValue(declaration->fun()));
12107       HValue* value = Pop();
12108       BindIfLive(variable, value);
12109       break;
12110     }
12111     case VariableLocation::CONTEXT: {
12112       CHECK_ALIVE(VisitForValue(declaration->fun()));
12113       HValue* value = Pop();
12114       HValue* context = environment()->context();
12115       HStoreContextSlot* store = Add<HStoreContextSlot>(
12116           context, variable->index(), HStoreContextSlot::kNoCheck, value);
12117       if (store->HasObservableSideEffects()) {
12118         Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
12119       }
12120       break;
12121     }
12122     case VariableLocation::LOOKUP:
12123       return Bailout(kUnsupportedLookupSlotInDeclaration);
12124   }
12125 }
12126
12127
12128 void HOptimizedGraphBuilder::VisitImportDeclaration(
12129     ImportDeclaration* declaration) {
12130   UNREACHABLE();
12131 }
12132
12133
12134 void HOptimizedGraphBuilder::VisitExportDeclaration(
12135     ExportDeclaration* declaration) {
12136   UNREACHABLE();
12137 }
12138
12139
12140 // Generators for inline runtime functions.
12141 // Support for types.
12142 void HOptimizedGraphBuilder::GenerateIsSmi(CallRuntime* call) {
12143   DCHECK(call->arguments()->length() == 1);
12144   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12145   HValue* value = Pop();
12146   HIsSmiAndBranch* result = New<HIsSmiAndBranch>(value);
12147   return ast_context()->ReturnControl(result, call->id());
12148 }
12149
12150
12151 void HOptimizedGraphBuilder::GenerateIsSpecObject(CallRuntime* call) {
12152   DCHECK(call->arguments()->length() == 1);
12153   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12154   HValue* value = Pop();
12155   HHasInstanceTypeAndBranch* result =
12156       New<HHasInstanceTypeAndBranch>(value,
12157                                      FIRST_SPEC_OBJECT_TYPE,
12158                                      LAST_SPEC_OBJECT_TYPE);
12159   return ast_context()->ReturnControl(result, call->id());
12160 }
12161
12162
12163 void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) {
12164   DCHECK(call->arguments()->length() == 1);
12165   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12166   HValue* value = Pop();
12167   HHasInstanceTypeAndBranch* result =
12168       New<HHasInstanceTypeAndBranch>(value, JS_FUNCTION_TYPE);
12169   return ast_context()->ReturnControl(result, call->id());
12170 }
12171
12172
12173 void HOptimizedGraphBuilder::GenerateIsMinusZero(CallRuntime* call) {
12174   DCHECK(call->arguments()->length() == 1);
12175   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12176   HValue* value = Pop();
12177   HCompareMinusZeroAndBranch* result = New<HCompareMinusZeroAndBranch>(value);
12178   return ast_context()->ReturnControl(result, call->id());
12179 }
12180
12181
12182 void HOptimizedGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
12183   DCHECK(call->arguments()->length() == 1);
12184   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12185   HValue* value = Pop();
12186   HHasCachedArrayIndexAndBranch* result =
12187       New<HHasCachedArrayIndexAndBranch>(value);
12188   return ast_context()->ReturnControl(result, call->id());
12189 }
12190
12191
12192 void HOptimizedGraphBuilder::GenerateIsArray(CallRuntime* call) {
12193   DCHECK(call->arguments()->length() == 1);
12194   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12195   HValue* value = Pop();
12196   HHasInstanceTypeAndBranch* result =
12197       New<HHasInstanceTypeAndBranch>(value, JS_ARRAY_TYPE);
12198   return ast_context()->ReturnControl(result, call->id());
12199 }
12200
12201
12202 void HOptimizedGraphBuilder::GenerateIsTypedArray(CallRuntime* call) {
12203   DCHECK(call->arguments()->length() == 1);
12204   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12205   HValue* value = Pop();
12206   HHasInstanceTypeAndBranch* result =
12207       New<HHasInstanceTypeAndBranch>(value, JS_TYPED_ARRAY_TYPE);
12208   return ast_context()->ReturnControl(result, call->id());
12209 }
12210
12211
12212 void HOptimizedGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
12213   DCHECK(call->arguments()->length() == 1);
12214   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12215   HValue* value = Pop();
12216   HHasInstanceTypeAndBranch* result =
12217       New<HHasInstanceTypeAndBranch>(value, JS_REGEXP_TYPE);
12218   return ast_context()->ReturnControl(result, call->id());
12219 }
12220
12221
12222 void HOptimizedGraphBuilder::GenerateToObject(CallRuntime* call) {
12223   DCHECK_EQ(1, call->arguments()->length());
12224   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12225   HValue* value = Pop();
12226   HValue* result = BuildToObject(value);
12227   return ast_context()->ReturnValue(result);
12228 }
12229
12230
12231 void HOptimizedGraphBuilder::GenerateIsJSProxy(CallRuntime* call) {
12232   DCHECK(call->arguments()->length() == 1);
12233   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12234   HValue* value = Pop();
12235   HIfContinuation continuation;
12236   IfBuilder if_proxy(this);
12237
12238   HValue* smicheck = if_proxy.IfNot<HIsSmiAndBranch>(value);
12239   if_proxy.And();
12240   HValue* map = Add<HLoadNamedField>(value, smicheck, HObjectAccess::ForMap());
12241   HValue* instance_type =
12242       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
12243   if_proxy.If<HCompareNumericAndBranch>(
12244       instance_type, Add<HConstant>(FIRST_JS_PROXY_TYPE), Token::GTE);
12245   if_proxy.And();
12246   if_proxy.If<HCompareNumericAndBranch>(
12247       instance_type, Add<HConstant>(LAST_JS_PROXY_TYPE), Token::LTE);
12248
12249   if_proxy.CaptureContinuation(&continuation);
12250   return ast_context()->ReturnContinuation(&continuation, call->id());
12251 }
12252
12253
12254 void HOptimizedGraphBuilder::GenerateHasFastPackedElements(CallRuntime* call) {
12255   DCHECK(call->arguments()->length() == 1);
12256   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12257   HValue* object = Pop();
12258   HIfContinuation continuation(graph()->CreateBasicBlock(),
12259                                graph()->CreateBasicBlock());
12260   IfBuilder if_not_smi(this);
12261   if_not_smi.IfNot<HIsSmiAndBranch>(object);
12262   if_not_smi.Then();
12263   {
12264     NoObservableSideEffectsScope no_effects(this);
12265
12266     IfBuilder if_fast_packed(this);
12267     HValue* elements_kind = BuildGetElementsKind(object);
12268     if_fast_packed.If<HCompareNumericAndBranch>(
12269         elements_kind, Add<HConstant>(FAST_SMI_ELEMENTS), Token::EQ);
12270     if_fast_packed.Or();
12271     if_fast_packed.If<HCompareNumericAndBranch>(
12272         elements_kind, Add<HConstant>(FAST_ELEMENTS), Token::EQ);
12273     if_fast_packed.Or();
12274     if_fast_packed.If<HCompareNumericAndBranch>(
12275         elements_kind, Add<HConstant>(FAST_DOUBLE_ELEMENTS), Token::EQ);
12276     if_fast_packed.JoinContinuation(&continuation);
12277   }
12278   if_not_smi.JoinContinuation(&continuation);
12279   return ast_context()->ReturnContinuation(&continuation, call->id());
12280 }
12281
12282
12283 // Support for construct call checks.
12284 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
12285   DCHECK(call->arguments()->length() == 0);
12286   if (function_state()->outer() != NULL) {
12287     // We are generating graph for inlined function.
12288     HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN
12289         ? graph()->GetConstantTrue()
12290         : graph()->GetConstantFalse();
12291     return ast_context()->ReturnValue(value);
12292   } else {
12293     return ast_context()->ReturnControl(New<HIsConstructCallAndBranch>(),
12294                                         call->id());
12295   }
12296 }
12297
12298
12299 // Support for arguments.length and arguments[?].
12300 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
12301   DCHECK(call->arguments()->length() == 0);
12302   HInstruction* result = NULL;
12303   if (function_state()->outer() == NULL) {
12304     HInstruction* elements = Add<HArgumentsElements>(false);
12305     result = New<HArgumentsLength>(elements);
12306   } else {
12307     // Number of arguments without receiver.
12308     int argument_count = environment()->
12309         arguments_environment()->parameter_count() - 1;
12310     result = New<HConstant>(argument_count);
12311   }
12312   return ast_context()->ReturnInstruction(result, call->id());
12313 }
12314
12315
12316 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) {
12317   DCHECK(call->arguments()->length() == 1);
12318   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12319   HValue* index = Pop();
12320   HInstruction* result = NULL;
12321   if (function_state()->outer() == NULL) {
12322     HInstruction* elements = Add<HArgumentsElements>(false);
12323     HInstruction* length = Add<HArgumentsLength>(elements);
12324     HInstruction* checked_index = Add<HBoundsCheck>(index, length);
12325     result = New<HAccessArgumentsAt>(elements, length, checked_index);
12326   } else {
12327     EnsureArgumentsArePushedForAccess();
12328
12329     // Number of arguments without receiver.
12330     HInstruction* elements = function_state()->arguments_elements();
12331     int argument_count = environment()->
12332         arguments_environment()->parameter_count() - 1;
12333     HInstruction* length = Add<HConstant>(argument_count);
12334     HInstruction* checked_key = Add<HBoundsCheck>(index, length);
12335     result = New<HAccessArgumentsAt>(elements, length, checked_key);
12336   }
12337   return ast_context()->ReturnInstruction(result, call->id());
12338 }
12339
12340
12341 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) {
12342   DCHECK(call->arguments()->length() == 1);
12343   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12344   HValue* object = Pop();
12345
12346   IfBuilder if_objectisvalue(this);
12347   HValue* objectisvalue = if_objectisvalue.If<HHasInstanceTypeAndBranch>(
12348       object, JS_VALUE_TYPE);
12349   if_objectisvalue.Then();
12350   {
12351     // Return the actual value.
12352     Push(Add<HLoadNamedField>(
12353             object, objectisvalue,
12354             HObjectAccess::ForObservableJSObjectOffset(
12355                 JSValue::kValueOffset)));
12356     Add<HSimulate>(call->id(), FIXED_SIMULATE);
12357   }
12358   if_objectisvalue.Else();
12359   {
12360     // If the object is not a value return the object.
12361     Push(object);
12362     Add<HSimulate>(call->id(), FIXED_SIMULATE);
12363   }
12364   if_objectisvalue.End();
12365   return ast_context()->ReturnValue(Pop());
12366 }
12367
12368
12369 void HOptimizedGraphBuilder::GenerateJSValueGetValue(CallRuntime* call) {
12370   DCHECK(call->arguments()->length() == 1);
12371   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12372   HValue* value = Pop();
12373   HInstruction* result = Add<HLoadNamedField>(
12374       value, nullptr,
12375       HObjectAccess::ForObservableJSObjectOffset(JSValue::kValueOffset));
12376   return ast_context()->ReturnInstruction(result, call->id());
12377 }
12378
12379
12380 void HOptimizedGraphBuilder::GenerateIsDate(CallRuntime* call) {
12381   DCHECK_EQ(1, call->arguments()->length());
12382   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12383   HValue* value = Pop();
12384   HHasInstanceTypeAndBranch* result =
12385       New<HHasInstanceTypeAndBranch>(value, JS_DATE_TYPE);
12386   return ast_context()->ReturnControl(result, call->id());
12387 }
12388
12389
12390 void HOptimizedGraphBuilder::GenerateThrowNotDateError(CallRuntime* call) {
12391   DCHECK_EQ(0, call->arguments()->length());
12392   Add<HDeoptimize>(Deoptimizer::kNotADateObject, Deoptimizer::EAGER);
12393   Add<HSimulate>(call->id(), FIXED_SIMULATE);
12394   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
12395 }
12396
12397
12398 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) {
12399   DCHECK(call->arguments()->length() == 2);
12400   DCHECK_NOT_NULL(call->arguments()->at(1)->AsLiteral());
12401   Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->value()));
12402   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12403   HValue* date = Pop();
12404   HDateField* result = New<HDateField>(date, index);
12405   return ast_context()->ReturnInstruction(result, call->id());
12406 }
12407
12408
12409 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar(
12410     CallRuntime* call) {
12411   DCHECK(call->arguments()->length() == 3);
12412   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12413   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12414   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
12415   HValue* string = Pop();
12416   HValue* value = Pop();
12417   HValue* index = Pop();
12418   Add<HSeqStringSetChar>(String::ONE_BYTE_ENCODING, string,
12419                          index, value);
12420   Add<HSimulate>(call->id(), FIXED_SIMULATE);
12421   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
12422 }
12423
12424
12425 void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar(
12426     CallRuntime* call) {
12427   DCHECK(call->arguments()->length() == 3);
12428   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12429   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12430   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
12431   HValue* string = Pop();
12432   HValue* value = Pop();
12433   HValue* index = Pop();
12434   Add<HSeqStringSetChar>(String::TWO_BYTE_ENCODING, string,
12435                          index, value);
12436   Add<HSimulate>(call->id(), FIXED_SIMULATE);
12437   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
12438 }
12439
12440
12441 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
12442   DCHECK(call->arguments()->length() == 2);
12443   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12444   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12445   HValue* value = Pop();
12446   HValue* object = Pop();
12447
12448   // Check if object is a JSValue.
12449   IfBuilder if_objectisvalue(this);
12450   if_objectisvalue.If<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE);
12451   if_objectisvalue.Then();
12452   {
12453     // Create in-object property store to kValueOffset.
12454     Add<HStoreNamedField>(object,
12455         HObjectAccess::ForObservableJSObjectOffset(JSValue::kValueOffset),
12456         value);
12457     if (!ast_context()->IsEffect()) {
12458       Push(value);
12459     }
12460     Add<HSimulate>(call->id(), FIXED_SIMULATE);
12461   }
12462   if_objectisvalue.Else();
12463   {
12464     // Nothing to do in this case.
12465     if (!ast_context()->IsEffect()) {
12466       Push(value);
12467     }
12468     Add<HSimulate>(call->id(), FIXED_SIMULATE);
12469   }
12470   if_objectisvalue.End();
12471   if (!ast_context()->IsEffect()) {
12472     Drop(1);
12473   }
12474   return ast_context()->ReturnValue(value);
12475 }
12476
12477
12478 // Fast support for charCodeAt(n).
12479 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
12480   DCHECK(call->arguments()->length() == 2);
12481   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12482   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12483   HValue* index = Pop();
12484   HValue* string = Pop();
12485   HInstruction* result = BuildStringCharCodeAt(string, index);
12486   return ast_context()->ReturnInstruction(result, call->id());
12487 }
12488
12489
12490 // Fast support for string.charAt(n) and string[n].
12491 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
12492   DCHECK(call->arguments()->length() == 1);
12493   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12494   HValue* char_code = Pop();
12495   HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
12496   return ast_context()->ReturnInstruction(result, call->id());
12497 }
12498
12499
12500 // Fast support for string.charAt(n) and string[n].
12501 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
12502   DCHECK(call->arguments()->length() == 2);
12503   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12504   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12505   HValue* index = Pop();
12506   HValue* string = Pop();
12507   HInstruction* char_code = BuildStringCharCodeAt(string, index);
12508   AddInstruction(char_code);
12509   HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
12510   return ast_context()->ReturnInstruction(result, call->id());
12511 }
12512
12513
12514 // Fast support for object equality testing.
12515 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
12516   DCHECK(call->arguments()->length() == 2);
12517   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12518   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12519   HValue* right = Pop();
12520   HValue* left = Pop();
12521   HCompareObjectEqAndBranch* result =
12522       New<HCompareObjectEqAndBranch>(left, right);
12523   return ast_context()->ReturnControl(result, call->id());
12524 }
12525
12526
12527 // Fast support for StringAdd.
12528 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) {
12529   DCHECK_EQ(2, call->arguments()->length());
12530   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12531   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12532   HValue* right = Pop();
12533   HValue* left = Pop();
12534   HInstruction* result =
12535       NewUncasted<HStringAdd>(left, right, strength(function_language_mode()));
12536   return ast_context()->ReturnInstruction(result, call->id());
12537 }
12538
12539
12540 // Fast support for SubString.
12541 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) {
12542   DCHECK_EQ(3, call->arguments()->length());
12543   CHECK_ALIVE(VisitExpressions(call->arguments()));
12544   PushArgumentsFromEnvironment(call->arguments()->length());
12545   HCallStub* result = New<HCallStub>(CodeStub::SubString, 3);
12546   return ast_context()->ReturnInstruction(result, call->id());
12547 }
12548
12549
12550 void HOptimizedGraphBuilder::GenerateStringGetLength(CallRuntime* call) {
12551   DCHECK(call->arguments()->length() == 1);
12552   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12553   HValue* string = Pop();
12554   HInstruction* result = BuildLoadStringLength(string);
12555   return ast_context()->ReturnInstruction(result, call->id());
12556 }
12557
12558
12559 // Support for direct calls from JavaScript to native RegExp code.
12560 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
12561   DCHECK_EQ(4, call->arguments()->length());
12562   CHECK_ALIVE(VisitExpressions(call->arguments()));
12563   PushArgumentsFromEnvironment(call->arguments()->length());
12564   HCallStub* result = New<HCallStub>(CodeStub::RegExpExec, 4);
12565   return ast_context()->ReturnInstruction(result, call->id());
12566 }
12567
12568
12569 void HOptimizedGraphBuilder::GenerateDoubleLo(CallRuntime* call) {
12570   DCHECK_EQ(1, call->arguments()->length());
12571   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12572   HValue* value = Pop();
12573   HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::LOW);
12574   return ast_context()->ReturnInstruction(result, call->id());
12575 }
12576
12577
12578 void HOptimizedGraphBuilder::GenerateDoubleHi(CallRuntime* call) {
12579   DCHECK_EQ(1, call->arguments()->length());
12580   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12581   HValue* value = Pop();
12582   HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::HIGH);
12583   return ast_context()->ReturnInstruction(result, call->id());
12584 }
12585
12586
12587 void HOptimizedGraphBuilder::GenerateConstructDouble(CallRuntime* call) {
12588   DCHECK_EQ(2, call->arguments()->length());
12589   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12590   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12591   HValue* lo = Pop();
12592   HValue* hi = Pop();
12593   HInstruction* result = NewUncasted<HConstructDouble>(hi, lo);
12594   return ast_context()->ReturnInstruction(result, call->id());
12595 }
12596
12597
12598 // Construct a RegExp exec result with two in-object properties.
12599 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
12600   DCHECK_EQ(3, call->arguments()->length());
12601   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12602   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12603   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
12604   HValue* input = Pop();
12605   HValue* index = Pop();
12606   HValue* length = Pop();
12607   HValue* result = BuildRegExpConstructResult(length, index, input);
12608   return ast_context()->ReturnValue(result);
12609 }
12610
12611
12612 // Fast support for number to string.
12613 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) {
12614   DCHECK_EQ(1, call->arguments()->length());
12615   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12616   HValue* number = Pop();
12617   HValue* result = BuildNumberToString(number, Type::Any(zone()));
12618   return ast_context()->ReturnValue(result);
12619 }
12620
12621
12622 // Fast support for calls.
12623 void HOptimizedGraphBuilder::GenerateCall(CallRuntime* call) {
12624   DCHECK_LE(2, call->arguments()->length());
12625   CHECK_ALIVE(VisitExpressions(call->arguments()));
12626   CallTrampolineDescriptor descriptor(isolate());
12627   PushArgumentsFromEnvironment(call->arguments()->length() - 1);
12628   HValue* trampoline = Add<HConstant>(isolate()->builtins()->Call());
12629   HValue* target = Pop();
12630   HValue* values[] = {context(), target,
12631                       Add<HConstant>(call->arguments()->length() - 2)};
12632   HInstruction* result = New<HCallWithDescriptor>(
12633       trampoline, call->arguments()->length() - 1, descriptor,
12634       Vector<HValue*>(values, arraysize(values)));
12635   return ast_context()->ReturnInstruction(result, call->id());
12636 }
12637
12638
12639 // Fast call for custom callbacks.
12640 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) {
12641   // 1 ~ The function to call is not itself an argument to the call.
12642   int arg_count = call->arguments()->length() - 1;
12643   DCHECK(arg_count >= 1);  // There's always at least a receiver.
12644
12645   CHECK_ALIVE(VisitExpressions(call->arguments()));
12646   // The function is the last argument
12647   HValue* function = Pop();
12648   // Push the arguments to the stack
12649   PushArgumentsFromEnvironment(arg_count);
12650
12651   IfBuilder if_is_jsfunction(this);
12652   if_is_jsfunction.If<HHasInstanceTypeAndBranch>(function, JS_FUNCTION_TYPE);
12653
12654   if_is_jsfunction.Then();
12655   {
12656     HInstruction* invoke_result =
12657         Add<HInvokeFunction>(function, arg_count);
12658     if (!ast_context()->IsEffect()) {
12659       Push(invoke_result);
12660     }
12661     Add<HSimulate>(call->id(), FIXED_SIMULATE);
12662   }
12663
12664   if_is_jsfunction.Else();
12665   {
12666     HInstruction* call_result =
12667         Add<HCallFunction>(function, arg_count);
12668     if (!ast_context()->IsEffect()) {
12669       Push(call_result);
12670     }
12671     Add<HSimulate>(call->id(), FIXED_SIMULATE);
12672   }
12673   if_is_jsfunction.End();
12674
12675   if (ast_context()->IsEffect()) {
12676     // EffectContext::ReturnValue ignores the value, so we can just pass
12677     // 'undefined' (as we do not have the call result anymore).
12678     return ast_context()->ReturnValue(graph()->GetConstantUndefined());
12679   } else {
12680     return ast_context()->ReturnValue(Pop());
12681   }
12682 }
12683
12684
12685 // Fast call to math functions.
12686 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) {
12687   DCHECK_EQ(2, call->arguments()->length());
12688   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12689   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12690   HValue* right = Pop();
12691   HValue* left = Pop();
12692   HInstruction* result = NewUncasted<HPower>(left, right);
12693   return ast_context()->ReturnInstruction(result, call->id());
12694 }
12695
12696
12697 void HOptimizedGraphBuilder::GenerateMathClz32(CallRuntime* call) {
12698   DCHECK(call->arguments()->length() == 1);
12699   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12700   HValue* value = Pop();
12701   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathClz32);
12702   return ast_context()->ReturnInstruction(result, call->id());
12703 }
12704
12705
12706 void HOptimizedGraphBuilder::GenerateMathFloor(CallRuntime* call) {
12707   DCHECK(call->arguments()->length() == 1);
12708   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12709   HValue* value = Pop();
12710   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathFloor);
12711   return ast_context()->ReturnInstruction(result, call->id());
12712 }
12713
12714
12715 void HOptimizedGraphBuilder::GenerateMathLogRT(CallRuntime* call) {
12716   DCHECK(call->arguments()->length() == 1);
12717   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12718   HValue* value = Pop();
12719   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathLog);
12720   return ast_context()->ReturnInstruction(result, call->id());
12721 }
12722
12723
12724 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
12725   DCHECK(call->arguments()->length() == 1);
12726   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12727   HValue* value = Pop();
12728   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt);
12729   return ast_context()->ReturnInstruction(result, call->id());
12730 }
12731
12732
12733 void HOptimizedGraphBuilder::GenerateLikely(CallRuntime* call) {
12734   DCHECK(call->arguments()->length() == 1);
12735   Visit(call->arguments()->at(0));
12736 }
12737
12738
12739 void HOptimizedGraphBuilder::GenerateUnlikely(CallRuntime* call) {
12740   return GenerateLikely(call);
12741 }
12742
12743
12744 void HOptimizedGraphBuilder::GenerateHasInPrototypeChain(CallRuntime* call) {
12745   DCHECK_EQ(2, call->arguments()->length());
12746   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12747   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12748   HValue* prototype = Pop();
12749   HValue* object = Pop();
12750   HHasInPrototypeChainAndBranch* result =
12751       New<HHasInPrototypeChainAndBranch>(object, prototype);
12752   return ast_context()->ReturnControl(result, call->id());
12753 }
12754
12755
12756 void HOptimizedGraphBuilder::GenerateFixedArrayGet(CallRuntime* call) {
12757   DCHECK(call->arguments()->length() == 2);
12758   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12759   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12760   HValue* index = Pop();
12761   HValue* object = Pop();
12762   HInstruction* result = New<HLoadKeyed>(
12763       object, index, nullptr, FAST_HOLEY_ELEMENTS, ALLOW_RETURN_HOLE);
12764   return ast_context()->ReturnInstruction(result, call->id());
12765 }
12766
12767
12768 void HOptimizedGraphBuilder::GenerateFixedArraySet(CallRuntime* call) {
12769   DCHECK(call->arguments()->length() == 3);
12770   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12771   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12772   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
12773   HValue* value = Pop();
12774   HValue* index = Pop();
12775   HValue* object = Pop();
12776   NoObservableSideEffectsScope no_effects(this);
12777   Add<HStoreKeyed>(object, index, value, FAST_HOLEY_ELEMENTS);
12778   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
12779 }
12780
12781
12782 void HOptimizedGraphBuilder::GenerateTheHole(CallRuntime* call) {
12783   DCHECK(call->arguments()->length() == 0);
12784   return ast_context()->ReturnValue(graph()->GetConstantHole());
12785 }
12786
12787
12788 void HOptimizedGraphBuilder::GenerateCreateIterResultObject(CallRuntime* call) {
12789   DCHECK_EQ(2, call->arguments()->length());
12790   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12791   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
12792   HValue* done = Pop();
12793   HValue* value = Pop();
12794   HValue* result = BuildCreateIterResultObject(value, done);
12795   return ast_context()->ReturnValue(result);
12796 }
12797
12798
12799 void HOptimizedGraphBuilder::GenerateJSCollectionGetTable(CallRuntime* call) {
12800   DCHECK(call->arguments()->length() == 1);
12801   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12802   HValue* receiver = Pop();
12803   HInstruction* result = New<HLoadNamedField>(
12804       receiver, nullptr, HObjectAccess::ForJSCollectionTable());
12805   return ast_context()->ReturnInstruction(result, call->id());
12806 }
12807
12808
12809 void HOptimizedGraphBuilder::GenerateStringGetRawHashField(CallRuntime* call) {
12810   DCHECK(call->arguments()->length() == 1);
12811   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12812   HValue* object = Pop();
12813   HInstruction* result = New<HLoadNamedField>(
12814       object, nullptr, HObjectAccess::ForStringHashField());
12815   return ast_context()->ReturnInstruction(result, call->id());
12816 }
12817
12818
12819 template <typename CollectionType>
12820 HValue* HOptimizedGraphBuilder::BuildAllocateOrderedHashTable() {
12821   static const int kCapacity = CollectionType::kMinCapacity;
12822   static const int kBucketCount = kCapacity / CollectionType::kLoadFactor;
12823   static const int kFixedArrayLength = CollectionType::kHashTableStartIndex +
12824                                        kBucketCount +
12825                                        (kCapacity * CollectionType::kEntrySize);
12826   static const int kSizeInBytes =
12827       FixedArray::kHeaderSize + (kFixedArrayLength * kPointerSize);
12828
12829   // Allocate the table and add the proper map.
12830   HValue* table =
12831       Add<HAllocate>(Add<HConstant>(kSizeInBytes), HType::HeapObject(),
12832                      NOT_TENURED, FIXED_ARRAY_TYPE);
12833   AddStoreMapConstant(table, isolate()->factory()->ordered_hash_table_map());
12834
12835   // Initialize the FixedArray...
12836   HValue* length = Add<HConstant>(kFixedArrayLength);
12837   Add<HStoreNamedField>(table, HObjectAccess::ForFixedArrayLength(), length);
12838
12839   // ...and the OrderedHashTable fields.
12840   Add<HStoreNamedField>(
12841       table,
12842       HObjectAccess::ForOrderedHashTableNumberOfBuckets<CollectionType>(),
12843       Add<HConstant>(kBucketCount));
12844   Add<HStoreNamedField>(
12845       table,
12846       HObjectAccess::ForOrderedHashTableNumberOfElements<CollectionType>(),
12847       graph()->GetConstant0());
12848   Add<HStoreNamedField>(
12849       table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
12850                  CollectionType>(),
12851       graph()->GetConstant0());
12852
12853   // Fill the buckets with kNotFound.
12854   HValue* not_found = Add<HConstant>(CollectionType::kNotFound);
12855   for (int i = 0; i < kBucketCount; ++i) {
12856     Add<HStoreNamedField>(
12857         table, HObjectAccess::ForOrderedHashTableBucket<CollectionType>(i),
12858         not_found);
12859   }
12860
12861   // Fill the data table with undefined.
12862   HValue* undefined = graph()->GetConstantUndefined();
12863   for (int i = 0; i < (kCapacity * CollectionType::kEntrySize); ++i) {
12864     Add<HStoreNamedField>(table,
12865                           HObjectAccess::ForOrderedHashTableDataTableIndex<
12866                               CollectionType, kBucketCount>(i),
12867                           undefined);
12868   }
12869
12870   return table;
12871 }
12872
12873
12874 void HOptimizedGraphBuilder::GenerateSetInitialize(CallRuntime* call) {
12875   DCHECK(call->arguments()->length() == 1);
12876   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12877   HValue* receiver = Pop();
12878
12879   NoObservableSideEffectsScope no_effects(this);
12880   HValue* table = BuildAllocateOrderedHashTable<OrderedHashSet>();
12881   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(), table);
12882   return ast_context()->ReturnValue(receiver);
12883 }
12884
12885
12886 void HOptimizedGraphBuilder::GenerateMapInitialize(CallRuntime* call) {
12887   DCHECK(call->arguments()->length() == 1);
12888   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12889   HValue* receiver = Pop();
12890
12891   NoObservableSideEffectsScope no_effects(this);
12892   HValue* table = BuildAllocateOrderedHashTable<OrderedHashMap>();
12893   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(), table);
12894   return ast_context()->ReturnValue(receiver);
12895 }
12896
12897
12898 template <typename CollectionType>
12899 void HOptimizedGraphBuilder::BuildOrderedHashTableClear(HValue* receiver) {
12900   HValue* old_table = Add<HLoadNamedField>(
12901       receiver, nullptr, HObjectAccess::ForJSCollectionTable());
12902   HValue* new_table = BuildAllocateOrderedHashTable<CollectionType>();
12903   Add<HStoreNamedField>(
12904       old_table, HObjectAccess::ForOrderedHashTableNextTable<CollectionType>(),
12905       new_table);
12906   Add<HStoreNamedField>(
12907       old_table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
12908                      CollectionType>(),
12909       Add<HConstant>(CollectionType::kClearedTableSentinel));
12910   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(),
12911                         new_table);
12912 }
12913
12914
12915 void HOptimizedGraphBuilder::GenerateSetClear(CallRuntime* call) {
12916   DCHECK(call->arguments()->length() == 1);
12917   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12918   HValue* receiver = Pop();
12919
12920   NoObservableSideEffectsScope no_effects(this);
12921   BuildOrderedHashTableClear<OrderedHashSet>(receiver);
12922   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
12923 }
12924
12925
12926 void HOptimizedGraphBuilder::GenerateMapClear(CallRuntime* call) {
12927   DCHECK(call->arguments()->length() == 1);
12928   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12929   HValue* receiver = Pop();
12930
12931   NoObservableSideEffectsScope no_effects(this);
12932   BuildOrderedHashTableClear<OrderedHashMap>(receiver);
12933   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
12934 }
12935
12936
12937 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
12938   DCHECK(call->arguments()->length() == 1);
12939   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
12940   HValue* value = Pop();
12941   HGetCachedArrayIndex* result = New<HGetCachedArrayIndex>(value);
12942   return ast_context()->ReturnInstruction(result, call->id());
12943 }
12944
12945
12946 void HOptimizedGraphBuilder::GenerateFastOneByteArrayJoin(CallRuntime* call) {
12947   // Simply returning undefined here would be semantically correct and even
12948   // avoid the bailout. Nevertheless, some ancient benchmarks like SunSpider's
12949   // string-fasta would tank, because fullcode contains an optimized version.
12950   // Obviously the fullcode => Crankshaft => bailout => fullcode dance is
12951   // faster... *sigh*
12952   return Bailout(kInlinedRuntimeFunctionFastOneByteArrayJoin);
12953 }
12954
12955
12956 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode(
12957     CallRuntime* call) {
12958   Add<HDebugBreak>();
12959   return ast_context()->ReturnValue(graph()->GetConstant0());
12960 }
12961
12962
12963 void HOptimizedGraphBuilder::GenerateDebugIsActive(CallRuntime* call) {
12964   DCHECK(call->arguments()->length() == 0);
12965   HValue* ref =
12966       Add<HConstant>(ExternalReference::debug_is_active_address(isolate()));
12967   HValue* value =
12968       Add<HLoadNamedField>(ref, nullptr, HObjectAccess::ForExternalUInteger8());
12969   return ast_context()->ReturnValue(value);
12970 }
12971
12972
12973 #undef CHECK_BAILOUT
12974 #undef CHECK_ALIVE
12975
12976
12977 HEnvironment::HEnvironment(HEnvironment* outer,
12978                            Scope* scope,
12979                            Handle<JSFunction> closure,
12980                            Zone* zone)
12981     : closure_(closure),
12982       values_(0, zone),
12983       frame_type_(JS_FUNCTION),
12984       parameter_count_(0),
12985       specials_count_(1),
12986       local_count_(0),
12987       outer_(outer),
12988       entry_(NULL),
12989       pop_count_(0),
12990       push_count_(0),
12991       ast_id_(BailoutId::None()),
12992       zone_(zone) {
12993   Scope* declaration_scope = scope->DeclarationScope();
12994   Initialize(declaration_scope->num_parameters() + 1,
12995              declaration_scope->num_stack_slots(), 0);
12996 }
12997
12998
12999 HEnvironment::HEnvironment(Zone* zone, int parameter_count)
13000     : values_(0, zone),
13001       frame_type_(STUB),
13002       parameter_count_(parameter_count),
13003       specials_count_(1),
13004       local_count_(0),
13005       outer_(NULL),
13006       entry_(NULL),
13007       pop_count_(0),
13008       push_count_(0),
13009       ast_id_(BailoutId::None()),
13010       zone_(zone) {
13011   Initialize(parameter_count, 0, 0);
13012 }
13013
13014
13015 HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone)
13016     : values_(0, zone),
13017       frame_type_(JS_FUNCTION),
13018       parameter_count_(0),
13019       specials_count_(0),
13020       local_count_(0),
13021       outer_(NULL),
13022       entry_(NULL),
13023       pop_count_(0),
13024       push_count_(0),
13025       ast_id_(other->ast_id()),
13026       zone_(zone) {
13027   Initialize(other);
13028 }
13029
13030
13031 HEnvironment::HEnvironment(HEnvironment* outer,
13032                            Handle<JSFunction> closure,
13033                            FrameType frame_type,
13034                            int arguments,
13035                            Zone* zone)
13036     : closure_(closure),
13037       values_(arguments, zone),
13038       frame_type_(frame_type),
13039       parameter_count_(arguments),
13040       specials_count_(0),
13041       local_count_(0),
13042       outer_(outer),
13043       entry_(NULL),
13044       pop_count_(0),
13045       push_count_(0),
13046       ast_id_(BailoutId::None()),
13047       zone_(zone) {
13048 }
13049
13050
13051 void HEnvironment::Initialize(int parameter_count,
13052                               int local_count,
13053                               int stack_height) {
13054   parameter_count_ = parameter_count;
13055   local_count_ = local_count;
13056
13057   // Avoid reallocating the temporaries' backing store on the first Push.
13058   int total = parameter_count + specials_count_ + local_count + stack_height;
13059   values_.Initialize(total + 4, zone());
13060   for (int i = 0; i < total; ++i) values_.Add(NULL, zone());
13061 }
13062
13063
13064 void HEnvironment::Initialize(const HEnvironment* other) {
13065   closure_ = other->closure();
13066   values_.AddAll(other->values_, zone());
13067   assigned_variables_.Union(other->assigned_variables_, zone());
13068   frame_type_ = other->frame_type_;
13069   parameter_count_ = other->parameter_count_;
13070   local_count_ = other->local_count_;
13071   if (other->outer_ != NULL) outer_ = other->outer_->Copy();  // Deep copy.
13072   entry_ = other->entry_;
13073   pop_count_ = other->pop_count_;
13074   push_count_ = other->push_count_;
13075   specials_count_ = other->specials_count_;
13076   ast_id_ = other->ast_id_;
13077 }
13078
13079
13080 void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
13081   DCHECK(!block->IsLoopHeader());
13082   DCHECK(values_.length() == other->values_.length());
13083
13084   int length = values_.length();
13085   for (int i = 0; i < length; ++i) {
13086     HValue* value = values_[i];
13087     if (value != NULL && value->IsPhi() && value->block() == block) {
13088       // There is already a phi for the i'th value.
13089       HPhi* phi = HPhi::cast(value);
13090       // Assert index is correct and that we haven't missed an incoming edge.
13091       DCHECK(phi->merged_index() == i || !phi->HasMergedIndex());
13092       DCHECK(phi->OperandCount() == block->predecessors()->length());
13093       phi->AddInput(other->values_[i]);
13094     } else if (values_[i] != other->values_[i]) {
13095       // There is a fresh value on the incoming edge, a phi is needed.
13096       DCHECK(values_[i] != NULL && other->values_[i] != NULL);
13097       HPhi* phi = block->AddNewPhi(i);
13098       HValue* old_value = values_[i];
13099       for (int j = 0; j < block->predecessors()->length(); j++) {
13100         phi->AddInput(old_value);
13101       }
13102       phi->AddInput(other->values_[i]);
13103       this->values_[i] = phi;
13104     }
13105   }
13106 }
13107
13108
13109 void HEnvironment::Bind(int index, HValue* value) {
13110   DCHECK(value != NULL);
13111   assigned_variables_.Add(index, zone());
13112   values_[index] = value;
13113 }
13114
13115
13116 bool HEnvironment::HasExpressionAt(int index) const {
13117   return index >= parameter_count_ + specials_count_ + local_count_;
13118 }
13119
13120
13121 bool HEnvironment::ExpressionStackIsEmpty() const {
13122   DCHECK(length() >= first_expression_index());
13123   return length() == first_expression_index();
13124 }
13125
13126
13127 void HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) {
13128   int count = index_from_top + 1;
13129   int index = values_.length() - count;
13130   DCHECK(HasExpressionAt(index));
13131   // The push count must include at least the element in question or else
13132   // the new value will not be included in this environment's history.
13133   if (push_count_ < count) {
13134     // This is the same effect as popping then re-pushing 'count' elements.
13135     pop_count_ += (count - push_count_);
13136     push_count_ = count;
13137   }
13138   values_[index] = value;
13139 }
13140
13141
13142 HValue* HEnvironment::RemoveExpressionStackAt(int index_from_top) {
13143   int count = index_from_top + 1;
13144   int index = values_.length() - count;
13145   DCHECK(HasExpressionAt(index));
13146   // Simulate popping 'count' elements and then
13147   // pushing 'count - 1' elements back.
13148   pop_count_ += Max(count - push_count_, 0);
13149   push_count_ = Max(push_count_ - count, 0) + (count - 1);
13150   return values_.Remove(index);
13151 }
13152
13153
13154 void HEnvironment::Drop(int count) {
13155   for (int i = 0; i < count; ++i) {
13156     Pop();
13157   }
13158 }
13159
13160
13161 void HEnvironment::Print() const {
13162   OFStream os(stdout);
13163   os << *this << "\n";
13164 }
13165
13166
13167 HEnvironment* HEnvironment::Copy() const {
13168   return new(zone()) HEnvironment(this, zone());
13169 }
13170
13171
13172 HEnvironment* HEnvironment::CopyWithoutHistory() const {
13173   HEnvironment* result = Copy();
13174   result->ClearHistory();
13175   return result;
13176 }
13177
13178
13179 HEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const {
13180   HEnvironment* new_env = Copy();
13181   for (int i = 0; i < values_.length(); ++i) {
13182     HPhi* phi = loop_header->AddNewPhi(i);
13183     phi->AddInput(values_[i]);
13184     new_env->values_[i] = phi;
13185   }
13186   new_env->ClearHistory();
13187   return new_env;
13188 }
13189
13190
13191 HEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer,
13192                                                   Handle<JSFunction> target,
13193                                                   FrameType frame_type,
13194                                                   int arguments) const {
13195   HEnvironment* new_env =
13196       new(zone()) HEnvironment(outer, target, frame_type,
13197                                arguments + 1, zone());
13198   for (int i = 0; i <= arguments; ++i) {  // Include receiver.
13199     new_env->Push(ExpressionStackAt(arguments - i));
13200   }
13201   new_env->ClearHistory();
13202   return new_env;
13203 }
13204
13205
13206 HEnvironment* HEnvironment::CopyForInlining(
13207     Handle<JSFunction> target,
13208     int arguments,
13209     FunctionLiteral* function,
13210     HConstant* undefined,
13211     InliningKind inlining_kind) const {
13212   DCHECK(frame_type() == JS_FUNCTION);
13213
13214   // Outer environment is a copy of this one without the arguments.
13215   int arity = function->scope()->num_parameters();
13216
13217   HEnvironment* outer = Copy();
13218   outer->Drop(arguments + 1);  // Including receiver.
13219   outer->ClearHistory();
13220
13221   if (inlining_kind == CONSTRUCT_CALL_RETURN) {
13222     // Create artificial constructor stub environment.  The receiver should
13223     // actually be the constructor function, but we pass the newly allocated
13224     // object instead, DoComputeConstructStubFrame() relies on that.
13225     outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments);
13226   } else if (inlining_kind == GETTER_CALL_RETURN) {
13227     // We need an additional StackFrame::INTERNAL frame for restoring the
13228     // correct context.
13229     outer = CreateStubEnvironment(outer, target, JS_GETTER, arguments);
13230   } else if (inlining_kind == SETTER_CALL_RETURN) {
13231     // We need an additional StackFrame::INTERNAL frame for temporarily saving
13232     // the argument of the setter, see StoreStubCompiler::CompileStoreViaSetter.
13233     outer = CreateStubEnvironment(outer, target, JS_SETTER, arguments);
13234   }
13235
13236   if (arity != arguments) {
13237     // Create artificial arguments adaptation environment.
13238     outer = CreateStubEnvironment(outer, target, ARGUMENTS_ADAPTOR, arguments);
13239   }
13240
13241   HEnvironment* inner =
13242       new(zone()) HEnvironment(outer, function->scope(), target, zone());
13243   // Get the argument values from the original environment.
13244   for (int i = 0; i <= arity; ++i) {  // Include receiver.
13245     HValue* push = (i <= arguments) ?
13246         ExpressionStackAt(arguments - i) : undefined;
13247     inner->SetValueAt(i, push);
13248   }
13249   inner->SetValueAt(arity + 1, context());
13250   for (int i = arity + 2; i < inner->length(); ++i) {
13251     inner->SetValueAt(i, undefined);
13252   }
13253
13254   inner->set_ast_id(BailoutId::FunctionEntry());
13255   return inner;
13256 }
13257
13258
13259 std::ostream& operator<<(std::ostream& os, const HEnvironment& env) {
13260   for (int i = 0; i < env.length(); i++) {
13261     if (i == 0) os << "parameters\n";
13262     if (i == env.parameter_count()) os << "specials\n";
13263     if (i == env.parameter_count() + env.specials_count()) os << "locals\n";
13264     if (i == env.parameter_count() + env.specials_count() + env.local_count()) {
13265       os << "expressions\n";
13266     }
13267     HValue* val = env.values()->at(i);
13268     os << i << ": ";
13269     if (val != NULL) {
13270       os << val;
13271     } else {
13272       os << "NULL";
13273     }
13274     os << "\n";
13275   }
13276   return os << "\n";
13277 }
13278
13279
13280 void HTracer::TraceCompilation(CompilationInfo* info) {
13281   Tag tag(this, "compilation");
13282   base::SmartArrayPointer<char> name = info->GetDebugName();
13283   if (info->IsOptimizing()) {
13284     PrintStringProperty("name", name.get());
13285     PrintIndent();
13286     trace_.Add("method \"%s:%d\"\n", name.get(), info->optimization_id());
13287   } else {
13288     PrintStringProperty("name", name.get());
13289     PrintStringProperty("method", "stub");
13290   }
13291   PrintLongProperty("date",
13292                     static_cast<int64_t>(base::OS::TimeCurrentMillis()));
13293 }
13294
13295
13296 void HTracer::TraceLithium(const char* name, LChunk* chunk) {
13297   DCHECK(!chunk->isolate()->concurrent_recompilation_enabled());
13298   AllowHandleDereference allow_deref;
13299   AllowDeferredHandleDereference allow_deferred_deref;
13300   Trace(name, chunk->graph(), chunk);
13301 }
13302
13303
13304 void HTracer::TraceHydrogen(const char* name, HGraph* graph) {
13305   DCHECK(!graph->isolate()->concurrent_recompilation_enabled());
13306   AllowHandleDereference allow_deref;
13307   AllowDeferredHandleDereference allow_deferred_deref;
13308   Trace(name, graph, NULL);
13309 }
13310
13311
13312 void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
13313   Tag tag(this, "cfg");
13314   PrintStringProperty("name", name);
13315   const ZoneList<HBasicBlock*>* blocks = graph->blocks();
13316   for (int i = 0; i < blocks->length(); i++) {
13317     HBasicBlock* current = blocks->at(i);
13318     Tag block_tag(this, "block");
13319     PrintBlockProperty("name", current->block_id());
13320     PrintIntProperty("from_bci", -1);
13321     PrintIntProperty("to_bci", -1);
13322
13323     if (!current->predecessors()->is_empty()) {
13324       PrintIndent();
13325       trace_.Add("predecessors");
13326       for (int j = 0; j < current->predecessors()->length(); ++j) {
13327         trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id());
13328       }
13329       trace_.Add("\n");
13330     } else {
13331       PrintEmptyProperty("predecessors");
13332     }
13333
13334     if (current->end()->SuccessorCount() == 0) {
13335       PrintEmptyProperty("successors");
13336     } else  {
13337       PrintIndent();
13338       trace_.Add("successors");
13339       for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) {
13340         trace_.Add(" \"B%d\"", it.Current()->block_id());
13341       }
13342       trace_.Add("\n");
13343     }
13344
13345     PrintEmptyProperty("xhandlers");
13346
13347     {
13348       PrintIndent();
13349       trace_.Add("flags");
13350       if (current->IsLoopSuccessorDominator()) {
13351         trace_.Add(" \"dom-loop-succ\"");
13352       }
13353       if (current->IsUnreachable()) {
13354         trace_.Add(" \"dead\"");
13355       }
13356       if (current->is_osr_entry()) {
13357         trace_.Add(" \"osr\"");
13358       }
13359       trace_.Add("\n");
13360     }
13361
13362     if (current->dominator() != NULL) {
13363       PrintBlockProperty("dominator", current->dominator()->block_id());
13364     }
13365
13366     PrintIntProperty("loop_depth", current->LoopNestingDepth());
13367
13368     if (chunk != NULL) {
13369       int first_index = current->first_instruction_index();
13370       int last_index = current->last_instruction_index();
13371       PrintIntProperty(
13372           "first_lir_id",
13373           LifetimePosition::FromInstructionIndex(first_index).Value());
13374       PrintIntProperty(
13375           "last_lir_id",
13376           LifetimePosition::FromInstructionIndex(last_index).Value());
13377     }
13378
13379     {
13380       Tag states_tag(this, "states");
13381       Tag locals_tag(this, "locals");
13382       int total = current->phis()->length();
13383       PrintIntProperty("size", current->phis()->length());
13384       PrintStringProperty("method", "None");
13385       for (int j = 0; j < total; ++j) {
13386         HPhi* phi = current->phis()->at(j);
13387         PrintIndent();
13388         std::ostringstream os;
13389         os << phi->merged_index() << " " << NameOf(phi) << " " << *phi << "\n";
13390         trace_.Add(os.str().c_str());
13391       }
13392     }
13393
13394     {
13395       Tag HIR_tag(this, "HIR");
13396       for (HInstructionIterator it(current); !it.Done(); it.Advance()) {
13397         HInstruction* instruction = it.Current();
13398         int uses = instruction->UseCount();
13399         PrintIndent();
13400         std::ostringstream os;
13401         os << "0 " << uses << " " << NameOf(instruction) << " " << *instruction;
13402         if (graph->info()->is_tracking_positions() &&
13403             instruction->has_position() && instruction->position().raw() != 0) {
13404           const SourcePosition pos = instruction->position();
13405           os << " pos:";
13406           if (pos.inlining_id() != 0) os << pos.inlining_id() << "_";
13407           os << pos.position();
13408         }
13409         os << " <|@\n";
13410         trace_.Add(os.str().c_str());
13411       }
13412     }
13413
13414
13415     if (chunk != NULL) {
13416       Tag LIR_tag(this, "LIR");
13417       int first_index = current->first_instruction_index();
13418       int last_index = current->last_instruction_index();
13419       if (first_index != -1 && last_index != -1) {
13420         const ZoneList<LInstruction*>* instructions = chunk->instructions();
13421         for (int i = first_index; i <= last_index; ++i) {
13422           LInstruction* linstr = instructions->at(i);
13423           if (linstr != NULL) {
13424             PrintIndent();
13425             trace_.Add("%d ",
13426                        LifetimePosition::FromInstructionIndex(i).Value());
13427             linstr->PrintTo(&trace_);
13428             std::ostringstream os;
13429             os << " [hir:" << NameOf(linstr->hydrogen_value()) << "] <|@\n";
13430             trace_.Add(os.str().c_str());
13431           }
13432         }
13433       }
13434     }
13435   }
13436 }
13437
13438
13439 void HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) {
13440   Tag tag(this, "intervals");
13441   PrintStringProperty("name", name);
13442
13443   const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
13444   for (int i = 0; i < fixed_d->length(); ++i) {
13445     TraceLiveRange(fixed_d->at(i), "fixed", allocator->zone());
13446   }
13447
13448   const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges();
13449   for (int i = 0; i < fixed->length(); ++i) {
13450     TraceLiveRange(fixed->at(i), "fixed", allocator->zone());
13451   }
13452
13453   const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges();
13454   for (int i = 0; i < live_ranges->length(); ++i) {
13455     TraceLiveRange(live_ranges->at(i), "object", allocator->zone());
13456   }
13457 }
13458
13459
13460 void HTracer::TraceLiveRange(LiveRange* range, const char* type,
13461                              Zone* zone) {
13462   if (range != NULL && !range->IsEmpty()) {
13463     PrintIndent();
13464     trace_.Add("%d %s", range->id(), type);
13465     if (range->HasRegisterAssigned()) {
13466       LOperand* op = range->CreateAssignedOperand(zone);
13467       int assigned_reg = op->index();
13468       if (op->IsDoubleRegister()) {
13469         trace_.Add(" \"%s\"",
13470                    DoubleRegister::AllocationIndexToString(assigned_reg));
13471       } else {
13472         DCHECK(op->IsRegister());
13473         trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg));
13474       }
13475     } else if (range->IsSpilled()) {
13476       LOperand* op = range->TopLevel()->GetSpillOperand();
13477       if (op->IsDoubleStackSlot()) {
13478         trace_.Add(" \"double_stack:%d\"", op->index());
13479       } else {
13480         DCHECK(op->IsStackSlot());
13481         trace_.Add(" \"stack:%d\"", op->index());
13482       }
13483     }
13484     int parent_index = -1;
13485     if (range->IsChild()) {
13486       parent_index = range->parent()->id();
13487     } else {
13488       parent_index = range->id();
13489     }
13490     LOperand* op = range->FirstHint();
13491     int hint_index = -1;
13492     if (op != NULL && op->IsUnallocated()) {
13493       hint_index = LUnallocated::cast(op)->virtual_register();
13494     }
13495     trace_.Add(" %d %d", parent_index, hint_index);
13496     UseInterval* cur_interval = range->first_interval();
13497     while (cur_interval != NULL && range->Covers(cur_interval->start())) {
13498       trace_.Add(" [%d, %d[",
13499                  cur_interval->start().Value(),
13500                  cur_interval->end().Value());
13501       cur_interval = cur_interval->next();
13502     }
13503
13504     UsePosition* current_pos = range->first_pos();
13505     while (current_pos != NULL) {
13506       if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
13507         trace_.Add(" %d M", current_pos->pos().Value());
13508       }
13509       current_pos = current_pos->next();
13510     }
13511
13512     trace_.Add(" \"\"\n");
13513   }
13514 }
13515
13516
13517 void HTracer::FlushToFile() {
13518   AppendChars(filename_.start(), trace_.ToCString().get(), trace_.length(),
13519               false);
13520   trace_.Reset();
13521 }
13522
13523
13524 void HStatistics::Initialize(CompilationInfo* info) {
13525   if (!info->has_shared_info()) return;
13526   source_size_ += info->shared_info()->SourceSize();
13527 }
13528
13529
13530 void HStatistics::Print() {
13531   PrintF(
13532       "\n"
13533       "----------------------------------------"
13534       "----------------------------------------\n"
13535       "--- Hydrogen timing results:\n"
13536       "----------------------------------------"
13537       "----------------------------------------\n");
13538   base::TimeDelta sum;
13539   for (int i = 0; i < times_.length(); ++i) {
13540     sum += times_[i];
13541   }
13542
13543   for (int i = 0; i < names_.length(); ++i) {
13544     PrintF("%33s", names_[i]);
13545     double ms = times_[i].InMillisecondsF();
13546     double percent = times_[i].PercentOf(sum);
13547     PrintF(" %8.3f ms / %4.1f %% ", ms, percent);
13548
13549     size_t size = sizes_[i];
13550     double size_percent = static_cast<double>(size) * 100 / total_size_;
13551     PrintF(" %9zu bytes / %4.1f %%\n", size, size_percent);
13552   }
13553
13554   PrintF(
13555       "----------------------------------------"
13556       "----------------------------------------\n");
13557   base::TimeDelta total = create_graph_ + optimize_graph_ + generate_code_;
13558   PrintF("%33s %8.3f ms / %4.1f %% \n", "Create graph",
13559          create_graph_.InMillisecondsF(), create_graph_.PercentOf(total));
13560   PrintF("%33s %8.3f ms / %4.1f %% \n", "Optimize graph",
13561          optimize_graph_.InMillisecondsF(), optimize_graph_.PercentOf(total));
13562   PrintF("%33s %8.3f ms / %4.1f %% \n", "Generate and install code",
13563          generate_code_.InMillisecondsF(), generate_code_.PercentOf(total));
13564   PrintF(
13565       "----------------------------------------"
13566       "----------------------------------------\n");
13567   PrintF("%33s %8.3f ms           %9zu bytes\n", "Total",
13568          total.InMillisecondsF(), total_size_);
13569   PrintF("%33s     (%.1f times slower than full code gen)\n", "",
13570          total.TimesOf(full_code_gen_));
13571
13572   double source_size_in_kb = static_cast<double>(source_size_) / 1024;
13573   double normalized_time =  source_size_in_kb > 0
13574       ? total.InMillisecondsF() / source_size_in_kb
13575       : 0;
13576   double normalized_size_in_kb =
13577       source_size_in_kb > 0
13578           ? static_cast<double>(total_size_) / 1024 / source_size_in_kb
13579           : 0;
13580   PrintF("%33s %8.3f ms           %7.3f kB allocated\n",
13581          "Average per kB source", normalized_time, normalized_size_in_kb);
13582 }
13583
13584
13585 void HStatistics::SaveTiming(const char* name, base::TimeDelta time,
13586                              size_t size) {
13587   total_size_ += size;
13588   for (int i = 0; i < names_.length(); ++i) {
13589     if (strcmp(names_[i], name) == 0) {
13590       times_[i] += time;
13591       sizes_[i] += size;
13592       return;
13593     }
13594   }
13595   names_.Add(name);
13596   times_.Add(time);
13597   sizes_.Add(size);
13598 }
13599
13600
13601 HPhase::~HPhase() {
13602   if (ShouldProduceTraceOutput()) {
13603     isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
13604   }
13605
13606 #ifdef DEBUG
13607   graph_->Verify(false);  // No full verify.
13608 #endif
13609 }
13610
13611 }  // namespace internal
13612 }  // namespace v8