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