Update V8 to r6101 as required by WebKit r74534

Change-Id: I7f84af8dd732f11898fd644b2c2b1538914cb78d
diff --git a/src/hydrogen.h b/src/hydrogen.h
new file mode 100644
index 0000000..ebabf3d
--- /dev/null
+++ b/src/hydrogen.h
@@ -0,0 +1,1070 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_HYDROGEN_H_
+#define V8_HYDROGEN_H_
+
+#include "v8.h"
+
+#include "ast.h"
+#include "compiler.h"
+#include "data-flow.h"
+#include "hydrogen-instructions.h"
+#include "zone.h"
+
+namespace v8 {
+namespace internal {
+
+// Forward declarations.
+class HEnvironment;
+class HGraph;
+class HLoopInformation;
+class HTracer;
+class LAllocator;
+class LChunk;
+class LiveRange;
+
+
+class HBasicBlock: public ZoneObject {
+ public:
+  explicit HBasicBlock(HGraph* graph);
+  virtual ~HBasicBlock() { }
+
+  // Simple accessors.
+  int block_id() const { return block_id_; }
+  void set_block_id(int id) { block_id_ = id; }
+  HGraph* graph() const { return graph_; }
+  const ZoneList<HPhi*>* phis() const { return &phis_; }
+  HInstruction* first() const { return first_; }
+  HInstruction* GetLastInstruction();
+  HControlInstruction* end() const { return end_; }
+  HLoopInformation* loop_information() const { return loop_information_; }
+  const ZoneList<HBasicBlock*>* predecessors() const { return &predecessors_; }
+  bool HasPredecessor() const { return predecessors_.length() > 0; }
+  const ZoneList<HBasicBlock*>* dominated_blocks() const {
+    return &dominated_blocks_;
+  }
+  const ZoneList<int>* deleted_phis() const {
+    return &deleted_phis_;
+  }
+  void RecordDeletedPhi(int merge_index) {
+    deleted_phis_.Add(merge_index);
+  }
+  HBasicBlock* dominator() const { return dominator_; }
+  HEnvironment* last_environment() const { return last_environment_; }
+  int argument_count() const { return argument_count_; }
+  void set_argument_count(int count) { argument_count_ = count; }
+  int first_instruction_index() const { return first_instruction_index_; }
+  void set_first_instruction_index(int index) {
+    first_instruction_index_ = index;
+  }
+  int last_instruction_index() const { return last_instruction_index_; }
+  void set_last_instruction_index(int index) {
+    last_instruction_index_ = index;
+  }
+
+  void AttachLoopInformation();
+  void DetachLoopInformation();
+  bool IsLoopHeader() const { return loop_information() != NULL; }
+  bool IsStartBlock() const { return block_id() == 0; }
+  void PostProcessLoopHeader(IterationStatement* stmt);
+
+  bool IsFinished() const { return end_ != NULL; }
+  void AddPhi(HPhi* phi);
+  void RemovePhi(HPhi* phi);
+  void AddInstruction(HInstruction* instr);
+  bool Dominates(HBasicBlock* other) const;
+
+  void SetInitialEnvironment(HEnvironment* env);
+  void ClearEnvironment() { last_environment_ = NULL; }
+  bool HasEnvironment() const { return last_environment_ != NULL; }
+  void UpdateEnvironment(HEnvironment* env) { last_environment_ = env; }
+  HBasicBlock* parent_loop_header() const {
+    if (!HasParentLoopHeader()) return NULL;
+    return parent_loop_header_.get();
+  }
+
+  void set_parent_loop_header(HBasicBlock* block) {
+    parent_loop_header_.set(block);
+  }
+
+  bool HasParentLoopHeader() const { return parent_loop_header_.is_set(); }
+
+  void SetJoinId(int id);
+
+  void Finish(HControlInstruction* last);
+  void Goto(HBasicBlock* block, bool include_stack_check = false);
+
+  int PredecessorIndexOf(HBasicBlock* predecessor) const;
+  void AddSimulate(int id) { AddInstruction(CreateSimulate(id)); }
+  void AssignCommonDominator(HBasicBlock* other);
+
+  // Add the inlined function exit sequence, adding an HLeaveInlined
+  // instruction and updating the bailout environment.
+  void AddLeaveInlined(HValue* return_value, HBasicBlock* target);
+
+  // If a target block is tagged as an inline function return, all
+  // predecessors should contain the inlined exit sequence:
+  //
+  // LeaveInlined
+  // Simulate (caller's environment)
+  // Goto (target block)
+  bool IsInlineReturnTarget() const { return is_inline_return_target_; }
+  void MarkAsInlineReturnTarget() { is_inline_return_target_ = true; }
+
+  Handle<Object> cond() { return cond_; }
+  void set_cond(Handle<Object> value) { cond_ = value; }
+
+#ifdef DEBUG
+  void Verify();
+#endif
+
+ private:
+  void RegisterPredecessor(HBasicBlock* pred);
+  void AddDominatedBlock(HBasicBlock* block);
+
+  HSimulate* CreateSimulate(int id);
+
+  int block_id_;
+  HGraph* graph_;
+  ZoneList<HPhi*> phis_;
+  HInstruction* first_;
+  HInstruction* last_;  // Last non-control instruction of the block.
+  HControlInstruction* end_;
+  HLoopInformation* loop_information_;
+  ZoneList<HBasicBlock*> predecessors_;
+  HBasicBlock* dominator_;
+  ZoneList<HBasicBlock*> dominated_blocks_;
+  HEnvironment* last_environment_;
+  // Outgoing parameter count at block exit, set during lithium translation.
+  int argument_count_;
+  // Instruction indices into the lithium code stream.
+  int first_instruction_index_;
+  int last_instruction_index_;
+  ZoneList<int> deleted_phis_;
+  SetOncePointer<HBasicBlock> parent_loop_header_;
+  bool is_inline_return_target_;
+  Handle<Object> cond_;
+};
+
+
+class HLoopInformation: public ZoneObject {
+ public:
+  explicit HLoopInformation(HBasicBlock* loop_header)
+      : back_edges_(4), loop_header_(loop_header), blocks_(8) {
+    blocks_.Add(loop_header);
+  }
+  virtual ~HLoopInformation() {}
+
+  const ZoneList<HBasicBlock*>* back_edges() const { return &back_edges_; }
+  const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
+  HBasicBlock* loop_header() const { return loop_header_; }
+  HBasicBlock* GetLastBackEdge() const;
+  void RegisterBackEdge(HBasicBlock* block);
+
+ private:
+  void AddBlock(HBasicBlock* block);
+
+  ZoneList<HBasicBlock*> back_edges_;
+  HBasicBlock* loop_header_;
+  ZoneList<HBasicBlock*> blocks_;
+};
+
+
+class HSubgraph: public ZoneObject {
+ public:
+  explicit HSubgraph(HGraph* graph)
+      : graph_(graph),
+        entry_block_(NULL),
+        exit_block_(NULL),
+        break_continue_info_(4) {
+  }
+
+  HGraph* graph() const { return graph_; }
+  HEnvironment* environment() const {
+    ASSERT(HasExit());
+    return exit_block_->last_environment();
+  }
+
+  bool HasExit() const { return exit_block_ != NULL; }
+
+  void PreProcessOsrEntry(IterationStatement* statement);
+
+  void AppendOptional(HSubgraph* graph,
+                      bool on_true_branch,
+                      HValue* boolean_value);
+  void AppendJoin(HSubgraph* then_graph, HSubgraph* else_graph, AstNode* node);
+  void AppendWhile(HSubgraph* condition,
+                   HSubgraph* body,
+                   IterationStatement* statement,
+                   HSubgraph* continue_subgraph,
+                   HSubgraph* exit);
+  void AppendDoWhile(HSubgraph* body,
+                     IterationStatement* statement,
+                     HSubgraph* go_back,
+                     HSubgraph* exit);
+  void AppendEndless(HSubgraph* body, IterationStatement* statement);
+  void Append(HSubgraph* next, BreakableStatement* statement);
+  void ResolveContinue(IterationStatement* statement);
+  HBasicBlock* BundleBreak(BreakableStatement* statement);
+  HBasicBlock* BundleContinue(IterationStatement* statement);
+  HBasicBlock* BundleBreakContinue(BreakableStatement* statement,
+                                   bool is_continue,
+                                   int join_id);
+  HBasicBlock* JoinBlocks(HBasicBlock* a, HBasicBlock* b, int id);
+
+  void FinishExit(HControlInstruction* instruction);
+  void FinishBreakContinue(BreakableStatement* target, bool is_continue);
+  void Initialize(HBasicBlock* block) {
+    ASSERT(entry_block_ == NULL);
+    entry_block_ = block;
+    exit_block_ = block;
+  }
+  HBasicBlock* entry_block() const { return entry_block_; }
+  HBasicBlock* exit_block() const { return exit_block_; }
+  void set_exit_block(HBasicBlock* block) {
+    exit_block_ = block;
+  }
+
+  void ConnectExitTo(HBasicBlock* other, bool include_stack_check = false) {
+    if (HasExit()) {
+      exit_block()->Goto(other, include_stack_check);
+    }
+  }
+
+  void AddBreakContinueInfo(HSubgraph* other) {
+    break_continue_info_.AddAll(other->break_continue_info_);
+  }
+
+ protected:
+  class BreakContinueInfo: public ZoneObject {
+   public:
+    BreakContinueInfo(BreakableStatement* target, HBasicBlock* block,
+                      bool is_continue)
+      : target_(target), block_(block), continue_(is_continue) {}
+    BreakableStatement* target() const { return target_; }
+    HBasicBlock* block() const { return block_; }
+    bool is_continue() const { return continue_; }
+    bool IsResolved() const { return block_ == NULL; }
+    void Resolve() { block_ = NULL; }
+
+   private:
+    BreakableStatement* target_;
+    HBasicBlock* block_;
+    bool continue_;
+  };
+
+  const ZoneList<BreakContinueInfo*>* break_continue_info() const {
+    return &break_continue_info_;
+  }
+
+  HGraph* graph_;  // The graph this is a subgraph of.
+  HBasicBlock* entry_block_;
+  HBasicBlock* exit_block_;
+
+ private:
+  ZoneList<BreakContinueInfo*> break_continue_info_;
+};
+
+
+class HGraph: public HSubgraph {
+ public:
+  explicit HGraph(CompilationInfo* info);
+
+  CompilationInfo* info() const { return info_; }
+  const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; }
+  const ZoneList<HPhi*>* phi_list() const { return phi_list_; }
+  Handle<String> debug_name() const { return info_->function()->debug_name(); }
+  HEnvironment* start_environment() const { return start_environment_; }
+
+  void InitializeInferredTypes();
+  void InsertTypeConversions();
+  void InsertRepresentationChanges();
+  bool ProcessArgumentsObject();
+  void EliminateRedundantPhis();
+  void Canonicalize();
+  void OrderBlocks();
+  void AssignDominators();
+
+  // Returns false if there are phi-uses of the arguments-object
+  // which are not supported by the optimizing compiler.
+  bool CollectPhis();
+
+  Handle<Code> Compile();
+
+  void set_undefined_constant(HConstant* constant) {
+    undefined_constant_.set(constant);
+  }
+  HConstant* GetConstantUndefined() const { return undefined_constant_.get(); }
+  HConstant* GetConstant1();
+  HConstant* GetConstantMinus1();
+  HConstant* GetConstantTrue();
+  HConstant* GetConstantFalse();
+
+  HBasicBlock* CreateBasicBlock();
+  HArgumentsObject* GetArgumentsObject() const {
+    return arguments_object_.get();
+  }
+  bool HasArgumentsObject() const { return arguments_object_.is_set(); }
+
+  void SetArgumentsObject(HArgumentsObject* object) {
+    arguments_object_.set(object);
+  }
+
+  // True iff. we are compiling for OSR and the statement is the entry.
+  bool HasOsrEntryAt(IterationStatement* statement);
+
+  int GetMaximumValueID() const { return values_.length(); }
+  int GetNextBlockID() { return next_block_id_++; }
+  int GetNextValueID(HValue* value) {
+    values_.Add(value);
+    return values_.length() - 1;
+  }
+  HValue* LookupValue(int id) const {
+    if (id >= 0 && id < values_.length()) return values_[id];
+    return NULL;
+  }
+
+#ifdef DEBUG
+  void Verify() const;
+#endif
+
+ private:
+  void Postorder(HBasicBlock* block,
+                 BitVector* visited,
+                 ZoneList<HBasicBlock*>* order,
+                 HBasicBlock* loop_header);
+  void PostorderLoopBlocks(HLoopInformation* loop,
+                           BitVector* visited,
+                           ZoneList<HBasicBlock*>* order,
+                           HBasicBlock* loop_header);
+  HConstant* GetConstant(SetOncePointer<HConstant>* pointer,
+                         Object* value);
+
+  void InsertTypeConversions(HInstruction* instr);
+  void PropagateMinusZeroChecks(HValue* value, BitVector* visited);
+  void InsertRepresentationChangeForUse(HValue* value,
+                                        HValue* use,
+                                        Representation to,
+                                        bool truncating);
+  void InsertRepresentationChanges(HValue* current);
+  void InferTypes(ZoneList<HValue*>* worklist);
+  void InitializeInferredTypes(int from_inclusive, int to_inclusive);
+  void CheckForBackEdge(HBasicBlock* block, HBasicBlock* successor);
+
+  int next_block_id_;
+  CompilationInfo* info_;
+  HEnvironment* start_environment_;
+  ZoneList<HBasicBlock*> blocks_;
+  ZoneList<HValue*> values_;
+  ZoneList<HPhi*>* phi_list_;
+  SetOncePointer<HConstant> undefined_constant_;
+  SetOncePointer<HConstant> constant_1_;
+  SetOncePointer<HConstant> constant_minus1_;
+  SetOncePointer<HConstant> constant_true_;
+  SetOncePointer<HConstant> constant_false_;
+  SetOncePointer<HArgumentsObject> arguments_object_;
+
+  friend class HSubgraph;
+
+  DISALLOW_COPY_AND_ASSIGN(HGraph);
+};
+
+
+class HEnvironment: public ZoneObject {
+ public:
+  HEnvironment(HEnvironment* outer,
+               Scope* scope,
+               Handle<JSFunction> closure);
+
+  void Bind(Variable* variable, HValue* value) {
+    Bind(IndexFor(variable), value);
+
+    if (FLAG_trace_environment) {
+      PrintF("Slot index=%d name=%s\n",
+             variable->AsSlot()->index(),
+             *variable->name()->ToCString());
+    }
+  }
+
+  void Bind(int index, HValue* value) {
+    ASSERT(value != NULL);
+    if (!assigned_variables_.Contains(index)) {
+      assigned_variables_.Add(index);
+    }
+    values_[index] = value;
+  }
+
+  HValue* Lookup(Variable* variable) const {
+    return Lookup(IndexFor(variable));
+  }
+  HValue* Lookup(int index) const {
+    HValue* result = values_[index];
+    ASSERT(result != NULL);
+    return result;
+  }
+
+  void Push(HValue* value) {
+    ASSERT(value != NULL);
+    ++push_count_;
+    values_.Add(value);
+  }
+
+  HValue* Top() const { return ExpressionStackAt(0); }
+
+  HValue* ExpressionStackAt(int index_from_top) const {
+    int index = values_.length() - index_from_top - 1;
+    ASSERT(IsExpressionStackIndex(index));
+    return values_[index];
+  }
+
+  void SetExpressionStackAt(int index_from_top, HValue* value) {
+    int index = values_.length() - index_from_top - 1;
+    ASSERT(IsExpressionStackIndex(index));
+    values_[index] = value;
+  }
+
+  HValue* Pop() {
+    ASSERT(!IsExpressionStackEmpty());
+    if (push_count_ > 0) {
+      --push_count_;
+      ASSERT(push_count_ >= 0);
+    } else {
+      ++pop_count_;
+    }
+    return values_.RemoveLast();
+  }
+
+  void Drop(int count) {
+    for (int i = 0; i < count; ++i) {
+      Pop();
+    }
+  }
+
+  Handle<JSFunction> closure() const { return closure_; }
+
+  // ID of the original AST node to identify deoptimization points.
+  int ast_id() const { return ast_id_; }
+  void set_ast_id(int id) { ast_id_ = id; }
+
+  const ZoneList<HValue*>* values() const { return &values_; }
+  const ZoneList<int>* assigned_variables() const {
+    return &assigned_variables_;
+  }
+  int parameter_count() const { return parameter_count_; }
+  int local_count() const { return local_count_; }
+  int push_count() const { return push_count_; }
+  int pop_count() const { return pop_count_; }
+  int total_count() const { return values_.length(); }
+  HEnvironment* outer() const { return outer_; }
+  HEnvironment* Copy() const;
+  HEnvironment* CopyWithoutHistory() const;
+  HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const;
+
+  // Create an "inlined version" of this environment, where the original
+  // environment is the outer environment but the top expression stack
+  // elements are moved to an inner environment as parameters. If
+  // is_speculative, the argument values are expected to be PushArgument
+  // instructions, otherwise they are the actual values.
+  HEnvironment* CopyForInlining(Handle<JSFunction> target,
+                                FunctionLiteral* function,
+                                bool is_speculative,
+                                HConstant* undefined) const;
+
+  void AddIncomingEdge(HBasicBlock* block, HEnvironment* other);
+  void ClearHistory() {
+    pop_count_ = 0;
+    push_count_ = 0;
+    assigned_variables_.Clear();
+  }
+  void SetValueAt(int index, HValue* value) {
+    ASSERT(index < total_count());
+    values_[index] = value;
+  }
+
+  void PrintTo(StringStream* stream);
+  void PrintToStd();
+
+ private:
+  explicit HEnvironment(const HEnvironment* other);
+
+  bool IsExpressionStackIndex(int index) const {
+    return index >= parameter_count_ + local_count_;
+  }
+  bool IsExpressionStackEmpty() const {
+    int length = values_.length();
+    int first_expression = parameter_count() + local_count();
+    ASSERT(length >= first_expression);
+    return length == first_expression;
+  }
+  void Initialize(int parameter_count, int local_count, int stack_height);
+  void Initialize(const HEnvironment* other);
+  int VariableToIndex(Variable* var);
+  int IndexFor(Variable* variable) const;
+
+  Handle<JSFunction> closure_;
+  // Value array [parameters] [locals] [temporaries].
+  ZoneList<HValue*> values_;
+  ZoneList<int> assigned_variables_;
+  int parameter_count_;
+  int local_count_;
+  HEnvironment* outer_;
+  int pop_count_;
+  int push_count_;
+  int ast_id_;
+};
+
+
+class HGraphBuilder;
+
+class AstContext {
+ public:
+  bool IsEffect() const { return kind_ == Expression::kEffect; }
+  bool IsValue() const { return kind_ == Expression::kValue; }
+  bool IsTest() const { return kind_ == Expression::kTest; }
+
+  // 'Fill' this context with a hydrogen value.  The value is assumed to
+  // have already been inserted in the instruction stream (or not need to
+  // be, e.g., HPhi).  Call this function in tail position in the Visit
+  // functions for expressions.
+  virtual void ReturnValue(HValue* value) = 0;
+
+  // Add a hydrogen instruction to the instruction stream (recording an
+  // environment simulation if necessary) and then fill this context with
+  // the instruction as value.
+  virtual void ReturnInstruction(HInstruction* instr, int ast_id) = 0;
+
+ protected:
+  AstContext(HGraphBuilder* owner, Expression::Context kind);
+  virtual ~AstContext();
+
+  HGraphBuilder* owner() const { return owner_; }
+
+  // We want to be able to assert, in a context-specific way, that the stack
+  // height makes sense when the context is filled.
+#ifdef DEBUG
+  int original_count_;
+#endif
+
+ private:
+  HGraphBuilder* owner_;
+  Expression::Context kind_;
+  AstContext* outer_;
+};
+
+
+class EffectContext: public AstContext {
+ public:
+  explicit EffectContext(HGraphBuilder* owner)
+      : AstContext(owner, Expression::kEffect) {
+  }
+  virtual ~EffectContext();
+
+  virtual void ReturnValue(HValue* value);
+  virtual void ReturnInstruction(HInstruction* instr, int ast_id);
+};
+
+
+class ValueContext: public AstContext {
+ public:
+  explicit ValueContext(HGraphBuilder* owner)
+      : AstContext(owner, Expression::kValue) {
+  }
+  virtual ~ValueContext();
+
+  virtual void ReturnValue(HValue* value);
+  virtual void ReturnInstruction(HInstruction* instr, int ast_id);
+};
+
+
+class TestContext: public AstContext {
+ public:
+  TestContext(HGraphBuilder* owner,
+              HBasicBlock* if_true,
+              HBasicBlock* if_false)
+      : AstContext(owner, Expression::kTest),
+        if_true_(if_true),
+        if_false_(if_false) {
+  }
+
+  virtual void ReturnValue(HValue* value);
+  virtual void ReturnInstruction(HInstruction* instr, int ast_id);
+
+  static TestContext* cast(AstContext* context) {
+    ASSERT(context->IsTest());
+    return reinterpret_cast<TestContext*>(context);
+  }
+
+  HBasicBlock* if_true() const { return if_true_; }
+  HBasicBlock* if_false() const { return if_false_; }
+
+ private:
+  // Build the shared core part of the translation unpacking a value into
+  // control flow.
+  void BuildBranch(HValue* value);
+
+  HBasicBlock* if_true_;
+  HBasicBlock* if_false_;
+};
+
+
+class HGraphBuilder: public AstVisitor {
+ public:
+  explicit HGraphBuilder(TypeFeedbackOracle* oracle)
+      : oracle_(oracle),
+        graph_(NULL),
+        current_subgraph_(NULL),
+        peeled_statement_(NULL),
+        ast_context_(NULL),
+        call_context_(NULL),
+        function_return_(NULL),
+        inlined_count_(0) { }
+
+  HGraph* CreateGraph(CompilationInfo* info);
+
+  // Simple accessors.
+  HGraph* graph() const { return graph_; }
+  HSubgraph* subgraph() const { return current_subgraph_; }
+
+  HEnvironment* environment() const { return subgraph()->environment(); }
+  HBasicBlock* CurrentBlock() const { return subgraph()->exit_block(); }
+
+  // Adding instructions.
+  HInstruction* AddInstruction(HInstruction* instr);
+  void AddSimulate(int id);
+
+  // Bailout environment manipulation.
+  void Push(HValue* value) { environment()->Push(value); }
+  HValue* Pop() { return environment()->Pop(); }
+
+ private:
+  // Type of a member function that generates inline code for a native function.
+  typedef void (HGraphBuilder::*InlineFunctionGenerator)(int argument_count,
+                                                         int ast_id);
+
+  // Forward declarations for inner scope classes.
+  class SubgraphScope;
+
+  static const InlineFunctionGenerator kInlineFunctionGenerators[];
+
+  static const int kMaxCallPolymorphism = 4;
+  static const int kMaxLoadPolymorphism = 4;
+  static const int kMaxStorePolymorphism = 4;
+
+  static const int kMaxInlinedNodes = 196;
+  static const int kMaxInlinedSize = 196;
+  static const int kMaxSourceSize = 600;
+
+  // Simple accessors.
+  TypeFeedbackOracle* oracle() const { return oracle_; }
+  AstContext* ast_context() const { return ast_context_; }
+  void set_ast_context(AstContext* context) { ast_context_ = context; }
+  AstContext* call_context() const { return call_context_; }
+  HBasicBlock* function_return() const { return function_return_; }
+
+  // Generators for inline runtime functions.
+#define INLINE_FUNCTION_GENERATOR_DECLARATION(Name, argc, ressize)      \
+  void Generate##Name(int argument_count, int ast_id);
+
+  INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
+  INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
+#undef INLINE_FUNCTION_GENERATOR_DECLARATION
+
+  void Bailout(const char* reason);
+
+  void AppendPeeledWhile(IterationStatement* stmt,
+                         HSubgraph* cond_graph,
+                         HSubgraph* body_graph,
+                         HSubgraph* exit_graph);
+
+  void AddToSubgraph(HSubgraph* graph, ZoneList<Statement*>* stmts);
+  void AddToSubgraph(HSubgraph* graph, Statement* stmt);
+  void AddToSubgraph(HSubgraph* graph, Expression* expr);
+
+  HValue* Top() const { return environment()->Top(); }
+  void Drop(int n) { environment()->Drop(n); }
+  void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
+
+  void VisitForValue(Expression* expr);
+  void VisitForEffect(Expression* expr);
+  void VisitForControl(Expression* expr,
+                       HBasicBlock* true_block,
+                       HBasicBlock* false_block);
+
+  // Visit an argument and wrap it in a PushArgument instruction.
+  HValue* VisitArgument(Expression* expr);
+  void VisitArgumentList(ZoneList<Expression*>* arguments);
+
+  void AddPhi(HPhi* phi);
+
+  void PushAndAdd(HInstruction* instr);
+
+  void PushArgumentsForStubCall(int argument_count);
+
+  // Remove the arguments from the bailout environment and emit instructions
+  // to push them as outgoing parameters.
+  void ProcessCall(HCall* call);
+
+  void AssumeRepresentation(HValue* value, Representation r);
+  static Representation ToRepresentation(TypeInfo info);
+
+  void SetupScope(Scope* scope);
+  virtual void VisitStatements(ZoneList<Statement*>* statements);
+
+#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
+  AST_NODE_LIST(DECLARE_VISIT)
+#undef DECLARE_VISIT
+
+  bool ShouldPeel(HSubgraph* cond, HSubgraph* body);
+
+  HBasicBlock* CreateBasicBlock(HEnvironment* env);
+  HSubgraph* CreateEmptySubgraph();
+  HSubgraph* CreateGotoSubgraph(HEnvironment* env);
+  HSubgraph* CreateBranchSubgraph(HEnvironment* env);
+  HSubgraph* CreateLoopHeaderSubgraph(HEnvironment* env);
+  HSubgraph* CreateInlinedSubgraph(HEnvironment* outer,
+                                   Handle<JSFunction> target,
+                                   FunctionLiteral* function);
+
+  // Helpers for flow graph construction.
+  void LookupGlobalPropertyCell(Variable* var,
+                                LookupResult* lookup,
+                                bool is_store);
+
+  bool TryArgumentsAccess(Property* expr);
+  bool TryCallApply(Call* expr);
+  bool TryInline(Call* expr);
+  bool TryMathFunctionInline(Call* expr);
+  void TraceInline(Handle<JSFunction> target, bool result);
+
+  void HandleGlobalVariableAssignment(Variable* var,
+                                      HValue* value,
+                                      int position,
+                                      int ast_id);
+
+  void HandlePropertyAssignment(Assignment* expr);
+  void HandleCompoundAssignment(Assignment* expr);
+  void HandlePolymorphicLoadNamedField(Property* expr,
+                                       HValue* object,
+                                       ZoneMapList* types,
+                                       Handle<String> name);
+  void HandlePolymorphicStoreNamedField(Assignment* expr,
+                                        HValue* object,
+                                        HValue* value,
+                                        ZoneMapList* types,
+                                        Handle<String> name);
+  void HandlePolymorphicCallNamed(Call* expr,
+                                  HValue* receiver,
+                                  ZoneMapList* types,
+                                  Handle<String> name);
+
+  HInstruction* BuildBinaryOperation(BinaryOperation* expr,
+                                     HValue* left,
+                                     HValue* right);
+  HInstruction* BuildIncrement(HValue* value, bool increment);
+  HLoadNamedField* BuildLoadNamedField(HValue* object,
+                                       Property* expr,
+                                       Handle<Map> type,
+                                       LookupResult* result,
+                                       bool smi_and_map_check);
+  HInstruction* BuildLoadNamedGeneric(HValue* object, Property* expr);
+  HInstruction* BuildLoadKeyedFastElement(HValue* object,
+                                          HValue* key,
+                                          Property* expr);
+  HInstruction* BuildLoadKeyedGeneric(HValue* object,
+                                      HValue* key);
+
+  HInstruction* BuildLoadNamed(HValue* object,
+                               Property* prop,
+                               Handle<Map> map,
+                               Handle<String> name);
+  HInstruction* BuildStoreNamed(HValue* object,
+                                HValue* value,
+                                Expression* expr);
+  HInstruction* BuildStoreNamedField(HValue* object,
+                                     Handle<String> name,
+                                     HValue* value,
+                                     Handle<Map> type,
+                                     LookupResult* lookup,
+                                     bool smi_and_map_check);
+  HInstruction* BuildStoreNamedGeneric(HValue* object,
+                                       Handle<String> name,
+                                       HValue* value);
+  HInstruction* BuildStoreKeyedGeneric(HValue* object,
+                                       HValue* key,
+                                       HValue* value);
+
+  HInstruction* BuildStoreKeyedFastElement(HValue* object,
+                                           HValue* key,
+                                           HValue* val,
+                                           Expression* expr);
+
+  HCompare* BuildSwitchCompare(HSubgraph* subgraph,
+                               HValue* switch_value,
+                               CaseClause* clause);
+
+  void AddCheckConstantFunction(Call* expr,
+                                HValue* receiver,
+                                Handle<Map> receiver_map,
+                                bool smi_and_map_check);
+
+
+  HBasicBlock* BuildTypeSwitch(ZoneMapList* maps,
+                               ZoneList<HSubgraph*>* subgraphs,
+                               HValue* receiver,
+                               int join_id);
+
+  TypeFeedbackOracle* oracle_;
+  HGraph* graph_;
+  HSubgraph* current_subgraph_;
+  IterationStatement* peeled_statement_;
+  // Expression context of the currently visited subexpression. NULL when
+  // visiting statements.
+  AstContext* ast_context_;
+
+  // During function inlining, expression context of the call being
+  // inlined. NULL when not inlining.
+  AstContext* call_context_;
+
+  // When inlining a call in an effect or value context, the return
+  // block. NULL otherwise. When inlining a call in a test context, there
+  // are a pair of target blocks in the call context.
+  HBasicBlock* function_return_;
+
+  int inlined_count_;
+
+  friend class AstContext;  // Pushes and pops the AST context stack.
+
+  DISALLOW_COPY_AND_ASSIGN(HGraphBuilder);
+};
+
+
+class HValueMap: public ZoneObject {
+ public:
+  HValueMap()
+      : array_size_(0),
+        lists_size_(0),
+        count_(0),
+        present_flags_(0),
+        array_(NULL),
+        lists_(NULL),
+        free_list_head_(kNil) {
+    ResizeLists(kInitialSize);
+    Resize(kInitialSize);
+  }
+
+  void Kill(int flags);
+
+  void Add(HValue* value) {
+    present_flags_ |= value->flags();
+    Insert(value);
+  }
+
+  HValue* Lookup(HValue* value) const;
+  HValueMap* Copy() const { return new HValueMap(this); }
+
+ private:
+  // A linked list of HValue* values.  Stored in arrays.
+  struct HValueMapListElement {
+    HValue* value;
+    int next;  // Index in the array of the next list element.
+  };
+  static const int kNil = -1;  // The end of a linked list
+
+  // Must be a power of 2.
+  static const int kInitialSize = 16;
+
+  explicit HValueMap(const HValueMap* other);
+
+  void Resize(int new_size);
+  void ResizeLists(int new_size);
+  void Insert(HValue* value);
+  uint32_t Bound(uint32_t value) const { return value & (array_size_ - 1); }
+
+  int array_size_;
+  int lists_size_;
+  int count_;  // The number of values stored in the HValueMap.
+  int present_flags_;  // All flags that are in any value in the HValueMap.
+  HValueMapListElement* array_;  // Primary store - contains the first value
+  // with a given hash.  Colliding elements are stored in linked lists.
+  HValueMapListElement* lists_;  // The linked lists containing hash collisions.
+  int free_list_head_;  // Unused elements in lists_ are on the free list.
+};
+
+
+class HStatistics: public Malloced {
+ public:
+  void Print();
+  void SaveTiming(const char* name, int64_t ticks);
+  static HStatistics* Instance() {
+    static SetOncePointer<HStatistics> instance;
+    if (!instance.is_set()) {
+      instance.set(new HStatistics());
+    }
+    return instance.get();
+  }
+
+ private:
+
+  HStatistics() : timing_(5), names_(5), total_(0), full_code_gen_(0) { }
+
+  List<int64_t> timing_;
+  List<const char*> names_;
+  int64_t total_;
+  int64_t full_code_gen_;
+};
+
+
+class HPhase BASE_EMBEDDED {
+ public:
+  static const char* const kFullCodeGen;
+  static const char* const kTotal;
+
+  explicit HPhase(const char* name) { Begin(name, NULL, NULL, NULL); }
+  HPhase(const char* name, HGraph* graph) {
+    Begin(name, graph, NULL, NULL);
+  }
+  HPhase(const char* name, LChunk* chunk) {
+    Begin(name, NULL, chunk, NULL);
+  }
+  HPhase(const char* name, LAllocator* allocator) {
+    Begin(name, NULL, NULL, allocator);
+  }
+
+  ~HPhase() {
+    End();
+  }
+
+ private:
+  void Begin(const char* name,
+             HGraph* graph,
+             LChunk* chunk,
+             LAllocator* allocator);
+  void End() const;
+
+  int64_t start_;
+  const char* name_;
+  HGraph* graph_;
+  LChunk* chunk_;
+  LAllocator* allocator_;
+};
+
+
+class HTracer: public Malloced {
+ public:
+  void TraceCompilation(FunctionLiteral* function);
+  void TraceHydrogen(const char* name, HGraph* graph);
+  void TraceLithium(const char* name, LChunk* chunk);
+  void TraceLiveRanges(const char* name, LAllocator* allocator);
+
+  static HTracer* Instance() {
+    static SetOncePointer<HTracer> instance;
+    if (!instance.is_set()) {
+      instance.set(new HTracer("hydrogen.cfg"));
+    }
+    return instance.get();
+  }
+
+ private:
+  class Tag BASE_EMBEDDED {
+   public:
+    Tag(HTracer* tracer, const char* name) {
+      name_ = name;
+      tracer_ = tracer;
+      tracer->PrintIndent();
+      tracer->trace_.Add("begin_%s\n", name);
+      tracer->indent_++;
+    }
+
+    ~Tag() {
+      tracer_->indent_--;
+      tracer_->PrintIndent();
+      tracer_->trace_.Add("end_%s\n", name_);
+      ASSERT(tracer_->indent_ >= 0);
+      tracer_->FlushToFile();
+    }
+
+   private:
+    HTracer* tracer_;
+    const char* name_;
+  };
+
+  explicit HTracer(const char* filename)
+      : filename_(filename), trace_(&string_allocator_), indent_(0) {
+    WriteChars(filename, "", 0, false);
+  }
+
+  void TraceLiveRange(LiveRange* range, const char* type);
+  void Trace(const char* name, HGraph* graph, LChunk* chunk);
+  void FlushToFile();
+
+  void PrintEmptyProperty(const char* name) {
+    PrintIndent();
+    trace_.Add("%s\n", name);
+  }
+
+  void PrintStringProperty(const char* name, const char* value) {
+    PrintIndent();
+    trace_.Add("%s \"%s\"\n", name, value);
+  }
+
+  void PrintLongProperty(const char* name, int64_t value) {
+    PrintIndent();
+    trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000));
+  }
+
+  void PrintBlockProperty(const char* name, int block_id) {
+    PrintIndent();
+    trace_.Add("%s \"B%d\"\n", name, block_id);
+  }
+
+  void PrintBlockProperty(const char* name, int block_id1, int block_id2) {
+    PrintIndent();
+    trace_.Add("%s \"B%d\" \"B%d\"\n", name, block_id1, block_id2);
+  }
+
+  void PrintIntProperty(const char* name, int value) {
+    PrintIndent();
+    trace_.Add("%s %d\n", name, value);
+  }
+
+  void PrintIndent() {
+    for (int i = 0; i < indent_; i++) {
+      trace_.Add("  ");
+    }
+  }
+
+  const char* filename_;
+  HeapStringAllocator string_allocator_;
+  StringStream trace_;
+  int indent_;
+};
+
+
+} }  // namespace v8::internal
+
+#endif  // V8_HYDROGEN_H_