Reland "[vm] Refactor Location to use either dart::Register or dart::host::Register"

Refactoring motivation: go/dart-simulated-ffi

* template Location and PairLocation with <dart::Register, dart::FpuRegister> or <dart::host::Register, dart::host::FpuRegister>
* move RegisterName and FpuRegisterName from assembler to constants
* move methods that are only implemented by Location and not HostLocation out of Location

Change-Id: Ie9aa2dae63380da0cbfb15eacc440537fbed48f8
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-bare-linux-release-simarm-try, vm-kernel-precomp-bare-linux-release-simarm64-try, vm-kernel-precomp-linux-debug-x64-try, vm-kernel-linux-debug-simdbc64-try, vm-kernel-precomp-win-release-simarm64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/98845
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
Auto-Submit: Daco Harkes <dacoharkes@google.com>
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index be43b30..7815569 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -352,6 +352,19 @@
 #error Unknown architecture.
 #endif
 
+// Determine whether HOST_ARCH equals TARGET_ARCH.
+#if defined(HOST_ARCH_ARM) && defined(TARGET_ARCH_ARM)
+#define HOST_ARCH_EQUALS_TARGET_ARCH 1
+#elif defined(HOST_ARCH_ARM64) && defined(TARGET_ARCH_ARM64)
+#define HOST_ARCH_EQUALS_TARGET_ARCH 1
+#elif defined(HOST_ARCH_IA32) && defined(TARGET_ARCH_IA32)
+#define HOST_ARCH_EQUALS_TARGET_ARCH 1
+#elif defined(HOST_ARCH_X64) && defined(TARGET_ARCH_X64)
+#define HOST_ARCH_EQUALS_TARGET_ARCH 1
+#else
+// HOST_ARCH != TARGET_ARCH.
+#endif
+
 #if !defined(TARGET_OS_ANDROID) && !defined(TARGET_OS_FUCHSIA) &&              \
     !defined(TARGET_OS_MACOS_IOS) && !defined(TARGET_OS_LINUX) &&              \
     !defined(TARGET_OS_MACOS) && !defined(TARGET_OS_WINDOWS)
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index f2376b8..e289919 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -3595,28 +3595,6 @@
   strb(tmp, Address(addr, 3));
 }
 
-static const char* cpu_reg_names[kNumberOfCpuRegisters] = {
-    "r0", "r1",  "r2", "r3", "r4", "r5", "r6", "r7",
-    "r8", "ctx", "pp", "fp", "ip", "sp", "lr", "pc",
-};
-
-const char* Assembler::RegisterName(Register reg) {
-  ASSERT((0 <= reg) && (reg < kNumberOfCpuRegisters));
-  return cpu_reg_names[reg];
-}
-
-static const char* fpu_reg_names[kNumberOfFpuRegisters] = {
-    "q0", "q1", "q2",  "q3",  "q4",  "q5",  "q6",  "q7",
-#if defined(VFPv3_D32)
-    "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15",
-#endif
-};
-
-const char* Assembler::FpuRegisterName(FpuRegister reg) {
-  ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters));
-  return fpu_reg_names[reg];
-}
-
 }  // namespace compiler
 }  // namespace dart
 
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index 145269b..85db232 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -379,10 +379,6 @@
 
   static void InitializeMemoryWithBreakpoints(uword data, intptr_t length);
 
-  static const char* RegisterName(Register reg);
-
-  static const char* FpuRegisterName(FpuRegister reg);
-
   // Data-processing instructions.
   void and_(Register rd, Register rn, Operand o, Condition cond = AL);
 
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index b466c6b..faa28dd 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -68,28 +68,6 @@
   buffer_.Emit<int32_t>(value);
 }
 
-static const char* cpu_reg_names[kNumberOfCpuRegisters] = {
-    "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",  "r8",  "r9",  "r10",
-    "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21",
-    "r22", "r23", "r24", "ip0", "ip1", "pp",  "ctx", "fp",  "lr",  "r31",
-};
-
-const char* Assembler::RegisterName(Register reg) {
-  ASSERT((0 <= reg) && (reg < kNumberOfCpuRegisters));
-  return cpu_reg_names[reg];
-}
-
-static const char* fpu_reg_names[kNumberOfFpuRegisters] = {
-    "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",  "v7",  "v8",  "v9",  "v10",
-    "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21",
-    "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
-};
-
-const char* Assembler::FpuRegisterName(FpuRegister reg) {
-  ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters));
-  return fpu_reg_names[reg];
-}
-
 int32_t Assembler::BindImm19Branch(int64_t position, int64_t dest) {
   if (use_far_branches() && !CanEncodeImm19BranchOffset(dest)) {
     // Far branches are enabled, and we can't encode the branch offset in
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index de51436..9de307b 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -473,10 +473,6 @@
 
   static void InitializeMemoryWithBreakpoints(uword data, intptr_t length);
 
-  static const char* RegisterName(Register reg);
-
-  static const char* FpuRegisterName(FpuRegister reg);
-
   void SetPrologueOffset() {
     if (prologue_offset_ == -1) {
       prologue_offset_ = CodeSize();
diff --git a/runtime/vm/compiler/assembler/assembler_dbc.cc b/runtime/vm/compiler/assembler/assembler_dbc.cc
index 141c36a..fe6f47f 100644
--- a/runtime/vm/compiler/assembler/assembler_dbc.cc
+++ b/runtime/vm/compiler/assembler/assembler_dbc.cc
@@ -71,14 +71,6 @@
   buffer_.Emit<int32_t>(value);
 }
 
-const char* Assembler::RegisterName(Register reg) {
-  return ThreadState::Current()->zone()->PrintToString("R%d", reg);
-}
-
-const char* Assembler::FpuRegisterName(FpuRegister reg) {
-  return ThreadState::Current()->zone()->PrintToString("F%d", reg);
-}
-
 static int32_t EncodeJump(int32_t relative_pc) {
   return SimulatorBytecode::kJump | (relative_pc << 8);
 }
diff --git a/runtime/vm/compiler/assembler/assembler_dbc.h b/runtime/vm/compiler/assembler/assembler_dbc.h
index 3c57878..253fdc1 100644
--- a/runtime/vm/compiler/assembler/assembler_dbc.h
+++ b/runtime/vm/compiler/assembler/assembler_dbc.h
@@ -44,10 +44,6 @@
 
   static void InitializeMemoryWithBreakpoints(uword data, intptr_t length);
 
-  static const char* RegisterName(Register reg);
-
-  static const char* FpuRegisterName(FpuRegister reg);
-
   static uword GetBreakInstructionFiller() { return SimulatorBytecode::kTrap; }
 
   static bool IsSafe(const Object& value) { return true; }
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index 5df8760..5806575 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2594,24 +2594,6 @@
 
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-// Used by disassembler, so it is declared outside of
-// !defined(DART_PRECOMPILED_RUNTIME) section.
-static const char* cpu_reg_names[kNumberOfCpuRegisters] = {
-    "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"};
-
-const char* Assembler::RegisterName(Register reg) {
-  ASSERT((0 <= reg) && (reg < kNumberOfCpuRegisters));
-  return cpu_reg_names[reg];
-}
-
-static const char* xmm_reg_names[kNumberOfXmmRegisters] = {
-    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"};
-
-const char* Assembler::FpuRegisterName(FpuRegister reg) {
-  ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters));
-  return xmm_reg_names[reg];
-}
-
 }  // namespace compiler
 }  // namespace dart
 
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h
index 1ec4248..6eb2936 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.h
+++ b/runtime/vm/compiler/assembler/assembler_ia32.h
@@ -811,9 +811,6 @@
 
   static void InitializeMemoryWithBreakpoints(uword data, intptr_t length);
 
-  static const char* RegisterName(Register reg);
-  static const char* FpuRegisterName(FpuRegister reg);
-
   // Check if the given value is an integer value that can be directly
   // emdedded into the code without additional XORing with jit_cookie.
   // We consider 16-bit integers, powers of two and corresponding masks
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index 0889448..63c6905 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -2133,26 +2133,6 @@
 
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-static const char* xmm_reg_names[kNumberOfXmmRegisters] = {
-    "xmm0", "xmm1", "xmm2",  "xmm3",  "xmm4",  "xmm5",  "xmm6",  "xmm7",
-    "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"};
-
-const char* Assembler::FpuRegisterName(FpuRegister reg) {
-  ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters));
-  return xmm_reg_names[reg];
-}
-
-static const char* cpu_reg_names[kNumberOfCpuRegisters] = {
-    "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
-    "r8",  "r9",  "r10", "r11", "r12", "r13", "thr", "pp"};
-
-// Used by disassembler, so it is declared outside of
-// !defined(DART_PRECOMPILED_RUNTIME) section.
-const char* Assembler::RegisterName(Register reg) {
-  ASSERT((0 <= reg) && (reg < kNumberOfCpuRegisters));
-  return cpu_reg_names[reg];
-}
-
 }  // namespace compiler
 }  // namespace dart
 
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index 2df4c31..34f612e 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -929,10 +929,6 @@
 
   static void InitializeMemoryWithBreakpoints(uword data, intptr_t length);
 
-  static const char* RegisterName(Register reg);
-
-  static const char* FpuRegisterName(FpuRegister reg);
-
   static Address ElementAddressForIntIndex(bool is_external,
                                            intptr_t cid,
                                            intptr_t index_scale,
diff --git a/runtime/vm/compiler/assembler/disassembler_x86.cc b/runtime/vm/compiler/assembler/disassembler_x86.cc
index 9d9b45e..756e5d4 100644
--- a/runtime/vm/compiler/assembler/disassembler_x86.cc
+++ b/runtime/vm/compiler/assembler/disassembler_x86.cc
@@ -308,7 +308,7 @@
   }
 
   const char* NameOfCPURegister(int reg) const {
-    return compiler::Assembler::RegisterName(static_cast<Register>(reg));
+    return RegisterNames::RegisterName(static_cast<Register>(reg));
   }
 
   const char* NameOfByteCPURegister(int reg) const {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 221ba66..b59a7fc 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -81,7 +81,8 @@
         it.CurrentValue()->definition()->IsPushArgument()) {
       it.SetCurrentLocation(Location::StackSlot(
           compiler::target::frame_layout.FrameSlotForVariableIndex(
-              -*stack_height)));
+              -*stack_height),
+          FPREG));
       (*stack_height)++;
     }
   }
@@ -960,8 +961,8 @@
   for (Environment::DeepIterator it(env); !it.Done(); it.Advance()) {
     Location loc = it.CurrentLocation();
     Value* value = it.CurrentValue();
-    it.SetCurrentLocation(loc.RemapForSlowPath(value->definition(),
-                                               cpu_reg_slots, fpu_reg_slots));
+    it.SetCurrentLocation(LocationRemapForSlowPath(
+        loc, value->definition(), cpu_reg_slots, fpu_reg_slots));
   }
 
   return env;
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc b/runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc
index 09c490bd..892cdb5 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc
@@ -113,7 +113,8 @@
         NULL,
         Location::StackSlot(
             compiler::target::frame_layout.FrameSlotForVariableIndex(
-                -stack_height)),
+                -stack_height),
+            FPREG),
         slot_ix++);
   }
 
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index c91ff08..dfa2fc7 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -727,7 +727,7 @@
       __ PushObject(value.constant());
     } else {
       ASSERT(value.IsStackSlot());
-      __ pushl(value.ToStackSlotAddress());
+      __ pushl(LocationToStackSlotAddress(value));
     }
   }
 }
@@ -990,8 +990,8 @@
   }
   // Do not use the code from the function, but let the code be patched so that
   // we can record the outgoing edges to other code.
-  GenerateStaticDartCall(deopt_id, token_pos,
-                         RawPcDescriptors::kOther, locs, function);
+  GenerateStaticDartCall(deopt_id, token_pos, RawPcDescriptors::kOther, locs,
+                         function);
   __ Drop(count_with_type_args);
 }
 
