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