| 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.
|
|
|