@@ -1182,15 +1182,15 @@
       __ movl(destination.reg(), source.reg());
     } else {
       ASSERT(destination.IsStackSlot());
-      __ movl(destination.ToStackSlotAddress(), source.reg());
+      __ movl(LocationToStackSlotAddress(destination), source.reg());
     }
   } else if (source.IsStackSlot()) {
     if (destination.IsRegister()) {
-      __ movl(destination.reg(), source.ToStackSlotAddress());
+      __ movl(destination.reg(), LocationToStackSlotAddress(source));
     } else {
       ASSERT(destination.IsStackSlot());
-      MoveMemoryToMemory(destination.ToStackSlotAddress(),
-                         source.ToStackSlotAddress());
+      MoveMemoryToMemory(LocationToStackSlotAddress(destination),
+                         LocationToStackSlotAddress(source));
     }
   } else if (source.IsFpuRegister()) {
     if (destination.IsFpuRegister()) {
@@ -1199,27 +1199,27 @@
       __ movaps(destination.fpu_reg(), source.fpu_reg());
     } else {
       if (destination.IsDoubleStackSlot()) {
-        __ movsd(destination.ToStackSlotAddress(), source.fpu_reg());
+        __ movsd(LocationToStackSlotAddress(destination), source.fpu_reg());
       } else {
         ASSERT(destination.IsQuadStackSlot());
-        __ movups(destination.ToStackSlotAddress(), source.fpu_reg());
+        __ movups(LocationToStackSlotAddress(destination), source.fpu_reg());
       }
     }
   } else if (source.IsDoubleStackSlot()) {
     if (destination.IsFpuRegister()) {
-      __ movsd(destination.fpu_reg(), source.ToStackSlotAddress());
+      __ movsd(destination.fpu_reg(), LocationToStackSlotAddress(source));
     } else {
       ASSERT(destination.IsDoubleStackSlot());
-      __ movsd(XMM0, source.ToStackSlotAddress());
-      __ movsd(destination.ToStackSlotAddress(), XMM0);
+      __ movsd(XMM0, LocationToStackSlotAddress(source));
+      __ movsd(LocationToStackSlotAddress(destination), XMM0);
     }
   } else if (source.IsQuadStackSlot()) {
     if (destination.IsFpuRegister()) {
-      __ movups(destination.fpu_reg(), source.ToStackSlotAddress());
+      __ movups(destination.fpu_reg(), LocationToStackSlotAddress(source));
     } else {
       ASSERT(destination.IsQuadStackSlot());
-      __ movups(XMM0, source.ToStackSlotAddress());
-      __ movups(destination.ToStackSlotAddress(), XMM0);
+      __ movups(XMM0, LocationToStackSlotAddress(source));
+      __ movups(LocationToStackSlotAddress(destination), XMM0);
     }
   } else {
     ASSERT(source.IsConstant());
@@ -1237,11 +1237,12 @@
   if (source.IsRegister() && destination.IsRegister()) {
     __ xchgl(destination.reg(), source.reg());
   } else if (source.IsRegister() && destination.IsStackSlot()) {
-    Exchange(source.reg(), destination.ToStackSlotAddress());
+    Exchange(source.reg(), LocationToStackSlotAddress(destination));
   } else if (source.IsStackSlot() && destination.IsRegister()) {
-    Exchange(destination.reg(), source.ToStackSlotAddress());
+    Exchange(destination.reg(), LocationToStackSlotAddress(source));
   } else if (source.IsStackSlot() && destination.IsStackSlot()) {
-    Exchange(destination.ToStackSlotAddress(), source.ToStackSlotAddress());
+    Exchange(LocationToStackSlotAddress(destination),
+             LocationToStackSlotAddress(source));
   } else if (source.IsFpuRegister() && destination.IsFpuRegister()) {
     __ movaps(XMM0, source.fpu_reg());
     __ movaps(source.fpu_reg(), destination.fpu_reg());
@@ -1254,8 +1255,8 @@
     XmmRegister reg =
         source.IsFpuRegister() ? source.fpu_reg() : destination.fpu_reg();
     const Address& slot_address = source.IsFpuRegister()
-                                      ? destination.ToStackSlotAddress()
-                                      : source.ToStackSlotAddress();
+                                      ? LocationToStackSlotAddress(destination)
+                                      : LocationToStackSlotAddress(source);
 
     if (double_width) {
       __ movsd(XMM0, slot_address);
@@ -1266,8 +1267,9 @@
     }
     __ movaps(reg, XMM0);
   } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
-    const Address& source_slot_address = source.ToStackSlotAddress();
-    const Address& destination_slot_address = destination.ToStackSlotAddress();
+    const Address& source_slot_address = LocationToStackSlotAddress(source);
+    const Address& destination_slot_address =
+        LocationToStackSlotAddress(destination);
 
     ScratchFpuRegisterScope ensure_scratch(this, XMM0);
     __ movsd(XMM0, source_slot_address);
@@ -1275,8 +1277,9 @@
     __ movsd(destination_slot_address, XMM0);
     __ movsd(source_slot_address, ensure_scratch.reg());
   } else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) {
-    const Address& source_slot_address = source.ToStackSlotAddress();
-    const Address& destination_slot_address = destination.ToStackSlotAddress();
+    const Address& source_slot_address = LocationToStackSlotAddress(source);
+    const Address& destination_slot_address =
+        LocationToStackSlotAddress(destination);
 
     ScratchFpuRegisterScope ensure_scratch(this, XMM0);
     __ movups(XMM0, source_slot_address);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 735f9c9..20c7f57 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -648,11 +648,11 @@
   Label done;
   if (!test_cache.IsNull()) {
     // Generate runtime call.
-    __ PushObject(Object::null_object());       // Make room for the result.
-    __ pushq(RAX);                              // Push the instance.
-    __ PushObject(type);                        // Push the type.
-    __ pushq(RDX);                              // Instantiator type arguments.
-    __ pushq(RCX);                              // Function type arguments.
+    __ PushObject(Object::null_object());  // Make room for the result.
+    __ pushq(RAX);                         // Push the instance.
+    __ PushObject(type);                   // Push the type.
+    __ pushq(RDX);                         // Instantiator type arguments.
+    __ pushq(RCX);                         // Function type arguments.
     __ LoadUniqueObject(RAX, test_cache);
     __ pushq(RAX);
     GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
@@ -787,7 +787,7 @@
       __ PushObject(value.constant());
     } else {
       ASSERT(value.IsStackSlot());
-      __ pushq(value.ToStackSlotAddress());
+      __ pushq(LocationToStackSlotAddress(value));
     }
   }
 }
@@ -1151,8 +1151,8 @@
   }
   // Do not use the code from the function, but let the code be patched so that
   // we can record the outgoing edges to other code.
-  GenerateStaticDartCall(deopt_id, token_pos,
-                         RawPcDescriptors::kOther, locs, function, entry_kind);
+  GenerateStaticDartCall(deopt_id, token_pos, RawPcDescriptors::kOther, locs,
+                         function, entry_kind);
   __ Drop(count_with_type_args, RCX);
 }
 
@@ -1308,18 +1308,18 @@
       ASSERT((destination.base_reg() != FPREG) ||
              ((-compiler::target::frame_layout.VariableIndexForFrameSlot(
                   destination.stack_index())) < compiler_->StackSize()));
-      __ movq(destination.ToStackSlotAddress(), source.reg());
+      __ movq(LocationToStackSlotAddress(destination), source.reg());
     }
   } else if (source.IsStackSlot()) {
     ASSERT((source.base_reg() != FPREG) ||
            ((-compiler::target::frame_layout.VariableIndexForFrameSlot(
                 source.stack_index())) < compiler_->StackSize()));
     if (destination.IsRegister()) {
-      __ movq(destination.reg(), source.ToStackSlotAddress());
+      __ movq(destination.reg(), LocationToStackSlotAddress(source));
     } else {
       ASSERT(destination.IsStackSlot());
-      MoveMemoryToMemory(destination.ToStackSlotAddress(),
-                         source.ToStackSlotAddress());
+      MoveMemoryToMemory(LocationToStackSlotAddress(destination),
+                         LocationToStackSlotAddress(source));
     }
   } else if (source.IsFpuRegister()) {
     if (destination.IsFpuRegister()) {
@@ -1328,27 +1328,27 @@
       __ movaps(destination.fpu_reg(), source.fpu_reg());
     } else {
       if (destination.IsDoubleStackSlot()) {
-        __ movsd(destination.ToStackSlotAddress(), source.fpu_reg());
+        __ movsd(LocationToStackSlotAddress(destination), source.fpu_reg());
       } else {
         ASSERT(destination.IsQuadStackSlot());
-        __ movups(destination.ToStackSlotAddress(), source.fpu_reg());
+        __ movups(LocationToStackSlotAddress(destination), source.fpu_reg());
       }
     }
   } else if (source.IsDoubleStackSlot()) {
     if (destination.IsFpuRegister()) {
-      __ movsd(destination.fpu_reg(), source.ToStackSlotAddress());
+      __ movsd(destination.fpu_reg(), LocationToStackSlotAddress(source));
     } else {
       ASSERT(destination.IsDoubleStackSlot());
-      __ movsd(XMM0, source.ToStackSlotAddress());
-      __ movsd(destination.ToStackSlotAddress(), XMM0);
+      __ movsd(XMM0, LocationToStackSlotAddress(source));
+      __ movsd(LocationToStackSlotAddress(destination), XMM0);
     }
   } else if (source.IsQuadStackSlot()) {
     if (destination.IsFpuRegister()) {
-      __ movups(destination.fpu_reg(), source.ToStackSlotAddress());
+      __ movups(destination.fpu_reg(), LocationToStackSlotAddress(source));
     } else {
       ASSERT(destination.IsQuadStackSlot());
-      __ movups(XMM0, source.ToStackSlotAddress());
-      __ movups(destination.ToStackSlotAddress(), XMM0);
+      __ movups(XMM0, LocationToStackSlotAddress(source));
+      __ movups(LocationToStackSlotAddress(destination), XMM0);
     }
   } else {
     ASSERT(source.IsConstant());
@@ -1372,11 +1372,12 @@
   if (source.IsRegister() && destination.IsRegister()) {
     __ xchgq(destination.reg(), source.reg());
   } else if (source.IsRegister() && destination.IsStackSlot()) {
-    Exchange(source.reg(), destination.ToStackSlotAddress());
+    Exchange(source.reg(), LocationToStackSlotAddress(destination));
   } else if (source.IsStackSlot() && destination.IsRegister()) {
-    Exchange(destination.reg(), source.ToStackSlotAddress());
+    Exchange(destination.reg(), LocationToStackSlotAddress(source));
   } else if (source.IsStackSlot() && destination.IsStackSlot()) {
-    Exchange(destination.ToStackSlotAddress(), source.ToStackSlotAddress());
+    Exchange(LocationToStackSlotAddress(destination),
+             LocationToStackSlotAddress(source));
   } else if (source.IsFpuRegister() && destination.IsFpuRegister()) {
     __ movaps(XMM0, source.fpu_reg());
     __ movaps(source.fpu_reg(), destination.fpu_reg());
@@ -1389,8 +1390,8 @@
     XmmRegister reg =
         source.IsFpuRegister() ? source.fpu_reg() : destination.fpu_reg();
     Address slot_address = source.IsFpuRegister()
-                               ? destination.ToStackSlotAddress()
-                               : source.ToStackSlotAddress();
+                               ? LocationToStackSlotAddress(destination)
+                               : LocationToStackSlotAddress(source);
 
     if (double_width) {
       __ movsd(XMM0, slot_address);
@@ -1401,8 +1402,9 @@
     }
     __ movaps(reg, XMM0);
   } else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
-    const Address& source_slot_address = source.ToStackSlotAddress();
-    const Address& destination_slot_address = destination.ToStackSlotAddress();
+    const Address& source_slot_address = LocationToStackSlotAddress(source);
+    const Address& destination_slot_address =
+        LocationToStackSlotAddress(destination);
 
     ScratchFpuRegisterScope ensure_scratch(this, XMM0);
     __ movsd(XMM0, source_slot_address);
@@ -1410,8 +1412,9 @@
     __ movsd(destination_slot_address, XMM0);
     __ movsd(source_slot_address, ensure_scratch.reg());
   } else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) {
-    const Address& source_slot_address = source.ToStackSlotAddress();
-    const Address& destination_slot_address = destination.ToStackSlotAddress();
+    const Address& source_slot_address = LocationToStackSlotAddress(source);
+    const Address& destination_slot_address =
+        LocationToStackSlotAddress(destination);
 
     ScratchFpuRegisterScope ensure_scratch(this, XMM0);
     __ movups(XMM0, source_slot_address);
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index ac28cce..c6dda52 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -3952,8 +3952,8 @@
   registers_remapped_ = true;
 
   for (intptr_t i = 0; i < InputCount(); i++) {
-    locations_[i] = LocationAt(i).RemapForSlowPath(
-        InputAt(i)->definition(), cpu_reg_slots, fpu_reg_slots);
+    locations_[i] = LocationRemapForSlowPath(
+        LocationAt(i), InputAt(i)->definition(), cpu_reg_slots, fpu_reg_slots);
   }
 }
 
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 94422d2..4dab058 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -79,7 +79,7 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  locs->set_in(0, Location::AnyOrConstant(value()));
+  locs->set_in(0, LocationAnyOrConstant(value()));
   return locs;
 }
 
