Revert "Revert "Upgrade to 5.0.71.48"" DO NOT MERGE

This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.

FPIIM-449

Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
(cherry picked from commit 109988c7ccb6f3fd1a58574fa3dfb88beaef6632)
diff --git a/test/unittests/interpreter/bytecode-array-builder-unittest.cc b/test/unittests/interpreter/bytecode-array-builder-unittest.cc
index 2140aa8..839215f 100644
--- a/test/unittests/interpreter/bytecode-array-builder-unittest.cc
+++ b/test/unittests/interpreter/bytecode-array-builder-unittest.cc
@@ -21,14 +21,16 @@
 
 
 TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
-  BytecodeArrayBuilder builder(isolate(), zone());
+  BytecodeArrayBuilder builder(isolate(), zone(), 0, 1, 131);
 
-  builder.set_locals_count(200);
-  builder.set_context_count(1);
-  builder.set_parameter_count(0);
-  CHECK_EQ(builder.locals_count(), 200);
+  CHECK_EQ(builder.locals_count(), 131);
   CHECK_EQ(builder.context_count(), 1);
-  CHECK_EQ(builder.fixed_register_count(), 201);
+  CHECK_EQ(builder.fixed_register_count(), 132);
+
+  // Emit argument creation operations.
+  builder.CreateArguments(CreateArgumentsType::kMappedArguments)
+      .CreateArguments(CreateArgumentsType::kUnmappedArguments)
+      .CreateArguments(CreateArgumentsType::kRestParameter);
 
   // Emit constant loads.
   builder.LoadLiteral(Smi::FromInt(0))
@@ -40,32 +42,23 @@
       .LoadTrue()
       .LoadFalse();
 
-  // Emit accumulator transfers. Stores followed by loads to the same register
-  // are not generated. Hence, a dummy instruction in between.
   Register reg(0);
+  Register other(reg.index() + 1);
+  Register wide(128);
+
   builder.LoadAccumulatorWithRegister(reg)
       .LoadNull()
       .StoreAccumulatorInRegister(reg);
 
   // Emit register-register transfer.
-  Register other(1);
   builder.MoveRegister(reg, other);
-
-  // Emit register-register exchanges.
-  Register wide(150);
-  builder.ExchangeRegisters(reg, wide);
-  builder.ExchangeRegisters(wide, reg);
-  Register wider(151);
-  builder.ExchangeRegisters(wide, wider);
+  builder.MoveRegister(reg, wide);
 
   // Emit global load / store operations.
   Factory* factory = isolate()->factory();
   Handle<String> name = factory->NewStringFromStaticChars("var_name");
-  builder.LoadGlobal(name, 1, LanguageMode::SLOPPY,
-                     TypeofMode::NOT_INSIDE_TYPEOF)
-      .LoadGlobal(name, 1, LanguageMode::STRICT, TypeofMode::NOT_INSIDE_TYPEOF)
-      .LoadGlobal(name, 1, LanguageMode::SLOPPY, TypeofMode::INSIDE_TYPEOF)
-      .LoadGlobal(name, 1, LanguageMode::STRICT, TypeofMode::INSIDE_TYPEOF)
+  builder.LoadGlobal(name, 1, TypeofMode::NOT_INSIDE_TYPEOF)
+      .LoadGlobal(name, 1, TypeofMode::INSIDE_TYPEOF)
       .StoreGlobal(name, 1, LanguageMode::SLOPPY)
       .StoreGlobal(name, 1, LanguageMode::STRICT);
 
@@ -76,12 +69,10 @@
       .StoreContextSlot(reg, 1);
 
   // Emit load / store property operations.
-  builder.LoadNamedProperty(reg, name, 0, LanguageMode::SLOPPY)
-      .LoadKeyedProperty(reg, 0, LanguageMode::SLOPPY)
+  builder.LoadNamedProperty(reg, name, 0)
+      .LoadKeyedProperty(reg, 0)
       .StoreNamedProperty(reg, name, 0, LanguageMode::SLOPPY)
       .StoreKeyedProperty(reg, reg, 0, LanguageMode::SLOPPY)
-      .LoadNamedProperty(reg, name, 0, LanguageMode::STRICT)
-      .LoadKeyedProperty(reg, 0, LanguageMode::STRICT)
       .StoreNamedProperty(reg, name, 0, LanguageMode::STRICT)
       .StoreKeyedProperty(reg, reg, 0, LanguageMode::STRICT);
 
@@ -97,65 +88,64 @@
       false);
   builder.CreateClosure(shared_info, NOT_TENURED);
 
-  // Emit argument creation operations.
-  builder.CreateArguments(CreateArgumentsType::kMappedArguments)
-      .CreateArguments(CreateArgumentsType::kUnmappedArguments);
-
   // Emit literal creation operations.
   builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("a"), 0, 0)
       .CreateArrayLiteral(factory->NewFixedArray(1), 0, 0)
       .CreateObjectLiteral(factory->NewFixedArray(1), 0, 0);
 
   // Call operations.
-  builder.Call(reg, reg, 0, 0)
-      .Call(reg, reg, 0, 1024)
+  builder.Call(reg, other, 1, 0)
+      .Call(reg, wide, 1, 0)
+      .TailCall(reg, other, 1, 0)
+      .TailCall(reg, wide, 1, 0)
       .CallRuntime(Runtime::kIsArray, reg, 1)
-      .CallRuntimeForPair(Runtime::kLoadLookupSlot, reg, 1, reg)
-      .CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, reg, 1);
+      .CallRuntime(Runtime::kIsArray, wide, 1)
+      .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, reg, 1, other)
+      .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, wide, 1, other)
+      .CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, reg, 1)
+      .CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, wide, 1);
 
   // Emit binary operator invocations.
-  builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
-      .BinaryOperation(Token::Value::SUB, reg, Strength::WEAK)
-      .BinaryOperation(Token::Value::MUL, reg, Strength::WEAK)
-      .BinaryOperation(Token::Value::DIV, reg, Strength::WEAK)
-      .BinaryOperation(Token::Value::MOD, reg, Strength::WEAK);
+  builder.BinaryOperation(Token::Value::ADD, reg)
+      .BinaryOperation(Token::Value::SUB, reg)
+      .BinaryOperation(Token::Value::MUL, reg)
+      .BinaryOperation(Token::Value::DIV, reg)
+      .BinaryOperation(Token::Value::MOD, reg);
 
   // Emit bitwise operator invocations
-  builder.BinaryOperation(Token::Value::BIT_OR, reg, Strength::WEAK)
-      .BinaryOperation(Token::Value::BIT_XOR, reg, Strength::WEAK)
-      .BinaryOperation(Token::Value::BIT_AND, reg, Strength::WEAK);
+  builder.BinaryOperation(Token::Value::BIT_OR, reg)
+      .BinaryOperation(Token::Value::BIT_XOR, reg)
+      .BinaryOperation(Token::Value::BIT_AND, reg);
 
   // Emit shift operator invocations
-  builder.BinaryOperation(Token::Value::SHL, reg, Strength::WEAK)
-      .BinaryOperation(Token::Value::SAR, reg, Strength::WEAK)
-      .BinaryOperation(Token::Value::SHR, reg, Strength::WEAK);
+  builder.BinaryOperation(Token::Value::SHL, reg)
+      .BinaryOperation(Token::Value::SAR, reg)
+      .BinaryOperation(Token::Value::SHR, reg);
 
   // Emit count operatior invocations
-  builder.CountOperation(Token::Value::ADD, Strength::WEAK)
-      .CountOperation(Token::Value::SUB, Strength::WEAK);
+  builder.CountOperation(Token::Value::ADD).CountOperation(Token::Value::SUB);
 
   // Emit unary operator invocations.
   builder.LogicalNot().TypeOf();
 
   // Emit delete
-  builder.Delete(reg, LanguageMode::SLOPPY)
-      .Delete(reg, LanguageMode::STRICT)
-      .DeleteLookupSlot();
+  builder.Delete(reg, LanguageMode::SLOPPY).Delete(reg, LanguageMode::STRICT);
 
   // Emit new.
   builder.New(reg, reg, 0);
+  builder.New(wide, wide, 0);
 
   // Emit test operator invocations.
-  builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
-      .CompareOperation(Token::Value::NE, reg, Strength::WEAK)
-      .CompareOperation(Token::Value::EQ_STRICT, reg, Strength::WEAK)
-      .CompareOperation(Token::Value::NE_STRICT, reg, Strength::WEAK)
-      .CompareOperation(Token::Value::LT, reg, Strength::WEAK)
-      .CompareOperation(Token::Value::GT, reg, Strength::WEAK)
-      .CompareOperation(Token::Value::LTE, reg, Strength::WEAK)
-      .CompareOperation(Token::Value::GTE, reg, Strength::WEAK)
-      .CompareOperation(Token::Value::INSTANCEOF, reg, Strength::WEAK)
-      .CompareOperation(Token::Value::IN, reg, Strength::WEAK);
+  builder.CompareOperation(Token::Value::EQ, reg)
+      .CompareOperation(Token::Value::NE, reg)
+      .CompareOperation(Token::Value::EQ_STRICT, reg)
+      .CompareOperation(Token::Value::NE_STRICT, reg)
+      .CompareOperation(Token::Value::LT, reg)
+      .CompareOperation(Token::Value::GT, reg)
+      .CompareOperation(Token::Value::LTE, reg)
+      .CompareOperation(Token::Value::GTE, reg)
+      .CompareOperation(Token::Value::INSTANCEOF, reg)
+      .CompareOperation(Token::Value::IN, reg);
 
   // Emit cast operator invocations.
   builder.CastAccumulatorToNumber()
@@ -168,50 +158,58 @@
   // Short jumps with Imm8 operands
   builder.Jump(&start)
       .JumpIfNull(&start)
-      .JumpIfUndefined(&start);
+      .JumpIfUndefined(&start)
+      .JumpIfNotHole(&start);
+
   // Perform an operation that returns boolean value to
   // generate JumpIfTrue/False
-  builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+  builder.CompareOperation(Token::Value::EQ, reg)
       .JumpIfTrue(&start)
-      .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+      .CompareOperation(Token::Value::EQ, reg)
       .JumpIfFalse(&start);
   // Perform an operation that returns a non-boolean operation to
   // generate JumpIfToBooleanTrue/False.
-  builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+  builder.BinaryOperation(Token::Value::ADD, reg)
       .JumpIfTrue(&start)
-      .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfFalse(&start);
   // Insert dummy ops to force longer jumps
   for (int i = 0; i < 128; i++) {
     builder.LoadTrue();
   }
   // Longer jumps requiring Constant operand
