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