Home | History | Annotate | Download | only in crankshaft
      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_CRANKSHAFT_HYDROGEN_H_
      6 #define V8_CRANKSHAFT_HYDROGEN_H_
      7 
      8 #include "src/accessors.h"
      9 #include "src/allocation.h"
     10 #include "src/ast/ast.h"
     11 #include "src/ast/scopes.h"
     12 #include "src/bailout-reason.h"
     13 #include "src/compiler.h"
     14 #include "src/crankshaft/hydrogen-instructions.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   ~EffectContext() override;
    792 
    793   void ReturnValue(HValue* value) override;
    794   void ReturnInstruction(HInstruction* instr, BailoutId ast_id) override;
    795   void ReturnControl(HControlInstruction* instr, BailoutId ast_id) override;
    796   void ReturnContinuation(HIfContinuation* continuation,
    797                           BailoutId ast_id) override;
    798 };
    799 
    800 
    801 class ValueContext final : public AstContext {
    802  public:
    803   ValueContext(HOptimizedGraphBuilder* owner, ArgumentsAllowedFlag flag)
    804       : AstContext(owner, Expression::kValue), flag_(flag) {
    805   }
    806   ~ValueContext() override;
    807 
    808   void ReturnValue(HValue* value) override;
    809   void ReturnInstruction(HInstruction* instr, BailoutId ast_id) override;
    810   void ReturnControl(HControlInstruction* instr, BailoutId ast_id) override;
    811   void ReturnContinuation(HIfContinuation* continuation,
    812                           BailoutId ast_id) override;
    813 
    814   bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; }
    815 
    816  private:
    817   ArgumentsAllowedFlag flag_;
    818 };
    819 
    820 
    821 class TestContext final : public AstContext {
    822  public:
    823   TestContext(HOptimizedGraphBuilder* owner,
    824               Expression* condition,
    825               HBasicBlock* if_true,
    826               HBasicBlock* if_false)
    827       : AstContext(owner, Expression::kTest),
    828         condition_(condition),
    829         if_true_(if_true),
    830         if_false_(if_false) {
    831   }
    832 
    833   void ReturnValue(HValue* value) override;
    834   void ReturnInstruction(HInstruction* instr, BailoutId ast_id) override;
    835   void ReturnControl(HControlInstruction* instr, BailoutId ast_id) override;
    836   void ReturnContinuation(HIfContinuation* continuation,
    837                           BailoutId ast_id) override;
    838 
    839   static TestContext* cast(AstContext* context) {
    840     DCHECK(context->IsTest());
    841     return reinterpret_cast<TestContext*>(context);
    842   }
    843 
    844   Expression* condition() const { return condition_; }
    845   HBasicBlock* if_true() const { return if_true_; }
    846   HBasicBlock* if_false() const { return if_false_; }
    847 
    848  private:
    849   // Build the shared core part of the translation unpacking a value into
    850   // control flow.
    851   void BuildBranch(HValue* value);
    852 
    853   Expression* condition_;
    854   HBasicBlock* if_true_;
    855   HBasicBlock* if_false_;
    856 };
    857 
    858 
    859 class FunctionState final {
    860  public:
    861   FunctionState(HOptimizedGraphBuilder* owner,
    862                 CompilationInfo* info,
    863                 InliningKind inlining_kind,
    864                 int inlining_id);
    865   ~FunctionState();
    866 
    867   CompilationInfo* compilation_info() { return compilation_info_; }
    868   AstContext* call_context() { return call_context_; }
    869   InliningKind inlining_kind() const { return inlining_kind_; }
    870   HBasicBlock* function_return() { return function_return_; }
    871   TestContext* test_context() { return test_context_; }
    872   void ClearInlinedTestContext() {
    873     delete test_context_;
    874     test_context_ = NULL;
    875   }
    876 
    877   FunctionState* outer() { return outer_; }
    878 
    879   HEnterInlined* entry() { return entry_; }
    880   void set_entry(HEnterInlined* entry) { entry_ = entry; }
    881 
    882   HArgumentsObject* arguments_object() { return arguments_object_; }
    883   void set_arguments_object(HArgumentsObject* arguments_object) {
    884     arguments_object_ = arguments_object;
    885   }
    886 
    887   HArgumentsElements* arguments_elements() { return arguments_elements_; }
    888   void set_arguments_elements(HArgumentsElements* arguments_elements) {
    889     arguments_elements_ = arguments_elements;
    890   }
    891 
    892   bool arguments_pushed() { return arguments_elements() != NULL; }
    893 
    894   int inlining_id() const { return inlining_id_; }
    895 
    896  private:
    897   HOptimizedGraphBuilder* owner_;
    898 
    899   CompilationInfo* compilation_info_;
    900 
    901   // During function inlining, expression context of the call being
    902   // inlined. NULL when not inlining.
    903   AstContext* call_context_;
    904 
    905   // The kind of call which is currently being inlined.
    906   InliningKind inlining_kind_;
    907 
    908   // When inlining in an effect or value context, this is the return block.
    909   // It is NULL otherwise.  When inlining in a test context, there are a
    910   // pair of return blocks in the context.  When not inlining, there is no
    911   // local return point.
    912   HBasicBlock* function_return_;
    913 
    914   // When inlining a call in a test context, a context containing a pair of
    915   // return blocks.  NULL in all other cases.
    916   TestContext* test_context_;
    917 
    918   // When inlining HEnterInlined instruction corresponding to the function
    919   // entry.
    920   HEnterInlined* entry_;
    921 
    922   HArgumentsObject* arguments_object_;
    923   HArgumentsElements* arguments_elements_;
    924 
    925   int inlining_id_;
    926   SourcePosition outer_source_position_;
    927 
    928   FunctionState* outer_;
    929 };
    930 
    931 
    932 class HIfContinuation final {
    933  public:
    934   HIfContinuation()
    935     : continuation_captured_(false),
    936       true_branch_(NULL),
    937       false_branch_(NULL) {}
    938   HIfContinuation(HBasicBlock* true_branch,
    939                   HBasicBlock* false_branch)
    940       : continuation_captured_(true), true_branch_(true_branch),
    941         false_branch_(false_branch) {}
    942   ~HIfContinuation() { DCHECK(!continuation_captured_); }
    943 
    944   void Capture(HBasicBlock* true_branch,
    945                HBasicBlock* false_branch) {
    946     DCHECK(!continuation_captured_);
    947     true_branch_ = true_branch;
    948     false_branch_ = false_branch;
    949     continuation_captured_ = true;
    950   }
    951 
    952   void Continue(HBasicBlock** true_branch,
    953                 HBasicBlock** false_branch) {
    954     DCHECK(continuation_captured_);
    955     *true_branch = true_branch_;
    956     *false_branch = false_branch_;
    957     continuation_captured_ = false;
    958   }
    959 
    960   bool IsTrueReachable() { return true_branch_ != NULL; }
    961   bool IsFalseReachable() { return false_branch_ != NULL; }
    962   bool TrueAndFalseReachable() {
    963     return IsTrueReachable() || IsFalseReachable();
    964   }
    965 
    966   HBasicBlock* true_branch() const { return true_branch_; }
    967   HBasicBlock* false_branch() const { return false_branch_; }
    968 
    969  private:
    970   bool continuation_captured_;
    971   HBasicBlock* true_branch_;
    972   HBasicBlock* false_branch_;
    973 };
    974 
    975 
    976 class HAllocationMode final BASE_EMBEDDED {
    977  public:
    978   explicit HAllocationMode(Handle<AllocationSite> feedback_site)
    979       : current_site_(NULL), feedback_site_(feedback_site),
    980         pretenure_flag_(NOT_TENURED) {}
    981   explicit HAllocationMode(HValue* current_site)
    982       : current_site_(current_site), pretenure_flag_(NOT_TENURED) {}
    983   explicit HAllocationMode(PretenureFlag pretenure_flag)
    984       : current_site_(NULL), pretenure_flag_(pretenure_flag) {}
    985   HAllocationMode()
    986       : current_site_(NULL), pretenure_flag_(NOT_TENURED) {}
    987 
    988   HValue* current_site() const { return current_site_; }
    989   Handle<AllocationSite> feedback_site() const { return feedback_site_; }
    990 
    991   bool CreateAllocationMementos() const WARN_UNUSED_RESULT {
    992     return current_site() != NULL;
    993   }
    994 
    995   PretenureFlag GetPretenureMode() const WARN_UNUSED_RESULT {
    996     if (!feedback_site().is_null()) return feedback_site()->GetPretenureMode();
    997     return pretenure_flag_;
    998   }
    999 
   1000  private:
   1001   HValue* current_site_;
   1002   Handle<AllocationSite> feedback_site_;
   1003   PretenureFlag pretenure_flag_;
   1004 };
   1005 
   1006 
   1007 class HGraphBuilder {
   1008  public:
   1009   explicit HGraphBuilder(CompilationInfo* info)
   1010       : info_(info),
   1011         graph_(NULL),
   1012         current_block_(NULL),
   1013         scope_(info->scope()),
   1014         position_(SourcePosition::Unknown()),
   1015         start_position_(0) {}
   1016   virtual ~HGraphBuilder() {}
   1017 
   1018   Scope* scope() const { return scope_; }
   1019   void set_scope(Scope* scope) { scope_ = scope; }
   1020 
   1021   HBasicBlock* current_block() const { return current_block_; }
   1022   void set_current_block(HBasicBlock* block) { current_block_ = block; }
   1023   HEnvironment* environment() const {
   1024     return current_block()->last_environment();
   1025   }
   1026   Zone* zone() const { return info_->zone(); }
   1027   HGraph* graph() const { return graph_; }
   1028   Isolate* isolate() const { return graph_->isolate(); }
   1029   CompilationInfo* top_info() { return info_; }
   1030 
   1031   HGraph* CreateGraph();
   1032 
   1033   // Bailout environment manipulation.
   1034   void Push(HValue* value) { environment()->Push(value); }
   1035   HValue* Pop() { return environment()->Pop(); }
   1036 
   1037   virtual HValue* context() = 0;
   1038 
   1039   // Adding instructions.
   1040   HInstruction* AddInstruction(HInstruction* instr);
   1041   void FinishCurrentBlock(HControlInstruction* last);
   1042   void FinishExitCurrentBlock(HControlInstruction* instruction);
   1043 
   1044   void Goto(HBasicBlock* from,
   1045             HBasicBlock* target,
   1046             FunctionState* state = NULL,
   1047             bool add_simulate = true) {
   1048     from->Goto(target, source_position(), state, add_simulate);
   1049   }
   1050   void Goto(HBasicBlock* target,
   1051             FunctionState* state = NULL,
   1052             bool add_simulate = true) {
   1053     Goto(current_block(), target, state, add_simulate);
   1054   }
   1055   void GotoNoSimulate(HBasicBlock* from, HBasicBlock* target) {
   1056     Goto(from, target, NULL, false);
   1057   }
   1058   void GotoNoSimulate(HBasicBlock* target) {
   1059     Goto(target, NULL, false);
   1060   }
   1061   void AddLeaveInlined(HBasicBlock* block,
   1062                        HValue* return_value,
   1063                        FunctionState* state) {
   1064     block->AddLeaveInlined(return_value, state, source_position());
   1065   }
   1066   void AddLeaveInlined(HValue* return_value, FunctionState* state) {
   1067     return AddLeaveInlined(current_block(), return_value, state);
   1068   }
   1069 
   1070   template <class I>
   1071   HInstruction* NewUncasted() {
   1072     return I::New(isolate(), zone(), context());
   1073   }
   1074 
   1075   template <class I>
   1076   I* New() {
   1077     return I::New(isolate(), zone(), context());
   1078   }
   1079 
   1080   template<class I>
   1081   HInstruction* AddUncasted() { return AddInstruction(NewUncasted<I>());}
   1082 
   1083   template<class I>
   1084   I* Add() { return AddInstructionTyped(New<I>());}
   1085 
   1086   template<class I, class P1>
   1087   HInstruction* NewUncasted(P1 p1) {
   1088     return I::New(isolate(), zone(), context(), p1);
   1089   }
   1090 
   1091   template <class I, class P1>
   1092   I* New(P1 p1) {
   1093     return I::New(isolate(), zone(), context(), p1);
   1094   }
   1095 
   1096   template<class I, class P1>
   1097   HInstruction* AddUncasted(P1 p1) {
   1098     HInstruction* result = AddInstruction(NewUncasted<I>(p1));
   1099     // Specializations must have their parameters properly casted
   1100     // to avoid landing here.
   1101     DCHECK(!result->IsReturn() && !result->IsSimulate() &&
   1102            !result->IsDeoptimize());
   1103     return result;
   1104   }
   1105 
   1106   template<class I, class P1>
   1107   I* Add(P1 p1) {
   1108     I* result = AddInstructionTyped(New<I>(p1));
   1109     // Specializations must have their parameters properly casted
   1110     // to avoid landing here.
   1111     DCHECK(!result->IsReturn() && !result->IsSimulate() &&
   1112            !result->IsDeoptimize());
   1113     return result;
   1114   }
   1115 
   1116   template<class I, class P1, class P2>
   1117   HInstruction* NewUncasted(P1 p1, P2 p2) {
   1118     return I::New(isolate(), zone(), context(), p1, p2);
   1119   }
   1120 
   1121   template<class I, class P1, class P2>
   1122   I* New(P1 p1, P2 p2) {
   1123     return I::New(isolate(), zone(), context(), p1, p2);
   1124   }
   1125 
   1126   template<class I, class P1, class P2>
   1127   HInstruction* AddUncasted(P1 p1, P2 p2) {
   1128     HInstruction* result = AddInstruction(NewUncasted<I>(p1, p2));
   1129     // Specializations must have their parameters properly casted
   1130     // to avoid landing here.
   1131     DCHECK(!result->IsSimulate());
   1132     return result;
   1133   }
   1134 
   1135   template<class I, class P1, class P2>
   1136   I* Add(P1 p1, P2 p2) {
   1137     I* result = AddInstructionTyped(New<I>(p1, p2));
   1138     // Specializations must have their parameters properly casted
   1139     // to avoid landing here.
   1140     DCHECK(!result->IsSimulate());
   1141     return result;
   1142   }
   1143 
   1144   template<class I, class P1, class P2, class P3>
   1145   HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3) {
   1146     return I::New(isolate(), zone(), context(), p1, p2, p3);
   1147   }
   1148 
   1149   template<class I, class P1, class P2, class P3>
   1150   I* New(P1 p1, P2 p2, P3 p3) {
   1151     return I::New(isolate(), zone(), context(), p1, p2, p3);
   1152   }
   1153 
   1154   template<class I, class P1, class P2, class P3>
   1155   HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3) {
   1156     return AddInstruction(NewUncasted<I>(p1, p2, p3));
   1157   }
   1158 
   1159   template<class I, class P1, class P2, class P3>
   1160   I* Add(P1 p1, P2 p2, P3 p3) {
   1161     return AddInstructionTyped(New<I>(p1, p2, p3));
   1162   }
   1163 
   1164   template<class I, class P1, class P2, class P3, class P4>
   1165   HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4) {
   1166     return I::New(isolate(), zone(), context(), p1, p2, p3, p4);
   1167   }
   1168 
   1169   template<class I, class P1, class P2, class P3, class P4>
   1170   I* New(P1 p1, P2 p2, P3 p3, P4 p4) {
   1171     return I::New(isolate(), zone(), context(), p1, p2, p3, p4);
   1172   }
   1173 
   1174   template<class I, class P1, class P2, class P3, class P4>
   1175   HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4) {
   1176     return AddInstruction(NewUncasted<I>(p1, p2, p3, p4));
   1177   }
   1178 
   1179   template<class I, class P1, class P2, class P3, class P4>
   1180   I* Add(P1 p1, P2 p2, P3 p3, P4 p4) {
   1181     return AddInstructionTyped(New<I>(p1, p2, p3, p4));
   1182   }
   1183 
   1184   template<class I, class P1, class P2, class P3, class P4, class P5>
   1185   HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
   1186     return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5);
   1187   }
   1188 
   1189   template<class I, class P1, class P2, class P3, class P4, class P5>
   1190   I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
   1191     return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5);
   1192   }
   1193 
   1194   template<class I, class P1, class P2, class P3, class P4, class P5>
   1195   HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
   1196     return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5));
   1197   }
   1198 
   1199   template<class I, class P1, class P2, class P3, class P4, class P5>
   1200   I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
   1201     return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5));
   1202   }
   1203 
   1204   template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
   1205   HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
   1206     return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6);
   1207   }
   1208 
   1209   template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
   1210   I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
   1211     return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6);
   1212   }
   1213 
   1214   template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
   1215   HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
   1216     return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6));
   1217   }
   1218 
   1219   template<class I, class P1, class P2, class P3, class P4, class P5, class P6>
   1220   I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
   1221     return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6));
   1222   }
   1223 
   1224   template<class I, class P1, class P2, class P3, class P4,
   1225       class P5, class P6, class P7>
   1226   HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
   1227     return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6, p7);
   1228   }
   1229 
   1230   template<class I, class P1, class P2, class P3, class P4,
   1231       class P5, class P6, class P7>
   1232       I* New(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,
   1237            class P4, class P5, class P6, class P7>
   1238   HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
   1239     return AddInstruction(NewUncasted<I>(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   I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {
   1245     return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7));
   1246   }
   1247 
   1248   template<class I, class P1, class P2, class P3, class P4,
   1249       class P5, class P6, class P7, class P8>
   1250   HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4,
   1251                             P5 p5, P6 p6, P7 p7, P8 p8) {
   1252     return I::New(isolate(), zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8);
   1253   }
   1254 
   1255   template<class I, class P1, class P2, class P3, class P4,
   1256       class P5, class P6, class P7, class P8>
   1257       I* New(P1 p1, P2 p2, P3 p3, P4 p4, 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   HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4,
   1264                             P5 p5, P6 p6, P7 p7, P8 p8) {
   1265     return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8));
   1266   }
   1267 
   1268   template<class I, class P1, class P2, class P3, class P4,
   1269            class P5, class P6, class P7, class P8>
   1270   I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
   1271     return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7, p8));
   1272   }
   1273 
   1274   void AddSimulate(BailoutId id, RemovableSimulate removable = FIXED_SIMULATE);
   1275 
   1276   // When initializing arrays, we'll unfold the loop if the number of elements
   1277   // is known at compile time and is <= kElementLoopUnrollThreshold.
   1278   static const int kElementLoopUnrollThreshold = 8;
   1279 
   1280  protected:
   1281   virtual bool BuildGraph() = 0;
   1282 
   1283   HBasicBlock* CreateBasicBlock(HEnvironment* env);
   1284   HBasicBlock* CreateLoopHeaderBlock();
   1285 
   1286   template <class BitFieldClass>
   1287   HValue* BuildDecodeField(HValue* encoded_field) {
   1288     HValue* mask_value = Add<HConstant>(static_cast<int>(BitFieldClass::kMask));
   1289     HValue* masked_field =
   1290         AddUncasted<HBitwise>(Token::BIT_AND, encoded_field, mask_value);
   1291     return AddUncasted<HShr>(masked_field,
   1292         Add<HConstant>(static_cast<int>(BitFieldClass::kShift)));
   1293   }
   1294 
   1295   HValue* BuildGetElementsKind(HValue* object);
   1296 
   1297   HValue* BuildCheckHeapObject(HValue* object);
   1298   HValue* BuildCheckString(HValue* string);
   1299   HValue* BuildWrapReceiver(HValue* object, HValue* function);
   1300 
   1301   // Building common constructs
   1302   HValue* BuildCheckForCapacityGrow(HValue* object,
   1303                                     HValue* elements,
   1304                                     ElementsKind kind,
   1305                                     HValue* length,
   1306                                     HValue* key,
   1307                                     bool is_js_array,
   1308                                     PropertyAccessType access_type);
   1309 
   1310   HValue* BuildCheckAndGrowElementsCapacity(HValue* object, HValue* elements,
   1311                                             ElementsKind kind, HValue* length,
   1312                                             HValue* capacity, HValue* key);
   1313 
   1314   HValue* BuildCopyElementsOnWrite(HValue* object,
   1315                                    HValue* elements,
   1316                                    ElementsKind kind,
   1317                                    HValue* length);
   1318 
   1319   void BuildTransitionElementsKind(HValue* object,
   1320                                    HValue* map,
   1321                                    ElementsKind from_kind,
   1322                                    ElementsKind to_kind,
   1323                                    bool is_jsarray);
   1324 
   1325   HValue* BuildNumberToString(HValue* object, Type* type);
   1326   HValue* BuildToObject(HValue* receiver);
   1327 
   1328   void BuildJSObjectCheck(HValue* receiver,
   1329                           int bit_field_mask);
   1330 
   1331   // Checks a key value that's being used for a keyed element access context. If
   1332   // the key is a index, i.e. a smi or a number in a unique string with a cached
   1333   // numeric value, the "true" of the continuation is joined. Otherwise,
   1334   // if the key is a name or a unique string, the "false" of the continuation is
   1335   // joined. Otherwise, a deoptimization is triggered. In both paths of the
   1336   // continuation, the key is pushed on the top of the environment.
   1337   void BuildKeyedIndexCheck(HValue* key,
   1338                             HIfContinuation* join_continuation);
   1339 
   1340   // Checks the properties of an object if they are in dictionary case, in which
   1341   // case "true" of continuation is taken, otherwise the "false"
   1342   void BuildTestForDictionaryProperties(HValue* object,
   1343                                         HIfContinuation* continuation);
   1344 
   1345   void BuildNonGlobalObjectCheck(HValue* receiver);
   1346 
   1347   HValue* BuildKeyedLookupCacheHash(HValue* object,
   1348                                     HValue* key);
   1349 
   1350   HValue* BuildUncheckedDictionaryElementLoad(HValue* receiver,
   1351                                               HValue* elements, HValue* key,
   1352                                               HValue* hash,
   1353                                               LanguageMode language_mode);
   1354 
   1355   // ES6 section 7.4.7 CreateIterResultObject ( value, done )
   1356   HValue* BuildCreateIterResultObject(HValue* value, HValue* done);
   1357 
   1358   HValue* BuildRegExpConstructResult(HValue* length,
   1359                                      HValue* index,
   1360                                      HValue* input);
   1361 
   1362   // Allocates a new object according with the given allocation properties.
   1363   HAllocate* BuildAllocate(HValue* object_size,
   1364                            HType type,
   1365                            InstanceType instance_type,
   1366                            HAllocationMode allocation_mode);
   1367   // Computes the sum of two string lengths, taking care of overflow handling.
   1368   HValue* BuildAddStringLengths(HValue* left_length, HValue* right_length);
   1369   // Creates a cons string using the two input strings.
   1370   HValue* BuildCreateConsString(HValue* length,
   1371                                 HValue* left,
   1372                                 HValue* right,
   1373                                 HAllocationMode allocation_mode);
   1374   // Copies characters from one sequential string to another.
   1375   void BuildCopySeqStringChars(HValue* src,
   1376                                HValue* src_offset,
   1377                                String::Encoding src_encoding,
   1378                                HValue* dst,
   1379                                HValue* dst_offset,
   1380                                String::Encoding dst_encoding,
   1381                                HValue* length);
   1382 
   1383   // Align an object size to object alignment boundary
   1384   HValue* BuildObjectSizeAlignment(HValue* unaligned_size, int header_size);
   1385 
   1386   // Both operands are non-empty strings.
   1387   HValue* BuildUncheckedStringAdd(HValue* left,
   1388                                   HValue* right,
   1389                                   HAllocationMode allocation_mode);
   1390   // Add two strings using allocation mode, validating type feedback.
   1391   HValue* BuildStringAdd(HValue* left,
   1392                          HValue* right,
   1393                          HAllocationMode allocation_mode);
   1394 
   1395   HInstruction* BuildUncheckedMonomorphicElementAccess(
   1396       HValue* checked_object,
   1397       HValue* key,
   1398       HValue* val,
   1399       bool is_js_array,
   1400       ElementsKind elements_kind,
   1401       PropertyAccessType access_type,
   1402       LoadKeyedHoleMode load_mode,
   1403       KeyedAccessStoreMode store_mode);
   1404 
   1405   HInstruction* AddElementAccess(
   1406       HValue* elements, HValue* checked_key, HValue* val, HValue* dependency,
   1407       HValue* backing_store_owner, ElementsKind elements_kind,
   1408       PropertyAccessType access_type,
   1409       LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE);
   1410 
   1411   HInstruction* AddLoadStringInstanceType(HValue* string);
   1412   HInstruction* AddLoadStringLength(HValue* string);
   1413   HInstruction* BuildLoadStringLength(HValue* string);
   1414   HStoreNamedField* AddStoreMapConstant(HValue* object, Handle<Map> map) {
   1415     return Add<HStoreNamedField>(object, HObjectAccess::ForMap(),
   1416                                  Add<HConstant>(map));
   1417   }
   1418   HLoadNamedField* AddLoadMap(HValue* object,
   1419                               HValue* dependency = NULL);
   1420   HLoadNamedField* AddLoadElements(HValue* object,
   1421                                    HValue* dependency = NULL);
   1422 
   1423   bool MatchRotateRight(HValue* left,
   1424                         HValue* right,
   1425                         HValue** operand,
   1426                         HValue** shift_amount);
   1427 
   1428   HValue* BuildBinaryOperation(Token::Value op, HValue* left, HValue* right,
   1429                                Type* left_type, Type* right_type,
   1430                                Type* result_type, Maybe<int> fixed_right_arg,
   1431                                HAllocationMode allocation_mode,
   1432                                Strength strength,
   1433                                BailoutId opt_id = BailoutId::None());
   1434 
   1435   HLoadNamedField* AddLoadFixedArrayLength(HValue *object,
   1436                                            HValue *dependency = NULL);
   1437 
   1438   HLoadNamedField* AddLoadArrayLength(HValue *object,
   1439                                       ElementsKind kind,
   1440                                       HValue *dependency = NULL);
   1441 
   1442   HValue* AddLoadJSBuiltin(int context_index);
   1443 
   1444   HValue* EnforceNumberType(HValue* number, Type* expected);
   1445   HValue* TruncateToNumber(HValue* value, Type** expected);
   1446 
   1447   void FinishExitWithHardDeoptimization(Deoptimizer::DeoptReason reason);
   1448 
   1449   void AddIncrementCounter(StatsCounter* counter);
   1450 
   1451   class IfBuilder final {
   1452    public:
   1453     // If using this constructor, Initialize() must be called explicitly!
   1454     IfBuilder();
   1455 
   1456     explicit IfBuilder(HGraphBuilder* builder);
   1457     IfBuilder(HGraphBuilder* builder,
   1458               HIfContinuation* continuation);
   1459 
   1460     ~IfBuilder() {
   1461       if (!finished_) End();
   1462     }
   1463 
   1464     void Initialize(HGraphBuilder* builder);
   1465 
   1466     template<class Condition>
   1467     Condition* If(HValue *p) {
   1468       Condition* compare = builder()->New<Condition>(p);
   1469       AddCompare(compare);
   1470       return compare;
   1471     }
   1472 
   1473     template<class Condition, class P2>
   1474     Condition* If(HValue* p1, P2 p2) {
   1475       Condition* compare = builder()->New<Condition>(p1, p2);
   1476       AddCompare(compare);
   1477       return compare;
   1478     }
   1479 
   1480     template<class Condition, class P2, class P3>
   1481     Condition* If(HValue* p1, P2 p2, P3 p3) {
   1482       Condition* compare = builder()->New<Condition>(p1, p2, p3);
   1483       AddCompare(compare);
   1484       return compare;
   1485     }
   1486 
   1487     template<class Condition>
   1488     Condition* IfNot(HValue* p) {
   1489       Condition* compare = If<Condition>(p);
   1490       compare->Not();
   1491       return compare;
   1492     }
   1493 
   1494     template<class Condition, class P2>
   1495     Condition* IfNot(HValue* p1, P2 p2) {
   1496       Condition* compare = If<Condition>(p1, p2);
   1497       compare->Not();
   1498       return compare;
   1499     }
   1500 
   1501     template<class Condition, class P2, class P3>
   1502     Condition* IfNot(HValue* p1, P2 p2, P3 p3) {
   1503       Condition* compare = If<Condition>(p1, p2, p3);
   1504       compare->Not();
   1505       return compare;
   1506     }
   1507 
   1508     template<class Condition>
   1509     Condition* OrIf(HValue *p) {
   1510       Or();
   1511       return If<Condition>(p);
   1512     }
   1513 
   1514     template<class Condition, class P2>
   1515     Condition* OrIf(HValue* p1, P2 p2) {
   1516       Or();
   1517       return If<Condition>(p1, p2);
   1518     }
   1519 
   1520     template<class Condition, class P2, class P3>
   1521     Condition* OrIf(HValue* p1, P2 p2, P3 p3) {
   1522       Or();
   1523       return If<Condition>(p1, p2, p3);
   1524     }
   1525 
   1526     template<class Condition>
   1527     Condition* AndIf(HValue *p) {
   1528       And();
   1529       return If<Condition>(p);
   1530     }
   1531 
   1532     template<class Condition, class P2>
   1533     Condition* AndIf(HValue* p1, P2 p2) {
   1534       And();
   1535       return If<Condition>(p1, p2);
   1536     }
   1537 
   1538     template<class Condition, class P2, class P3>
   1539     Condition* AndIf(HValue* p1, P2 p2, P3 p3) {
   1540       And();
   1541       return If<Condition>(p1, p2, p3);
   1542     }
   1543 
   1544     void Or();
   1545     void And();
   1546 
   1547     // Captures the current state of this IfBuilder in the specified
   1548     // continuation and ends this IfBuilder.
   1549     void CaptureContinuation(HIfContinuation* continuation);
   1550 
   1551     // Joins the specified continuation from this IfBuilder and ends this
   1552     // IfBuilder. This appends a Goto instruction from the true branch of
   1553     // this IfBuilder to the true branch of the continuation unless the
   1554     // true branch of this IfBuilder is already finished. And vice versa
   1555     // for the false branch.
   1556     //
   1557     // The basic idea is as follows: You have several nested IfBuilder's
   1558     // that you want to join based on two possible outcomes (i.e. success
   1559     // and failure, or whatever). You can do this easily using this method
   1560     // now, for example:
   1561     //
   1562     //   HIfContinuation cont(graph()->CreateBasicBlock(),
   1563     //                        graph()->CreateBasicBlock());
   1564     //   ...
   1565     //     IfBuilder if_whatever(this);
   1566     //     if_whatever.If<Condition>(arg);
   1567     //     if_whatever.Then();
   1568     //     ...
   1569     //     if_whatever.Else();
   1570     //     ...
   1571     //     if_whatever.JoinContinuation(&cont);
   1572     //   ...
   1573     //     IfBuilder if_something(this);
   1574     //     if_something.If<Condition>(arg1, arg2);
   1575     //     if_something.Then();
   1576     //     ...
   1577     //     if_something.Else();
   1578     //     ...
   1579     //     if_something.JoinContinuation(&cont);
   1580     //   ...
   1581     //   IfBuilder if_finally(this, &cont);
   1582     //   if_finally.Then();
   1583     //   // continues after then code of if_whatever or if_something.
   1584     //   ...
   1585     //   if_finally.Else();
   1586     //   // continues after else code of if_whatever or if_something.
   1587     //   ...
   1588     //   if_finally.End();
   1589     void JoinContinuation(HIfContinuation* continuation);
   1590 
   1591     void Then();
   1592     void Else();
   1593     void End();
   1594     void EndUnreachable();
   1595 
   1596     void Deopt(Deoptimizer::DeoptReason reason);
   1597     void ThenDeopt(Deoptimizer::DeoptReason reason) {
   1598       Then();
   1599       Deopt(reason);
   1600     }
   1601     void ElseDeopt(Deoptimizer::DeoptReason reason) {
   1602       Else();
   1603       Deopt(reason);
   1604     }
   1605 
   1606     void Return(HValue* value);
   1607 
   1608    private:
   1609     void InitializeDontCreateBlocks(HGraphBuilder* builder);
   1610 
   1611     HControlInstruction* AddCompare(HControlInstruction* compare);
   1612 
   1613     HGraphBuilder* builder() const {
   1614       DCHECK(builder_ != NULL);  // Have you called "Initialize"?
   1615       return builder_;
   1616     }
   1617 
   1618     void AddMergeAtJoinBlock(bool deopt);
   1619 
   1620     void Finish();
   1621     void Finish(HBasicBlock** then_continuation,
   1622                 HBasicBlock** else_continuation);
   1623 
   1624     class MergeAtJoinBlock : public ZoneObject {
   1625      public:
   1626       MergeAtJoinBlock(HBasicBlock* block,
   1627                        bool deopt,
   1628                        MergeAtJoinBlock* next)
   1629         : block_(block),
   1630           deopt_(deopt),
   1631           next_(next) {}
   1632       HBasicBlock* block_;
   1633       bool deopt_;
   1634       MergeAtJoinBlock* next_;
   1635     };
   1636 
   1637     HGraphBuilder* builder_;
   1638     bool finished_ : 1;
   1639     bool did_then_ : 1;
   1640     bool did_else_ : 1;
   1641     bool did_else_if_ : 1;
   1642     bool did_and_ : 1;
   1643     bool did_or_ : 1;
   1644     bool captured_ : 1;
   1645     bool needs_compare_ : 1;
   1646     bool pending_merge_block_ : 1;
   1647     HBasicBlock* first_true_block_;
   1648     HBasicBlock* first_false_block_;
   1649     HBasicBlock* split_edge_merge_block_;
   1650     MergeAtJoinBlock* merge_at_join_blocks_;
   1651     int normal_merge_at_join_block_count_;
   1652     int deopt_merge_at_join_block_count_;
   1653   };
   1654 
   1655   class LoopBuilder final {
   1656    public:
   1657     enum Direction {
   1658       kPreIncrement,
   1659       kPostIncrement,
   1660       kPreDecrement,
   1661       kPostDecrement,
   1662       kWhileTrue
   1663     };
   1664 
   1665     explicit LoopBuilder(HGraphBuilder* builder);  // while (true) {...}
   1666     LoopBuilder(HGraphBuilder* builder,
   1667                 HValue* context,
   1668                 Direction direction);
   1669     LoopBuilder(HGraphBuilder* builder,
   1670                 HValue* context,
   1671                 Direction direction,
   1672                 HValue* increment_amount);
   1673 
   1674     ~LoopBuilder() {
   1675       DCHECK(finished_);
   1676     }
   1677 
   1678     HValue* BeginBody(
   1679         HValue* initial,
   1680         HValue* terminating,
   1681         Token::Value token);
   1682 
   1683     void BeginBody(int drop_count);
   1684 
   1685     void Break();
   1686 
   1687     void EndBody();
   1688 
   1689    private:
   1690     void Initialize(HGraphBuilder* builder, HValue* context,
   1691                     Direction direction, HValue* increment_amount);
   1692     Zone* zone() { return builder_->zone(); }
   1693 
   1694     HGraphBuilder* builder_;
   1695     HValue* context_;
   1696     HValue* increment_amount_;
   1697     HInstruction* increment_;
   1698     HPhi* phi_;
   1699     HBasicBlock* header_block_;
   1700     HBasicBlock* body_block_;
   1701     HBasicBlock* exit_block_;
   1702     HBasicBlock* exit_trampoline_block_;
   1703     Direction direction_;
   1704     bool finished_;
   1705   };
   1706 
   1707   HValue* BuildNewElementsCapacity(HValue* old_capacity);
   1708 
   1709   class JSArrayBuilder final {
   1710    public:
   1711     JSArrayBuilder(HGraphBuilder* builder,
   1712                    ElementsKind kind,
   1713                    HValue* allocation_site_payload,
   1714                    HValue* constructor_function,
   1715                    AllocationSiteOverrideMode override_mode);
   1716 
   1717     JSArrayBuilder(HGraphBuilder* builder,
   1718                    ElementsKind kind,
   1719                    HValue* constructor_function = NULL);
   1720 
   1721     enum FillMode {
   1722       DONT_FILL_WITH_HOLE,
   1723       FILL_WITH_HOLE
   1724     };
   1725 
   1726     ElementsKind kind() { return kind_; }
   1727     HAllocate* elements_location() { return elements_location_; }
   1728 
   1729     HAllocate* AllocateEmptyArray();
   1730     HAllocate* AllocateArray(HValue* capacity,
   1731                              HValue* length_field,
   1732                              FillMode fill_mode = FILL_WITH_HOLE);
   1733     // Use these allocators when capacity could be unknown at compile time
   1734     // but its limit is known. For constant |capacity| the value of
   1735     // |capacity_upper_bound| is ignored and the actual |capacity|
   1736     // value is used as an upper bound.
   1737     HAllocate* AllocateArray(HValue* capacity,
   1738                              int capacity_upper_bound,
   1739                              HValue* length_field,
   1740                              FillMode fill_mode = FILL_WITH_HOLE);
   1741     HAllocate* AllocateArray(HValue* capacity,
   1742                              HConstant* capacity_upper_bound,
   1743                              HValue* length_field,
   1744                              FillMode fill_mode = FILL_WITH_HOLE);
   1745     HValue* GetElementsLocation() { return elements_location_; }
   1746     HValue* EmitMapCode();
   1747 
   1748    private:
   1749     Zone* zone() const { return builder_->zone(); }
   1750     int elements_size() const {
   1751       return IsFastDoubleElementsKind(kind_) ? kDoubleSize : kPointerSize;
   1752     }
   1753     HGraphBuilder* builder() { return builder_; }
   1754     HGraph* graph() { return builder_->graph(); }
   1755     int initial_capacity() {
   1756       STATIC_ASSERT(JSArray::kPreallocatedArrayElements > 0);
   1757       return JSArray::kPreallocatedArrayElements;
   1758     }
   1759 
   1760     HValue* EmitInternalMapCode();
   1761 
   1762     HGraphBuilder* builder_;
   1763     ElementsKind kind_;
   1764     AllocationSiteMode mode_;
   1765     HValue* allocation_site_payload_;
   1766     HValue* constructor_function_;
   1767     HAllocate* elements_location_;
   1768   };
   1769 
   1770   HValue* BuildAllocateArrayFromLength(JSArrayBuilder* array_builder,
   1771                                        HValue* length_argument);
   1772   HValue* BuildCalculateElementsSize(ElementsKind kind,
   1773                                      HValue* capacity);
   1774   HAllocate* AllocateJSArrayObject(AllocationSiteMode mode);
   1775   HConstant* EstablishElementsAllocationSize(ElementsKind kind, int capacity);
   1776 
   1777   HAllocate* BuildAllocateElements(ElementsKind kind, HValue* size_in_bytes);
   1778 
   1779   void BuildInitializeElementsHeader(HValue* elements,
   1780                                      ElementsKind kind,
   1781                                      HValue* capacity);
   1782 
   1783   // Build allocation and header initialization code for respective successor
   1784   // of FixedArrayBase.
   1785   HValue* BuildAllocateAndInitializeArray(ElementsKind kind, HValue* capacity);
   1786 
   1787   // |array| must have been allocated with enough room for
   1788   // 1) the JSArray and 2) an AllocationMemento if mode requires it.
   1789   // If the |elements| value provided is NULL then the array elements storage
   1790   // is initialized with empty array.
   1791   void BuildJSArrayHeader(HValue* array,
   1792                           HValue* array_map,
   1793                           HValue* elements,
   1794                           AllocationSiteMode mode,
   1795                           ElementsKind elements_kind,
   1796                           HValue* allocation_site_payload,
   1797                           HValue* length_field);
   1798 
   1799   HValue* BuildGrowElementsCapacity(HValue* object,
   1800                                     HValue* elements,
   1801                                     ElementsKind kind,
   1802                                     ElementsKind new_kind,
   1803                                     HValue* length,
   1804                                     HValue* new_capacity);
   1805 
   1806   void BuildFillElementsWithValue(HValue* elements,
   1807                                   ElementsKind elements_kind,
   1808                                   HValue* from,
   1809                                   HValue* to,
   1810                                   HValue* value);
   1811 
   1812   void BuildFillElementsWithHole(HValue* elements,
   1813                                  ElementsKind elements_kind,
   1814                                  HValue* from,
   1815                                  HValue* to);
   1816 
   1817   void BuildCopyProperties(HValue* from_properties, HValue* to_properties,
   1818                            HValue* length, HValue* capacity);
   1819 
   1820   void BuildCopyElements(HValue* from_elements,
   1821                          ElementsKind from_elements_kind,
   1822                          HValue* to_elements,
   1823                          ElementsKind to_elements_kind,
   1824                          HValue* length,
   1825                          HValue* capacity);
   1826 
   1827   HValue* BuildCloneShallowArrayCow(HValue* boilerplate,
   1828                                     HValue* allocation_site,
   1829                                     AllocationSiteMode mode,
   1830                                     ElementsKind kind);
   1831 
   1832   HValue* BuildCloneShallowArrayEmpty(HValue* boilerplate,
   1833                                       HValue* allocation_site,
   1834                                       AllocationSiteMode mode);
   1835 
   1836   HValue* BuildCloneShallowArrayNonEmpty(HValue* boilerplate,
   1837                                          HValue* allocation_site,
   1838                                          AllocationSiteMode mode,
   1839                                          ElementsKind kind);
   1840 
   1841   HValue* BuildElementIndexHash(HValue* index);
   1842 
   1843   enum MapEmbedding { kEmbedMapsDirectly, kEmbedMapsViaWeakCells };
   1844 
   1845   void BuildCompareNil(HValue* value, Type* type, HIfContinuation* continuation,
   1846                        MapEmbedding map_embedding = kEmbedMapsDirectly);
   1847 
   1848   void BuildCreateAllocationMemento(HValue* previous_object,
   1849                                     HValue* previous_object_size,
   1850                                     HValue* payload);
   1851 
   1852   HInstruction* BuildConstantMapCheck(Handle<JSObject> constant);
   1853   HInstruction* BuildCheckPrototypeMaps(Handle<JSObject> prototype,
   1854                                         Handle<JSObject> holder);
   1855 
   1856   HInstruction* BuildGetNativeContext(HValue* closure);
   1857   HInstruction* BuildGetNativeContext();
   1858   HInstruction* BuildGetScriptContext(int context_index);
   1859   // Builds a loop version if |depth| is specified or unrolls the loop to
   1860   // |depth_value| iterations otherwise.
   1861   HValue* BuildGetParentContext(HValue* depth, int depth_value);
   1862 
   1863   HInstruction* BuildGetArrayFunction();
   1864   HValue* BuildArrayBufferViewFieldAccessor(HValue* object,
   1865                                             HValue* checked_object,
   1866                                             FieldIndex index);
   1867 
   1868 
   1869  protected:
   1870   void SetSourcePosition(int position) {
   1871     if (position != RelocInfo::kNoPosition) {
   1872       position_.set_position(position - start_position_);
   1873     }
   1874     // Otherwise position remains unknown.
   1875   }
   1876 
   1877   void EnterInlinedSource(int start_position, int id) {
   1878     if (top_info()->is_tracking_positions()) {
   1879       start_position_ = start_position;
   1880       position_.set_inlining_id(id);
   1881     }
   1882   }
   1883 
   1884   // Convert the given absolute offset from the start of the script to
   1885   // the SourcePosition assuming that this position corresponds to the
   1886   // same function as current position_.
   1887   SourcePosition ScriptPositionToSourcePosition(int position) {
   1888     if (position == RelocInfo::kNoPosition) {
   1889       return SourcePosition::Unknown();
   1890     }
   1891     SourcePosition pos = position_;
   1892     pos.set_position(position - start_position_);
   1893     return pos;
   1894   }
   1895 
   1896   SourcePosition source_position() { return position_; }
   1897   void set_source_position(SourcePosition position) { position_ = position; }
   1898 
   1899   HValue* BuildAllocateEmptyArrayBuffer(HValue* byte_length);
   1900   template <typename ViewClass>
   1901   void BuildArrayBufferViewInitialization(HValue* obj,
   1902                                           HValue* buffer,
   1903                                           HValue* byte_offset,
   1904                                           HValue* byte_length);
   1905 
   1906  private:
   1907   HGraphBuilder();
   1908 
   1909   template <class I>
   1910   I* AddInstructionTyped(I* instr) {
   1911     return I::cast(AddInstruction(instr));
   1912   }
   1913 
   1914   CompilationInfo* info_;
   1915   HGraph* graph_;
   1916   HBasicBlock* current_block_;
   1917   Scope* scope_;
   1918   SourcePosition position_;
   1919   int start_position_;
   1920 };
   1921 
   1922 
   1923 template <>
   1924 inline HDeoptimize* HGraphBuilder::Add<HDeoptimize>(
   1925     Deoptimizer::DeoptReason reason, Deoptimizer::BailoutType type) {
   1926   if (type == Deoptimizer::SOFT) {
   1927     isolate()->counters()->soft_deopts_requested()->Increment();
   1928     if (FLAG_always_opt) return NULL;
   1929   }
   1930   if (current_block()->IsDeoptimizing()) return NULL;
   1931   HBasicBlock* after_deopt_block = CreateBasicBlock(
   1932       current_block()->last_environment());
   1933   HDeoptimize* instr = New<HDeoptimize>(reason, type, after_deopt_block);
   1934   if (type == Deoptimizer::SOFT) {
   1935     isolate()->counters()->soft_deopts_inserted()->Increment();
   1936   }
   1937   FinishCurrentBlock(instr);
   1938   set_current_block(after_deopt_block);
   1939   return instr;
   1940 }
   1941 
   1942 
   1943 template <>
   1944 inline HInstruction* HGraphBuilder::AddUncasted<HDeoptimize>(
   1945     Deoptimizer::DeoptReason reason, Deoptimizer::BailoutType type) {
   1946   return Add<HDeoptimize>(reason, type);
   1947 }
   1948 
   1949 
   1950 template<>
   1951 inline HSimulate* HGraphBuilder::Add<HSimulate>(
   1952     BailoutId id,
   1953     RemovableSimulate removable) {
   1954   HSimulate* instr = current_block()->CreateSimulate(id, removable);
   1955   AddInstruction(instr);
   1956   return instr;
   1957 }
   1958 
   1959 
   1960 template<>
   1961 inline HSimulate* HGraphBuilder::Add<HSimulate>(
   1962     BailoutId id) {
   1963   return Add<HSimulate>(id, FIXED_SIMULATE);
   1964 }
   1965 
   1966 
   1967 template<>
   1968 inline HInstruction* HGraphBuilder::AddUncasted<HSimulate>(BailoutId id) {
   1969   return Add<HSimulate>(id, FIXED_SIMULATE);
   1970 }
   1971 
   1972 
   1973 template<>
   1974 inline HReturn* HGraphBuilder::Add<HReturn>(HValue* value) {
   1975   int num_parameters = graph()->info()->num_parameters();
   1976   HValue* params = AddUncasted<HConstant>(num_parameters);
   1977   HReturn* return_instruction = New<HReturn>(value, params);
   1978   FinishExitCurrentBlock(return_instruction);
   1979   return return_instruction;
   1980 }
   1981 
   1982 
   1983 template<>
   1984 inline HReturn* HGraphBuilder::Add<HReturn>(HConstant* value) {
   1985   return Add<HReturn>(static_cast<HValue*>(value));
   1986 }
   1987 
   1988 template<>
   1989 inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HValue* value) {
   1990   return Add<HReturn>(value);
   1991 }
   1992 
   1993 
   1994 template<>
   1995 inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HConstant* value) {
   1996   return Add<HReturn>(value);
   1997 }
   1998 
   1999 
   2000 template<>
   2001 inline HCallRuntime* HGraphBuilder::Add<HCallRuntime>(
   2002     const Runtime::Function* c_function,
   2003     int argument_count) {
   2004   HCallRuntime* instr = New<HCallRuntime>(c_function, argument_count);
   2005   if (graph()->info()->IsStub()) {
   2006     // When compiling code stubs, we don't want to save all double registers
   2007     // upon entry to the stub, but instead have the call runtime instruction
   2008     // save the double registers only on-demand (in the fallback case).
   2009     instr->set_save_doubles(kSaveFPRegs);
   2010   }
   2011   AddInstruction(instr);
   2012   return instr;
   2013 }
   2014 
   2015 
   2016 template<>
   2017 inline HInstruction* HGraphBuilder::AddUncasted<HCallRuntime>(
   2018     Handle<String> name,
   2019     const Runtime::Function* c_function,
   2020     int argument_count) {
   2021   return Add<HCallRuntime>(c_function, argument_count);
   2022 }
   2023 
   2024 
   2025 template <>
   2026 inline HParameter* HGraphBuilder::New<HParameter>(unsigned index) {
   2027   return HParameter::New(isolate(), zone(), nullptr, index);
   2028 }
   2029 
   2030 
   2031 template <>
   2032 inline HParameter* HGraphBuilder::New<HParameter>(
   2033     unsigned index, HParameter::ParameterKind kind) {
   2034   return HParameter::New(isolate(), zone(), nullptr, index, kind);
   2035 }
   2036 
   2037 
   2038 template <>
   2039 inline HParameter* HGraphBuilder::New<HParameter>(
   2040     unsigned index, HParameter::ParameterKind kind, Representation r) {
   2041   return HParameter::New(isolate(), zone(), nullptr, index, kind, r);
   2042 }
   2043 
   2044 
   2045 template <>
   2046 inline HPrologue* HGraphBuilder::New<HPrologue>() {
   2047   return HPrologue::New(zone());
   2048 }
   2049 
   2050 
   2051 template <>
   2052 inline HContext* HGraphBuilder::New<HContext>() {
   2053   return HContext::New(zone());
   2054 }
   2055 
   2056 
   2057 class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
   2058  public:
   2059   // A class encapsulating (lazily-allocated) break and continue blocks for
   2060   // a breakable statement.  Separated from BreakAndContinueScope so that it
   2061   // can have a separate lifetime.
   2062   class BreakAndContinueInfo final BASE_EMBEDDED {
   2063    public:
   2064     explicit BreakAndContinueInfo(BreakableStatement* target,
   2065                                   Scope* scope,
   2066                                   int drop_extra = 0)
   2067         : target_(target),
   2068           break_block_(NULL),
   2069           continue_block_(NULL),
   2070           scope_(scope),
   2071           drop_extra_(drop_extra) {
   2072     }
   2073 
   2074     BreakableStatement* target() { return target_; }
   2075     HBasicBlock* break_block() { return break_block_; }
   2076     void set_break_block(HBasicBlock* block) { break_block_ = block; }
   2077     HBasicBlock* continue_block() { return continue_block_; }
   2078     void set_continue_block(HBasicBlock* block) { continue_block_ = block; }
   2079     Scope* scope() { return scope_; }
   2080     int drop_extra() { return drop_extra_; }
   2081 
   2082    private:
   2083     BreakableStatement* target_;
   2084     HBasicBlock* break_block_;
   2085     HBasicBlock* continue_block_;
   2086     Scope* scope_;
   2087     int drop_extra_;
   2088   };
   2089 
   2090   // A helper class to maintain a stack of current BreakAndContinueInfo
   2091   // structures mirroring BreakableStatement nesting.
   2092   class BreakAndContinueScope final BASE_EMBEDDED {
   2093    public:
   2094     BreakAndContinueScope(BreakAndContinueInfo* info,
   2095                           HOptimizedGraphBuilder* owner)
   2096         : info_(info), owner_(owner), next_(owner->break_scope()) {
   2097       owner->set_break_scope(this);
   2098     }
   2099 
   2100     ~BreakAndContinueScope() { owner_->set_break_scope(next_); }
   2101 
   2102     BreakAndContinueInfo* info() { return info_; }
   2103     HOptimizedGraphBuilder* owner() { return owner_; }
   2104     BreakAndContinueScope* next() { return next_; }
   2105 
   2106     // Search the break stack for a break or continue target.
   2107     enum BreakType { BREAK, CONTINUE };
   2108     HBasicBlock* Get(BreakableStatement* stmt, BreakType type,
   2109                      Scope** scope, int* drop_extra);
   2110 
   2111    private:
   2112     BreakAndContinueInfo* info_;
   2113     HOptimizedGraphBuilder* owner_;
   2114     BreakAndContinueScope* next_;
   2115   };
   2116 
   2117   explicit HOptimizedGraphBuilder(CompilationInfo* info);
   2118 
   2119   bool BuildGraph() override;
   2120 
   2121   // Simple accessors.
   2122   BreakAndContinueScope* break_scope() const { return break_scope_; }
   2123   void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }
   2124 
   2125   HValue* context() override { return environment()->context(); }
   2126 
   2127   HOsrBuilder* osr() const { return osr_; }
   2128 
   2129   void Bailout(BailoutReason reason);
   2130 
   2131   HBasicBlock* CreateJoin(HBasicBlock* first,
   2132                           HBasicBlock* second,
   2133                           BailoutId join_id);
   2134 
   2135   FunctionState* function_state() const { return function_state_; }
   2136 
   2137   void VisitDeclarations(ZoneList<Declaration*>* declarations) override;
   2138 
   2139   void* operator new(size_t size, Zone* zone) { return zone->New(size); }
   2140   void operator delete(void* pointer, Zone* zone) { }
   2141   void operator delete(void* pointer) { }
   2142 
   2143   DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
   2144 
   2145  protected:
   2146   // Forward declarations for inner scope classes.
   2147   class SubgraphScope;
   2148 
   2149   static const int kMaxCallPolymorphism = 4;
   2150   static const int kMaxLoadPolymorphism = 4;
   2151   static const int kMaxStorePolymorphism = 4;
   2152 
   2153   // Even in the 'unlimited' case we have to have some limit in order not to
   2154   // overflow the stack.
   2155   static const int kUnlimitedMaxInlinedSourceSize = 100000;
   2156   static const int kUnlimitedMaxInlinedNodes = 10000;
   2157   static const int kUnlimitedMaxInlinedNodesCumulative = 10000;
   2158 
   2159   // Maximum depth and total number of elements and properties for literal
   2160   // graphs to be considered for fast deep-copying.
   2161   static const int kMaxFastLiteralDepth = 3;
   2162   static const int kMaxFastLiteralProperties = 8;
   2163 
   2164   // Simple accessors.
   2165   void set_function_state(FunctionState* state) { function_state_ = state; }
   2166 
   2167   AstContext* ast_context() const { return ast_context_; }
   2168   void set_ast_context(AstContext* context) { ast_context_ = context; }
   2169 
   2170   // Accessors forwarded to the function state.
   2171   CompilationInfo* current_info() const {
   2172     return function_state()->compilation_info();
   2173   }
   2174   AstContext* call_context() const {
   2175     return function_state()->call_context();
   2176   }
   2177   HBasicBlock* function_return() const {
   2178     return function_state()->function_return();
   2179   }
   2180   TestContext* inlined_test_context() const {
   2181     return function_state()->test_context();
   2182   }
   2183   Handle<SharedFunctionInfo> current_shared_info() const {
   2184     return current_info()->shared_info();
   2185   }
   2186   TypeFeedbackVector* current_feedback_vector() const {
   2187     return current_shared_info()->feedback_vector();
   2188   }
   2189   void ClearInlinedTestContext() {
   2190     function_state()->ClearInlinedTestContext();
   2191   }
   2192   LanguageMode function_language_mode() {
   2193     return function_state()->compilation_info()->language_mode();
   2194   }
   2195 
   2196 #define FOR_EACH_HYDROGEN_INTRINSIC(F) \
   2197   F(IsSmi)                             \
   2198   F(IsArray)                           \
   2199   F(IsTypedArray)                      \
   2200   F(IsRegExp)                          \
   2201   F(IsJSProxy)                         \
   2202   F(Call)                              \
   2203   F(ArgumentsLength)                   \
   2204   F(Arguments)                         \
   2205   F(ValueOf)                           \
   2206   F(SetValueOf)                        \
   2207   F(IsDate)                            \
   2208   F(StringCharFromCode)                \
   2209   F(StringCharAt)                      \
   2210   F(OneByteSeqStringSetChar)           \
   2211   F(TwoByteSeqStringSetChar)           \
   2212   F(ObjectEquals)                      \
   2213   F(ToInteger)                         \
   2214   F(ToObject)                          \
   2215   F(ToString)                          \
   2216   F(ToLength)                          \
   2217   F(ToNumber)                          \
   2218   F(IsFunction)                        \
   2219   F(IsJSReceiver)                      \
   2220   F(MathPow)                           \
   2221   F(IsMinusZero)                       \
   2222   F(HasCachedArrayIndex)               \
   2223   F(GetCachedArrayIndex)               \
   2224   F(FastOneByteArrayJoin)              \
   2225   F(DebugBreakInOptimizedCode)         \
   2226   F(StringCharCodeAt)                  \
   2227   F(SubString)                         \
   2228   F(RegExpExec)                        \
   2229   F(RegExpConstructResult)             \
   2230   F(RegExpFlags)                       \
   2231   F(RegExpSource)                      \
   2232   F(NumberToString)                    \
   2233   F(DebugIsActive)                     \
   2234   /* Typed Arrays */                   \
   2235   F(TypedArrayInitialize)              \
   2236   F(DataViewInitialize)                \
   2237   F(MaxSmi)                            \
   2238   F(TypedArrayMaxSizeInHeap)           \
   2239   F(ArrayBufferViewGetByteLength)      \
   2240   F(ArrayBufferViewGetByteOffset)      \
   2241   F(TypedArrayGetLength)               \
   2242   /* ArrayBuffer */                    \
   2243   F(ArrayBufferGetByteLength)          \
   2244   /* Maths */                          \
   2245   F(ConstructDouble)                   \
   2246   F(DoubleHi)                          \
   2247   F(DoubleLo)                          \
   2248   F(MathClz32)                         \
   2249   F(MathFloor)                         \
   2250   F(MathSqrt)                          \
   2251   F(MathLogRT)                         \
   2252   /* ES6 Collections */                \
   2253   F(MapClear)                          \
   2254   F(MapInitialize)                     \
   2255   F(SetClear)                          \
   2256   F(SetInitialize)                     \
   2257   F(FixedArrayGet)                     \
   2258   F(FixedArraySet)                     \
   2259   F(JSCollectionGetTable)              \
   2260   F(StringGetRawHashField)             \
   2261   F(TheHole)                           \
   2262   /* ES6 Iterators */                  \
   2263   F(CreateIterResultObject)            \
   2264   /* Arrays */                         \
   2265   F(HasFastPackedElements)             \
   2266   /* JSValue */                        \
   2267   F(JSValueGetValue)
   2268 
   2269 #define GENERATOR_DECLARATION(Name) void Generate##Name(CallRuntime* call);
   2270   FOR_EACH_HYDROGEN_INTRINSIC(GENERATOR_DECLARATION)
   2271 #undef GENERATOR_DECLARATION
   2272 
   2273   void VisitDelete(UnaryOperation* expr);
   2274   void VisitVoid(UnaryOperation* expr);
   2275   void VisitTypeof(UnaryOperation* expr);
   2276   void VisitNot(UnaryOperation* expr);
   2277 
   2278   void VisitComma(BinaryOperation* expr);
   2279   void VisitLogicalExpression(BinaryOperation* expr);
   2280   void VisitArithmeticExpression(BinaryOperation* expr);
   2281 
   2282   void VisitLoopBody(IterationStatement* stmt,
   2283                      HBasicBlock* loop_entry);
   2284 
   2285   void BuildForInBody(ForInStatement* stmt, Variable* each_var,
   2286                       HValue* enumerable);
   2287 
   2288   // Create a back edge in the flow graph.  body_exit is the predecessor
   2289   // block and loop_entry is the successor block.  loop_successor is the
   2290   // block where control flow exits the loop normally (e.g., via failure of
   2291   // the condition) and break_block is the block where control flow breaks
   2292   // from the loop.  All blocks except loop_entry can be NULL.  The return
   2293   // value is the new successor block which is the join of loop_successor
   2294   // and break_block, or NULL.
   2295   HBasicBlock* CreateLoop(IterationStatement* statement,
   2296                           HBasicBlock* loop_entry,
   2297                           HBasicBlock* body_exit,
   2298                           HBasicBlock* loop_successor,
   2299                           HBasicBlock* break_block);
   2300 
   2301   // Build a loop entry
   2302   HBasicBlock* BuildLoopEntry();
   2303 
   2304   // Builds a loop entry respectful of OSR requirements
   2305   HBasicBlock* BuildLoopEntry(IterationStatement* statement);
   2306 
   2307   HBasicBlock* JoinContinue(IterationStatement* statement,
   2308                             HBasicBlock* exit_block,
   2309                             HBasicBlock* continue_block);
   2310 
   2311   HValue* Top() const { return environment()->Top(); }
   2312   void Drop(int n) { environment()->Drop(n); }
   2313   void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
   2314   bool IsEligibleForEnvironmentLivenessAnalysis(Variable* var,
   2315                                                 int index,
   2316                                                 HValue* value,
   2317                                                 HEnvironment* env) {
   2318     if (!FLAG_analyze_environment_liveness) return false;
   2319     // |this| and |arguments| are always live; zapping parameters isn't
   2320     // safe because function.arguments can inspect them at any time.
   2321     return !var->is_this() &&
   2322            !var->is_arguments() &&
   2323            !value->IsArgumentsObject() &&
   2324            env->is_local_index(index);
   2325   }
   2326   void BindIfLive(Variable* var, HValue* value) {
   2327     HEnvironment* env = environment();
   2328     int index = env->IndexFor(var);
   2329     env->Bind(index, value);
   2330     if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) {
   2331       HEnvironmentMarker* bind =
   2332           Add<HEnvironmentMarker>(HEnvironmentMarker::BIND, index);
   2333       USE(bind);
   2334 #ifdef DEBUG
   2335       bind->set_closure(env->closure());
   2336 #endif
   2337     }
   2338   }
   2339   HValue* LookupAndMakeLive(Variable* var) {
   2340     HEnvironment* env = environment();
   2341     int index = env->IndexFor(var);
   2342     HValue* value = env->Lookup(index);
   2343     if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) {
   2344       HEnvironmentMarker* lookup =
   2345           Add<HEnvironmentMarker>(HEnvironmentMarker::LOOKUP, index);
   2346       USE(lookup);
   2347 #ifdef DEBUG
   2348       lookup->set_closure(env->closure());
   2349 #endif
   2350     }
   2351     return value;
   2352   }
   2353 
   2354   // The value of the arguments object is allowed in some but not most value
   2355   // contexts.  (It's allowed in all effect contexts and disallowed in all
   2356   // test contexts.)
   2357   void VisitForValue(Expression* expr,
   2358                      ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED);
   2359   void VisitForTypeOf(Expression* expr);
   2360   void VisitForEffect(Expression* expr);
   2361   void VisitForControl(Expression* expr,
   2362                        HBasicBlock* true_block,
   2363                        HBasicBlock* false_block);
   2364 
   2365   // Visit a list of expressions from left to right, each in a value context.
   2366   void VisitExpressions(ZoneList<Expression*>* exprs) override;
   2367   void VisitExpressions(ZoneList<Expression*>* exprs,
   2368                         ArgumentsAllowedFlag flag);
   2369 
   2370   // Remove the arguments from the bailout environment and emit instructions
   2371   // to push them as outgoing parameters.
   2372   template <class Instruction> HInstruction* PreProcessCall(Instruction* call);
   2373   void PushArgumentsFromEnvironment(int count);
   2374 
   2375   void SetUpScope(Scope* scope);
   2376   void VisitStatements(ZoneList<Statement*>* statements) override;
   2377 
   2378 #define DECLARE_VISIT(type) void Visit##type(type* node) override;
   2379   AST_NODE_LIST(DECLARE_VISIT)
   2380 #undef DECLARE_VISIT
   2381 
   2382  private:
   2383   // Helpers for flow graph construction.
   2384   enum GlobalPropertyAccess {
   2385     kUseCell,
   2386     kUseGeneric
   2387   };
   2388   GlobalPropertyAccess LookupGlobalProperty(Variable* var, LookupIterator* it,
   2389                                             PropertyAccessType access_type);
   2390 
   2391   void EnsureArgumentsArePushedForAccess();
   2392   bool TryArgumentsAccess(Property* expr);
   2393 
   2394   // Shared code for .call and .apply optimizations.
   2395   void HandleIndirectCall(Call* expr, HValue* function, int arguments_count);
   2396   // Try to optimize indirect calls such as fun.apply(receiver, arguments)
   2397   // or fun.call(...).
   2398   bool TryIndirectCall(Call* expr);
   2399   void BuildFunctionApply(Call* expr);
   2400   void BuildFunctionCall(Call* expr);
   2401 
   2402   bool TryHandleArrayCall(Call* expr, HValue* function);
   2403   bool TryHandleArrayCallNew(CallNew* expr, HValue* function);
   2404   void BuildArrayCall(Expression* expr, int arguments_count, HValue* function,
   2405                       Handle<AllocationSite> cell);
   2406 
   2407   enum ArrayIndexOfMode { kFirstIndexOf, kLastIndexOf };
   2408   HValue* BuildArrayIndexOf(HValue* receiver,
   2409                             HValue* search_element,
   2410                             ElementsKind kind,
   2411                             ArrayIndexOfMode mode);
   2412 
   2413   HValue* ImplicitReceiverFor(HValue* function,
   2414                               Handle<JSFunction> target);
   2415 
   2416   int InliningAstSize(Handle<JSFunction> target);
   2417   bool TryInline(Handle<JSFunction> target, int arguments_count,
   2418                  HValue* implicit_return_value, BailoutId ast_id,
   2419                  BailoutId return_id, InliningKind inlining_kind);
   2420 
   2421   bool TryInlineCall(Call* expr);
   2422   bool TryInlineConstruct(CallNew* expr, HValue* implicit_return_value);
   2423   bool TryInlineGetter(Handle<JSFunction> getter,
   2424                        Handle<Map> receiver_map,
   2425                        BailoutId ast_id,
   2426                        BailoutId return_id);
   2427   bool TryInlineSetter(Handle<JSFunction> setter,
   2428                        Handle<Map> receiver_map,
   2429                        BailoutId id,
   2430                        BailoutId assignment_id,
   2431                        HValue* implicit_return_value);
   2432   bool TryInlineIndirectCall(Handle<JSFunction> function, Call* expr,
   2433                              int arguments_count);
   2434   bool TryInlineBuiltinMethodCall(Call* expr, Handle<JSFunction> function,
   2435                                   Handle<Map> receiver_map,
   2436                                   int args_count_no_receiver);
   2437   bool TryInlineBuiltinFunctionCall(Call* expr);
   2438   enum ApiCallType {
   2439     kCallApiFunction,
   2440     kCallApiMethod,
   2441     kCallApiGetter,
   2442     kCallApiSetter
   2443   };
   2444   bool TryInlineApiMethodCall(Call* expr,
   2445                               HValue* receiver,
   2446                               SmallMapList* receiver_types);
   2447   bool TryInlineApiFunctionCall(Call* expr, HValue* receiver);
   2448   bool TryInlineApiGetter(Handle<JSFunction> function,
   2449                           Handle<Map> receiver_map,
   2450                           BailoutId ast_id);
   2451   bool TryInlineApiSetter(Handle<JSFunction> function,
   2452                           Handle<Map> receiver_map,
   2453                           BailoutId ast_id);
   2454   bool TryInlineApiCall(Handle<JSFunction> function,
   2455                          HValue* receiver,
   2456                          SmallMapList* receiver_maps,
   2457                          int argc,
   2458                          BailoutId ast_id,
   2459                          ApiCallType call_type);
   2460   static bool IsReadOnlyLengthDescriptor(Handle<Map> jsarray_map);
   2461   static bool CanInlineArrayResizeOperation(Handle<Map> receiver_map);
   2462 
   2463   // If --trace-inlining, print a line of the inlining trace.  Inlining
   2464   // succeeded if the reason string is NULL and failed if there is a
   2465   // non-NULL reason string.
   2466   void TraceInline(Handle<JSFunction> target,
   2467                    Handle<JSFunction> caller,
   2468                    const char* failure_reason);
   2469 
   2470   void HandleGlobalVariableAssignment(Variable* var, HValue* value,
   2471                                       FeedbackVectorSlot slot,
   2472                                       BailoutId ast_id);
   2473 
   2474   void HandlePropertyAssignment(Assignment* expr);
   2475   void HandleCompoundAssignment(Assignment* expr);
   2476   void HandlePolymorphicNamedFieldAccess(
   2477       PropertyAccessType access_type, Expression* expr, FeedbackVectorSlot slot,
   2478       BailoutId ast_id, BailoutId return_id, HValue* object, HValue* value,
   2479       SmallMapList* types, Handle<Name> name);
   2480 
   2481   HValue* BuildAllocateExternalElements(
   2482       ExternalArrayType array_type,
   2483       bool is_zero_byte_offset,
   2484       HValue* buffer, HValue* byte_offset, HValue* length);
   2485   HValue* BuildAllocateFixedTypedArray(ExternalArrayType array_type,
   2486                                        size_t element_size,
   2487                                        ElementsKind fixed_elements_kind,
   2488                                        HValue* byte_length, HValue* length,
   2489                                        bool initialize);
   2490 
   2491   // TODO(adamk): Move all OrderedHashTable functions to their own class.
   2492   HValue* BuildOrderedHashTableHashToBucket(HValue* hash, HValue* num_buckets);
   2493   template <typename CollectionType>
   2494   HValue* BuildOrderedHashTableHashToEntry(HValue* table, HValue* hash,
   2495                                            HValue* num_buckets);
   2496   template <typename CollectionType>
   2497   HValue* BuildOrderedHashTableEntryToIndex(HValue* entry, HValue* num_buckets);
   2498   template <typename CollectionType>
   2499   HValue* BuildOrderedHashTableFindEntry(HValue* table, HValue* key,
   2500                                          HValue* hash);
   2501   template <typename CollectionType>
   2502   HValue* BuildOrderedHashTableAddEntry(HValue* table, HValue* key,
   2503                                         HValue* hash,
   2504                                         HIfContinuation* join_continuation);
   2505   template <typename CollectionType>
   2506   HValue* BuildAllocateOrderedHashTable();
   2507   template <typename CollectionType>
   2508   void BuildOrderedHashTableClear(HValue* receiver);
   2509   template <typename CollectionType>
   2510   void BuildJSCollectionDelete(CallRuntime* call,
   2511                                const Runtime::Function* c_function);
   2512   template <typename CollectionType>
   2513   void BuildJSCollectionHas(CallRuntime* call,
   2514                             const Runtime::Function* c_function);
   2515   HValue* BuildStringHashLoadIfIsStringAndHashComputed(
   2516       HValue* object, HIfContinuation* continuation);
   2517 
   2518   Handle<JSFunction> array_function() {
   2519     return handle(isolate()->native_context()->array_function());
   2520   }
   2521 
   2522   bool IsCallArrayInlineable(int argument_count, Handle<AllocationSite> site);
   2523   void BuildInlinedCallArray(Expression* expression, int argument_count,
   2524                              Handle<AllocationSite> site);
   2525 
   2526   void BuildInitializeInobjectProperties(HValue* receiver,
   2527                                          Handle<Map> initial_map);
   2528 
   2529   class PropertyAccessInfo {
   2530    public:
   2531     PropertyAccessInfo(HOptimizedGraphBuilder* builder,
   2532                        PropertyAccessType access_type, Handle<Map> map,
   2533                        Handle<Name> name)
   2534         : builder_(builder),
   2535           access_type_(access_type),
   2536           map_(map),
   2537           name_(name),
   2538           field_type_(HType::Tagged()),
   2539           access_(HObjectAccess::ForMap()),
   2540           lookup_type_(NOT_FOUND),
   2541           details_(NONE, DATA, Representation::None()) {}
   2542 
   2543     // Checkes whether this PropertyAccessInfo can be handled as a monomorphic
   2544     // load named. It additionally fills in the fields necessary to generate the
   2545     // lookup code.
   2546     bool CanAccessMonomorphic();
   2547 
   2548     // Checks whether all types behave uniform when loading name. If all maps
   2549     // behave the same, a single monomorphic load instruction can be emitted,
   2550     // guarded by a single map-checks instruction that whether the receiver is
   2551     // an instance of any of the types.
   2552     // This method skips the first type in types, assuming that this
   2553     // PropertyAccessInfo is built for types->first().
   2554     bool CanAccessAsMonomorphic(SmallMapList* types);
   2555 
   2556     bool NeedsWrappingFor(Handle<JSFunction> target) const;
   2557 
   2558     Handle<Map> map();
   2559     Handle<Name> name() const { return name_; }
   2560 
   2561     bool IsJSObjectFieldAccessor() {
   2562       int offset;  // unused
   2563       return Accessors::IsJSObjectFieldAccessor(map_, name_, &offset);
   2564     }
   2565 
   2566     bool GetJSObjectFieldAccess(HObjectAccess* access) {
   2567       int offset;
   2568       if (Accessors::IsJSObjectFieldAccessor(map_, name_, &offset)) {
   2569         if (IsStringType()) {
   2570           DCHECK(Name::Equals(isolate()->factory()->length_string(), name_));
   2571           *access = HObjectAccess::ForStringLength();
   2572         } else if (IsArrayType()) {
   2573           DCHECK(Name::Equals(isolate()->factory()->length_string(), name_));
   2574           *access = HObjectAccess::ForArrayLength(map_->elements_kind());
   2575         } else {
   2576           *access = HObjectAccess::ForMapAndOffset(map_, offset);
   2577         }
   2578         return true;
   2579       }
   2580       return false;
   2581     }
   2582 
   2583     bool IsJSArrayBufferViewFieldAccessor() {
   2584       int offset;  // unused
   2585       return Accessors::IsJSArrayBufferViewFieldAccessor(map_, name_, &offset);
   2586     }
   2587 
   2588     bool GetJSArrayBufferViewFieldAccess(HObjectAccess* access) {
   2589       int offset;
   2590       if (Accessors::IsJSArrayBufferViewFieldAccessor(map_, name_, &offset)) {
   2591         *access = HObjectAccess::ForMapAndOffset(map_, offset);
   2592         return true;
   2593       }
   2594       return false;
   2595     }
   2596 
   2597     bool has_holder() { return !holder_.is_null(); }
   2598     bool IsLoad() const { return access_type_ == LOAD; }
   2599 
   2600     Isolate* isolate() const { return builder_->isolate(); }
   2601     Handle<JSObject> holder() { return holder_; }
   2602     Handle<JSFunction> accessor() { return accessor_; }
   2603     Handle<Object> constant() { return constant_; }
   2604     Handle<Map> transition() { return transition_; }
   2605     SmallMapList* field_maps() { return &field_maps_; }
   2606     HType field_type() const { return field_type_; }
   2607     HObjectAccess access() { return access_; }
   2608 
   2609     bool IsFound() const { return lookup_type_ != NOT_FOUND; }
   2610     bool IsProperty() const { return IsFound() && !IsTransition(); }
   2611     bool IsTransition() const { return lookup_type_ == TRANSITION_TYPE; }
   2612     bool IsData() const {
   2613       return lookup_type_ == DESCRIPTOR_TYPE && details_.type() == DATA;
   2614     }
   2615     bool IsDataConstant() const {
   2616       return lookup_type_ == DESCRIPTOR_TYPE &&
   2617              details_.type() == DATA_CONSTANT;
   2618     }
   2619     bool IsAccessorConstant() const {
   2620       return !IsTransition() && details_.type() == ACCESSOR_CONSTANT;
   2621     }
   2622     bool IsConfigurable() const { return details_.IsConfigurable(); }
   2623     bool IsReadOnly() const { return details_.IsReadOnly(); }
   2624 
   2625     bool IsStringType() { return map_->instance_type() < FIRST_NONSTRING_TYPE; }
   2626     bool IsNumberType() { return map_->instance_type() == HEAP_NUMBER_TYPE; }
   2627     bool IsValueWrapped() { return IsStringType() || IsNumberType(); }
   2628     bool IsArrayType() { return map_->instance_type() == JS_ARRAY_TYPE; }
   2629 
   2630    private:
   2631     Handle<Object> GetConstantFromMap(Handle<Map> map) const {
   2632       DCHECK_EQ(DESCRIPTOR_TYPE, lookup_type_);
   2633       DCHECK(number_ < map->NumberOfOwnDescriptors());
   2634       return handle(map->instance_descriptors()->GetValue(number_), isolate());
   2635     }
   2636     Handle<Object> GetAccessorsFromMap(Handle<Map> map) const {
   2637       return GetConstantFromMap(map);
   2638     }
   2639     Handle<HeapType> GetFieldTypeFromMap(Handle<Map> map) const {
   2640       DCHECK(IsFound());
   2641       DCHECK(number_ < map->NumberOfOwnDescriptors());
   2642       return handle(map->instance_descriptors()->GetFieldType(number_),
   2643                     isolate());
   2644     }
   2645     Handle<Map> GetFieldOwnerFromMap(Handle<Map> map) const {
   2646       DCHECK(IsFound());
   2647       DCHECK(number_ < map->NumberOfOwnDescriptors());
   2648       return handle(map->FindFieldOwner(number_));
   2649     }
   2650     int GetLocalFieldIndexFromMap(Handle<Map> map) const {
   2651       DCHECK(lookup_type_ == DESCRIPTOR_TYPE ||
   2652              lookup_type_ == TRANSITION_TYPE);
   2653       DCHECK(number_ < map->NumberOfOwnDescriptors());
   2654       int field_index = map->instance_descriptors()->GetFieldIndex(number_);
   2655       return field_index - map->GetInObjectProperties();
   2656     }
   2657 
   2658     void LookupDescriptor(Map* map, Name* name) {
   2659       DescriptorArray* descriptors = map->instance_descriptors();
   2660       int number = descriptors->SearchWithCache(name, map);
   2661       if (number == DescriptorArray::kNotFound) return NotFound();
   2662       lookup_type_ = DESCRIPTOR_TYPE;
   2663       details_ = descriptors->GetDetails(number);
   2664       number_ = number;
   2665     }
   2666     void LookupTransition(Map* map, Name* name, PropertyAttributes attributes) {
   2667       Map* target =
   2668           TransitionArray::SearchTransition(map, kData, name, attributes);
   2669       if (target == NULL) return NotFound();
   2670       lookup_type_ = TRANSITION_TYPE;
   2671       transition_ = handle(target);
   2672       number_ = transition_->LastAdded();
   2673       details_ = transition_->instance_descriptors()->GetDetails(number_);
   2674     }
   2675     void NotFound() {
   2676       lookup_type_ = NOT_FOUND;
   2677       details_ = PropertyDetails::Empty();
   2678     }
   2679     Representation representation() const {
   2680       DCHECK(IsFound());
   2681       return details_.representation();
   2682     }
   2683     bool IsTransitionToData() const {
   2684       return IsTransition() && details_.type() == DATA;
   2685     }
   2686 
   2687     Zone* zone() { return builder_->zone(); }
   2688     CompilationInfo* top_info() { return builder_->top_info(); }
   2689     CompilationInfo* current_info() { return builder_->current_info(); }
   2690 
   2691     bool LoadResult(Handle<Map> map);
   2692     bool LoadFieldMaps(Handle<Map> map);
   2693     bool LookupDescriptor();
   2694     bool LookupInPrototypes();
   2695     bool IsIntegerIndexedExotic();
   2696     bool IsCompatible(PropertyAccessInfo* other);
   2697 
   2698     void GeneralizeRepresentation(Representation r) {
   2699       access_ = access_.WithRepresentation(
   2700           access_.representation().generalize(r));
   2701     }
   2702 
   2703     HOptimizedGraphBuilder* builder_;
   2704     PropertyAccessType access_type_;
   2705     Handle<Map> map_;
   2706     Handle<Name> name_;
   2707     Handle<JSObject> holder_;
   2708     Handle<JSFunction> accessor_;
   2709     Handle<JSObject> api_holder_;
   2710     Handle<Object> constant_;
   2711     SmallMapList field_maps_;
   2712     HType field_type_;
   2713     HObjectAccess access_;
   2714 
   2715     enum { NOT_FOUND, DESCRIPTOR_TYPE, TRANSITION_TYPE } lookup_type_;
   2716     Handle<Map> transition_;
   2717     int number_;
   2718     PropertyDetails details_;
   2719   };
   2720 
   2721   HValue* BuildMonomorphicAccess(PropertyAccessInfo* info, HValue* object,
   2722                                  HValue* checked_object, HValue* value,
   2723                                  BailoutId ast_id, BailoutId return_id,
   2724                                  bool can_inline_accessor = true);
   2725 
   2726   HValue* BuildNamedAccess(PropertyAccessType access, BailoutId ast_id,
   2727                            BailoutId reutrn_id, Expression* expr,
   2728                            FeedbackVectorSlot slot, HValue* object,
   2729                            Handle<Name> name, HValue* value,
   2730                            bool is_uninitialized = false);
   2731 
   2732   void HandlePolymorphicCallNamed(Call* expr,
   2733                                   HValue* receiver,
   2734                                   SmallMapList* types,
   2735                                   Handle<String> name);
   2736   void HandleLiteralCompareTypeof(CompareOperation* expr,
   2737                                   Expression* sub_expr,
   2738                                   Handle<String> check);
   2739   void HandleLiteralCompareNil(CompareOperation* expr,
   2740                                Expression* sub_expr,
   2741                                NilValue nil);
   2742 
   2743   enum PushBeforeSimulateBehavior {
   2744     PUSH_BEFORE_SIMULATE,
   2745     NO_PUSH_BEFORE_SIMULATE
   2746   };
   2747 
   2748   HControlInstruction* BuildCompareInstruction(
   2749       Token::Value op, HValue* left, HValue* right, Type* left_type,
   2750       Type* right_type, Type* combined_type, SourcePosition left_position,
   2751       SourcePosition right_position, PushBeforeSimulateBehavior push_sim_result,
   2752       BailoutId bailout_id);
   2753 
   2754   HInstruction* BuildStringCharCodeAt(HValue* string,
   2755                                       HValue* index);
   2756 
   2757   HValue* BuildBinaryOperation(
   2758       BinaryOperation* expr,
   2759       HValue* left,
   2760       HValue* right,
   2761       PushBeforeSimulateBehavior push_sim_result);
   2762   HInstruction* BuildIncrement(bool returns_original_input,
   2763                                CountOperation* expr);
   2764   HInstruction* BuildKeyedGeneric(PropertyAccessType access_type,
   2765                                   Expression* expr, FeedbackVectorSlot slot,
   2766                                   HValue* object, HValue* key, HValue* value);
   2767 
   2768   HInstruction* TryBuildConsolidatedElementLoad(HValue* object,
   2769                                                 HValue* key,
   2770                                                 HValue* val,
   2771                                                 SmallMapList* maps);
   2772 
   2773   LoadKeyedHoleMode BuildKeyedHoleMode(Handle<Map> map);
   2774 
   2775   HInstruction* BuildMonomorphicElementAccess(HValue* object,
   2776                                               HValue* key,
   2777                                               HValue* val,
   2778                                               HValue* dependency,
   2779                                               Handle<Map> map,
   2780                                               PropertyAccessType access_type,
   2781                                               KeyedAccessStoreMode store_mode);
   2782 
   2783   HValue* HandlePolymorphicElementAccess(
   2784       Expression* expr, FeedbackVectorSlot slot, HValue* object, HValue* key,
   2785       HValue* val, SmallMapList* maps, PropertyAccessType access_type,
   2786       KeyedAccessStoreMode store_mode, bool* has_side_effects);
   2787 
   2788   HValue* HandleKeyedElementAccess(HValue* obj, HValue* key, HValue* val,
   2789                                    Expression* expr, FeedbackVectorSlot slot,
   2790                                    BailoutId ast_id, BailoutId return_id,
   2791                                    PropertyAccessType access_type,
   2792                                    bool* has_side_effects);
   2793 
   2794   HInstruction* BuildNamedGeneric(PropertyAccessType access, Expression* expr,
   2795                                   FeedbackVectorSlot slot, HValue* object,
   2796                                   Handle<Name> name, HValue* value,
   2797                                   bool is_uninitialized = false);
   2798 
   2799   HCheckMaps* AddCheckMap(HValue* object, Handle<Map> map);
   2800 
   2801   void BuildLoad(Property* property,
   2802                  BailoutId ast_id);
   2803   void PushLoad(Property* property,
   2804                 HValue* object,
   2805                 HValue* key);
   2806 
   2807   void BuildStoreForEffect(Expression* expression, Property* prop,
   2808                            FeedbackVectorSlot slot, BailoutId ast_id,
   2809                            BailoutId return_id, HValue* object, HValue* key,
   2810                            HValue* value);
   2811 
   2812   void BuildStore(Expression* expression, Property* prop,
   2813                   FeedbackVectorSlot slot, BailoutId ast_id,
   2814                   BailoutId return_id, bool is_uninitialized = false);
   2815 
   2816   HInstruction* BuildLoadNamedField(PropertyAccessInfo* info,
   2817                                     HValue* checked_object);
   2818   HInstruction* BuildStoreNamedField(PropertyAccessInfo* info,
   2819                                      HValue* checked_object,
   2820                                      HValue* value);
   2821 
   2822   HValue* BuildContextChainWalk(Variable* var);
   2823 
   2824   HValue* AddThisFunction();
   2825   HInstruction* BuildThisFunction();
   2826 
   2827   HInstruction* BuildFastLiteral(Handle<JSObject> boilerplate_object,
   2828                                  AllocationSiteUsageContext* site_context);
   2829 
   2830   void BuildEmitObjectHeader(Handle<JSObject> boilerplate_object,
   2831                              HInstruction* object);
   2832 
   2833   void BuildEmitInObjectProperties(Handle<JSObject> boilerplate_object,
   2834                                    HInstruction* object,
   2835                                    AllocationSiteUsageContext* site_context,
   2836                                    PretenureFlag pretenure_flag);
   2837 
   2838   void BuildEmitElements(Handle<JSObject> boilerplate_object,
   2839                          Handle<FixedArrayBase> elements,
   2840                          HValue* object_elements,
   2841                          AllocationSiteUsageContext* site_context);
   2842 
   2843   void BuildEmitFixedDoubleArray(Handle<FixedArrayBase> elements,
   2844                                  ElementsKind kind,
   2845                                  HValue* object_elements);
   2846 
   2847   void BuildEmitFixedArray(Handle<FixedArrayBase> elements,
   2848                            ElementsKind kind,
   2849                            HValue* object_elements,
   2850                            AllocationSiteUsageContext* site_context);
   2851 
   2852   void AddCheckPrototypeMaps(Handle<JSObject> holder,
   2853                              Handle<Map> receiver_map);
   2854 
   2855   HInstruction* NewPlainFunctionCall(HValue* fun, int argument_count);
   2856 
   2857   HInstruction* NewArgumentAdaptorCall(HValue* fun, HValue* context,
   2858                                        int argument_count,
   2859                                        HValue* expected_param_count);
   2860 
   2861   HInstruction* BuildCallConstantFunction(Handle<JSFunction> target,
   2862                                           int argument_count);
   2863 
   2864   bool CanBeFunctionApplyArguments(Call* expr);
   2865 
   2866   // The translation state of the currently-being-translated function.
   2867   FunctionState* function_state_;
   2868 
   2869   // The base of the function state stack.
   2870   FunctionState initial_function_state_;
   2871 
   2872   // Expression context of the currently visited subexpression. NULL when
   2873   // visiting statements.
   2874   AstContext* ast_context_;
   2875 
   2876   // A stack of breakable statements entered.
   2877   BreakAndContinueScope* break_scope_;
   2878 
   2879   int inlined_count_;
   2880   ZoneList<Handle<Object> > globals_;
   2881 
   2882   bool inline_bailout_;
   2883 
   2884   HOsrBuilder* osr_;
   2885 
   2886   friend class FunctionState;  // Pushes and pops the state stack.
   2887   friend class AstContext;  // Pushes and pops the AST context stack.
   2888   friend class KeyedLoadFastElementStub;
   2889   friend class HOsrBuilder;
   2890 
   2891   DISALLOW_COPY_AND_ASSIGN(HOptimizedGraphBuilder);
   2892 };
   2893 
   2894 
   2895 Zone* AstContext::zone() const { return owner_->zone(); }
   2896 
   2897 
   2898 class HStatistics final : public Malloced {
   2899  public:
   2900   HStatistics()
   2901       : times_(5),
   2902         names_(5),
   2903         sizes_(5),
   2904         total_size_(0),
   2905         source_size_(0) { }
   2906 
   2907   void Initialize(CompilationInfo* info);
   2908   void Print();
   2909   void SaveTiming(const char* name, base::TimeDelta time, size_t size);
   2910 
   2911   void IncrementFullCodeGen(base::TimeDelta full_code_gen) {
   2912     full_code_gen_ += full_code_gen;
   2913   }
   2914 
   2915   void IncrementCreateGraph(base::TimeDelta delta) { create_graph_ += delta; }
   2916 
   2917   void IncrementOptimizeGraph(base::TimeDelta delta) {
   2918     optimize_graph_ += delta;
   2919   }
   2920 
   2921   void IncrementGenerateCode(base::TimeDelta delta) { generate_code_ += delta; }
   2922 
   2923   void IncrementSubtotals(base::TimeDelta create_graph,
   2924                           base::TimeDelta optimize_graph,
   2925                           base::TimeDelta generate_code) {
   2926     IncrementCreateGraph(create_graph);
   2927     IncrementOptimizeGraph(optimize_graph);
   2928     IncrementGenerateCode(generate_code);
   2929   }
   2930 
   2931  private:
   2932   List<base::TimeDelta> times_;
   2933   List<const char*> names_;
   2934   List<size_t> sizes_;
   2935   base::TimeDelta create_graph_;
   2936   base::TimeDelta optimize_graph_;
   2937   base::TimeDelta generate_code_;
   2938   size_t total_size_;
   2939   base::TimeDelta full_code_gen_;
   2940   double source_size_;
   2941 };
   2942 
   2943 
   2944 class HPhase : public CompilationPhase {
   2945  public:
   2946   HPhase(const char* name, HGraph* graph)
   2947       : CompilationPhase(name, graph->info()),
   2948         graph_(graph) { }
   2949   ~HPhase();
   2950 
   2951  protected:
   2952   HGraph* graph() const { return graph_; }
   2953 
   2954  private:
   2955   HGraph* graph_;
   2956 
   2957   DISALLOW_COPY_AND_ASSIGN(HPhase);
   2958 };
   2959 
   2960 
   2961 class HTracer final : public Malloced {
   2962  public:
   2963   explicit HTracer(int isolate_id)
   2964       : trace_(&string_allocator_), indent_(0) {
   2965     if (FLAG_trace_hydrogen_file == NULL) {
   2966       SNPrintF(filename_,
   2967                "hydrogen-%d-%d.cfg",
   2968                base::OS::GetCurrentProcessId(),
   2969                isolate_id);
   2970     } else {
   2971       StrNCpy(filename_, FLAG_trace_hydrogen_file, filename_.length());
   2972     }
   2973     WriteChars(filename_.start(), "", 0, false);
   2974   }
   2975 
   2976   void TraceCompilation(CompilationInfo* info);
   2977   void TraceHydrogen(const char* name, HGraph* graph);
   2978   void TraceLithium(const char* name, LChunk* chunk);
   2979   void TraceLiveRanges(const char* name, LAllocator* allocator);
   2980 
   2981  private:
   2982   class Tag final BASE_EMBEDDED {
   2983    public:
   2984     Tag(HTracer* tracer, const char* name) {
   2985       name_ = name;
   2986       tracer_ = tracer;
   2987       tracer->PrintIndent();
   2988       tracer->trace_.Add("begin_%s\n", name);
   2989       tracer->indent_++;
   2990     }
   2991 
   2992     ~Tag() {
   2993       tracer_->indent_--;
   2994       tracer_->PrintIndent();
   2995       tracer_->trace_.Add("end_%s\n", name_);
   2996       DCHECK(tracer_->indent_ >= 0);
   2997       tracer_->FlushToFile();
   2998     }
   2999 
   3000    private:
   3001     HTracer* tracer_;
   3002     const char* name_;
   3003   };
   3004 
   3005   void TraceLiveRange(LiveRange* range, const char* type, Zone* zone);
   3006   void Trace(const char* name, HGraph* graph, LChunk* chunk);
   3007   void FlushToFile();
   3008 
   3009   void PrintEmptyProperty(const char* name) {
   3010     PrintIndent();
   3011     trace_.Add("%s\n", name);
   3012   }
   3013 
   3014   void PrintStringProperty(const char* name, const char* value) {
   3015     PrintIndent();
   3016     trace_.Add("%s \"%s\"\n", name, value);
   3017   }
   3018 
   3019   void PrintLongProperty(const char* name, int64_t value) {
   3020     PrintIndent();
   3021     trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000));
   3022   }
   3023 
   3024   void PrintBlockProperty(const char* name, int block_id) {
   3025     PrintIndent();
   3026     trace_.Add("%s \"B%d\"\n", name, block_id);
   3027   }
   3028 
   3029   void PrintIntProperty(const char* name, int value) {
   3030     PrintIndent();
   3031     trace_.Add("%s %d\n", name, value);
   3032   }
   3033 
   3034   void PrintIndent() {
   3035     for (int i = 0; i < indent_; i++) {
   3036       trace_.Add("  ");
   3037     }
   3038   }
   3039 
   3040   EmbeddedVector<char, 64> filename_;
   3041   HeapStringAllocator string_allocator_;
   3042   StringStream trace_;
   3043   int indent_;
   3044 };
   3045 
   3046 
   3047 class NoObservableSideEffectsScope final {
   3048  public:
   3049   explicit NoObservableSideEffectsScope(HGraphBuilder* builder) :
   3050       builder_(builder) {
   3051     builder_->graph()->IncrementInNoSideEffectsScope();
   3052   }
   3053   ~NoObservableSideEffectsScope() {
   3054     builder_->graph()->DecrementInNoSideEffectsScope();
   3055   }
   3056 
   3057  private:
   3058   HGraphBuilder* builder_;
   3059 };
   3060 
   3061 
   3062 }  // namespace internal
   3063 }  // namespace v8
   3064 
   3065 #endif  // V8_CRANKSHAFT_HYDROGEN_H_
   3066