@@ -558,12 +558,12 @@
     const intptr_t kNumTemps = 0;
     LocationSummary* locs = new (zone)
         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-    locs->set_in(0, Location::RegisterOrConstant(left()));
+    locs->set_in(0, LocationRegisterOrConstant(left()));
     // Only one input can be a constant operand. The case of two constant
     // operands should be handled by constant propagation.
     locs->set_in(1, locs->in(0).IsConstant()
                         ? Location::RequiresRegister()
-                        : Location::RegisterOrConstant(right()));
+                        : LocationRegisterOrConstant(right()));
     locs->set_out(0, Location::RequiresRegister());
     return locs;
   }
@@ -794,7 +794,7 @@
   locs->set_in(0, Location::RequiresRegister());
   // Only one input can be a constant operand. The case of two constant
   // operands should be handled by constant propagation.
-  locs->set_in(1, Location::RegisterOrConstant(right()));
+  locs->set_in(1, LocationRegisterOrConstant(right()));
   return locs;
 }
 
@@ -894,12 +894,12 @@
   ASSERT(operation_cid() == kSmiCid);
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  summary->set_in(0, Location::RegisterOrConstant(left()));
+  summary->set_in(0, LocationRegisterOrConstant(left()));
   // Only one input can be a constant operand. The case of two constant
   // operands should be handled by constant propagation.
   summary->set_in(1, summary->in(0).IsConstant()
                          ? Location::RequiresRegister()
-                         : Location::RegisterOrConstant(right()));
+                         : LocationRegisterOrConstant(right()));
   summary->set_out(0, Location::RequiresRegister());
   return summary;
 }
@@ -1010,14 +1010,14 @@
   auto load_single_slot = [&](Location from, Location to) {
     if (!to.IsStackSlot()) return;
     if (from.IsRegister()) {
-      __ str(from.reg(), to.ToStackSlotAddress());
+      __ str(from.reg(), LocationToStackSlotAddress(to));
     } else if (from.IsFpuRegister()) {
       __ vstrs(EvenSRegisterOf(EvenDRegisterOf(from.fpu_reg())),
-               to.ToStackSlotAddress());
+               LocationToStackSlotAddress(to));
     } else if (from.IsStackSlot() || from.IsDoubleStackSlot()) {
       ASSERT(from.base_reg() == FPREG);
       __ ldr(TMP, Address(saved_fp, from.ToStackSlotOffset()));
-      __ str(TMP, to.ToStackSlotAddress());
+      __ str(TMP, LocationToStackSlotAddress(to));
     } else {
       UNREACHABLE();
     }
@@ -1032,11 +1032,11 @@
     } else if (target.IsDoubleStackSlot()) {
       if (origin.IsFpuRegister()) {
         __ vstrd(EvenDRegisterOf(origin.fpu_reg()),
-                 target.ToStackSlotAddress());
+                 LocationToStackSlotAddress(target));
       } else {
         ASSERT(origin.IsDoubleStackSlot() && origin.base_reg() == FPREG);
         __ vldrd(DTMP, Address(saved_fp, origin.ToStackSlotOffset()));
-        __ vstrd(DTMP, target.ToStackSlotAddress());
+        __ vstrd(DTMP, LocationToStackSlotAddress(target));
       }
     } else if (target.IsPairLocation()) {
       ASSERT(origin.IsPairLocation());
@@ -1626,7 +1626,7 @@
     case kArrayCid:
       locs->set_in(2, ShouldEmitStoreBarrier()
                           ? Location::RegisterLocation(kWriteBarrierValueReg)
-                          : Location::RegisterOrConstant(value()));
+                          : LocationRegisterOrConstant(value()));
       if (ShouldEmitStoreBarrier()) {
         locs->set_in(0, Location::RegisterLocation(kWriteBarrierObjectReg));
         locs->set_temp(0, Location::RegisterLocation(kWriteBarrierSlotReg));
@@ -2315,7 +2315,7 @@
   } else {
     summary->set_in(1, ShouldEmitStoreBarrier()
                            ? Location::RegisterLocation(kWriteBarrierValueReg)
-                           : Location::RegisterOrConstant(value()));
+                           : LocationRegisterOrConstant(value()));
   }
   return summary;
 }
@@ -3629,7 +3629,7 @@
     return summary;
   }
   summary->set_in(0, Location::RequiresRegister());
-  summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+  summary->set_in(1, LocationRegisterOrSmiConstant(right()));
   if (((op_kind() == Token::kSHL) && can_overflow()) ||
       (op_kind() == Token::kSHR)) {
     summary->set_temp(0, Location::RequiresRegister());
@@ -3941,7 +3941,7 @@
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
-  summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+  summary->set_in(1, LocationRegisterOrSmiConstant(right()));
   if (((op_kind() == Token::kSHL) && can_overflow()) ||
       (op_kind() == Token::kSHR)) {
     summary->set_temp(0, Location::RequiresRegister());
@@ -5972,8 +5972,8 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length()));
-  locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index()));
+  locs->set_in(kLengthPos, LocationRegisterOrSmiConstant(length()));
+  locs->set_in(kIndexPos, LocationRegisterOrSmiConstant(index()));
   return locs;
 }
 
@@ -6339,7 +6339,7 @@
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::Pair(Location::RequiresRegister(),
                                     Location::RequiresRegister()));
-  summary->set_in(1, Location::WritableRegisterOrSmiConstant(right()));
+  summary->set_in(1, LocationWritableRegisterOrSmiConstant(right()));
   summary->set_out(0, Location::Pair(Location::RequiresRegister(),
                                      Location::RequiresRegister()));
   return summary;
@@ -6474,7 +6474,7 @@
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
-  summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+  summary->set_in(1, LocationRegisterOrSmiConstant(right()));
   summary->set_temp(0, Location::RequiresRegister());
   summary->set_out(0, Location::RequiresRegister());
   return summary;
@@ -6945,7 +6945,7 @@
   if ((constant != NULL) && !left()->IsSingleUse()) {
     locs->set_in(0, Location::RequiresRegister());
   } else {
-    locs->set_in(0, Location::RegisterOrConstant(left()));
+    locs->set_in(0, LocationRegisterOrConstant(left()));
   }
 
   constant = right()->definition()->AsConstant();
@@ -6956,7 +6956,7 @@
     // one is a constant.
     locs->set_in(1, locs->in(0).IsConstant()
                         ? Location::RequiresRegister()
-                        : Location::RegisterOrConstant(right()));
+                        : LocationRegisterOrConstant(right()));
   }
   locs->set_out(0, Location::RequiresRegister());
   return locs;
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 67e080b..747ee54 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -79,7 +79,7 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  locs->set_in(0, Location::AnyOrConstant(value()));
+  locs->set_in(0, LocationAnyOrConstant(value()));
   return locs;
 }
 
@@ -627,13 +627,13 @@
     const intptr_t kNumTemps = 0;
     LocationSummary* locs = new (zone)
         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-    locs->set_in(0, Location::RegisterOrConstant(left()));
+    locs->set_in(0, LocationRegisterOrConstant(left()));
     // Only one input can be a constant operand. The case of two constant
     // operands should be handled by constant propagation.
     // Only right can be a stack slot.
     locs->set_in(1, locs->in(0).IsConstant()
                         ? Location::RequiresRegister()
-                        : Location::RegisterOrConstant(right()));
+                        : LocationRegisterOrConstant(right()));
     locs->set_out(0, Location::RequiresRegister());
     return locs;
   }
@@ -695,7 +695,7 @@
   locs->set_in(0, Location::RequiresRegister());
   // Only one input can be a constant operand. The case of two constant
   // operands should be handled by constant propagation.
-  locs->set_in(1, Location::RegisterOrConstant(right()));
+  locs->set_in(1, LocationRegisterOrConstant(right()));
   return locs;
 }
 
@@ -783,12 +783,12 @@
   if (operation_cid() == kSmiCid || operation_cid() == kMintCid) {
     LocationSummary* summary = new (zone)
         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-    summary->set_in(0, Location::RegisterOrConstant(left()));
+    summary->set_in(0, LocationRegisterOrConstant(left()));
     // Only one input can be a constant operand. The case of two constant
     // operands should be handled by constant propagation.
     summary->set_in(1, summary->in(0).IsConstant()
                            ? Location::RequiresRegister()
-                           : Location::RegisterOrConstant(right()));
+                           : LocationRegisterOrConstant(right()));
     summary->set_out(0, Location::RequiresRegister());
     return summary;
   }
@@ -1465,7 +1465,7 @@
     case kArrayCid:
       locs->set_in(2, ShouldEmitStoreBarrier()
                           ? Location::RegisterLocation(kWriteBarrierValueReg)
-                          : Location::RegisterOrConstant(value()));
+                          : LocationRegisterOrConstant(value()));
       if (ShouldEmitStoreBarrier()) {
         locs->set_in(0, Location::RegisterLocation(kWriteBarrierObjectReg));
         locs->set_temp(0, Location::RegisterLocation(kWriteBarrierSlotReg));
@@ -2015,7 +2015,7 @@
   } else {
     summary->set_in(1, ShouldEmitStoreBarrier()
                            ? Location::RegisterLocation(kWriteBarrierValueReg)
-                           : Location::RegisterOrConstant(value()));
+                           : LocationRegisterOrConstant(value()));
   }
   return summary;
 }
@@ -3301,7 +3301,7 @@
     return summary;
   }
   summary->set_in(0, Location::RequiresRegister());
-  summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+  summary->set_in(1, LocationRegisterOrSmiConstant(right()));
   if (((op_kind() == Token::kSHL) && can_overflow()) ||
       (op_kind() == Token::kSHR)) {
     summary->set_temp(0, Location::RequiresRegister());
@@ -5135,8 +5135,8 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length()));
-  locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index()));
+  locs->set_in(kLengthPos, LocationRegisterOrSmiConstant(length()));
+  locs->set_in(kIndexPos, LocationRegisterOrSmiConstant(index()));
   return locs;
 }
 
@@ -5337,7 +5337,7 @@
       LocationSummary* summary = new (zone) LocationSummary(
           zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
       summary->set_in(0, Location::RequiresRegister());
-      summary->set_in(1, Location::RegisterOrConstant(right()));
+      summary->set_in(1, LocationRegisterOrConstant(right()));
       summary->set_out(0, Location::RequiresRegister());
       return summary;
     }
