Port lithium template classes to ARM.
authorfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 24 Jan 2011 09:43:14 +0000 (09:43 +0000)
committerfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 24 Jan 2011 09:43:14 +0000 (09:43 +0000)
This is a port of the IA32 version and is needed to allow
changing the register allocator interface in a later change.

Review URL: http://codereview.chromium.org/6250027

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6436 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/arm/lithium-arm.cc
src/arm/lithium-arm.h
src/arm/lithium-codegen-arm.cc
src/arm/lithium-codegen-arm.h
src/ia32/lithium-ia32.cc
src/ia32/lithium-ia32.h
src/x64/lithium-x64.cc
src/x64/lithium-x64.h

index 8d839ca..c484e39 100644 (file)
@@ -64,12 +64,12 @@ void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index,
 }
 
 
-void LInstruction::PrintTo(StringStream* stream) const {
+void LInstruction::PrintTo(StringStream* stream) {
   stream->Add("%s ", this->Mnemonic());
   if (HasResult()) {
-    result()->PrintTo(stream);
-    stream->Add(" ");
+    PrintOutputOperandTo(stream);
   }
+
   PrintDataTo(stream);
 
   if (HasEnvironment()) {
@@ -84,7 +84,29 @@ void LInstruction::PrintTo(StringStream* stream) const {
 }
 
 
-void LLabel::PrintDataTo(StringStream* stream) const {
+template<int R, int I, int T>
+void LTemplateInstruction<R, I, T>::PrintDataTo(StringStream* stream) {
+  stream->Add("= ");
+  inputs_.PrintOperandsTo(stream);
+}
+
+
+template<int R, int I, int T>
+void LTemplateInstruction<R, I, T>::PrintOutputOperandTo(StringStream* stream) {
+  results_.PrintOperandsTo(stream);
+}
+
+
+template<typename T, int N>
+void OperandContainer<T, N>::PrintOperandsTo(StringStream* stream) {
+  for (int i = 0; i < N; i++) {
+    if (i > 0) stream->Add(" ");
+    elems_[i]->PrintTo(stream);
+  }
+}
+
+
+void LLabel::PrintDataTo(StringStream* stream) {
   LGap::PrintDataTo(stream);
   LLabel* rep = replacement();
   if (rep != NULL) {
@@ -143,74 +165,65 @@ const char* LArithmeticT::Mnemonic() const {
 }
 
 
-
-void LBinaryOperation::PrintDataTo(StringStream* stream) const {
-  stream->Add("= ");
-  left()->PrintTo(stream);
-  stream->Add(" ");
-  right()->PrintTo(stream);
-}
-
-
-void LGoto::PrintDataTo(StringStream* stream) const {
+void LGoto::PrintDataTo(StringStream* stream) {
   stream->Add("B%d", block_id());
 }
 
 
-void LBranch::PrintDataTo(StringStream* stream) const {
+void LBranch::PrintDataTo(StringStream* stream) {
   stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
-  input()->PrintTo(stream);
+  InputAt(0)->PrintTo(stream);
 }
 
 
-void LCmpIDAndBranch::PrintDataTo(StringStream* stream) const {
+void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
   stream->Add("if ");
-  left()->PrintTo(stream);
+  InputAt(0)->PrintTo(stream);
   stream->Add(" %s ", Token::String(op()));
-  right()->PrintTo(stream);
+  InputAt(1)->PrintTo(stream);
   stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
 }
 
 
-void LIsNullAndBranch::PrintDataTo(StringStream* stream) const {
+void LIsNullAndBranch::PrintDataTo(StringStream* stream) {
   stream->Add("if ");
-  input()->PrintTo(stream);
+  InputAt(0)->PrintTo(stream);
   stream->Add(is_strict() ? " === null" : " == null");
   stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
 }
 
 
-void LIsObjectAndBranch::PrintDataTo(StringStream* stream) const {
+void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
   stream->Add("if is_object(");
-  input()->PrintTo(stream);
+  InputAt(0)->PrintTo(stream);
   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
 }
 
 
-void LIsSmiAndBranch::PrintDataTo(StringStream* stream) const {
+void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
   stream->Add("if is_smi(");
-  input()->PrintTo(stream);
+  InputAt(0)->PrintTo(stream);
   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
 }
 
 
-void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) const {
+void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
   stream->Add("if has_instance_type(");
-  input()->PrintTo(stream);
+  InputAt(0)->PrintTo(stream);
   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
 }
 
 
-void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) const {
+void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
   stream->Add("if has_cached_array_index(");
-  input()->PrintTo(stream);
+  InputAt(0)->PrintTo(stream);
   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
 }
 
 
-void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) const {
+void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
   stream->Add("if class_of_test(");
-  input()->PrintTo(stream);
+  InputAt(0)->PrintTo(stream);
   stream->Add(", \"%o\") then B%d else B%d",
               *hydrogen()->class_name(),
               true_block_id(),
@@ -218,29 +231,29 @@ void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) const {
 }
 
 
-void LTypeofIs::PrintDataTo(StringStream* stream) const {
-  input()->PrintTo(stream);
+void LTypeofIs::PrintDataTo(StringStream* stream) {
+  InputAt(0)->PrintTo(stream);
   stream->Add(" == \"%s\"", *hydrogen()->type_literal()->ToCString());
 }
 
 
-void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) const {
+void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
   stream->Add("if typeof ");
-  input()->PrintTo(stream);
+  InputAt(0)->PrintTo(stream);
   stream->Add(" == \"%s\" then B%d else B%d",
               *hydrogen()->type_literal()->ToCString(),
               true_block_id(), false_block_id());
 }
 
 
-void LCallConstantFunction::PrintDataTo(StringStream* stream) const {
+void LCallConstantFunction::PrintDataTo(StringStream* stream) {
   stream->Add("#%d / ", arity());
 }
 
 
-void LUnaryMathOperation::PrintDataTo(StringStream* stream) const {
+void LUnaryMathOperation::PrintDataTo(StringStream* stream) {
   stream->Add("/%s ", hydrogen()->OpName());
-  input()->PrintTo(stream);
+  InputAt(0)->PrintTo(stream);
 }
 
 
@@ -249,48 +262,43 @@ void LLoadContextSlot::PrintDataTo(StringStream* stream) {
 }
 
 
-void LCallKeyed::PrintDataTo(StringStream* stream) const {
+void LCallKeyed::PrintDataTo(StringStream* stream) {
   stream->Add("[r2] #%d / ", arity());
 }
 
 
-void LCallNamed::PrintDataTo(StringStream* stream) const {
+void LCallNamed::PrintDataTo(StringStream* stream) {
   SmartPointer<char> name_string = name()->ToCString();
   stream->Add("%s #%d / ", *name_string, arity());
 }
 
 
-void LCallGlobal::PrintDataTo(StringStream* stream) const {
+void LCallGlobal::PrintDataTo(StringStream* stream) {
   SmartPointer<char> name_string = name()->ToCString();
   stream->Add("%s #%d / ", *name_string, arity());
 }
 
 
-void LCallKnownGlobal::PrintDataTo(StringStream* stream) const {
+void LCallKnownGlobal::PrintDataTo(StringStream* stream) {
   stream->Add("#%d / ", arity());
 }
 
 
-void LCallNew::PrintDataTo(StringStream* stream) const {
-  LUnaryOperation::PrintDataTo(stream);
+void LCallNew::PrintDataTo(StringStream* stream) {
+  stream->Add("= ");
+  InputAt(0)->PrintTo(stream);
   stream->Add(" #%d / ", arity());
 }
 
 
-void LClassOfTest::PrintDataTo(StringStream* stream) const {
+void LClassOfTest::PrintDataTo(StringStream* stream) {
   stream->Add("= class_of_test(");
-  input()->PrintTo(stream);
+  InputAt(0)->PrintTo(stream);
   stream->Add(", \"%o\")", *hydrogen()->class_name());
 }
 
 
-void LUnaryOperation::PrintDataTo(StringStream* stream) const {
-  stream->Add("= ");
-  input()->PrintTo(stream);
-}
-
-
-void LAccessArgumentsAt::PrintDataTo(StringStream* stream) const {
+void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
   arguments()->PrintTo(stream);
 
   stream->Add(" length ");
@@ -301,6 +309,24 @@ void LAccessArgumentsAt::PrintDataTo(StringStream* stream) const {
 }
 
 
+void LStoreNamed::PrintDataTo(StringStream* stream) {
+  object()->PrintTo(stream);
+  stream->Add(".");
+  stream->Add(*String::cast(*name())->ToCString());
+  stream->Add(" <- ");
+  value()->PrintTo(stream);
+}
+
+
+void LStoreKeyed::PrintDataTo(StringStream* stream) {
+  object()->PrintTo(stream);
+  stream->Add("[");
+  key()->PrintTo(stream);
+  stream->Add("] <- ");
+  value()->PrintTo(stream);
+}
+
+
 LChunk::LChunk(HGraph* graph)
     : spill_slot_count_(0),
       graph_(graph),
@@ -310,11 +336,6 @@ LChunk::LChunk(HGraph* graph)
 }
 
 
-void LChunk::Verify() const {
-  // TODO(twuerthinger): Implement verification for chunk.
-}
-
-
 int LChunk::GetNextSpillIndex(bool is_double) {
   // Skip a slot if for a double-width slot.
   if (is_double) spill_slot_count_++;
@@ -369,24 +390,6 @@ void LChunk::MarkEmptyBlocks() {
 }
 
 
-void LStoreNamed::PrintDataTo(StringStream* stream) const {
-  object()->PrintTo(stream);
-  stream->Add(".");
-  stream->Add(*String::cast(*name())->ToCString());
-  stream->Add(" <- ");
-  value()->PrintTo(stream);
-}
-
-
-void LStoreKeyed::PrintDataTo(StringStream* stream) const {
-  object()->PrintTo(stream);
-  stream->Add("[");
-  key()->PrintTo(stream);
-  stream->Add("] <- ");
-  value()->PrintTo(stream);
-}
-
-
 int LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
   LGap* gap = new LGap(block);
   int index = -1;
@@ -593,33 +596,52 @@ LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
 }
 
 
-LInstruction* LChunkBuilder::Define(LInstruction* instr) {
+template<int I, int T>
+LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
+                                    LUnallocated* result) {
+  allocator_->RecordDefinition(current_instruction_, result);
+  instr->set_result(result);
+  return instr;
+}
+
+
+template<int I, int T>
+LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr) {
   return Define(instr, new LUnallocated(LUnallocated::NONE));
 }
 
 
-LInstruction* LChunkBuilder::DefineAsRegister(LInstruction* instr) {
+template<int I, int T>
+LInstruction* LChunkBuilder::DefineAsRegister(
+    LTemplateInstruction<1, I, T>* instr) {
   return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
 }
 
 
-LInstruction* LChunkBuilder::DefineAsSpilled(LInstruction* instr, int index) {
+template<int I, int T>
+LInstruction* LChunkBuilder::DefineAsSpilled(
+    LTemplateInstruction<1, I, T>* instr, int index) {
   return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index));
 }
 
 
-LInstruction* LChunkBuilder::DefineSameAsFirst(LInstruction* instr) {
+template<int I, int T>
+LInstruction* LChunkBuilder::DefineSameAsFirst(
+    LTemplateInstruction<1, I, T>* instr) {
   return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
 }
 
 
-LInstruction* LChunkBuilder::DefineFixed(LInstruction* instr, Register reg) {
+template<int I, int T>
+LInstruction* LChunkBuilder::DefineFixed(
+    LTemplateInstruction<1, I, T>* instr, Register reg) {
   return Define(instr, ToUnallocated(reg));
 }
 
 
-LInstruction* LChunkBuilder::DefineFixedDouble(LInstruction* instr,
-                                               DoubleRegister reg) {
+template<int I, int T>
+LInstruction* LChunkBuilder::DefineFixedDouble(
+    LTemplateInstruction<1, I, T>* instr, DoubleRegister reg) {
   return Define(instr, ToUnallocated(reg));
 }
 
@@ -687,13 +709,6 @@ LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
 }
 
 
-LInstruction* LChunkBuilder::Define(LInstruction* instr, LUnallocated* result) {
-  allocator_->RecordDefinition(current_instruction_, result);
-  instr->set_result(result);
-  return instr;
-}
-
-
 LUnallocated* LChunkBuilder::TempRegister() {
   LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
   allocator_->RecordTemporary(operand);
@@ -801,7 +816,7 @@ LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
   ASSERT(right->representation().IsTagged());
   LOperand* left_operand = UseFixed(left, r1);
   LOperand* right_operand = UseFixed(right, r0);
-  LInstruction* result = new LArithmeticT(op, left_operand, right_operand);
+  LArithmeticT* result = new LArithmeticT(op, left_operand, right_operand);
   return MarkAsCall(DefineFixed(result, r0), instr);
 }
 
@@ -882,8 +897,14 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
     if (FLAG_stress_environments && !instr->HasEnvironment()) {
       instr = AssignEnvironment(instr);
     }
-    if (current->IsTest()) {
-      instr->set_hydrogen_value(HTest::cast(current)->value());
+    if (current->IsTest() && !instr->IsGoto()) {
+      ASSERT(instr->IsControl());
+      HTest* test = HTest::cast(current);
+      instr->set_hydrogen_value(test->value());
+      HBasicBlock* first = test->FirstSuccessor();
+      HBasicBlock* second = test->SecondSuccessor();
+      ASSERT(first != NULL && second != NULL);
+      instr->SetBranchTargets(first->block_id(), second->block_id());
     } else {
       instr->set_hydrogen_value(current);
     }
@@ -939,21 +960,13 @@ LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
 
 LInstruction* LChunkBuilder::DoTest(HTest* instr) {
   HValue* v = instr->value();
-  HBasicBlock* first = instr->FirstSuccessor();
-  HBasicBlock* second = instr->SecondSuccessor();
-  ASSERT(first != NULL && second != NULL);
-  int first_id = first->block_id();
-  int second_id = second->block_id();
-
   if (v->EmitAtUses()) {
     if (v->IsClassOfTest()) {
       HClassOfTest* compare = HClassOfTest::cast(v);
       ASSERT(compare->value()->representation().IsTagged());
 
       return new LClassOfTestAndBranch(UseTempRegister(compare->value()),
-                                       TempRegister(),
-                                       first_id,
-                                       second_id);
+                                       TempRegister());
     } else if (v->IsCompare()) {
       HCompare* compare = HCompare::cast(v);
       Token::Value op = compare->token();
@@ -964,16 +977,12 @@ LInstruction* LChunkBuilder::DoTest(HTest* instr) {
         ASSERT(left->representation().IsInteger32());
         ASSERT(right->representation().IsInteger32());
         return new LCmpIDAndBranch(UseRegisterAtStart(left),
-                                   UseOrConstantAtStart(right),
-                                   first_id,
-                                   second_id);
+                                   UseOrConstantAtStart(right));
       } else if (r.IsDouble()) {
         ASSERT(left->representation().IsDouble());
         ASSERT(right->representation().IsDouble());
         return new LCmpIDAndBranch(UseRegisterAtStart(left),
-                                   UseRegisterAtStart(right),
-                                   first_id,
-                                   second_id);
+                                   UseRegisterAtStart(right));
       } else {
         ASSERT(left->representation().IsTagged());
         ASSERT(right->representation().IsTagged());
@@ -981,38 +990,30 @@ LInstruction* LChunkBuilder::DoTest(HTest* instr) {
         LOperand* left_operand = UseFixed(left, reversed ? r0 : r1);
         LOperand* right_operand = UseFixed(right, reversed ? r1 : r0);
         LInstruction* result = new LCmpTAndBranch(left_operand,
-                                                  right_operand,
-                                                  first_id,
-                                                  second_id);
+                                                  right_operand);
         return MarkAsCall(result, instr);
       }
     } else if (v->IsIsSmi()) {
       HIsSmi* compare = HIsSmi::cast(v);
       ASSERT(compare->value()->representation().IsTagged());
 
-      return new LIsSmiAndBranch(Use(compare->value()),
-                                 first_id,
-                                 second_id);
+      return new LIsSmiAndBranch(Use(compare->value()));
     } else if (v->IsHasInstanceType()) {
       HHasInstanceType* compare = HHasInstanceType::cast(v);
       ASSERT(compare->value()->representation().IsTagged());
-
-      return new LHasInstanceTypeAndBranch(UseRegisterAtStart(compare->value()),
-                                           first_id,
-                                           second_id);
+      return new LHasInstanceTypeAndBranch(
+          UseRegisterAtStart(compare->value()));
     } else if (v->IsHasCachedArrayIndex()) {
       HHasCachedArrayIndex* compare = HHasCachedArrayIndex::cast(v);
       ASSERT(compare->value()->representation().IsTagged());
 
       return new LHasCachedArrayIndexAndBranch(
-          UseRegisterAtStart(compare->value()), first_id, second_id);
+          UseRegisterAtStart(compare->value()));
     } else if (v->IsIsNull()) {
       HIsNull* compare = HIsNull::cast(v);
       ASSERT(compare->value()->representation().IsTagged());
 
-      return new LIsNullAndBranch(UseRegisterAtStart(compare->value()),
-                                  first_id,
-                                  second_id);
+      return new LIsNullAndBranch(UseRegisterAtStart(compare->value()));
     } else if (v->IsIsObject()) {
       HIsObject* compare = HIsObject::cast(v);
       ASSERT(compare->value()->representation().IsTagged());
@@ -1021,41 +1022,33 @@ LInstruction* LChunkBuilder::DoTest(HTest* instr) {
       LOperand* temp2 = TempRegister();
       return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()),
                                     temp1,
-                                    temp2,
-                                    first_id,
-                                    second_id);
+                                    temp2);
     } else if (v->IsCompareJSObjectEq()) {
       HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v);
       return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()),
-                                         UseRegisterAtStart(compare->right()),
-                                         first_id,
-                                         second_id);
+                                         UseRegisterAtStart(compare->right()));
     } else if (v->IsInstanceOf()) {
       HInstanceOf* instance_of = HInstanceOf::cast(v);
       LInstruction* result =
           new LInstanceOfAndBranch(Use(instance_of->left()),
-                                   Use(instance_of->right()),
-                                   first_id,
-                                   second_id);
+                                   Use(instance_of->right()));
       return MarkAsCall(result, instr);
     } else if (v->IsTypeofIs()) {
       HTypeofIs* typeof_is = HTypeofIs::cast(v);
-      return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()),
-                                    first_id,
-                                    second_id);
+      return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()));
     } else {
       if (v->IsConstant()) {
         if (HConstant::cast(v)->handle()->IsTrue()) {
-          return new LGoto(first_id);
+          return new LGoto(instr->FirstSuccessor()->block_id());
         } else if (HConstant::cast(v)->handle()->IsFalse()) {
-          return new LGoto(second_id);
+          return new LGoto(instr->SecondSuccessor()->block_id());
         }
       }
       Abort("Undefined compare before branch");
       return NULL;
     }
   }
-  return new LBranch(UseRegisterAtStart(v), first_id, second_id);
+  return new LBranch(UseRegisterAtStart(v));
 }
 
 
@@ -1078,7 +1071,7 @@ LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
 
 
 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
-  LInstruction* result =
+  LInstanceOf* result =
       new LInstanceOf(UseFixed(instr->left(), r0),
                       UseFixed(instr->right(), r1));
   return MarkAsCall(DefineFixed(result, r0), instr);
@@ -1087,7 +1080,7 @@ LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
 
 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
     HInstanceOfKnownGlobal* instr) {
-  LInstruction* result =
+  LInstanceOfKnownGlobal* result =
       new LInstanceOfKnownGlobal(UseFixed(instr->value(), r0), FixedTemp(r4));
   MarkAsSaveDoubles(result);
   return AssignEnvironment(AssignPointerMap(DefineFixed(result, r0)));
@@ -1099,10 +1092,10 @@ LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
   LOperand* receiver = UseFixed(instr->receiver(), r0);
   LOperand* length = UseRegisterAtStart(instr->length());
   LOperand* elements = UseRegisterAtStart(instr->elements());
-  LInstruction* result = new LApplyArguments(function,
-                                             receiver,
-                                             length,
-                                             elements);
+  LApplyArguments* result = new LApplyArguments(function,
+                                                receiver,
+                                                length,
+                                                elements);
   return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY);
 }
 
