Index: runtime/vm/flow_graph_compiler_x64.cc |
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc |
index 9b447958f0c18caecafd04b64f0d05a074cd92ae..2a584751ecf1f3e41f03cbbbe80f9705c35535b0 100644 |
--- a/runtime/vm/flow_graph_compiler_x64.cc |
+++ b/runtime/vm/flow_graph_compiler_x64.cc |
@@ -1112,18 +1112,43 @@ void FlowGraphCompiler::LoadDoubleOrSmiToXmm(XmmRegister result, |
#define __ compiler_->assembler()-> |
+static Address ToAddress(Location loc) { |
+ ASSERT(loc.IsSpillSlot()); |
+ const intptr_t offset = |
+ (ParsedFunction::kFirstLocalSlotIndex - loc.spill_index()) * kWordSize; |
+ return Address(RBP, offset); |
+} |
+ |
+ |
void ParallelMoveResolver::EmitMove(int index) { |
MoveOperands* move = moves_[index]; |
const Location source = move->src(); |
const Location destination = move->dest(); |
- ASSERT(destination.IsRegister()); |
if (source.IsRegister()) { |
- __ movq(destination.reg(), source.reg()); |
+ if (destination.IsRegister()) { |
+ __ movq(destination.reg(), source.reg()); |
+ } else { |
+ ASSERT(destination.IsSpillSlot()); |
+ __ movq(ToAddress(destination), source.reg()); |
+ } |
+ } else if (source.IsSpillSlot()) { |
+ if (destination.IsRegister()) { |
+ __ movq(destination.reg(), ToAddress(source)); |
+ } else { |
+ ASSERT(destination.IsSpillSlot()); |
+ __ MoveMemory(ToAddress(destination), ToAddress(source)); |
+ } |
} else { |
ASSERT(source.IsConstant()); |
- __ LoadObject(destination.reg(), source.constant()); |
+ if (destination.IsRegister()) { |
+ __ LoadObject(destination.reg(), source.constant()); |
+ } else { |
+ ASSERT(destination.IsSpillSlot()); |
+ __ StoreObject(ToAddress(destination), source.constant()); |
+ } |
} |
+ |
move->Eliminate(); |
} |
@@ -1133,8 +1158,17 @@ void ParallelMoveResolver::EmitSwap(int index) { |
const Location source = move->src(); |
const Location destination = move->dest(); |
- ASSERT(source.IsRegister() && destination.IsRegister()); |
- __ xchgq(destination.reg(), source.reg()); |
+ if (source.IsRegister() && destination.IsRegister()) { |
+ __ xchgq(destination.reg(), source.reg()); |
+ } else if (source.IsRegister() && destination.IsSpillSlot()) { |
+ __ Exchange(source.reg(), ToAddress(destination)); |
+ } else if (source.IsSpillSlot() && destination.IsRegister()) { |
+ __ Exchange(destination.reg(), ToAddress(source)); |
+ } else if (source.IsSpillSlot() && destination.IsSpillSlot()) { |
+ __ Exchange(ToAddress(destination), ToAddress(source)); |
+ } else { |
+ UNREACHABLE(); |
+ } |
// The swap of source and destination has executed a move from source to |
// destination. |