@@ -5553,7 +5553,7 @@
       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
   summary->set_in(0, Location::RequiresRegister());
   summary->set_in(1, RangeUtils::IsPositive(shift_range())
-                         ? Location::RegisterOrConstant(right())
+                         ? LocationRegisterOrConstant(right())
                          : Location::RequiresRegister());
   summary->set_out(0, Location::RequiresRegister());
   return summary;
@@ -5597,7 +5597,7 @@
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
-  summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+  summary->set_in(1, LocationRegisterOrSmiConstant(right()));
   summary->set_out(0, Location::RequiresRegister());
   return summary;
 }
@@ -5664,7 +5664,7 @@
       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
   summary->set_in(0, Location::RequiresRegister());
   summary->set_in(1, RangeUtils::IsPositive(shift_range())
-                         ? Location::RegisterOrConstant(right())
+                         ? LocationRegisterOrConstant(right())
                          : Location::RequiresRegister());
   summary->set_out(0, Location::RequiresRegister());
   return summary;
@@ -5710,7 +5710,7 @@
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
-  summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+  summary->set_in(1, LocationRegisterOrSmiConstant(right()));
   summary->set_out(0, Location::RequiresRegister());
   return summary;
 }
@@ -6102,12 +6102,12 @@
   }
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  locs->set_in(0, Location::RegisterOrConstant(left()));
+  locs->set_in(0, LocationRegisterOrConstant(left()));
   // Only one of the inputs can be a constant. Choose register if the first one
   // is a constant.
   locs->set_in(1, locs->in(0).IsConstant()
                       ? Location::RequiresRegister()
-                      : Location::RegisterOrConstant(right()));
+                      : LocationRegisterOrConstant(right()));
   locs->set_out(0, Location::RequiresRegister());
   return locs;
 }
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 19983a1..2cebcec 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -73,7 +73,7 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  locs->set_in(0, Location::AnyOrConstant(value()));
+  locs->set_in(0, LocationAnyOrConstant(value()));
   return locs;
 }
 
@@ -88,7 +88,7 @@
       __ PushObject(value.constant());
     } else {
       ASSERT(value.IsStackSlot());
-      __ pushl(value.ToStackSlotAddress());
+      __ pushl(LocationToStackSlotAddress(value));
     }
   }
 }
@@ -140,7 +140,7 @@
   const intptr_t stack_index =
       compiler::target::frame_layout.FrameSlotForVariable(&local());
   return LocationSummary::Make(zone, kNumInputs,
-                               Location::StackSlot(stack_index),
+                               Location::StackSlot(stack_index, FPREG),
                                LocationSummary::kNoCall);
 }
 
@@ -224,20 +224,20 @@
     } else {
       __ movsd(XMM0, Address::Absolute(addr));
     }
-    __ movsd(destination.ToStackSlotAddress(), XMM0);
+    __ movsd(LocationToStackSlotAddress(destination), XMM0);
   } else {
     ASSERT(destination.IsStackSlot());
     if (value_.IsSmi() && representation() == kUnboxedInt32) {
-      __ movl(destination.ToStackSlotAddress(),
+      __ movl(LocationToStackSlotAddress(destination),
               Immediate(Smi::Cast(value_).Value()));
     } else {
       if (Assembler::IsSafeSmi(value_) || value_.IsNull()) {
-        __ movl(destination.ToStackSlotAddress(),
+        __ movl(LocationToStackSlotAddress(destination),
                 Immediate(reinterpret_cast<int32_t>(value_.raw())));
       } else {
         __ pushl(EAX);
         __ LoadObjectSafely(EAX, value_);
-        __ movl(destination.ToStackSlotAddress(), EAX);
+        __ movl(LocationToStackSlotAddress(destination), EAX);
         __ popl(EAX);
       }
     }
@@ -381,13 +381,13 @@
     const intptr_t kNumTemps = 0;
     LocationSummary* locs = new (zone)
         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-    locs->set_in(0, Location::RegisterOrConstant(left()));
+    locs->set_in(0, LocationRegisterOrConstant(left()));
     // Only one input can be a constant operand. The case of two constant
     // operands should be handled by constant propagation.
     // Only right can be a stack slot.
     locs->set_in(1, locs->in(0).IsConstant()
                         ? Location::RequiresRegister()
-                        : Location::RegisterOrConstant(right()));
+                        : LocationRegisterOrConstant(right()));
     locs->set_out(0, Location::RequiresRegister());
     return locs;
   }
@@ -507,7 +507,7 @@
   } else if (right.IsConstant()) {
     __ CompareObject(left.reg(), right.constant());
   } else if (right.IsStackSlot()) {
-    __ cmpl(left.reg(), right.ToStackSlotAddress());
+    __ cmpl(left.reg(), LocationToStackSlotAddress(right));
   } else {
     __ cmpl(left.reg(), right.reg());
   }
@@ -682,7 +682,7 @@
   locs->set_in(0, Location::RequiresRegister());
   // Only one input can be a constant operand. The case of two constant
   // operands should be handled by constant propagation.
-  locs->set_in(1, Location::RegisterOrConstant(right()));
+  locs->set_in(1, LocationRegisterOrConstant(right()));
   return locs;
 }
 
@@ -781,12 +781,12 @@
   ASSERT(operation_cid() == kSmiCid);
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  summary->set_in(0, Location::RegisterOrConstant(left()));
+  summary->set_in(0, LocationRegisterOrConstant(left()));
   // Only one input can be a constant operand. The case of two constant
   // operands should be handled by constant propagation.
   summary->set_in(1, summary->in(0).IsConstant()
                          ? Location::RequiresRegister()
-                         : Location::RegisterOrConstant(right()));
+                         : LocationRegisterOrConstant(right()));
   summary->set_out(0, Location::RequiresRegister());
   return summary;
 }
@@ -874,13 +874,13 @@
   auto load_single_slot = [&](Location from, Location to) {
     ASSERT(to.IsStackSlot());
     if (from.IsRegister()) {
-      __ movl(to.ToStackSlotAddress(), from.reg());
+      __ movl(LocationToStackSlotAddress(to), from.reg());
     } else if (from.IsFpuRegister()) {
-      __ movss(to.ToStackSlotAddress(), from.fpu_reg());
+      __ movss(LocationToStackSlotAddress(to), from.fpu_reg());
     } else if (from.IsStackSlot() || from.IsDoubleStackSlot()) {
       ASSERT(from.base_reg() == FPREG);
       __ movl(tmp, Address(saved_fp, from.ToStackSlotOffset()));
-      __ movl(to.ToStackSlotAddress(), tmp);
+      __ movl(LocationToStackSlotAddress(to), tmp);
     } else {
       UNREACHABLE();
     }
@@ -894,11 +894,11 @@
       load_single_slot(origin, target);
     } else if (target.IsDoubleStackSlot()) {
       if (origin.IsFpuRegister()) {
-        __ movsd(target.ToStackSlotAddress(), origin.fpu_reg());
+        __ movsd(LocationToStackSlotAddress(target), origin.fpu_reg());
       } else {
         ASSERT(origin.IsDoubleStackSlot() && origin.base_reg() == FPREG);
         __ movl(tmp, Address(saved_fp, origin.ToStackSlotOffset()));
-        __ movl(target.ToStackSlotAddress(), tmp);
+        __ movl(LocationToStackSlotAddress(target), tmp);
         __ movl(tmp, Address(saved_fp, origin.ToStackSlotOffset() + 4));
         __ movl(Address(SPREG, target.ToStackSlotOffset() + 4), tmp);
       }
@@ -1392,7 +1392,7 @@
     case kArrayCid:
       locs->set_in(2, ShouldEmitStoreBarrier()
                           ? Location::WritableRegister()
-                          : Location::RegisterOrConstant(value()));
+                          : LocationRegisterOrConstant(value()));
       if (ShouldEmitStoreBarrier()) {
         locs->set_in(0, Location::RegisterLocation(kWriteBarrierObjectReg));
         locs->set_temp(0, Location::RegisterLocation(kWriteBarrierSlotReg));
@@ -1406,7 +1406,7 @@
     case kOneByteStringCid:
       // TODO(fschneider): Add location constraint for byte registers (EAX,
       // EBX, ECX, EDX) instead of using a fixed register.
-      locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), EAX));
+      locs->set_in(2, LocationFixedRegisterOrSmiConstant(value(), EAX));
       break;
     case kTypedDataInt16ArrayCid:
     case kTypedDataUint16ArrayCid:
@@ -1907,7 +1907,7 @@
   } else {
     summary->set_in(1, ShouldEmitStoreBarrier()
                            ? Location::WritableRegister()
-                           : Location::RegisterOrConstant(value()));
+                           : LocationRegisterOrConstant(value()));
   }
   return summary;
 }
@@ -2962,7 +2962,7 @@
     LocationSummary* summary = new (zone)
         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
     summary->set_in(0, Location::RequiresRegister());
-    summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
+    summary->set_in(1, LocationFixedRegisterOrSmiConstant(right(), ECX));
     summary->set_out(0, Location::SameAsFirstInput());
     return summary;
   } else if (op_kind() == Token::kSHL) {
@@ -2974,7 +2974,7 @@
     LocationSummary* summary = new (zone)
         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
     summary->set_in(0, Location::RequiresRegister());
-    summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
+    summary->set_in(1, LocationFixedRegisterOrSmiConstant(right(), ECX));
     if (kNumTemps == 1) {
       summary->set_temp(0, Location::RequiresRegister());
     }
@@ -2987,7 +2987,7 @@
     summary->set_in(0, Location::RequiresRegister());
     ConstantInstr* constant = right()->definition()->AsConstant();
     if (constant != NULL) {
-      summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+      summary->set_in(1, LocationRegisterOrSmiConstant(right()));
     } else {
       summary->set_in(1, Location::PrefersRegister());
     }
@@ -3096,7 +3096,7 @@
   }  // if locs()->in(1).IsConstant()
 
   if (locs()->in(1).IsStackSlot()) {
-    const Address& right = locs()->in(1).ToStackSlotAddress();
+    const Address& right = LocationToStackSlotAddress(locs()->in(1));
     if (op_kind() == Token::kMUL) {
       __ SmiUntag(left);
     }
@@ -3243,7 +3243,7 @@
     LocationSummary* summary = new (zone)
         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
     summary->set_in(0, Location::RequiresRegister());
-    summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
+    summary->set_in(1, LocationFixedRegisterOrSmiConstant(right(), ECX));
     summary->set_out(0, Location::SameAsFirstInput());
     return summary;
   } else if (op_kind() == Token::kSHL) {
@@ -3251,7 +3251,7 @@
     LocationSummary* summary = new (zone)
         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
     summary->set_in(0, Location::RequiresRegister());
-    summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
+    summary->set_in(1, LocationFixedRegisterOrSmiConstant(right(), ECX));
     if (can_overflow()) {
       summary->set_temp(0, Location::RequiresRegister());
     }
@@ -3264,7 +3264,7 @@
     summary->set_in(0, Location::RequiresRegister());
     ConstantInstr* constant = right()->definition()->AsConstant();
     if (constant != NULL) {
-      summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+      summary->set_in(1, LocationRegisterOrSmiConstant(right()));
     } else {
       summary->set_in(1, Location::PrefersRegister());
     }
@@ -3353,7 +3353,7 @@
   }  // if locs()->in(1).IsConstant()
 
   if (locs()->in(1).IsStackSlot()) {
-    const Address& right = locs()->in(1).ToStackSlotAddress();
+    const Address& right = LocationToStackSlotAddress(locs()->in(1));
     EmitIntegerArithmetic(compiler, op_kind(), left, right, deopt);
     return;
   }  // if locs()->in(1).IsStackSlot.
@@ -5301,11 +5301,11 @@
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   if (length()->definition()->IsConstant()) {
-    locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length()));
+    locs->set_in(kLengthPos, LocationRegisterOrSmiConstant(length()));
   } else {
     locs->set_in(kLengthPos, Location::PrefersRegister());
   }