@@ -1135,7 +1128,7 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
   BuiltinFunctionId op = instr->op();
   LOperand* input = UseRegisterAtStart(instr->value());
   LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
-  LInstruction* result = new LUnaryMathOperation(input, temp);
+  LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
   switch (op) {
     case kMathAbs:
       return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
@@ -1168,8 +1161,8 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
   ASSERT(instr->key()->representation().IsTagged());
   argument_count_ -= instr->argument_count();
-  UseFixed(instr->key(), r2);
-  return MarkAsCall(DefineFixed(new LCallKeyed, r0), instr);
+  LOperand* key = UseFixed(instr->key(), r2);
+  return MarkAsCall(DefineFixed(new LCallKeyed(key), r0), instr);
 }
 
 
@@ -1194,7 +1187,7 @@ LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
   LOperand* constructor = UseFixed(instr->constructor(), r1);
   argument_count_ -= instr->argument_count();
-  LInstruction* result = new LCallNew(constructor);
+  LCallNew* result = new LCallNew(constructor);
   return MarkAsCall(DefineFixed(result, r0), instr);
 }
 
@@ -1384,7 +1377,7 @@ LInstruction* LChunkBuilder::DoCompare(HCompare* instr) {
     bool reversed = (op == Token::GT || op == Token::LTE);
     LOperand* left = UseFixed(instr->left(), reversed ? r0 : r1);
     LOperand* right = UseFixed(instr->right(), reversed ? r1 : r0);
-    LInstruction* result = new LCmpT(left, right);
+    LCmpT* result = new LCmpT(left, right);
     return MarkAsCall(DefineFixed(result, r0), instr);
   }
 }
@@ -1394,7 +1387,7 @@ LInstruction* LChunkBuilder::DoCompareJSObjectEq(
     HCompareJSObjectEq* instr) {
   LOperand* left = UseRegisterAtStart(instr->left());
   LOperand* right = UseRegisterAtStart(instr->right());
-  LInstruction* result = new LCmpJSObjectEq(left, right);
+  LCmpJSObjectEq* result = new LCmpJSObjectEq(left, right);
   return DefineAsRegister(result);
 }
 
@@ -1461,7 +1454,7 @@ LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) {
 
 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
   LOperand* object = UseRegister(instr->value());
-  LInstruction* result = new LValueOf(object, TempRegister());
+  LValueOf* result = new LValueOf(object, TempRegister());
   return AssignEnvironment(DefineSameAsFirst(result));
 }
 
@@ -1484,7 +1477,7 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
   if (from.IsTagged()) {
     if (to.IsDouble()) {
       LOperand* value = UseRegister(instr->value());
-      LInstruction* res = new LNumberUntagD(value);
+      LNumberUntagD* res = new LNumberUntagD(value);
       return AssignEnvironment(DefineAsRegister(res));
     } else {
       ASSERT(to.IsInteger32());
@@ -1510,13 +1503,13 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
       // Make sure that the temp and result_temp registers are
       // different.
       LUnallocated* result_temp = TempRegister();
-      LInstruction* result = new LNumberTagD(value, temp1, temp2);
+      LNumberTagD* result = new LNumberTagD(value, temp1, temp2);
       Define(result, result_temp);
       return AssignPointerMap(result);
     } else {
       ASSERT(to.IsInteger32());
       LOperand* value = UseRegister(instr->value());
-      LInstruction* res = new LDoubleToI(value);
+      LDoubleToI* res = new LDoubleToI(value);
       return AssignEnvironment(DefineAsRegister(res));
     }
   } else if (from.IsInteger32()) {
@@ -1526,7 +1519,7 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
       if (val->HasRange() && val->range()->IsInSmiRange()) {
         return DefineSameAsFirst(new LSmiTag(value));
       } else {
-        LInstruction* result = new LNumberTagI(value);
+        LNumberTagI* result = new LNumberTagI(value);
         return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
       }
     } else {
@@ -1603,7 +1596,7 @@ LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
 
 
 LInstruction* LChunkBuilder::DoLoadGlobal(HLoadGlobal* instr) {
-  LInstruction* result = new LLoadGlobal();
+  LLoadGlobal* result = new LLoadGlobal();
   return instr->check_hole_value()
       ? AssignEnvironment(DefineAsRegister(result))
       : DefineAsRegister(result);
@@ -1652,7 +1645,7 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
   ASSERT(instr->key()->representation().IsInteger32());
   LOperand* obj = UseRegisterAtStart(instr->object());
   LOperand* key = UseRegisterAtStart(instr->key());
-  LInstruction* result = new LLoadKeyedFastElement(obj, key);
+  LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key);
   return AssignEnvironment(DefineSameAsFirst(result));
 }
 
@@ -1726,7 +1719,7 @@ LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
   LOperand* string = UseRegister(instr->string());
   LOperand* index = UseRegisterOrConstant(instr->index());
-  LInstruction* result = new LStringCharCodeAt(string, index);
+  LStringCharCodeAt* result = new LStringCharCodeAt(string, index);
   return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
 }
 
@@ -1760,7 +1753,7 @@ LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
   LOperand* object = UseRegisterAtStart(instr->object());
   LOperand* key = UseRegisterAtStart(instr->key());
-  LInstruction* result = new LDeleteProperty(object, key);
+  LDeleteProperty* result = new LDeleteProperty(object, key);
   return MarkAsCall(DefineFixed(result, r0), instr);
 }
 
@@ -1801,13 +1794,13 @@ LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
   LOperand* arguments = UseRegister(instr->arguments());
   LOperand* length = UseTempRegister(instr->length());
   LOperand* index = UseRegister(instr->index());
-  LInstruction* result = new LAccessArgumentsAt(arguments, length, index);
-  return DefineAsRegister(AssignEnvironment(result));
+  LAccessArgumentsAt* result = new LAccessArgumentsAt(arguments, length, index);
+  return AssignEnvironment(DefineAsRegister(result));
 }
 
 
 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
-  LInstruction* result = new LTypeof(UseRegisterAtStart(instr->value()));
+  LTypeof* result = new LTypeof(UseRegisterAtStart(instr->value()));
   return MarkAsCall(DefineFixed(result, r0), instr);
 }
 
index 1cf9898..81a0266 100644 (file)
@@ -43,10 +43,22 @@ class LCodeGen;
 // Type hierarchy:
 //
 // LInstruction
-//   LAccessArgumentsAt
-//   LArgumentsElements
-//   LArgumentsLength
-//   LBinaryOperation
+//   LTemplateInstruction
+//     LControlInstruction
+//       LBranch
+//       LClassOfTestAndBranch
+//       LCmpJSObjectEqAndBranch
+//       LCmpIDAndBranch
+//       LHasCachedArrayIndexAndBranch
+//       LHasInstanceTypeAndBranch
+//       LInstanceOfAndBranch
+//       LIsNullAndBranch
+//       LIsObjectAndBranch
+//       LIsSmiAndBranch
+//       LTypeofIsAndBranch
+//     LAccessArgumentsAt
+//     LArgumentsElements
+//     LArgumentsLength
 //     LAddI
 //     LApplyArguments
 //     LArithmeticD
@@ -54,80 +66,73 @@ class LCodeGen;
 //     LBitI
 //     LBoundsCheck
 //     LCmpID
-//     LCmpIDAndBranch
 //     LCmpJSObjectEq
-//     LCmpJSObjectEqAndBranch
 //     LCmpT
 //     LDivI
 //     LInstanceOf
-//     LInstanceOfAndBranch
 //     LInstanceOfKnownGlobal
 //     LLoadKeyedFastElement
 //     LLoadKeyedGeneric
 //     LModI
 //     LMulI
+//     LPower
 //     LShiftI
-//     LStringCharCodeAt
 //     LSubI