-  builder.Jump(&start)
-      .JumpIfNull(&start)
-      .JumpIfUndefined(&start);
+  builder.Jump(&start).JumpIfNull(&start).JumpIfUndefined(&start).JumpIfNotHole(
+      &start);
   // Perform an operation that returns boolean value to
   // generate JumpIfTrue/False
-  builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+  builder.CompareOperation(Token::Value::EQ, reg)
       .JumpIfTrue(&start)
-      .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+      .CompareOperation(Token::Value::EQ, reg)
       .JumpIfFalse(&start);
   // Perform an operation that returns a non-boolean operation to
   // generate JumpIfToBooleanTrue/False.
-  builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+  builder.BinaryOperation(Token::Value::ADD, reg)
       .JumpIfTrue(&start)
-      .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfFalse(&start);
 
-  // Emit throw in it's own basic block so that the rest of the code isn't
-  // omitted due to being dead.
-  BytecodeLabel after_throw;
-  builder.Jump(&after_throw)
-    .Throw()
-    .Bind(&after_throw);
+  // Emit stack check bytecode.
+  builder.StackCheck();
 
-  builder.ForInPrepare(reg, reg, reg)
+  // Emit throw and re-throw in it's own basic block so that the rest of the
+  // code isn't omitted due to being dead.
+  BytecodeLabel after_throw;
+  builder.Jump(&after_throw).Throw().Bind(&after_throw);
+  BytecodeLabel after_rethrow;
+  builder.Jump(&after_rethrow).ReThrow().Bind(&after_rethrow);
+
+  builder.ForInPrepare(reg)
       .ForInDone(reg, reg)
-      .ForInNext(reg, reg, reg, reg)
+      .ForInNext(reg, reg, reg)
+      .ForInStep(reg);
+  builder.ForInPrepare(wide)
+      .ForInDone(reg, other)
+      .ForInNext(wide, wide, wide)
       .ForInStep(reg);
 
   // Wide constant pool loads
@@ -223,28 +221,21 @@
   Handle<String> wide_name = factory->NewStringFromStaticChars("var_wide_name");
 
   // Emit wide global load / store operations.
-  builder.LoadGlobal(name, 1024, LanguageMode::SLOPPY,
-                     TypeofMode::NOT_INSIDE_TYPEOF)
-      .LoadGlobal(wide_name, 1, LanguageMode::STRICT,
-                  TypeofMode::NOT_INSIDE_TYPEOF)
-      .LoadGlobal(name, 1024, LanguageMode::SLOPPY, TypeofMode::INSIDE_TYPEOF)
-      .LoadGlobal(wide_name, 1, LanguageMode::STRICT, TypeofMode::INSIDE_TYPEOF)
+  builder.LoadGlobal(name, 1024, TypeofMode::NOT_INSIDE_TYPEOF)
+      .LoadGlobal(name, 1024, TypeofMode::INSIDE_TYPEOF)
       .StoreGlobal(name, 1024, LanguageMode::SLOPPY)
       .StoreGlobal(wide_name, 1, LanguageMode::STRICT);
 
   // Emit wide load / store property operations.
-  builder.LoadNamedProperty(reg, wide_name, 0, LanguageMode::SLOPPY)
-      .LoadKeyedProperty(reg, 2056, LanguageMode::SLOPPY)
+  builder.LoadNamedProperty(reg, wide_name, 0)
+      .LoadKeyedProperty(reg, 2056)
       .StoreNamedProperty(reg, wide_name, 0, LanguageMode::SLOPPY)
       .StoreKeyedProperty(reg, reg, 2056, LanguageMode::SLOPPY)
-      .LoadNamedProperty(reg, wide_name, 0, LanguageMode::STRICT)
-      .LoadKeyedProperty(reg, 2056, LanguageMode::STRICT)
       .StoreNamedProperty(reg, wide_name, 0, LanguageMode::STRICT)
       .StoreKeyedProperty(reg, reg, 2056, LanguageMode::STRICT);
 
   // Emit wide context operations.
-  builder.LoadContextSlot(reg, 1024)
-      .StoreContextSlot(reg, 1024);
+  builder.LoadContextSlot(reg, 1024).StoreContextSlot(reg, 1024);
 
   // Emit wide load / store lookup slots.
   builder.LoadLookupSlot(wide_name, TypeofMode::NOT_INSIDE_TYPEOF)
@@ -265,26 +256,31 @@
       .CreateObjectLiteral(factory->NewFixedArray(2), 0, 0);
 
   // Longer jumps requiring ConstantWide operand
-  builder.Jump(&start).JumpIfNull(&start).JumpIfUndefined(&start);
+  builder.Jump(&start).JumpIfNull(&start).JumpIfUndefined(&start).JumpIfNotHole(
+      &start);
   // Perform an operation that returns boolean value to
   // generate JumpIfTrue/False
-  builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+  builder.CompareOperation(Token::Value::EQ, reg)
       .JumpIfTrue(&start)
-      .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+      .CompareOperation(Token::Value::EQ, reg)
       .JumpIfFalse(&start);
   // Perform an operation that returns a non-boolean operation to
   // generate JumpIfToBooleanTrue/False.
-  builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+  builder.BinaryOperation(Token::Value::ADD, reg)
       .JumpIfTrue(&start)
-      .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfFalse(&start);
 
+  builder.Debugger();
+
   builder.Return();
 
   // Generate BytecodeArray.
   Handle<BytecodeArray> the_array = builder.ToBytecodeArray();
   CHECK_EQ(the_array->frame_size(),
-           builder.fixed_register_count() * kPointerSize);
+           (builder.fixed_and_temporary_register_count() +
+            builder.translation_register_count()) *
+               kPointerSize);
 
   // Build scorecard of bytecodes encountered in the BytecodeArray.
   std::vector<int> scorecard(Bytecodes::ToByte(Bytecode::kLast) + 1);
@@ -301,9 +297,11 @@
   CHECK_EQ(final_bytecode, Bytecode::kReturn);
   CHECK_EQ(scorecard[Bytecodes::ToByte(final_bytecode)], 1);
 
-#define CHECK_BYTECODE_PRESENT(Name, ...)     \
-  /* Check Bytecode is marked in scorecard */ \
-  CHECK_GE(scorecard[Bytecodes::ToByte(Bytecode::k##Name)], 1);
+#define CHECK_BYTECODE_PRESENT(Name, ...)                                \
+  /* Check Bytecode is marked in scorecard, unless it's a debug break */ \
+  if (!Bytecodes::IsDebugBreak(Bytecode::k##Name)) {                     \
+    CHECK_GE(scorecard[Bytecodes::ToByte(Bytecode::k##Name)], 1);        \
+  }
   BYTECODE_LIST(CHECK_BYTECODE_PRESENT)
 #undef CHECK_BYTECODE_PRESENT
 }
@@ -313,12 +311,9 @@
   for (int locals = 0; locals < 5; locals++) {
     for (int contexts = 0; contexts < 4; contexts++) {
       for (int temps = 0; temps < 3; temps++) {
-        BytecodeArrayBuilder builder(isolate(), zone());
-        builder.set_parameter_count(0);
-        builder.set_locals_count(locals);
-        builder.set_context_count(contexts);
-
-        BytecodeRegisterAllocator temporaries(&builder);
+        BytecodeArrayBuilder builder(isolate(), zone(), 0, contexts, locals);
+        BytecodeRegisterAllocator temporaries(
+            zone(), builder.temporary_register_allocator());
         for (int i = 0; i < temps; i++) {
           builder.StoreAccumulatorInRegister(temporaries.NewRegister());
         }
@@ -349,11 +344,7 @@
 
 
 TEST_F(BytecodeArrayBuilderTest, Parameters) {
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(10);
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
-
+  BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 0);
   Register param0(builder.Parameter(0));
   Register param9(builder.Parameter(9));
   CHECK_EQ(param9.index() - param0.index(), 9);
@@ -361,12 +352,9 @@
 
 
 TEST_F(BytecodeArrayBuilderTest, RegisterType) {
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(10);
-  builder.set_locals_count(3);
-  builder.set_context_count(0);
-
-  BytecodeRegisterAllocator register_allocator(&builder);
+  BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 3);
+  BytecodeRegisterAllocator register_allocator(
+      zone(), builder.temporary_register_allocator());
   Register temp0 = register_allocator.NewRegister();
   Register param0(builder.Parameter(0));
   Register param9(builder.Parameter(9));
@@ -387,11 +375,7 @@
 
 
 TEST_F(BytecodeArrayBuilderTest, Constants) {
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(0);
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
-
+  BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
   Factory* factory = isolate()->factory();
   Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(3.14);
   Handle<HeapObject> heap_num_2 = factory->NewHeapNumber(5.2);
@@ -402,7 +386,8 @@
       .LoadLiteral(large_smi)
       .LoadLiteral(heap_num_1)
       .LoadLiteral(heap_num_1)
-      .LoadLiteral(heap_num_2_copy);
+      .LoadLiteral(heap_num_2_copy)
+      .Return();
 
   Handle<BytecodeArray> array = builder.ToBytecodeArray();
   // Should only have one entry for each identical constant.
@@ -413,23 +398,19 @@
 TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
   static const int kFarJumpDistance = 256;
 
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(0);
-  builder.set_locals_count(1);
-  builder.set_context_count(0);
-
+  BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1);
   Register reg(0);
   BytecodeLabel far0, far1, far2, far3, far4;
   BytecodeLabel near0, near1, near2, near3, near4;
 
   builder.Jump(&near0)
-      .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+      .CompareOperation(Token::Value::EQ, reg)
       .JumpIfTrue(&near1)
-      .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+      .CompareOperation(Token::Value::EQ, reg)
       .JumpIfFalse(&near2)
-      .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfTrue(&near3)
-      .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfFalse(&near4)
       .Bind(&near0)
       .Bind(&near1)
@@ -437,13 +418,13 @@
       .Bind(&near3)
       .Bind(&near4)
       .Jump(&far0)
-      .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+      .CompareOperation(Token::Value::EQ, reg)
       .JumpIfTrue(&far1)
-      .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+      .CompareOperation(Token::Value::EQ, reg)
       .JumpIfFalse(&far2)
-      .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfTrue(&far3)
-      .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfFalse(&far4);
   for (int i = 0; i < kFarJumpDistance - 18; i++) {
     builder.LoadUndefined();
@@ -529,38 +510,31 @@
 
 
 TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(0);
-  builder.set_locals_count(1);
-  builder.set_context_count(0);
+  BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1);
   Register reg(0);
 
   BytecodeLabel label0, label1, label2, label3, label4;
   builder.Bind(&label0)
       .Jump(&label0)
       .Bind(&label1)
-      .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+      .CompareOperation(Token::Value::EQ, reg)
       .JumpIfTrue(&label1)
       .Bind(&label2)
-      .CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
+      .CompareOperation(Token::Value::EQ, reg)
       .JumpIfFalse(&label2)
       .Bind(&label3)
-      .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfTrue(&label3)
       .Bind(&label4)
-      .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+      .BinaryOperation(Token::Value::ADD, reg)
       .JumpIfFalse(&label4);
   for (int i = 0; i < 63; i++) {
     builder.Jump(&label4);
   }
-  builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
-      .JumpIfFalse(&label4);
-  builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
-      .JumpIfTrue(&label3);
-  builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
-      .JumpIfFalse(&label2);
-  builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
-      .JumpIfTrue(&label1);
+  builder.BinaryOperation(Token::Value::ADD, reg).JumpIfFalse(&label4);
+  builder.BinaryOperation(Token::Value::ADD, reg).JumpIfTrue(&label3);
+  builder.CompareOperation(Token::Value::EQ, reg).JumpIfFalse(&label2);
+  builder.CompareOperation(Token::Value::EQ, reg).JumpIfTrue(&label1);
   builder.Jump(&label0);
   builder.Return();
 
@@ -625,10 +599,7 @@
 
 
 TEST_F(BytecodeArrayBuilderTest, LabelReuse) {
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(0);
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
+  BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
 
   // Labels can only have 1 forward reference, but
   // can be referred to mulitple times once bound.
@@ -656,16 +627,11 @@
 TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) {
   static const int kRepeats = 3;
 
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(0);
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
-
+  BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
   for (int i = 0; i < kRepeats; i++) {
     BytecodeLabel label;
     builder.Jump(&label).Bind(&label).Jump(&label).Jump(&label);
   }
-
   builder.Return();
 
   Handle<BytecodeArray> array = builder.ToBytecodeArray();
@@ -686,7 +652,6 @@
   CHECK(iterator.done());
 }
 
-
 }  // namespace interpreter
 }  // namespace internal
 }  // namespace v8
diff --git a/test/unittests/interpreter/bytecode-array-iterator-unittest.cc b/test/unittests/interpreter/bytecode-array-iterator-unittest.cc
index cd9f120..f2dcd71 100644
--- a/test/unittests/interpreter/bytecode-array-iterator-unittest.cc
+++ b/test/unittests/interpreter/bytecode-array-iterator-unittest.cc
@@ -22,11 +22,7 @@
 TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
   // Use a builder to create an array with containing multiple bytecodes
   // with 0, 1 and 2 operands.
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(3);
-  builder.set_locals_count(2);
-  builder.set_context_count(0);
-
+  BytecodeArrayBuilder builder(isolate(), zone(), 3, 2, 0);
   Factory* factory = isolate()->factory();
   Handle<HeapObject> heap_num_0 = factory->NewHeapNumber(2.718);
   Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(2147483647);
@@ -46,9 +42,10 @@
       .LoadLiteral(smi_0)
       .LoadLiteral(smi_1)
       .LoadAccumulatorWithRegister(reg_0)
-      .LoadNamedProperty(reg_1, name, feedback_slot, LanguageMode::SLOPPY)
+      .LoadNamedProperty(reg_1, name, feedback_slot)
       .StoreAccumulatorInRegister(reg_2)
       .CallRuntime(Runtime::kLoadIC_Miss, reg_0, 1)
+      .Debugger()
       .Return();
 
   // Test iterator sees the expected output from the builder.
@@ -82,7 +79,7 @@
   CHECK(!iterator.done());
   iterator.Advance();
 
-  CHECK_EQ(iterator.current_bytecode(), Bytecode::kLoadICSloppy);
+  CHECK_EQ(iterator.current_bytecode(), Bytecode::kLoadIC);
   CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index());
   CHECK_EQ(iterator.GetIndexOperand(1), name_index);
   CHECK_EQ(iterator.GetIndexOperand(2), feedback_slot);
@@ -98,7 +95,11 @@
   CHECK_EQ(static_cast<Runtime::FunctionId>(iterator.GetIndexOperand(0)),
            Runtime::kLoadIC_Miss);
   CHECK_EQ(iterator.GetRegisterOperand(1).index(), reg_0.index());
-  CHECK_EQ(iterator.GetCountOperand(2), 1);
+  CHECK_EQ(iterator.GetRegisterCountOperand(2), 1);
+  CHECK(!iterator.done());
+  iterator.Advance();
+
+  CHECK_EQ(iterator.current_bytecode(), Bytecode::kDebugger);
   CHECK(!iterator.done());
   iterator.Advance();
 
diff --git a/test/unittests/interpreter/bytecode-register-allocator-unittest.cc b/test/unittests/interpreter/bytecode-register-allocator-unittest.cc
index 0620322..ec29935 100644
--- a/test/unittests/interpreter/bytecode-register-allocator-unittest.cc
+++ b/test/unittests/interpreter/bytecode-register-allocator-unittest.cc
@@ -12,51 +12,219 @@
 namespace internal {
 namespace interpreter {
 
+class TemporaryRegisterAllocatorTest : public TestWithIsolateAndZone {
+ public:
+  TemporaryRegisterAllocatorTest() : allocator_(zone(), 0) {}
+  ~TemporaryRegisterAllocatorTest() override {}
+  TemporaryRegisterAllocator* allocator() { return &allocator_; }
+
+ private:
+  TemporaryRegisterAllocator allocator_;
+};
+
+TEST_F(TemporaryRegisterAllocatorTest, FirstAllocation) {
+  CHECK_EQ(allocator()->allocation_count(), 0);
+  int reg0_index = allocator()->BorrowTemporaryRegister();
+  CHECK_EQ(reg0_index, 0);
+  CHECK_EQ(allocator()->allocation_count(), 1);
+  CHECK(allocator()->RegisterIsLive(Register(reg0_index)));
+  allocator()->ReturnTemporaryRegister(reg0_index);
+  CHECK(!allocator()->RegisterIsLive(Register(reg0_index)));
+  CHECK_EQ(allocator()->allocation_count(), 1);
+  CHECK(allocator()->first_temporary_register() == Register(0));
+  CHECK(allocator()->last_temporary_register() == Register(0));
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, SimpleAllocations) {
+  for (int i = 0; i < 13; i++) {
+    int reg_index = allocator()->BorrowTemporaryRegister();
+    CHECK_EQ(reg_index, i);
+    CHECK_EQ(allocator()->allocation_count(), i + 1);
+  }
+  for (int i = 0; i < 13; i++) {
+    CHECK(allocator()->RegisterIsLive(Register(i)));
+    allocator()->ReturnTemporaryRegister(i);
+    CHECK(!allocator()->RegisterIsLive(Register(i)));
+    int reg_index = allocator()->BorrowTemporaryRegister();
+    CHECK_EQ(reg_index, i);
+    CHECK_EQ(allocator()->allocation_count(), 13);
+  }
+  for (int i = 0; i < 13; i++) {
+    CHECK(allocator()->RegisterIsLive(Register(i)));
+    allocator()->ReturnTemporaryRegister(i);
+    CHECK(!allocator()->RegisterIsLive(Register(i)));
+  }
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, SimpleRangeAllocation) {
+  static const int kRunLength = 7;
+  int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength);
+  CHECK(!allocator()->RegisterIsLive(Register(start)));
+  for (int i = 0; i < kRunLength; i++) {
+    CHECK(!allocator()->RegisterIsLive(Register(start + i)));
+    allocator()->BorrowConsecutiveTemporaryRegister(start + i);
+    CHECK(allocator()->RegisterIsLive(Register(start + i)));
+  }
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, RangeAllocationAbuttingFree) {
+  static const int kFreeCount = 3;
+  static const int kRunLength = 6;
+
+  for (int i = 0; i < kFreeCount; i++) {
+    int to_free = allocator()->BorrowTemporaryRegister();
+    CHECK_EQ(to_free, i);
+  }
+  for (int i = 0; i < kFreeCount; i++) {
+    allocator()->ReturnTemporaryRegister(i);
+  }
+
+  int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength);
+  CHECK(!allocator()->RegisterIsLive(Register(start)));
+  for (int i = 0; i < kRunLength; i++) {
+    CHECK(!allocator()->RegisterIsLive(Register(start + i)));
+    allocator()->BorrowConsecutiveTemporaryRegister(start + i);
+    CHECK(allocator()->RegisterIsLive(Register(start + i)));
+  }
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, RangeAllocationAbuttingHole) {
+  static const int kPreAllocatedCount = 7;
+  static const int kPreAllocatedFreeCount = 6;
+  static const int kRunLength = 8;
+
+  for (int i = 0; i < kPreAllocatedCount; i++) {
+    int to_free = allocator()->BorrowTemporaryRegister();
+    CHECK_EQ(to_free, i);
+  }
+  for (int i = 0; i < kPreAllocatedFreeCount; i++) {
+    allocator()->ReturnTemporaryRegister(i);
+  }
+  int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength);
+  CHECK(!allocator()->RegisterIsLive(Register(start)));
+  CHECK_EQ(start, kPreAllocatedCount);
+  for (int i = 0; i < kRunLength; i++) {
+    CHECK(!allocator()->RegisterIsLive(Register(start + i)));
+    allocator()->BorrowConsecutiveTemporaryRegister(start + i);
+    CHECK(allocator()->RegisterIsLive(Register(start + i)));
+  }
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, RangeAllocationAvailableInTemporaries) {
+  static const int kNotRunLength = 13;
+  static const int kRunLength = 8;
+
+  // Allocate big batch
+  for (int i = 0; i < kNotRunLength * 2 + kRunLength; i++) {
+    int allocated = allocator()->BorrowTemporaryRegister();
+    CHECK_EQ(allocated, i);
+  }
+  // Free every other register either side of target.
+  for (int i = 0; i < kNotRunLength; i++) {
+    if ((i & 2) == 1) {
+      allocator()->ReturnTemporaryRegister(i);
+      allocator()->ReturnTemporaryRegister(kNotRunLength + kRunLength + i);
+    }
+  }
+  // Free all registers for target.
+  for (int i = kNotRunLength; i < kNotRunLength + kRunLength; i++) {
+    allocator()->ReturnTemporaryRegister(i);
+  }
+
+  int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength);
+  CHECK_EQ(start, kNotRunLength);
+  for (int i = 0; i < kRunLength; i++) {
+    CHECK(!allocator()->RegisterIsLive(Register(start + i)));
+    allocator()->BorrowConsecutiveTemporaryRegister(start + i);
+    CHECK(allocator()->RegisterIsLive(Register(start + i)));
+  }
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, RangeAvoidsTranslationBoundary) {
+  int boundary = RegisterTranslator::DistanceToTranslationWindow(Register(0));
+  int limit = boundary + 64;
+
+  for (int run_length = 2; run_length < 32; run_length += 7) {
+    ZoneVector<int> run_starts(zone());
+    for (int start = 0; start < limit; start += run_length) {
+      int run_start =
+          allocator()->PrepareForConsecutiveTemporaryRegisters(run_length);
+      run_starts.push_back(run_start);
+      for (int i = 0; i < run_length; i++) {
+        allocator()->BorrowConsecutiveTemporaryRegister(run_start + i);
+      }
+      CHECK(run_start >= boundary || run_start + run_length <= boundary);
+    }
+    for (size_t batch = 0; batch < run_starts.size(); batch++) {
+      for (int i = run_starts[batch]; i < run_starts[batch] + run_length; i++) {
+        allocator()->ReturnTemporaryRegister(i);
+      }
+    }
+  }
+}
+
+TEST_F(TemporaryRegisterAllocatorTest, NotInRange) {
+  for (int i = 0; i < 10; i++) {
+    int reg = allocator()->BorrowTemporaryRegisterNotInRange(2, 5);
+    CHECK(reg == i || (reg > 2 && reg == i + 4));
+  }
+  for (int i = 0; i < 10; i++) {
+    if (i < 2) {
+      allocator()->ReturnTemporaryRegister(i);
+    } else {
+      allocator()->ReturnTemporaryRegister(i + 4);
+    }
+  }
+  int reg0 = allocator()->BorrowTemporaryRegisterNotInRange(0, 3);
+  CHECK_EQ(reg0, 4);
+  int reg1 = allocator()->BorrowTemporaryRegisterNotInRange(3, 10);
+  CHECK_EQ(reg1, 2);
+  int reg2 = allocator()->BorrowTemporaryRegisterNotInRange(2, 6);
+  CHECK_EQ(reg2, 1);
+  allocator()->ReturnTemporaryRegister(reg0);
+  allocator()->ReturnTemporaryRegister(reg1);
+  allocator()->ReturnTemporaryRegister(reg2);
+}
+
 class BytecodeRegisterAllocatorTest : public TestWithIsolateAndZone {
  public:
   BytecodeRegisterAllocatorTest() {}
   ~BytecodeRegisterAllocatorTest() override {}
 };
 
-
 TEST_F(BytecodeRegisterAllocatorTest, TemporariesRecycled) {
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(0);
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
+  BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
 
   int first;
   {
-    BytecodeRegisterAllocator temporaries(&builder);
-    first = temporaries.NewRegister().index();
-    temporaries.NewRegister();
-    temporaries.NewRegister();
-    temporaries.NewRegister();
+    BytecodeRegisterAllocator allocator(zone(),
+                                        builder.temporary_register_allocator());
+    first = allocator.NewRegister().index();
+    allocator.NewRegister();
+    allocator.NewRegister();
+    allocator.NewRegister();
   }
 
   int second;
   {
-    BytecodeRegisterAllocator temporaries(&builder);
-    second = temporaries.NewRegister().index();
+    BytecodeRegisterAllocator allocator(zone(),
+                                        builder.temporary_register_allocator());
+    second = allocator.NewRegister().index();
   }
 
   CHECK_EQ(first, second);
 }
 
-
 TEST_F(BytecodeRegisterAllocatorTest, ConsecutiveRegisters) {
-  BytecodeArrayBuilder builder(isolate(), zone());
-  builder.set_parameter_count(0);
-  builder.set_locals_count(0);
-  builder.set_context_count(0);
-
-  BytecodeRegisterAllocator temporaries(&builder);
-  temporaries.PrepareForConsecutiveAllocations(4);
-  Register reg0 = temporaries.NextConsecutiveRegister();
-  Register other = temporaries.NewRegister();
-  Register reg1 = temporaries.NextConsecutiveRegister();
-  Register reg2 = temporaries.NextConsecutiveRegister();
-  Register reg3 = temporaries.NextConsecutiveRegister();
+  BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
+  BytecodeRegisterAllocator allocator(zone(),
+                                      builder.temporary_register_allocator());
+  allocator.PrepareForConsecutiveAllocations(4);
+  Register reg0 = allocator.NextConsecutiveRegister();
+  Register other = allocator.NewRegister();
+  Register reg1 = allocator.NextConsecutiveRegister();
+  Register reg2 = allocator.NextConsecutiveRegister();
+  Register reg3 = allocator.NextConsecutiveRegister();
   USE(other);
 
   CHECK(Register::AreContiguous(reg0, reg1, reg2, reg3));
diff --git a/test/unittests/interpreter/bytecodes-unittest.cc b/test/unittests/interpreter/bytecodes-unittest.cc
index 812ee46..212e029 100644
--- a/test/unittests/interpreter/bytecodes-unittest.cc
+++ b/test/unittests/interpreter/bytecodes-unittest.cc
@@ -9,20 +9,40 @@
 #include "src/interpreter/bytecodes.h"
 #include "test/unittests/test-utils.h"
 
-
 namespace v8 {
 namespace internal {
 namespace interpreter {
 
 TEST(OperandConversion, Registers) {
-  for (int i = 0; i < 128; i++) {
-    uint8_t operand_value = Register(i).ToOperand();
-    Register r = Register::FromOperand(operand_value);
-    CHECK_EQ(i, r.index());
+  int register_count = Register::MaxRegisterIndex() + 1;
+  int step = register_count / 7;
+  for (int i = 0; i < register_count; i += step) {
+    if (i <= kMaxInt8) {
+      uint8_t operand0 = Register(i).ToOperand();
+      Register reg0 = Register::FromOperand(operand0);
+      CHECK_EQ(i, reg0.index());
+    }
+
+    uint16_t operand1 = Register(i).ToWideOperand();
+    Register reg1 = Register::FromWideOperand(operand1);
+    CHECK_EQ(i, reg1.index());
+
+    uint32_t operand2 = Register(i).ToRawOperand();
+    Register reg2 = Register::FromRawOperand(operand2);
+    CHECK_EQ(i, reg2.index());
+  }
+
+  for (int i = 0; i <= kMaxUInt8; i++) {
+    uint8_t operand = static_cast<uint8_t>(i);
+    Register reg = Register::FromOperand(operand);
+    if (i > 0 && i < -kMinInt8) {
+      CHECK(reg.is_parameter());
+    } else {
+      CHECK(!reg.is_parameter());
+    }
   }
 }
 
-
 TEST(OperandConversion, Parameters) {
   int parameter_counts[] = {7, 13, 99};
 
@@ -38,26 +58,115 @@
   }
 }
 
-
 TEST(OperandConversion, RegistersParametersNoOverlap) {
-  std::vector<uint8_t> operand_count(256);
+  int register_count = Register::MaxRegisterIndex() + 1;
+  int parameter_count = Register::MaxParameterIndex() + 1;
+  int32_t register_space_size = base::bits::RoundUpToPowerOfTwo32(
+      static_cast<uint32_t>(register_count + parameter_count));
+  uint32_t range = static_cast<uint32_t>(register_space_size);
+  std::vector<uint8_t> operand_count(range);
 
-  for (int i = 0; i <= kMaxInt8; i++) {
+  for (int i = 0; i < register_count; i += 1) {
     Register r = Register(i);
-    uint8_t operand = r.ToOperand();
+    uint32_t operand = r.ToWideOperand();
+    CHECK_LT(operand, operand_count.size());
     operand_count[operand] += 1;
     CHECK_EQ(operand_count[operand], 1);
   }
 
-  int parameter_count = Register::MaxParameterIndex() + 1;
-  for (int i = 0; i < parameter_count; i++) {
+  for (int i = 0; i < parameter_count; i += 1) {
     Register r = Register::FromParameterIndex(i, parameter_count);
-    uint8_t operand = r.ToOperand();
+    uint32_t operand = r.ToWideOperand();
+    CHECK_LT(operand, operand_count.size());
     operand_count[operand] += 1;
     CHECK_EQ(operand_count[operand], 1);
   }
 }
 
+TEST(Bytecodes, HasAnyRegisterOperands) {
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kAdd), 1);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kCall), 2);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kCallRuntime), 1);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kCallRuntimeWide), 1);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kCallRuntimeForPair),
+           2);
+  CHECK_EQ(
+      Bytecodes::NumberOfRegisterOperands(Bytecode::kCallRuntimeForPairWide),
+      2);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kDeletePropertyStrict),
+           1);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kForInPrepare), 1);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kForInPrepareWide), 1);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kInc), 0);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kJumpIfTrue), 0);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kNew), 2);
+  CHECK_EQ(Bytecodes::NumberOfRegisterOperands(Bytecode::kToName), 0);
+}
+
+TEST(Bytecodes, RegisterOperandBitmaps) {
+  CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kAdd), 1);
+  CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kCallRuntimeForPair),
+           10);
+  CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kStar), 1);
+  CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kMov), 3);
+  CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kTestIn), 1);
+  CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kForInPrepare), 1);
+  CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kForInDone), 3);
+  CHECK_EQ(Bytecodes::GetRegisterOperandBitmap(Bytecode::kForInNext), 7);
+}
+
+TEST(Bytecodes, RegisterOperands) {
+  CHECK(Bytecodes::IsRegisterOperandType(OperandType::kReg8));
+  CHECK(Bytecodes::IsRegisterInputOperandType(OperandType::kReg8));
+  CHECK(!Bytecodes::IsRegisterOutputOperandType(OperandType::kReg8));
+  CHECK(!Bytecodes::IsRegisterInputOperandType(OperandType::kRegOut8));
+  CHECK(Bytecodes::IsRegisterOutputOperandType(OperandType::kRegOut8));
+
+#define IS_REGISTER_OPERAND_TYPE(Name, _) \
+  CHECK(Bytecodes::IsRegisterOperandType(OperandType::k##Name));
+  REGISTER_OPERAND_TYPE_LIST(IS_REGISTER_OPERAND_TYPE)
+#undef IS_REGISTER_OPERAND_TYPE
+
+#define IS_NOT_REGISTER_OPERAND_TYPE(Name, _) \
+  CHECK(!Bytecodes::IsRegisterOperandType(OperandType::k##Name));
+  NON_REGISTER_OPERAND_TYPE_LIST(IS_NOT_REGISTER_OPERAND_TYPE)
+#undef IS_NOT_REGISTER_OPERAND_TYPE
+
+#define IS_REGISTER_INPUT_OPERAND_TYPE(Name, _) \
+  CHECK(Bytecodes::IsRegisterInputOperandType(OperandType::k##Name));
+  REGISTER_INPUT_OPERAND_TYPE_LIST(IS_REGISTER_INPUT_OPERAND_TYPE)
+#undef IS_REGISTER_INPUT_OPERAND_TYPE
+
+#define IS_NOT_REGISTER_INPUT_OPERAND_TYPE(Name, _) \
+  CHECK(!Bytecodes::IsRegisterInputOperandType(OperandType::k##Name));
+  NON_REGISTER_OPERAND_TYPE_LIST(IS_NOT_REGISTER_INPUT_OPERAND_TYPE);
+  REGISTER_OUTPUT_OPERAND_TYPE_LIST(IS_NOT_REGISTER_INPUT_OPERAND_TYPE)
+#undef IS_NOT_REGISTER_INPUT_OPERAND_TYPE
+
+#define IS_REGISTER_OUTPUT_OPERAND_TYPE(Name, _) \
+  CHECK(Bytecodes::IsRegisterOutputOperandType(OperandType::k##Name));
+  REGISTER_OUTPUT_OPERAND_TYPE_LIST(IS_REGISTER_OUTPUT_OPERAND_TYPE)
+#undef IS_REGISTER_OUTPUT_OPERAND_TYPE
+
+#define IS_NOT_REGISTER_OUTPUT_OPERAND_TYPE(Name, _) \
+  CHECK(!Bytecodes::IsRegisterOutputOperandType(OperandType::k##Name));
+  NON_REGISTER_OPERAND_TYPE_LIST(IS_NOT_REGISTER_OUTPUT_OPERAND_TYPE)
+  REGISTER_INPUT_OPERAND_TYPE_LIST(IS_NOT_REGISTER_OUTPUT_OPERAND_TYPE)
+#undef IS_NOT_REGISTER_INPUT_OPERAND_TYPE
+}
+
+TEST(Bytecodes, DebugBreak) {
+  for (uint32_t i = 0; i < Bytecodes::ToByte(Bytecode::kLast); i++) {
+    Bytecode bytecode = Bytecodes::FromByte(i);
+    Bytecode debugbreak = Bytecodes::GetDebugBreak(bytecode);
+    if (!Bytecodes::IsDebugBreak(debugbreak)) {
+      PrintF("Bytecode %s has no matching debug break with length %d\n",
+             Bytecodes::ToString(bytecode), Bytecodes::Size(bytecode));
+      CHECK(false);
+    }
+  }
+}
+
 }  // namespace interpreter
 }  // namespace internal
 }  // namespace v8
diff --git a/test/unittests/interpreter/constant-array-builder-unittest.cc b/test/unittests/interpreter/constant-array-builder-unittest.cc
index ea5d1bb..b3ec5ff 100644
--- a/test/unittests/interpreter/constant-array-builder-unittest.cc
+++ b/test/unittests/interpreter/constant-array-builder-unittest.cc
@@ -33,13 +33,11 @@
 TEST_F(ConstantArrayBuilderTest, AllocateAllEntries) {
   ConstantArrayBuilder builder(isolate(), zone());
   for (size_t i = 0; i < kMaxCapacity; i++) {
-    Handle<Object> object = isolate()->factory()->NewNumberFromSize(i);
-    builder.Insert(object);
-    CHECK_EQ(builder.size(), i + 1);
-    CHECK(builder.At(i)->SameValue(*object));
+    builder.Insert(handle(Smi::FromInt(static_cast<int>(i)), isolate()));
   }
+  CHECK_EQ(builder.size(), kMaxCapacity);
   for (size_t i = 0; i < kMaxCapacity; i++) {
-    CHECK_EQ(Handle<Smi>::cast(builder.At(i))->value(), static_cast<double>(i));
+    CHECK_EQ(Handle<Smi>::cast(builder.At(i))->value(), i);
   }
 }
 
@@ -158,8 +156,7 @@
     builder.Insert(object);
     CHECK(builder.At(i)->SameValue(*object));
   }
-  Handle<FixedArray> constant_array =
-      builder.ToFixedArray(isolate()->factory());
+  Handle<FixedArray> constant_array = builder.ToFixedArray();
   CHECK_EQ(constant_array->length(), kNumberOfElements);
   for (size_t i = 0; i < kNumberOfElements; i++) {
     CHECK(constant_array->get(static_cast<int>(i))->SameValue(*builder.At(i)));
diff --git a/test/unittests/interpreter/interpreter-assembler-unittest.cc b/test/unittests/interpreter/interpreter-assembler-unittest.cc
new file mode 100644
index 0000000..3375a6b
--- /dev/null
+++ b/test/unittests/interpreter/interpreter-assembler-unittest.cc
@@ -0,0 +1,696 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "test/unittests/interpreter/interpreter-assembler-unittest.h"
+
+#include "src/code-factory.h"
+#include "src/compiler/graph.h"
+#include "src/compiler/node.h"
+#include "src/interface-descriptors.h"
+#include "src/isolate.h"
+#include "test/unittests/compiler/compiler-test-utils.h"
+#include "test/unittests/compiler/node-test-utils.h"
+
+using ::testing::_;
+
+namespace v8 {
+namespace internal {
+
+using namespace compiler;
+
+namespace interpreter {
+
+const interpreter::Bytecode kBytecodes[] = {
+#define DEFINE_BYTECODE(Name, ...) interpreter::Bytecode::k##Name,
+    BYTECODE_LIST(DEFINE_BYTECODE)
+#undef DEFINE_BYTECODE
+};
+
+Matcher<Node*> IsIntPtrConstant(const intptr_t value) {
+  return kPointerSize == 8 ? IsInt64Constant(static_cast<int64_t>(value))
+                           : IsInt32Constant(static_cast<int32_t>(value));
+}
+
+Matcher<Node*> IsIntPtrAdd(const Matcher<Node*>& lhs_matcher,
+                           const Matcher<Node*>& rhs_matcher) {
+  return kPointerSize == 8 ? IsInt64Add(lhs_matcher, rhs_matcher)
+                           : IsInt32Add(lhs_matcher, rhs_matcher);
+}
+
+Matcher<Node*> IsIntPtrSub(const Matcher<Node*>& lhs_matcher,
+                           const Matcher<Node*>& rhs_matcher) {
+  return kPointerSize == 8 ? IsInt64Sub(lhs_matcher, rhs_matcher)
+                           : IsInt32Sub(lhs_matcher, rhs_matcher);
+}
+
+Matcher<Node*> IsWordShl(const Matcher<Node*>& lhs_matcher,
+                         const Matcher<Node*>& rhs_matcher) {
+  return kPointerSize == 8 ? IsWord64Shl(lhs_matcher, rhs_matcher)
+                           : IsWord32Shl(lhs_matcher, rhs_matcher);
+}
+
+Matcher<Node*> IsWordSar(const Matcher<Node*>& lhs_matcher,
+                         const Matcher<Node*>& rhs_matcher) {
+  return kPointerSize == 8 ? IsWord64Sar(lhs_matcher, rhs_matcher)
+                           : IsWord32Sar(lhs_matcher, rhs_matcher);
+}
+
+Matcher<Node*> IsWordOr(const Matcher<Node*>& lhs_matcher,
+                        const Matcher<Node*>& rhs_matcher) {
+  return kPointerSize == 8 ? IsWord64Or(lhs_matcher, rhs_matcher)
+                           : IsWord32Or(lhs_matcher, rhs_matcher);
+}
+
+Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsLoad(
+    const Matcher<LoadRepresentation>& rep_matcher,
+    const Matcher<Node*>& base_matcher, const Matcher<Node*>& index_matcher) {
+  return ::i::compiler::IsLoad(rep_matcher, base_matcher, index_matcher, _, _);
+}
+
+Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsStore(
+    const Matcher<StoreRepresentation>& rep_matcher,
+    const Matcher<Node*>& base_matcher, const Matcher<Node*>& index_matcher,
+    const Matcher<Node*>& value_matcher) {
+  return ::i::compiler::IsStore(rep_matcher, base_matcher, index_matcher,
+                                value_matcher, _, _);
+}
+
+Matcher<Node*>
+InterpreterAssemblerTest::InterpreterAssemblerForTest::IsBytecodeOperand(
+    int offset) {
+  return IsLoad(
+      MachineType::Uint8(),
+      IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+      IsIntPtrAdd(
+          IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+          IsInt32Constant(offset)));
+}
+
+Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::
+    IsBytecodeOperandSignExtended(int offset) {
+  Matcher<Node*> load_matcher = IsLoad(
+      MachineType::Int8(),
+      IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+      IsIntPtrAdd(
+          IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+          IsInt32Constant(offset)));
+  if (kPointerSize == 8) {
+    load_matcher = IsChangeInt32ToInt64(load_matcher);
+  }
+  return load_matcher;
+}
+
+Matcher<Node*>
+InterpreterAssemblerTest::InterpreterAssemblerForTest::IsBytecodeOperandShort(
+    int offset) {
+  if (TargetSupportsUnalignedAccess()) {
+    return IsLoad(
+        MachineType::Uint16(),
+        IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+        IsIntPtrAdd(
+            IsParameter(
+                InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+            IsInt32Constant(offset)));
+  } else {
+    Matcher<Node*> first_byte = IsLoad(
+        MachineType::Uint8(),
+        IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+        IsIntPtrAdd(
+            IsParameter(
+                InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+            IsInt32Constant(offset)));
+    Matcher<Node*> second_byte = IsLoad(
+        MachineType::Uint8(),
+        IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+        IsIntPtrAdd(
+            IsParameter(
+                InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+            IsInt32Constant(offset + 1)));
+#if V8_TARGET_LITTLE_ENDIAN
+    return IsWordOr(IsWordShl(second_byte, IsInt32Constant(kBitsPerByte)),
+                    first_byte);
+#elif V8_TARGET_BIG_ENDIAN
+    return IsWordOr(IsWordShl(first_byte, IsInt32Constant(kBitsPerByte)),
+                    second_byte);
+#else
+#error "Unknown Architecture"
+#endif
+  }
+}
+
+Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::
+    IsBytecodeOperandShortSignExtended(int offset) {
+  Matcher<Node*> load_matcher;
+  if (TargetSupportsUnalignedAccess()) {
+    load_matcher = IsLoad(
+        MachineType::Int16(),
+        IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+        IsIntPtrAdd(
+            IsParameter(
+                InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+            IsInt32Constant(offset)));
+  } else {
+#if V8_TARGET_LITTLE_ENDIAN
+    int hi_byte_offset = offset + 1;
+    int lo_byte_offset = offset;
+
+#elif V8_TARGET_BIG_ENDIAN
+    int hi_byte_offset = offset;
+    int lo_byte_offset = offset + 1;
+#else
+#error "Unknown Architecture"
+#endif
+    Matcher<Node*> hi_byte = IsLoad(
+        MachineType::Int8(),
+        IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+        IsIntPtrAdd(
+            IsParameter(
+                InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+            IsInt32Constant(hi_byte_offset)));
+    hi_byte = IsWord32Shl(hi_byte, IsInt32Constant(kBitsPerByte));
+    Matcher<Node*> lo_byte = IsLoad(
+        MachineType::Uint8(),
+        IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+        IsIntPtrAdd(
+            IsParameter(
+                InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+            IsInt32Constant(lo_byte_offset)));
+    load_matcher = IsWord32Or(hi_byte, lo_byte);
+  }
+
+  if (kPointerSize == 8) {
+    load_matcher = IsChangeInt32ToInt64(load_matcher);
+  }
+  return load_matcher;
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, Dispatch) {
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    m.Dispatch();
+    Graph* graph = m.graph();
+
+    Node* end = graph->end();
+    EXPECT_EQ(1, end->InputCount());
+    Node* tail_call_node = end->InputAt(0);
+
+    Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
+        IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+        IsInt32Constant(interpreter::Bytecodes::Size(bytecode)));
+    Matcher<Node*> target_bytecode_matcher = m.IsLoad(
+        MachineType::Uint8(),
+        IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+        next_bytecode_offset_matcher);
+    Matcher<Node*> code_target_matcher = m.IsLoad(
+        MachineType::Pointer(),
+        IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
+        IsWord32Shl(target_bytecode_matcher,
+                    IsInt32Constant(kPointerSizeLog2)));
+
+    EXPECT_THAT(
+        tail_call_node,
+        IsTailCall(
+            _, code_target_matcher,
+            IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
+            IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
+            next_bytecode_offset_matcher,
+            IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+            IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
+            IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
+            _));
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, Jump) {
+  // If debug code is enabled we emit extra code in Jump.
+  if (FLAG_debug_code) return;
+
+  int jump_offsets[] = {-9710, -77, 0, +3, +97109};
+  TRACED_FOREACH(int, jump_offset, jump_offsets) {
+    TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+      InterpreterAssemblerForTest m(this, bytecode);
+      m.Jump(m.Int32Constant(jump_offset));
+      Graph* graph = m.graph();
+      Node* end = graph->end();
+      EXPECT_EQ(1, end->InputCount());
+      Node* tail_call_node = end->InputAt(0);
+
+      Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
+          IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+          IsInt32Constant(jump_offset));
+      Matcher<Node*> target_bytecode_matcher =
+          m.IsLoad(MachineType::Uint8(), _, next_bytecode_offset_matcher);
+      Matcher<Node*> code_target_matcher = m.IsLoad(
+          MachineType::Pointer(),
+          IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
+          IsWord32Shl(target_bytecode_matcher,
+                      IsInt32Constant(kPointerSizeLog2)));
+
+      EXPECT_THAT(
+          tail_call_node,
+          IsTailCall(
+              _, code_target_matcher,
+              IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
+              IsParameter(
+                  InterpreterDispatchDescriptor::kRegisterFileParameter),
+              next_bytecode_offset_matcher, _,
+              IsParameter(
+                  InterpreterDispatchDescriptor::kDispatchTableParameter),
+              IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
+              _));
+    }
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, JumpIfWordEqual) {
+  static const int kJumpIfTrueOffset = 73;
+
+  // If debug code is enabled we emit extra code in Jump.
+  if (FLAG_debug_code) return;
+
+  MachineOperatorBuilder machine(zone());
+
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    Node* lhs = m.IntPtrConstant(0);
+    Node* rhs = m.IntPtrConstant(1);
+    m.JumpIfWordEqual(lhs, rhs, m.Int32Constant(kJumpIfTrueOffset));
+    Graph* graph = m.graph();
+    Node* end = graph->end();
+    EXPECT_EQ(2, end->InputCount());
+
+    int jump_offsets[] = {kJumpIfTrueOffset,
+                          interpreter::Bytecodes::Size(bytecode)};
+    for (int i = 0; i < static_cast<int>(arraysize(jump_offsets)); i++) {
+      Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
+          IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+          IsInt32Constant(jump_offsets[i]));
+      Matcher<Node*> target_bytecode_matcher =
+          m.IsLoad(MachineType::Uint8(), _, next_bytecode_offset_matcher);
+      Matcher<Node*> code_target_matcher = m.IsLoad(
+          MachineType::Pointer(),
+          IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
+          IsWord32Shl(target_bytecode_matcher,
+                      IsInt32Constant(kPointerSizeLog2)));
+      EXPECT_THAT(
+          end->InputAt(i),
+          IsTailCall(
+              _, code_target_matcher,
+              IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
+              IsParameter(
+                  InterpreterDispatchDescriptor::kRegisterFileParameter),
+              next_bytecode_offset_matcher, _,
+              IsParameter(
+                  InterpreterDispatchDescriptor::kDispatchTableParameter),
+              IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
+              _));
+    }
+
+    // TODO(oth): test control flow paths.
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, InterpreterReturn) {
+  // If debug code is enabled we emit extra code in InterpreterReturn.
+  if (FLAG_debug_code) return;
+
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    m.InterpreterReturn();
+    Graph* graph = m.graph();
+
+    Node* end = graph->end();
+    EXPECT_EQ(1, end->InputCount());
+    Node* tail_call_node = end->InputAt(0);
+
+    Handle<HeapObject> exit_trampoline =
+        isolate()->builtins()->InterpreterExitTrampoline();
+    EXPECT_THAT(
+        tail_call_node,
+        IsTailCall(
+            _, IsHeapConstant(exit_trampoline),
+            IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
+            IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
+            IsParameter(
+                InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
+            _,
+            IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
+            IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
+            _));
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    int number_of_operands = interpreter::Bytecodes::NumberOfOperands(bytecode);
+    for (int i = 0; i < number_of_operands; i++) {
+      int offset = interpreter::Bytecodes::GetOperandOffset(bytecode, i);
+      switch (interpreter::Bytecodes::GetOperandType(bytecode, i)) {
+        case interpreter::OperandType::kRegCount8:
+          EXPECT_THAT(m.BytecodeOperandCount(i), m.IsBytecodeOperand(offset));
+          break;
+        case interpreter::OperandType::kIdx8:
+          EXPECT_THAT(m.BytecodeOperandIdx(i), m.IsBytecodeOperand(offset));
+          break;
+        case interpreter::OperandType::kImm8:
+          EXPECT_THAT(m.BytecodeOperandImm(i),
+                      m.IsBytecodeOperandSignExtended(offset));
+          break;
+        case interpreter::OperandType::kMaybeReg8:
+        case interpreter::OperandType::kReg8:
+        case interpreter::OperandType::kRegOut8:
+        case interpreter::OperandType::kRegOutPair8:
+        case interpreter::OperandType::kRegOutTriple8:
+        case interpreter::OperandType::kRegPair8:
+          EXPECT_THAT(m.BytecodeOperandReg(i),
+                      m.IsBytecodeOperandSignExtended(offset));
+          break;
+        case interpreter::OperandType::kRegCount16:
+          EXPECT_THAT(m.BytecodeOperandCount(i),
+                      m.IsBytecodeOperandShort(offset));
+          break;
+        case interpreter::OperandType::kIdx16:
+          EXPECT_THAT(m.BytecodeOperandIdx(i),
+                      m.IsBytecodeOperandShort(offset));
+          break;
+        case interpreter::OperandType::kMaybeReg16:
+        case interpreter::OperandType::kReg16:
+        case interpreter::OperandType::kRegOut16:
+        case interpreter::OperandType::kRegOutPair16:
+        case interpreter::OperandType::kRegOutTriple16:
+        case interpreter::OperandType::kRegPair16:
+          EXPECT_THAT(m.BytecodeOperandReg(i),
+                      m.IsBytecodeOperandShortSignExtended(offset));
+          break;
+        case interpreter::OperandType::kNone:
+          UNREACHABLE();
+          break;
+      }
+    }
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, GetSetAccumulator) {
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    // Should be incoming accumulator if not set.
+    EXPECT_THAT(
+        m.GetAccumulator(),
+        IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter));
+
+    // Should be set by SetAccumulator.
+    Node* accumulator_value_1 = m.Int32Constant(0xdeadbeef);
+    m.SetAccumulator(accumulator_value_1);
+    EXPECT_THAT(m.GetAccumulator(), accumulator_value_1);
+    Node* accumulator_value_2 = m.Int32Constant(42);
+    m.SetAccumulator(accumulator_value_2);
+    EXPECT_THAT(m.GetAccumulator(), accumulator_value_2);
+
+    // Should be passed to next bytecode handler on dispatch.
+    m.Dispatch();
+    Graph* graph = m.graph();
+
+    Node* end = graph->end();
+    EXPECT_EQ(1, end->InputCount());
+    Node* tail_call_node = end->InputAt(0);
+
+    EXPECT_THAT(tail_call_node,
+                IsTailCall(_, _, accumulator_value_2, _, _, _, _, _, _));
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, GetSetContext) {
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    Node* context_node = m.Int32Constant(100);
+    m.SetContext(context_node);
+    EXPECT_THAT(m.GetContext(), context_node);
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, RegisterLocation) {
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    Node* reg_index_node = m.Int32Constant(44);
+    Node* reg_location_node = m.RegisterLocation(reg_index_node);
+    EXPECT_THAT(
+        reg_location_node,
+        IsIntPtrAdd(
+            IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
+            IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2))));
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, LoadRegister) {
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    Node* reg_index_node = m.Int32Constant(44);
+    Node* load_reg_node = m.LoadRegister(reg_index_node);
+    EXPECT_THAT(
+        load_reg_node,
+        m.IsLoad(
+            MachineType::AnyTagged(),
+            IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
+            IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2))));
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, StoreRegister) {
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    Node* store_value = m.Int32Constant(0xdeadbeef);
+    Node* reg_index_node = m.Int32Constant(44);
+    Node* store_reg_node = m.StoreRegister(store_value, reg_index_node);
+    EXPECT_THAT(
+        store_reg_node,
+        m.IsStore(
+            StoreRepresentation(MachineRepresentation::kTagged,
+                                kNoWriteBarrier),
+            IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
+            IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2)),
+            store_value));
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, SmiTag) {
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    Node* value = m.Int32Constant(44);
+    EXPECT_THAT(m.SmiTag(value),
+                IsWordShl(value, IsInt32Constant(kSmiShiftSize + kSmiTagSize)));
+    EXPECT_THAT(m.SmiUntag(value),
+                IsWordSar(value, IsInt32Constant(kSmiShiftSize + kSmiTagSize)));
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, IntPtrAdd) {
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    Node* a = m.Int32Constant(0);
+    Node* b = m.Int32Constant(1);
+    Node* add = m.IntPtrAdd(a, b);
+    EXPECT_THAT(add, IsIntPtrAdd(a, b));
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, IntPtrSub) {
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    Node* a = m.Int32Constant(0);
+    Node* b = m.Int32Constant(1);
+    Node* add = m.IntPtrSub(a, b);
+    EXPECT_THAT(add, IsIntPtrSub(a, b));
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, WordShl) {
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    Node* a = m.Int32Constant(0);
+    Node* add = m.WordShl(a, 10);
+    EXPECT_THAT(add, IsWordShl(a, IsInt32Constant(10)));
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, LoadConstantPoolEntry) {
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    Node* index = m.Int32Constant(2);
+    Node* load_constant = m.LoadConstantPoolEntry(index);
+    Matcher<Node*> constant_pool_matcher = m.IsLoad(
+        MachineType::AnyTagged(),
+        IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
+        IsIntPtrConstant(BytecodeArray::kConstantPoolOffset - kHeapObjectTag));
+    EXPECT_THAT(
+        load_constant,
+        m.IsLoad(MachineType::AnyTagged(), constant_pool_matcher,
+                 IsIntPtrAdd(
+                     IsIntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
+                     IsWordShl(index, IsInt32Constant(kPointerSizeLog2)))));
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, LoadFixedArrayElement) {
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    int index = 3;
+    Node* fixed_array = m.IntPtrConstant(0xdeadbeef);
+    Node* load_element = m.LoadFixedArrayElement(fixed_array, index);
+    EXPECT_THAT(
+        load_element,
+        m.IsLoad(MachineType::AnyTagged(), fixed_array,
+                 IsIntPtrAdd(
+                     IsIntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
+                     IsWordShl(IsInt32Constant(index),
+                               IsInt32Constant(kPointerSizeLog2)))));
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, LoadObjectField) {
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    Node* object = m.IntPtrConstant(0xdeadbeef);
+    int offset = 16;
+    Node* load_field = m.LoadObjectField(object, offset);
+    EXPECT_THAT(load_field,
+                m.IsLoad(MachineType::AnyTagged(), object,
+                         IsIntPtrConstant(offset - kHeapObjectTag)));
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, LoadContextSlot) {
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    Node* context = m.Int32Constant(1);
+    Node* slot_index = m.Int32Constant(22);
+    Node* load_context_slot = m.LoadContextSlot(context, slot_index);
+
+    Matcher<Node*> offset =
+        IsIntPtrAdd(IsWordShl(slot_index, IsInt32Constant(kPointerSizeLog2)),
+                    IsInt32Constant(Context::kHeaderSize - kHeapObjectTag));
+    EXPECT_THAT(load_context_slot,
+                m.IsLoad(MachineType::AnyTagged(), context, offset));
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, StoreContextSlot) {
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    Node* context = m.Int32Constant(1);
+    Node* slot_index = m.Int32Constant(22);
+    Node* value = m.Int32Constant(100);
+    Node* store_context_slot = m.StoreContextSlot(context, slot_index, value);
+
+    Matcher<Node*> offset =
+        IsIntPtrAdd(IsWordShl(slot_index, IsInt32Constant(kPointerSizeLog2)),
+                    IsInt32Constant(Context::kHeaderSize - kHeapObjectTag));
+    EXPECT_THAT(store_context_slot,
+                m.IsStore(StoreRepresentation(MachineRepresentation::kTagged,
+                                              kFullWriteBarrier),
+                          context, offset, value));
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime2) {
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    Node* arg1 = m.Int32Constant(2);
+    Node* arg2 = m.Int32Constant(3);
+    Node* context =
+        m.Parameter(InterpreterDispatchDescriptor::kContextParameter);
+    Node* call_runtime = m.CallRuntime(Runtime::kAdd, context, arg1, arg2);
+    EXPECT_THAT(
+        call_runtime,
+        IsCall(_, _, arg1, arg2, _, IsInt32Constant(2),
+               IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
+               _));
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime) {
+  const int kResultSizes[] = {1, 2};
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    TRACED_FOREACH(int, result_size, kResultSizes) {
+      InterpreterAssemblerForTest m(this, bytecode);
+      Callable builtin = CodeFactory::InterpreterCEntry(isolate(), result_size);
+
+      Node* function_id = m.Int32Constant(0);
+      Node* first_arg = m.Int32Constant(1);
+      Node* arg_count = m.Int32Constant(2);
+      Node* context =
+          m.Parameter(InterpreterDispatchDescriptor::kContextParameter);
+
+      Matcher<Node*> function_table = IsExternalConstant(
+          ExternalReference::runtime_function_table_address(isolate()));
+      Matcher<Node*> function = IsIntPtrAdd(
+          function_table,
+          IsInt32Mul(function_id, IsInt32Constant(sizeof(Runtime::Function))));
+      Matcher<Node*> function_entry =
+          m.IsLoad(MachineType::Pointer(), function,
+                   IsInt32Constant(offsetof(Runtime::Function, entry)));
+
+      Node* call_runtime = m.CallRuntimeN(function_id, context, first_arg,
+                                          arg_count, result_size);
+      EXPECT_THAT(
+          call_runtime,
+          IsCall(_, IsHeapConstant(builtin.code()), arg_count, first_arg,
+                 function_entry,
+                 IsParameter(InterpreterDispatchDescriptor::kContextParameter),
+                 _, _));
+    }
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, CallJS) {
+  TailCallMode tail_call_modes[] = {TailCallMode::kDisallow,
+                                    TailCallMode::kAllow};
+  TRACED_FOREACH(TailCallMode, tail_call_mode, tail_call_modes) {
+    TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+      InterpreterAssemblerForTest m(this, bytecode);
+      Callable builtin =
+          CodeFactory::InterpreterPushArgsAndCall(isolate(), tail_call_mode);
+      Node* function = m.Int32Constant(0);
+      Node* first_arg = m.Int32Constant(1);
+      Node* arg_count = m.Int32Constant(2);
+      Node* context =
+          m.Parameter(InterpreterDispatchDescriptor::kContextParameter);
+      Node* call_js =
+          m.CallJS(function, context, first_arg, arg_count, tail_call_mode);
+      EXPECT_THAT(
+          call_js,
+          IsCall(_, IsHeapConstant(builtin.code()), arg_count, first_arg,
+                 function,
+                 IsParameter(InterpreterDispatchDescriptor::kContextParameter),
+                 _, _));
+    }
+  }
+}
+
+TARGET_TEST_F(InterpreterAssemblerTest, LoadTypeFeedbackVector) {
+  TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
+    InterpreterAssemblerForTest m(this, bytecode);
+    Node* feedback_vector = m.LoadTypeFeedbackVector();
+
+    Matcher<Node*> load_function_matcher = m.IsLoad(
+        MachineType::AnyTagged(),
+        IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
+        IsIntPtrConstant(
+            InterpreterFrameConstants::kFunctionFromRegisterPointer));
+    Matcher<Node*> load_shared_function_info_matcher =
+        m.IsLoad(MachineType::AnyTagged(), load_function_matcher,
+                 IsIntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
+                                  kHeapObjectTag));
+
+    EXPECT_THAT(
+        feedback_vector,
+        m.IsLoad(MachineType::AnyTagged(), load_shared_function_info_matcher,
+                 IsIntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
+                                  kHeapObjectTag)));
+  }
+}
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
diff --git a/test/unittests/interpreter/interpreter-assembler-unittest.h b/test/unittests/interpreter/interpreter-assembler-unittest.h
new file mode 100644
index 0000000..321c724
--- /dev/null
+++ b/test/unittests/interpreter/interpreter-assembler-unittest.h
@@ -0,0 +1,57 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_UNITTESTS_INTERPRETER_INTERPRETER_ASSEMBLER_UNITTEST_H_
+#define V8_UNITTESTS_INTERPRETER_INTERPRETER_ASSEMBLER_UNITTEST_H_
+
+#include "src/compiler/machine-operator.h"
+#include "src/interpreter/interpreter-assembler.h"
+#include "test/unittests/test-utils.h"
+#include "testing/gmock-support.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+using ::testing::Matcher;
+
+class InterpreterAssemblerTest : public TestWithIsolateAndZone {
+ public:
+  InterpreterAssemblerTest() {}
+  ~InterpreterAssemblerTest() override {}
+
+  class InterpreterAssemblerForTest final : public InterpreterAssembler {
+   public:
+    InterpreterAssemblerForTest(InterpreterAssemblerTest* test,
+                                Bytecode bytecode)
+        : InterpreterAssembler(test->isolate(), test->zone(), bytecode) {}
+    ~InterpreterAssemblerForTest() override {}
+
+    Matcher<compiler::Node*> IsLoad(
+        const Matcher<compiler::LoadRepresentation>& rep_matcher,
+        const Matcher<compiler::Node*>& base_matcher,
+        const Matcher<compiler::Node*>& index_matcher);
+    Matcher<compiler::Node*> IsStore(
+        const Matcher<compiler::StoreRepresentation>& rep_matcher,
+        const Matcher<compiler::Node*>& base_matcher,
+        const Matcher<compiler::Node*>& index_matcher,
+        const Matcher<compiler::Node*>& value_matcher);
+
+    Matcher<compiler::Node*> IsBytecodeOperand(int offset);
+    Matcher<compiler::Node*> IsBytecodeOperandSignExtended(int offset);
+    Matcher<compiler::Node*> IsBytecodeOperandShort(int offset);
+    Matcher<compiler::Node*> IsBytecodeOperandShortSignExtended(int offset);
+
+    using InterpreterAssembler::graph;
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(InterpreterAssemblerForTest);
+  };
+};
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_UNITTESTS_INTERPRETER_INTERPRETER_ASSEMBLER_UNITTEST_H_
diff --git a/test/unittests/interpreter/register-translator-unittest.cc b/test/unittests/interpreter/register-translator-unittest.cc
new file mode 100644
index 0000000..e9f65a6
--- /dev/null
+++ b/test/unittests/interpreter/register-translator-unittest.cc
@@ -0,0 +1,260 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stack>
+
+#include "src/v8.h"
+
+#include "src/interpreter/register-translator.h"
+#include "src/isolate.h"
+#include "test/unittests/test-utils.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+class RegisterTranslatorTest : public TestWithIsolateAndZone,
+                               private RegisterMover {
+ public:
+  RegisterTranslatorTest() : translator_(this), move_count_(0) {
+    window_start_ =
+        RegisterTranslator::DistanceToTranslationWindow(Register(0));
+    window_width_ =
+        Register::MaxRegisterIndexForByteOperand() - window_start_ + 1;
+  }
+
+  ~RegisterTranslatorTest() override {}
+
+  bool PopMoveAndMatch(Register from, Register to) {
+    if (!moves_.empty()) {
+      CHECK(from.is_valid() && to.is_valid());
+      const std::pair<Register, Register> top = moves_.top();
+      moves_.pop();
+      return top.first == from && top.second == to;
+    } else {
+      return false;
+    }
+  }
+
+  int move_count() const { return move_count_; }
+  RegisterTranslator* translator() { return &translator_; }
+
+  int window_start() const { return window_start_; }
+  int window_width() const { return window_width_; }
+  int window_limit() const { return window_start_ + window_width_; }
+
+ protected:
+  static const char* const kBadOperandRegex;
+
+ private:
+  void MoveRegisterUntranslated(Register from, Register to) override {
+    moves_.push(std::make_pair(from, to));
+    move_count_++;
+  }
+
+  RegisterTranslator translator_;
+  std::stack<std::pair<Register, Register>> moves_;
+  int move_count_;
+  int window_start_;
+  int window_width_;
+};
+
+const char* const RegisterTranslatorTest::kBadOperandRegex =
+    ".*OperandType::kReg8 \\|\\| .*OperandType::kRegOut8\\) && "
+    "RegisterIsMovableToWindow.*";
+
+TEST_F(RegisterTranslatorTest, TestFrameSizeAdjustmentsForTranslationWindow) {
+  EXPECT_EQ(0, RegisterTranslator::RegisterCountAdjustment(0, 0));
+  EXPECT_EQ(0, RegisterTranslator::RegisterCountAdjustment(10, 10));
+  EXPECT_EQ(window_width(),
+            RegisterTranslator::RegisterCountAdjustment(173, 0));
+  EXPECT_EQ(window_width(),
+            RegisterTranslator::RegisterCountAdjustment(173, 137));
+  EXPECT_EQ(window_width(),
+            RegisterTranslator::RegisterCountAdjustment(173, 137));
+  // TODO(oth): Add a kMaxParameters8 that derives this info from the frame.
+  int param_limit = FLAG_enable_embedded_constant_pool ? 119 : 120;
+  EXPECT_EQ(0, RegisterTranslator::RegisterCountAdjustment(0, param_limit));
+  EXPECT_EQ(window_limit(),
+            RegisterTranslator::RegisterCountAdjustment(0, 128));
+  EXPECT_EQ(window_limit(),
+            RegisterTranslator::RegisterCountAdjustment(0, 129));
+  EXPECT_EQ(window_limit() - 32,
+            RegisterTranslator::RegisterCountAdjustment(32, 129));
+}
+
+TEST_F(RegisterTranslatorTest, TestInTranslationWindow) {
+  EXPECT_GE(window_start(), 0);
+  EXPECT_FALSE(
+      RegisterTranslator::InTranslationWindow(Register(window_start() - 1)));
+  EXPECT_TRUE(RegisterTranslator::InTranslationWindow(
+      Register(Register::MaxRegisterIndexForByteOperand())));
+  EXPECT_FALSE(RegisterTranslator::InTranslationWindow(
+      Register(Register::MaxRegisterIndexForByteOperand() + 1)));
+  for (int index = window_start(); index < window_limit(); index += 1) {
+    EXPECT_TRUE(RegisterTranslator::InTranslationWindow(Register(index)));
+  }
+}
+
+TEST_F(RegisterTranslatorTest, FitsInReg8Operand) {
+  EXPECT_GT(window_start(), 0);
+  EXPECT_TRUE(RegisterTranslator::FitsInReg8Operand(
+      Register::FromParameterIndex(0, 3)));
+  EXPECT_TRUE(RegisterTranslator::FitsInReg8Operand(
+      Register::FromParameterIndex(2, 3)));
+  EXPECT_TRUE(RegisterTranslator::FitsInReg8Operand(Register(0)));
+  EXPECT_TRUE(
+      RegisterTranslator::FitsInReg8Operand(Register(window_start() - 1)));
+  EXPECT_FALSE(RegisterTranslator::FitsInReg8Operand(Register(kMaxInt8)));
+  EXPECT_FALSE(RegisterTranslator::FitsInReg8Operand(Register(kMaxInt8 + 1)));
+  for (int index = window_start(); index < window_limit(); index += 1) {
+    EXPECT_FALSE(RegisterTranslator::FitsInReg8Operand(Register(index)));
+  }
+}
+
+TEST_F(RegisterTranslatorTest, FitsInReg16Operand) {
+  EXPECT_GT(window_start(), 0);
+  EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(
+      Register::FromParameterIndex(0, 3)));
+  EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(
+      Register::FromParameterIndex(2, 3)));
+  EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(
+      Register::FromParameterIndex(0, 999)));
+  EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(
+      Register::FromParameterIndex(0, Register::MaxParameterIndex() + 1)));
+  EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(Register(0)));
+  EXPECT_TRUE(
+      RegisterTranslator::FitsInReg16Operand(Register(window_start() - 1)));
+  EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(Register(kMaxInt8 + 1)));
+  EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(Register(kMaxInt8 + 2)));
+  for (int index = 0; index <= kMaxInt16 - window_width(); index += 1) {
+    EXPECT_TRUE(RegisterTranslator::FitsInReg16Operand(Register(index)));
+  }
+  for (int index = Register::MaxRegisterIndex() - window_width() + 1;
+       index < Register::MaxRegisterIndex() + 2; index += 1) {
+    EXPECT_FALSE(RegisterTranslator::FitsInReg16Operand(Register(index)));
+  }
+}
+
+TEST_F(RegisterTranslatorTest, NoTranslationRequired) {
+  Register window_reg(window_start());
+  Register local_reg(57);
+  uint32_t operands[] = {local_reg.ToRawOperand()};
+  translator()->TranslateInputRegisters(Bytecode::kLdar, operands, 1);
+  translator()->TranslateOutputRegisters();
+  EXPECT_EQ(0, move_count());
+
+  Register param_reg = Register::FromParameterIndex(129, 130);
+  operands[0] = param_reg.ToRawOperand();
+  translator()->TranslateInputRegisters(Bytecode::kAdd, operands, 1);
+  translator()->TranslateOutputRegisters();
+  EXPECT_EQ(0, move_count());
+}
+
+TEST_F(RegisterTranslatorTest, TranslationRequired) {
+  Register window_reg(window_start());
+  Register local_reg(137);
+  Register local_reg_translated(local_reg.index() + window_width());
+
+  uint32_t operands[] = {local_reg.ToRawOperand()};
+  translator()->TranslateInputRegisters(Bytecode::kLdar, operands, 1);
+  EXPECT_EQ(1, move_count());
+  EXPECT_TRUE(PopMoveAndMatch(local_reg_translated, window_reg));
+  translator()->TranslateOutputRegisters();
+  EXPECT_EQ(1, move_count());
+  EXPECT_FALSE(PopMoveAndMatch(window_reg, local_reg_translated));
+
+  operands[0] = local_reg.ToRawOperand();
+  translator()->TranslateInputRegisters(Bytecode::kStar, operands, 1);
+  EXPECT_EQ(1, move_count());
+  EXPECT_FALSE(PopMoveAndMatch(local_reg_translated, window_reg));
+  translator()->TranslateOutputRegisters();
+  EXPECT_EQ(2, move_count());
+  EXPECT_TRUE(PopMoveAndMatch(window_reg, local_reg_translated));
+
+  Register param_reg = Register::FromParameterIndex(0, 130);
+  operands[0] = {param_reg.ToRawOperand()};
+  translator()->TranslateInputRegisters(Bytecode::kLdar, operands, 1);
+  EXPECT_EQ(3, move_count());
+  EXPECT_TRUE(PopMoveAndMatch(param_reg, window_reg));
+  translator()->TranslateOutputRegisters();
+  EXPECT_EQ(3, move_count());
+  EXPECT_FALSE(PopMoveAndMatch(window_reg, param_reg));
+
+  operands[0] = {param_reg.ToRawOperand()};
+  translator()->TranslateInputRegisters(Bytecode::kStar, operands, 1);
+  EXPECT_EQ(3, move_count());
+  EXPECT_FALSE(PopMoveAndMatch(local_reg_translated, window_reg));
+  translator()->TranslateOutputRegisters();
+  EXPECT_EQ(4, move_count());
+  EXPECT_TRUE(PopMoveAndMatch(window_reg, param_reg));
+}
+
+TEST_F(RegisterTranslatorTest, RangeTranslation) {
+  Register window0(window_start());
+  Register window1(window_start() + 1);
+  Register window2(window_start() + 2);
+  uint32_t operands[3];
+
+  // Bytecode::kNew with valid range operand.
+  Register constructor0(0);
+  Register args0(1);
+  operands[0] = constructor0.ToRawOperand();
+  operands[1] = args0.ToRawOperand();
+  operands[2] = 1;
+  translator()->TranslateInputRegisters(Bytecode::kNew, operands, 3);
+  translator()->TranslateOutputRegisters();
+  EXPECT_EQ(0, move_count());
+
+  // Bytecode::kNewWide with valid range operand.
+  Register constructor1(128);
+  Register constructor1_translated(constructor1.index() + window_width());
+  Register args1(129);
+  Register args1_translated(args1.index() + window_width());
+  operands[0] = constructor1.ToRawOperand();
+  operands[1] = args1.ToRawOperand();
+  operands[2] = 3;
+  translator()->TranslateInputRegisters(Bytecode::kNewWide, operands, 3);
+  translator()->TranslateOutputRegisters();
+  EXPECT_EQ(0, move_count());
+}
+
+TEST_F(RegisterTranslatorTest, BadRange0) {
+  // Bytecode::kNew with invalid range operand (kMaybeReg8).
+  Register constructor1(128);
+  Register args1(129);
+  uint32_t operands[] = {constructor1.ToRawOperand(), args1.ToRawOperand(), 3};
+  ASSERT_DEATH_IF_SUPPORTED(
+      translator()->TranslateInputRegisters(Bytecode::kNew, operands, 3),
+      kBadOperandRegex);
+}
+
+TEST_F(RegisterTranslatorTest, BadRange1) {
+  // Bytecode::kForInPrepare with invalid range operand (kRegTriple8)
+  Register for_in_state(160);
+  Register for_in_state_translated(for_in_state.index() + window_width());
+  uint32_t operands[] = {for_in_state.ToRawOperand()};
+  ASSERT_DEATH_IF_SUPPORTED(translator()->TranslateInputRegisters(
+                                Bytecode::kForInPrepare, operands, 1),
+                            kBadOperandRegex);
+}
+
+TEST_F(RegisterTranslatorTest, BadRange2) {
+  // Bytecode::kForInNext with invalid range operand (kRegPair8)
+  Register receiver(192);
+  Register receiver_translated(receiver.index() + window_width());
+  Register index(193);
+  Register index_translated(index.index() + window_width());
+  Register cache_info_pair(194);
+  Register cache_info_pair_translated(cache_info_pair.index() + window_width());
+  uint32_t operands[] = {receiver.ToRawOperand(), index.ToRawOperand(),
+                         cache_info_pair.ToRawOperand()};
+  ASSERT_DEATH_IF_SUPPORTED(
+      translator()->TranslateInputRegisters(Bytecode::kForInNext, operands, 3),
+      kBadOperandRegex);
+}
+
+}  // namespace interpreter
+}  // namespace internal
+}  // namespace v8