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