-//   LCallConstantFunction
-//   LCallFunction
-//   LCallGlobal
-//   LCallKeyed
-//   LCallKnownGlobal
-//   LCallNamed
-//   LCallRuntime
-//   LCallStub
-//   LCheckPrototypeMaps
-//   LConstant
-//     LConstantD
-//     LConstantI
-//     LConstantT
-//   LDeoptimize
-//   LFunctionLiteral
-//   LGlobalObject
-//   LGlobalReceiver
-//   LLabel
-//   LLazyBailout
-//   LLoadContextSlot
-//   LLoadGlobal
-//   LMaterializedLiteral
+//     LCallConstantFunction
+//     LCallFunction
+//     LCallGlobal
+//     LCallKeyed
+//     LCallKnownGlobal
+//     LCallNamed
+//     LCallRuntime
+//     LCallStub
+//     LConstant
+//       LConstantD
+//       LConstantI
+//       LConstantT
+//     LDeoptimize
+//     LFunctionLiteral
+//     LGap
+//       LLabel
+//     LGlobalObject
+//     LGlobalReceiver
+//     LGoto
+//     LLazyBailout
+//     LLoadGlobal
+//     LCheckPrototypeMaps
+//     LLoadContextSlot
 //     LArrayLiteral
 //     LObjectLiteral
 //     LRegExpLiteral
-//   LOsrEntry
-//   LParameter
-//   LStackCheck
-//   LStoreKeyed
-//     LStoreKeyedFastElement
-//     LStoreKeyedGeneric
-//   LStoreNamed
-//     LStoreNamedField
-//     LStoreNamedGeneric
-//   LUnaryOperation
-//     LJSArrayLength
-//     LFixedArrayLength
+//     LOsrEntry
+//     LParameter
+//     LRegExpConstructResult
+//     LStackCheck
+//     LStoreKeyed
+//       LStoreKeyedFastElement
+//       LStoreKeyedGeneric
+//     LStoreNamed
+//       LStoreNamedField
+//       LStoreNamedGeneric
+//     LStringCharCodeAt
 //     LBitNotI
-//     LBranch
 //     LCallNew
 //     LCheckFunction
+//     LCheckPrototypeMaps
 //     LCheckInstanceType
 //     LCheckMap
 //     LCheckSmi
 //     LClassOfTest
-//     LClassOfTestAndBranch
 //     LDeleteProperty
 //     LDoubleToI
+//     LFixedArrayLength
 //     LHasCachedArrayIndex
-//     LHasCachedArrayIndexAndBranch
 //     LHasInstanceType
-//     LHasInstanceTypeAndBranch
 //     LInteger32ToDouble
 //     LIsNull
-//     LIsNullAndBranch
 //     LIsObject
-//     LIsObjectAndBranch
 //     LIsSmi
-//     LIsSmiAndBranch
+//     LJSArrayLength
 //     LLoadNamedField
 //     LLoadNamedGeneric
 //     LLoadFunctionPrototype
@@ -142,19 +147,16 @@ class LCodeGen;
 //     LThrow
 //     LTypeof
 //     LTypeofIs
-//     LTypeofIsAndBranch
 //     LUnaryMathOperation
 //     LValueOf
-//   LUnknownOSRValue
+//     LUnknownOSRValue
 
 #define LITHIUM_ALL_INSTRUCTION_LIST(V)         \
-  V(BinaryOperation)                            \
+  V(ControlInstruction)                         \
   V(Constant)                                   \
   V(Call)                                       \
-  V(MaterializedLiteral)                        \
   V(StoreKeyed)                                 \
   V(StoreNamed)                                 \
-  V(UnaryOperation)                             \
   LITHIUM_CONCRETE_INSTRUCTION_LIST(V)
 
 
@@ -293,14 +295,17 @@ class LInstruction: public ZoneObject {
 
   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; }
   LITHIUM_ALL_INSTRUCTION_LIST(DECLARE_DO)
 #undef DECLARE_DO
+
   virtual bool IsControl() const { return false; }
+  virtual void SetBranchTargets(int true_block_id, int false_block_id) { }
 
   void set_environment(LEnvironment* env) { environment_.set(env); }
   LEnvironment* environment() const { return environment_.get(); }
@@ -310,9 +315,7 @@ class LInstruction: public ZoneObject {
   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_; }
@@ -330,13 +333,66 @@ class LInstruction: public ZoneObject {
  private:
   SetOncePointer<LEnvironment> environment_;
   SetOncePointer<LPointerMap> pointer_map_;
-  SetOncePointer<LOperand> result_;
   HValue* hydrogen_value_;
   SetOncePointer<LEnvironment> deoptimization_environment_;
 };
 
 
