[presubmit] Enable readability/namespace linter checking.
[platform/upstream/v8.git] / src / hydrogen.h
1 // Copyright 2012 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 #ifndef V8_HYDROGEN_H_
6 #define V8_HYDROGEN_H_
7
8 #include "src/accessors.h"
9 #include "src/allocation.h"
10 #include "src/ast.h"
11 #include "src/bailout-reason.h"
12 #include "src/compiler.h"
13 #include "src/hydrogen-instructions.h"
14 #include "src/scopes.h"
15 #include "src/zone.h"
16
17 namespace v8 {
18 namespace internal {
19
20 // Forward declarations.
21 class BitVector;
22 class FunctionState;
23 class HEnvironment;
24 class HGraph;
25 class HLoopInformation;
26 class HOsrBuilder;
27 class HTracer;
28 class LAllocator;
29 class LChunk;
30 class LiveRange;
31
32
33 class HBasicBlock final : public ZoneObject {
34  public:
35   explicit HBasicBlock(HGraph* graph);
36   ~HBasicBlock() { }
37
38   // Simple accessors.
39   int block_id() const { return block_id_; }
40   void set_block_id(int id) { block_id_ = id; }
41   HGraph* graph() const { return graph_; }
42   Isolate* isolate() const;
43   const ZoneList<HPhi*>* phis() const { return &phis_; }
44   HInstruction* first() const { return first_; }
45   HInstruction* last() const { return last_; }
46   void set_last(HInstruction* instr) { last_ = instr; }
47   HControlInstruction* end() const { return end_; }
48   HLoopInformation* loop_information() const { return loop_information_; }
49   HLoopInformation* current_loop() const {
50     return IsLoopHeader() ? loop_information()
51                           : (parent_loop_header() != NULL
52                             ? parent_loop_header()->loop_information() : NULL);
53   }
54   const ZoneList<HBasicBlock*>* predecessors() const { return &predecessors_; }
55   bool HasPredecessor() const { return predecessors_.length() > 0; }
56   const ZoneList<HBasicBlock*>* dominated_blocks() const {
57     return &dominated_blocks_;
58   }
59   const ZoneList<int>* deleted_phis() const {
60     return &deleted_phis_;
61   }
62   void RecordDeletedPhi(int merge_index) {
63     deleted_phis_.Add(merge_index, zone());
64   }
65   HBasicBlock* dominator() const { return dominator_; }
66   HEnvironment* last_environment() const { return last_environment_; }
67   int argument_count() const { return argument_count_; }
68   void set_argument_count(int count) { argument_count_ = count; }
69   int first_instruction_index() const { return first_instruction_index_; }
70   void set_first_instruction_index(int index) {
71     first_instruction_index_ = index;
72   }
73   int last_instruction_index() const { return last_instruction_index_; }
74   void set_last_instruction_index(int index) {
75     last_instruction_index_ = index;
76   }
77   bool is_osr_entry() { return is_osr_entry_; }
78   void set_osr_entry() { is_osr_entry_ = true; }
79
80   void AttachLoopInformation();
81   void DetachLoopInformation();
82   bool IsLoopHeader() const { return loop_information() != NULL; }
83   bool IsStartBlock() const { return block_id() == 0; }
84   void PostProcessLoopHeader(IterationStatement* stmt);
85
86   bool IsFinished() const { return end_ != NULL; }
87   void AddPhi(HPhi* phi);
88   void RemovePhi(HPhi* phi);
89   void AddInstruction(HInstruction* instr, SourcePosition position);
90   bool Dominates(HBasicBlock* other) const;
91   bool EqualToOrDominates(HBasicBlock* other) const;
92   int LoopNestingDepth() const;
93
94   void SetInitialEnvironment(HEnvironment* env);
95   void ClearEnvironment() {
96     DCHECK(IsFinished());
97     DCHECK(end()->SuccessorCount() == 0);
98     last_environment_ = NULL;
99   }
100   bool HasEnvironment() const { return last_environment_ != NULL; }
101   void UpdateEnvironment(HEnvironment* env);
102   HBasicBlock* parent_loop_header() const { return parent_loop_header_; }
103
104   void set_parent_loop_header(HBasicBlock* block) {
105     DCHECK(parent_loop_header_ == NULL);
106     parent_loop_header_ = block;
107   }
108
109   bool HasParentLoopHeader() const { return parent_loop_header_ != NULL; }
110
111   void SetJoinId(BailoutId ast_id);
112
113   int PredecessorIndexOf(HBasicBlock* predecessor) const;
114   HPhi* AddNewPhi(int merged_index);
115   HSimulate* AddNewSimulate(BailoutId ast_id, SourcePosition position,
116                             RemovableSimulate removable = FIXED_SIMULATE) {
117     HSimulate* instr = CreateSimulate(ast_id, removable);
118     AddInstruction(instr, position);
119     return instr;
120   }
121   void AssignCommonDominator(HBasicBlock* other);
122   void AssignLoopSuccessorDominators();
123
124   // If a target block is tagged as an inline function return, all
125   // predecessors should contain the inlined exit sequence:
126   //
127   // LeaveInlined
128   // Simulate (caller's environment)
129   // Goto (target block)
130   bool IsInlineReturnTarget() const { return is_inline_return_target_; }
131   void MarkAsInlineReturnTarget(HBasicBlock* inlined_entry_block) {
132     is_inline_return_target_ = true;
133     inlined_entry_block_ = inlined_entry_block;
134   }
135   HBasicBlock* inlined_entry_block() { return inlined_entry_block_; }
136
137   bool IsDeoptimizing() const {
138     return end() != NULL && end()->IsDeoptimize();
139   }
140
141   void MarkUnreachable();
142   bool IsUnreachable() const { return !is_reachable_; }
143   bool IsReachable() const { return is_reachable_; }
144
145   bool IsLoopSuccessorDominator() const {
146     return dominates_loop_successors_;
147   }
148   void MarkAsLoopSuccessorDominator() {
149     dominates_loop_successors_ = true;
150   }
151
152   bool IsOrdered() const { return is_ordered_; }
153   void MarkAsOrdered() { is_ordered_ = true; }
154
155   void MarkSuccEdgeUnreachable(int succ);
156
157   inline Zone* zone() const;
158
159 #ifdef DEBUG
160   void Verify();
161 #endif
162
163  protected:
164   friend class HGraphBuilder;
165
166   HSimulate* CreateSimulate(BailoutId ast_id, RemovableSimulate removable);
167   void Finish(HControlInstruction* last, SourcePosition position);
168   void FinishExit(HControlInstruction* instruction, SourcePosition position);
169   void Goto(HBasicBlock* block, SourcePosition position,
170             FunctionState* state = NULL, bool add_simulate = true);
171   void GotoNoSimulate(HBasicBlock* block, SourcePosition position) {
172     Goto(block, position, NULL, false);
173   }
174
175   // Add the inlined function exit sequence, adding an HLeaveInlined
176   // instruction and updating the bailout environment.
177   void AddLeaveInlined(HValue* return_value, FunctionState* state,
178                        SourcePosition position);
179
180  private:
181   void RegisterPredecessor(HBasicBlock* pred);
182   void AddDominatedBlock(HBasicBlock* block);
183
184   int block_id_;
185   HGraph* graph_;
186   ZoneList<HPhi*> phis_;
187   HInstruction* first_;
188   HInstruction* last_;
189   HControlInstruction* end_;
190   HLoopInformation* loop_information_;
191   ZoneList<HBasicBlock*> predecessors_;
192   HBasicBlock* dominator_;
193   ZoneList<HBasicBlock*> dominated_blocks_;
194   HEnvironment* last_environment_;
195   // Outgoing parameter count at block exit, set during lithium translation.
196   int argument_count_;
197   // Instruction indices into the lithium code stream.
198   int first_instruction_index_;
199   int last_instruction_index_;
200   ZoneList<int> deleted_phis_;
201   HBasicBlock* parent_loop_header_;
202   // For blocks marked as inline return target: the block with HEnterInlined.
203   HBasicBlock* inlined_entry_block_;
204   bool is_inline_return_target_ : 1;
205   bool is_reachable_ : 1;
206   bool dominates_loop_successors_ : 1;
207   bool is_osr_entry_ : 1;
208   bool is_ordered_ : 1;
209 };
210
211
212 std::ostream& operator<<(std::ostream& os, const HBasicBlock& b);
213
214
215 class HPredecessorIterator final BASE_EMBEDDED {
216  public:
217   explicit HPredecessorIterator(HBasicBlock* block)
218       : predecessor_list_(block->predecessors()), current_(0) { }
219
220   bool Done() { return current_ >= predecessor_list_->length(); }
221   HBasicBlock* Current() { return predecessor_list_->at(current_); }
222   void Advance() { current_++; }
223
224  private:
225   const ZoneList<HBasicBlock*>* predecessor_list_;
226   int current_;
227 };
228
229
230 class HInstructionIterator final BASE_EMBEDDED {
231  public:
232   explicit HInstructionIterator(HBasicBlock* block)
233       : instr_(block->first()) {
234     next_ = Done() ? NULL : instr_->next();
235   }
236
237   inline bool Done() const { return instr_ == NULL; }
238   inline HInstruction* Current() { return instr_; }
239   inline void Advance() {
240     instr_ = next_;
241     next_ = Done() ? NULL : instr_->next();
242   }
243
244  private:
245   HInstruction* instr_;
246   HInstruction* next_;
247 };
248
249
250 class HLoopInformation final : public ZoneObject {
251  public:
252   HLoopInformation(HBasicBlock* loop_header, Zone* zone)
253       : back_edges_(4, zone),
254         loop_header_(loop_header),
255         blocks_(8, zone),
256         stack_check_(NULL) {
257     blocks_.Add(loop_header, zone);
258   }
259   ~HLoopInformation() {}
260
261   const ZoneList<HBasicBlock*>* back_edges() const { return &back_edges_; }
262   const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
263   HBasicBlock* loop_header() const { return loop_header_; }
264   HBasicBlock* GetLastBackEdge() const;
265   void RegisterBackEdge(HBasicBlock* block);
266
267   HStackCheck* stack_check() const { return stack_check_; }
268   void set_stack_check(HStackCheck* stack_check) {
269     stack_check_ = stack_check;
270   }
271
272   bool IsNestedInThisLoop(HLoopInformation* other) {
273     while (other != NULL) {
274       if (other == this) {
275         return true;
276       }
277       other = other->parent_loop();
278     }
279     return false;
280   }
281   HLoopInformation* parent_loop() {
282     HBasicBlock* parent_header = loop_header()->parent_loop_header();
283     return parent_header != NULL ? parent_header->loop_information() : NULL;
284   }
285
286  private:
287   void AddBlock(HBasicBlock* block);
288
289   ZoneList<HBasicBlock*> back_edges_;
290   HBasicBlock* loop_header_;
291   ZoneList<HBasicBlock*> blocks_;
292   HStackCheck* stack_check_;
293 };
294
295
296 class BoundsCheckTable;
297 class InductionVariableBlocksTable;
298 class HGraph final : public ZoneObject {
299  public:
300   explicit HGraph(CompilationInfo* info);
301
302   Isolate* isolate() const { return isolate_; }
303   Zone* zone() const { return zone_; }
304   CompilationInfo* info() const { return info_; }
305
306   const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
307   const ZoneList<HPhi*>* phi_list() const { return phi_list_; }
308   HBasicBlock* entry_block() const { return entry_block_; }
309   HEnvironment* start_environment() const { return start_environment_; }
310
311   void FinalizeUniqueness();
312   void OrderBlocks();
313   void AssignDominators();
314   void RestoreActualValues();
315
316   // Returns false if there are phi-uses of the arguments-object
317   // which are not supported by the optimizing compiler.
318   bool CheckArgumentsPhiUses();
319
320   // Returns false if there are phi-uses of an uninitialized const
321   // which are not supported by the optimizing compiler.
322   bool CheckConstPhiUses();
323
324   void CollectPhis();
325
326   HConstant* GetConstantUndefined();
327   HConstant* GetConstant0();
328   HConstant* GetConstant1();
329   HConstant* GetConstantMinus1();
330   HConstant* GetConstantTrue();
331   HConstant* GetConstantFalse();
332   HConstant* GetConstantBool(bool value);
333   HConstant* GetConstantHole();
334   HConstant* GetConstantNull();
335   HConstant* GetInvalidContext();
336
337   bool IsConstantUndefined(HConstant* constant);
338   bool IsConstant0(HConstant* constant);
339   bool IsConstant1(HConstant* constant);
340   bool IsConstantMinus1(HConstant* constant);
341   bool IsConstantTrue(HConstant* constant);
342   bool IsConstantFalse(HConstant* constant);
343   bool IsConstantHole(HConstant* constant);
344   bool IsConstantNull(HConstant* constant);
345   bool IsStandardConstant(HConstant* constant);
346
347   HBasicBlock* CreateBasicBlock();
348   HArgumentsObject* GetArgumentsObject() const {
349     return arguments_object_.get();
350   }
351
352   void SetArgumentsObject(HArgumentsObject* object) {
353     arguments_object_.set(object);
354   }
355
356   int GetMaximumValueID() const { return values_.length(); }
357   int GetNextBlockID() { return next_block_id_++; }
358   int GetNextValueID(HValue* value) {
359     DCHECK(!disallow_adding_new_values_);
360     values_.Add(value, zone());
361     return values_.length() - 1;
362   }
363   HValue* LookupValue(int id) const {
364     if (id >= 0 && id < values_.length()) return values_[id];
365     return NULL;
366   }
367   void DisallowAddingNewValues() {
368     disallow_adding_new_values_ = true;
369   }
370
371   bool Optimize(BailoutReason* bailout_reason);
372
373 #ifdef DEBUG
374   void Verify(bool do_full_verify) const;
375 #endif
376
377   bool has_osr() {
378     return osr_ != NULL;
379   }
380
381   void set_osr(HOsrBuilder* osr) {
382     osr_ = osr;
383   }
384
385   HOsrBuilder* osr() {
386     return osr_;
387   }
388
389   int update_type_change_checksum(int delta) {
390     type_change_checksum_ += delta;
391     return type_change_checksum_;
392   }
393
394   void update_maximum_environment_size(int environment_size) {
395     if (environment_size > maximum_environment_size_) {
396       maximum_environment_size_ = environment_size;
397     }
398   }
399   int maximum_environment_size() { return maximum_environment_size_; }
400
401   bool use_optimistic_licm() {
402     return use_optimistic_licm_;
403   }
404
405   void set_use_optimistic_licm(bool value) {
406     use_optimistic_licm_ = value;
407   }
408
409   void MarkRecursive() { is_recursive_ = true; }
410   bool is_recursive() const { return is_recursive_; }
411
412   void MarkDependsOnEmptyArrayProtoElements() {
413     // Add map dependency if not already added.
414     if (depends_on_empty_array_proto_elements_) return;
415     info()->dependencies()->AssumePropertyCell(
416         isolate()->factory()->array_protector());
417     depends_on_empty_array_proto_elements_ = true;
418   }
419
420   bool depends_on_empty_array_proto_elements() {
421     return depends_on_empty_array_proto_elements_;
422   }
423
424   bool has_uint32_instructions() {
425     DCHECK(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
426     return uint32_instructions_ != NULL;
427   }
428
429   ZoneList<HInstruction*>* uint32_instructions() {
430     DCHECK(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
431     return uint32_instructions_;
432   }
433
434   void RecordUint32Instruction(HInstruction* instr) {
435     DCHECK(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
436     if (uint32_instructions_ == NULL) {
437       uint32_instructions_ = new(zone()) ZoneList<HInstruction*>(4, zone());
438     }
439     uint32_instructions_->Add(instr, zone());
440   }
441
442   void IncrementInNoSideEffectsScope() { no_side_effects_scope_count_++; }
443   void DecrementInNoSideEffectsScope() { no_side_effects_scope_count_--; }
444   bool IsInsideNoSideEffectsScope() { return no_side_effects_scope_count_ > 0; }
445
446   // If we are tracking source positions then this function assigns a unique
447   // identifier to each inlining and dumps function source if it was inlined
448   // for the first time during the current optimization.
449   int TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
450                            SourcePosition position);
451
452   // Converts given SourcePosition to the absolute offset from the start of
453   // the corresponding script.
454   int SourcePositionToScriptPosition(SourcePosition position);
455
456  private:
457   HConstant* ReinsertConstantIfNecessary(HConstant* constant);
458   HConstant* GetConstant(SetOncePointer<HConstant>* pointer,
459                          int32_t integer_value);
460
461   template<class Phase>
462   void Run() {
463     Phase phase(this);
464     phase.Run();
465   }
466
467   Isolate* isolate_;
468   int next_block_id_;
469   HBasicBlock* entry_block_;
470   HEnvironment* start_environment_;
471   ZoneList<HBasicBlock*> blocks_;
472   ZoneList<HValue*> values_;
473   ZoneList<HPhi*>* phi_list_;
474   ZoneList<HInstruction*>* uint32_instructions_;
475   SetOncePointer<HConstant> constant_undefined_;
476   SetOncePointer<HConstant> constant_0_;
477   SetOncePointer<HConstant> constant_1_;
478   SetOncePointer<HConstant> constant_minus1_;
479   SetOncePointer<HConstant> constant_true_;
480   SetOncePointer<HConstant> constant_false_;
481   SetOncePointer<HConstant> constant_the_hole_;
482   SetOncePointer<HConstant> constant_null_;
483   SetOncePointer<HConstant> constant_invalid_context_;
484   SetOncePointer<HArgumentsObject> arguments_object_;
485
486   HOsrBuilder* osr_;
487
488   CompilationInfo* info_;
489   Zone* zone_;
490
491   bool is_recursive_;
492   bool use_optimistic_licm_;
493   bool depends_on_empty_array_proto_elements_;
494   int type_change_checksum_;
495   int maximum_environment_size_;
496   int no_side_effects_scope_count_;
497   bool disallow_adding_new_values_;
498
499   DISALLOW_COPY_AND_ASSIGN(HGraph);
500 };
501
502
503 Zone* HBasicBlock::zone() const { return graph_->zone(); }
504
505
506 // Type of stack frame an environment might refer to.
507 enum FrameType {
508   JS_FUNCTION,
509   JS_CONSTRUCT,
510   JS_GETTER,
511   JS_SETTER,
512   ARGUMENTS_ADAPTOR,
513   STUB
514 };
515
516
517 class HEnvironment final : public ZoneObject {
518  public:
519   HEnvironment(HEnvironment* outer,
520                Scope* scope,
521                Handle<JSFunction> closure,
522                Zone* zone);
523
524   HEnvironment(Zone* zone, int parameter_count);
525
526   HEnvironment* arguments_environment() {
527     return outer()->frame_type() == ARGUMENTS_ADAPTOR ? outer() : this;
528   }
529
530   // Simple accessors.
531   Handle<JSFunction> closure() const { return closure_; }
532   const ZoneList<HValue*>* values() const { return &values_; }
533   const GrowableBitVector* assigned_variables() const {
534     return &assigned_variables_;
535   }
536   FrameType frame_type() const { return frame_type_; }
537   int parameter_count() const { return parameter_count_; }
538   int specials_count() const { return specials_count_; }
539   int local_count() const { return local_count_; }
540   HEnvironment* outer() const { return outer_; }
541   int pop_count() const { return pop_count_; }
542   int push_count() const { return push_count_; }
543
544   BailoutId ast_id() const { return ast_id_; }
545   void set_ast_id(BailoutId id) { ast_id_ = id; }
546
547   HEnterInlined* entry() const { return entry_; }
548   void set_entry(HEnterInlined* entry) { entry_ = entry; }
549
550   int length() const { return values_.length(); }
551
552   int first_expression_index() const {
553     return parameter_count() + specials_count() + local_count();
554   }
555
556   int first_local_index() const {
557     return parameter_count() + specials_count();
558   }
559
560   void Bind(Variable* variable, HValue* value) {
561     Bind(IndexFor(variable), value);
562   }
563
564   void Bind(int index, HValue* value);
565
566   void BindContext(HValue* value) {
567     Bind(parameter_count(), value);
568   }
569
570   HValue* Lookup(Variable* variable) const {
571     return Lookup(IndexFor(variable));
572   }
573
574   HValue* Lookup(int index) const {
575     HValue* result = values_[index];
576     DCHECK(result != NULL);
577     return result;
578   }
579
580   HValue* context() const {
581     // Return first special.
582     return Lookup(parameter_count());
583   }
584
585   void Push(HValue* value) {
586     DCHECK(value != NULL);
587     ++push_count_;
588     values_.Add(value, zone());
589   }
590
591   HValue* Pop() {
592     DCHECK(!ExpressionStackIsEmpty());
593     if (push_count_ > 0) {
594       --push_count_;
595     } else {
596       ++pop_count_;
597     }
598     return values_.RemoveLast();
599   }
600
601   void Drop(int count);
602
603   HValue* Top() const { return ExpressionStackAt(0); }
604
605   bool ExpressionStackIsEmpty() const;
606
607   HValue* ExpressionStackAt(int index_from_top) const {
608     int index = length() - index_from_top - 1;
609     DCHECK(HasExpressionAt(index));
610     return values_[index];
611   }
612
613   void SetExpressionStackAt(int index_from_top, HValue* value);
614   HValue* RemoveExpressionStackAt(int index_from_top);
615
616   void Print() const;
617
618   HEnvironment* Copy() const;
619   HEnvironment* CopyWithoutHistory() const;
620   HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const;
621
622   // Create an "inlined version" of this environment, where the original
623   // environment is the outer environment but the top expression stack
624   // elements are moved to an inner environment as parameters.
625   HEnvironment* CopyForInlining(Handle<JSFunction> target,
626                                 int arguments,
627                                 FunctionLiteral* function,
628                                 HConstant* undefined,
629                                 InliningKind inlining_kind) const;
630
631   HEnvironment* DiscardInlined(bool drop_extra) {
632     HEnvironment* outer = outer_;
633     while (outer->frame_type() != JS_FUNCTION) outer = outer->outer_;
634     if (drop_extra) outer->Drop(1);
635     return outer;
636   }
637
638   void AddIncomingEdge(HBasicBlock* block, HEnvironment* other);
639
640   void ClearHistory() {
641     pop_count_ = 0;
642     push_count_ = 0;
643     assigned_variables_.Clear();
644   }
645
646   void SetValueAt(int index, HValue* value) {
647     DCHECK(index < length());
648     values_[index] = value;
649   }
650
651   // Map a variable to an environment index.  Parameter indices are shifted
652   // by 1 (receiver is parameter index -1 but environment index 0).
653   // Stack-allocated local indices are shifted by the number of parameters.
654   int IndexFor(Variable* variable) const {
655     DCHECK(variable->IsStackAllocated());
656     int shift = variable->IsParameter()
657         ? 1
658         : parameter_count_ + specials_count_;
659     return variable->index() + shift;
660   }
661
662   bool is_local_index(int i) const {
663     return i >= first_local_index() && i < first_expression_index();
664   }
665
666   bool is_parameter_index(int i) const {
667     return i >= 0 && i < parameter_count();
668   }
669
670   bool is_special_index(int i) const {
671     return i >= parameter_count() && i < parameter_count() + specials_count();
672   }
673
674   Zone* zone() const { return zone_; }
675
676  private:
677   HEnvironment(const HEnvironment* other, Zone* zone);
678
679   HEnvironment(HEnvironment* outer,
680                Handle<JSFunction> closure,
681                FrameType frame_type,
682                int arguments,
683                Zone* zone);
684
685   // Create an artificial stub environment (e.g. for argument adaptor or
686   // constructor stub).
687   HEnvironment* CreateStubEnvironment(HEnvironment* outer,
688                                       Handle<JSFunction> target,
689                                       FrameType frame_type,
690                                       int arguments) const;
691
692   // True if index is included in the expression stack part of the environment.
693   bool HasExpressionAt(int index) const;
694
695   void Initialize(int parameter_count, int local_count, int stack_height);
696   void Initialize(const HEnvironment* other);
697
698   Handle<JSFunction> closure_;
699   // Value array [parameters] [specials] [locals] [temporaries].
700   ZoneList<HValue*> values_;
701   GrowableBitVector assigned_variables_;
702   FrameType frame_type_;
703   int parameter_count_;
704   int specials_count_;
705   int local_count_;
706   HEnvironment* outer_;
707   HEnterInlined* entry_;
708   int pop_count_;
709   int push_count_;
710   BailoutId ast_id_;
711   Zone* zone_;
712 };
713
714
715 std::ostream& operator<<(std::ostream& os, const HEnvironment& env);
716
717
718 class HOptimizedGraphBuilder;
719
720 enum ArgumentsAllowedFlag {
721   ARGUMENTS_NOT_ALLOWED,
722   ARGUMENTS_ALLOWED,
723   ARGUMENTS_FAKED
724 };
725
726
727 class HIfContinuation;
728
729 // This class is not BASE_EMBEDDED because our inlining implementation uses
730 // new and delete.
731 class AstContext {
732  public:
733   bool IsEffect() const { return kind_ == Expression::kEffect; }
734   bool IsValue() const { return kind_ == Expression::kValue; }
735   bool IsTest() const { return kind_ == Expression::kTest; }
736
737   // 'Fill' this context with a hydrogen value.  The value is assumed to
738   // have already been inserted in the instruction stream (or not need to
739   // be, e.g., HPhi).  Call this function in tail position in the Visit
740   // functions for expressions.
741   virtual void ReturnValue(HValue* value) = 0;
742
743   // Add a hydrogen instruction to the instruction stream (recording an
744   // environment simulation if necessary) and then fill this context with
745   // the instruction as value.
746   virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id) = 0;
747
748   // Finishes the current basic block and materialize a boolean for
749   // value context, nothing for effect, generate a branch for test context.
750   // Call this function in tail position in the Visit functions for
751   // expressions.
752   virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id) = 0;
753
754   // Finishes the current basic block and materialize a boolean for
755   // value context, nothing for effect, generate a branch for test context.
756   // Call this function in tail position in the Visit functions for
757   // expressions that use an IfBuilder.
758   virtual void ReturnContinuation(HIfContinuation* continuation,
759                                   BailoutId ast_id) = 0;
760
761   void set_typeof_mode(TypeofMode typeof_mode) { typeof_mode_ = typeof_mode; }
762   TypeofMode typeof_mode() { return typeof_mode_; }
763
764  protected:
765   AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind);
766   virtual ~AstContext();
767
768   HOptimizedGraphBuilder* owner() const { return owner_; }
769
770   inline Zone* zone() const;
771
772   // We want to be able to assert, in a context-specific way, that the stack
773   // height makes sense when the context is filled.
774 #ifdef DEBUG
775   int original_length_;
776 #endif
777
778  private:
779   HOptimizedGraphBuilder* owner_;
780   Expression::Context kind_;
781   AstContext* outer_;
782   TypeofMode typeof_mode_;
783 };
784
785
786 class EffectContext final : public AstContext {
787  public:
788   explicit EffectContext(HOptimizedGraphBuilder* owner)
789       : AstContext(owner, Expression::kEffect) {
790   }
791   virtual ~EffectContext();
792
793   void ReturnValue(HValue* value) override;
794   virtual void ReturnInstruction(HInstruction* instr,
795                                  BailoutId ast_id) override;
796   virtual void ReturnControl(HControlInstruction* instr,
797                              BailoutId ast_id) override;
798   virtual void ReturnContinuation(HIfContinuation* continuation,
799                                   BailoutId ast_id) override;
800 };
801
802
803 class ValueContext final : public AstContext {
804  public:
805   ValueContext(HOptimizedGraphBuilder* owner, ArgumentsAllowedFlag flag)
806       : AstContext(owner, Expression::kValue), flag_(flag) {
807   }
808   virtual ~ValueContext();
809
810   void ReturnValue(HValue* value) override;
811   virtual void ReturnInstruction(HInstruction* instr,
812                                  BailoutId ast_id) override;
813   virtual void ReturnControl(HControlInstruction* instr,
814                              BailoutId ast_id) override;
815   virtual void ReturnContinuation(HIfContinuation* continuation,
816                                   BailoutId ast_id) override;
817
818   bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; }
819
820  private:
821   ArgumentsAllowedFlag flag_;
822 };
823
824
825 class TestContext final : public AstContext {
826  public:
827   TestContext(HOptimizedGraphBuilder* owner,
828               Expression* condition,
829               HBasicBlock* if_true,
830               HBasicBlock* if_false)
831       : AstContext(owner, Expression::kTest),
832         condition_(condition),
833         if_true_(if_true),
834         if_false_(if_false) {
835   }
836
837   void ReturnValue(HValue* value) override;
838   virtual void ReturnInstruction(HInstruction* instr,
839                                  BailoutId ast_id) override;
840   virtual void ReturnControl(HControlInstruction* instr,
841                              BailoutId ast_id) override;
842   virtual void ReturnContinuation(HIfContinuation* continuation,
843                                   BailoutId ast_id) override;
844
845   static TestContext* cast(AstContext* context) {
846     DCHECK(context->IsTest());
847     return reinterpret_cast<TestContext*>(context);
848   }
849
850   Expression* condition() const { return condition_; }
851   HBasicBlock* if_true() const { return if_true_; }
852   HBasicBlock* if_false() const { return if_false_; }
853
854  private:
855   // Build the shared core part of the translation unpacking a value into
856   // control flow.
857   void BuildBranch(HValue* value);
858
859   Expression* condition_;
860   HBasicBlock* if_true_;
861   HBasicBlock* if_false_;
862 };
863
864
865 class FunctionState final {
866  public:
867   FunctionState(HOptimizedGraphBuilder* owner,
868                 CompilationInfo* info,
869                 InliningKind inlining_kind,
870                 int inlining_id);
871   ~FunctionState();
872
873   CompilationInfo* compilation_info() { return compilation_info_; }
874   AstContext* call_context() { return call_context_; }
875   InliningKind inlining_kind() const { return inlining_kind_; }
876   HBasicBlock* function_return() { return function_return_; }
877   TestContext* test_context() { return test_context_; }
878   void ClearInlinedTestContext() {
879     delete test_context_;
880     test_context_ = NULL;
881   }
882
883   FunctionState* outer() { return outer_; }
884
885   HEnterInlined* entry() { return entry_; }
886   void set_entry(HEnterInlined* entry) { entry_ = entry; }
887
888   HArgumentsObject* arguments_object() { return arguments_object_; }
889   void set_arguments_object(HArgumentsObject* arguments_object) {
890     arguments_object_ = arguments_object;
891   }
892
893   HArgumentsElements* arguments_elements() { return arguments_elements_; }
894   void set_arguments_elements(HArgumentsElements* arguments_elements) {
895     arguments_elements_ = arguments_elements;
896   }
897
898   bool arguments_pushed() { return arguments_elements() != NULL; }
899
900   int inlining_id() const { return inlining_id_; }
901
902  private:
903   HOptimizedGraphBuilder* owner_;
904
905   CompilationInfo* compilation_info_;
906
907   // During function inlining, expression context of the call being
908   // inlined. NULL when not inlining.
909   AstContext* call_context_;
910
911   // The kind of call which is currently being inlined.
912   InliningKind inlining_kind_;
913
914   // When inlining in an effect or value context, this is the return block.
915   // It is NULL otherwise.  When inlining in a test context, there are a
916   // pair of return blocks in the context.  When not inlining, there is no
917   // local return point.
918   HBasicBlock* function_return_;
919
920   // When inlining a call in a test context, a context containing a pair of
921   // return blocks.  NULL in all other cases.
922   TestContext* test_context_;
923
924   // When inlining HEnterInlined instruction corresponding to the function
925   // entry.
926   HEnterInlined* entry_;
927
928   HArgumentsObject* arguments_object_;
929   HArgumentsElements* arguments_elements_;
930
931   int inlining_id_;
932   SourcePosition outer_source_position_;
933
934   FunctionState* outer_;
935 };
936
937
938 class HIfContinuation final {
939  public:
940   HIfContinuation()
941     : continuation_captured_(false),
942       true_branch_(NULL),
943       false_branch_(NULL) {}
944   HIfContinuation(HBasicBlock* true_branch,
945                   HBasicBlock* false_branch)
946       : continuation_captured_(true), true_branch_(true_branch),
947         false_branch_(false_branch) {}
948   ~HIfContinuation() { DCHECK(!continuation_captured_); }
949
950   void Capture(HBasicBlock* true_branch,
951                HBasicBlock* false_branch) {
952     DCHECK(!continuation_captured_);
953     true_branch_ = true_branch;
954     false_branch_ = false_branch;
955     continuation_captured_ = true;
956   }
957
958   void Continue(HBasicBlock** true_branch,
959                 HBasicBlock** false_branch) {
960     DCHECK(continuation_captured_);
961     *true_branch = true_branch_;
962     *false_branch = false_branch_;
963     continuation_captured_ = false;
964   }
965
966   bool IsTrueReachable() { return true_branch_ != NULL; }
967   bool IsFalseReachable() { return false_branch_ != NULL; }
968   bool TrueAndFalseReachable() {
969     return IsTrueReachable() || IsFalseReachable();
970   }
971
972   HBasicBlock* true_branch() const { return true_branch_; }
973   HBasicBlock* false_branch() const { return false_branch_; }
974
975  private:
976   bool continuation_captured_;
977   HBasicBlock* true_branch_;
978   HBasicBlock* false_branch_;
979 };
980
981
982 class HAllocationMode final BASE_EMBEDDED {
983  public:
984   explicit HAllocationMode(Handle<AllocationSite> feedback_site)
985       : current_site_(NULL), feedback_site_(feedback_site),
986         pretenure_flag_(NOT_TENURED) {}
987   explicit HAllocationMode(HValue* current_site)
988       : current_site_(current_site), pretenure_flag_(NOT_TENURED) {}
989   explicit HAllocationMode(PretenureFlag pretenure_flag)
990       : current_site_(NULL), pretenure_flag_(pretenure_flag) {}
991   HAllocationMode()
992       : current_site_(NULL), pretenure_flag_(NOT_TENURED) {}
993
994   HValue* current_site() const { return current_site_; }
995   Handle<AllocationSite> feedback_site() const { return feedback_site_; }
996
997   bool CreateAllocationMementos() const WARN_UNUSED_RESULT {
998     return current_site() != NULL;
999   }
1000
1001   PretenureFlag GetPretenureMode() const WARN_UNUSED_RESULT {
1002     if (!feedback_site().is_null()) return feedback_site()->GetPretenureMode();
1003     return pretenure_flag_;
1004   }
1005
1006  private:
1007   HValue* current_site_;
1008   Handle<AllocationSite> feedback_site_;
1009   PretenureFlag pretenure_flag_;
1010 };
1011
1012
1013 class HGraphBuilder {
1014  public:
1015   explicit HGraphBuilder(CompilationInfo* info)
1016       : info_(info),
1017         graph_(NULL),
1018         current_block_(NULL),
1019         scope_(info->scope()),
1020         position_(SourcePosition::Unknown()),
1021         start_position_(0) {}
1022   virtual ~HGraphBuilder() {}
1023
1024   Scope* scope() const { return scope_; }
1025   void set_scope(Scope* scope) { scope_ = scope; }
1026
1027   HBasicBlock* current_block() const { return current_block_; }
1028   void set_current_block(HBasicBlock* block) { current_block_ = block; }
1029   HEnvironment* environment() const {
1030     return current_block()->last_environment();
1031   }
1032   Zone* zone() const { return info_->zone(); }
1033   HGraph* graph() const { return graph_; }
1034   Isolate* isolate() const { return graph_->isolate(); }
1035   CompilationInfo* top_info() { return info_; }
1036
1037   HGraph* CreateGraph();
1038
1039   // Bailout environment manipulation.
1040   void Push(HValue* value) { environment()->Push(value); }
1041   HValue* Pop() { return environment()->Pop(); }
1042
1043   virtual HValue* context() = 0;
1044
1045   // Adding instructions.
1046   HInstruction* AddInstruction(HInstruction* instr);
1047   void FinishCurrentBlock(HControlInstruction* last);
1048   void FinishExitCurrentBlock(HControlInstruction* instruction);
1049
1050   void Goto(HBasicBlock* from,
1051             HBasicBlock* target,
1052             FunctionState* state = NULL,
1053             bool add_simulate = true) {
1054     from->Goto(target, source_position(), state, add_simulate);
1055   }
1056   void Goto(HBasicBlock* target,
1057             FunctionState* state = NULL,
1058             bool add_simulate = true) {
1059     Goto(current_block(), target, state, add_simulate);
1060   }
1061   void GotoNoSimulate(HBasicBlock* from, HBasicBlock* target) {
1062     Goto(from, target, NULL, false);
1063   }
1064   void GotoNoSimulate(HBasicBlock* target) {
1065     Goto(target, NULL, false);
1066   }
1067   void AddLeaveInlined(HBasicBlock* block,
1068                        HValue* return_value,
1069                        FunctionState* state) {
1070     block->AddLeaveInlined(return_value, state, source_position());
1071   }
1072   void AddLeaveInlined(HValue* return_value, FunctionState* state) {
1073     return AddLeaveInlined(current_block(), return_value, state);
1074   }
1075
1076   template <class I>
1077   HInstruction* NewUncasted() {
1078     return I::New(isolate(), zone(), context());
1079   }
1080
1081   template <class I>
1082   I* New() {
1083     return I::New(isolate(), zone(), context());
1084   }
1085
1086   template<class I>
1087   HInstruction* AddUncasted() { return AddInstruction(NewUncasted<I>());}
1088
1089   template<class I>
1090   I* Add() { return AddInstructionTyped(New<I>());}
1091
1092   template<class I, class P1>
1093   HInstruction* NewUncasted(P1 p1) {
1094     return I::New(isolate(), zone(), context(), p1);
1095   }
1096
1097   template <class I, class P1>
1098   I* New(P1 p1) {
1099     return I::New(isolate(), zone(), context(), p1);
1100   }
1101
1102   template<class I, class P1>
1103   HInstruction* AddUncasted(P1 p1) {
1104     HInstruction* result = AddInstruction(NewUncasted<I>(p1));
1105     // Specializations must have their parameters properly casted
1106     // to avoid landing here.
1107     DCHECK(!result->IsReturn() && !result->IsSimulate() &&
1108            !result->IsDeoptimize());
1109     return result;
1110   }
1111
1112   template<class I, class P1>
1113   I* Add(P1 p1) {
1114     I* result = AddInstructionTyped(New<I>(p1));
1115     // Specializations must have their parameters properly casted
1116     // to avoid landing here.
1117     DCHECK(!result->IsReturn() && !result->IsSimulate() &&
1118            !result->IsDeoptimize());
1119     return result;
1120   }
1121
1122   template<class I, class P1, class P2>
1123   HInstruction* NewUncasted(P1 p1, P2 p2) {
1124     return I::New(isolate(), zone(), context(), p1, p2);
1125   }
1126
1127   template<class I, class P1, class P2>
1128   I* New(P1 p1, P2 p2) {
1129     return I::New(isolate(), zone(), context(), p1, p2);
1130   }
1131
1132   template<class I, class P1, class P2>
1133   HInstruction* AddUncasted(P1 p1, P2 p2) {
1134     HInstruction* result = AddInstruction(NewUncasted<I>(p1, p2));
1135     // Specializations must have their parameters properly casted
1136     // to avoid landing here.
1137     DCHECK(!result->IsSimulate());
1138     return result;
1139   }
1140
1141   template<class I, class P1, class P2>
1142   I* Add(P1 p1, P2 p2) {
1143     I* result = AddInstructionTyped(New<I>(p1, p2));
1144     // Specializations must have their parameters properly casted
1145     // to avoid landing here.
1146     DCHECK(!result->IsSimulate());
1147     return result;
1148   }
1149
1150   template<class I, class P1, class P2, class P3>
1151   HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3) {
1152     return I::New(isolate(), zone(), context(), p1, p2, p3);
1153   }
1154
1155   template<class I, class P1, class P2, class P3>
1156   I* New(P1 p1, P2 p2, P3 p3) {
1157     return I::New(isolate(), zone(), context(), p1, p2, p3);
1158   }
1159
1160   template<class I, class P1, class P2, class P3>
1161   HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3) {
1162     return AddInstruction(NewUncasted<I>(p1, p2, p3));
1163   }
1164
1165   template<class I, class P1, class P2, class P3>
1166   I* Add(P1 p1, P2 p2, P3 p3) {
1167     return AddInstructionTyped(New<I>(p1, p2, p3));
1168   }
1169
1170   template<class I, class P1, class P2, class P3, class P4>
1171   HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4) {
1172     return I::New(isolate(), zone(), context(), p1, p2, p3, p4);
1173   }
1174
1175   template<class I, class P1, class P2, class P3, class P4>
1176   I* New(P1 p1, P2 p2, P3 p3, P4 p4) {
1177     return I::New(isolate(), zone(), context(), p1, p2, p3, p4);
1178   }
1179
1180   template<class I, class P1, class P2, class P3, class P4>
1181   HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4) {
1182     return AddInstruction(NewUncasted<I>(p1, p2, p3, p4));
1183   }
1184
1185   template<class I, class P1, class P2, class P3, class P4>
1186   I* Add(P1 p1, P2 p2, P3 p3, P4 p4) {
1187     return AddInstructionTyped(New<I>(p1, p2, p3, p4));
1188   }
1189
1190   template<class I, class P1, class P2, class P3, class P4, class P5>
1191   HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1192     return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5);
1193   }
1194
1195   template<class I, class P1, class P2, class P3, class P4, class P5>
1196   I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1197     return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5);
1198   }
1199
1200   template<class I, class P1, class P2, class P3, class P4, class P5>
1201   HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1202     return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5));
1203   }
1204
1205   template<class I, class P1, class P2, class P3, class P4, class P5>
1206   I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
1207     return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5));
1208   }
1209
1210   template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
1211   HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1212     return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6);
1213   }
1214
1215   template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
1216   I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1217     return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6);
1218   }
1219
1220   template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
1221   HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1222     return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6));
1223   }
1224
1225   template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
1226   I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
1227     return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6));
1228   }
1229
1230   template<class I, class P1, class P2, class P3, class P4,
1231       class P5, class P6, class P7>
1232   HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1233     return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6, p7);
1234   }
1235
1236   template<class I, class P1, class P2, class P3, class P4,
1237       class P5, class P6, class P7>
1238       I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1239     return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6, p7);
1240   }
1241
1242   template<class I, class P1, class P2, class P3,
1243            class P4, class P5, class P6, class P7>
1244   HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1245     return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7));
1246   }
1247
1248   template<class I, class P1, class P2, class P3,
1249            class P4, class P5, class P6, class P7>
1250   I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
1251     return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7));
1252   }
1253
1254   template<class I, class P1, class P2, class P3, class P4,
1255       class P5, class P6, class P7, class P8>
1256   HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4,
1257                             P5 p5, P6 p6, P7 p7, P8 p8) {
1258     return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8);
1259   }
1260
1261   template<class I, class P1, class P2, class P3, class P4,
1262       class P5, class P6, class P7, class P8>
1263       I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
1264     return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8);
1265   }
1266
1267   template<class I, class P1, class P2, class P3, class P4,
1268            class P5, class P6, class P7, class P8>
1269   HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4,
1270                             P5 p5, P6 p6, P7 p7, P8 p8) {
1271     return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8));
1272   }
1273
1274   template<class I, class P1, class P2, class P3, class P4,
1275            class P5, class P6, class P7, class P8>
1276   I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
1277     return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7, p8));
1278   }
1279
1280   void AddSimulate(BailoutId id, RemovableSimulate removable = FIXED_SIMULATE);
1281
1282   // When initializing arrays, we'll unfold the loop if the number of elements
1283   // is known at compile time and is <= kElementLoopUnrollThreshold.
1284   static const int kElementLoopUnrollThreshold = 8;
1285
1286  protected:
1287   virtual bool BuildGraph() = 0;
1288
1289   HBasicBlock* CreateBasicBlock(HEnvironment* env);
1290   HBasicBlock* CreateLoopHeaderBlock();
1291
1292   template <class BitFieldClass>
1293   HValue* BuildDecodeField(HValue* encoded_field) {
1294     HValue* mask_value = Add<HConstant>(static_cast<int>(BitFieldClass::kMask));
1295     HValue* masked_field =
1296         AddUncasted<HBitwise>(Token::BIT_AND, encoded_field, mask_value);
1297     return AddUncasted<HShr>(masked_field,
1298         Add<HConstant>(static_cast<int>(BitFieldClass::kShift)));
1299   }
1300
1301   HValue* BuildGetElementsKind(HValue* object);
1302
1303   HValue* BuildCheckHeapObject(HValue* object);
1304   HValue* BuildCheckString(HValue* string);
1305   HValue* BuildWrapReceiver(HValue* object, HValue* function);
1306
1307   // Building common constructs
1308   HValue* BuildCheckForCapacityGrow(HValue* object,
1309                                     HValue* elements,
1310                                     ElementsKind kind,
1311                                     HValue* length,
1312                                     HValue* key,
1313                                     bool is_js_array,
1314                                     PropertyAccessType access_type);
1315
1316   HValue* BuildCheckAndGrowElementsCapacity(HValue* object, HValue* elements,
1317                                             ElementsKind kind, HValue* length,
1318                                             HValue* capacity, HValue* key);
1319
1320   HValue* BuildCopyElementsOnWrite(HValue* object,
1321                                    HValue* elements,
1322                                    ElementsKind kind,
1323                                    HValue* length);
1324
1325   void BuildTransitionElementsKind(HValue* object,
1326                                    HValue* map,
1327                                    ElementsKind from_kind,
1328                                    ElementsKind to_kind,
1329                                    bool is_jsarray);
1330
1331   HValue* BuildNumberToString(HValue* object, Type* type);
1332   HValue* BuildToObject(HValue* receiver);
1333
1334   void BuildJSObjectCheck(HValue* receiver,
1335                           int bit_field_mask);
1336
1337   // Checks a key value that's being used for a keyed element access context. If
1338   // the key is a index, i.e. a smi or a number in a unique string with a cached
1339   // numeric value, the "true" of the continuation is joined. Otherwise,
1340   // if the key is a name or a unique string, the "false" of the continuation is
1341   // joined. Otherwise, a deoptimization is triggered. In both paths of the
1342   // continuation, the key is pushed on the top of the environment.
1343   void BuildKeyedIndexCheck(HValue* key,
1344                             HIfContinuation* join_continuation);
1345
1346   // Checks the properties of an object if they are in dictionary case, in which
1347   // case "true" of continuation is taken, otherwise the "false"
1348   void BuildTestForDictionaryProperties(HValue* object,
1349                                         HIfContinuation* continuation);
1350
1351   void BuildNonGlobalObjectCheck(HValue* receiver);
1352
1353   HValue* BuildKeyedLookupCacheHash(HValue* object,
1354                                     HValue* key);
1355
1356   HValue* BuildUncheckedDictionaryElementLoad(HValue* receiver,
1357                                               HValue* elements, HValue* key,
1358                                               HValue* hash,
1359                                               LanguageMode language_mode);
1360
1361   // ES6 section 7.4.7 CreateIterResultObject ( value, done )
1362   HValue* BuildCreateIterResultObject(HValue* value, HValue* done);
1363
1364   HValue* BuildRegExpConstructResult(HValue* length,
1365                                      HValue* index,
1366                                      HValue* input);
1367
1368   // Allocates a new object according with the given allocation properties.
1369   HAllocate* BuildAllocate(HValue* object_size,
1370                            HType type,
1371                            InstanceType instance_type,
1372                            HAllocationMode allocation_mode);
1373   // Computes the sum of two string lengths, taking care of overflow handling.
1374   HValue* BuildAddStringLengths(HValue* left_length, HValue* right_length);
1375   // Creates a cons string using the two input strings.
1376   HValue* BuildCreateConsString(HValue* length,
1377                                 HValue* left,
1378                                 HValue* right,
1379                                 HAllocationMode allocation_mode);
1380   // Copies characters from one sequential string to another.
1381   void BuildCopySeqStringChars(HValue* src,
1382                                HValue* src_offset,
1383                                String::Encoding src_encoding,
1384                                HValue* dst,
1385                                HValue* dst_offset,
1386                                String::Encoding dst_encoding,
1387                                HValue* length);
1388
1389   // Align an object size to object alignment boundary
1390   HValue* BuildObjectSizeAlignment(HValue* unaligned_size, int header_size);
1391
1392   // Both operands are non-empty strings.
1393   HValue* BuildUncheckedStringAdd(HValue* left,
1394                                   HValue* right,
1395                                   HAllocationMode allocation_mode);
1396   // Add two strings using allocation mode, validating type feedback.
1397   HValue* BuildStringAdd(HValue* left,
1398                          HValue* right,
1399                          HAllocationMode allocation_mode);
1400
1401   HInstruction* BuildUncheckedMonomorphicElementAccess(
1402       HValue* checked_object,
1403       HValue* key,
1404       HValue* val,
1405       bool is_js_array,
1406       ElementsKind elements_kind,
1407       PropertyAccessType access_type,
1408       LoadKeyedHoleMode load_mode,
1409       KeyedAccessStoreMode store_mode);
1410
1411   HInstruction* AddElementAccess(
1412       HValue* elements,
1413       HValue* checked_key,
1414       HValue* val,
1415       HValue* dependency,
1416       ElementsKind elements_kind,
1417       PropertyAccessType access_type,
1418       LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE);
1419
1420   HInstruction* AddLoadStringInstanceType(HValue* string);
1421   HInstruction* AddLoadStringLength(HValue* string);
1422   HInstruction* BuildLoadStringLength(HValue* string);
1423   HStoreNamedField* AddStoreMapConstant(HValue* object, Handle<Map> map) {
1424     return Add<HStoreNamedField>(object, HObjectAccess::ForMap(),
1425                                  Add<HConstant>(map));
1426   }
1427   HLoadNamedField* AddLoadMap(HValue* object,
1428                               HValue* dependency = NULL);
1429   HLoadNamedField* AddLoadElements(HValue* object,
1430                                    HValue* dependency = NULL);
1431
1432   bool MatchRotateRight(HValue* left,
1433                         HValue* right,
1434                         HValue** operand,
1435                         HValue** shift_amount);
1436
1437   HValue* BuildBinaryOperation(Token::Value op, HValue* left, HValue* right,
1438                                Type* left_type, Type* right_type,
1439                                Type* result_type, Maybe<int> fixed_right_arg,
1440                                HAllocationMode allocation_mode,
1441                                Strength strength,
1442                                BailoutId opt_id = BailoutId::None());
1443
1444   HLoadNamedField* AddLoadFixedArrayLength(HValue *object,
1445                                            HValue *dependency = NULL);
1446
1447   HLoadNamedField* AddLoadArrayLength(HValue *object,
1448                                       ElementsKind kind,
1449                                       HValue *dependency = NULL);
1450
1451   HValue* AddLoadJSBuiltin(int context_index);
1452
1453   HValue* EnforceNumberType(HValue* number, Type* expected);
1454   HValue* TruncateToNumber(HValue* value, Type** expected);
1455
1456   void FinishExitWithHardDeoptimization(Deoptimizer::DeoptReason reason);
1457
1458   void AddIncrementCounter(StatsCounter* counter);
1459
1460   class IfBuilder final {
1461    public:
1462     // If using this constructor, Initialize() must be called explicitly!
1463     IfBuilder();
1464
1465     explicit IfBuilder(HGraphBuilder* builder);
1466     IfBuilder(HGraphBuilder* builder,
1467               HIfContinuation* continuation);
1468
1469     ~IfBuilder() {
1470       if (!finished_) End();
1471     }
1472
1473     void Initialize(HGraphBuilder* builder);
1474
1475     template<class Condition>
1476     Condition* If(HValue *p) {
1477       Condition* compare = builder()->New<Condition>(p);
1478       AddCompare(compare);
1479       return compare;
1480     }
1481
1482     template<class Condition, class P2>
1483     Condition* If(HValue* p1, P2 p2) {
1484       Condition* compare = builder()->New<Condition>(p1, p2);
1485       AddCompare(compare);
1486       return compare;
1487     }
1488
1489     template<class Condition, class P2, class P3>
1490     Condition* If(HValue* p1, P2 p2, P3 p3) {
1491       Condition* compare = builder()->New<Condition>(p1, p2, p3);
1492       AddCompare(compare);
1493       return compare;
1494     }
1495
1496     template<class Condition>
1497     Condition* IfNot(HValue* p) {
1498       Condition* compare = If<Condition>(p);
1499       compare->Not();
1500       return compare;
1501     }
1502
1503     template<class Condition, class P2>
1504     Condition* IfNot(HValue* p1, P2 p2) {
1505       Condition* compare = If<Condition>(p1, p2);
1506       compare->Not();
1507       return compare;
1508     }
1509
1510     template<class Condition, class P2, class P3>
1511     Condition* IfNot(HValue* p1, P2 p2, P3 p3) {
1512       Condition* compare = If<Condition>(p1, p2, p3);
1513       compare->Not();
1514       return compare;
1515     }
1516
1517     template<class Condition>
1518     Condition* OrIf(HValue *p) {
1519       Or();
1520       return If<Condition>(p);
1521     }
1522
1523     template<class Condition, class P2>
1524     Condition* OrIf(HValue* p1, P2 p2) {
1525       Or();
1526       return If<Condition>(p1, p2);
1527     }
1528
1529     template<class Condition, class P2, class P3>
1530     Condition* OrIf(HValue* p1, P2 p2, P3 p3) {
1531       Or();
1532       return If<Condition>(p1, p2, p3);
1533     }
1534
1535     template<class Condition>
1536     Condition* AndIf(HValue *p) {
1537       And();
1538       return If<Condition>(p);
1539     }
1540
1541     template<class Condition, class P2>
1542     Condition* AndIf(HValue* p1, P2 p2) {
1543       And();
1544       return If<Condition>(p1, p2);
1545     }
1546
1547     template<class Condition, class P2, class P3>
1548     Condition* AndIf(HValue* p1, P2 p2, P3 p3) {
1549       And();
1550       return If<Condition>(p1, p2, p3);
1551     }
1552
1553     void Or();
1554     void And();
1555
1556     // Captures the current state of this IfBuilder in the specified
1557     // continuation and ends this IfBuilder.
1558     void CaptureContinuation(HIfContinuation* continuation);
1559
1560     // Joins the specified continuation from this IfBuilder and ends this
1561     // IfBuilder. This appends a Goto instruction from the true branch of
1562     // this IfBuilder to the true branch of the continuation unless the
1563     // true branch of this IfBuilder is already finished. And vice versa
1564     // for the false branch.
1565     //
1566     // The basic idea is as follows: You have several nested IfBuilder's
1567     // that you want to join based on two possible outcomes (i.e. success
1568     // and failure, or whatever). You can do this easily using this method
1569     // now, for example:
1570     //
1571     //   HIfContinuation cont(graph()->CreateBasicBlock(),
1572     //                        graph()->CreateBasicBlock());
1573     //   ...
1574     //     IfBuilder if_whatever(this);
1575     //     if_whatever.If<Condition>(arg);
1576     //     if_whatever.Then();
1577     //     ...
1578     //     if_whatever.Else();
1579     //     ...
1580     //     if_whatever.JoinContinuation(&cont);
1581     //   ...
1582     //     IfBuilder if_something(this);
1583     //     if_something.If<Condition>(arg1, arg2);
1584     //     if_something.Then();
1585     //     ...
1586     //     if_something.Else();
1587     //     ...
1588     //     if_something.JoinContinuation(&cont);
1589     //   ...
1590     //   IfBuilder if_finally(this, &cont);
1591     //   if_finally.Then();
1592     //   // continues after then code of if_whatever or if_something.
1593     //   ...
1594     //   if_finally.Else();
1595     //   // continues after else code of if_whatever or if_something.
1596     //   ...
1597     //   if_finally.End();
1598     void JoinContinuation(HIfContinuation* continuation);
1599
1600     void Then();
1601     void Else();
1602     void End();
1603     void EndUnreachable();
1604
1605     void Deopt(Deoptimizer::DeoptReason reason);
1606     void ThenDeopt(Deoptimizer::DeoptReason reason) {
1607       Then();
1608       Deopt(reason);
1609     }
1610     void ElseDeopt(Deoptimizer::DeoptReason reason) {
1611       Else();
1612       Deopt(reason);
1613     }
1614
1615     void Return(HValue* value);
1616
1617    private:
1618     void InitializeDontCreateBlocks(HGraphBuilder* builder);
1619
1620     HControlInstruction* AddCompare(HControlInstruction* compare);
1621
1622     HGraphBuilder* builder() const {
1623       DCHECK(builder_ != NULL);  // Have you called "Initialize"?
1624       return builder_;
1625     }
1626
1627     void AddMergeAtJoinBlock(bool deopt);
1628
1629     void Finish();
1630     void Finish(HBasicBlock** then_continuation,
1631                 HBasicBlock** else_continuation);
1632
1633     class MergeAtJoinBlock : public ZoneObject {
1634      public:
1635       MergeAtJoinBlock(HBasicBlock* block,
1636                        bool deopt,
1637                        MergeAtJoinBlock* next)
1638         : block_(block),
1639           deopt_(deopt),
1640           next_(next) {}
1641       HBasicBlock* block_;
1642       bool deopt_;
1643       MergeAtJoinBlock* next_;
1644     };
1645
1646     HGraphBuilder* builder_;
1647     bool finished_ : 1;
1648     bool did_then_ : 1;
1649     bool did_else_ : 1;
1650     bool did_else_if_ : 1;
1651     bool did_and_ : 1;
1652     bool did_or_ : 1;
1653     bool captured_ : 1;
1654     bool needs_compare_ : 1;
1655     bool pending_merge_block_ : 1;
1656     HBasicBlock* first_true_block_;
1657     HBasicBlock* first_false_block_;
1658     HBasicBlock* split_edge_merge_block_;
1659     MergeAtJoinBlock* merge_at_join_blocks_;
1660     int normal_merge_at_join_block_count_;
1661     int deopt_merge_at_join_block_count_;
1662   };
1663
1664   class LoopBuilder final {
1665    public:
1666     enum Direction {
1667       kPreIncrement,
1668       kPostIncrement,
1669       kPreDecrement,
1670       kPostDecrement,
1671       kWhileTrue
1672     };
1673
1674     explicit LoopBuilder(HGraphBuilder* builder);  // while (true) {...}
1675     LoopBuilder(HGraphBuilder* builder,
1676                 HValue* context,
1677                 Direction direction);
1678     LoopBuilder(HGraphBuilder* builder,
1679                 HValue* context,
1680                 Direction direction,
1681                 HValue* increment_amount);
1682
1683     ~LoopBuilder() {
1684       DCHECK(finished_);
1685     }
1686
1687     HValue* BeginBody(
1688         HValue* initial,
1689         HValue* terminating,
1690         Token::Value token);
1691
1692     void BeginBody(int drop_count);
1693
1694     void Break();
1695
1696     void EndBody();
1697
1698    private:
1699     void Initialize(HGraphBuilder* builder, HValue* context,
1700                     Direction direction, HValue* increment_amount);
1701     Zone* zone() { return builder_->zone(); }
1702
1703     HGraphBuilder* builder_;
1704     HValue* context_;
1705     HValue* increment_amount_;
1706     HInstruction* increment_;
1707     HPhi* phi_;
1708     HBasicBlock* header_block_;
1709     HBasicBlock* body_block_;
1710     HBasicBlock* exit_block_;
1711     HBasicBlock* exit_trampoline_block_;
1712     Direction direction_;
1713     bool finished_;
1714   };
1715
1716   HValue* BuildNewElementsCapacity(HValue* old_capacity);
1717
1718   class JSArrayBuilder final {
1719    public:
1720     JSArrayBuilder(HGraphBuilder* builder,
1721                    ElementsKind kind,
1722                    HValue* allocation_site_payload,
1723                    HValue* constructor_function,
1724                    AllocationSiteOverrideMode override_mode);
1725
1726     JSArrayBuilder(HGraphBuilder* builder,
1727                    ElementsKind kind,
1728                    HValue* constructor_function = NULL);
1729
1730     enum FillMode {
1731       DONT_FILL_WITH_HOLE,
1732       FILL_WITH_HOLE
1733     };
1734
1735     ElementsKind kind() { return kind_; }
1736     HAllocate* elements_location() { return elements_location_; }
1737
1738     HAllocate* AllocateEmptyArray();
1739     HAllocate* AllocateArray(HValue* capacity,
1740                              HValue* length_field,
1741                              FillMode fill_mode = FILL_WITH_HOLE);
1742     // Use these allocators when capacity could be unknown at compile time
1743     // but its limit is known. For constant |capacity| the value of
1744     // |capacity_upper_bound| is ignored and the actual |capacity|
1745     // value is used as an upper bound.
1746     HAllocate* AllocateArray(HValue* capacity,
1747                              int capacity_upper_bound,
1748                              HValue* length_field,
1749                              FillMode fill_mode = FILL_WITH_HOLE);
1750     HAllocate* AllocateArray(HValue* capacity,
1751                              HConstant* capacity_upper_bound,
1752                              HValue* length_field,
1753                              FillMode fill_mode = FILL_WITH_HOLE);
1754     HValue* GetElementsLocation() { return elements_location_; }
1755     HValue* EmitMapCode();
1756
1757    private:
1758     Zone* zone() const { return builder_->zone(); }
1759     int elements_size() const {
1760       return IsFastDoubleElementsKind(kind_) ? kDoubleSize : kPointerSize;
1761     }
1762     HGraphBuilder* builder() { return builder_; }
1763     HGraph* graph() { return builder_->graph(); }
1764     int initial_capacity() {
1765       STATIC_ASSERT(JSArray::kPreallocatedArrayElements > 0);
1766       return JSArray::kPreallocatedArrayElements;
1767     }
1768
1769     HValue* EmitInternalMapCode();
1770
1771     HGraphBuilder* builder_;
1772     ElementsKind kind_;
1773     AllocationSiteMode mode_;
1774     HValue* allocation_site_payload_;
1775     HValue* constructor_function_;
1776     HAllocate* elements_location_;
1777   };
1778
1779   HValue* BuildAllocateArrayFromLength(JSArrayBuilder* array_builder,
1780                                        HValue* length_argument);
1781   HValue* BuildCalculateElementsSize(ElementsKind kind,
1782                                      HValue* capacity);
1783   HAllocate* AllocateJSArrayObject(AllocationSiteMode mode);
1784   HConstant* EstablishElementsAllocationSize(ElementsKind kind, int capacity);
1785
1786   HAllocate* BuildAllocateElements(ElementsKind kind, HValue* size_in_bytes);
1787
1788   void BuildInitializeElementsHeader(HValue* elements,
1789                                      ElementsKind kind,
1790                                      HValue* capacity);
1791
1792   // Build allocation and header initialization code for respective successor
1793   // of FixedArrayBase.
1794   HValue* BuildAllocateAndInitializeArray(ElementsKind kind, HValue* capacity);
1795
1796   // |array| must have been allocated with enough room for
1797   // 1) the JSArray and 2) an AllocationMemento if mode requires it.
1798   // If the |elements| value provided is NULL then the array elements storage
1799   // is initialized with empty array.
1800   void BuildJSArrayHeader(HValue* array,
1801                           HValue* array_map,
1802                           HValue* elements,
1803                           AllocationSiteMode mode,
1804                           ElementsKind elements_kind,
1805                           HValue* allocation_site_payload,
1806                           HValue* length_field);
1807
1808   HValue* BuildGrowElementsCapacity(HValue* object,
1809                                     HValue* elements,
1810                                     ElementsKind kind,
1811                                     ElementsKind new_kind,
1812                                     HValue* length,
1813                                     HValue* new_capacity);
1814
1815   void BuildFillElementsWithValue(HValue* elements,
1816                                   ElementsKind elements_kind,
1817                                   HValue* from,
1818                                   HValue* to,
1819                                   HValue* value);
1820
1821   void BuildFillElementsWithHole(HValue* elements,
1822                                  ElementsKind elements_kind,
1823                                  HValue* from,
1824                                  HValue* to);
1825
1826   void BuildCopyProperties(HValue* from_properties, HValue* to_properties,
1827                            HValue* length, HValue* capacity);
1828
1829   void BuildCopyElements(HValue* from_elements,
1830                          ElementsKind from_elements_kind,
1831                          HValue* to_elements,
1832                          ElementsKind to_elements_kind,
1833                          HValue* length,
1834                          HValue* capacity);
1835
1836   HValue* BuildCloneShallowArrayCow(HValue* boilerplate,
1837                                     HValue* allocation_site,
1838                                     AllocationSiteMode mode,
1839                                     ElementsKind kind);
1840
1841   HValue* BuildCloneShallowArrayEmpty(HValue* boilerplate,
1842                                       HValue* allocation_site,
1843                                       AllocationSiteMode mode);
1844
1845   HValue* BuildCloneShallowArrayNonEmpty(HValue* boilerplate,
1846                                          HValue* allocation_site,
1847                                          AllocationSiteMode mode,
1848                                          ElementsKind kind);
1849
1850   HValue* BuildElementIndexHash(HValue* index);
1851
1852   enum MapEmbedding { kEmbedMapsDirectly, kEmbedMapsViaWeakCells };
1853
1854   void BuildCompareNil(HValue* value, Type* type, HIfContinuation* continuation,
1855                        MapEmbedding map_embedding = kEmbedMapsDirectly);
1856
1857   void BuildCreateAllocationMemento(HValue* previous_object,
1858                                     HValue* previous_object_size,
1859                                     HValue* payload);
1860
1861   HInstruction* BuildConstantMapCheck(Handle<JSObject> constant);
1862   HInstruction* BuildCheckPrototypeMaps(Handle<JSObject> prototype,
1863                                         Handle<JSObject> holder);
1864
1865   HInstruction* BuildGetNativeContext(HValue* closure);
1866   HInstruction* BuildGetNativeContext();
1867   HInstruction* BuildGetScriptContext(int context_index);
1868   // Builds a loop version if |depth| is specified or unrolls the loop to
1869   // |depth_value| iterations otherwise.
1870   HValue* BuildGetParentContext(HValue* depth, int depth_value);
1871
1872   HInstruction* BuildGetArrayFunction();
1873   HValue* BuildArrayBufferViewFieldAccessor(HValue* object,
1874                                             HValue* checked_object,
1875                                             FieldIndex index);
1876
1877
1878  protected:
1879   void SetSourcePosition(int position) {
1880     if (position != RelocInfo::kNoPosition) {
1881       position_.set_position(position - start_position_);
1882     }
1883     // Otherwise position remains unknown.
1884   }
1885
1886   void EnterInlinedSource(int start_position, int id) {
1887     if (top_info()->is_tracking_positions()) {
1888       start_position_ = start_position;
1889       position_.set_inlining_id(id);
1890     }
1891   }
1892
1893   // Convert the given absolute offset from the start of the script to
1894   // the SourcePosition assuming that this position corresponds to the
1895   // same function as current position_.
1896   SourcePosition ScriptPositionToSourcePosition(int position) {
1897     if (position == RelocInfo::kNoPosition) {
1898       return SourcePosition::Unknown();
1899     }
1900     SourcePosition pos = position_;
1901     pos.set_position(position - start_position_);
1902     return pos;
1903   }
1904
1905   SourcePosition source_position() { return position_; }
1906   void set_source_position(SourcePosition position) { position_ = position; }
1907
1908   HValue* BuildAllocateEmptyArrayBuffer(HValue* byte_length);
1909   template <typename ViewClass>
1910   void BuildArrayBufferViewInitialization(HValue* obj,
1911                                           HValue* buffer,
1912                                           HValue* byte_offset,
1913                                           HValue* byte_length);
1914
1915  private:
1916   HGraphBuilder();
1917
1918   template <class I>
1919   I* AddInstructionTyped(I* instr) {
1920     return I::cast(AddInstruction(instr));
1921   }
1922
1923   CompilationInfo* info_;
1924   HGraph* graph_;
1925   HBasicBlock* current_block_;
1926   Scope* scope_;
1927   SourcePosition position_;
1928   int start_position_;
1929 };
1930
1931
1932 template <>
1933 inline HDeoptimize* HGraphBuilder::Add<HDeoptimize>(
1934     Deoptimizer::DeoptReason reason, Deoptimizer::BailoutType type) {
1935   if (type == Deoptimizer::SOFT) {
1936     isolate()->counters()->soft_deopts_requested()->Increment();
1937     if (FLAG_always_opt) return NULL;
1938   }
1939   if (current_block()->IsDeoptimizing()) return NULL;
1940   HBasicBlock* after_deopt_block = CreateBasicBlock(
1941       current_block()->last_environment());
1942   HDeoptimize* instr = New<HDeoptimize>(reason, type, after_deopt_block);
1943   if (type == Deoptimizer::SOFT) {
1944     isolate()->counters()->soft_deopts_inserted()->Increment();
1945   }
1946   FinishCurrentBlock(instr);
1947   set_current_block(after_deopt_block);
1948   return instr;
1949 }
1950
1951
1952 template <>
1953 inline HInstruction* HGraphBuilder::AddUncasted<HDeoptimize>(
1954     Deoptimizer::DeoptReason reason, Deoptimizer::BailoutType type) {
1955   return Add<HDeoptimize>(reason, type);
1956 }
1957
1958
1959 template<>
1960 inline HSimulate* HGraphBuilder::Add<HSimulate>(
1961     BailoutId id,
1962     RemovableSimulate removable) {
1963   HSimulate* instr = current_block()->CreateSimulate(id, removable);
1964   AddInstruction(instr);
1965   return instr;
1966 }
1967
1968
1969 template<>
1970 inline HSimulate* HGraphBuilder::Add<HSimulate>(
1971     BailoutId id) {
1972   return Add<HSimulate>(id, FIXED_SIMULATE);
1973 }
1974
1975
1976 template<>
1977 inline HInstruction* HGraphBuilder::AddUncasted<HSimulate>(BailoutId id) {
1978   return Add<HSimulate>(id, FIXED_SIMULATE);
1979 }
1980
1981
1982 template<>
1983 inline HReturn* HGraphBuilder::Add<HReturn>(HValue* value) {
1984   int num_parameters = graph()->info()->num_parameters();
1985   HValue* params = AddUncasted<HConstant>(num_parameters);
1986   HReturn* return_instruction = New<HReturn>(value, params);
1987   FinishExitCurrentBlock(return_instruction);
1988   return return_instruction;
1989 }
1990
1991
1992 template<>
1993 inline HReturn* HGraphBuilder::Add<HReturn>(HConstant* value) {
1994   return Add<HReturn>(static_cast<HValue*>(value));
1995 }
1996
1997 template<>
1998 inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HValue* value) {
1999   return Add<HReturn>(value);
2000 }
2001
2002
2003 template<>
2004 inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HConstant* value) {
2005   return Add<HReturn>(value);
2006 }
2007
2008
2009 template<>
2010 inline HCallRuntime* HGraphBuilder::Add<HCallRuntime>(
2011     const Runtime::Function* c_function,
2012     int argument_count) {
2013   HCallRuntime* instr = New<HCallRuntime>(c_function, argument_count);
2014   if (graph()->info()->IsStub()) {
2015     // When compiling code stubs, we don't want to save all double registers
2016     // upon entry to the stub, but instead have the call runtime instruction
2017     // save the double registers only on-demand (in the fallback case).
2018     instr->set_save_doubles(kSaveFPRegs);
2019   }
2020   AddInstruction(instr);
2021   return instr;
2022 }
2023
2024
2025 template<>
2026 inline HInstruction* HGraphBuilder::AddUncasted<HCallRuntime>(
2027     Handle<String> name,
2028     const Runtime::Function* c_function,
2029     int argument_count) {
2030   return Add<HCallRuntime>(c_function, argument_count);
2031 }
2032
2033
2034 template <>
2035 inline HParameter* HGraphBuilder::New<HParameter>(unsigned index) {
2036   return HParameter::New(isolate(), zone(), nullptr, index);
2037 }
2038
2039
2040 template <>
2041 inline HParameter* HGraphBuilder::New<HParameter>(
2042     unsigned index, HParameter::ParameterKind kind) {
2043   return HParameter::New(isolate(), zone(), nullptr, index, kind);
2044 }
2045
2046
2047 template <>
2048 inline HParameter* HGraphBuilder::New<HParameter>(
2049     unsigned index, HParameter::ParameterKind kind, Representation r) {
2050   return HParameter::New(isolate(), zone(), nullptr, index, kind, r);
2051 }
2052
2053
2054 template <>
2055 inline HPrologue* HGraphBuilder::New<HPrologue>() {
2056   return HPrologue::New(zone());
2057 }
2058
2059
2060 template <>
2061 inline HContext* HGraphBuilder::New<HContext>() {
2062   return HContext::New(zone());
2063 }
2064
2065
2066 class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
2067  public:
2068   // A class encapsulating (lazily-allocated) break and continue blocks for
2069   // a breakable statement.  Separated from BreakAndContinueScope so that it
2070   // can have a separate lifetime.
2071   class BreakAndContinueInfo final BASE_EMBEDDED {
2072    public:
2073     explicit BreakAndContinueInfo(BreakableStatement* target,
2074                                   Scope* scope,
2075                                   int drop_extra = 0)
2076         : target_(target),
2077           break_block_(NULL),
2078           continue_block_(NULL),
2079           scope_(scope),
2080           drop_extra_(drop_extra) {
2081     }
2082
2083     BreakableStatement* target() { return target_; }
2084     HBasicBlock* break_block() { return break_block_; }
2085     void set_break_block(HBasicBlock* block) { break_block_ = block; }
2086     HBasicBlock* continue_block() { return continue_block_; }
2087     void set_continue_block(HBasicBlock* block) { continue_block_ = block; }
2088     Scope* scope() { return scope_; }
2089     int drop_extra() { return drop_extra_; }
2090
2091    private:
2092     BreakableStatement* target_;
2093     HBasicBlock* break_block_;
2094     HBasicBlock* continue_block_;
2095     Scope* scope_;
2096     int drop_extra_;
2097   };
2098
2099   // A helper class to maintain a stack of current BreakAndContinueInfo
2100   // structures mirroring BreakableStatement nesting.
2101   class BreakAndContinueScope final BASE_EMBEDDED {
2102    public:
2103     BreakAndContinueScope(BreakAndContinueInfo* info,
2104                           HOptimizedGraphBuilder* owner)
2105         : info_(info), owner_(owner), next_(owner->break_scope()) {
2106       owner->set_break_scope(this);
2107     }
2108
2109     ~BreakAndContinueScope() { owner_->set_break_scope(next_); }
2110
2111     BreakAndContinueInfo* info() { return info_; }
2112     HOptimizedGraphBuilder* owner() { return owner_; }
2113     BreakAndContinueScope* next() { return next_; }
2114
2115     // Search the break stack for a break or continue target.
2116     enum BreakType { BREAK, CONTINUE };
2117     HBasicBlock* Get(BreakableStatement* stmt, BreakType type,
2118                      Scope** scope, int* drop_extra);
2119
2120    private:
2121     BreakAndContinueInfo* info_;
2122     HOptimizedGraphBuilder* owner_;
2123     BreakAndContinueScope* next_;
2124   };
2125
2126   explicit HOptimizedGraphBuilder(CompilationInfo* info);
2127
2128   bool BuildGraph() override;
2129
2130   // Simple accessors.
2131   BreakAndContinueScope* break_scope() const { return break_scope_; }
2132   void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }
2133
2134   HValue* context() override { return environment()->context(); }
2135
2136   HOsrBuilder* osr() const { return osr_; }
2137
2138   void Bailout(BailoutReason reason);
2139
2140   HBasicBlock* CreateJoin(HBasicBlock* first,
2141                           HBasicBlock* second,
2142                           BailoutId join_id);
2143
2144   FunctionState* function_state() const { return function_state_; }
2145
2146   void VisitDeclarations(ZoneList<Declaration*>* declarations) override;
2147
2148   void* operator new(size_t size, Zone* zone) { return zone->New(size); }
2149   void operator delete(void* pointer, Zone* zone) { }
2150   void operator delete(void* pointer) { }
2151
2152   DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
2153
2154  protected:
2155   // Forward declarations for inner scope classes.
2156   class SubgraphScope;
2157
2158   static const int kMaxCallPolymorphism = 4;
2159   static const int kMaxLoadPolymorphism = 4;
2160   static const int kMaxStorePolymorphism = 4;
2161
2162   // Even in the 'unlimited' case we have to have some limit in order not to
2163   // overflow the stack.
2164   static const int kUnlimitedMaxInlinedSourceSize = 100000;
2165   static const int kUnlimitedMaxInlinedNodes = 10000;
2166   static const int kUnlimitedMaxInlinedNodesCumulative = 10000;
2167
2168   // Maximum depth and total number of elements and properties for literal
2169   // graphs to be considered for fast deep-copying.
2170   static const int kMaxFastLiteralDepth = 3;
2171   static const int kMaxFastLiteralProperties = 8;
2172
2173   // Simple accessors.
2174   void set_function_state(FunctionState* state) { function_state_ = state; }
2175
2176   AstContext* ast_context() const { return ast_context_; }
2177   void set_ast_context(AstContext* context) { ast_context_ = context; }
2178
2179   // Accessors forwarded to the function state.
2180   CompilationInfo* current_info() const {
2181     return function_state()->compilation_info();
2182   }
2183   AstContext* call_context() const {
2184     return function_state()->call_context();
2185   }
2186   HBasicBlock* function_return() const {
2187     return function_state()->function_return();
2188   }
2189   TestContext* inlined_test_context() const {
2190     return function_state()->test_context();
2191   }
2192   Handle<SharedFunctionInfo> current_shared_info() const {
2193     return current_info()->shared_info();
2194   }
2195   TypeFeedbackVector* current_feedback_vector() const {
2196     return current_shared_info()->feedback_vector();
2197   }
2198   void ClearInlinedTestContext() {
2199     function_state()->ClearInlinedTestContext();
2200   }
2201   LanguageMode function_language_mode() {
2202     return function_state()->compilation_info()->language_mode();
2203   }
2204
2205 #define FOR_EACH_HYDROGEN_INTRINSIC(F) \
2206   F(IsSmi)                             \
2207   F(IsArray)                           \
2208   F(IsTypedArray)                      \
2209   F(IsRegExp)                          \
2210   F(IsJSProxy)                         \
2211   F(IsConstructCall)                   \
2212   F(Call)                              \
2213   F(CallFunction)                      \
2214   F(ArgumentsLength)                   \
2215   F(Arguments)                         \
2216   F(ValueOf)                           \
2217   F(SetValueOf)                        \
2218   F(IsDate)                            \
2219   F(DateField)                         \
2220   F(ThrowNotDateError)                 \
2221   F(StringCharFromCode)                \
2222   F(StringCharAt)                      \
2223   F(OneByteSeqStringSetChar)           \
2224   F(TwoByteSeqStringSetChar)           \
2225   F(ObjectEquals)                      \
2226   F(ToInteger)                         \
2227   F(ToObject)                          \
2228   F(ToString)                          \
2229   F(IsFunction)                        \
2230   F(IsSpecObject)                      \
2231   F(MathPow)                           \
2232   F(IsMinusZero)                       \
2233   F(HasCachedArrayIndex)               \
2234   F(GetCachedArrayIndex)               \
2235   F(FastOneByteArrayJoin)              \
2236   F(DebugBreakInOptimizedCode)         \
2237   F(StringCharCodeAt)                  \
2238   F(StringAdd)                         \
2239   F(SubString)                         \
2240   F(RegExpExec)                        \
2241   F(RegExpConstructResult)             \
2242   F(NumberToString)                    \
2243   F(DebugIsActive)                     \
2244   F(Likely)                            \
2245   F(Unlikely)                          \
2246   F(HasInPrototypeChain)               \
2247   /* Typed Arrays */                   \
2248   F(TypedArrayInitialize)              \
2249   F(DataViewInitialize)                \
2250   F(MaxSmi)                            \
2251   F(TypedArrayMaxSizeInHeap)           \
2252   F(ArrayBufferViewGetByteLength)      \
2253   F(ArrayBufferViewGetByteOffset)      \
2254   F(TypedArrayGetLength)               \
2255   /* ArrayBuffer */                    \
2256   F(ArrayBufferGetByteLength)          \
2257   /* Maths */                          \
2258   F(ConstructDouble)                   \
2259   F(DoubleHi)                          \
2260   F(DoubleLo)                          \
2261   F(MathClz32)                         \
2262   F(MathFloor)                         \
2263   F(MathSqrt)                          \
2264   F(MathLogRT)                         \
2265   /* ES6 Collections */                \
2266   F(MapClear)                          \
2267   F(MapInitialize)                     \
2268   F(SetClear)                          \
2269   F(SetInitialize)                     \
2270   F(FixedArrayGet)                     \
2271   F(FixedArraySet)                     \
2272   F(JSCollectionGetTable)              \
2273   F(StringGetRawHashField)             \
2274   F(TheHole)                           \
2275   /* ES6 Iterators */                  \
2276   F(CreateIterResultObject)            \
2277   /* Arrays */                         \
2278   F(HasFastPackedElements)             \
2279   /* Strings */                        \
2280   F(StringGetLength)                   \
2281   /* JSValue */                        \
2282   F(JSValueGetValue)
2283
2284 #define GENERATOR_DECLARATION(Name) void Generate##Name(CallRuntime* call);
2285   FOR_EACH_HYDROGEN_INTRINSIC(GENERATOR_DECLARATION)
2286 #undef GENERATOR_DECLARATION
2287
2288   void VisitDelete(UnaryOperation* expr);
2289   void VisitVoid(UnaryOperation* expr);
2290   void VisitTypeof(UnaryOperation* expr);
2291   void VisitNot(UnaryOperation* expr);
2292
2293   void VisitComma(BinaryOperation* expr);
2294   void VisitLogicalExpression(BinaryOperation* expr);
2295   void VisitArithmeticExpression(BinaryOperation* expr);
2296
2297   void VisitLoopBody(IterationStatement* stmt,
2298                      HBasicBlock* loop_entry);
2299
2300   void BuildForInBody(ForInStatement* stmt, Variable* each_var,
2301                       HValue* enumerable);
2302
2303   // Create a back edge in the flow graph.  body_exit is the predecessor
2304   // block and loop_entry is the successor block.  loop_successor is the
2305   // block where control flow exits the loop normally (e.g., via failure of
2306   // the condition) and break_block is the block where control flow breaks
2307   // from the loop.  All blocks except loop_entry can be NULL.  The return
2308   // value is the new successor block which is the join of loop_successor
2309   // and break_block, or NULL.
2310   HBasicBlock* CreateLoop(IterationStatement* statement,
2311                           HBasicBlock* loop_entry,
2312                           HBasicBlock* body_exit,
2313                           HBasicBlock* loop_successor,
2314                           HBasicBlock* break_block);
2315
2316   // Build a loop entry
2317   HBasicBlock* BuildLoopEntry();
2318
2319   // Builds a loop entry respectful of OSR requirements
2320   HBasicBlock* BuildLoopEntry(IterationStatement* statement);
2321
2322   HBasicBlock* JoinContinue(IterationStatement* statement,
2323                             HBasicBlock* exit_block,
2324                             HBasicBlock* continue_block);
2325
2326   HValue* Top() const { return environment()->Top(); }
2327   void Drop(int n) { environment()->Drop(n); }
2328   void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
2329   bool IsEligibleForEnvironmentLivenessAnalysis(Variable* var,
2330                                                 int index,
2331                                                 HValue* value,
2332                                                 HEnvironment* env) {
2333     if (!FLAG_analyze_environment_liveness) return false;
2334     // |this| and |arguments| are always live; zapping parameters isn't
2335     // safe because function.arguments can inspect them at any time.
2336     return !var->is_this() &&
2337            !var->is_arguments() &&
2338            !value->IsArgumentsObject() &&
2339            env->is_local_index(index);
2340   }
2341   void BindIfLive(Variable* var, HValue* value) {
2342     HEnvironment* env = environment();
2343     int index = env->IndexFor(var);
2344     env->Bind(index, value);
2345     if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) {
2346       HEnvironmentMarker* bind =
2347           Add<HEnvironmentMarker>(HEnvironmentMarker::BIND, index);
2348       USE(bind);
2349 #ifdef DEBUG
2350       bind->set_closure(env->closure());
2351 #endif
2352     }
2353   }
2354   HValue* LookupAndMakeLive(Variable* var) {
2355     HEnvironment* env = environment();
2356     int index = env->IndexFor(var);
2357     HValue* value = env->Lookup(index);
2358     if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) {
2359       HEnvironmentMarker* lookup =
2360           Add<HEnvironmentMarker>(HEnvironmentMarker::LOOKUP, index);
2361       USE(lookup);
2362 #ifdef DEBUG
2363       lookup->set_closure(env->closure());
2364 #endif
2365     }
2366     return value;
2367   }
2368
2369   // The value of the arguments object is allowed in some but not most value
2370   // contexts.  (It's allowed in all effect contexts and disallowed in all
2371   // test contexts.)
2372   void VisitForValue(Expression* expr,
2373                      ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED);
2374   void VisitForTypeOf(Expression* expr);
2375   void VisitForEffect(Expression* expr);
2376   void VisitForControl(Expression* expr,
2377                        HBasicBlock* true_block,
2378                        HBasicBlock* false_block);
2379
2380   // Visit a list of expressions from left to right, each in a value context.
2381   void VisitExpressions(ZoneList<Expression*>* exprs) override;
2382   void VisitExpressions(ZoneList<Expression*>* exprs,
2383                         ArgumentsAllowedFlag flag);
2384
2385   // Remove the arguments from the bailout environment and emit instructions
2386   // to push them as outgoing parameters.
2387   template <class Instruction> HInstruction* PreProcessCall(Instruction* call);
2388   void PushArgumentsFromEnvironment(int count);
2389
2390   void SetUpScope(Scope* scope);
2391   void VisitStatements(ZoneList<Statement*>* statements) override;
2392
2393 #define DECLARE_VISIT(type) virtual void Visit##type(type* node) override;
2394   AST_NODE_LIST(DECLARE_VISIT)
2395 #undef DECLARE_VISIT
2396
2397  private:
2398   // Helpers for flow graph construction.
2399   enum GlobalPropertyAccess {
2400     kUseCell,
2401     kUseGeneric
2402   };
2403   GlobalPropertyAccess LookupGlobalProperty(Variable* var, LookupIterator* it,
2404                                             PropertyAccessType access_type);
2405
2406   void EnsureArgumentsArePushedForAccess();
2407   bool TryArgumentsAccess(Property* expr);
2408
2409   // Shared code for .call and .apply optimizations.
2410   void HandleIndirectCall(Call* expr, HValue* function, int arguments_count);
2411   // Try to optimize indirect calls such as fun.apply(receiver, arguments)
2412   // or fun.call(...).
2413   bool TryIndirectCall(Call* expr);
2414   void BuildFunctionApply(Call* expr);
2415   void BuildFunctionCall(Call* expr);
2416
2417   bool TryHandleArrayCall(Call* expr, HValue* function);
2418   bool TryHandleArrayCallNew(CallNew* expr, HValue* function);
2419   void BuildArrayCall(Expression* expr, int arguments_count, HValue* function,
2420                       Handle<AllocationSite> cell);
2421
2422   enum ArrayIndexOfMode { kFirstIndexOf, kLastIndexOf };
2423   HValue* BuildArrayIndexOf(HValue* receiver,
2424                             HValue* search_element,
2425                             ElementsKind kind,
2426                             ArrayIndexOfMode mode);
2427
2428   HValue* ImplicitReceiverFor(HValue* function,
2429                               Handle<JSFunction> target);
2430
2431   int InliningAstSize(Handle<JSFunction> target);
2432   bool TryInline(Handle<JSFunction> target, int arguments_count,
2433                  HValue* implicit_return_value, BailoutId ast_id,
2434                  BailoutId return_id, InliningKind inlining_kind);
2435
2436   bool TryInlineCall(Call* expr);
2437   bool TryInlineConstruct(CallNew* expr, HValue* implicit_return_value);
2438   bool TryInlineGetter(Handle<JSFunction> getter,
2439                        Handle<Map> receiver_map,
2440                        BailoutId ast_id,
2441                        BailoutId return_id);
2442   bool TryInlineSetter(Handle<JSFunction> setter,
2443                        Handle<Map> receiver_map,
2444                        BailoutId id,
2445                        BailoutId assignment_id,
2446                        HValue* implicit_return_value);
2447   bool TryInlineIndirectCall(Handle<JSFunction> function, Call* expr,
2448                              int arguments_count);
2449   bool TryInlineBuiltinMethodCall(Call* expr, Handle<JSFunction> function,
2450                                   Handle<Map> receiver_map,
2451                                   int args_count_no_receiver);
2452   bool TryInlineBuiltinFunctionCall(Call* expr);
2453   enum ApiCallType {
2454     kCallApiFunction,
2455     kCallApiMethod,
2456     kCallApiGetter,
2457     kCallApiSetter
2458   };
2459   bool TryInlineApiMethodCall(Call* expr,
2460                               HValue* receiver,
2461                               SmallMapList* receiver_types);
2462   bool TryInlineApiFunctionCall(Call* expr, HValue* receiver);
2463   bool TryInlineApiGetter(Handle<JSFunction> function,
2464                           Handle<Map> receiver_map,
2465                           BailoutId ast_id);
2466   bool TryInlineApiSetter(Handle<JSFunction> function,
2467                           Handle<Map> receiver_map,
2468                           BailoutId ast_id);
2469   bool TryInlineApiCall(Handle<JSFunction> function,
2470                          HValue* receiver,
2471                          SmallMapList* receiver_maps,
2472                          int argc,
2473                          BailoutId ast_id,
2474                          ApiCallType call_type);
2475   static bool IsReadOnlyLengthDescriptor(Handle<Map> jsarray_map);
2476   static bool CanInlineArrayResizeOperation(Handle<Map> receiver_map);
2477
2478   // If --trace-inlining, print a line of the inlining trace.  Inlining
2479   // succeeded if the reason string is NULL and failed if there is a
2480   // non-NULL reason string.
2481   void TraceInline(Handle<JSFunction> target,
2482                    Handle<JSFunction> caller,
2483                    const char* failure_reason);
2484
2485   void HandleGlobalVariableAssignment(Variable* var, HValue* value,
2486                                       FeedbackVectorICSlot ic_slot,
2487                                       BailoutId ast_id);
2488
2489   void HandlePropertyAssignment(Assignment* expr);
2490   void HandleCompoundAssignment(Assignment* expr);
2491   void HandlePolymorphicNamedFieldAccess(
2492       PropertyAccessType access_type, Expression* expr,
2493       FeedbackVectorICSlot slot, BailoutId ast_id, BailoutId return_id,
2494       HValue* object, HValue* value, SmallMapList* types, Handle<String> name);
2495
2496   HValue* BuildAllocateExternalElements(
2497       ExternalArrayType array_type,
2498       bool is_zero_byte_offset,
2499       HValue* buffer, HValue* byte_offset, HValue* length);
2500   HValue* BuildAllocateFixedTypedArray(ExternalArrayType array_type,
2501                                        size_t element_size,
2502                                        ElementsKind fixed_elements_kind,
2503                                        HValue* byte_length, HValue* length,
2504                                        bool initialize);
2505
2506   // TODO(adamk): Move all OrderedHashTable functions to their own class.
2507   HValue* BuildOrderedHashTableHashToBucket(HValue* hash, HValue* num_buckets);
2508   template <typename CollectionType>
2509   HValue* BuildOrderedHashTableHashToEntry(HValue* table, HValue* hash,
2510                                            HValue* num_buckets);
2511   template <typename CollectionType>
2512   HValue* BuildOrderedHashTableEntryToIndex(HValue* entry, HValue* num_buckets);
2513   template <typename CollectionType>
2514   HValue* BuildOrderedHashTableFindEntry(HValue* table, HValue* key,
2515                                          HValue* hash);
2516   template <typename CollectionType>
2517   HValue* BuildOrderedHashTableAddEntry(HValue* table, HValue* key,
2518                                         HValue* hash,
2519                                         HIfContinuation* join_continuation);
2520   template <typename CollectionType>
2521   HValue* BuildAllocateOrderedHashTable();
2522   template <typename CollectionType>
2523   void BuildOrderedHashTableClear(HValue* receiver);
2524   template <typename CollectionType>
2525   void BuildJSCollectionDelete(CallRuntime* call,
2526                                const Runtime::Function* c_function);
2527   template <typename CollectionType>
2528   void BuildJSCollectionHas(CallRuntime* call,
2529                             const Runtime::Function* c_function);
2530   HValue* BuildStringHashLoadIfIsStringAndHashComputed(
2531       HValue* object, HIfContinuation* continuation);
2532
2533   Handle<JSFunction> array_function() {
2534     return handle(isolate()->native_context()->array_function());
2535   }
2536
2537   bool IsCallArrayInlineable(int argument_count, Handle<AllocationSite> site);
2538   void BuildInlinedCallArray(Expression* expression, int argument_count,
2539                              Handle<AllocationSite> site);
2540
2541   void BuildInitializeInobjectProperties(HValue* receiver,
2542                                          Handle<Map> initial_map);
2543
2544   class PropertyAccessInfo {
2545    public:
2546     PropertyAccessInfo(HOptimizedGraphBuilder* builder,
2547                        PropertyAccessType access_type, Handle<Map> map,
2548                        Handle<Name> name)
2549         : builder_(builder),
2550           access_type_(access_type),
2551           map_(map),
2552           name_(name),
2553           field_type_(HType::Tagged()),
2554           access_(HObjectAccess::ForMap()),
2555           lookup_type_(NOT_FOUND),
2556           details_(NONE, DATA, Representation::None()) {}
2557
2558     // Checkes whether this PropertyAccessInfo can be handled as a monomorphic
2559     // load named. It additionally fills in the fields necessary to generate the
2560     // lookup code.
2561     bool CanAccessMonomorphic();
2562
2563     // Checks whether all types behave uniform when loading name. If all maps
2564     // behave the same, a single monomorphic load instruction can be emitted,
2565     // guarded by a single map-checks instruction that whether the receiver is
2566     // an instance of any of the types.
2567     // This method skips the first type in types, assuming that this
2568     // PropertyAccessInfo is built for types->first().
2569     bool CanAccessAsMonomorphic(SmallMapList* types);
2570
2571     bool NeedsWrappingFor(Handle<JSFunction> target) const;
2572
2573     Handle<Map> map();
2574     Handle<Name> name() const { return name_; }
2575
2576     bool IsJSObjectFieldAccessor() {
2577       int offset;  // unused
2578       return Accessors::IsJSObjectFieldAccessor(map_, name_, &offset);
2579     }
2580
2581     bool GetJSObjectFieldAccess(HObjectAccess* access) {
2582       int offset;
2583       if (Accessors::IsJSObjectFieldAccessor(map_, name_, &offset)) {
2584         if (IsStringType()) {
2585           DCHECK(Name::Equals(isolate()->factory()->length_string(), name_));
2586           *access = HObjectAccess::ForStringLength();
2587         } else if (IsArrayType()) {
2588           DCHECK(Name::Equals(isolate()->factory()->length_string(), name_));
2589           *access = HObjectAccess::ForArrayLength(map_->elements_kind());
2590         } else {
2591           *access = HObjectAccess::ForMapAndOffset(map_, offset);
2592         }
2593         return true;
2594       }
2595       return false;
2596     }
2597
2598     bool IsJSArrayBufferViewFieldAccessor() {
2599       int offset;  // unused
2600       return Accessors::IsJSArrayBufferViewFieldAccessor(map_, name_, &offset);
2601     }
2602
2603     bool GetJSArrayBufferViewFieldAccess(HObjectAccess* access) {
2604       int offset;
2605       if (Accessors::IsJSArrayBufferViewFieldAccessor(map_, name_, &offset)) {
2606         *access = HObjectAccess::ForMapAndOffset(map_, offset);
2607         return true;
2608       }
2609       return false;
2610     }
2611
2612     bool has_holder() { return !holder_.is_null(); }
2613     bool IsLoad() const { return access_type_ == LOAD; }
2614
2615     Isolate* isolate() const { return builder_->isolate(); }
2616     Handle<JSObject> holder() { return holder_; }
2617     Handle<JSFunction> accessor() { return accessor_; }
2618     Handle<Object> constant() { return constant_; }
2619     Handle<Map> transition() { return transition_; }
2620     SmallMapList* field_maps() { return &field_maps_; }
2621     HType field_type() const { return field_type_; }
2622     HObjectAccess access() { return access_; }
2623
2624     bool IsFound() const { return lookup_type_ != NOT_FOUND; }
2625     bool IsProperty() const { return IsFound() && !IsTransition(); }
2626     bool IsTransition() const { return lookup_type_ == TRANSITION_TYPE; }
2627     bool IsData() const {
2628       return lookup_type_ == DESCRIPTOR_TYPE && details_.type() == DATA;
2629     }
2630     bool IsDataConstant() const {
2631       return lookup_type_ == DESCRIPTOR_TYPE &&
2632              details_.type() == DATA_CONSTANT;
2633     }
2634     bool IsAccessorConstant() const {
2635       return !IsTransition() && details_.type() == ACCESSOR_CONSTANT;
2636     }
2637     bool IsConfigurable() const { return details_.IsConfigurable(); }
2638     bool IsReadOnly() const { return details_.IsReadOnly(); }
2639
2640     bool IsStringType() { return map_->instance_type() < FIRST_NONSTRING_TYPE; }
2641     bool IsNumberType() { return map_->instance_type() == HEAP_NUMBER_TYPE; }
2642     bool IsValueWrapped() { return IsStringType() || IsNumberType(); }
2643     bool IsArrayType() { return map_->instance_type() == JS_ARRAY_TYPE; }
2644
2645    private:
2646     Handle<Object> GetConstantFromMap(Handle<Map> map) const {
2647       DCHECK_EQ(DESCRIPTOR_TYPE, lookup_type_);
2648       DCHECK(number_ < map->NumberOfOwnDescriptors());
2649       return handle(map->instance_descriptors()->GetValue(number_), isolate());
2650     }
2651     Handle<Object> GetAccessorsFromMap(Handle<Map> map) const {
2652       return GetConstantFromMap(map);
2653     }
2654     Handle<HeapType> GetFieldTypeFromMap(Handle<Map> map) const {
2655       DCHECK(IsFound());
2656       DCHECK(number_ < map->NumberOfOwnDescriptors());
2657       return handle(map->instance_descriptors()->GetFieldType(number_),
2658                     isolate());
2659     }
2660     Handle<Map> GetFieldOwnerFromMap(Handle<Map> map) const {
2661       DCHECK(IsFound());
2662       DCHECK(number_ < map->NumberOfOwnDescriptors());
2663       return handle(map->FindFieldOwner(number_));
2664     }
2665     int GetLocalFieldIndexFromMap(Handle<Map> map) const {
2666       DCHECK(lookup_type_ == DESCRIPTOR_TYPE ||
2667              lookup_type_ == TRANSITION_TYPE);
2668       DCHECK(number_ < map->NumberOfOwnDescriptors());
2669       int field_index = map->instance_descriptors()->GetFieldIndex(number_);
2670       return field_index - map->GetInObjectProperties();
2671     }
2672
2673     void LookupDescriptor(Map* map, Name* name) {
2674       DescriptorArray* descriptors = map->instance_descriptors();
2675       int number = descriptors->SearchWithCache(name, map);
2676       if (number == DescriptorArray::kNotFound) return NotFound();
2677       lookup_type_ = DESCRIPTOR_TYPE;
2678       details_ = descriptors->GetDetails(number);
2679       number_ = number;
2680     }
2681     void LookupTransition(Map* map, Name* name, PropertyAttributes attributes) {
2682       Map* target =
2683           TransitionArray::SearchTransition(map, kData, name, attributes);
2684       if (target == NULL) return NotFound();
2685       lookup_type_ = TRANSITION_TYPE;
2686       transition_ = handle(target);
2687       number_ = transition_->LastAdded();
2688       details_ = transition_->instance_descriptors()->GetDetails(number_);
2689     }
2690     void NotFound() {
2691       lookup_type_ = NOT_FOUND;
2692       details_ = PropertyDetails::Empty();
2693     }
2694     Representation representation() const {
2695       DCHECK(IsFound());
2696       return details_.representation();
2697     }
2698     bool IsTransitionToData() const {
2699       return IsTransition() && details_.type() == DATA;
2700     }
2701
2702     Zone* zone() { return builder_->zone(); }
2703     CompilationInfo* top_info() { return builder_->top_info(); }
2704     CompilationInfo* current_info() { return builder_->current_info(); }
2705
2706     bool LoadResult(Handle<Map> map);
2707     bool LoadFieldMaps(Handle<Map> map);
2708     bool LookupDescriptor();
2709     bool LookupInPrototypes();
2710     bool IsIntegerIndexedExotic();
2711     bool IsCompatible(PropertyAccessInfo* other);
2712
2713     void GeneralizeRepresentation(Representation r) {
2714       access_ = access_.WithRepresentation(
2715           access_.representation().generalize(r));
2716     }
2717
2718     HOptimizedGraphBuilder* builder_;
2719     PropertyAccessType access_type_;
2720     Handle<Map> map_;
2721     Handle<Name> name_;
2722     Handle<JSObject> holder_;
2723     Handle<JSFunction> accessor_;
2724     Handle<JSObject> api_holder_;
2725     Handle<Object> constant_;
2726     SmallMapList field_maps_;
2727     HType field_type_;
2728     HObjectAccess access_;
2729
2730     enum { NOT_FOUND, DESCRIPTOR_TYPE, TRANSITION_TYPE } lookup_type_;
2731     Handle<Map> transition_;
2732     int number_;
2733     PropertyDetails details_;
2734   };
2735
2736   HValue* BuildMonomorphicAccess(PropertyAccessInfo* info, HValue* object,
2737                                  HValue* checked_object, HValue* value,
2738                                  BailoutId ast_id, BailoutId return_id,
2739                                  bool can_inline_accessor = true);
2740
2741   HValue* BuildNamedAccess(PropertyAccessType access, BailoutId ast_id,
2742                            BailoutId reutrn_id, Expression* expr,
2743                            FeedbackVectorICSlot slot, HValue* object,
2744                            Handle<String> name, HValue* value,
2745                            bool is_uninitialized = false);
2746
2747   void HandlePolymorphicCallNamed(Call* expr,
2748                                   HValue* receiver,
2749                                   SmallMapList* types,
2750                                   Handle<String> name);
2751   void HandleLiteralCompareTypeof(CompareOperation* expr,
2752                                   Expression* sub_expr,
2753                                   Handle<String> check);
2754   void HandleLiteralCompareNil(CompareOperation* expr,
2755                                Expression* sub_expr,
2756                                NilValue nil);
2757
2758   enum PushBeforeSimulateBehavior {
2759     PUSH_BEFORE_SIMULATE,
2760     NO_PUSH_BEFORE_SIMULATE
2761   };
2762
2763   HControlInstruction* BuildCompareInstruction(
2764       Token::Value op, HValue* left, HValue* right, Type* left_type,
2765       Type* right_type, Type* combined_type, SourcePosition left_position,
2766       SourcePosition right_position, PushBeforeSimulateBehavior push_sim_result,
2767       BailoutId bailout_id);
2768
2769   HInstruction* BuildStringCharCodeAt(HValue* string,
2770                                       HValue* index);
2771
2772   HValue* BuildBinaryOperation(
2773       BinaryOperation* expr,
2774       HValue* left,
2775       HValue* right,
2776       PushBeforeSimulateBehavior push_sim_result);
2777   HInstruction* BuildIncrement(bool returns_original_input,
2778                                CountOperation* expr);
2779   HInstruction* BuildKeyedGeneric(PropertyAccessType access_type,
2780                                   Expression* expr, FeedbackVectorICSlot slot,
2781                                   HValue* object, HValue* key, HValue* value);
2782
2783   HInstruction* TryBuildConsolidatedElementLoad(HValue* object,
2784                                                 HValue* key,
2785                                                 HValue* val,
2786                                                 SmallMapList* maps);
2787
2788   LoadKeyedHoleMode BuildKeyedHoleMode(Handle<Map> map);
2789
2790   HInstruction* BuildMonomorphicElementAccess(HValue* object,
2791                                               HValue* key,
2792                                               HValue* val,
2793                                               HValue* dependency,
2794                                               Handle<Map> map,
2795                                               PropertyAccessType access_type,
2796                                               KeyedAccessStoreMode store_mode);
2797
2798   HValue* HandlePolymorphicElementAccess(
2799       Expression* expr, FeedbackVectorICSlot slot, HValue* object, HValue* key,
2800       HValue* val, SmallMapList* maps, PropertyAccessType access_type,
2801       KeyedAccessStoreMode store_mode, bool* has_side_effects);
2802
2803   HValue* HandleKeyedElementAccess(HValue* obj, HValue* key, HValue* val,
2804                                    Expression* expr, FeedbackVectorICSlot slot,
2805                                    BailoutId ast_id, BailoutId return_id,
2806                                    PropertyAccessType access_type,
2807                                    bool* has_side_effects);
2808
2809   HInstruction* BuildNamedGeneric(PropertyAccessType access, Expression* expr,
2810                                   FeedbackVectorICSlot slot, HValue* object,
2811                                   Handle<Name> name, HValue* value,
2812                                   bool is_uninitialized = false);
2813
2814   HCheckMaps* AddCheckMap(HValue* object, Handle<Map> map);
2815
2816   void BuildLoad(Property* property,
2817                  BailoutId ast_id);
2818   void PushLoad(Property* property,
2819                 HValue* object,
2820                 HValue* key);
2821
2822   void BuildStoreForEffect(Expression* expression, Property* prop,
2823                            FeedbackVectorICSlot slot, BailoutId ast_id,
2824                            BailoutId return_id, HValue* object, HValue* key,
2825                            HValue* value);
2826
2827   void BuildStore(Expression* expression, Property* prop,
2828                   FeedbackVectorICSlot slot, BailoutId ast_id,
2829                   BailoutId return_id, bool is_uninitialized = false);
2830
2831   HInstruction* BuildLoadNamedField(PropertyAccessInfo* info,
2832                                     HValue* checked_object);
2833   HInstruction* BuildStoreNamedField(PropertyAccessInfo* info,
2834                                      HValue* checked_object,
2835                                      HValue* value);
2836
2837   HValue* BuildContextChainWalk(Variable* var);
2838
2839   HInstruction* BuildThisFunction();
2840
2841   HInstruction* BuildFastLiteral(Handle<JSObject> boilerplate_object,
2842                                  AllocationSiteUsageContext* site_context);
2843
2844   void BuildEmitObjectHeader(Handle<JSObject> boilerplate_object,
2845                              HInstruction* object);
2846
2847   void BuildEmitInObjectProperties(Handle<JSObject> boilerplate_object,
2848                                    HInstruction* object,
2849                                    AllocationSiteUsageContext* site_context,
2850                                    PretenureFlag pretenure_flag);
2851
2852   void BuildEmitElements(Handle<JSObject> boilerplate_object,
2853                          Handle<FixedArrayBase> elements,
2854                          HValue* object_elements,
2855                          AllocationSiteUsageContext* site_context);
2856
2857   void BuildEmitFixedDoubleArray(Handle<FixedArrayBase> elements,
2858                                  ElementsKind kind,
2859                                  HValue* object_elements);
2860
2861   void BuildEmitFixedArray(Handle<FixedArrayBase> elements,
2862                            ElementsKind kind,
2863                            HValue* object_elements,
2864                            AllocationSiteUsageContext* site_context);
2865
2866   void AddCheckPrototypeMaps(Handle<JSObject> holder,
2867                              Handle<Map> receiver_map);
2868
2869   HInstruction* NewPlainFunctionCall(HValue* fun, int argument_count);
2870
2871   HInstruction* NewArgumentAdaptorCall(HValue* fun, HValue* context,
2872                                        int argument_count,
2873                                        HValue* expected_param_count);
2874
2875   HInstruction* BuildCallConstantFunction(Handle<JSFunction> target,
2876                                           int argument_count);
2877
2878   bool CanBeFunctionApplyArguments(Call* expr);
2879
2880   // The translation state of the currently-being-translated function.
2881   FunctionState* function_state_;
2882
2883   // The base of the function state stack.
2884   FunctionState initial_function_state_;
2885
2886   // Expression context of the currently visited subexpression. NULL when
2887   // visiting statements.
2888   AstContext* ast_context_;
2889
2890   // A stack of breakable statements entered.
2891   BreakAndContinueScope* break_scope_;
2892
2893   int inlined_count_;
2894   ZoneList<Handle<Object> > globals_;
2895
2896   bool inline_bailout_;
2897
2898   HOsrBuilder* osr_;
2899
2900   friend class FunctionState;  // Pushes and pops the state stack.
2901   friend class AstContext;  // Pushes and pops the AST context stack.
2902   friend class KeyedLoadFastElementStub;
2903   friend class HOsrBuilder;
2904
2905   DISALLOW_COPY_AND_ASSIGN(HOptimizedGraphBuilder);
2906 };
2907
2908
2909 Zone* AstContext::zone() const { return owner_->zone(); }
2910
2911
2912 class HStatistics final : public Malloced {
2913  public:
2914   HStatistics()
2915       : times_(5),
2916         names_(5),
2917         sizes_(5),
2918         total_size_(0),
2919         source_size_(0) { }
2920
2921   void Initialize(CompilationInfo* info);
2922   void Print();
2923   void SaveTiming(const char* name, base::TimeDelta time, size_t size);
2924
2925   void IncrementFullCodeGen(base::TimeDelta full_code_gen) {
2926     full_code_gen_ += full_code_gen;
2927   }
2928
2929   void IncrementCreateGraph(base::TimeDelta delta) { create_graph_ += delta; }
2930
2931   void IncrementOptimizeGraph(base::TimeDelta delta) {
2932     optimize_graph_ += delta;
2933   }
2934
2935   void IncrementGenerateCode(base::TimeDelta delta) { generate_code_ += delta; }
2936
2937   void IncrementSubtotals(base::TimeDelta create_graph,
2938                           base::TimeDelta optimize_graph,
2939                           base::TimeDelta generate_code) {
2940     IncrementCreateGraph(create_graph);
2941     IncrementOptimizeGraph(optimize_graph);
2942     IncrementGenerateCode(generate_code);
2943   }
2944
2945  private:
2946   List<base::TimeDelta> times_;
2947   List<const char*> names_;
2948   List<size_t> sizes_;
2949   base::TimeDelta create_graph_;
2950   base::TimeDelta optimize_graph_;
2951   base::TimeDelta generate_code_;
2952   size_t total_size_;
2953   base::TimeDelta full_code_gen_;
2954   double source_size_;
2955 };
2956
2957
2958 class HPhase : public CompilationPhase {
2959  public:
2960   HPhase(const char* name, HGraph* graph)
2961       : CompilationPhase(name, graph->info()),
2962         graph_(graph) { }
2963   ~HPhase();
2964
2965  protected:
2966   HGraph* graph() const { return graph_; }
2967
2968  private:
2969   HGraph* graph_;
2970
2971   DISALLOW_COPY_AND_ASSIGN(HPhase);
2972 };
2973
2974
2975 class HTracer final : public Malloced {
2976  public:
2977   explicit HTracer(int isolate_id)
2978       : trace_(&string_allocator_), indent_(0) {
2979     if (FLAG_trace_hydrogen_file == NULL) {
2980       SNPrintF(filename_,
2981                "hydrogen-%d-%d.cfg",
2982                base::OS::GetCurrentProcessId(),
2983                isolate_id);
2984     } else {
2985       StrNCpy(filename_, FLAG_trace_hydrogen_file, filename_.length());
2986     }
2987     WriteChars(filename_.start(), "", 0, false);
2988   }
2989
2990   void TraceCompilation(CompilationInfo* info);
2991   void TraceHydrogen(const char* name, HGraph* graph);
2992   void TraceLithium(const char* name, LChunk* chunk);
2993   void TraceLiveRanges(const char* name, LAllocator* allocator);
2994
2995  private:
2996   class Tag final BASE_EMBEDDED {
2997    public:
2998     Tag(HTracer* tracer, const char* name) {
2999       name_ = name;
3000       tracer_ = tracer;
3001       tracer->PrintIndent();
3002       tracer->trace_.Add("begin_%s\n", name);
3003       tracer->indent_++;
3004     }
3005
3006     ~Tag() {
3007       tracer_->indent_--;
3008       tracer_->PrintIndent();
3009       tracer_->trace_.Add("end_%s\n", name_);
3010       DCHECK(tracer_->indent_ >= 0);
3011       tracer_->FlushToFile();
3012     }
3013
3014    private:
3015     HTracer* tracer_;
3016     const char* name_;
3017   };
3018
3019   void TraceLiveRange(LiveRange* range, const char* type, Zone* zone);
3020   void Trace(const char* name, HGraph* graph, LChunk* chunk);
3021   void FlushToFile();
3022
3023   void PrintEmptyProperty(const char* name) {
3024     PrintIndent();
3025     trace_.Add("%s\n", name);
3026   }
3027
3028   void PrintStringProperty(const char* name, const char* value) {
3029     PrintIndent();
3030     trace_.Add("%s \"%s\"\n", name, value);
3031   }
3032
3033   void PrintLongProperty(const char* name, int64_t value) {
3034     PrintIndent();
3035     trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000));
3036   }
3037
3038   void PrintBlockProperty(const char* name, int block_id) {
3039     PrintIndent();
3040     trace_.Add("%s \"B%d\"\n", name, block_id);
3041   }
3042
3043   void PrintIntProperty(const char* name, int value) {
3044     PrintIndent();
3045     trace_.Add("%s %d\n", name, value);
3046   }
3047
3048   void PrintIndent() {
3049     for (int i = 0; i < indent_; i++) {
3050       trace_.Add("  ");
3051     }
3052   }
3053
3054   EmbeddedVector<char, 64> filename_;
3055   HeapStringAllocator string_allocator_;
3056   StringStream trace_;
3057   int indent_;
3058 };
3059
3060
3061 class NoObservableSideEffectsScope final {
3062  public:
3063   explicit NoObservableSideEffectsScope(HGraphBuilder* builder) :
3064       builder_(builder) {
3065     builder_->graph()->IncrementInNoSideEffectsScope();
3066   }
3067   ~NoObservableSideEffectsScope() {
3068     builder_->graph()->DecrementInNoSideEffectsScope();
3069   }
3070
3071  private:
3072   HGraphBuilder* builder_;
3073 };
3074
3075
3076 }  // namespace internal
3077 }  // namespace v8
3078
3079 #endif  // V8_HYDROGEN_H_