-  locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index()));
+  locs->set_in(kIndexPos, LocationRegisterOrSmiConstant(index()));
   return locs;
 }
 
@@ -5345,7 +5345,7 @@
   } else if (index_loc.IsConstant()) {
     const Smi& index = Smi::Cast(index_loc.constant());
     if (length_loc.IsStackSlot()) {
-      const Address& length = length_loc.ToStackSlotAddress();
+      const Address& length = LocationToStackSlotAddress(length_loc);
       __ cmpl(length, Immediate(reinterpret_cast<int32_t>(index.raw())));
     } else {
       Register length = length_loc.reg();
@@ -5354,7 +5354,7 @@
     __ j(BELOW_EQUAL, deopt);
   } else if (length_loc.IsStackSlot()) {
     Register index = index_loc.reg();
-    const Address& length = length_loc.ToStackSlotAddress();
+    const Address& length = LocationToStackSlotAddress(length_loc);
     if (index_cid != kSmiCid) {
       __ BranchIfNotSmi(index, deopt);
     }
@@ -5722,7 +5722,7 @@
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::Pair(Location::RequiresRegister(),
                                     Location::RequiresRegister()));
-  summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
+  summary->set_in(1, LocationFixedRegisterOrSmiConstant(right(), ECX));
   summary->set_out(0, Location::SameAsFirstInput());
   return summary;
 }
@@ -5859,7 +5859,7 @@
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
-  summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
+  summary->set_in(1, LocationFixedRegisterOrSmiConstant(right(), ECX));
   summary->set_out(0, Location::SameAsFirstInput());
   return summary;
 }
@@ -6229,12 +6229,12 @@
   }
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  locs->set_in(0, Location::RegisterOrConstant(left()));
+  locs->set_in(0, LocationRegisterOrConstant(left()));
   // Only one of the inputs can be a constant. Choose register if the first one
   // is a constant.
   locs->set_in(1, locs->in(0).IsConstant()
                       ? Location::RequiresRegister()
-                      : Location::RegisterOrConstant(right()));
+                      : LocationRegisterOrConstant(right()));
   locs->set_out(0, Location::RequiresRegister());
   return locs;
 }
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index 18c53a9..19b2aed 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -1075,13 +1075,13 @@
 }
 
 void LoadIndexedUnsafeInstr::PrintOperandsTo(BufferFormatter* f) const {
-  f->Print("%s[", Assembler::RegisterName(base_reg()));
+  f->Print("%s[", RegisterNames::RegisterName(base_reg()));
   index()->PrintTo(f);
   f->Print(" + %" Pd "]", offset());
 }
 
 void StoreIndexedUnsafeInstr::PrintOperandsTo(BufferFormatter* f) const {
-  f->Print("%s[", Assembler::RegisterName(base_reg()));
+  f->Print("%s[", RegisterNames::RegisterName(base_reg()));
   index()->PrintTo(f);
   f->Print(" + %" Pd "], ", offset());
   value()->PrintTo(f);
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 6947e3c..664236a 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -74,7 +74,7 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  locs->set_in(0, Location::AnyOrConstant(value()));
+  locs->set_in(0, LocationAnyOrConstant(value()));
   return locs;
 }
 
@@ -89,7 +89,7 @@
       __ PushObject(value.constant());
     } else {
       ASSERT(value.IsStackSlot());
-      __ pushq(value.ToStackSlotAddress());
+      __ pushq(LocationToStackSlotAddress(value));
     }
   }
 }
@@ -243,7 +243,7 @@
   const intptr_t stack_index =
       compiler::target::frame_layout.FrameSlotForVariable(&local());
   return LocationSummary::Make(zone, kNumInputs,
-                               Location::StackSlot(stack_index),
+                               Location::StackSlot(stack_index, FPREG),
                                LocationSummary::kNoCall);
 }
 
@@ -321,16 +321,16 @@
       __ LoadObject(tmp, value_);
       __ movsd(XMM0, FieldAddress(tmp, Double::value_offset()));
     }
-    __ movsd(destination.ToStackSlotAddress(), XMM0);
+    __ movsd(LocationToStackSlotAddress(destination), XMM0);
   } else {
     ASSERT(destination.IsStackSlot());
     if (representation() == kUnboxedInt32 ||
         representation() == kUnboxedInt64) {
       const int64_t value = Integer::Cast(value_).AsInt64Value();
-      __ movq(destination.ToStackSlotAddress(), Immediate(value));
+      __ movq(LocationToStackSlotAddress(destination), Immediate(value));
     } else {
       ASSERT(representation() == kTagged);
-      __ StoreObject(destination.ToStackSlotAddress(), value_);
+      __ StoreObject(LocationToStackSlotAddress(destination), value_);
     }
   }
 }
@@ -525,13 +525,13 @@
     const intptr_t kNumTemps = 0;
     LocationSummary* locs = new (zone)
         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-    locs->set_in(0, Location::RegisterOrConstant(left()));
+    locs->set_in(0, LocationRegisterOrConstant(left()));
     // Only one input can be a constant operand. The case of two constant
     // operands should be handled by constant propagation.
     // Only right can be a stack slot.
     locs->set_in(1, locs->in(0).IsConstant()
                         ? Location::RequiresRegister()
-                        : Location::RegisterOrConstant(right()));
+                        : LocationRegisterOrConstant(right()));
     locs->set_out(0, Location::RequiresRegister());
     return locs;
   }
@@ -632,7 +632,7 @@
       __ CompareObject(left.reg(), right.constant());
     }
   } else if (right.IsStackSlot()) {
-    __ cmpq(left.reg(), right.ToStackSlotAddress());
+    __ cmpq(left.reg(), LocationToStackSlotAddress(right));
   } else {
     __ cmpq(left.reg(), right.reg());
   }
@@ -720,7 +720,7 @@
   locs->set_in(0, Location::RequiresRegister());
   // Only one input can be a constant operand. The case of two constant
   // operands should be handled by constant propagation.
-  locs->set_in(1, Location::RegisterOrConstant(right()));
+  locs->set_in(1, LocationRegisterOrConstant(right()));
   return locs;
 }
 
@@ -808,12 +808,12 @@
   if (operation_cid() == kSmiCid || operation_cid() == kMintCid) {
     LocationSummary* summary = new (zone)
         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-    summary->set_in(0, Location::RegisterOrConstant(left()));
+    summary->set_in(0, LocationRegisterOrConstant(left()));
     // Only one input can be a constant operand. The case of two constant
     // operands should be handled by constant propagation.
     summary->set_in(1, summary->in(0).IsConstant()
                            ? Location::RequiresRegister()
-                           : Location::RegisterOrConstant(right()));
+                           : LocationRegisterOrConstant(right()));
     summary->set_out(0, Location::RequiresRegister());
     return summary;
   }
@@ -912,15 +912,15 @@
 
     if (target.IsStackSlot()) {
       if (origin.IsRegister()) {
-        __ movq(target.ToStackSlotAddress(), origin.reg());
+        __ movq(LocationToStackSlotAddress(target), origin.reg());
       } else if (origin.IsFpuRegister()) {
         __ movq(TMP, origin.fpu_reg());
-        __ movq(target.ToStackSlotAddress(), TMP);
+        __ movq(LocationToStackSlotAddress(target), TMP);
       } else if (origin.IsStackSlot() || origin.IsDoubleStackSlot()) {
         // The base register cannot be SPREG because we've moved it.
         ASSERT(origin.base_reg() == FPREG);
         __ movq(TMP, Address(saved_fp, origin.ToStackSlotOffset()));
-        __ movq(target.ToStackSlotAddress(), TMP);
+        __ movq(LocationToStackSlotAddress(target), TMP);
       }
     } else {
       ASSERT(origin.Equals(target));
@@ -1498,7 +1498,7 @@
     case kArrayCid:
       locs->set_in(2, ShouldEmitStoreBarrier()
                           ? Location::RegisterLocation(kWriteBarrierValueReg)
-                          : Location::RegisterOrConstant(value()));
+                          : LocationRegisterOrConstant(value()));
       if (ShouldEmitStoreBarrier()) {
         locs->set_in(0, Location::RegisterLocation(kWriteBarrierObjectReg));
         locs->set_temp(0, Location::RegisterLocation(kWriteBarrierSlotReg));
@@ -1512,7 +1512,7 @@
     case kOneByteStringCid:
       // TODO(fschneider): Add location constraint for byte registers (RAX,
       // RBX, RCX, RDX) instead of using a fixed register.
-      locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX));
+      locs->set_in(2, LocationFixedRegisterOrSmiConstant(value(), RAX));
       break;
     case kTypedDataInt16ArrayCid:
     case kTypedDataUint16ArrayCid:
@@ -2019,7 +2019,7 @@
   } else {
     summary->set_in(1, ShouldEmitStoreBarrier()
                            ? Location::RegisterLocation(kWriteBarrierValueReg)
-                           : Location::RegisterOrConstant(value()));
+                           : LocationRegisterOrConstant(value()));
   }
   return summary;
 }
@@ -3375,7 +3375,7 @@
     LocationSummary* summary = new (zone)
         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
     summary->set_in(0, Location::RequiresRegister());
-    summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX));
+    summary->set_in(1, LocationFixedRegisterOrSmiConstant(right(), RCX));
     summary->set_out(0, Location::SameAsFirstInput());
     return summary;
   } else if (op_kind() == Token::kSHL) {
@@ -3386,7 +3386,7 @@
     LocationSummary* summary = new (zone)
         LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
     summary->set_in(0, Location::RequiresRegister());
-    summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX));
+    summary->set_in(1, LocationFixedRegisterOrSmiConstant(right(), RCX));
     if (kNumTemps == 1) {
       summary->set_temp(0, Location::RequiresRegister());
     }
@@ -3399,7 +3399,7 @@
     summary->set_in(0, Location::RequiresRegister());
     ConstantInstr* constant = right()->definition()->AsConstant();
     if (constant != NULL) {
-      summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+      summary->set_in(1, LocationRegisterOrSmiConstant(right()));
     } else {
       summary->set_in(1, Location::PrefersRegister());
     }
@@ -3499,7 +3499,7 @@
   }  // locs()->in(1).IsConstant().
 
   if (locs()->in(1).IsStackSlot()) {
-    const Address& right = locs()->in(1).ToStackSlotAddress();
+    const Address& right = LocationToStackSlotAddress(locs()->in(1));
     switch (op_kind()) {
       case Token::kADD: {
         __ addq(left, right);
@@ -5385,8 +5385,8 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length()));
-  locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index()));
+  locs->set_in(kLengthPos, LocationRegisterOrSmiConstant(length()));
+  locs->set_in(kIndexPos, LocationRegisterOrSmiConstant(index()));
   return locs;
 }
 
@@ -5669,7 +5669,7 @@
       LocationSummary* summary = new (zone) LocationSummary(
           zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
       summary->set_in(0, Location::RequiresRegister());
-      summary->set_in(1, Location::RegisterOrConstant(right()));
+      summary->set_in(1, LocationRegisterOrConstant(right()));
       summary->set_out(0, Location::SameAsFirstInput());
       return summary;
     }
@@ -5856,7 +5856,7 @@
       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
   summary->set_in(0, Location::RequiresRegister());
   summary->set_in(1, RangeUtils::IsPositive(shift_range())
-                         ? Location::FixedRegisterOrConstant(right(), RCX)
+                         ? LocationFixedRegisterOrConstant(right(), RCX)
                          : Location::RegisterLocation(RCX));
   summary->set_out(0, Location::SameAsFirstInput());
   return summary;
@@ -5902,7 +5902,7 @@
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
-  summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX));
+  summary->set_in(1, LocationFixedRegisterOrSmiConstant(right(), RCX));
   summary->set_out(0, Location::SameAsFirstInput());
   return summary;
 }
