Version 3.0.8

Exposed heap size limit to the heap statistics gathered by the GetHeapStatistics API. 

Wrapped external pointers more carefully (issue 1037).

Hardened the implementation of error objects to avoid setters intercepting the properties set then throwing an error.

Avoided trashing the FPSCR when calculating Math.floor on ARM.

Performance improvements on the IA32 platform.


git-svn-id: http://v8.googlecode.com/svn/trunk@6346 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index 4b0db40..07f0a8d 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -38,8 +38,6 @@
 
 // Forward declarations.
 class LCodeGen;
-class LEnvironment;
-class Translation;
 
 
 // Type hierarchy:
@@ -79,16 +77,20 @@
 //   LCallNamed
 //   LCallRuntime
 //   LCallStub
+//   LCheckPrototypeMaps
 //   LConstant
 //     LConstantD
 //     LConstantI
 //     LConstantT
 //   LDeoptimize
 //   LFunctionLiteral
+//   LGap
+//     LLabel
 //   LGlobalObject
 //   LGlobalReceiver
-//   LLabel
-//   LLayzBailout
+//   LGoto
+//   LLazyBailout
+//   LLoadContextSlot
 //   LLoadGlobal
 //   LMaterializedLiteral
 //     LArrayLiteral
@@ -111,7 +113,6 @@
 //     LCheckFunction
 //     LCheckInstanceType
 //     LCheckMap
-//     LCheckPrototypeMaps
 //     LCheckSmi
 //     LClassOfTest
 //     LClassOfTestAndBranch
@@ -225,6 +226,7 @@
   V(ClassOfTestAndBranch)                       \
   V(Label)                                      \
   V(LazyBailout)                                \
+  V(LoadContextSlot)                            \
   V(LoadElements)                               \
   V(LoadGlobal)                                 \
   V(LoadKeyedFastElement)                       \
@@ -292,8 +294,9 @@
 
   virtual void CompileToNative(LCodeGen* generator) = 0;
   virtual const char* Mnemonic() const = 0;
-  virtual void PrintTo(StringStream* stream) const;
-  virtual void PrintDataTo(StringStream* stream) const { }
+  virtual void PrintTo(StringStream* stream);
+  virtual void PrintDataTo(StringStream* stream) = 0;
+  virtual void PrintOutputOperandTo(StringStream* stream) = 0;
 
   // Declare virtual type testers.
 #define DECLARE_DO(type) virtual bool Is##type() const { return false; }
@@ -309,9 +312,7 @@
   LPointerMap* pointer_map() const { return pointer_map_.get(); }
   bool HasPointerMap() const { return pointer_map_.is_set(); }
 
-  void set_result(LOperand* operand) { result_.set(operand); }
-  LOperand* result() const { return result_.get(); }
-  bool HasResult() const { return result_.is_set(); }
+  virtual bool HasResult() const = 0;
 
   void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
   HValue* hydrogen_value() const { return hydrogen_value_; }
@@ -329,34 +330,66 @@
  private:
   SetOncePointer<LEnvironment> environment_;
   SetOncePointer<LPointerMap> pointer_map_;
-  SetOncePointer<LOperand> result_;
   HValue* hydrogen_value_;
   SetOncePointer<LEnvironment> deoptimization_environment_;
 };
 
 
