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