@@ -5976,7 +5976,7 @@
       zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
   summary->set_in(0, Location::RequiresRegister());
   summary->set_in(1, RangeUtils::IsPositive(shift_range())
-                         ? Location::FixedRegisterOrConstant(right(), RCX)
+                         ? LocationFixedRegisterOrConstant(right(), RCX)
                          : Location::RegisterLocation(RCX));
   summary->set_out(0, Location::SameAsFirstInput());
   return summary;
@@ -6021,7 +6021,7 @@
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   summary->set_in(0, Location::RequiresRegister());
-  summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX));
+  summary->set_in(1, LocationFixedRegisterOrSmiConstant(right(), RCX));
   summary->set_out(0, Location::SameAsFirstInput());
   return summary;
 }
@@ -6391,12 +6391,12 @@
   }
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  locs->set_in(0, Location::RegisterOrConstant(left()));
+  locs->set_in(0, LocationRegisterOrConstant(left()));
   // Only one of the inputs can be a constant. Choose register if the first one
   // is a constant.
   locs->set_in(1, locs->in(0).IsConstant()
                       ? Location::RequiresRegister()
-                      : Location::RegisterOrConstant(right()));
+                      : LocationRegisterOrConstant(right()));
   locs->set_out(0, Location::RequiresRegister());
   return locs;
 }
diff --git a/runtime/vm/compiler/backend/linearscan.cc b/runtime/vm/compiler/backend/linearscan.cc
index 9c7d766..4f5473c 100644
--- a/runtime/vm/compiler/backend/linearscan.cc
+++ b/runtime/vm/compiler/backend/linearscan.cc
@@ -675,10 +675,10 @@
       Location loc;
       switch (param->kind()) {
         case SpecialParameterInstr::kException:
-          loc = Location::ExceptionLocation();
+          loc = LocationExceptionLocation();
           break;
         case SpecialParameterInstr::kStackTrace:
-          loc = Location::StackTraceLocation();
+          loc = LocationStackTraceLocation();
           break;
         default:
           UNREACHABLE();
@@ -764,7 +764,7 @@
     ASSERT(param->kind() == SpecialParameterInstr::kArgDescriptor);
     Location loc;
 #if defined(TARGET_ARCH_DBC)
-    loc = Location::ArgumentsDescriptorLocation();
+    loc = LocationArgumentsDescriptorLocation();
 #else
     loc = Location::RegisterLocation(ARGS_DESC_REG);
 #endif  // defined(TARGET_ARCH_DBC)
@@ -2049,7 +2049,7 @@
   if (register_kind_ == Location::kRegister) {
     const intptr_t slot_index =
         compiler::target::frame_layout.FrameSlotForVariableIndex(-idx);
-    range->set_spill_slot(Location::StackSlot(slot_index));
+    range->set_spill_slot(Location::StackSlot(slot_index, FPREG));
   } else {
     // We use the index of the slot with the lowest address as an index for the
     // FPU register spill slot. In terms of indexes this relation is inverted:
@@ -2064,11 +2064,11 @@
         (range->representation() == kUnboxedInt32x4) ||
         (range->representation() == kUnboxedFloat64x2)) {
       ASSERT(need_quad);
-      location = Location::QuadStackSlot(slot_idx);
+      location = Location::QuadStackSlot(slot_idx, FPREG);
     } else {
       ASSERT(range->representation() == kUnboxedFloat ||
              range->representation() == kUnboxedDouble);
-      location = Location::DoubleStackSlot(slot_idx);
+      location = Location::DoubleStackSlot(slot_idx, FPREG);
     }
     range->set_spill_slot(location);
   }
diff --git a/runtime/vm/compiler/backend/locations.cc b/runtime/vm/compiler/backend/locations.cc
index e549879..f705a15 100644
--- a/runtime/vm/compiler/backend/locations.cc
+++ b/runtime/vm/compiler/backend/locations.cc
@@ -27,7 +27,7 @@
   for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
     Register r = static_cast<Register>(i);
     if (ContainsRegister(r)) {
-      THR_Print("%s %s\n", Assembler::RegisterName(r),
+      THR_Print("%s %s\n", RegisterNames::RegisterName(r),
                 IsTagged(r) ? "tagged" : "untagged");
     }
   }
@@ -35,7 +35,7 @@
   for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
     FpuRegister r = static_cast<FpuRegister>(i);
     if (ContainsFpuRegister(r)) {
-      THR_Print("%s\n", Assembler::FpuRegisterName(r));
+      THR_Print("%s\n", RegisterNames::FpuRegisterName(r));
     }
   }
 }
@@ -70,56 +70,66 @@
   return summary;
 }
 
