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