-class LGap: public LInstruction {
+template<typename ElementType, int NumElements>
+class OperandContainer {
+ public:
+  OperandContainer() {
+    for (int i = 0; i < NumElements; i++) elems_[i] = NULL;
+  }
+  int length() { return NumElements; }
+  ElementType& operator[](int i) {
+    ASSERT(i < length());
+    return elems_[i];
+  }
+  void PrintOperandsTo(StringStream* stream);
+
+ private:
+  ElementType elems_[NumElements];
+};
+
+
+template<typename ElementType>
+class OperandContainer<ElementType, 0> {
+ public:
+  int length() { return 0; }
+  void PrintOperandsTo(StringStream* stream) { }
+};
+
+
+// R = number of result operands (0 or 1).
+// I = number of input operands.
+// T = number of temporary operands.
+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) { results_[0] = operand; }
+  LOperand* result() { return results_[0]; }
+
+  int InputCount() { return I; }
+  LOperand* InputAt(int i) { return inputs_[i]; }
+
+  int TempCount() { return T; }
+  LOperand* TempAt(int i) { return temps_[i]; }
+
+  virtual void PrintDataTo(StringStream* stream);
+  virtual void PrintOutputOperandTo(StringStream* stream);
+
+ protected:
+  OperandContainer<LOperand*, R> results_;
+  OperandContainer<LOperand*, I> inputs_;
+  OperandContainer<LOperand*, T> temps_;
+};
+
+
+class LGap: public LTemplateInstruction<0, 0, 0> {
  public:
   explicit LGap(HBasicBlock* block)
       : block_(block) {
@@ -377,13 +433,13 @@ class LGap: public LInstruction {
 };
 
 
-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_; }
@@ -395,7 +451,7 @@ class LGoto: public LInstruction {
 };
 
 
-class LLazyBailout: public LInstruction {
+class LLazyBailout: public LTemplateInstruction<0, 0, 0> {
  public:
   LLazyBailout() : gap_instructions_size_(0) { }
 
@@ -411,7 +467,7 @@ class LLazyBailout: public LInstruction {
 };
 
 
-class LDeoptimize: public LInstruction {
+class LDeoptimize: public LTemplateInstruction<0, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(Deoptimize, "deoptimize")
 };
@@ -424,7 +480,7 @@ class LLabel: public LGap {
 
   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(); }
@@ -439,13 +495,13 @@ class LLabel: public LGap {
 };
 
 
-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)
@@ -456,96 +512,81 @@ class LCallStub: public LInstruction {
 };
 
 
-class LUnknownOSRValue: public LInstruction {
+class LUnknownOSRValue: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(UnknownOSRValue, "unknown-osr-value")
 };
 
 
-class LUnaryOperation: public LInstruction {
- public:
-  explicit LUnaryOperation(LOperand* input) : input_(input) { }
-
-  DECLARE_INSTRUCTION(UnaryOperation)
-
-  LOperand* input() const { return input_; }
-
-  virtual void PrintDataTo(StringStream* stream) const;
-
- private:
-  LOperand* input_;
-};
-
-
-class LBinaryOperation: public LInstruction {
+template<int I, int T>
+class LControlInstruction: public LTemplateInstruction<0, I, T> {
  public:
-  LBinaryOperation(LOperand* left, LOperand* right)
-      : left_(left), right_(right) { }
-
-  DECLARE_INSTRUCTION(BinaryOperation)
+  DECLARE_INSTRUCTION(ControlInstruction)
+  virtual bool IsControl() const { return true; }
 
-  LOperand* left() const { return left_; }
-  LOperand* right() const { return right_; }
-  virtual void PrintDataTo(StringStream* stream) const;
+  int true_block_id() const { return true_block_id_; }
+  int false_block_id() const { return false_block_id_; }
+  void SetBranchTargets(int true_block_id, int false_block_id) {
+    true_block_id_ = true_block_id;
+    false_block_id_ = false_block_id;
+  }
 
  private:
-  LOperand* left_;
-  LOperand* right_;
+  int true_block_id_;
+  int false_block_id_;
 };
 
 
-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) {
+    inputs_[0] = function;
+    inputs_[1] = receiver;
+    inputs_[2] = length;
+    inputs_[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() { return inputs_[0]; }
+  LOperand* receiver() { return inputs_[1]; }
+  LOperand* length() { return inputs_[2]; }
+  LOperand* elements() { return inputs_[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) {
+    inputs_[0] = arguments;
+    inputs_[1] = length;
+    inputs_[2] = index;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(AccessArgumentsAt, "access-arguments-at")
 
-  LOperand* arguments() const { return arguments_; }
-  LOperand* length() const { return length_; }
-  LOperand* index() const { return index_; }
-
-  virtual void PrintDataTo(StringStream* stream) const;
+  LOperand* arguments() { return inputs_[0]; }
+  LOperand* length() { return inputs_[1]; }
+  LOperand* index() { return inputs_[2]; }
 
- private:
-  LOperand* arguments_;
-  LOperand* length_;
-  LOperand* index_;
+  virtual void PrintDataTo(StringStream* stream);
 };
 
 
-class LArgumentsLength: public LUnaryOperation {
+class LArgumentsLength: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LArgumentsLength(LOperand* elements) : LUnaryOperation(elements) {}
+  explicit LArgumentsLength(LOperand* elements) {
+    inputs_[0] = elements;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(ArgumentsLength, "arguments-length")
 };
 
 
-class LArgumentsElements: public LInstruction {
+class LArgumentsElements: public LTemplateInstruction<1, 0, 0> {
  public:
   LArgumentsElements() { }
 
@@ -553,341 +594,274 @@ class LArgumentsElements: public LInstruction {
 };
 
 
-class LModI: public LBinaryOperation {
+class LModI: public LTemplateInstruction<1, 2, 0> {
  public:
-  LModI(LOperand* left, LOperand* right) : LBinaryOperation(left, right) { }
+  LModI(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(ModI, "mod-i")
   DECLARE_HYDROGEN_ACCESSOR(Mod)
 };
 
 
-class LDivI: public LBinaryOperation {
+class LDivI: public LTemplateInstruction<1, 2, 0> {
  public:
-  LDivI(LOperand* left, LOperand* right)
-      : LBinaryOperation(left, right) { }
+  LDivI(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
   DECLARE_HYDROGEN_ACCESSOR(Div)
 };
 
 
-class LMulI: public LBinaryOperation {
+class LMulI: public LTemplateInstruction<1, 2, 1> {
  public:
-  LMulI(LOperand* left, LOperand* right, LOperand* temp)
-      : LBinaryOperation(left, right), temp_(temp) { }
+  LMulI(LOperand* left, LOperand* right, LOperand* temp) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+    temps_[0] = temp;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i")
   DECLARE_HYDROGEN_ACCESSOR(Mul)
-
-  LOperand* temp() const { return temp_; }
-
- private:
-  LOperand* temp_;
 };
 
 
-class LCmpID: public LBinaryOperation {
+class LCmpID: public LTemplateInstruction<1, 2, 0> {
  public:
-  LCmpID(LOperand* left, LOperand* right)
-      : LBinaryOperation(left, right) { }
+  LCmpID(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
+
+  DECLARE_CONCRETE_INSTRUCTION(CmpID, "cmp-id")
+  DECLARE_HYDROGEN_ACCESSOR(Compare)
 
   Token::Value op() const { return hydrogen()->token(); }
   bool is_double() const {
     return hydrogen()->GetInputRepresentation().IsDouble();
   }
-
-  DECLARE_CONCRETE_INSTRUCTION(CmpID, "cmp-id")
-  DECLARE_HYDROGEN_ACCESSOR(Compare)
 };
 
 
-class LCmpIDAndBranch: public LCmpID {
+class LCmpIDAndBranch: public LControlInstruction<2, 0> {
  public:
-  LCmpIDAndBranch(LOperand* left,
-                  LOperand* right,
-                  int true_block_id,
-                  int false_block_id)
-      : LCmpID(left, right),
-        true_block_id_(true_block_id),
-        false_block_id_(false_block_id) { }
+  LCmpIDAndBranch(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(CmpIDAndBranch, "cmp-id-and-branch")
-  virtual void PrintDataTo(StringStream* stream) const;
-  virtual bool IsControl() const { return true; }
+  DECLARE_HYDROGEN_ACCESSOR(Compare)
 
-  int true_block_id() const { return true_block_id_; }
-  int false_block_id() const { return false_block_id_; }
+  Token::Value op() const { return hydrogen()->token(); }
+  bool is_double() const {
+    return hydrogen()->GetInputRepresentation().IsDouble();
+  }
 
- private:
-  int true_block_id_;
-  int false_block_id_;
+  virtual void PrintDataTo(StringStream* stream);
 };
 
 
-class LUnaryMathOperation: public LUnaryOperation {
+class LUnaryMathOperation: public LTemplateInstruction<1, 1, 1> {
  public:
-  explicit LUnaryMathOperation(LOperand* value, LOperand* temp)
-      : LUnaryOperation(value), temp_(temp) { }
+  LUnaryMathOperation(LOperand* value, LOperand* temp) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+  }
 
   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(); }
-  LOperand* temp() const { return temp_; }
-
- private:
-  LOperand* temp_;
 };
 
 
-class LCmpJSObjectEq: public LBinaryOperation {
+class LCmpJSObjectEq: public LTemplateInstruction<1, 2, 0> {
  public:
-  LCmpJSObjectEq(LOperand* left, LOperand* right)
-      : LBinaryOperation(left, right) {}
+  LCmpJSObjectEq(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(CmpJSObjectEq, "cmp-jsobject-eq")
 };
 
 
-class LCmpJSObjectEqAndBranch: public LCmpJSObjectEq {
+class LCmpJSObjectEqAndBranch: public LControlInstruction<2, 0> {
  public:
-  LCmpJSObjectEqAndBranch(LOperand* left,
-                          LOperand* right,
-                          int true_block_id,
-                          int false_block_id)
-      : LCmpJSObjectEq(left, right),
-        true_block_id_(true_block_id),
-        false_block_id_(false_block_id) { }
+  LCmpJSObjectEqAndBranch(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(CmpJSObjectEqAndBranch,
                                "cmp-jsobject-eq-and-branch")
-
-  int true_block_id() const { return true_block_id_; }
-  int false_block_id() const { return false_block_id_; }
-
- private:
-  int true_block_id_;
-  int false_block_id_;
 };
 
 
-class LIsNull: public LUnaryOperation {
+class LIsNull: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LIsNull(LOperand* value) : LUnaryOperation(value) {}
+  explicit LIsNull(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(IsNull, "is-null")
-  DECLARE_HYDROGEN_ACCESSOR(IsNull);
+  DECLARE_HYDROGEN_ACCESSOR(IsNull)
 
   bool is_strict() const { return hydrogen()->is_strict(); }
 };
 
-
-class LIsNullAndBranch: public LIsNull {
+class LIsNullAndBranch: public LControlInstruction<1, 0> {
  public:
-  LIsNullAndBranch(LOperand* value,
-                   int true_block_id,
-                   int false_block_id)
-      : LIsNull(value),
-        true_block_id_(true_block_id),
-        false_block_id_(false_block_id) { }
+  explicit LIsNullAndBranch(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(IsNullAndBranch, "is-null-and-branch")
-  virtual void PrintDataTo(StringStream* stream) const;
-  virtual bool IsControl() const { return true; }
+  DECLARE_HYDROGEN_ACCESSOR(IsNull)
 
-  int true_block_id() const { return true_block_id_; }
-  int false_block_id() const { return false_block_id_; }
+  bool is_strict() const { return hydrogen()->is_strict(); }
 
- private:
-  int true_block_id_;
-  int false_block_id_;
+  virtual void PrintDataTo(StringStream* stream);
 };
 
 
-class LIsObject: public LUnaryOperation {
+class LIsObject: public LTemplateInstruction<1, 1, 1> {
  public:
-  LIsObject(LOperand* value, LOperand* temp)
-      : LUnaryOperation(value), temp_(temp) {}
+  LIsObject(LOperand* value, LOperand* temp) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(IsObject, "is-object")
-
-  LOperand* temp() const { return temp_; }
-
- private:
-  LOperand* temp_;
 };
 
 
-class LIsObjectAndBranch: public LIsObject {
+class LIsObjectAndBranch: public LControlInstruction<1, 2> {
  public:
-  LIsObjectAndBranch(LOperand* value,
-                     LOperand* temp,
-                     LOperand* temp2,
-                     int true_block_id,
-                     int false_block_id)
-      : LIsObject(value, temp),
-        temp2_(temp2),
-        true_block_id_(true_block_id),
-        false_block_id_(false_block_id) { }
+  LIsObjectAndBranch(LOperand* value, LOperand* temp, LOperand* temp2) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+    temps_[1] = temp2;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch, "is-object-and-branch")
-  virtual void PrintDataTo(StringStream* stream) const;
-  virtual bool IsControl() const { return true; }
-
-  int true_block_id() const { return true_block_id_; }
-  int false_block_id() const { return false_block_id_; }
-
-  LOperand* temp2() const { return temp2_; }
 
- private:
-  LOperand* temp2_;
-  int true_block_id_;
-  int false_block_id_;
+  virtual void PrintDataTo(StringStream* stream);
 };
 
 
-class LIsSmi: public LUnaryOperation {
+class LIsSmi: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LIsSmi(LOperand* value) : LUnaryOperation(value) {}
+  explicit LIsSmi(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(IsSmi, "is-smi")
   DECLARE_HYDROGEN_ACCESSOR(IsSmi)
 };
 
 
-class LIsSmiAndBranch: public LIsSmi {
+class LIsSmiAndBranch: public LControlInstruction<1, 0> {
  public:
-  LIsSmiAndBranch(LOperand* value,
-                  int true_block_id,
-                  int false_block_id)
-      : LIsSmi(value),
-        true_block_id_(true_block_id),
-        false_block_id_(false_block_id) { }
+  explicit LIsSmiAndBranch(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(IsSmiAndBranch, "is-smi-and-branch")
-  virtual void PrintDataTo(StringStream* stream) const;
-  virtual bool IsControl() const { return true; }
 
-  int true_block_id() const { return true_block_id_; }
-  int false_block_id() const { return false_block_id_; }
-
- private:
-  int true_block_id_;
-  int false_block_id_;
+  virtual void PrintDataTo(StringStream* stream);
 };
 
 
-class LHasInstanceType: public LUnaryOperation {
+class LHasInstanceType: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LHasInstanceType(LOperand* value)
-      : LUnaryOperation(value) { }
+  explicit LHasInstanceType(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(HasInstanceType, "has-instance-type")
   DECLARE_HYDROGEN_ACCESSOR(HasInstanceType)
-
-  InstanceType TestType();  // The type to test against when generating code.
-  Condition BranchCondition();  // The branch condition for 'true'.
 };
 
 
-class LHasInstanceTypeAndBranch: public LHasInstanceType {
+class LHasInstanceTypeAndBranch: public LControlInstruction<1, 0> {
  public:
-  LHasInstanceTypeAndBranch(LOperand* value,
-                            int true_block_id,
-                            int false_block_id)
-      : LHasInstanceType(value),
-        true_block_id_(true_block_id),
-        false_block_id_(false_block_id) { }
+  explicit LHasInstanceTypeAndBranch(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(HasInstanceTypeAndBranch,
                                "has-instance-type-and-branch")
-  virtual void PrintDataTo(StringStream* stream) const;
-  virtual bool IsControl() const { return true; }
-
-  int true_block_id() const { return true_block_id_; }
-  int false_block_id() const { return false_block_id_; }
+  DECLARE_HYDROGEN_ACCESSOR(HasInstanceType)
 
- private:
-  int true_block_id_;
-  int false_block_id_;
+  virtual void PrintDataTo(StringStream* stream);
 };
 
 
-class LHasCachedArrayIndex: public LUnaryOperation {
+class LHasCachedArrayIndex: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LHasCachedArrayIndex(LOperand* value) : LUnaryOperation(value) {}
+  explicit LHasCachedArrayIndex(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndex, "has-cached-array-index")
   DECLARE_HYDROGEN_ACCESSOR(HasCachedArrayIndex)
 };
 
 
-class LHasCachedArrayIndexAndBranch: public LHasCachedArrayIndex {
+class LHasCachedArrayIndexAndBranch: public LControlInstruction<1, 0> {
  public:
-  LHasCachedArrayIndexAndBranch(LOperand* value,
-                                int true_block_id,
-                                int false_block_id)
-      : LHasCachedArrayIndex(value),
-        true_block_id_(true_block_id),
-        false_block_id_(false_block_id) { }
+  explicit LHasCachedArrayIndexAndBranch(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(HasCachedArrayIndexAndBranch,
                                "has-cached-array-index-and-branch")
-  virtual void PrintDataTo(StringStream* stream) const;
-  virtual bool IsControl() const { return true; }
-
-  int true_block_id() const { return true_block_id_; }
-  int false_block_id() const { return false_block_id_; }
-
- private:
-  int true_block_id_;
-  int false_block_id_;
+  virtual void PrintDataTo(StringStream* stream);
 };
 
 
-class LClassOfTest: public LUnaryOperation {
+class LClassOfTest: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LClassOfTest(LOperand* value) : LUnaryOperation(value) {}
+  explicit LClassOfTest(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(ClassOfTest, "class-of-test")
   DECLARE_HYDROGEN_ACCESSOR(ClassOfTest)
 
-  virtual void PrintDataTo(StringStream* stream) const;
+  virtual void PrintDataTo(StringStream* stream);
 };
 
 
-class LClassOfTestAndBranch: public LClassOfTest {
+class LClassOfTestAndBranch: public LControlInstruction<1, 1> {
  public:
-  LClassOfTestAndBranch(LOperand* value,
-                        LOperand* temporary,
-                        int true_block_id,
-                        int false_block_id)
-      : LClassOfTest(value),
-        temporary_(temporary),
-        true_block_id_(true_block_id),
-        false_block_id_(false_block_id) { }
+  LClassOfTestAndBranch(LOperand* value, LOperand* temp) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(ClassOfTestAndBranch,
                                "class-of-test-and-branch")
-  virtual void PrintDataTo(StringStream* stream) const;
-  virtual bool IsControl() const { return true; }
-
-  int true_block_id() const { return true_block_id_; }
-  int false_block_id() const { return false_block_id_; }
-  LOperand* temporary() { return temporary_; }
+  DECLARE_HYDROGEN_ACCESSOR(ClassOfTest)
 
- private:
-  LOperand* temporary_;
-  int true_block_id_;
-  int false_block_id_;
+  virtual void PrintDataTo(StringStream* stream);
 };
 
 
-class LCmpT: public LBinaryOperation {
+class LCmpT: public LTemplateInstruction<1, 2, 0> {
  public:
-  LCmpT(LOperand* left, LOperand* right) : LBinaryOperation(left, right) {}
+  LCmpT(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(CmpT, "cmp-t")
   DECLARE_HYDROGEN_ACCESSOR(Compare)
@@ -896,90 +870,78 @@ class LCmpT: public LBinaryOperation {
 };
 
 
-class LCmpTAndBranch: public LCmpT {
+class LCmpTAndBranch: public LControlInstruction<2, 0> {
  public:
-  LCmpTAndBranch(LOperand* left,
-                 LOperand* right,
-                 int true_block_id,
-                 int false_block_id)
-      : LCmpT(left, right),
-        true_block_id_(true_block_id),
-        false_block_id_(false_block_id) { }
+  LCmpTAndBranch(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(CmpTAndBranch, "cmp-t-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(Compare)
 
-  int true_block_id() const { return true_block_id_; }
-  int false_block_id() const { return false_block_id_; }
-
- private:
-  int true_block_id_;
-  int false_block_id_;
+  Token::Value op() const { return hydrogen()->token(); }
 };
 
 
-class LInstanceOf: public LBinaryOperation {
+class LInstanceOf: public LTemplateInstruction<1, 2, 0> {
  public:
-  LInstanceOf(LOperand* left, LOperand* right)
-      : LBinaryOperation(left, right) { }
+  LInstanceOf(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(InstanceOf, "instance-of")
 };
 
 
-class LInstanceOfAndBranch: public LInstanceOf {
+class LInstanceOfAndBranch: public LControlInstruction<2, 0> {
  public:
-  LInstanceOfAndBranch(LOperand* left,
-                       LOperand* right,
-                       int true_block_id,
-                       int false_block_id)
-      : LInstanceOf(left, right),
-        true_block_id_(true_block_id),
-        false_block_id_(false_block_id) { }
+  LInstanceOfAndBranch(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(InstanceOfAndBranch, "instance-of-and-branch")
-
-  int true_block_id() const { return true_block_id_; }
-  int false_block_id() const { return false_block_id_; }
-
- private:
-  int true_block_id_;
-  int false_block_id_;
 };
 
 
-class LInstanceOfKnownGlobal: public LUnaryOperation {
+class LInstanceOfKnownGlobal: public LTemplateInstruction<1, 1, 1> {
  public:
-  explicit LInstanceOfKnownGlobal(LOperand* left, LOperand* temp)
-      : LUnaryOperation(left), temp_(temp) { }
+  LInstanceOfKnownGlobal(LOperand* value, LOperand* temp) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(InstanceOfKnownGlobal,
                                "instance-of-known-global")
   DECLARE_HYDROGEN_ACCESSOR(InstanceOfKnownGlobal)
 
   Handle<JSFunction> function() const { return hydrogen()->function(); }
-  LOperand* temp() const { return temp_; }
-
- private:
-  LOperand* temp_;
 };
 
 
-class LBoundsCheck: public LBinaryOperation {
+class LBoundsCheck: public LTemplateInstruction<0, 2, 0> {
  public:
-  LBoundsCheck(LOperand* index, LOperand* length)
-      : LBinaryOperation(index, length) { }
+  LBoundsCheck(LOperand* index, LOperand* length) {
+    inputs_[0] = index;
+    inputs_[1] = length;
+  }
 
-  LOperand* index() const { return left(); }
-  LOperand* length() const { return right(); }
+  LOperand* index() { return inputs_[0]; }
+  LOperand* length() { return inputs_[1]; }
 
   DECLARE_CONCRETE_INSTRUCTION(BoundsCheck, "bounds-check")
 };
 
 
-class LBitI: public LBinaryOperation {
+class LBitI: public LTemplateInstruction<1, 2, 0> {
  public:
   LBitI(Token::Value op, LOperand* left, LOperand* right)
-      : LBinaryOperation(left, right), op_(op) { }
+      : op_(op) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
 
   Token::Value op() const { return op_; }
 
@@ -990,10 +952,13 @@ class LBitI: public LBinaryOperation {
 };
 
 
-class LShiftI: public LBinaryOperation {
+class LShiftI: public LTemplateInstruction<1, 2, 0> {
  public:
   LShiftI(Token::Value op, LOperand* left, LOperand* right, bool can_deopt)
-      : LBinaryOperation(left, right), op_(op), can_deopt_(can_deopt) { }
+      : op_(op), can_deopt_(can_deopt) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
 
   Token::Value op() const { return op_; }
 
@@ -1007,17 +972,19 @@ class LShiftI: public LBinaryOperation {
 };
 
 
-class LSubI: public LBinaryOperation {
+class LSubI: public LTemplateInstruction<1, 2, 0> {
  public:
-  LSubI(LOperand* left, LOperand* right)
-      : LBinaryOperation(left, right) { }
+  LSubI(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = 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)
 };
 
@@ -1058,39 +1025,31 @@ class LConstantT: public LConstant {
 };
 
 
-class LBranch: public LUnaryOperation {
+class LBranch: public LControlInstruction<1, 0> {
  public:
-  LBranch(LOperand* input, int true_block_id, int false_block_id)
-      : LUnaryOperation(input),
-        true_block_id_(true_block_id),
-        false_block_id_(false_block_id) { }
+  explicit LBranch(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(Branch, "branch")
   DECLARE_HYDROGEN_ACCESSOR(Value)
 
-  virtual void PrintDataTo(StringStream* stream) const;
-  virtual bool IsControl() const { return true; }
-
-  int true_block_id() const { return true_block_id_; }
-  int false_block_id() const { return false_block_id_; }
-
- private:
-  int true_block_id_;
-  int false_block_id_;
+  virtual void PrintDataTo(StringStream* stream);
 };
 
 
-class LCmpMapAndBranch: public LUnaryOperation {
+class LCmpMapAndBranch: public LTemplateInstruction<0, 1, 1> {
  public:
-  LCmpMapAndBranch(LOperand* value, LOperand* temp)
-      : LUnaryOperation(value), temp_(temp) { }
+  LCmpMapAndBranch(LOperand* value, LOperand* temp) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch")
   DECLARE_HYDROGEN_ACCESSOR(CompareMap)
 
   virtual bool IsControl() const { return true; }
 
-  LOperand* temp() const { return temp_; }
   Handle<Map> map() const { return hydrogen()->map(); }
   int true_block_id() const {
     return hydrogen()->FirstSuccessor()->block_id();
@@ -1098,75 +1057,82 @@ class LCmpMapAndBranch: public LUnaryOperation {
   int false_block_id() const {
     return hydrogen()->SecondSuccessor()->block_id();
   }
-
- private:
-  LOperand* temp_;
 };
 
 
-class LJSArrayLength: public LUnaryOperation {
+class LJSArrayLength: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LJSArrayLength(LOperand* input) : LUnaryOperation(input) { }
+  explicit LJSArrayLength(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(JSArrayLength, "js-array-length")
   DECLARE_HYDROGEN_ACCESSOR(JSArrayLength)
 };
 
 
-class LFixedArrayLength: public LUnaryOperation {
+class LFixedArrayLength: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LFixedArrayLength(LOperand* input) : LUnaryOperation(input) { }
+  explicit LFixedArrayLength(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(FixedArrayLength, "fixed-array-length")
   DECLARE_HYDROGEN_ACCESSOR(FixedArrayLength)
 };
 
 
-class LValueOf: public LUnaryOperation {
+class LValueOf: public LTemplateInstruction<1, 1, 1> {
  public:
-  LValueOf(LOperand* input, LOperand* temporary)
-      : LUnaryOperation(input), temporary_(temporary) { }
-
-  LOperand* temporary() const { return temporary_; }
+  LValueOf(LOperand* value, LOperand* temp) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(ValueOf, "value-of")
   DECLARE_HYDROGEN_ACCESSOR(ValueOf)
-
- private:
-  LOperand* temporary_;
 };
 
 
-class LThrow: public LUnaryOperation {
+class LThrow: public LTemplateInstruction<0, 1, 0> {
  public:
-  explicit LThrow(LOperand* value) : LUnaryOperation(value) { }
+  explicit LThrow(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(Throw, "throw")
 };
 
 
-class LBitNotI: public LUnaryOperation {
+class LBitNotI: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LBitNotI(LOperand* use) : LUnaryOperation(use) { }
+  explicit LBitNotI(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(BitNotI, "bit-not-i")
 };
 
 
-class LAddI: public LBinaryOperation {
+class LAddI: public LTemplateInstruction<1, 2, 0> {
  public:
-  LAddI(LOperand* left, LOperand* right)
-      : LBinaryOperation(left, right) { }
+  LAddI(LOperand* left, LOperand* right) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(AddI, "add-i")
   DECLARE_HYDROGEN_ACCESSOR(Add)
 };
 
 
-class LArithmeticD: public LBinaryOperation {
+class LArithmeticD: public LTemplateInstruction<1, 2, 0> {
  public:
   LArithmeticD(Token::Value op, LOperand* left, LOperand* right)
-      : LBinaryOperation(left, right), op_(op) { }
+      : op_(op) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
 
   Token::Value op() const { return op_; }
 
@@ -1178,10 +1144,13 @@ class LArithmeticD: public LBinaryOperation {
 };
 
 
-class LArithmeticT: public LBinaryOperation {
+class LArithmeticT: public LTemplateInstruction<1, 2, 0> {
  public:
   LArithmeticT(Token::Value op, LOperand* left, LOperand* right)
-      : LBinaryOperation(left, right), op_(op) { }
+      : op_(op) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+  }
 
   virtual void CompileToNative(LCodeGen* generator);
   virtual const char* Mnemonic() const;
@@ -1193,166 +1162,186 @@ class LArithmeticT: public LBinaryOperation {
 };
 
 
-class LReturn: public LUnaryOperation {
+class LReturn: public LTemplateInstruction<0, 1, 0> {
  public:
-  explicit LReturn(LOperand* use) : LUnaryOperation(use) { }
+  explicit LReturn(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(Return, "return")
 };
 
 
-class LLoadNamedField: public LUnaryOperation {
+class LLoadNamedField: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LLoadNamedField(LOperand* object) : LUnaryOperation(object) { }
+  explicit LLoadNamedField(LOperand* object) {
+    inputs_[0] = object;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadNamedField, "load-named-field")
   DECLARE_HYDROGEN_ACCESSOR(LoadNamedField)
 };
 
 
-class LLoadNamedGeneric: public LUnaryOperation {
+class LLoadNamedGeneric: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LLoadNamedGeneric(LOperand* object) : LUnaryOperation(object) { }
+  explicit LLoadNamedGeneric(LOperand* object) {
+    inputs_[0] = object;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadNamedGeneric, "load-named-generic")
   DECLARE_HYDROGEN_ACCESSOR(LoadNamedGeneric)
 
-  LOperand* object() const { return input(); }
+  LOperand* object() { return inputs_[0]; }
   Handle<Object> name() const { return hydrogen()->name(); }
 };
 
 
-class LLoadFunctionPrototype: public LUnaryOperation {
+class LLoadFunctionPrototype: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LLoadFunctionPrototype(LOperand* function)
-      : LUnaryOperation(function) { }
+  explicit LLoadFunctionPrototype(LOperand* function) {
+    inputs_[0] = function;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadFunctionPrototype, "load-function-prototype")
   DECLARE_HYDROGEN_ACCESSOR(LoadFunctionPrototype)
 
-  LOperand* function() const { return input(); }
+  LOperand* function() { return inputs_[0]; }
 };
 
 
-class LLoadElements: public LUnaryOperation {
+class LLoadElements: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LLoadElements(LOperand* obj) : LUnaryOperation(obj) { }
+  explicit LLoadElements(LOperand* object) {
+    inputs_[0] = object;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadElements, "load-elements")
 };
 
 
-class LLoadKeyedFastElement: public LBinaryOperation {
+class LLoadKeyedFastElement: public LTemplateInstruction<1, 2, 0> {
  public:
-  LLoadKeyedFastElement(LOperand* elements, LOperand* key)
-      : LBinaryOperation(elements, key) { }
+  LLoadKeyedFastElement(LOperand* elements, LOperand* key) {
+    inputs_[0] = elements;
+    inputs_[1] = key;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastElement, "load-keyed-fast-element")
   DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastElement)
 
-  LOperand* elements() const { return left(); }
-  LOperand* key() const { return right(); }
+  LOperand* elements() { return inputs_[0]; }
+  LOperand* key() { return inputs_[1]; }
 };
 
 
-class LLoadKeyedGeneric: public LBinaryOperation {
+class LLoadKeyedGeneric: public LTemplateInstruction<1, 2, 0> {
  public:
-  LLoadKeyedGeneric(LOperand* obj, LOperand* key)
-      : LBinaryOperation(obj, key) { }
+  LLoadKeyedGeneric(LOperand* obj, LOperand* key) {
+    inputs_[0] = obj;
+    inputs_[1] = key;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(LoadKeyedGeneric, "load-keyed-generic")
 
-  LOperand* object() const { return left(); }
-  LOperand* key() const { return right(); }
+  LOperand* object() { return inputs_[0]; }
+  LOperand* key() { return inputs_[1]; }
 };
 
 
-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 LTemplateInstruction<0, 1, 0> {
  public:
-  explicit LStoreGlobal(LOperand* value) : LUnaryOperation(value) {}
+  explicit LStoreGlobal(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(StoreGlobal, "store-global")
   DECLARE_HYDROGEN_ACCESSOR(StoreGlobal)
 };
 
 
-class LLoadContextSlot: public LInstruction {
+class LLoadContextSlot: public LTemplateInstruction<1, 0, 0> {
  public:
   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(); }
+  int context_chain_length() { return hydrogen()->context_chain_length(); }
+  int slot_index() { return hydrogen()->slot_index(); }
 
   virtual void PrintDataTo(StringStream* stream);
 };
 
 
-class LPushArgument: public LUnaryOperation {
+class LPushArgument: public LTemplateInstruction<0, 1, 0> {
  public:
-  explicit LPushArgument(LOperand* argument) : LUnaryOperation(argument) {}
+  explicit LPushArgument(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   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, 1, 0> {
  public:
+  explicit LCallKeyed(LOperand* key) {
+    inputs_[0] = key;
+  }
+
   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)
@@ -1361,44 +1350,46 @@ class LCallFunction: public LInstruction {
 };
 
 
-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 LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LCallNew(LOperand* constructor) : LUnaryOperation(constructor) { }
+  explicit LCallNew(LOperand* constructor) {
+    inputs_[0] = 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)
@@ -1408,42 +1399,44 @@ class LCallRuntime: public LInstruction {
 };
 
 
-class LInteger32ToDouble: public LUnaryOperation {
+class LInteger32ToDouble: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LInteger32ToDouble(LOperand* use) : LUnaryOperation(use) { }
+  explicit LInteger32ToDouble(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(Integer32ToDouble, "int32-to-double")
 };
 
 
-class LNumberTagI: public LUnaryOperation {
+class LNumberTagI: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LNumberTagI(LOperand* use) : LUnaryOperation(use) { }
+  explicit LNumberTagI(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(NumberTagI, "number-tag-i")
 };
 
 
-class LNumberTagD: public LUnaryOperation {
+class LNumberTagD: public LTemplateInstruction<1, 1, 2> {
  public:
-  LNumberTagD(LOperand* value, LOperand* temp1, LOperand* temp2)
-      : LUnaryOperation(value), temp1_(temp1), temp2_(temp2) { }
+  LNumberTagD(LOperand* value, LOperand* temp1, LOperand* temp2) {
+    inputs_[0] = value;
+    temps_[0] = temp1;
+    temps_[1] = temp2;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(NumberTagD, "number-tag-d")
-
-  LOperand* temp1() const { return temp1_; }
-  LOperand* temp2() const { return temp2_; }
-
- private:
-  LOperand* temp1_;
-  LOperand* temp2_;
 };
 
 
 // Sometimes truncating conversion from a tagged value to an int32.
-class LDoubleToI: public LUnaryOperation {
+class LDoubleToI: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LDoubleToI(LOperand* value) : LUnaryOperation(value) { }
+  explicit LDoubleToI(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(DoubleToI, "double-to-i")
   DECLARE_HYDROGEN_ACCESSOR(Change)
@@ -1453,42 +1446,46 @@ class LDoubleToI: public LUnaryOperation {
 
 
 // Truncating conversion from a tagged value to an int32.
-class LTaggedToI: public LUnaryOperation {
+class LTaggedToI: public LTemplateInstruction<1, 1, 1> {
  public:
-  LTaggedToI(LOperand* value, LOperand* temp)
-      : LUnaryOperation(value), temp_(temp) { }
+  LTaggedToI(LOperand* value, LOperand* temp) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i")
   DECLARE_HYDROGEN_ACCESSOR(Change)
 
   bool truncating() { return hydrogen()->CanTruncateToInt32(); }
-  LOperand* temp() const { return temp_; }
-
- private:
-  LOperand* temp_;
 };
 
 
-class LSmiTag: public LUnaryOperation {
+class LSmiTag: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LSmiTag(LOperand* use) : LUnaryOperation(use) { }
+  explicit LSmiTag(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(SmiTag, "smi-tag")
 };
 
 
-class LNumberUntagD: public LUnaryOperation {
+class LNumberUntagD: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LNumberUntagD(LOperand* value) : LUnaryOperation(value) { }
+  explicit LNumberUntagD(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag")
 };
 
 
-class LSmiUntag: public LUnaryOperation {
+class LSmiUntag: public LTemplateInstruction<1, 1, 0> {
  public:
-  LSmiUntag(LOperand* use, bool needs_check)
-      : LUnaryOperation(use), needs_check_(needs_check) { }
+  LSmiUntag(LOperand* value, bool needs_check)
+      : needs_check_(needs_check) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
 
@@ -1499,23 +1496,21 @@ class LSmiUntag: public LUnaryOperation {
 };
 
 
-class LStoreNamed: public LInstruction {
+class LStoreNamed: public LTemplateInstruction<0, 2, 0> {
  public:
-  LStoreNamed(LOperand* obj, LOperand* val)
-      : object_(obj), value_(val) { }
+  LStoreNamed(LOperand* obj, LOperand* val) {
+    inputs_[0] = obj;
+    inputs_[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_; }
+  LOperand* object() { return inputs_[0]; }
+  LOperand* value() { return inputs_[1]; }
   Handle<Object> name() const { return hydrogen()->name(); }
-  LOperand* value() const { return value_; }
-
- private:
-  LOperand* object_;
-  LOperand* value_;
 };
 
 
@@ -1530,7 +1525,7 @@ class LStoreNamedField: public LStoreNamed {
   bool is_in_object() { return hydrogen()->is_in_object(); }
   int offset() { return hydrogen()->offset(); }
   bool needs_write_barrier() { return hydrogen()->NeedsWriteBarrier(); }
-  Handle<Map> transition() { return hydrogen()->transition(); }
+  Handle<Map> transition() const { return hydrogen()->transition(); }
 };
 
 
@@ -1544,23 +1539,21 @@ class LStoreNamedGeneric: public LStoreNamed {
 };
 
 
-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) {
+    inputs_[0] = obj;
+    inputs_[1] = key;
+    inputs_[2] = val;
+  }
 
   DECLARE_INSTRUCTION(StoreKeyed)
 
-  virtual void PrintDataTo(StringStream* stream) const;
-
-  LOperand* object() const { return object_; }
-  LOperand* key() const { return key_; }
-  LOperand* value() const { return value_; }
+  virtual void PrintDataTo(StringStream* stream);
 
- private:
-  LOperand* object_;
-  LOperand* key_;
-  LOperand* value_;
+  LOperand* object() { return inputs_[0]; }
+  LOperand* key() { return inputs_[1]; }
+  LOperand* value() { return inputs_[2]; }
 };
 
 
@@ -1584,84 +1577,88 @@ class LStoreKeyedGeneric: public LStoreKeyed {
 };
 
 
-class LStringCharCodeAt: public LBinaryOperation {
+class LStringCharCodeAt: public LTemplateInstruction<1, 2, 0> {
  public:
-  LStringCharCodeAt(LOperand* string, LOperand* index)
-      : LBinaryOperation(string, index) {}
+  LStringCharCodeAt(LOperand* string, LOperand* index) {
+    inputs_[0] = string;
+    inputs_[1] = index;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(StringCharCodeAt, "string-char-code-at")
   DECLARE_HYDROGEN_ACCESSOR(StringCharCodeAt)
 
-  LOperand* string() { return left(); }
-  LOperand* index() { return right(); }
+  LOperand* string() { return inputs_[0]; }
+  LOperand* index() { return inputs_[1]; }
 };
 
 
-class LStringLength: public LUnaryOperation {
+class LStringLength: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LStringLength(LOperand* string) : LUnaryOperation(string) {}
+  explicit LStringLength(LOperand* string) {
+    inputs_[0] = string;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(StringLength, "string-length")
   DECLARE_HYDROGEN_ACCESSOR(StringLength)
+
+  LOperand* string() { return inputs_[0]; }
 };
 
 
-class LCheckFunction: public LUnaryOperation {
+class LCheckFunction: public LTemplateInstruction<0, 1, 0> {
  public:
-  explicit LCheckFunction(LOperand* use) : LUnaryOperation(use) { }
+  explicit LCheckFunction(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check-function")
   DECLARE_HYDROGEN_ACCESSOR(CheckFunction)
 };
 
 
-class LCheckInstanceType: public LUnaryOperation {
+class LCheckInstanceType: public LTemplateInstruction<0, 1, 0> {
  public:
-  explicit LCheckInstanceType(LOperand* use) : LUnaryOperation(use) { }
+  explicit LCheckInstanceType(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(CheckInstanceType, "check-instance-type")
   DECLARE_HYDROGEN_ACCESSOR(CheckInstanceType)
-
-  LOperand* temp() const { return temp_; }
-
- private:
-  LOperand* temp_;
 };
 
 
-class LCheckMap: public LUnaryOperation {
+class LCheckMap: public LTemplateInstruction<0, 1, 0> {
  public:
-  explicit LCheckMap(LOperand* use) : LUnaryOperation(use) { }
+  explicit LCheckMap(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(CheckMap, "check-map")
   DECLARE_HYDROGEN_ACCESSOR(CheckMap)
 };
 
 
-class LCheckPrototypeMaps: public LInstruction {
+class LCheckPrototypeMaps: public LTemplateInstruction<0, 0, 2> {
  public:
-  LCheckPrototypeMaps(LOperand* temp1, LOperand* temp2)
-      : temp1_(temp1), temp2_(temp2) { }
+  LCheckPrototypeMaps(LOperand* temp1, LOperand* temp2)  {
+    temps_[0] = temp1;
+    temps_[1] = temp2;
+  }
 
   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* temp1() const { return temp1_; }
-  LOperand* temp2() const { return temp2_; }
-
- private:
-  LOperand* temp1_;
-  LOperand* temp2_;
 };
 
 
-class LCheckSmi: public LUnaryOperation {
+class LCheckSmi: public LTemplateInstruction<0, 1, 0> {
  public:
-  LCheckSmi(LOperand* use, Condition condition)
-      : LUnaryOperation(use), condition_(condition) { }
+  LCheckSmi(LOperand* value, Condition condition)
+      : condition_(condition) {
+    inputs_[0] = value;
+  }
 
   Condition condition() const { return condition_; }
 
@@ -1675,34 +1672,28 @@ class LCheckSmi: public LUnaryOperation {
 };
 
 
-class LMaterializedLiteral: public LInstruction {
- public:
-  DECLARE_INSTRUCTION(MaterializedLiteral)
-};
-
-
-class LArrayLiteral: public LMaterializedLiteral {
+class LArrayLiteral: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(ArrayLiteral, "array-literal")
   DECLARE_HYDROGEN_ACCESSOR(ArrayLiteral)
 };
 
 
-class LObjectLiteral: public LMaterializedLiteral {
+class LObjectLiteral: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(ObjectLiteral, "object-literal")
   DECLARE_HYDROGEN_ACCESSOR(ObjectLiteral)
 };
 
 
-class LRegExpLiteral: public LMaterializedLiteral {
+class LRegExpLiteral: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(RegExpLiteral, "regexp-literal")
   DECLARE_HYDROGEN_ACCESSOR(RegExpLiteral)
 };
 
 
-class LFunctionLiteral: public LInstruction {
+class LFunctionLiteral: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function-literal")
   DECLARE_HYDROGEN_ACCESSOR(FunctionLiteral)
@@ -1711,61 +1702,61 @@ class LFunctionLiteral: public LInstruction {
 };
 
 
-class LTypeof: public LUnaryOperation {
+class LTypeof: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LTypeof(LOperand* input) : LUnaryOperation(input) { }
+  explicit LTypeof(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(Typeof, "typeof")
 };
 
 
-class LTypeofIs: public LUnaryOperation {
+class LTypeofIs: public LTemplateInstruction<1, 1, 0> {
  public:
-  explicit LTypeofIs(LOperand* input) : LUnaryOperation(input) { }
-  virtual void PrintDataTo(StringStream* stream) const;
+  explicit LTypeofIs(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(TypeofIs, "typeof-is")
   DECLARE_HYDROGEN_ACCESSOR(TypeofIs)
 
   Handle<String> type_literal() { return hydrogen()->type_literal(); }
+
+  virtual void PrintDataTo(StringStream* stream);
 };
 
 
-class LTypeofIsAndBranch: public LTypeofIs {
+class LTypeofIsAndBranch: public LControlInstruction<1, 0> {
  public:
-  LTypeofIsAndBranch(LOperand* value,
-                     int true_block_id,
-                     int false_block_id)
-      : LTypeofIs(value),
-        true_block_id_(true_block_id),
-        false_block_id_(false_block_id) { }
+  explicit LTypeofIsAndBranch(LOperand* value) {
+    inputs_[0] = value;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch, "typeof-is-and-branch")
+  DECLARE_HYDROGEN_ACCESSOR(TypeofIs)
 
-  virtual void PrintDataTo(StringStream* stream) const;
-  virtual bool IsControl() const { return true; }
-
-  int true_block_id() const { return true_block_id_; }
-  int false_block_id() const { return false_block_id_; }
+  Handle<String> type_literal() { return hydrogen()->type_literal(); }
 
- private:
-  int true_block_id_;
-  int false_block_id_;
+  virtual void PrintDataTo(StringStream* stream);
 };
 
 
-class LDeleteProperty: public LBinaryOperation {
+class LDeleteProperty: public LTemplateInstruction<1, 2, 0> {
  public:
-  LDeleteProperty(LOperand* obj, LOperand* key) : LBinaryOperation(obj, key) {}
+  LDeleteProperty(LOperand* obj, LOperand* key) {
+    inputs_[0] = obj;
+    inputs_[1] = key;
+  }
 
   DECLARE_CONCRETE_INSTRUCTION(DeleteProperty, "delete-property")
 
-  LOperand* object() const { return left(); }
-  LOperand* key() const { return right(); }
+  LOperand* object() { return inputs_[0]; }
+  LOperand* key() { return inputs_[1]; }
 };
 
 
-class LOsrEntry: public LInstruction {
+class LOsrEntry: public LTemplateInstruction<0, 0, 0> {
  public:
   LOsrEntry();
 
@@ -1788,7 +1779,7 @@ class LOsrEntry: public LInstruction {
 };
 
 
-class LStackCheck: public LInstruction {
+class LStackCheck: public LTemplateInstruction<0, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(StackCheck, "stack-check")
 };
@@ -1844,8 +1835,6 @@ class LChunk: public ZoneObject {
     inlined_closures_.Add(closure);
   }
 
-  void Verify() const;
-
  private:
   int spill_slot_count_;
   HGraph* const graph_;
@@ -1902,9 +1891,10 @@ class LChunkBuilder BASE_EMBEDDED {
   LUnallocated* ToUnallocated(DoubleRegister reg);
 
   // Methods for setting up define-use relationships.
-  LOperand* Use(HValue* value, LUnallocated* operand);
-  LOperand* UseFixed(HValue* value, Register fixed_register);
-  LOperand* UseFixedDouble(HValue* value, DoubleRegister fixed_register);
+  MUST_USE_RESULT LOperand* Use(HValue* value, LUnallocated* operand);
+  MUST_USE_RESULT LOperand* UseFixed(HValue* value, Register fixed_register);
+  MUST_USE_RESULT LOperand* UseFixedDouble(HValue* value,
+                                           DoubleRegister fixed_register);
 
   // A value that is guaranteed to be allocated to a register.
   // Operand created by UseRegister is guaranteed to be live until the end of
@@ -1914,37 +1904,53 @@ class LChunkBuilder BASE_EMBEDDED {
   // instruction start. Register allocator is free to assign the same register
   // to some other operand used inside instruction (i.e. temporary or
   // output).
-  LOperand* UseRegister(HValue* value);
-  LOperand* UseRegisterAtStart(HValue* value);
+  MUST_USE_RESULT LOperand* UseRegister(HValue* value);
+  MUST_USE_RESULT LOperand* UseRegisterAtStart(HValue* value);
 
   // An input operand in a register that may be trashed.
-  LOperand* UseTempRegister(HValue* value);
+  MUST_USE_RESULT LOperand* UseTempRegister(HValue* value);
 
   // An input operand in a register or stack slot.
-  LOperand* Use(HValue* value);
-  LOperand* UseAtStart(HValue* value);
+  MUST_USE_RESULT LOperand* Use(HValue* value);
+  MUST_USE_RESULT LOperand* UseAtStart(HValue* value);
 
   // An input operand in a register, stack slot or a constant operand.
-  LOperand* UseOrConstant(HValue* value);
-  LOperand* UseOrConstantAtStart(HValue* value);
+  MUST_USE_RESULT LOperand* UseOrConstant(HValue* value);
+  MUST_USE_RESULT LOperand* UseOrConstantAtStart(HValue* value);
 
   // An input operand in a register or a constant operand.
-  LOperand* UseRegisterOrConstant(HValue* value);
-  LOperand* UseRegisterOrConstantAtStart(HValue* value);
+  MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value);
+  MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value);
 
   // An input operand in register, stack slot or a constant operand.
   // Will not be moved to a register even if one is freely available.
-  LOperand* UseAny(HValue* value);
+  MUST_USE_RESULT LOperand* UseAny(HValue* value);
+
+  // Temporary operand that must be in a register.
+  MUST_USE_RESULT LUnallocated* TempRegister();
+  MUST_USE_RESULT LOperand* FixedTemp(Register reg);
+  MUST_USE_RESULT LOperand* FixedTemp(DoubleRegister reg);
 
   // 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, DoubleRegister 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,
+                                      DoubleRegister reg);
   LInstruction* AssignEnvironment(LInstruction* instr);
   LInstruction* AssignPointerMap(LInstruction* instr);
 
@@ -1965,11 +1971,6 @@ class LChunkBuilder BASE_EMBEDDED {
 
   LEnvironment* CreateEnvironment(HEnvironment* hydrogen_env);
 
-  // Temporary operand that must be in a register.
-  LUnallocated* TempRegister();
-  LOperand* FixedTemp(Register reg);
-  LOperand* FixedTemp(DoubleRegister reg);
-
   void VisitInstruction(HInstruction* current);
 
   void DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block);
index 8d3c9c2..6abb830 100644 (file)
@@ -1016,8 +1016,8 @@ void LCodeGen::DoModI(LModI* instr) {
     LModI* instr_;
   };
   // These registers hold untagged 32 bit values.
-  Register left = ToRegister(instr->left());
-  Register right = ToRegister(instr->right());
+  Register left = ToRegister(instr->InputAt(0));
+  Register right = ToRegister(instr->InputAt(1));
   Register result = ToRegister(instr->result());
   Register scratch = scratch0();
 
@@ -1102,8 +1102,8 @@ void LCodeGen::DoDivI(LDivI* instr) {
     LDivI* instr_;
   };
 
-  const Register left = ToRegister(instr->left());
-  const Register right = ToRegister(instr->right());
+  const Register left = ToRegister(instr->InputAt(0));
+  const Register right = ToRegister(instr->InputAt(1));
   const Register scratch = scratch0();
   const Register result = ToRegister(instr->result());
 
@@ -1170,10 +1170,11 @@ void LCodeGen::DoDivI(LDivI* instr) {
 }
 
 
-void LCodeGen::DoDeferredGenericBinaryStub(LBinaryOperation* instr,
+template<int T>
+void LCodeGen::DoDeferredGenericBinaryStub(LTemplateInstruction<1, 2, T>* instr,
                                            Token::Value op) {
-  Register left = ToRegister(instr->left());
-  Register right = ToRegister(instr->right());
+  Register left = ToRegister(instr->InputAt(0));
+  Register right = ToRegister(instr->InputAt(1));
 
   __ PushSafepointRegistersAndDoubles();
   GenericBinaryOpStub stub(op, OVERWRITE_LEFT, left, right);
@@ -1190,12 +1191,12 @@ void LCodeGen::DoDeferredGenericBinaryStub(LBinaryOperation* instr,
 
 void LCodeGen::DoMulI(LMulI* instr) {
   Register scratch = scratch0();
-  Register left = ToRegister(instr->left());
-  Register right = EmitLoadRegister(instr->right(), scratch);
+  Register left = ToRegister(instr->InputAt(0));
+  Register right = EmitLoadRegister(instr->InputAt(1), scratch);
 
   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) &&
-      !instr->right()->IsConstantOperand()) {
-    __ orr(ToRegister(instr->temp()), left, right);
+      !instr->InputAt(1)->IsConstantOperand()) {
+    __ orr(ToRegister(instr->TempAt(0)), left, right);
   }
 
   if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
@@ -1213,13 +1214,13 @@ void LCodeGen::DoMulI(LMulI* instr) {
     Label done;
     __ tst(left, Operand(left));
     __ b(ne, &done);
-    if (instr->right()->IsConstantOperand()) {
-      if (ToInteger32(LConstantOperand::cast(instr->right())) < 0) {
+    if (instr->InputAt(1)->IsConstantOperand()) {
+      if (ToInteger32(LConstantOperand::cast(instr->InputAt(1))) < 0) {
         DeoptimizeIf(no_condition, instr->environment());
       }
     } else {
       // Test the non-zero operand for negative sign.
-      __ cmp(ToRegister(instr->temp()), Operand(0));
+      __ cmp(ToRegister(instr->TempAt(0)), Operand(0));
       DeoptimizeIf(mi, instr->environment());
     }
     __ bind(&done);
@@ -1228,8 +1229,8 @@ void LCodeGen::DoMulI(LMulI* instr) {
 
 
 void LCodeGen::DoBitI(LBitI* instr) {
-  LOperand* left = instr->left();
-  LOperand* right = instr->right();
+  LOperand* left = instr->InputAt(0);
+  LOperand* right = instr->InputAt(1);
   ASSERT(left->Equals(instr->result()));
   ASSERT(left->IsRegister());
   Register result = ToRegister(left);
@@ -1253,8 +1254,8 @@ void LCodeGen::DoBitI(LBitI* instr) {
 
 void LCodeGen::DoShiftI(LShiftI* instr) {
   Register scratch = scratch0();
-  LOperand* left = instr->left();
-  LOperand* right = instr->right();
+  LOperand* left = instr->InputAt(0);
+  LOperand* right = instr->InputAt(1);
   ASSERT(left->Equals(instr->result()));
   ASSERT(left->IsRegister());
   Register result = ToRegister(left);
@@ -1311,9 +1312,9 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
 
 
 void LCodeGen::DoSubI(LSubI* instr) {
-  Register left = ToRegister(instr->left());
-  Register right = EmitLoadRegister(instr->right(), ip);
-  ASSERT(instr->left()->Equals(instr->result()));
+  Register left = ToRegister(instr->InputAt(0));
+  Register right = EmitLoadRegister(instr->InputAt(1), ip);
+  ASSERT(instr->InputAt(0)->Equals(instr->result()));
   __ sub(left, left, right, SetCC);
   if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
     DeoptimizeIf(vs, instr->environment());
@@ -1343,22 +1344,22 @@ void LCodeGen::DoConstantT(LConstantT* instr) {
 
 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
   Register result = ToRegister(instr->result());
-  Register array = ToRegister(instr->input());
+  Register array = ToRegister(instr->InputAt(0));
   __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset));
 }
 
 
 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) {
   Register result = ToRegister(instr->result());
-  Register array = ToRegister(instr->input());
+  Register array = ToRegister(instr->InputAt(0));
   __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset));
 }
 
 
 void LCodeGen::DoValueOf(LValueOf* instr) {
-  Register input = ToRegister(instr->input());
+  Register input = ToRegister(instr->InputAt(0));
   Register result = ToRegister(instr->result());
-  Register map = ToRegister(instr->temporary());
+  Register map = ToRegister(instr->TempAt(0));
   ASSERT(input.is(result));
   Label done;
 
@@ -1376,14 +1377,14 @@ void LCodeGen::DoValueOf(LValueOf* instr) {
 
 
 void LCodeGen::DoBitNotI(LBitNotI* instr) {
-  LOperand* input = instr->input();
+  LOperand* input = instr->InputAt(0);
   ASSERT(input->Equals(instr->result()));
   __ mvn(ToRegister(input), Operand(ToRegister(input)));
 }
 
 
 void LCodeGen::DoThrow(LThrow* instr) {
-  Register input_reg = EmitLoadRegister(instr->input(), ip);
+  Register input_reg = EmitLoadRegister(instr->InputAt(0), ip);
   __ push(input_reg);
   CallRuntime(Runtime::kThrow, 1, instr);
 
@@ -1394,8 +1395,8 @@ void LCodeGen::DoThrow(LThrow* instr) {
 
 
 void LCodeGen::DoAddI(LAddI* instr) {
-  LOperand* left = instr->left();
-  LOperand* right = instr->right();
+  LOperand* left = instr->InputAt(0);
+  LOperand* right = instr->InputAt(1);
   ASSERT(left->Equals(instr->result()));
 
   Register right_reg = EmitLoadRegister(right, ip);
@@ -1408,8 +1409,8 @@ void LCodeGen::DoAddI(LAddI* instr) {
 
 
 void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
-  DoubleRegister left = ToDoubleRegister(instr->left());
-  DoubleRegister right = ToDoubleRegister(instr->right());
+  DoubleRegister left = ToDoubleRegister(instr->InputAt(0));
+  DoubleRegister right = ToDoubleRegister(instr->InputAt(1));
   switch (instr->op()) {
     case Token::ADD:
       __ vadd(left, left, right);
@@ -1435,8 +1436,8 @@ void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
 
 
 void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
-  ASSERT(ToRegister(instr->left()).is(r1));
-  ASSERT(ToRegister(instr->right()).is(r0));
+  ASSERT(ToRegister(instr->InputAt(0)).is(r1));
+  ASSERT(ToRegister(instr->InputAt(1)).is(r0));
   ASSERT(ToRegister(instr->result()).is(r0));
 
   // TODO(regis): Implement TypeRecordingBinaryOpStub and replace current
@@ -1480,11 +1481,11 @@ void LCodeGen::DoBranch(LBranch* instr) {
 
   Representation r = instr->hydrogen()->representation();
   if (r.IsInteger32()) {
-    Register reg = ToRegister(instr->input());
+    Register reg = ToRegister(instr->InputAt(0));
     __ cmp(reg, Operand(0));
     EmitBranch(true_block, false_block, nz);
   } else if (r.IsDouble()) {
-    DoubleRegister reg = ToDoubleRegister(instr->input());
+    DoubleRegister reg = ToDoubleRegister(instr->InputAt(0));
     Register scratch = scratch0();
 
     // Test the double value. Zero and NaN are false.
@@ -1493,7 +1494,7 @@ void LCodeGen::DoBranch(LBranch* instr) {
     EmitBranch(true_block, false_block, ne);
   } else {
     ASSERT(r.IsTagged());
-    Register reg = ToRegister(instr->input());
+    Register reg = ToRegister(instr->InputAt(0));
     if (instr->hydrogen()->type().IsBoolean()) {
       __ LoadRoot(ip, Heap::kTrueValueRootIndex);
       __ cmp(reg, ip);
@@ -1636,8 +1637,8 @@ void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
 
 
 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) {
-  Register left = ToRegister(instr->left());
-  Register right = ToRegister(instr->right());
+  Register left = ToRegister(instr->InputAt(0));
+  Register right = ToRegister(instr->InputAt(1));
   Register result = ToRegister(instr->result());
 
   __ cmp(left, Operand(right));
@@ -1647,8 +1648,8 @@ void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) {
 
 
 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) {
-  Register left = ToRegister(instr->left());
-  Register right = ToRegister(instr->right());
+  Register left = ToRegister(instr->InputAt(0));
+  Register right = ToRegister(instr->InputAt(1));
   int false_block = chunk_->LookupDestination(instr->false_block_id());
   int true_block = chunk_->LookupDestination(instr->true_block_id());
 
@@ -1658,7 +1659,7 @@ void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) {
 
 
 void LCodeGen::DoIsNull(LIsNull* instr) {
-  Register reg = ToRegister(instr->input());
+  Register reg = ToRegister(instr->InputAt(0));
   Register result = ToRegister(instr->result());
 
   __ LoadRoot(ip, Heap::kNullValueRootIndex);
@@ -1693,7 +1694,7 @@ void LCodeGen::DoIsNull(LIsNull* instr) {
 
 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
   Register scratch = scratch0();
-  Register reg = ToRegister(instr->input());
+  Register reg = ToRegister(instr->InputAt(0));
 
   // TODO(fsc): If the expression is known to be a smi, then it's
   // definitely not null. Jump to the false block.
@@ -1747,7 +1748,7 @@ void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
 void LCodeGen::DoIsSmi(LIsSmi* instr) {
   ASSERT(instr->hydrogen()->value()->representation().IsTagged());
   Register result = ToRegister(instr->result());
-  Register input_reg = EmitLoadRegister(instr->input(), ip);
+  Register input_reg = EmitLoadRegister(instr->InputAt(0), ip);
   __ tst(input_reg, Operand(kSmiTagMask));
   __ LoadRoot(result, Heap::kTrueValueRootIndex);
   Label done;
@@ -1761,32 +1762,12 @@ void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
   int true_block = chunk_->LookupDestination(instr->true_block_id());
   int false_block = chunk_->LookupDestination(instr->false_block_id());
 
-  Register input_reg = EmitLoadRegister(instr->input(), ip);
+  Register input_reg = EmitLoadRegister(instr->InputAt(0), ip);
   __ tst(input_reg, Operand(kSmiTagMask));
   EmitBranch(true_block, false_block, eq);
 }
 
 
-InstanceType LHasInstanceType::TestType() {
-  InstanceType from = hydrogen()->from();
-  InstanceType to = hydrogen()->to();
-  if (from == FIRST_TYPE) return to;
-  ASSERT(from == to || to == LAST_TYPE);
-  return from;
-}
-
-
-Condition LHasInstanceType::BranchCondition() {
-  InstanceType from = hydrogen()->from();
-  InstanceType to = hydrogen()->to();
-  if (from == to) return eq;
-  if (to == LAST_TYPE) return hs;
-  if (from == FIRST_TYPE) return ls;
-  UNREACHABLE();
-  return eq;
-}
-
-
 static InstanceType TestType(HHasInstanceType* instr) {
   InstanceType from = instr->from();
   InstanceType to = instr->to();
@@ -1808,7 +1789,7 @@ static Condition BranchCondition(HHasInstanceType* instr) {
 
 
 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) {
-  Register input = ToRegister(instr->input());
+  Register input = ToRegister(instr->InputAt(0));
   Register result = ToRegister(instr->result());
 
   ASSERT(instr->hydrogen()->value()->representation().IsTagged());
@@ -1826,7 +1807,7 @@ void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) {
 
 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
   Register scratch = scratch0();
-  Register input = ToRegister(instr->input());
+  Register input = ToRegister(instr->InputAt(0));
 
   int true_block = chunk_->LookupDestination(instr->true_block_id());
   int false_block = chunk_->LookupDestination(instr->false_block_id());
@@ -1836,8 +1817,8 @@ void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
   __ tst(input, Operand(kSmiTagMask));
   __ b(eq, false_label);
 
-  __ CompareObjectType(input, scratch, scratch, instr->TestType());
-  EmitBranch(true_block, false_block, instr->BranchCondition());
+  __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen()));
+  EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen()));
 }
 
 
@@ -1910,7 +1891,7 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
 
 
 void LCodeGen::DoClassOfTest(LClassOfTest* instr) {
-  Register input = ToRegister(instr->input());
+  Register input = ToRegister(instr->InputAt(0));
   Register result = ToRegister(instr->result());
   ASSERT(input.is(result));
   Handle<String> class_name = instr->hydrogen()->class_name();
@@ -1931,9 +1912,9 @@ void LCodeGen::DoClassOfTest(LClassOfTest* instr) {
 
 
 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
-  Register input = ToRegister(instr->input());
+  Register input = ToRegister(instr->InputAt(0));
   Register temp = scratch0();
-  Register temp2 = ToRegister(instr->temporary());
+  Register temp2 = ToRegister(instr->TempAt(0));
   Handle<String> class_name = instr->hydrogen()->class_name();
 
   int true_block = chunk_->LookupDestination(instr->true_block_id());
@@ -1949,8 +1930,8 @@ void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
 
 
 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
-  Register reg = ToRegister(instr->input());
-  Register temp = ToRegister(instr->temp());
+  Register reg = ToRegister(instr->InputAt(0));
+  Register temp = ToRegister(instr->TempAt(0));
   int true_block = instr->true_block_id();
   int false_block = instr->false_block_id();
 
@@ -1961,8 +1942,8 @@ void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
 
 
 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
-  ASSERT(ToRegister(instr->left()).is(r0));  // Object is in r0.
-  ASSERT(ToRegister(instr->right()).is(r1));  // Function is in r1.
+  ASSERT(ToRegister(instr->InputAt(0)).is(r0));  // Object is in r0.
+  ASSERT(ToRegister(instr->InputAt(1)).is(r1));  // Function is in r1.
 
   InstanceofStub stub(InstanceofStub::kArgsInRegisters);
   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
@@ -2000,8 +1981,8 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
   deferred = new DeferredInstanceOfKnownGlobal(this, instr);
 
   Label done, false_result;
-  Register object = ToRegister(instr->input());
-  Register temp = ToRegister(instr->temp());
+  Register object = ToRegister(instr->InputAt(0));
+  Register temp = ToRegister(instr->TempAt(0));
   Register result = ToRegister(instr->result());
 
   ASSERT(object.is(r0));
@@ -2073,7 +2054,7 @@ void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
   // Get the temp register reserved by the instruction. This needs to be r4 as
   // its slot of the pushing of safepoint registers is used to communicate the
   // offset to the location of the map check.
-  Register temp = ToRegister(instr->temp());
+  Register temp = ToRegister(instr->TempAt(0));
   ASSERT(temp.is(r4));
   __ mov(InstanceofStub::right(), Operand(instr->function()));
   static const int kAdditionalDelta = 4;
@@ -2169,7 +2150,7 @@ void LCodeGen::DoLoadGlobal(LLoadGlobal* instr) {
 
 
 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) {
-  Register value = ToRegister(instr->input());
+  Register value = ToRegister(instr->InputAt(0));
   __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell())));
   __ str(value, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
 }
@@ -2184,7 +2165,7 @@ void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
 
 
 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
-  Register object = ToRegister(instr->input());
+  Register object = ToRegister(instr->InputAt(0));
   Register result = ToRegister(instr->result());
   if (instr->hydrogen()->is_in_object()) {
     __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset()));
@@ -2251,8 +2232,8 @@ void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
 
 
 void LCodeGen::DoLoadElements(LLoadElements* instr) {
-  ASSERT(instr->result()->Equals(instr->input()));
-  Register reg = ToRegister(instr->input());
+  ASSERT(instr->result()->Equals(instr->InputAt(0)));
+  Register reg = ToRegister(instr->InputAt(0));
   Register scratch = scratch0();
 
   __ ldr(reg, FieldMemOperand(reg, JSObject::kElementsOffset));
@@ -2333,7 +2314,7 @@ void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
 
 
 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
-  Register elem = ToRegister(instr->input());
+  Register elem = ToRegister(instr->InputAt(0));
   Register result = ToRegister(instr->result());
 
   Label done;
@@ -2418,7 +2399,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
 
 
 void LCodeGen::DoPushArgument(LPushArgument* instr) {
-  LOperand* argument = instr->input();
+  LOperand* argument = instr->InputAt(0);
   if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) {
     Abort("DoPushArgument not implemented for double type.");
   } else {
@@ -2482,7 +2463,7 @@ void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
 
 
 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
-  Register input = ToRegister(instr->input());
+  Register input = ToRegister(instr->InputAt(0));
   Register scratch = scratch0();
 
   // Deoptimize if not a heap number.
@@ -2546,7 +2527,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
   Label is_positive;
   uint32_t kSignMask = 0x80000000u;
-  Register input = ToRegister(instr->input());
+  Register input = ToRegister(instr->InputAt(0));
   __ tst(input, Operand(kSignMask));
   __ b(eq, &is_positive);
   __ rsb(input, input, Operand(0), SetCC);
@@ -2570,10 +2551,10 @@ void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
     LUnaryMathOperation* instr_;
   };
 
-  ASSERT(instr->input()->Equals(instr->result()));
+  ASSERT(instr->InputAt(0)->Equals(instr->result()));
   Representation r = instr->hydrogen()->value()->representation();
   if (r.IsDouble()) {
-    DwVfpRegister input = ToDoubleRegister(instr->input());
+    DwVfpRegister input = ToDoubleRegister(instr->InputAt(0));
     // __ vabs(input, input);
     Abort("Double DoMathAbs unimplemented");
   } else if (r.IsInteger32()) {
@@ -2582,7 +2563,7 @@ void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
     // Representation is tagged.
     DeferredMathAbsTaggedHeapNumber* deferred =
         new DeferredMathAbsTaggedHeapNumber(this, instr);
-    Register input = ToRegister(instr->input());
+    Register input = ToRegister(instr->InputAt(0));
     // Smi check.
     __ BranchOnNotSmi(input, deferred->entry());
     // If smi, handle it directly.
@@ -2593,9 +2574,9 @@ void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
 
 
 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
-  DoubleRegister input = ToDoubleRegister(instr->input());
+  DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
   Register result = ToRegister(instr->result());
-  Register prev_fpscr = ToRegister(instr->temp());
+  Register prev_fpscr = ToRegister(instr->TempAt(0));
   SwVfpRegister single_scratch = double_scratch0().low();
   Register scratch = scratch0();
 
@@ -2637,7 +2618,7 @@ void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
 
 
 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
-  DoubleRegister input = ToDoubleRegister(instr->input());
+  DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
   ASSERT(ToDoubleRegister(instr->result()).is(input));
   __ vsqrt(input, input);
 }
@@ -2713,7 +2694,7 @@ void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
 
 
 void LCodeGen::DoCallNew(LCallNew* instr) {
-  ASSERT(ToRegister(instr->input()).is(r1));
+  ASSERT(ToRegister(instr->InputAt(0)).is(r1));
   ASSERT(ToRegister(instr->result()).is(r0));
 
   Handle<Code> builtin(Builtins::builtin(Builtins::JSConstructCall));
@@ -2955,14 +2936,14 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
 
 
 void LCodeGen::DoStringLength(LStringLength* instr) {
-  Register string = ToRegister(instr->input());
+  Register string = ToRegister(instr->InputAt(0));
   Register result = ToRegister(instr->result());
   __ ldr(result, FieldMemOperand(string, String::kLengthOffset));
 }
 
 
 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
-  LOperand* input = instr->input();
+  LOperand* input = instr->InputAt(0);
   ASSERT(input->IsRegister() || input->IsStackSlot());
   LOperand* output = instr->result();
   ASSERT(output->IsDoubleRegister());
@@ -2988,7 +2969,7 @@ void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
     LNumberTagI* instr_;
   };
 
-  LOperand* input = instr->input();
+  LOperand* input = instr->InputAt(0);
   ASSERT(input->IsRegister() && input->Equals(instr->result()));
   Register reg = ToRegister(input);
 
@@ -3001,7 +2982,7 @@ void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
 
 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) {
   Label slow;
-  Register reg = ToRegister(instr->input());
+  Register reg = ToRegister(instr->InputAt(0));
   DoubleRegister dbl_scratch = d0;
   SwVfpRegister flt_scratch = s0;
 
@@ -3058,11 +3039,11 @@ void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
     LNumberTagD* instr_;
   };
 
-  DoubleRegister input_reg = ToDoubleRegister(instr->input());
+  DoubleRegister input_reg = ToDoubleRegister(instr->InputAt(0));
   Register scratch = scratch0();
   Register reg = ToRegister(instr->result());
-  Register temp1 = ToRegister(instr->temp1());
-  Register temp2 = ToRegister(instr->temp2());
+  Register temp1 = ToRegister(instr->TempAt(0));
+  Register temp2 = ToRegister(instr->TempAt(1));
 
   DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr);
   if (FLAG_inline_new) {
@@ -3095,7 +3076,7 @@ void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
 
 
 void LCodeGen::DoSmiTag(LSmiTag* instr) {
-  LOperand* input = instr->input();
+  LOperand* input = instr->InputAt(0);
   ASSERT(input->IsRegister() && input->Equals(instr->result()));
   ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow));
   __ SmiTag(ToRegister(input));
@@ -3103,7 +3084,7 @@ void LCodeGen::DoSmiTag(LSmiTag* instr) {
 
 
 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
-  LOperand* input = instr->input();
+  LOperand* input = instr->InputAt(0);
   ASSERT(input->IsRegister() && input->Equals(instr->result()));
   if (instr->needs_check()) {
     __ tst(ToRegister(input), Operand(kSmiTagMask));
@@ -3170,11 +3151,11 @@ class DeferredTaggedToI: public LDeferredCode {
 
 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
   Label done;
-  Register input_reg = ToRegister(instr->input());
+  Register input_reg = ToRegister(instr->InputAt(0));
   Register scratch = scratch0();
   DoubleRegister dbl_scratch = d0;
   SwVfpRegister flt_scratch = s0;
-  DoubleRegister dbl_tmp = ToDoubleRegister(instr->temp());
+  DoubleRegister dbl_tmp = ToDoubleRegister(instr->TempAt(0));
 
   // Heap number map check.
   __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
@@ -3231,7 +3212,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
 
 
 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
-  LOperand* input = instr->input();
+  LOperand* input = instr->InputAt(0);
   ASSERT(input->IsRegister());
   ASSERT(input->Equals(instr->result()));
 
@@ -3251,7 +3232,7 @@ void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
 
 
 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
-  LOperand* input = instr->input();
+  LOperand* input = instr->InputAt(0);
   ASSERT(input->IsRegister());
   LOperand* result = instr->result();
   ASSERT(result->IsDoubleRegister());
@@ -3269,7 +3250,7 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
 
 
 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
-  LOperand* input = instr->input();
+  LOperand* input = instr->InputAt(0);
   ASSERT(input->IsRegister());
   __ tst(ToRegister(input), Operand(kSmiTagMask));
   DeoptimizeIf(instr->condition(), instr->environment());
@@ -3277,7 +3258,7 @@ void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
 
 
 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
-  Register input = ToRegister(instr->input());
+  Register input = ToRegister(instr->InputAt(0));
   Register scratch = scratch0();
   InstanceType first = instr->hydrogen()->first();
   InstanceType last = instr->hydrogen()->last();
@@ -3301,8 +3282,8 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
 
 
 void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
-  ASSERT(instr->input()->IsRegister());
-  Register reg = ToRegister(instr->input());
+  ASSERT(instr->InputAt(0)->IsRegister());
+  Register reg = ToRegister(instr->InputAt(0));
   __ cmp(reg, Operand(instr->hydrogen()->target()));
   DeoptimizeIf(ne, instr->environment());
 }
@@ -3310,7 +3291,7 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
 
 void LCodeGen::DoCheckMap(LCheckMap* instr) {
   Register scratch = scratch0();
-  LOperand* input = instr->input();
+  LOperand* input = instr->InputAt(0);
   ASSERT(input->IsRegister());
   Register reg = ToRegister(input);
   __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
@@ -3333,8 +3314,8 @@ void LCodeGen::LoadHeapObject(Register result,
 
 
 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
-  Register temp1 = ToRegister(instr->temp1());
-  Register temp2 = ToRegister(instr->temp2());
+  Register temp1 = ToRegister(instr->TempAt(0));
+  Register temp2 = ToRegister(instr->TempAt(1));
 
   Handle<JSObject> holder = instr->holder();
   Handle<JSObject> current_prototype = instr->prototype();
@@ -3482,14 +3463,14 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
 
 
 void LCodeGen::DoTypeof(LTypeof* instr) {
-  Register input = ToRegister(instr->input());
+  Register input = ToRegister(instr->InputAt(0));
   __ push(input);
   CallRuntime(Runtime::kTypeof, 1, instr);
 }
 
 
 void LCodeGen::DoTypeofIs(LTypeofIs* instr) {
-  Register input = ToRegister(instr->input());
+  Register input = ToRegister(instr->InputAt(0));
   Register result = ToRegister(instr->result());
   Label true_label;
   Label false_label;
@@ -3512,7 +3493,7 @@ void LCodeGen::DoTypeofIs(LTypeofIs* instr) {
 
 
 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
-  Register input = ToRegister(instr->input());
+  Register input = ToRegister(instr->InputAt(0));
   int true_block = chunk_->LookupDestination(instr->true_block_id());
   int false_block = chunk_->LookupDestination(instr->false_block_id());
   Label* true_label = chunk_->GetAssemblyLabel(true_block);
index cfdfdf6..3b2ad80 100644 (file)
@@ -93,7 +93,9 @@ class LCodeGen BASE_EMBEDDED {
   void FinishCode(Handle<Code> code);
 
   // Deferred code support.
-  void DoDeferredGenericBinaryStub(LBinaryOperation* instr, Token::Value op);
+  template<int T>
+  void DoDeferredGenericBinaryStub(LTemplateInstruction<1, 2, T>* instr,
+                                   Token::Value op);
   void DoDeferredNumberTagD(LNumberTagD* instr);
   void DoDeferredNumberTagI(LNumberTagI* instr);
   void DoDeferredTaggedToI(LTaggedToI* instr);
index 554cc02..f422514 100644 (file)
@@ -921,9 +921,6 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
       instr = AssignEnvironment(instr);
     }
     if (current->IsTest() && !instr->IsGoto()) {
-      // TODO(fschneider): Handle test instructions uniformly like
-      // other instructions. This requires us to generate the right
-      // branch instruction already at the HIR level.
       ASSERT(instr->IsControl());
       HTest* test = HTest::cast(current);
       instr->set_hydrogen_value(test->value());
index b63b00d..1cdd31e 100644 (file)
@@ -339,32 +339,35 @@ class LInstruction: public ZoneObject {
 };
 
 
-template<typename T, int N>
+template<typename ElementType, int NumElements>
 class OperandContainer {
  public:
   OperandContainer() {
-    for (int i = 0; i < N; i++) elems_[i] = NULL;
+    for (int i = 0; i < NumElements; i++) elems_[i] = NULL;
   }
-  int length() { return N; }
-  T& operator[](int i) {
+  int length() { return NumElements; }
+  ElementType& operator[](int i) {
     ASSERT(i < length());
     return elems_[i];
   }
   void PrintOperandsTo(StringStream* stream);
 
  private:
-  T elems_[N];
+  ElementType elems_[NumElements];
 };
 
 
-template<typename T>
-class OperandContainer<T, 0> {
+template<typename ElementType>
+class OperandContainer<ElementType, 0> {
  public:
   int length() { return 0; }
   void PrintOperandsTo(StringStream* stream) { }
 };
 
 
+// R = number of result operands (0 or 1).
+// I = number of input operands.
+// T = number of temporary operands.
 template<int R, int I, int T>
 class LTemplateInstruction: public LInstruction {
  public:
@@ -1436,7 +1439,7 @@ class LNumberTagI: public LTemplateInstruction<1, 1, 0> {
 
 class LNumberTagD: public LTemplateInstruction<1, 1, 1> {
  public:
-  explicit LNumberTagD(LOperand* value, LOperand* temp) {
+  LNumberTagD(LOperand* value, LOperand* temp) {
     inputs_[0] = value;
     temps_[0] = temp;
   }
index a63a43e..eff6d51 100644 (file)
@@ -848,9 +848,6 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
       instr = AssignEnvironment(instr);
     }
     if (current->IsTest() && !instr->IsGoto()) {
-      // TODO(fschneider): Handle test instructions uniformly like
-      // other instructions. This requires us to generate the right
-      // branch instruction already at the HIR level.
       ASSERT(instr->IsControl());
       HTest* test = HTest::cast(current);
       instr->set_hydrogen_value(test->value());
index e1edbf5..9b7d568 100644 (file)
@@ -335,32 +335,35 @@ class LInstruction: public ZoneObject {
 };
 
 
-template<typename T, int N>
+template<typename ElementType, int NumElements>
 class OperandContainer {
  public:
   OperandContainer() {
-    for (int i = 0; i < N; i++) elems_[i] = NULL;
+    for (int i = 0; i < NumElements; i++) elems_[i] = NULL;
   }
-  int length() { return N; }
-  T& operator[](int i) {
+  int length() { return NumElements; }
+  ElementType& operator[](int i) {
     ASSERT(i < length());
     return elems_[i];
   }
   void PrintOperandsTo(StringStream* stream);
 
  private:
-  T elems_[N];
+  ElementType elems_[NumElements];
 };
 
 
-template<typename T>
-class OperandContainer<T, 0> {
+template<typename ElementType>
+class OperandContainer<ElementType, 0> {
  public:
   int length() { return 0; }
   void PrintOperandsTo(StringStream* stream) { }
 };
 
 
+// R = number of result operands (0 or 1).
+// I = number of input operands.
+// T = number of temporary operands.
 template<int R, int I, int T>
 class LTemplateInstruction: public LInstruction {
  public: