lithium-gap-resolver-arm.cc revision 3ef787dbeca8a5fb1086949cda830dccee07bfbd
1692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Redistribution and use in source and binary forms, with or without 3e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// modification, are permitted provided that the following conditions are 4e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// met: 5e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// 6e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// * Redistributions of source code must retain the above copyright 7e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// notice, this list of conditions and the following disclaimer. 8e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// * Redistributions in binary form must reproduce the above 9e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// copyright notice, this list of conditions and the following 10e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// disclaimer in the documentation and/or other materials provided 11e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// with the distribution. 12e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// * Neither the name of Google Inc. nor the names of its 13e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// contributors may be used to endorse or promote products derived 14e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// from this software without specific prior written permission. 15e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// 16e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "v8.h" 2944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 30e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include "arm/lithium-gap-resolver-arm.h" 31e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include "arm/lithium-codegen-arm.h" 32e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 33e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochnamespace v8 { 34e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochnamespace internal { 35e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 36e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstatic const Register kSavedValueRegister = { 9 }; 37e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 38e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochLGapResolver::LGapResolver(LCodeGen* owner) 39e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch : cgen_(owner), moves_(32), root_index_(0), in_cycle_(false), 40e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch saved_destination_(NULL) { } 41e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 42e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 43e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::Resolve(LParallelMove* parallel_move) { 44e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(moves_.is_empty()); 45e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Build up a worklist of moves. 46e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch BuildInitialMoveList(parallel_move); 47e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 48e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < moves_.length(); ++i) { 49e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LMoveOperands move = moves_[i]; 50e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Skip constants to perform them last. They don't block other moves 51e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // and skipping such moves with register destinations keeps those 52e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // registers free for the whole algorithm. 53e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!move.IsEliminated() && !move.source()->IsConstantOperand()) { 54e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch root_index_ = i; // Any cycle is found when by reaching this move again. 55e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PerformMove(i); 56e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (in_cycle_) { 57e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch RestoreValue(); 58e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 59e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 60e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 61e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 62e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Perform the moves with constant sources. 63e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < moves_.length(); ++i) { 64e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!moves_[i].IsEliminated()) { 65e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(moves_[i].source()->IsConstantOperand()); 66e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch EmitMove(i); 67e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 68e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 69e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 70e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch moves_.Rewind(0); 71e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 72e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 73e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 74e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) { 75e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Perform a linear sweep of the moves to add them to the initial list of 76e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // moves to perform, ignoring any move that is redundant (the source is 77e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the same as the destination, the destination is ignored and 78e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // unallocated, or the move was already eliminated). 79e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const ZoneList<LMoveOperands>* moves = parallel_move->move_operands(); 80e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < moves->length(); ++i) { 81e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LMoveOperands move = moves->at(i); 82e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!move.IsRedundant()) moves_.Add(move); 83e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 84e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Verify(); 85e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 86e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 87e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 88e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::PerformMove(int index) { 89e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Each call to this function performs a move and deletes it from the move 90e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // graph. We first recursively perform any move blocking this one. We 91e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // mark a move as "pending" on entry to PerformMove in order to detect 92e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // cycles in the move graph. 93e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 94e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // We can only find a cycle, when doing a depth-first traversal of moves, 95e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // be encountering the starting move again. So by spilling the source of 96e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the starting move, we break the cycle. All moves are then unblocked, 97e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // and the starting move is completed by writing the spilled value to 98e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // its destination. All other moves from the spilled source have been 99e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // completed prior to breaking the cycle. 100e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // An additional complication is that moves to MemOperands with large 101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // offsets (more than 1K or 4K) require us to spill this spilled value to 102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the stack, to free up the register. 103e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(!moves_[index].IsPending()); 104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(!moves_[index].IsRedundant()); 105e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 106e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Clear this move's destination to indicate a pending move. The actual 107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // destination is saved in a stack allocated local. Multiple moves can 108e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // be pending because this function is recursive. 109e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(moves_[index].source() != NULL); // Or else it will look eliminated. 110e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* destination = moves_[index].destination(); 111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch moves_[index].set_destination(NULL); 112e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 113e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Perform a depth-first traversal of the move graph to resolve 114e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // dependencies. Any unperformed, unpending move with a source the same 115e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // as this one's destination blocks this one so recursively perform all 116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // such moves. 117e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < moves_.length(); ++i) { 118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LMoveOperands other_move = moves_[i]; 119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (other_move.Blocks(destination) && !other_move.IsPending()) { 120e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PerformMove(i); 121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If there is a blocking, pending move it must be moves_[root_index_] 122e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // and all other moves with the same source as moves_[root_index_] are 123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // sucessfully executed (because they are cycle-free) by this loop. 124e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 125e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 126e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 127e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // We are about to resolve this move and don't need it marked as 128e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // pending, so restore its destination. 129e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch moves_[index].set_destination(destination); 130e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 131e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The move may be blocked on a pending move, which must be the starting move. 132e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // In this case, we have a cycle, and we save the source of this move to 133e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // a scratch register to break it. 134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LMoveOperands other_move = moves_[root_index_]; 135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (other_move.Blocks(destination)) { 136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(other_move.IsPending()); 137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch BreakCycle(index); 138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return; 139e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 141e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // This move is no longer blocked. 142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch EmitMove(index); 143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::Verify() { 147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#ifdef ENABLE_SLOW_ASSERTS 148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // No operand should be the destination for more than one move. 149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < moves_.length(); ++i) { 150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* destination = moves_[i].destination(); 151e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int j = i + 1; j < moves_.length(); ++j) { 152e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch SLOW_ASSERT(!destination->Equals(moves_[j].destination())); 153e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 154e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#endif 156e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#define __ ACCESS_MASM(cgen_->masm()) 159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::BreakCycle(int index) { 161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // We save in a register the value that should end up in the source of 162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // moves_[root_index]. After performing all moves in the tree rooted 163e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // in that move, we save the value to that source. 164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(moves_[index].destination()->Equals(moves_[root_index_].source())); 165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(!in_cycle_); 166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch in_cycle_ = true; 167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* source = moves_[index].source(); 168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch saved_destination_ = moves_[index].destination(); 169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (source->IsRegister()) { 170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(kSavedValueRegister, cgen_->ToRegister(source)); 171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (source->IsStackSlot()) { 172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(kSavedValueRegister, cgen_->ToMemOperand(source)); 173e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (source->IsDoubleRegister()) { 174692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ vmov(kScratchDoubleReg, cgen_->ToDoubleRegister(source)); 175e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (source->IsDoubleStackSlot()) { 176692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ vldr(kScratchDoubleReg, cgen_->ToMemOperand(source)); 177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch UNREACHABLE(); 179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // This move will be done by restoring the saved value to the destination. 181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch moves_[index].Eliminate(); 182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::RestoreValue() { 186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(in_cycle_); 187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(saved_destination_ != NULL); 188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 189e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Spilled value is in kSavedValueRegister or kSavedDoubleValueRegister. 190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (saved_destination_->IsRegister()) { 191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(cgen_->ToRegister(saved_destination_), kSavedValueRegister); 192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (saved_destination_->IsStackSlot()) { 193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ str(kSavedValueRegister, cgen_->ToMemOperand(saved_destination_)); 194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (saved_destination_->IsDoubleRegister()) { 195692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ vmov(cgen_->ToDoubleRegister(saved_destination_), kScratchDoubleReg); 196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (saved_destination_->IsDoubleStackSlot()) { 197692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ vstr(kScratchDoubleReg, cgen_->ToMemOperand(saved_destination_)); 198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch UNREACHABLE(); 200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch in_cycle_ = false; 203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch saved_destination_ = NULL; 204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::EmitMove(int index) { 208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* source = moves_[index].source(); 209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* destination = moves_[index].destination(); 210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Dispatch on the source and destination operand kinds. Not all 212e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // combinations are possible. 213e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 214e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (source->IsRegister()) { 215e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register source_register = cgen_->ToRegister(source); 216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (destination->IsRegister()) { 217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(cgen_->ToRegister(destination), source_register); 218e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(destination->IsStackSlot()); 220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ str(source_register, cgen_->ToMemOperand(destination)); 221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (source->IsStackSlot()) { 224e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch MemOperand source_operand = cgen_->ToMemOperand(source); 225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (destination->IsRegister()) { 226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(cgen_->ToRegister(destination), source_operand); 227e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(destination->IsStackSlot()); 229e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch MemOperand destination_operand = cgen_->ToMemOperand(destination); 230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (in_cycle_) { 231e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!destination_operand.OffsetIsUint12Encodable()) { 232e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // ip is overwritten while saving the value to the destination. 233e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Therefore we can't use ip. It is OK if the read from the source 234e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // destroys ip, since that happens before the value is read. 235692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ vldr(kScratchDoubleReg.low(), source_operand); 236692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ vstr(kScratchDoubleReg.low(), destination_operand); 237e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 238e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(ip, source_operand); 239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ str(ip, destination_operand); 240e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 241e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(kSavedValueRegister, source_operand); 243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ str(kSavedValueRegister, destination_operand); 244e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 245e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 246e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 247e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (source->IsConstantOperand()) { 2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LConstantOperand* constant_source = LConstantOperand::cast(source); 249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (destination->IsRegister()) { 2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register dst = cgen_->ToRegister(destination); 2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cgen_->IsInteger32(constant_source)) { 2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(dst, Operand(cgen_->ToInteger32(constant_source))); 2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadObject(dst, cgen_->ToHandle(constant_source)); 2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 256e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(destination->IsStackSlot()); 258e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(!in_cycle_); // Constant moves happen after all cycles are gone. 2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cgen_->IsInteger32(constant_source)) { 2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(kSavedValueRegister, 2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(cgen_->ToInteger32(constant_source))); 2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadObject(kSavedValueRegister, 2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch cgen_->ToHandle(constant_source)); 2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 266e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ str(kSavedValueRegister, cgen_->ToMemOperand(destination)); 267e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (source->IsDoubleRegister()) { 270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DoubleRegister source_register = cgen_->ToDoubleRegister(source); 271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (destination->IsDoubleRegister()) { 272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ vmov(cgen_->ToDoubleRegister(destination), source_register); 273e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 274e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(destination->IsDoubleStackSlot()); 27569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ vstr(source_register, cgen_->ToMemOperand(destination)); 276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (source->IsDoubleStackSlot()) { 279e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch MemOperand source_operand = cgen_->ToMemOperand(source); 280e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (destination->IsDoubleRegister()) { 281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ vldr(cgen_->ToDoubleRegister(destination), source_operand); 282e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(destination->IsDoubleStackSlot()); 284e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch MemOperand destination_operand = cgen_->ToMemOperand(destination); 285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (in_cycle_) { 286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // kSavedDoubleValueRegister was used to break the cycle, 287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // but kSavedValueRegister is free. 288e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch MemOperand source_high_operand = 289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch cgen_->ToHighMemOperand(source); 290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch MemOperand destination_high_operand = 291e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch cgen_->ToHighMemOperand(destination); 292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(kSavedValueRegister, source_operand); 293e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ str(kSavedValueRegister, destination_operand); 294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(kSavedValueRegister, source_high_operand); 295e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ str(kSavedValueRegister, destination_high_operand); 296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 297692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ vldr(kScratchDoubleReg, source_operand); 298692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ vstr(kScratchDoubleReg, destination_operand); 299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch UNREACHABLE(); 303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch moves_[index].Eliminate(); 306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#undef __ 310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} } // namespace v8::internal 312