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