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
41namespace v8 {
42namespace internal {
43
44// Forward declarations.
45class BitVector;
46class FunctionState;
47class HEnvironment;
48class HGraph;
49class HLoopInformation;
50class HOsrBuilder;
51class HTracer;
52class LAllocator;
53class LChunk;
54class LiveRange;
55
56
57class HBasicBlock V8_FINAL : public ZoneObject {
58 public:
59  explicit HBasicBlock(HGraph* graph);
60  ~HBasicBlock() { }
61
62  // Simple accessors.
63  int block_id() const { return block_id_; }
64  void set_block_id(int id) { block_id_ = id; }
65  HGraph* graph() const { return graph_; }
66  Isolate* isolate() const;
67  const ZoneList<HPhi*>* phis() const { return &phis_; }
68  HInstruction* first() const { return first_; }
69  HInstruction* last() const { return last_; }
70  void set_last(HInstruction* instr) { last_ = instr; }
71  HControlInstruction* end() const { return end_; }
72  HLoopInformation* loop_information() const { return loop_information_; }
73  HLoopInformation* current_loop() const {
74    return IsLoopHeader() ? loop_information()
75                          : (parent_loop_header() != NULL
76                            ? parent_loop_header()->loop_information() : NULL);
77  }
78  const ZoneList<HBasicBlock*>* predecessors() const { return &predecessors_; }
79  bool HasPredecessor() const { return predecessors_.length() > 0; }
80  const ZoneList<HBasicBlock*>* dominated_blocks() const {
81    return &dominated_blocks_;
82  }
83  const ZoneList<int>* deleted_phis() const {
84    return &deleted_phis_;
85  }
86  void RecordDeletedPhi(int merge_index) {
87    deleted_phis_.Add(merge_index, zone());
88  }
89  HBasicBlock* dominator() const { return dominator_; }
90  HEnvironment* last_environment() const { return last_environment_; }
91  int argument_count() const { return argument_count_; }
92  void set_argument_count(int count) { argument_count_ = count; }
93  int first_instruction_index() const { return first_instruction_index_; }
94  void set_first_instruction_index(int index) {
95    first_instruction_index_ = index;
96  }
97  int last_instruction_index() const { return last_instruction_index_; }
98  void set_last_instruction_index(int index) {
99    last_instruction_index_ = index;
100  }
101  bool is_osr_entry() { return is_osr_entry_; }
102  void set_osr_entry() { is_osr_entry_ = true; }
103
104  void AttachLoopInformation();
105  void DetachLoopInformation();
106  bool IsLoopHeader() const { return loop_information() != NULL; }
107  bool IsStartBlock() const { return block_id() == 0; }
108  void PostProcessLoopHeader(IterationStatement* stmt);
109
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);
118  void ClearEnvironment() {
119    ASSERT(IsFinished());
120    ASSERT(end()->SuccessorCount() == 0);
121    last_environment_ = NULL;
122  }
123  bool HasEnvironment() const { return last_environment_ != NULL; }
124  void UpdateEnvironment(HEnvironment* env);
125  HBasicBlock* parent_loop_header() const { return parent_loop_header_; }
126
127  void set_parent_loop_header(HBasicBlock* block) {
128    ASSERT(parent_loop_header_ == NULL);
129    parent_loop_header_ = block;
130  }
131
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)
154  bool IsInlineReturnTarget() const { return is_inline_return_target_; }
155  void MarkAsInlineReturnTarget(HBasicBlock* inlined_entry_block) {
156    is_inline_return_target_ = true;
157    inlined_entry_block_ = inlined_entry_block;
158  }
159  HBasicBlock* inlined_entry_block() { return inlined_entry_block_; }
160
161  bool IsDeoptimizing() const {
162    return end() != NULL && end()->IsDeoptimize();
163  }
164
165  void MarkUnreachable();
166  bool IsUnreachable() const { return !is_reachable_; }
167  bool IsReachable() const { return is_reachable_; }
168
169  bool IsLoopSuccessorDominator() const {
170    return dominates_loop_successors_;
171  }
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);
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
233class HPredecessorIterator V8_FINAL BASE_EMBEDDED {
234 public:
235  explicit HPredecessorIterator(HBasicBlock* block)
236      : predecessor_list_(block->predecessors()), current_(0) { }
237
238  bool Done() { return current_ >= predecessor_list_->length(); }
239  HBasicBlock* Current() { return predecessor_list_->at(current_); }
240  void Advance() { current_++; }
241
242 private:
243  const ZoneList<HBasicBlock*>* predecessor_list_;
244  int current_;
245};
246
247
248class HInstructionIterator V8_FINAL BASE_EMBEDDED {
249 public:
250  explicit HInstructionIterator(HBasicBlock* block)
251      : instr_(block->first()) {
252    next_ = Done() ? NULL : instr_->next();
253  }
254
255  inline bool Done() const { return instr_ == NULL; }
256  inline HInstruction* Current() { return instr_; }
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
268class HLoopInformation V8_FINAL : public ZoneObject {
269 public:
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  }
277  ~HLoopInformation() {}
278
279  const ZoneList<HBasicBlock*>* back_edges() const { return &back_edges_; }
280  const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
281  HBasicBlock* loop_header() const { return loop_header_; }
282  HBasicBlock* GetLastBackEdge() const;
283  void RegisterBackEdge(HBasicBlock* block);
284
285  HStackCheck* stack_check() const { return stack_check_; }
286  void set_stack_check(HStackCheck* stack_check) {
287    stack_check_ = stack_check;
288  }
289
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  }
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
314class BoundsCheckTable;
315class InductionVariableBlocksTable;
316class HGraph V8_FINAL : public ZoneObject {
317 public:
318  explicit HGraph(CompilationInfo* info);
319
320  Isolate* isolate() const { return isolate_; }
321  Zone* zone() const { return zone_; }
322  CompilationInfo* info() const { return info_; }
323
324  const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
325  const ZoneList<HPhi*>* phi_list() const { return phi_list_; }
326  HBasicBlock* entry_block() const { return entry_block_; }
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();
366  HArgumentsObject* GetArgumentsObject() const {
367    return arguments_object_.get();
368  }
369
370  void SetArgumentsObject(HArgumentsObject* object) {
371    arguments_object_.set(object);
372  }
373
374  int GetMaximumValueID() const { return values_.length(); }
375  int GetNextBlockID() { return next_block_id_++; }
376  int GetNextValueID(HValue* value) {
377    ASSERT(!disallow_adding_new_values_);
378    values_.Add(value, zone());
379    return values_.length() - 1;
380  }
381  HValue* LookupValue(int id) const {
382    if (id >= 0 && id < values_.length()) return values_[id];
383    return NULL;
384  }
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
395  bool has_osr() {
396    return osr_ != NULL;
397  }
398
399  void set_osr(HOsrBuilder* osr) {
400    osr_ = osr;
401  }
402
403  HOsrBuilder* osr() {
404    return osr_;
405  }
406
407  int update_type_change_checksum(int delta) {
408    type_change_checksum_ += delta;
409    return type_change_checksum_;
410  }
411
412  void update_maximum_environment_size(int environment_size) {
413    if (environment_size > maximum_environment_size_) {
414      maximum_environment_size_ = environment_size;
415    }
416  }
417  int maximum_environment_size() { return maximum_environment_size_; }
418
419  bool use_optimistic_licm() {
420    return use_optimistic_licm_;
421  }
422
423  void set_use_optimistic_licm(bool value) {
424    use_optimistic_licm_ = value;
425  }
426
427  void MarkRecursive() {
428    is_recursive_ = true;
429  }
430
431  bool is_recursive() const {
432    return is_recursive_;
433  }
434
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
445  bool depends_on_empty_array_proto_elements() {
446    return depends_on_empty_array_proto_elements_;
447  }
448
449  bool has_uint32_instructions() {
450    ASSERT(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
451    return uint32_instructions_ != NULL;
452  }
453
454  ZoneList<HInstruction*>* uint32_instructions() {
455    ASSERT(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
456    return uint32_instructions_;
457  }
458
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
467  void IncrementInNoSideEffectsScope() { no_side_effects_scope_count_++; }
468  void DecrementInNoSideEffectsScope() { no_side_effects_scope_count_--; }
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>
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
520Zone* HBasicBlock::zone() const { return graph_->zone(); }
521
522
523// Type of stack frame an environment might refer to.
524enum FrameType {
525  JS_FUNCTION,
526  JS_CONSTRUCT,
527  JS_GETTER,
528  JS_SETTER,
529  ARGUMENTS_ADAPTOR,
530  STUB
531};
532
533
534class 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
543  HEnvironment* arguments_environment() {
544    return outer()->frame_type() == ARGUMENTS_ADAPTOR ? outer() : this;
545  }
546
547  // Simple accessors.
548  Handle<JSFunction> closure() const { return closure_; }
549  const ZoneList<HValue*>* values() const { return &values_; }
550  const GrowableBitVector* assigned_variables() const {
551    return &assigned_variables_;
552  }
553  FrameType frame_type() const { return frame_type_; }
554  int parameter_count() const { return parameter_count_; }
555  int specials_count() const { return specials_count_; }
556  int local_count() const { return local_count_; }
557  HEnvironment* outer() const { return outer_; }
558  int pop_count() const { return pop_count_; }
559  int push_count() const { return push_count_; }
560
561  BailoutId ast_id() const { return ast_id_; }
562  void set_ast_id(BailoutId id) { ast_id_ = id; }
563
564  HEnterInlined* entry() const { return entry_; }
565  void set_entry(HEnterInlined* entry) { entry_ = entry; }
566
567  int length() const { return values_.length(); }
568
569  int first_expression_index() const {
570    return parameter_count() + specials_count() + local_count();
571  }
572
573  int first_local_index() const {
574    return parameter_count() + specials_count();
575  }
576
577  void Bind(Variable* variable, HValue* value) {
578    Bind(IndexFor(variable), value);
579  }
580
581  void Bind(int index, HValue* value);
582
583  void BindContext(HValue* value) {
584    Bind(parameter_count(), value);
585  }
586
587  HValue* Lookup(Variable* variable) const {
588    return Lookup(IndexFor(variable));
589  }
590
591  HValue* Lookup(int index) const {
592    HValue* result = values_[index];
593    ASSERT(result != NULL);
594    return result;
595  }
596
597  HValue* context() const {
598    // Return first special.
599    return Lookup(parameter_count());
600  }
601
602  void Push(HValue* value) {
603    ASSERT(value != NULL);
604    ++push_count_;
605    values_.Add(value, zone());
606  }
607
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
620  HValue* Top() const { return ExpressionStackAt(0); }
621
622  bool ExpressionStackIsEmpty() const;
623
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
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
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
663  void ClearHistory() {
664    pop_count_ = 0;
665    push_count_ = 0;
666    assigned_variables_.Clear();
667  }
668
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.
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
685  bool is_local_index(int i) const {
686    return i >= first_local_index() && i < first_expression_index();
687  }
688
689  bool is_parameter_index(int i) const {
690    return i >= 0 && i < parameter_count();
691  }
692
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
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
741class HOptimizedGraphBuilder;
742
743enum ArgumentsAllowedFlag {
744  ARGUMENTS_NOT_ALLOWED,
745  ARGUMENTS_ALLOWED
746};
747
748
749class HIfContinuation;
750
751// This class is not BASE_EMBEDDED because our inlining implementation uses
752// new and delete.
753class AstContext {
754 public:
755  bool IsEffect() const { return kind_ == Expression::kEffect; }
756  bool IsValue() const { return kind_ == Expression::kValue; }
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
783  void set_for_typeof(bool for_typeof) { for_typeof_ = for_typeof; }
784  bool is_for_typeof() { return for_typeof_; }
785
786 protected:
787  AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind);
788  virtual ~AstContext();
789
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
808class EffectContext V8_FINAL : public AstContext {
809 public:
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
825class ValueContext V8_FINAL : public AstContext {
826 public:
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
840  bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; }
841
842 private:
843  ArgumentsAllowedFlag flag_;
844};
845
846
847class TestContext V8_FINAL : public AstContext {
848 public:
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
867  static TestContext* cast(AstContext* context) {
868    ASSERT(context->IsTest());
869    return reinterpret_cast<TestContext*>(context);
870  }
871
872  Expression* condition() const { return condition_; }
873  HBasicBlock* if_true() const { return if_true_; }
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
887class FunctionState V8_FINAL {
888 public:
889  FunctionState(HOptimizedGraphBuilder* owner,
890                CompilationInfo* info,
891                InliningKind inlining_kind);
892  ~FunctionState();
893
894  CompilationInfo* compilation_info() { return compilation_info_; }
895  AstContext* call_context() { return call_context_; }
896  InliningKind inlining_kind() const { return inlining_kind_; }
897  HBasicBlock* function_return() { return function_return_; }
898  TestContext* test_context() { return test_context_; }
899  void ClearInlinedTestContext() {
900    delete test_context_;
901    test_context_ = NULL;
902  }
903
904  FunctionState* outer() { return outer_; }
905
906  HEnterInlined* entry() { return entry_; }
907  void set_entry(HEnterInlined* entry) { entry_ = entry; }
908
909  HArgumentsObject* arguments_object() { return arguments_object_; }
910  void set_arguments_object(HArgumentsObject* arguments_object) {
911    arguments_object_ = arguments_object;
912  }
913
914  HArgumentsElements* arguments_elements() { return arguments_elements_; }
915  void set_arguments_elements(HArgumentsElements* arguments_elements) {
916    arguments_elements_ = arguments_elements;
917  }
918
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
954class HIfContinuation V8_FINAL {
955 public:
956  HIfContinuation()
957    : continuation_captured_(false),
958      true_branch_(NULL),
959      false_branch_(NULL) {}
960  HIfContinuation(HBasicBlock* true_branch,
961                  HBasicBlock* false_branch)
962      : continuation_captured_(true), true_branch_(true_branch),
963        false_branch_(false_branch) {}
964  ~HIfContinuation() { ASSERT(!continuation_captured_); }
965
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
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
982  bool IsTrueReachable() { return true_branch_ != NULL; }
983  bool IsFalseReachable() { return false_branch_ != NULL; }
984  bool TrueAndFalseReachable() {
985    return IsTrueReachable() || IsFalseReachable();
986  }
987
988  HBasicBlock* true_branch() const { return true_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
998class HGraphBuilder {
999 public:
1000  explicit HGraphBuilder(CompilationInfo* info)
1001      : info_(info),
1002        graph_(NULL),
1003        current_block_(NULL),
1004        position_(RelocInfo::kNoPosition) {}
1005  virtual ~HGraphBuilder() {}
1006
1007  HBasicBlock* current_block() const { return current_block_; }
1008  void set_current_block(HBasicBlock* block) { current_block_ = block; }
1009  HEnvironment* environment() const {
1010    return current_block()->last_environment();
1011  }
1012  Zone* zone() const { return info_->zone(); }
1013  HGraph* graph() const { return graph_; }
1014  Isolate* isolate() const { return graph_->isolate(); }
1015  CompilationInfo* top_info() { return info_; }
1016
1017  HGraph* CreateGraph();
1018
1019  // Bailout environment manipulation.
1020  void Push(HValue* value) { environment()->Push(value); }
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  }
1041  void GotoNoSimulate(HBasicBlock* from, HBasicBlock* target) {
1042    Goto(from, target, NULL, false);
1043  }
1044  void GotoNoSimulate(HBasicBlock* target) {
1045    Goto(target, NULL, false);
1046  }
1047  void AddLeaveInlined(HBasicBlock* block,
1048                       HValue* return_value,
1049                       FunctionState* state) {
1050    block->AddLeaveInlined(return_value, state, position_);
1051  }
1052  void AddLeaveInlined(HValue* return_value, FunctionState* state) {
1053    return AddLeaveInlined(current_block(), return_value, state);
1054  }
1055
1056  template<class I>
1057  HInstruction* NewUncasted() { return I::New(zone(), context()); }
1058
1059  template<class I>
1060  I* New() { return I::New(zone(), context()); }
1061
1062  template<class I>
1063  HInstruction* AddUncasted() { return AddInstruction(NewUncasted<I>());}
1064
1065  template<class I>
1066  I* Add() { return AddInstructionTyped(New<I>());}
1067
1068  template<class I, class P1>
1069  HInstruction* NewUncasted(P1 p1) {
1070    return I::New(zone(), context(), p1);
1071  }
1072
1073  template<class I, class P1>
1074  I* New(P1 p1) { return I::New(zone(), context(), p1); }
1075
1076  template<class I, class 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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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
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);
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
1375    ~IfBuilder() {
1376      if (!finished_) End();
1377    }
1378
1379    template<class Condition>
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>
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>
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>
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>
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>
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>
1422    Condition* OrIf(HValue *p) {
1423      Or();
1424      return If<Condition>(p);
1425    }
1426
1427    template<class Condition, class 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>
1434    Condition* OrIf(HValue* p1, P2 p2, P3 p3) {
1435      Or();
1436      return If<Condition>(p1, p2, p3);
1437    }
1438
1439    template<class Condition>
1440    Condition* AndIf(HValue *p) {
1441      And();
1442      return If<Condition>(p);
1443    }
1444
1445    template<class Condition, class 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>
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);
1509    void ThenDeopt(const char* reason) {
1510      Then();
1511      Deopt(reason);
1512    }
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
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:
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
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:
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
1630    ElementsKind kind() { return kind_; }
1631
1632    HValue* AllocateEmptyArray();
1633    HValue* AllocateArray(HValue* capacity, HValue* length_field,
1634                          FillMode fill_mode = FILL_WITH_HOLE);
1635    HValue* GetElementsLocation() { return elements_location_; }
1636    HValue* EmitMapCode();
1637
1638   private:
1639    Zone* zone() const { return builder_->zone(); }
1640    int elements_size() const {
1641      return IsFastDoubleElementsKind(kind_) ? kDoubleSize : kPointerSize;
1642    }
1643    HGraphBuilder* builder() { return builder_; }
1644    HGraph* graph() { return builder_->graph(); }
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:
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>
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
1770template<>
1771inline 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
1790template<>
1791inline HInstruction* HGraphBuilder::AddUncasted<HDeoptimize>(
1792    const char* reason, Deoptimizer::BailoutType type) {
1793  return Add<HDeoptimize>(reason, type);
1794}
1795
1796
1797template<>
1798inline 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
1807template<>
1808inline HSimulate* HGraphBuilder::Add<HSimulate>(
1809    BailoutId id) {
1810  return Add<HSimulate>(id, FIXED_SIMULATE);
1811}
1812
1813
1814template<>
1815inline HInstruction* HGraphBuilder::AddUncasted<HSimulate>(BailoutId id) {
1816  return Add<HSimulate>(id, FIXED_SIMULATE);
1817}
1818
1819
1820template<>
1821inline 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
1830template<>
1831inline HReturn* HGraphBuilder::Add<HReturn>(HConstant* value) {
1832  return Add<HReturn>(static_cast<HValue*>(value));
1833}
1834
1835template<>
1836inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HValue* value) {
1837  return Add<HReturn>(value);
1838}
1839
1840
1841template<>
1842inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HConstant* value) {
1843  return Add<HReturn>(value);
1844}
1845
1846
1847template<>
1848inline 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
1864template<>
1865inline 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
1873template<>
1874inline HContext* HGraphBuilder::New<HContext>() {
1875  return HContext::New(zone());
1876}
1877
1878
1879template<>
1880inline HInstruction* HGraphBuilder::NewUncasted<HContext>() {
1881  return New<HContext>();
1882}
1883
1884class 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)
1893        : target_(target),
1894          break_block_(NULL),
1895          continue_block_(NULL),
1896          drop_extra_(drop_extra) {
1897    }
1898
1899    BreakableStatement* target() { return target_; }
1900    HBasicBlock* break_block() { return break_block_; }
1901    void set_break_block(HBasicBlock* block) { break_block_ = block; }
1902    HBasicBlock* continue_block() { return continue_block_; }
1903    void set_continue_block(HBasicBlock* block) { continue_block_ = block; }
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:
1917    BreakAndContinueScope(BreakAndContinueInfo* info,
1918                          HOptimizedGraphBuilder* owner)
1919        : info_(info), owner_(owner), next_(owner->break_scope()) {
1920      owner->set_break_scope(this);
1921    }
1922
1923    ~BreakAndContinueScope() { owner_->set_break_scope(next_); }
1924
1925    BreakAndContinueInfo* info() { return info_; }
1926    HOptimizedGraphBuilder* owner() { return owner_; }
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.
1944  BreakAndContinueScope* break_scope() const { return break_scope_; }
1945  void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; }
1946
1947  bool inline_bailout() { return inline_bailout_; }
1948
1949  HValue* context() { return environment()->context(); }
1950
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
1959  FunctionState* function_state() const { return function_state_; }
1960
1961  void VisitDeclarations(ZoneList<Declaration*>* declarations);
1962
1963  void* operator new(size_t size, Zone* zone) {
1964    return zone->New(static_cast<int>(size));
1965  }
1966  void operator delete(void* pointer, Zone* zone) { }
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.
1997  void set_function_state(FunctionState* state) { function_state_ = state; }
1998
1999  AstContext* ast_context() const { return ast_context_; }
2000  void set_ast_context(AstContext* context) { ast_context_ = context; }
2001
2002  // Accessors forwarded to the function state.
2003  CompilationInfo* current_info() const {
2004    return function_state()->compilation_info();
2005  }
2006  AstContext* call_context() const {
2007    return function_state()->call_context();
2008  }
2009  HBasicBlock* function_return() const {
2010    return function_state()->function_return();
2011  }
2012  TestContext* inlined_test_context() const {
2013    return function_state()->test_context();
2014  }
2015  void ClearInlinedTestContext() {
2016    function_state()->ClearInlinedTestContext();
2017  }
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
2068  HValue* Top() const { return environment()->Top(); }
2069  void Drop(int n) { environment()->Drop(n); }
2070  void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
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  }
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
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:
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
2232    bool IsJSObjectFieldAccessor() {
2233      int offset;  // unused
2234      return Accessors::IsJSObjectFieldAccessor(map_, name_, &offset);
2235    }
2236
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
2254    bool has_holder() { return !holder_.is_null(); }
2255
2256    LookupResult* lookup() { return &lookup_; }
2257    Handle<Map> map() { return map_; }
2258    Handle<JSObject> holder() { return holder_; }
2259    Handle<JSFunction> accessor() { return accessor_; }
2260    Handle<Object> constant() { return constant_; }
2261    HObjectAccess access() { return access_; }
2262
2263   private:
2264    Isolate* isolate() { return lookup_.isolate(); }
2265
2266    bool IsStringLength() {
2267      return map_->instance_type() < FIRST_NONSTRING_TYPE &&
2268          name_->Equals(isolate()->heap()->length_string());
2269    }
2270
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
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
2478Zone* AstContext::zone() const { return owner_->zone(); }
2479
2480
2481class HStatistics V8_FINAL: public Malloced {
2482 public:
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
2494  void IncrementFullCodeGen(TimeDelta full_code_gen) {
2495    full_code_gen_ += full_code_gen;
2496  }
2497
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
2519class HPhase : public CompilationPhase {
2520 public:
2521  HPhase(const char* name, HGraph* graph)
2522      : CompilationPhase(name, graph->info()),
2523        graph_(graph) { }
2524  ~HPhase();
2525
2526 protected:
2527  HGraph* graph() const { return graph_; }
2528
2529 private:
2530  HGraph* graph_;
2531
2532  DISALLOW_COPY_AND_ASSIGN(HPhase);
2533};
2534
2535
2536class HTracer V8_FINAL : public Malloced {
2537 public:
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:
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
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
2584  void PrintEmptyProperty(const char* name) {
2585    PrintIndent();
2586    trace_.Add("%s\n", name);
2587  }
2588
2589  void PrintStringProperty(const char* name, const char* value) {
2590    PrintIndent();
2591    trace_.Add("%s \"%s\"\n", name, value);
2592  }
2593
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
2599  void PrintBlockProperty(const char* name, int block_id) {
2600    PrintIndent();
2601    trace_.Add("%s \"B%d\"\n", name, block_id);
2602  }
2603
2604  void PrintIntProperty(const char* name, int value) {
2605    PrintIndent();
2606    trace_.Add("%s %d\n", name, value);
2607  }
2608
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
2622class NoObservableSideEffectsScope V8_FINAL {
2623 public:
2624  explicit NoObservableSideEffectsScope(HGraphBuilder* builder) :
2625      builder_(builder) {
2626    builder_->graph()->IncrementInNoSideEffectsScope();
2627  }
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