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