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