1692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm/lithium-codegen-arm.h" 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm/lithium-gap-resolver-arm.h" 9e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 10e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochnamespace v8 { 11e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochnamespace internal { 12e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// We use the root register to spill a value while breaking a cycle in parallel 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// moves. We don't need access to roots while resolving the move list and using 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the root register has two advantages: 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - It is not in crankshaft allocatable registers list, so it can't interfere 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// with any of the moves we are resolving. 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// - We don't need to push it on the stack, as we can reload it with its value 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// once we have resolved a cycle. 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define kSavedValueRegister kRootRegister 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 22e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 23e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochLGapResolver::LGapResolver(LCodeGen* owner) 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : cgen_(owner), moves_(32, owner->zone()), root_index_(0), in_cycle_(false), 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch saved_destination_(NULL), need_to_restore_root_(false) { } 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(cgen_->masm()) 29e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 30e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 31e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::Resolve(LParallelMove* parallel_move) { 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(moves_.is_empty()); 33e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Build up a worklist of moves. 34e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch BuildInitialMoveList(parallel_move); 35e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 36e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < moves_.length(); ++i) { 37e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LMoveOperands move = moves_[i]; 38e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Skip constants to perform them last. They don't block other moves 39e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // and skipping such moves with register destinations keeps those 40e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // registers free for the whole algorithm. 41e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!move.IsEliminated() && !move.source()->IsConstantOperand()) { 42e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch root_index_ = i; // Any cycle is found when by reaching this move again. 43e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PerformMove(i); 44e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (in_cycle_) { 45e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch RestoreValue(); 46e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 47e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 48e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 49e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 50e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Perform the moves with constant sources. 51e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < moves_.length(); ++i) { 52e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!moves_[i].IsEliminated()) { 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(moves_[i].source()->IsConstantOperand()); 54e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch EmitMove(i); 55e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 56e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 57e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (need_to_restore_root_) { 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(kSavedValueRegister.is(kRootRegister)); 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InitializeRootRegister(); 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch need_to_restore_root_ = false; 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 64e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch moves_.Rewind(0); 65e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 66e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 67e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 68e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) { 69e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Perform a linear sweep of the moves to add them to the initial list of 70e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // moves to perform, ignoring any move that is redundant (the source is 71e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the same as the destination, the destination is ignored and 72e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // unallocated, or the move was already eliminated). 73e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const ZoneList<LMoveOperands>* moves = parallel_move->move_operands(); 74e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < moves->length(); ++i) { 75e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LMoveOperands move = moves->at(i); 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!move.IsRedundant()) moves_.Add(move, cgen_->zone()); 77e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 78e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Verify(); 79e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 80e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 81e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 82e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::PerformMove(int index) { 83e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Each call to this function performs a move and deletes it from the move 84e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // graph. We first recursively perform any move blocking this one. We 85e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // mark a move as "pending" on entry to PerformMove in order to detect 86e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // cycles in the move graph. 87e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 88e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // We can only find a cycle, when doing a depth-first traversal of moves, 89e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // be encountering the starting move again. So by spilling the source of 90e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the starting move, we break the cycle. All moves are then unblocked, 91e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // and the starting move is completed by writing the spilled value to 92e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // its destination. All other moves from the spilled source have been 93e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // completed prior to breaking the cycle. 94e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // An additional complication is that moves to MemOperands with large 95e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // offsets (more than 1K or 4K) require us to spill this spilled value to 96e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the stack, to free up the register. 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!moves_[index].IsPending()); 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!moves_[index].IsRedundant()); 99e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 100e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Clear this move's destination to indicate a pending move. The actual 101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // destination is saved in a stack allocated local. Multiple moves can 102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // be pending because this function is recursive. 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(moves_[index].source() != NULL); // Or else it will look eliminated. 104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* destination = moves_[index].destination(); 105e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch moves_[index].set_destination(NULL); 106e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Perform a depth-first traversal of the move graph to resolve 108e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // dependencies. Any unperformed, unpending move with a source the same 109e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // as this one's destination blocks this one so recursively perform all 110e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // such moves. 111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < moves_.length(); ++i) { 112e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LMoveOperands other_move = moves_[i]; 113e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (other_move.Blocks(destination) && !other_move.IsPending()) { 114e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PerformMove(i); 115e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If there is a blocking, pending move it must be moves_[root_index_] 116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // and all other moves with the same source as moves_[root_index_] are 117e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // sucessfully executed (because they are cycle-free) by this loop. 118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 120e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // We are about to resolve this move and don't need it marked as 122e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // pending, so restore its destination. 123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch moves_[index].set_destination(destination); 124e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 125e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The move may be blocked on a pending move, which must be the starting move. 126e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // In this case, we have a cycle, and we save the source of this move to 127e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // a scratch register to break it. 128e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LMoveOperands other_move = moves_[root_index_]; 129e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (other_move.Blocks(destination)) { 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(other_move.IsPending()); 131e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch BreakCycle(index); 132e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return; 133e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // This move is no longer blocked. 136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch EmitMove(index); 137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 139e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::Verify() { 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef ENABLE_SLOW_DCHECKS 142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // No operand should be the destination for more than one move. 143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < moves_.length(); ++i) { 144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* destination = moves_[i].destination(); 145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int j = i + 1; j < moves_.length(); ++j) { 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SLOW_DCHECK(!destination->Equals(moves_[j].destination())); 147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#endif 150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 151e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 152e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 153e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::BreakCycle(int index) { 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We save in a register the source of that move and we remember its 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // destination. Then we mark this move as resolved so the cycle is 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // broken and we can perform the other moves. 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(moves_[index].destination()->Equals(moves_[root_index_].source())); 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!in_cycle_); 159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch in_cycle_ = true; 160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* source = moves_[index].source(); 161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch saved_destination_ = moves_[index].destination(); 162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (source->IsRegister()) { 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch need_to_restore_root_ = true; 164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(kSavedValueRegister, cgen_->ToRegister(source)); 165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (source->IsStackSlot()) { 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch need_to_restore_root_ = true; 167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(kSavedValueRegister, cgen_->ToMemOperand(source)); 168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (source->IsDoubleRegister()) { 169692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ vmov(kScratchDoubleReg, cgen_->ToDoubleRegister(source)); 170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (source->IsDoubleStackSlot()) { 171692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ vldr(kScratchDoubleReg, cgen_->ToMemOperand(source)); 172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 173e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch UNREACHABLE(); 174e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 175e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // This move will be done by restoring the saved value to the destination. 176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch moves_[index].Eliminate(); 177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::RestoreValue() { 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(in_cycle_); 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(saved_destination_ != NULL); 183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (saved_destination_->IsRegister()) { 185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(cgen_->ToRegister(saved_destination_), kSavedValueRegister); 186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (saved_destination_->IsStackSlot()) { 187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ str(kSavedValueRegister, cgen_->ToMemOperand(saved_destination_)); 188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (saved_destination_->IsDoubleRegister()) { 189692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ vmov(cgen_->ToDoubleRegister(saved_destination_), kScratchDoubleReg); 190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (saved_destination_->IsDoubleStackSlot()) { 191692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ vstr(kScratchDoubleReg, cgen_->ToMemOperand(saved_destination_)); 192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch UNREACHABLE(); 194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch in_cycle_ = false; 197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch saved_destination_ = NULL; 198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid LGapResolver::EmitMove(int index) { 202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* source = moves_[index].source(); 203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LOperand* destination = moves_[index].destination(); 204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Dispatch on the source and destination operand kinds. Not all 206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // combinations are possible. 207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (source->IsRegister()) { 209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register source_register = cgen_->ToRegister(source); 210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (destination->IsRegister()) { 211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ mov(cgen_->ToRegister(destination), source_register); 212e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(destination->IsStackSlot()); 214e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ str(source_register, cgen_->ToMemOperand(destination)); 215e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (source->IsStackSlot()) { 217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch MemOperand source_operand = cgen_->ToMemOperand(source); 218e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (destination->IsRegister()) { 219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ ldr(cgen_->ToRegister(destination), source_operand); 220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(destination->IsStackSlot()); 222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch MemOperand destination_operand = cgen_->ToMemOperand(destination); 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!destination_operand.OffsetIsUint12Encodable()) { 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ip is overwritten while saving the value to the destination. 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Therefore we can't use ip. It is OK if the read from the source 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // destroys ip, since that happens before the value is read. 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vldr(kScratchDoubleReg.low(), source_operand); 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vstr(kScratchDoubleReg.low(), destination_operand); 229e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(ip, source_operand); 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(ip, destination_operand); 232e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 233e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 234e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 235e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (source->IsConstantOperand()) { 2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LConstantOperand* constant_source = LConstantOperand::cast(source); 237e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (destination->IsRegister()) { 2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register dst = cgen_->ToRegister(destination); 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Representation r = cgen_->IsSmi(constant_source) 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? Representation::Smi() : Representation::Integer32(); 2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cgen_->IsInteger32(constant_source)) { 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(dst, Operand(cgen_->ToRepresentation(constant_source, r))); 2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(dst, cgen_->ToHandle(constant_source)); 2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (destination->IsDoubleRegister()) { 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister result = cgen_->ToDoubleRegister(destination); 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double v = cgen_->ToDouble(constant_source); 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Vmov(result, v, ip); 250e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(destination->IsStackSlot()); 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!in_cycle_); // Constant moves happen after all cycles are gone. 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch need_to_restore_root_ = true; 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Representation r = cgen_->IsSmi(constant_source) 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? Representation::Smi() : Representation::Integer32(); 2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cgen_->IsInteger32(constant_source)) { 2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(kSavedValueRegister, 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(cgen_->ToRepresentation(constant_source, r))); 2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(kSavedValueRegister, cgen_->ToHandle(constant_source)); 2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 262e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ str(kSavedValueRegister, cgen_->ToMemOperand(destination)); 263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 264e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 265e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (source->IsDoubleRegister()) { 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DwVfpRegister source_register = cgen_->ToDoubleRegister(source); 267e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (destination->IsDoubleRegister()) { 268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ vmov(cgen_->ToDoubleRegister(destination), source_register); 269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(destination->IsDoubleStackSlot()); 27169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ vstr(source_register, cgen_->ToMemOperand(destination)); 272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 273e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 274e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (source->IsDoubleStackSlot()) { 275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch MemOperand source_operand = cgen_->ToMemOperand(source); 276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (destination->IsDoubleRegister()) { 277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ vldr(cgen_->ToDoubleRegister(destination), source_operand); 278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(destination->IsDoubleStackSlot()); 280e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch MemOperand destination_operand = cgen_->ToMemOperand(destination); 281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (in_cycle_) { 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // kScratchDoubleReg was used to break the cycle. 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vstm(db_w, sp, kScratchDoubleReg, kScratchDoubleReg); 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vldr(kScratchDoubleReg, source_operand); 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vstr(kScratchDoubleReg, destination_operand); 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ vldm(ia_w, sp, kScratchDoubleReg, kScratchDoubleReg); 287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 288692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ vldr(kScratchDoubleReg, source_operand); 289692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch __ vstr(kScratchDoubleReg, destination_operand); 290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 291e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 293e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch UNREACHABLE(); 294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 295e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch moves_[index].Eliminate(); 297e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 298e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#undef __ 301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} } // namespace v8::internal 303