-class LParallelMove : public ZoneObject {
+template<typename T, int N>
+class OperandContainer {
  public:
-  LParallelMove() : move_operands_(4) { }
-
-  void AddMove(LOperand* from, LOperand* to) {
-    move_operands_.Add(LMoveOperands(from, to));
+  OperandContainer() {
+    for (int i = 0; i < N; i++) elems_[i] = NULL;
   }
-
-  bool IsRedundant() const;
-
-  const ZoneList<LMoveOperands>* move_operands() const {
-    return &move_operands_;
-  }
-
-  void PrintDataTo(StringStream* stream) const;
-
+  int length() const { return N; }
+  T at(int i) const { return elems_[i]; }
+  void set_at(int i, T value) { elems_[i] = value; }
  private:
-  ZoneList<LMoveOperands> move_operands_;
+  T elems_[N];
 };
 
 
-class LGap: public LInstruction {
+template<typename T>
+class OperandContainer<T, 0> {
+ public:
+  int length() const { return 0; }
+  T at(int i) const {
+    UNREACHABLE();
+    return NULL;
+  }
+  void set_at(int i, T value) {
+    UNREACHABLE();
+  }
+};
+
+
+template<int R, int I, int T>
+class LTemplateInstruction: public LInstruction {
+ public:
+  // Allow 0 or 1 output operands.
+  STATIC_ASSERT(R == 0 || R == 1);
+  virtual bool HasResult() const { return R != 0; }
+  void set_result(LOperand* operand) { outputs_.set_at(0, operand); }
+  LOperand* result() const { return outputs_.at(0); }
+
+  int InputCount() const { return inputs_.length(); }
+  LOperand* InputAt(int i) const { return inputs_.at(i); }
+  void SetInputAt(int i, LOperand* operand) { inputs_.set_at(i, operand); }
+
+  int TempCount() const { return temps_.length(); }
+  LOperand* TempAt(int i) const { return temps_.at(i); }
+
+  virtual void PrintDataTo(StringStream* stream);
+  virtual void PrintOutputOperandTo(StringStream* stream);
+
+ private:
+  OperandContainer<LOperand*, R> outputs_;
+  OperandContainer<LOperand*, I> inputs_;
+  OperandContainer<LOperand*, T> temps_;
+};
+
+
+class LGap: public LTemplateInstruction<0, 0, 0> {
  public:
   explicit LGap(HBasicBlock* block)
       : block_(block) {
@@ -367,7 +400,7 @@
   }
 
   DECLARE_CONCRETE_INSTRUCTION(Gap, "gap")
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   bool IsRedundant() const;
 
@@ -397,13 +430,13 @@
 };
 
 
-class LGoto: public LInstruction {
+class LGoto: public LTemplateInstruction<0, 0, 0> {
  public:
   LGoto(int block_id, bool include_stack_check = false)
     : block_id_(block_id), include_stack_check_(include_stack_check) { }
 
   DECLARE_CONCRETE_INSTRUCTION(Goto, "goto")
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
   virtual bool IsControl() const { return true; }
 
   int block_id() const { return block_id_; }
@@ -415,7 +448,7 @@
 };
 
 
-class LLazyBailout: public LInstruction {
+class LLazyBailout: public LTemplateInstruction<0, 0, 0> {
  public:
   LLazyBailout() : gap_instructions_size_(0) { }
 
@@ -431,7 +464,7 @@
 };
 
 
-class LDeoptimize: public LInstruction {
+class LDeoptimize: public LTemplateInstruction<0, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
 };
@@ -444,7 +477,7 @@
 
   DECLARE_CONCRETE_INSTRUCTION(Label, "label")
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   int block_id() const { return block()->block_id(); }
   bool is_loop_header() const { return block()->IsLoopHeader(); }
@@ -459,13 +492,13 @@
 };
 
 
-class LParameter: public LInstruction {
+class LParameter: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(Parameter, "parameter")
 };
 
 
-class LCallStub: public LInstruction {
+class LCallStub: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(CallStub, "call-stub")
   DECLARE_HYDROGEN_ACCESSOR(CallStub)
@@ -476,96 +509,89 @@
 };
 
 
-class LUnknownOSRValue: public LInstruction {
+class LUnknownOSRValue: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown-osr-value")
 };
 
 
-class LUnaryOperation: public LInstruction {
+template<int R>
+class LUnaryOperation: public LTemplateInstruction<R, 1, 0> {
  public:
-  explicit LUnaryOperation(LOperand* input) : input_(input) { }
+  explicit LUnaryOperation<R>(LOperand* input) {
+    this->SetInputAt(0, input);
+  }
+
+  LOperand* input() const { return this->InputAt(0); }
 
   DECLARE_INSTRUCTION(UnaryOperation)
-
-  LOperand* input() const { return input_; }
-
-  virtual void PrintDataTo(StringStream* stream) const;
-
- private:
-  LOperand* input_;
 };
 
 
-class LBinaryOperation: public LInstruction {
+template<int R>
+class LBinaryOperation: public LTemplateInstruction<R, 2, 0> {
  public:
-  LBinaryOperation(LOperand* left, LOperand* right)
-      : left_(left), right_(right) { }
+  LBinaryOperation(LOperand* left, LOperand* right) {
+    this->SetInputAt(0, left);
+    this->SetInputAt(1, right);
+  }
 
   DECLARE_INSTRUCTION(BinaryOperation)
 
-  LOperand* left() const { return left_; }
-  LOperand* right() const { return right_; }
-  virtual void PrintDataTo(StringStream* stream) const;
-
- private:
-  LOperand* left_;
-  LOperand* right_;
+  LOperand* left() const { return this->InputAt(0); }
+  LOperand* right() const { return this->InputAt(1); }
 };
 
 
-class LApplyArguments: public LBinaryOperation {
+class LApplyArguments: public LTemplateInstruction<1, 4, 0> {
  public:
   LApplyArguments(LOperand* function,
                   LOperand* receiver,
                   LOperand* length,
-                  LOperand* elements)
-      : LBinaryOperation(function, receiver),
-        length_(length),
-        elements_(elements) { }
+                  LOperand* elements) {
+    this->SetInputAt(0, function);
+    this->SetInputAt(1, receiver);
+    this->SetInputAt(2, length);
+    this->SetInputAt(3, elements);
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(ApplyArguments, "apply-arguments")
 
-  LOperand* function() const { return left(); }
-  LOperand* receiver() const { return right(); }
-  LOperand* length() const { return length_; }
-  LOperand* elements() const { return elements_; }
-
- private:
-  LOperand* length_;
-  LOperand* elements_;
+  LOperand* function() const { return InputAt(0); }
+  LOperand* receiver() const { return InputAt(1); }
+  LOperand* length() const { return InputAt(2); }
+  LOperand* elements() const { return InputAt(3); }
 };
 
 
-class LAccessArgumentsAt: public LInstruction {
+class LAccessArgumentsAt: public LTemplateInstruction<1, 3, 0> {
  public:
-  LAccessArgumentsAt(LOperand* arguments, LOperand* length, LOperand* index)
-      : arguments_(arguments), length_(length), index_(index) { }
+  LAccessArgumentsAt(LOperand* arguments, LOperand* length, LOperand* index) {
+    this->SetInputAt(0, arguments);
+    this->SetInputAt(1, length);
+    this->SetInputAt(2, index);
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access-arguments-at")
 
-  LOperand* arguments() const { return arguments_; }
-  LOperand* length() const { return length_; }
-  LOperand* index() const { return index_; }
+  LOperand* arguments() const { return this->InputAt(0); }
+  LOperand* length() const { return this->InputAt(1); }
+  LOperand* index() const { return this->InputAt(2); }
 
-  virtual void PrintDataTo(StringStream* stream) const;
-
- private:
-  LOperand* arguments_;
-  LOperand* length_;
-  LOperand* index_;
+  virtual void PrintDataTo(StringStream* stream);
 };
 
 
-class LArgumentsLength: public LUnaryOperation {
+class LArgumentsLength: public LUnaryOperation<1> {
  public:
-  explicit LArgumentsLength(LOperand* elements) : LUnaryOperation(elements) {}
+  explicit LArgumentsLength(LOperand* elements)
+      : LUnaryOperation<1>(elements) {}
 
   DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments-length")
 };
 
 
-class LArgumentsElements: public LInstruction {
+class LArgumentsElements: public LTemplateInstruction<1, 0, 0> {
  public:
   LArgumentsElements() { }
 
@@ -573,29 +599,29 @@
 };
 
 
-class LModI: public LBinaryOperation {
+class LModI: public LBinaryOperation<1> {
  public:
-  LModI(LOperand* left, LOperand* right) : LBinaryOperation(left, right) { }
+  LModI(LOperand* left, LOperand* right) : LBinaryOperation<1>(left, right) { }
 
   DECLARE_CONCRETE_INSTRUCTION(ModI, "mod-i")
   DECLARE_HYDROGEN_ACCESSOR(Mod)
 };
 
 
-class LDivI: public LBinaryOperation {
+class LDivI: public LBinaryOperation<1> {
  public:
   LDivI(LOperand* left, LOperand* right)
-      : LBinaryOperation(left, right) { }
+      : LBinaryOperation<1>(left, right) { }
 
   DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
   DECLARE_HYDROGEN_ACCESSOR(Div)
 };
 
 
-class LMulI: public LBinaryOperation {
+class LMulI: public LBinaryOperation<1> {
  public:
   LMulI(LOperand* left, LOperand* right, LOperand* temp)
-      : LBinaryOperation(left, right), temp_(temp) { }
+      : LBinaryOperation<1>(left, right), temp_(temp) { }
 
   DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i")
   DECLARE_HYDROGEN_ACCESSOR(Mul)
@@ -607,36 +633,33 @@
 };
 
 
-class LCmpID: public LBinaryOperation {
+class LCmpID: public LBinaryOperation<1> {
  public:
-  LCmpID(Token::Value op, LOperand* left, LOperand* right, bool is_double)
-      : LBinaryOperation(left, right), op_(op), is_double_(is_double) { }
+  LCmpID(LOperand* left, LOperand* right)
+      : LBinaryOperation<1>(left, right) { }
 
-  Token::Value op() const { return op_; }
-  bool is_double() const { return is_double_; }
+  Token::Value op() const { return hydrogen()->token(); }
+  bool is_double() const {
+    return hydrogen()->GetInputRepresentation().IsDouble();
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(CmpID, "cmp-id")
-
- private:
-  Token::Value op_;
-  bool is_double_;
+  DECLARE_HYDROGEN_ACCESSOR(Compare)
 };
 
 
 class LCmpIDAndBranch: public LCmpID {
  public:
-  LCmpIDAndBranch(Token::Value op,
-                  LOperand* left,
+  LCmpIDAndBranch(LOperand* left,
                   LOperand* right,
                   int true_block_id,
-                  int false_block_id,
-                  bool is_double)
-      : LCmpID(op, left, right, is_double),
+                  int false_block_id)
+      : LCmpID(left, right),
         true_block_id_(true_block_id),
         false_block_id_(false_block_id) { }
 
   DECLARE_CONCRETE_INSTRUCTION(CmpIDAndBranch, "cmp-id-and-branch")
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
   virtual bool IsControl() const { return true; }
 
   int true_block_id() const { return true_block_id_; }
@@ -648,23 +671,23 @@
 };
 
 
-class LUnaryMathOperation: public LUnaryOperation {
+class LUnaryMathOperation: public LUnaryOperation<1> {
  public:
   explicit LUnaryMathOperation(LOperand* value)
-      : LUnaryOperation(value) { }
+      : LUnaryOperation<1>(value) { }
 
   DECLARE_CONCRETE_INSTRUCTION(UnaryMathOperation, "unary-math-operation")
   DECLARE_HYDROGEN_ACCESSOR(UnaryMathOperation)
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
   BuiltinFunctionId op() const { return hydrogen()->op(); }
 };
 
 
-class LCmpJSObjectEq: public LBinaryOperation {
+class LCmpJSObjectEq: public LBinaryOperation<1> {
  public:
   LCmpJSObjectEq(LOperand* left, LOperand* right)
-      : LBinaryOperation(left, right) {}
+      : LBinaryOperation<1>(left, right) {}
 
   DECLARE_CONCRETE_INSTRUCTION(CmpJSObjectEq, "cmp-jsobject-eq")
 };
@@ -692,34 +715,30 @@
 };
 
 
-class LIsNull: public LUnaryOperation {
+class LIsNull: public LUnaryOperation<1> {
  public:
-  LIsNull(LOperand* value, bool is_strict)
-      : LUnaryOperation(value), is_strict_(is_strict) {}
+  explicit LIsNull(LOperand* value) : LUnaryOperation<1>(value) { }
 
   DECLARE_CONCRETE_INSTRUCTION(IsNull, "is-null")
+  DECLARE_HYDROGEN_ACCESSOR(IsNull)
 
-  bool is_strict() const { return is_strict_; }
-
- private:
-  bool is_strict_;
+  bool is_strict() const { return hydrogen()->is_strict(); }
 };
 
 
 class LIsNullAndBranch: public LIsNull {
  public:
   LIsNullAndBranch(LOperand* value,
-                   bool is_strict,
                    LOperand* temp,
                    int true_block_id,
                    int false_block_id)
-      : LIsNull(value, is_strict),
+      : LIsNull(value),
         temp_(temp),
         true_block_id_(true_block_id),
         false_block_id_(false_block_id) { }
 
   DECLARE_CONCRETE_INSTRUCTION(IsNullAndBranch, "is-null-and-branch")
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
   virtual bool IsControl() const { return true; }
 
   int true_block_id() const { return true_block_id_; }
@@ -734,10 +753,10 @@
 };
 
 
-class LIsObject: public LUnaryOperation {
+class LIsObject: public LUnaryOperation<1> {
  public:
   LIsObject(LOperand* value, LOperand* temp)
-      : LUnaryOperation(value), temp_(temp) {}
+      : LUnaryOperation<1>(value), temp_(temp) {}
 
   DECLARE_CONCRETE_INSTRUCTION(IsObject, "is-object")
 
@@ -761,7 +780,7 @@
         false_block_id_(false_block_id) { }
 
   DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
   virtual bool IsControl() const { return true; }
 
   int true_block_id() const { return true_block_id_; }
@@ -776,9 +795,9 @@
 };
 
 
-class LIsSmi: public LUnaryOperation {
+class LIsSmi: public LUnaryOperation<1> {
  public:
-  explicit LIsSmi(LOperand* value) : LUnaryOperation(value) {}
+  explicit LIsSmi(LOperand* value) : LUnaryOperation<1>(value) {}
 
   DECLARE_CONCRETE_INSTRUCTION(IsSmi, "is-smi")
   DECLARE_HYDROGEN_ACCESSOR(IsSmi)
@@ -795,7 +814,7 @@
         false_block_id_(false_block_id) { }
 
   DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch, "is-smi-and-branch")
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
   virtual bool IsControl() const { return true; }
 
   int true_block_id() const { return true_block_id_; }
@@ -807,10 +826,10 @@
 };
 
 
-class LHasInstanceType: public LUnaryOperation {
+class LHasInstanceType: public LUnaryOperation<1> {
  public:
   explicit LHasInstanceType(LOperand* value)
-      : LUnaryOperation(value) { }
+      : LUnaryOperation<1>(value) { }
 
   DECLARE_CONCRETE_INSTRUCTION(HasInstanceType, "has-instance-type")
   DECLARE_HYDROGEN_ACCESSOR(HasInstanceType)
@@ -833,7 +852,7 @@
 
   DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch,
                                "has-instance-type-and-branch")
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
   virtual bool IsControl() const { return true; }
 
   int true_block_id() const { return true_block_id_; }
@@ -848,9 +867,9 @@
 };
 
 
-class LHasCachedArrayIndex: public LUnaryOperation {
+class LHasCachedArrayIndex: public LUnaryOperation<1> {
  public:
-  explicit LHasCachedArrayIndex(LOperand* value) : LUnaryOperation(value) {}
+  explicit LHasCachedArrayIndex(LOperand* value) : LUnaryOperation<1>(value) {}
 
   DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndex, "has-cached-array-index")
   DECLARE_HYDROGEN_ACCESSOR(HasCachedArrayIndex)
@@ -868,7 +887,7 @@
 
   DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch,
                                "has-cached-array-index-and-branch")
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
   virtual bool IsControl() const { return true; }
 
   int true_block_id() const { return true_block_id_; }
@@ -880,20 +899,20 @@
 };
 
 
-class LClassOfTest: public LUnaryOperation {
+class LClassOfTest: public LUnaryOperation<1> {
  public:
   LClassOfTest(LOperand* value, LOperand* temp)
-      : LUnaryOperation(value), temporary_(temp) {}
+      : LUnaryOperation<1>(value), temporary_(temp) {}
 
   DECLARE_CONCRETE_INSTRUCTION(ClassOfTest, "class-of-test")
   DECLARE_HYDROGEN_ACCESSOR(ClassOfTest)
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   LOperand* temporary() { return temporary_; }
 
  private:
-  LOperand *temporary_;
+  LOperand* temporary_;
 };
 
 
@@ -911,7 +930,7 @@
 
   DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch,
                                "class-of-test-and-branch")
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
   virtual bool IsControl() const { return true; }
 
   int true_block_id() const { return true_block_id_; }
@@ -925,9 +944,9 @@
 };
 
 
-class LCmpT: public LBinaryOperation {
+class LCmpT: public LBinaryOperation<1> {
  public:
-  LCmpT(LOperand* left, LOperand* right) : LBinaryOperation(left, right) {}
+  LCmpT(LOperand* left, LOperand* right) : LBinaryOperation<1>(left, right) {}
 
   DECLARE_CONCRETE_INSTRUCTION(CmpT, "cmp-t")
   DECLARE_HYDROGEN_ACCESSOR(Compare)
@@ -957,10 +976,10 @@
 };
 
 
-class LInstanceOf: public LBinaryOperation {
+class LInstanceOf: public LBinaryOperation<1> {
  public:
   LInstanceOf(LOperand* left, LOperand* right)
-      : LBinaryOperation(left, right) { }
+      : LBinaryOperation<1>(left, right) { }
 
   DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
 };
@@ -987,10 +1006,10 @@
 };
 
 
-class LInstanceOfKnownGlobal: public LUnaryOperation {
+class LInstanceOfKnownGlobal: public LUnaryOperation<1> {
  public:
   LInstanceOfKnownGlobal(LOperand* left, LOperand* temp)
-      : LUnaryOperation(left), temp_(temp) { }
+      : LUnaryOperation<1>(left), temp_(temp) { }
 
   DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
                                "instance-of-known-global")
@@ -1004,10 +1023,10 @@
 };
 
 
-class LBoundsCheck: public LBinaryOperation {
+class LBoundsCheck: public LBinaryOperation<0> {
  public:
   LBoundsCheck(LOperand* index, LOperand* length)
-      : LBinaryOperation(index, length) { }
+      : LBinaryOperation<0>(index, length) { }
 
   LOperand* index() const { return left(); }
   LOperand* length() const { return right(); }
@@ -1016,10 +1035,10 @@
 };
 
 
-class LBitI: public LBinaryOperation {
+class LBitI: public LBinaryOperation<1> {
  public:
   LBitI(Token::Value op, LOperand* left, LOperand* right)
-      : LBinaryOperation(left, right), op_(op) { }
+      : LBinaryOperation<1>(left, right), op_(op) { }
 
   Token::Value op() const { return op_; }
 
@@ -1030,10 +1049,10 @@
 };
 
 
-class LShiftI: public LBinaryOperation {
+class LShiftI: public LBinaryOperation<1> {
  public:
   LShiftI(Token::Value op, LOperand* left, LOperand* right, bool can_deopt)
-      : LBinaryOperation(left, right), op_(op), can_deopt_(can_deopt) { }
+      : LBinaryOperation<1>(left, right), op_(op), can_deopt_(can_deopt) { }
 
   Token::Value op() const { return op_; }
 
@@ -1047,17 +1066,17 @@
 };
 
 
-class LSubI: public LBinaryOperation {
+class LSubI: public LBinaryOperation<1> {
  public:
   LSubI(LOperand* left, LOperand* right)
-      : LBinaryOperation(left, right) { }
+      : LBinaryOperation<1>(left, right) { }
 
   DECLARE_CONCRETE_INSTRUCTION(SubI, "sub-i")
   DECLARE_HYDROGEN_ACCESSOR(Sub)
 };
 
 
-class LConstant: public LInstruction {
+class LConstant: public LTemplateInstruction<1, 0, 0> {
   DECLARE_INSTRUCTION(Constant)
 };
 
@@ -1098,17 +1117,17 @@
 };
 
 
-class LBranch: public LUnaryOperation {
+class LBranch: public LUnaryOperation<0> {
  public:
   LBranch(LOperand* input, int true_block_id, int false_block_id)
-      : LUnaryOperation(input),
+      : LUnaryOperation<0>(input),
         true_block_id_(true_block_id),
         false_block_id_(false_block_id) { }
 
   DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
   DECLARE_HYDROGEN_ACCESSOR(Value)
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
   virtual bool IsControl() const { return true; }
 
   int true_block_id() const { return true_block_id_; }
@@ -1120,9 +1139,9 @@
 };
 
 
-class LCmpMapAndBranch: public LUnaryOperation {
+class LCmpMapAndBranch: public LUnaryOperation<0> {
  public:
-  explicit LCmpMapAndBranch(LOperand* value) : LUnaryOperation(value) { }
+  explicit LCmpMapAndBranch(LOperand* value) : LUnaryOperation<0>(value) { }
 
   DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
   DECLARE_HYDROGEN_ACCESSOR(CompareMapAndBranch)
@@ -1139,28 +1158,28 @@
 };
 
 
-class LJSArrayLength: public LUnaryOperation {
+class LJSArrayLength: public LUnaryOperation<1> {
  public:
-  explicit LJSArrayLength(LOperand* input) : LUnaryOperation(input) { }
+  explicit LJSArrayLength(LOperand* input) : LUnaryOperation<1>(input) { }
 
   DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js-array-length")
   DECLARE_HYDROGEN_ACCESSOR(JSArrayLength)
 };
 
 
-class LFixedArrayLength: public LUnaryOperation {
+class LFixedArrayLength: public LUnaryOperation<1> {
  public:
-  explicit LFixedArrayLength(LOperand* input) : LUnaryOperation(input) { }
+  explicit LFixedArrayLength(LOperand* input) : LUnaryOperation<1>(input) { }
 
   DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed-array-length")
   DECLARE_HYDROGEN_ACCESSOR(FixedArrayLength)
 };
 
 
-class LValueOf: public LUnaryOperation {
+class LValueOf: public LUnaryOperation<1> {
  public:
   LValueOf(LOperand* input, LOperand* temporary)
-      : LUnaryOperation(input), temporary_(temporary) { }
+      : LUnaryOperation<1>(input), temporary_(temporary) { }
 
   LOperand* temporary() const { return temporary_; }
 
@@ -1172,46 +1191,46 @@
 };
 
 
-class LThrow: public LUnaryOperation {
+class LThrow: public LUnaryOperation<0> {
  public:
-  explicit LThrow(LOperand* value) : LUnaryOperation(value) { }
+  explicit LThrow(LOperand* value) : LUnaryOperation<0>(value) { }
 
   DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
 };
 
 
-class LBitNotI: public LUnaryOperation {
+class LBitNotI: public LUnaryOperation<1> {
  public:
-  explicit LBitNotI(LOperand* use) : LUnaryOperation(use) { }
+  explicit LBitNotI(LOperand* input) : LUnaryOperation<1>(input) { }
 
   DECLARE_CONCRETE_INSTRUCTION(BitNotI, "bit-not-i")
 };
 
 
-class LAddI: public LBinaryOperation {
+class LAddI: public LBinaryOperation<1> {
  public:
   LAddI(LOperand* left, LOperand* right)
-      : LBinaryOperation(left, right) { }
+      : LBinaryOperation<1>(left, right) { }
 
   DECLARE_CONCRETE_INSTRUCTION(AddI, "add-i")
   DECLARE_HYDROGEN_ACCESSOR(Add)
 };
 
 
-class LPower: public LBinaryOperation {
+class LPower: public LBinaryOperation<1> {
  public:
   LPower(LOperand* left, LOperand* right)
-      : LBinaryOperation(left, right) { }
+      : LBinaryOperation<1>(left, right) { }
 
   DECLARE_CONCRETE_INSTRUCTION(Power, "power")
   DECLARE_HYDROGEN_ACCESSOR(Power)
 };
 
 
-class LArithmeticD: public LBinaryOperation {
+class LArithmeticD: public LBinaryOperation<1> {
  public:
   LArithmeticD(Token::Value op, LOperand* left, LOperand* right)
-      : LBinaryOperation(left, right), op_(op) { }
+      : LBinaryOperation<1>(left, right), op_(op) { }
 
   Token::Value op() const { return op_; }
 
@@ -1223,10 +1242,10 @@
 };
 
 
-class LArithmeticT: public LBinaryOperation {
+class LArithmeticT: public LBinaryOperation<1> {
  public:
   LArithmeticT(Token::Value op, LOperand* left, LOperand* right)
-      : LBinaryOperation(left, right), op_(op) { }
+      : LBinaryOperation<1>(left, right), op_(op) { }
 
   virtual void CompileToNative(LCodeGen* generator);
   virtual const char* Mnemonic() const;
@@ -1238,26 +1257,26 @@
 };
 
 
-class LReturn: public LUnaryOperation {
+class LReturn: public LUnaryOperation<0> {
  public:
-  explicit LReturn(LOperand* use) : LUnaryOperation(use) { }
+  explicit LReturn(LOperand* use) : LUnaryOperation<0>(use) { }
 
   DECLARE_CONCRETE_INSTRUCTION(Return, "return")
 };
 
 
-class LLoadNamedField: public LUnaryOperation {
+class LLoadNamedField: public LUnaryOperation<1> {
  public:
-  explicit LLoadNamedField(LOperand* object) : LUnaryOperation(object) { }
+  explicit LLoadNamedField(LOperand* object) : LUnaryOperation<1>(object) { }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field")
   DECLARE_HYDROGEN_ACCESSOR(LoadNamedField)
 };
 
 
-class LLoadNamedGeneric: public LUnaryOperation {
+class LLoadNamedGeneric: public LUnaryOperation<1> {
  public:
-  explicit LLoadNamedGeneric(LOperand* object) : LUnaryOperation(object) { }
+  explicit LLoadNamedGeneric(LOperand* object) : LUnaryOperation<1>(object) { }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic")
   DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric)
@@ -1267,10 +1286,10 @@
 };
 
 
-class LLoadFunctionPrototype: public LUnaryOperation {
+class LLoadFunctionPrototype: public LUnaryOperation<1> {
  public:
   LLoadFunctionPrototype(LOperand* function, LOperand* temporary)
-      : LUnaryOperation(function), temporary_(temporary) { }
+      : LUnaryOperation<1>(function), temporary_(temporary) { }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
   DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
@@ -1283,38 +1302,31 @@
 };
 
 
-class LLoadElements: public LUnaryOperation {
+class LLoadElements: public LUnaryOperation<1> {
  public:
-  explicit LLoadElements(LOperand* obj) : LUnaryOperation(obj) { }
+  explicit LLoadElements(LOperand* obj) : LUnaryOperation<1>(obj) { }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements")
 };
 
 
-class LLoadKeyedFastElement: public LBinaryOperation {
+class LLoadKeyedFastElement: public LBinaryOperation<1> {
  public:
-  LLoadKeyedFastElement(LOperand* elements,
-                        LOperand* key,
-                        LOperand* load_result)
-      : LBinaryOperation(elements, key),
-        load_result_(load_result) { }
+  LLoadKeyedFastElement(LOperand* elements, LOperand* key)
+      : LBinaryOperation<1>(elements, key) { }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement, "load-keyed-fast-element")
   DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastElement)
 
   LOperand* elements() const { return left(); }
   LOperand* key() const { return right(); }
-  LOperand* load_result() const { return load_result_; }
-
- private:
-  LOperand* load_result_;
 };
 
 
-class LLoadKeyedGeneric: public LBinaryOperation {
+class LLoadKeyedGeneric: public LBinaryOperation<1> {
  public:
   LLoadKeyedGeneric(LOperand* obj, LOperand* key)
-      : LBinaryOperation(obj, key) { }
+      : LBinaryOperation<1>(obj, key) { }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic")
 
@@ -1323,78 +1335,92 @@
 };
 
 
-class LLoadGlobal: public LInstruction {
+class LLoadGlobal: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(LoadGlobal, "load-global")
   DECLARE_HYDROGEN_ACCESSOR(LoadGlobal)
 };
 
 
-class LStoreGlobal: public LUnaryOperation {
+class LStoreGlobal: public LUnaryOperation<0> {
  public:
-  explicit LStoreGlobal(LOperand* value) : LUnaryOperation(value) {}
+  explicit LStoreGlobal(LOperand* value) : LUnaryOperation<0>(value) {}
 
   DECLARE_CONCRETE_INSTRUCTION(StoreGlobal, "store-global")
   DECLARE_HYDROGEN_ACCESSOR(StoreGlobal)
 };
 
 
-class LPushArgument: public LUnaryOperation {
+class LLoadContextSlot: public LTemplateInstruction<1, 0, 0> {
  public:
-  explicit LPushArgument(LOperand* argument) : LUnaryOperation(argument) {}
+  DECLARE_CONCRETE_INSTRUCTION(LoadContextSlot, "load-context-slot")
+  DECLARE_HYDROGEN_ACCESSOR(LoadContextSlot)
+
+  int context_chain_length() const {
+    return hydrogen()->context_chain_length();
+  }
+  int slot_index() const { return hydrogen()->slot_index(); }
+
+  virtual void PrintDataTo(StringStream* stream);
+};
+
+
+class LPushArgument: public LUnaryOperation<0> {
+ public:
+  explicit LPushArgument(LOperand* argument) : LUnaryOperation<0>(argument) {}
 
   DECLARE_CONCRETE_INSTRUCTION(PushArgument, "push-argument")
 };
 
 
-class LGlobalObject: public LInstruction {
+class LGlobalObject: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object")
 };
 
 
-class LGlobalReceiver: public LInstruction {
+class LGlobalReceiver: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(GlobalReceiver, "global-receiver")
 };
 
 
-class LCallConstantFunction: public LInstruction {
+class LCallConstantFunction: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call-constant-function")
   DECLARE_HYDROGEN_ACCESSOR(CallConstantFunction)
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
-  Handle<JSFunction> function() const { return hydrogen()->function(); }
+  Handle<JSFunction> function() { return hydrogen()->function(); }
   int arity() const { return hydrogen()->argument_count() - 1; }
 };
 
 
-class LCallKeyed: public LInstruction {
+class LCallKeyed: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call-keyed")
   DECLARE_HYDROGEN_ACCESSOR(CallKeyed)
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   int arity() const { return hydrogen()->argument_count() - 1; }
 };
 
 
-class LCallNamed: public LInstruction {
+class LCallNamed: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call-named")
   DECLARE_HYDROGEN_ACCESSOR(CallNamed)
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   Handle<String> name() const { return hydrogen()->name(); }
   int arity() const { return hydrogen()->argument_count() - 1; }
 };
 
 
-class LCallFunction: public LInstruction {
+class LCallFunction: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(CallFunction, "call-function")
   DECLARE_HYDROGEN_ACCESSOR(CallFunction)
@@ -1403,44 +1429,44 @@
 };
 
 
-class LCallGlobal: public LInstruction {
+class LCallGlobal: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call-global")
   DECLARE_HYDROGEN_ACCESSOR(CallGlobal)
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   Handle<String> name() const {return hydrogen()->name(); }
   int arity() const { return hydrogen()->argument_count() - 1; }
 };
 
 
-class LCallKnownGlobal: public LInstruction {
+class LCallKnownGlobal: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call-known-global")
   DECLARE_HYDROGEN_ACCESSOR(CallKnownGlobal)
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   Handle<JSFunction> target() const { return hydrogen()->target();  }
   int arity() const { return hydrogen()->argument_count() - 1;  }
 };
 
 
-class LCallNew: public LUnaryOperation {
+class LCallNew: public LUnaryOperation<1> {
  public:
-  explicit LCallNew(LOperand* constructor) : LUnaryOperation(constructor) { }
+  explicit LCallNew(LOperand* constructor) : LUnaryOperation<1>(constructor) { }
 
   DECLARE_CONCRETE_INSTRUCTION(CallNew, "call-new")
   DECLARE_HYDROGEN_ACCESSOR(CallNew)
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
   int arity() const { return hydrogen()->argument_count() - 1; }
 };
 
 
-class LCallRuntime: public LInstruction {
+class LCallRuntime: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
   DECLARE_HYDROGEN_ACCESSOR(CallRuntime)
@@ -1450,26 +1476,26 @@
 };
 
 
-class LInteger32ToDouble: public LUnaryOperation {
+class LInteger32ToDouble: public LUnaryOperation<1> {
  public:
-  explicit LInteger32ToDouble(LOperand* use) : LUnaryOperation(use) { }
+  explicit LInteger32ToDouble(LOperand* use) : LUnaryOperation<1>(use) { }
 
   DECLARE_CONCRETE_INSTRUCTION(Integer32ToDouble, "int32-to-double")
 };
 
 
-class LNumberTagI: public LUnaryOperation {
+class LNumberTagI: public LUnaryOperation<1> {
  public:
-  explicit LNumberTagI(LOperand* use) : LUnaryOperation(use) { }
+  explicit LNumberTagI(LOperand* use) : LUnaryOperation<1>(use) { }
 
   DECLARE_CONCRETE_INSTRUCTION(NumberTagI, "number-tag-i")
 };
 
 
-class LNumberTagD: public LUnaryOperation {
+class LNumberTagD: public LUnaryOperation<1> {
  public:
   explicit LNumberTagD(LOperand* value, LOperand* temp)
-      : LUnaryOperation(value), temp_(temp) { }
+      : LUnaryOperation<1>(value), temp_(temp) { }
 
   DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d")
 
@@ -1481,22 +1507,27 @@
 
 
 // Sometimes truncating conversion from a tagged value to an int32.
-class LDoubleToI: public LUnaryOperation {
+class LDoubleToI: public LUnaryOperation<1> {
  public:
-  explicit LDoubleToI(LOperand* value) : LUnaryOperation(value) { }
+  LDoubleToI(LOperand* value, LOperand* temporary)
+      : LUnaryOperation<1>(value), temporary_(temporary) { }
 
   DECLARE_CONCRETE_INSTRUCTION(DoubleToI, "double-to-i")
   DECLARE_HYDROGEN_ACCESSOR(Change)
 
   bool truncating() { return hydrogen()->CanTruncateToInt32(); }
+  LOperand* temporary() const { return temporary_; }
+
+ private:
+  LOperand* temporary_;
 };
 
 
 // Truncating conversion from a tagged value to an int32.
-class LTaggedToI: public LUnaryOperation {
+class LTaggedToI: public LUnaryOperation<1> {
  public:
   LTaggedToI(LOperand* value, LOperand* temp)
-      : LUnaryOperation(value), temp_(temp) { }
+      : LUnaryOperation<1>(value), temp_(temp) { }
 
   DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i")
   DECLARE_HYDROGEN_ACCESSOR(Change)
@@ -1509,26 +1540,26 @@
 };
 
 
-class LSmiTag: public LUnaryOperation {
+class LSmiTag: public LUnaryOperation<1> {
  public:
-  explicit LSmiTag(LOperand* use) : LUnaryOperation(use) { }
+  explicit LSmiTag(LOperand* use) : LUnaryOperation<1>(use) { }
 
   DECLARE_CONCRETE_INSTRUCTION(SmiTag, "smi-tag")
 };
 
 
-class LNumberUntagD: public LUnaryOperation {
+class LNumberUntagD: public LUnaryOperation<1> {
  public:
-  explicit LNumberUntagD(LOperand* value) : LUnaryOperation(value) { }
+  explicit LNumberUntagD(LOperand* value) : LUnaryOperation<1>(value) { }
 
   DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag")
 };
 
 
-class LSmiUntag: public LUnaryOperation {
+class LSmiUntag: public LUnaryOperation<1> {
  public:
   LSmiUntag(LOperand* use, bool needs_check)
-      : LUnaryOperation(use), needs_check_(needs_check) { }
+      : LUnaryOperation<1>(use), needs_check_(needs_check) { }
 
   DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
 
@@ -1539,89 +1570,69 @@
 };
 
 
-class LStoreNamed: public LInstruction {
+class LStoreNamed: public LTemplateInstruction<0, 2, 0> {
  public:
-  LStoreNamed(LOperand* obj, Handle<Object> name, LOperand* val)
-      : object_(obj), name_(name), value_(val) { }
+  LStoreNamed(LOperand* obj, LOperand* val) {
+    this->SetInputAt(0, obj);
+    this->SetInputAt(1, val);
+  }
 
   DECLARE_INSTRUCTION(StoreNamed)
+  DECLARE_HYDROGEN_ACCESSOR(StoreNamed)
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
-  LOperand* object() const { return object_; }
-  Handle<Object> name() const { return name_; }
-  LOperand* value() const { return value_; }
-
- private:
-  LOperand* object_;
-  Handle<Object> name_;
-  LOperand* value_;
+  LOperand* object() const { return this->InputAt(0); }
+  LOperand* value() const { return this->InputAt(1); }
+  Handle<Object> name() const { return hydrogen()->name(); }
 };
 
 
 class LStoreNamedField: public LStoreNamed {
  public:
-  LStoreNamedField(LOperand* obj,
-                   Handle<Object> name,
-                   LOperand* val,
-                   bool in_object,
-                   int offset,
-                   LOperand* temp,
-                   bool needs_write_barrier,
-                   Handle<Map> transition)
-      : LStoreNamed(obj, name, val),
-        is_in_object_(in_object),
-        offset_(offset),
-        temp_(temp),
-        needs_write_barrier_(needs_write_barrier),
-        transition_(transition) { }
+  LStoreNamedField(LOperand* obj, LOperand* val, LOperand* temp)
+      : LStoreNamed(obj, val), temp_(temp) { }
 
   DECLARE_CONCRETE_INSTRUCTION(StoreNamedField, "store-named-field")
+  DECLARE_HYDROGEN_ACCESSOR(StoreNamedField)
 
-  bool is_in_object() { return is_in_object_; }
-  int offset() { return offset_; }
+  bool is_in_object() { return hydrogen()->is_in_object(); }
+  int offset() { return hydrogen()->offset(); }
+  bool needs_write_barrier() { return hydrogen()->NeedsWriteBarrier(); }
+  Handle<Map> transition() const { return hydrogen()->transition(); }
+
   LOperand* temp() { return temp_; }
-  bool needs_write_barrier() { return needs_write_barrier_; }
-  Handle<Map> transition() const { return transition_; }
-  void set_transition(Handle<Map> map) { transition_ = map; }
 
  private:
-  bool is_in_object_;
-  int offset_;
   LOperand* temp_;
-  bool needs_write_barrier_;
-  Handle<Map> transition_;
 };
 
 
 class LStoreNamedGeneric: public LStoreNamed {
  public:
-  LStoreNamedGeneric(LOperand* obj,
-                     Handle<Object> name,
-                     LOperand* val)
-      : LStoreNamed(obj, name, val) { }
+  LStoreNamedGeneric(LOperand* obj, LOperand* val)
+      : LStoreNamed(obj, val) { }
 
   DECLARE_CONCRETE_INSTRUCTION(StoreNamedGeneric, "store-named-generic")
+  DECLARE_HYDROGEN_ACCESSOR(StoreNamedGeneric)
 };
 
 
-class LStoreKeyed: public LInstruction {
+class LStoreKeyed: public LTemplateInstruction<0, 3, 0> {
  public:
-  LStoreKeyed(LOperand* obj, LOperand* key, LOperand* val)
-      : object_(obj), key_(key), value_(val) { }
+  LStoreKeyed(LOperand* obj, LOperand* key, LOperand* val) {
+    this->SetInputAt(0, obj);
+    this->SetInputAt(1, key);
+    this->SetInputAt(2, val);
+  }
 
   DECLARE_INSTRUCTION(StoreKeyed)
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 
-  LOperand* object() const { return object_; }
-  LOperand* key() const { return key_; }
-  LOperand* value() const { return value_; }
-
- private:
-  LOperand* object_;
-  LOperand* key_;
-  LOperand* value_;
+  LOperand* object() const { return this->InputAt(0); }
+  LOperand* key() const { return this->InputAt(1); }
+  LOperand* value() const { return this->InputAt(2); }
 };
 
 
@@ -1645,19 +1656,19 @@
 };
 
 
-class LCheckFunction: public LUnaryOperation {
+class LCheckFunction: public LUnaryOperation<0> {
  public:
-  explicit LCheckFunction(LOperand* use) : LUnaryOperation(use) { }
+  explicit LCheckFunction(LOperand* use) : LUnaryOperation<0>(use) { }
 
   DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check-function")
   DECLARE_HYDROGEN_ACCESSOR(CheckFunction)
 };
 
 
-class LCheckInstanceType: public LUnaryOperation {
+class LCheckInstanceType: public LUnaryOperation<0> {
  public:
   LCheckInstanceType(LOperand* use, LOperand* temp)
-      : LUnaryOperation(use), temp_(temp) { }
+      : LUnaryOperation<0>(use), temp_(temp) { }
 
   DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check-instance-type")
   DECLARE_HYDROGEN_ACCESSOR(CheckInstanceType)
@@ -1669,41 +1680,36 @@
 };
 
 
-class LCheckMap: public LUnaryOperation {
+class LCheckMap: public LUnaryOperation<0> {
  public:
-  explicit LCheckMap(LOperand* use) : LUnaryOperation(use) { }
+  explicit LCheckMap(LOperand* use) : LUnaryOperation<0>(use) { }
 
   DECLARE_CONCRETE_INSTRUCTION(CheckMap, "check-map")
   DECLARE_HYDROGEN_ACCESSOR(CheckMap)
 };
 
 
-class LCheckPrototypeMaps: public LInstruction {
+class LCheckPrototypeMaps: public LTemplateInstruction<0, 0, 0> {
  public:
-  LCheckPrototypeMaps(LOperand* temp,
-                      Handle<JSObject> holder,
-                      Handle<Map> receiver_map)
-      : temp_(temp),
-        holder_(holder),
-        receiver_map_(receiver_map) { }
+  explicit LCheckPrototypeMaps(LOperand* temp) : temp_(temp) { }
 
   DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check-prototype-maps")
+  DECLARE_HYDROGEN_ACCESSOR(CheckPrototypeMaps)
+
+  Handle<JSObject> prototype() const { return hydrogen()->prototype(); }
+  Handle<JSObject> holder() const { return hydrogen()->holder(); }
 
   LOperand* temp() const { return temp_; }
-  Handle<JSObject> holder() const { return holder_; }
-  Handle<Map> receiver_map() const { return receiver_map_; }
 
  private:
   LOperand* temp_;
-  Handle<JSObject> holder_;
-  Handle<Map> receiver_map_;
 };
 
 
-class LCheckSmi: public LUnaryOperation {
+class LCheckSmi: public LUnaryOperation<0> {
  public:
   LCheckSmi(LOperand* use, Condition condition)
-      : LUnaryOperation(use), condition_(condition) { }
+      : LUnaryOperation<0>(use), condition_(condition) { }
 
   Condition condition() const { return condition_; }
 
@@ -1717,7 +1723,7 @@
 };
 
 
-class LMaterializedLiteral: public LInstruction {
+class LMaterializedLiteral: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_INSTRUCTION(MaterializedLiteral)
 };
@@ -1744,7 +1750,7 @@
 };
 
 
-class LFunctionLiteral: public LInstruction {
+class LFunctionLiteral: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function-literal")
   DECLARE_HYDROGEN_ACCESSOR(FunctionLiteral)
@@ -1753,18 +1759,18 @@
 };
 
 
-class LTypeof: public LUnaryOperation {
+class LTypeof: public LUnaryOperation<1> {
  public:
-  explicit LTypeof(LOperand* input) : LUnaryOperation(input) { }
+  explicit LTypeof(LOperand* input) : LUnaryOperation<1>(input) { }
 
   DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
 };
 
 
-class LTypeofIs: public LUnaryOperation {
+class LTypeofIs: public LUnaryOperation<1> {
  public:
-  explicit LTypeofIs(LOperand* input) : LUnaryOperation(input) { }
-  virtual void PrintDataTo(StringStream* stream) const;
+  explicit LTypeofIs(LOperand* input) : LUnaryOperation<1>(input) { }
+  virtual void PrintDataTo(StringStream* stream);
 
   DECLARE_CONCRETE_INSTRUCTION(TypeofIs, "typeof-is")
   DECLARE_HYDROGEN_ACCESSOR(TypeofIs)
@@ -1784,7 +1790,7 @@
 
   DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch, "typeof-is-and-branch")
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
   virtual bool IsControl() const { return true; }
 
   int true_block_id() const { return true_block_id_; }
@@ -1796,9 +1802,10 @@
 };
 
 
-class LDeleteProperty: public LBinaryOperation {
+class LDeleteProperty: public LBinaryOperation<1> {
  public:
-  LDeleteProperty(LOperand* obj, LOperand* key) : LBinaryOperation(obj, key) {}
+  LDeleteProperty(LOperand* obj, LOperand* key)
+      : LBinaryOperation<1>(obj, key) { }
 
   DECLARE_CONCRETE_INSTRUCTION(DeleteProperty, "delete-property")
 
@@ -1807,7 +1814,7 @@
 };
 
 
-class LOsrEntry: public LInstruction {
+class LOsrEntry: public LTemplateInstruction<0, 0, 0> {
  public:
   LOsrEntry();
 
@@ -1830,114 +1837,12 @@
 };
 
 
-class LStackCheck: public LInstruction {
+class LStackCheck: public LTemplateInstruction<0, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check")
 };
 
 
-class LPointerMap: public ZoneObject {
- public:
-  explicit LPointerMap(int position)
-      : pointer_operands_(8), position_(position), lithium_position_(-1) { }
-
-  const ZoneList<LOperand*>* operands() const { return &pointer_operands_; }
-  int position() const { return position_; }
-  int lithium_position() const { return lithium_position_; }
-
-  void set_lithium_position(int pos) {
-    ASSERT(lithium_position_ == -1);
-    lithium_position_ = pos;
-  }
-
-  void RecordPointer(LOperand* op);
-  void PrintTo(StringStream* stream) const;
-
- private:
-  ZoneList<LOperand*> pointer_operands_;
-  int position_;
-  int lithium_position_;
-};
-
-
-class LEnvironment: public ZoneObject {
- public:
-  LEnvironment(Handle<JSFunction> closure,
-               int ast_id,
-               int parameter_count,
-               int argument_count,
-               int value_count,
-               LEnvironment* outer)
-      : closure_(closure),
-        arguments_stack_height_(argument_count),
-        deoptimization_index_(Safepoint::kNoDeoptimizationIndex),
-        translation_index_(-1),
-        ast_id_(ast_id),
-        parameter_count_(parameter_count),
-        values_(value_count),
-        representations_(value_count),
-        spilled_registers_(NULL),
-        spilled_double_registers_(NULL),
-        outer_(outer) {
-  }
-
-  Handle<JSFunction> closure() const { return closure_; }
-  int arguments_stack_height() const { return arguments_stack_height_; }
-  int deoptimization_index() const { return deoptimization_index_; }
-  int translation_index() const { return translation_index_; }
-  int ast_id() const { return ast_id_; }
-  int parameter_count() const { return parameter_count_; }
-  const ZoneList<LOperand*>* values() const { return &values_; }
-  LEnvironment* outer() const { return outer_; }
-
-  void AddValue(LOperand* operand, Representation representation) {
-    values_.Add(operand);
-    representations_.Add(representation);
-  }
-
-  bool HasTaggedValueAt(int index) const {
-    return representations_[index].IsTagged();
-  }
-
-  void Register(int deoptimization_index, int translation_index) {
-    ASSERT(!HasBeenRegistered());
-    deoptimization_index_ = deoptimization_index;
-    translation_index_ = translation_index;
-  }
-  bool HasBeenRegistered() const {
-    return deoptimization_index_ != Safepoint::kNoDeoptimizationIndex;
-  }
-
-  void SetSpilledRegisters(LOperand** registers,
-                           LOperand** double_registers) {
-    spilled_registers_ = registers;
-    spilled_double_registers_ = double_registers;
-  }
-
-  // Emit frame translation commands for this environment.
-  void WriteTranslation(LCodeGen* cgen, Translation* translation) const;
-
-  void PrintTo(StringStream* stream) const;
-
- private:
-  Handle<JSFunction> closure_;
-  int arguments_stack_height_;
-  int deoptimization_index_;
-  int translation_index_;
-  int ast_id_;
-  int parameter_count_;
-  ZoneList<LOperand*> values_;
-  ZoneList<Representation> representations_;
-
-  // Allocation index indexed arrays of spill slot operands for registers
-  // that are also in spill slots at an OSR entry.  NULL for environments
-  // that do not correspond to an OSR entry.
-  LOperand** spilled_registers_;
-  LOperand** spilled_double_registers_;
-
-  LEnvironment* outer_;
-};
-
 class LChunkBuilder;
 class LChunk: public ZoneObject {
  public:
@@ -1993,8 +1898,6 @@
     inlined_closures_.Add(closure);
   }
 
-  void Verify() const;
-
  private:
   int spill_slot_count_;
   HGraph* const graph_;
@@ -2077,13 +1980,24 @@
 
   // Methods for setting up define-use relationships.
   // Return the same instruction that they are passed.
-  LInstruction* Define(LInstruction* instr, LUnallocated* result);
-  LInstruction* Define(LInstruction* instr);
-  LInstruction* DefineAsRegister(LInstruction* instr);
-  LInstruction* DefineAsSpilled(LInstruction* instr, int index);
-  LInstruction* DefineSameAsFirst(LInstruction* instr);
-  LInstruction* DefineFixed(LInstruction* instr, Register reg);
-  LInstruction* DefineFixedDouble(LInstruction* instr, XMMRegister reg);
+  template<int I, int T>
+      LInstruction* Define(LTemplateInstruction<1, I, T>* instr,
+                           LUnallocated* result);
+  template<int I, int T>
+      LInstruction* Define(LTemplateInstruction<1, I, T>* instr);
+  template<int I, int T>
+      LInstruction* DefineAsRegister(LTemplateInstruction<1, I, T>* instr);
+  template<int I, int T>
+      LInstruction* DefineAsSpilled(LTemplateInstruction<1, I, T>* instr,
+                                    int index);
+  template<int I, int T>
+      LInstruction* DefineSameAsFirst(LTemplateInstruction<1, I, T>* instr);
+  template<int I, int T>
+      LInstruction* DefineFixed(LTemplateInstruction<1, I, T>* instr,
+                                Register reg);
+  template<int I, int T>
+      LInstruction* DefineFixedDouble(LTemplateInstruction<1, I, T>* instr,
+                                      XMMRegister reg);
   LInstruction* AssignEnvironment(LInstruction* instr);
   LInstruction* AssignPointerMap(LInstruction* instr);
 
@@ -2104,8 +2018,6 @@
 
   LEnvironment* CreateEnvironment(HEnvironment* hydrogen_env);
 
-  // Temporary operand that may be a memory location.
-  LOperand* Temp();
   // Temporary operand that must be in a register.
   LUnallocated* TempRegister();
   LOperand* FixedTemp(Register reg);