-Location Location::Pair(Location first, Location second) {
-  PairLocation* pair_location = new PairLocation();
+template <class Register, class FpuRegister>
+TemplateLocation<Register, FpuRegister>
+TemplateLocation<Register, FpuRegister>::Pair(
+    TemplateLocation<Register, FpuRegister> first,
+    TemplateLocation<Register, FpuRegister> second) {
+  TemplatePairLocation<TemplateLocation<Register, FpuRegister>>* pair_location =
+      new TemplatePairLocation<TemplateLocation<Register, FpuRegister>>();
   ASSERT((reinterpret_cast<intptr_t>(pair_location) & kLocationTagMask) == 0);
   pair_location->SetAt(0, first);
   pair_location->SetAt(1, second);
-  Location loc(reinterpret_cast<uword>(pair_location) | kPairLocationTag);
+  TemplateLocation<Register, FpuRegister> loc(
+      reinterpret_cast<uword>(pair_location) | kPairLocationTag);
   return loc;
 }
 
-PairLocation* Location::AsPairLocation() const {
+template <class Register, class FpuRegister>
+TemplatePairLocation<TemplateLocation<Register, FpuRegister>>*
+TemplateLocation<Register, FpuRegister>::AsPairLocation() const {
   ASSERT(IsPairLocation());
-  return reinterpret_cast<PairLocation*>(value_ & ~kLocationTagMask);
+  return reinterpret_cast<
+      TemplatePairLocation<TemplateLocation<Register, FpuRegister>>*>(
+      value_ & ~kLocationTagMask);
 }
 
-Location Location::RegisterOrConstant(Value* value) {
+Location LocationRegisterOrConstant(Value* value) {
   ConstantInstr* constant = value->definition()->AsConstant();
   return ((constant != NULL) && Assembler::IsSafe(constant->value()))
              ? Location::Constant(constant)
              : Location::RequiresRegister();
 }
 
-Location Location::RegisterOrSmiConstant(Value* value) {
+Location LocationRegisterOrSmiConstant(Value* value) {
   ConstantInstr* constant = value->definition()->AsConstant();
   return ((constant != NULL) && Assembler::IsSafeSmi(constant->value()))
              ? Location::Constant(constant)
              : Location::RequiresRegister();
 }
 
-Location Location::WritableRegisterOrSmiConstant(Value* value) {
+Location LocationWritableRegisterOrSmiConstant(Value* value) {
   ConstantInstr* constant = value->definition()->AsConstant();
   return ((constant != NULL) && Assembler::IsSafeSmi(constant->value()))
              ? Location::Constant(constant)
              : Location::WritableRegister();
 }
 
-Location Location::FixedRegisterOrConstant(Value* value, Register reg) {
+Location LocationFixedRegisterOrConstant(Value* value, Register reg) {
   ConstantInstr* constant = value->definition()->AsConstant();
   return ((constant != NULL) && Assembler::IsSafe(constant->value()))
              ? Location::Constant(constant)
              : Location::RegisterLocation(reg);
 }
 
-Location Location::FixedRegisterOrSmiConstant(Value* value, Register reg) {
+Location LocationFixedRegisterOrSmiConstant(Value* value, Register reg) {
   ConstantInstr* constant = value->definition()->AsConstant();
   return ((constant != NULL) && Assembler::IsSafeSmi(constant->value()))
              ? Location::Constant(constant)
              : Location::RegisterLocation(reg);
 }
 
-Location Location::AnyOrConstant(Value* value) {
+Location LocationAnyOrConstant(Value* value) {
   ConstantInstr* constant = value->definition()->AsConstant();
   return ((constant != NULL) && Assembler::IsSafe(constant->value()))
              ? Location::Constant(constant)
@@ -128,27 +138,30 @@
 
 // DBC does not have an notion of 'address' in its instruction set.
 #if !defined(TARGET_ARCH_DBC)
-Address Location::ToStackSlotAddress() const {
-  return Address(base_reg(), ToStackSlotOffset());
+Address LocationToStackSlotAddress(Location loc) {
+  return Address(loc.base_reg(), loc.ToStackSlotOffset());
 }
 #endif
 
-intptr_t Location::ToStackSlotOffset() const {
+template <class Register, class FpuRegister>
+intptr_t TemplateLocation<Register, FpuRegister>::ToStackSlotOffset() const {
   return stack_index() * kWordSize;
 }
 
-const Object& Location::constant() const {
+template <class Register, class FpuRegister>
+const Object& TemplateLocation<Register, FpuRegister>::constant() const {
   return constant_instruction()->value();
 }
 
-const char* Location::Name() const {
+template <class Register, class FpuRegister>
+const char* TemplateLocation<Register, FpuRegister>::Name() const {
   switch (kind()) {
     case kInvalid:
       return "?";
     case kRegister:
-      return Assembler::RegisterName(reg());
+      return RegisterNames::RegisterName(reg());
     case kFpuRegister:
-      return Assembler::FpuRegisterName(fpu_reg());
+      return RegisterNames::FpuRegisterName(fpu_reg());
     case kStackSlot:
       return "S";
     case kDoubleStackSlot:
@@ -195,7 +208,9 @@
   return "?";
 }
 
-void Location::PrintTo(BufferFormatter* f) const {
+template <class Register, class FpuRegister>
+void TemplateLocation<Register, FpuRegister>::PrintTo(
+    BufferFormatter* f) const {
   if (!FLAG_support_il_printer) {
     return;
   }
@@ -216,14 +231,16 @@
   }
 }
 
-const char* Location::ToCString() const {
+template <class Register, class FpuRegister>
+const char* TemplateLocation<Register, FpuRegister>::ToCString() const {
   char buffer[1024];
   BufferFormatter bf(buffer, 1024);
   PrintTo(&bf);
   return Thread::Current()->zone()->MakeCopyOfString(buffer);
 }
 
-void Location::Print() const {
+template <class Register, class FpuRegister>
+void TemplateLocation<Register, FpuRegister>::Print() const {
   if (kind() == kStackSlot) {
     THR_Print("S%+" Pd "", stack_index());
   } else {
@@ -231,46 +248,77 @@
   }
 }
 
-Location Location::Copy() const {
+template <class Register, class FpuRegister>
+TemplateLocation<Register, FpuRegister>
+TemplateLocation<Register, FpuRegister>::Copy() const {
   if (IsPairLocation()) {
-    PairLocation* pair = AsPairLocation();
+    TemplatePairLocation<TemplateLocation<Register, FpuRegister>>* pair =
+        AsPairLocation();
     ASSERT(!pair->At(0).IsPairLocation());
     ASSERT(!pair->At(1).IsPairLocation());
-    return Location::Pair(pair->At(0).Copy(), pair->At(1).Copy());
+    return TemplateLocation::Pair(pair->At(0).Copy(), pair->At(1).Copy());
   } else {
     // Copy by value.
     return *this;
   }
 }
 
-Location Location::RemapForSlowPath(Definition* def,
-                                    intptr_t* cpu_reg_slots,
-                                    intptr_t* fpu_reg_slots) const {
-  if (IsRegister()) {
-    intptr_t index = cpu_reg_slots[reg()];
+Location LocationArgumentsDescriptorLocation() {
+#ifdef TARGET_ARCH_DBC
+  return Location(Location::kSpecialDbcRegister, Location::kArgsDescriptorReg);
+#else
+  return Location::RegisterLocation(ARGS_DESC_REG);
+#endif
+}
+
+Location LocationExceptionLocation() {
+#ifdef TARGET_ARCH_DBC
+  return Location(Location::kSpecialDbcRegister, Location::kExceptionReg);
+#else
+  return Location::RegisterLocation(kExceptionObjectReg);
+#endif
+}
+
+Location LocationStackTraceLocation() {
+#ifdef TARGET_ARCH_DBC
+  return Location(Location::kSpecialDbcRegister, Location::kStackTraceReg);
+#else
+  return Location::RegisterLocation(kStackTraceObjectReg);
+#endif
+}
+
+Location LocationRemapForSlowPath(Location loc,
+                                  Definition* def,
+                                  intptr_t* cpu_reg_slots,
+                                  intptr_t* fpu_reg_slots) {
+  if (loc.IsRegister()) {
+    intptr_t index = cpu_reg_slots[loc.reg()];
     ASSERT(index >= 0);
     return Location::StackSlot(
-        compiler::target::frame_layout.FrameSlotForVariableIndex(-index));
-  } else if (IsFpuRegister()) {
-    intptr_t index = fpu_reg_slots[fpu_reg()];
+        compiler::target::frame_layout.FrameSlotForVariableIndex(-index),
+        FPREG);
+  } else if (loc.IsFpuRegister()) {
+    intptr_t index = fpu_reg_slots[loc.fpu_reg()];
     ASSERT(index >= 0);
     switch (def->representation()) {
       case kUnboxedDouble:
         return Location::DoubleStackSlot(
-            compiler::target::frame_layout.FrameSlotForVariableIndex(-index));
+            compiler::target::frame_layout.FrameSlotForVariableIndex(-index),
+            FPREG);
 
       case kUnboxedFloat32x4:
       case kUnboxedInt32x4:
       case kUnboxedFloat64x2:
         return Location::QuadStackSlot(
-            compiler::target::frame_layout.FrameSlotForVariableIndex(-index));
+            compiler::target::frame_layout.FrameSlotForVariableIndex(-index),
+            FPREG);
 
       default:
         UNREACHABLE();
     }
-  } else if (IsPairLocation()) {
+  } else if (loc.IsPairLocation()) {
     ASSERT(def->representation() == kUnboxedInt64);
-    PairLocation* value_pair = AsPairLocation();
+    PairLocation* value_pair = loc.AsPairLocation();
     intptr_t index_lo;
     intptr_t index_hi;
 
@@ -290,14 +338,14 @@
       index_hi = value_pair->At(1).stack_index();
     }
 
-    return Location::Pair(Location::StackSlot(index_lo),
-                          Location::StackSlot(index_hi));
-  } else if (IsInvalid() && def->IsMaterializeObject()) {
+    return Location::Pair(Location::StackSlot(index_lo, FPREG),
+                          Location::StackSlot(index_hi, FPREG));
+  } else if (loc.IsInvalid() && def->IsMaterializeObject()) {
     def->AsMaterializeObject()->RemapRegisters(cpu_reg_slots, fpu_reg_slots);
-    return *this;
+    return loc;
   }
 
-  return *this;
+  return loc;
 }
 
 void LocationSummary::PrintTo(BufferFormatter* f) const {
@@ -358,6 +406,14 @@
 }
 #endif
 
+template class TemplateLocation<dart::Register, dart::FpuRegister>;
+template class TemplatePairLocation<Location>;
+
+#if !defined(HOST_ARCH_EQUALS_TARGET_ARCH)
+template class TemplateLocation<dart::host::Register, dart::host::FpuRegister>;
+template class TemplatePairLocation<HostLocation>;
+#endif  // !defined(HOST_ARCH_EQUALS_TARGET_ARCH)
+
 }  // namespace dart
 
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/backend/locations.h b/runtime/vm/compiler/backend/locations.h
index a14d8a0..c8191b9 100644
--- a/runtime/vm/compiler/backend/locations.h
+++ b/runtime/vm/compiler/backend/locations.h
@@ -9,15 +9,18 @@
 #include "vm/bitfield.h"
 #include "vm/bitmap.h"
 #include "vm/compiler/assembler/assembler.h"
+#include "vm/constants.h"
 
 namespace dart {
 
 class BufferFormatter;
 class ConstantInstr;
 class Definition;
-class PairLocation;
 class Value;
 
+template <class Location>
+class TemplatePairLocation;
+
 enum Representation {
   kNoRepresentation,
   kTagged,
@@ -62,7 +65,8 @@
 // are bitwise unequal then these two locations are guaranteed to be disjoint.
 // Properties like representation belong to the value that is stored in
 // the location not to the location itself.
-class Location : public ValueObject {
+template <class Register, class FpuRegister>
+class TemplateLocation : public ValueObject {
  private:
   enum {
     // Number of bits required to encode Kind value.
@@ -128,7 +132,7 @@
 #endif
   };
 
-  Location() : value_(kInvalidLocation) {
+  TemplateLocation() : value_(kInvalidLocation) {
     // Verify that non-tagged location kinds do not interfere with location tags
     // (kConstantTag and kPairLocationTag).
     COMPILE_ASSERT((kInvalid & kLocationTagMask) != kConstantTag);
@@ -166,9 +170,10 @@
     ASSERT(IsInvalid());
   }
 
-  Location(const Location& other) : ValueObject(), value_(other.value_) {}
+  TemplateLocation(const TemplateLocation& other)
+      : ValueObject(), value_(other.value_) {}
 
-  Location& operator=(const Location& other) {
+  TemplateLocation& operator=(const TemplateLocation& other) {
     value_ = other.value_;
     return *this;
   }
@@ -180,8 +185,8 @@
     return (value_ & kLocationTagMask) == kConstantTag;
   }
 
-  static Location Constant(const ConstantInstr* obj) {
-    Location loc(reinterpret_cast<uword>(obj) | kConstantTag);
+  static TemplateLocation Constant(const ConstantInstr* obj) {
+    TemplateLocation loc(reinterpret_cast<uword>(obj) | kConstantTag);
     ASSERT(obj == loc.constant_instruction());
     return loc;
   }
@@ -197,9 +202,10 @@
     return (value_ & kLocationTagMask) == kPairLocationTag;
   }
 
-  static Location Pair(Location first, Location second);
+  static TemplateLocation Pair(TemplateLocation first, TemplateLocation second);
 
-  PairLocation* AsPairLocation() const;
+  TemplatePairLocation<TemplateLocation<Register, FpuRegister>>*
+  AsPairLocation() const;
 
   // Unallocated locations.
   enum Policy {
@@ -215,37 +221,37 @@
 
   bool IsRegisterBeneficial() { return !Equals(Any()); }
 
-  static Location UnallocatedLocation(Policy policy) {
-    return Location(kUnallocated, PolicyField::encode(policy));
+  static TemplateLocation UnallocatedLocation(Policy policy) {
+    return TemplateLocation(kUnallocated, PolicyField::encode(policy));
   }
 
   // Any free register is suitable to replace this unallocated location.
-  static Location Any() { return UnallocatedLocation(kAny); }
+  static TemplateLocation Any() { return UnallocatedLocation(kAny); }
 
-  static Location PrefersRegister() {
+  static TemplateLocation PrefersRegister() {
     return UnallocatedLocation(kPrefersRegister);
   }
 
-  static Location RequiresRegister() {
+  static TemplateLocation RequiresRegister() {
     return UnallocatedLocation(kRequiresRegister);
   }
 
-  static Location RequiresFpuRegister() {
+  static TemplateLocation RequiresFpuRegister() {
     return UnallocatedLocation(kRequiresFpuRegister);
   }
 
-  static Location WritableRegister() {
+  static TemplateLocation WritableRegister() {
     return UnallocatedLocation(kWritableRegister);
   }
 
   // The location of the first input to the instruction will be
   // used to replace this unallocated location.
-  static Location SameAsFirstInput() {
+  static TemplateLocation SameAsFirstInput() {
     return UnallocatedLocation(kSameAsFirstInput);
   }
 
   // Empty location. Used if there the location should be ignored.
-  static Location NoLocation() { return Location(); }
+  static TemplateLocation NoLocation() { return TemplateLocation(); }
 
   Policy policy() const {
     ASSERT(IsUnallocated());
@@ -253,8 +259,8 @@
   }
 
   // Register locations.
-  static Location RegisterLocation(Register reg) {
-    return Location(kRegister, reg);
+  static TemplateLocation RegisterLocation(Register reg) {
+    return TemplateLocation(kRegister, reg);
   }
 
   bool IsRegister() const { return kind() == kRegister; }
@@ -265,36 +271,12 @@
   }
 
   // FpuRegister locations.
-  static Location FpuRegisterLocation(FpuRegister reg) {
-    return Location(kFpuRegister, reg);
+  static TemplateLocation FpuRegisterLocation(FpuRegister reg) {
+    return TemplateLocation(kFpuRegister, reg);
   }
 
   bool IsFpuRegister() const { return kind() == kFpuRegister; }
 
-  static Location ArgumentsDescriptorLocation() {
-#ifdef TARGET_ARCH_DBC
-    return Location(kSpecialDbcRegister, kArgsDescriptorReg);
-#else
-    return Location::RegisterLocation(ARGS_DESC_REG);
-#endif
-  }
-
-  static Location ExceptionLocation() {
-#ifdef TARGET_ARCH_DBC
-    return Location(kSpecialDbcRegister, kExceptionReg);
-#else
-    return Location::RegisterLocation(kExceptionObjectReg);
-#endif
-  }
-
-  static Location StackTraceLocation() {
-#ifdef TARGET_ARCH_DBC
-    return Location(kSpecialDbcRegister, kStackTraceReg);
-#else
-    return Location::RegisterLocation(kStackTraceObjectReg);
-#endif
-  }
-
 #ifdef TARGET_ARCH_DBC
   bool IsArgsDescRegister() const {
     return IsSpecialDbcRegister(kArgsDescriptorReg);
@@ -320,7 +302,7 @@
     return (kind == kRegister) || (kind == kFpuRegister);
   }
 
-  static Location MachineRegisterLocation(Kind kind, intptr_t reg) {
+  static TemplateLocation MachineRegisterLocation(Kind kind, intptr_t reg) {
     if (kind == kRegister) {
       return RegisterLocation(static_cast<Register>(reg));
     } else {
@@ -342,10 +324,10 @@
     return static_cast<uword>(kStackIndexBias + stack_index);
   }
 
-  static Location StackSlot(intptr_t stack_index, Register base = FPREG) {
+  static TemplateLocation StackSlot(intptr_t stack_index, Register base) {
     uword payload = StackSlotBaseField::encode(base) |
                     StackIndexField::encode(EncodeStackIndex(stack_index));
-    Location loc(kStackSlot, payload);
+    TemplateLocation loc(kStackSlot, payload);
     // Ensure that sign is preserved.
     ASSERT(loc.stack_index() == stack_index);
     return loc;
@@ -353,10 +335,10 @@
 
   bool IsStackSlot() const { return kind() == kStackSlot; }
 
-  static Location DoubleStackSlot(intptr_t stack_index, Register base = FPREG) {
+  static TemplateLocation DoubleStackSlot(intptr_t stack_index, Register base) {
     uword payload = StackSlotBaseField::encode(base) |
                     StackIndexField::encode(EncodeStackIndex(stack_index));
-    Location loc(kDoubleStackSlot, payload);
+    TemplateLocation loc(kDoubleStackSlot, payload);
     // Ensure that sign is preserved.
     ASSERT(loc.stack_index() == stack_index);
     return loc;
@@ -364,10 +346,10 @@
 
   bool IsDoubleStackSlot() const { return kind() == kDoubleStackSlot; }
 
-  static Location QuadStackSlot(intptr_t stack_index) {
-    uword payload = StackSlotBaseField::encode(FPREG) |
+  static TemplateLocation QuadStackSlot(intptr_t stack_index, Register base) {
+    uword payload = StackSlotBaseField::encode(base) |
                     StackIndexField::encode(EncodeStackIndex(stack_index));
-    Location loc(kQuadStackSlot, payload);
+    TemplateLocation loc(kQuadStackSlot, payload);
     // Ensure that sign is preserved.
     ASSERT(loc.stack_index() == stack_index);
     return loc;
@@ -390,45 +372,27 @@
     return IsStackSlot() || IsDoubleStackSlot() || IsQuadStackSlot();
   }
 
-// DBC does not have an notion of 'address' in its instruction set.
-#if !defined(TARGET_ARCH_DBC)
-  // Return a memory operand for stack slot locations.
-  Address ToStackSlotAddress() const;
-#endif
-
   // Returns the offset from the frame pointer for stack slot locations.
   intptr_t ToStackSlotOffset() const;
 
-  // Constants.
-  static Location RegisterOrConstant(Value* value);
-  static Location RegisterOrSmiConstant(Value* value);
-  static Location WritableRegisterOrSmiConstant(Value* value);
-  static Location FixedRegisterOrConstant(Value* value, Register reg);
-  static Location FixedRegisterOrSmiConstant(Value* value, Register reg);
-  static Location AnyOrConstant(Value* value);
-
   const char* Name() const;
   void PrintTo(BufferFormatter* f) const;
   void Print() const;
   const char* ToCString() const;
 
   // Compare two locations.
-  bool Equals(Location other) const { return value_ == other.value_; }
+  bool Equals(TemplateLocation other) const { return value_ == other.value_; }
 
   // If current location is constant might return something that
   // is not equal to any Kind.
   Kind kind() const { return KindField::decode(value_); }
 
-  Location Copy() const;
-
-  Location RemapForSlowPath(Definition* def,
-                            intptr_t* cpu_reg_slots,
-                            intptr_t* fpu_reg_slots) const;
+  TemplateLocation Copy() const;
 
  private:
-  explicit Location(uword value) : value_(value) {}
+  explicit TemplateLocation(uword value) : value_(value) {}
 
-  Location(Kind kind, uword payload)
+  TemplateLocation(Kind kind, uword payload)
       : value_(KindField::encode(kind) | PayloadField::encode(payload)) {}
 
   uword payload() const { return PayloadField::decode(value_); }
@@ -462,11 +426,48 @@
   // a constant locations. Values of enumeration Kind are selected in such a
   // way that none of them can be interpreted as a kConstant tag.
   uword value_;
+
+  // The following functions are only defined for Location, not for
+  // HostLocation, but they do need access to private fields or constructors.
+  friend TemplateLocation<dart::Register, dart::FpuRegister>
+  LocationArgumentsDescriptorLocation();
+  friend TemplateLocation<dart::Register, dart::FpuRegister>
+  LocationExceptionLocation();
+  friend TemplateLocation<dart::Register, dart::FpuRegister>
+  LocationStackTraceLocation();
 };
 
-class PairLocation : public ZoneAllocated {
+using Location = TemplateLocation<dart::Register, dart::FpuRegister>;
+using HostLocation =
+    TemplateLocation<dart::host::Register, dart::host::FpuRegister>;
+
+// The following functions are only defined for Location, not for HostLocation.
+Location LocationArgumentsDescriptorLocation();
+Location LocationExceptionLocation();
+Location LocationStackTraceLocation();
+// Constants.
+Location LocationRegisterOrConstant(Value* value);
+Location LocationRegisterOrSmiConstant(Value* value);
+Location LocationWritableRegisterOrSmiConstant(Value* value);
+Location LocationFixedRegisterOrConstant(Value* value, Register reg);
+Location LocationFixedRegisterOrSmiConstant(Value* value, Register reg);
+Location LocationAnyOrConstant(Value* value);
+
+Location LocationRemapForSlowPath(Location loc,
+                                  Definition* def,
+                                  intptr_t* cpu_reg_slots,
+                                  intptr_t* fpu_reg_slots);
+
+// DBC does not have an notion of 'address' in its instruction set.
+#if !defined(TARGET_ARCH_DBC)
+// Return a memory operand for stack slot locations.
+Address LocationToStackSlotAddress(Location loc);
+#endif
+
+template <class Location>
+class TemplatePairLocation : public ZoneAllocated {
  public:
-  PairLocation() {
+  TemplatePairLocation() {
     for (intptr_t i = 0; i < kPairLength; i++) {
       ASSERT(locations_[i].IsInvalid());
     }
@@ -497,6 +498,9 @@
   Location locations_[kPairLength];
 };
 
+using PairLocation = TemplatePairLocation<Location>;
+using HostPairLocation = TemplatePairLocation<HostLocation>;
+
 template <typename T>
 class SmallSet {
  public:
diff --git a/runtime/vm/constants.h b/runtime/vm/constants.h
index 90137d3..7fe6c15 100644
--- a/runtime/vm/constants.h
+++ b/runtime/vm/constants.h
@@ -63,6 +63,28 @@
 
 }  // namespace host
 
+class RegisterNames {
+ public:
+  static const char* RegisterName(Register reg) {
+    ASSERT((0 <= reg) && (reg < kNumberOfCpuRegisters));
+    return cpu_reg_names[reg];
+  }
+  static const char* FpuRegisterName(FpuRegister reg) {
+    ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters));
+    return fpu_reg_names[reg];
+  }
+#if !defined(HOST_ARCH_EQUALS_TARGET_ARCH)
+  static const char* RegisterName(host::Register reg) {
+    ASSERT((0 <= reg) && (reg < host::kNumberOfCpuRegisters));
+    return host::cpu_reg_names[reg];
+  }
+  static const char* FpuRegisterName(host::FpuRegister reg) {
+    ASSERT((0 <= reg) && (reg < host::kNumberOfFpuRegisters));
+    return host::fpu_reg_names[reg];
+  }
+#endif  // !defined(HOST_ARCH_EQUALS_TARGET_ARCH)
+};
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_CONSTANTS_H_
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index 4e18c28..afbcb92 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -265,6 +265,18 @@
 const int kNumberOfFpuRegisters = kNumberOfQRegisters;
 const FpuRegister kNoFpuRegister = kNoQRegister;
 
+static const char* cpu_reg_names[kNumberOfCpuRegisters] = {
+    "r0", "r1",  "r2", "r3", "r4", "r5", "r6", "r7",
+    "r8", "ctx", "pp", "fp", "ip", "sp", "lr", "pc",
+};
+
+static const char* fpu_reg_names[kNumberOfFpuRegisters] = {
+    "q0", "q1", "q2",  "q3",  "q4",  "q5",  "q6",  "q7",
+#if defined(VFPv3_D32)
+    "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15",
+#endif
+};
+
 // Register aliases.
 const Register TMP = IP;            // Used as scratch register by assembler.
 const Register TMP2 = kNoRegister;  // There is no second assembler temporary.
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index 62df515..9f3355a 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -108,6 +108,18 @@
 const int kNumberOfFpuRegisters = kNumberOfVRegisters;
 const FpuRegister kNoFpuRegister = kNoVRegister;
 
+static const char* cpu_reg_names[kNumberOfCpuRegisters] = {
+    "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",  "r8",  "r9",  "r10",
+    "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21",
+    "r22", "r23", "r24", "ip0", "ip1", "pp",  "ctx", "fp",  "lr",  "r31",
+};
+
+static const char* fpu_reg_names[kNumberOfFpuRegisters] = {
+    "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",  "v7",  "v8",  "v9",  "v10",
+    "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21",
+    "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
+};
+
 // Register aliases.
 const Register TMP = R16;  // Used as scratch register by assembler.
 const Register TMP2 = R17;
diff --git a/runtime/vm/constants_dbc.h b/runtime/vm/constants_dbc.h
index 0f5495a..2eb202d 100644
--- a/runtime/vm/constants_dbc.h
+++ b/runtime/vm/constants_dbc.h
@@ -1111,6 +1111,21 @@
 const FpuRegister FpuTMP = kFakeFpuRegister;
 const intptr_t kNumberOfFpuRegisters = 1;
 
+static const char* cpu_reg_names[kNumberOfCpuRegisters] = {
+    "R0",  "R1",  "R2",  "R3",  "R4",  "R5",  "R6",  "R7",  "R8",  "R9",  "R10",
+    "R11", "R12", "R13", "R14", "R15", "R16", "R17", "R18", "R19", "R20", "R21",
+    "R22", "R23", "R24", "R25", "R26", "R27", "R28", "R29", "R30", "R31",
+#if defined(ARCH_IS_64_BIT)
+    "R32", "R33", "R34", "R35", "R36", "R37", "R38", "R39", "R40", "R41", "R42",
+    "R43", "R44", "R45", "R46", "R47", "R48", "R49", "R50", "R51", "R52", "R53",
+    "R54", "R55", "R56", "R57", "R58", "R59", "R60", "R61", "R62", "R63",
+#endif
+};
+
+static const char* fpu_reg_names[kNumberOfFpuRegisters] = {
+    "F0",
+};
+
 // After a comparison, the condition NEXT_IS_TRUE means the following
 // instruction is executed if the comparison is true and skipped over overwise.
 // Condition NEXT_IS_FALSE means the following instruction is executed if the
diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h
index 269888d..ce697b9 100644
--- a/runtime/vm/constants_ia32.h
+++ b/runtime/vm/constants_ia32.h
@@ -57,6 +57,12 @@
 const int kNumberOfFpuRegisters = kNumberOfXmmRegisters;
 const FpuRegister kNoFpuRegister = kNoXmmRegister;
 
+static const char* cpu_reg_names[kNumberOfCpuRegisters] = {
+    "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"};
+
+static const char* fpu_reg_names[kNumberOfXmmRegisters] = {
+    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"};
+
 // Register aliases.
 const Register TMP = kNoRegister;   // No scratch register used by assembler.
 const Register TMP2 = kNoRegister;  // No second assembler scratch register.
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index 60e9568..cc79dd3 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -94,6 +94,14 @@
 const int kNumberOfFpuRegisters = kNumberOfXmmRegisters;
 const FpuRegister kNoFpuRegister = kNoXmmRegister;
 
+static const char* cpu_reg_names[kNumberOfCpuRegisters] = {
+    "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
+    "r8",  "r9",  "r10", "r11", "r12", "r13", "thr", "pp"};
+
+static const char* fpu_reg_names[kNumberOfXmmRegisters] = {
+    "xmm0", "xmm1", "xmm2",  "xmm3",  "xmm4",  "xmm5",  "xmm6",  "xmm7",
+    "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"};
+
 enum RexBits {
   REX_NONE = 0,
   REX_B = 1 << 0,
diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h
index 9270768..3e5d46c 100644
--- a/runtime/vm/deopt_instructions.h
+++ b/runtime/vm/deopt_instructions.h
@@ -19,7 +19,6 @@
 
 namespace dart {
 
-class Location;
 class Value;
 class MaterializeObjectInstr;
 class StackFrame;
@@ -462,10 +461,12 @@
 
   RegisterType reg() const { return static_cast<RegisterType>(raw_index()); }
 
-  static const char* Name(Register reg) { return Assembler::RegisterName(reg); }
+  static const char* Name(Register reg) {
+    return RegisterNames::RegisterName(reg);
+  }
 
   static const char* Name(FpuRegister fpu_reg) {
-    return Assembler::FpuRegisterName(fpu_reg);
+    return RegisterNames::FpuRegisterName(fpu_reg);
   }
 
   const intptr_t source_index_;
@@ -601,7 +602,6 @@
   static const intptr_t kEntrySize = 3;
 };
 
-
 // Holds deopt information at one deoptimization point. The information consists
 // of two parts:
 //  - first a prefix consisting of kMaterializeObject instructions describing
@@ -638,7 +638,6 @@
                                   const Array& deopt_table,
                                   const TypedData& packed);
 
-
  private:
   static void UnpackInto(const Array& table,
                          const TypedData& packed,