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