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