11e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Copyright 2011 the V8 project authors. All rights reserved. 21e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Redistribution and use in source and binary forms, with or without 31e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// modification, are permitted provided that the following conditions are 41e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// met: 51e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// 61e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// * Redistributions of source code must retain the above copyright 71e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// notice, this list of conditions and the following disclaimer. 81e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// * Redistributions in binary form must reproduce the above 91e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// copyright notice, this list of conditions and the following 101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// disclaimer in the documentation and/or other materials provided 111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// with the distribution. 121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// * Neither the name of Google Inc. nor the names of its 131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// contributors may be used to endorse or promote products derived 141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// from this software without specific prior written permission. 151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// 161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#include "v8.h" 291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#if defined(V8_TARGET_ARCH_X64) 311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#include "x64/lithium-gap-resolver-x64.h" 331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#include "x64/lithium-codegen-x64.h" 341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blocknamespace v8 { 361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blocknamespace internal { 371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 381e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockLGapResolver::LGapResolver(LCodeGen* owner) 391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block : cgen_(owner), moves_(32) {} 401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LGapResolver::Resolve(LParallelMove* parallel_move) { 431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(moves_.is_empty()); 441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Build up a worklist of moves. 451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block BuildInitialMoveList(parallel_move); 461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < moves_.length(); ++i) { 481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LMoveOperands move = moves_[i]; 491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Skip constants to perform them last. They don't block other moves 501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // and skipping such moves with register destinations keeps those 511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // registers free for the whole algorithm. 521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (!move.IsEliminated() && !move.source()->IsConstantOperand()) { 531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PerformMove(i); 541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Perform the moves with constant sources. 581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < moves_.length(); ++i) { 591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (!moves_[i].IsEliminated()) { 601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(moves_[i].source()->IsConstantOperand()); 611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitMove(i); 621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block moves_.Rewind(0); 661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) { 701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Perform a linear sweep of the moves to add them to the initial list of 711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // moves to perform, ignoring any move that is redundant (the source is 721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the same as the destination, the destination is ignored and 731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // unallocated, or the move was already eliminated). 741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block const ZoneList<LMoveOperands>* moves = parallel_move->move_operands(); 751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < moves->length(); ++i) { 761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LMoveOperands move = moves->at(i); 771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (!move.IsRedundant()) moves_.Add(move); 781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Verify(); 801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LGapResolver::PerformMove(int index) { 841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Each call to this function performs a move and deletes it from the move 851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // graph. We first recursively perform any move blocking this one. We 861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // mark a move as "pending" on entry to PerformMove in order to detect 871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // cycles in the move graph. We use operand swaps to resolve cycles, 881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // which means that a call to PerformMove could change any source operand 891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // in the move graph. 901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!moves_[index].IsPending()); 921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!moves_[index].IsRedundant()); 931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Clear this move's destination to indicate a pending move. The actual 951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // destination is saved in a stack-allocated local. Recursion may allow 961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // multiple moves to be pending. 971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(moves_[index].source() != NULL); // Or else it will look eliminated. 981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* destination = moves_[index].destination(); 991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block moves_[index].set_destination(NULL); 1001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Perform a depth-first traversal of the move graph to resolve 1021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // dependencies. Any unperformed, unpending move with a source the same 1031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // as this one's destination blocks this one so recursively perform all 1041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // such moves. 1051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < moves_.length(); ++i) { 1061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LMoveOperands other_move = moves_[i]; 1071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (other_move.Blocks(destination) && !other_move.IsPending()) { 1081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Though PerformMove can change any source operand in the move graph, 1091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // this call cannot create a blocking move via a swap (this loop does 1101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // not miss any). Assume there is a non-blocking move with source A 1111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // and this move is blocked on source B and there is a swap of A and 1121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // B. Then A and B must be involved in the same cycle (or they would 1131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // not be swapped). Since this move's destination is B and there is 1141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // only a single incoming edge to an operand, this move must also be 1151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // involved in the same cycle. In that case, the blocking move will 1161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // be created but will be "pending" when we return from PerformMove. 1171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PerformMove(i); 1181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // We are about to resolve this move and don't need it marked as 1221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // pending, so restore its destination. 1231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block moves_[index].set_destination(destination); 1241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // This move's source may have changed due to swaps to resolve cycles and 1261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // so it may now be the last move in the cycle. If so remove it. 1271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (moves_[index].source()->Equals(destination)) { 1281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block moves_[index].Eliminate(); 1291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return; 1301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The move may be blocked on a (at most one) pending move, in which case 1331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // we have a cycle. Search for such a blocking move and perform a swap to 1341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // resolve it. 1351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < moves_.length(); ++i) { 1361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LMoveOperands other_move = moves_[i]; 1371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (other_move.Blocks(destination)) { 1381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(other_move.IsPending()); 1391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitSwap(index); 1401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return; 1411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // This move is not blocked. 1451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block EmitMove(index); 1461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 1471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LGapResolver::Verify() { 1501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef ENABLE_SLOW_ASSERTS 1511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // No operand should be the destination for more than one move. 1521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < moves_.length(); ++i) { 1531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* destination = moves_[i].destination(); 1541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int j = i + 1; j < moves_.length(); ++j) { 1551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block SLOW_ASSERT(!destination->Equals(moves_[j].destination())); 1561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 1591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 1601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#define __ ACCESS_MASM(cgen_->masm()) 1631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LGapResolver::EmitMove(int index) { 1661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* source = moves_[index].source(); 1671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* destination = moves_[index].destination(); 1681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Dispatch on the source and destination operand kinds. Not all 1701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // combinations are possible. 1711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (source->IsRegister()) { 1721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register src = cgen_->ToRegister(source); 1731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (destination->IsRegister()) { 1741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register dst = cgen_->ToRegister(destination); 1751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(dst, src); 1761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 1771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(destination->IsStackSlot()); 1781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Operand dst = cgen_->ToOperand(destination); 1791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(dst, src); 1801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (source->IsStackSlot()) { 1831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Operand src = cgen_->ToOperand(source); 1841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (destination->IsRegister()) { 1851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register dst = cgen_->ToRegister(destination); 1861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(dst, src); 1871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 1881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(destination->IsStackSlot()); 1891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Operand dst = cgen_->ToOperand(destination); 1901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(kScratchRegister, src); 1911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(dst, kScratchRegister); 1921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 1931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (source->IsConstantOperand()) { 1951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LConstantOperand* constant_source = LConstantOperand::cast(source); 1961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (destination->IsRegister()) { 1971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register dst = cgen_->ToRegister(destination); 1981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (cgen_->IsInteger32Constant(constant_source)) { 1991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movl(dst, Immediate(cgen_->ToInteger32(constant_source))); 2001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadObject(dst, cgen_->ToHandle(constant_source)); 2021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 2031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 2041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(destination->IsStackSlot()); 2051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Operand dst = cgen_->ToOperand(destination); 2061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (cgen_->IsInteger32Constant(constant_source)) { 2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Zero top 32 bits of a 64 bit spill slot that holds a 32 bit untagged 2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // value. 2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(dst, Immediate(cgen_->ToInteger32(constant_source))); 2101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadObject(kScratchRegister, cgen_->ToHandle(constant_source)); 2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(dst, kScratchRegister); 2131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 2141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 2151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (source->IsDoubleRegister()) { 2171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block XMMRegister src = cgen_->ToDoubleRegister(source); 2181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (destination->IsDoubleRegister()) { 219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movaps(cgen_->ToDoubleRegister(destination), src); 2201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 2211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(destination->IsDoubleStackSlot()); 2221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(cgen_->ToOperand(destination), src); 2231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 2241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (source->IsDoubleStackSlot()) { 2251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Operand src = cgen_->ToOperand(source); 2261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (destination->IsDoubleRegister()) { 2271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(cgen_->ToDoubleRegister(destination), src); 2281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 2291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(destination->IsDoubleStackSlot()); 2301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(xmm0, src); 2311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(cgen_->ToOperand(destination), xmm0); 2321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 2331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 2341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 2351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 2361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block moves_[index].Eliminate(); 2381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 2391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid LGapResolver::EmitSwap(int index) { 2421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* source = moves_[index].source(); 2431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* destination = moves_[index].destination(); 2441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Dispatch on the source and destination operand kinds. Not all 2461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // combinations are possible. 2471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (source->IsRegister() && destination->IsRegister()) { 2481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Swap two general-purpose registers. 2491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register src = cgen_->ToRegister(source); 2501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register dst = cgen_->ToRegister(destination); 2511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ xchg(dst, src); 2521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((source->IsRegister() && destination->IsStackSlot()) || 2541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (source->IsStackSlot() && destination->IsRegister())) { 2551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Swap a general-purpose register and a stack slot. 2561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register reg = 2571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block cgen_->ToRegister(source->IsRegister() ? source : destination); 2581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Operand mem = 2591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block cgen_->ToOperand(source->IsRegister() ? destination : source); 2601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(kScratchRegister, mem); 2611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(mem, reg); 2621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(reg, kScratchRegister); 2631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if ((source->IsStackSlot() && destination->IsStackSlot()) || 2651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (source->IsDoubleStackSlot() && destination->IsDoubleStackSlot())) { 2661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Swap two stack slots or two double stack slots. 2671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Operand src = cgen_->ToOperand(source); 2681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Operand dst = cgen_->ToOperand(destination); 2691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(xmm0, src); 2701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(kScratchRegister, dst); 2711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(dst, xmm0); 2721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(src, kScratchRegister); 2731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) { 2751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Swap two double registers. 2761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block XMMRegister source_reg = cgen_->ToDoubleRegister(source); 2771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block XMMRegister destination_reg = cgen_->ToDoubleRegister(destination); 278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movaps(xmm0, source_reg); 279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movaps(source_reg, destination_reg); 280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movaps(destination_reg, xmm0); 2811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (source->IsDoubleRegister() || destination->IsDoubleRegister()) { 2831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Swap a double register and a double stack slot. 2841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT((source->IsDoubleRegister() && destination->IsDoubleStackSlot()) || 2851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (source->IsDoubleStackSlot() && destination->IsDoubleRegister())); 2861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block XMMRegister reg = cgen_->ToDoubleRegister(source->IsDoubleRegister() 2871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ? source 2881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block : destination); 2891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LOperand* other = source->IsDoubleRegister() ? destination : source; 2901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(other->IsDoubleStackSlot()); 2911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Operand other_operand = cgen_->ToOperand(other); 2921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(xmm0, other_operand); 2931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(other_operand, reg); 2941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(reg, xmm0); 2951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 2971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // No other combinations are possible. 2981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 2991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The swap of source and destination has executed a move from source to 3021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // destination. 3031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block moves_[index].Eliminate(); 3041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Any unperformed (including pending) move with a source of either 3061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // this move's source or destination needs to have their source 3071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // changed to reflect the state of affairs after the swap. 3081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < moves_.length(); ++i) { 3091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block LMoveOperands other_move = moves_[i]; 3101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (other_move.Blocks(source)) { 3111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block moves_[i].set_source(destination); 3121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (other_move.Blocks(destination)) { 3131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block moves_[i].set_source(source); 3141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 3171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#undef __ 3191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} } // namespace v8::internal 3211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif // V8_TARGET_ARCH_X64 323