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