1f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Copyright 2013 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
4f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
6f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
7975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org#include "src/arm64/delayed-masm-arm64-inl.h"
8196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/arm64/lithium-codegen-arm64.h"
94b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/arm64/lithium-gap-resolver-arm64.h"
10f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
11f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgnamespace v8 {
12f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgnamespace internal {
13f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
14975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org#define __ ACCESS_MASM((&masm_))
15f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
16a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org
17975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.orgvoid DelayedGapMasm::EndDelayedUse() {
18975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  DelayedMasm::EndDelayedUse();
19975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  if (scratch_register_used()) {
20e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(ScratchRegister().Is(root));
21e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!pending());
22975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org    InitializeRootRegister();
23975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org    reset_scratch_register_used();
24975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  }
25975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org}
26a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org
27f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
28975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.orgLGapResolver::LGapResolver(LCodeGen* owner)
29975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org    : cgen_(owner), masm_(owner, owner->masm()), moves_(32, owner->zone()),
30975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org      root_index_(0), in_cycle_(false), saved_destination_(NULL) {
31975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org}
32f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
33f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
34f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid LGapResolver::Resolve(LParallelMove* parallel_move) {
35e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(moves_.is_empty());
36e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!masm_.pending());
37f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
38f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Build up a worklist of moves.
39f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  BuildInitialMoveList(parallel_move);
40f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
41f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  for (int i = 0; i < moves_.length(); ++i) {
42f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    LMoveOperands move = moves_[i];
43f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
44f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // Skip constants to perform them last. They don't block other moves
45f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // and skipping such moves with register destinations keeps those
46f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // registers free for the whole algorithm.
47f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (!move.IsEliminated() && !move.source()->IsConstantOperand()) {
48f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      root_index_ = i;  // Any cycle is found when we reach this move again.
49f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      PerformMove(i);
50f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      if (in_cycle_) RestoreValue();
51f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
52f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
53f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
54f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Perform the moves with constant sources.
55f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  for (int i = 0; i < moves_.length(); ++i) {
56f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    LMoveOperands move = moves_[i];
57f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
58f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (!move.IsEliminated()) {
59e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(move.source()->IsConstantOperand());
60f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      EmitMove(i);
61f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
62f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
63f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
64975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  __ EndDelayedUse();
65f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
66f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  moves_.Rewind(0);
67f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
68f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
69f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
70f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid LGapResolver::BuildInitialMoveList(LParallelMove* parallel_move) {
71f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Perform a linear sweep of the moves to add them to the initial list of
72f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // moves to perform, ignoring any move that is redundant (the source is
73f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // the same as the destination, the destination is ignored and
74f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // unallocated, or the move was already eliminated).
75f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  const ZoneList<LMoveOperands>* moves = parallel_move->move_operands();
76f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  for (int i = 0; i < moves->length(); ++i) {
77f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    LMoveOperands move = moves->at(i);
78f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (!move.IsRedundant()) moves_.Add(move, cgen_->zone());
79f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
80f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Verify();
81f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
82f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
83f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
84f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid LGapResolver::PerformMove(int index) {
85f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Each call to this function performs a move and deletes it from the move
86f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // graph. We first recursively perform any move blocking this one. We
87f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // mark a move as "pending" on entry to PerformMove in order to detect
88f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // cycles in the move graph.
89f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  LMoveOperands& current_move = moves_[index];
90f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
91e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!current_move.IsPending());
92e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!current_move.IsRedundant());
93f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
94f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Clear this move's destination to indicate a pending move.  The actual
95f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // destination is saved in a stack allocated local. Multiple moves can
96f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // be pending because this function is recursive.
97e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(current_move.source() != NULL);  // Otherwise it will look eliminated.
98f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  LOperand* destination = current_move.destination();
99f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  current_move.set_destination(NULL);
100f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
101f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Perform a depth-first traversal of the move graph to resolve
102f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // dependencies. Any unperformed, unpending move with a source the same
103f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // as this one's destination blocks this one so recursively perform all
104f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // such moves.
105f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  for (int i = 0; i < moves_.length(); ++i) {
106f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    LMoveOperands other_move = moves_[i];
107f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (other_move.Blocks(destination) && !other_move.IsPending()) {
108f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      PerformMove(i);
109f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      // If there is a blocking, pending move it must be moves_[root_index_]
110f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      // and all other moves with the same source as moves_[root_index_] are
111f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      // sucessfully executed (because they are cycle-free) by this loop.
112f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
113f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
114f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
115f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // We are about to resolve this move and don't need it marked as
116f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // pending, so restore its destination.
117f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  current_move.set_destination(destination);
118f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
119f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // The move may be blocked on a pending move, which must be the starting move.
120f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // In this case, we have a cycle, and we save the source of this move to
121f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // a scratch register to break it.
122f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  LMoveOperands other_move = moves_[root_index_];
123f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  if (other_move.Blocks(destination)) {
124e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(other_move.IsPending());
125f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    BreakCycle(index);
126f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return;
127f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
128f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
129f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // This move is no longer blocked.
130f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  EmitMove(index);
131f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
132f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
133f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
134f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid LGapResolver::Verify() {
135e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org#ifdef ENABLE_SLOW_DCHECKS
136f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // No operand should be the destination for more than one move.
137f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  for (int i = 0; i < moves_.length(); ++i) {
138f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    LOperand* destination = moves_[i].destination();
139f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    for (int j = i + 1; j < moves_.length(); ++j) {
140e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      SLOW_DCHECK(!destination->Equals(moves_[j].destination()));
141f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
142f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
143f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#endif
144f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
145f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
146f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
147f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid LGapResolver::BreakCycle(int index) {
148e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(moves_[index].destination()->Equals(moves_[root_index_].source()));
149e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!in_cycle_);
150f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
151f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // We save in a register the source of that move and we remember its
152f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // destination. Then we mark this move as resolved so the cycle is
153f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // broken and we can perform the other moves.
154f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  in_cycle_ = true;
155f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  LOperand* source = moves_[index].source();
156f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  saved_destination_ = moves_[index].destination();
157f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
158f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  if (source->IsRegister()) {
159975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org    AcquireSavedValueRegister();
160975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org    __ Mov(SavedValueRegister(), cgen_->ToRegister(source));
161f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  } else if (source->IsStackSlot()) {
162975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org    AcquireSavedValueRegister();
163975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org    __ Load(SavedValueRegister(), cgen_->ToMemOperand(source));
164f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  } else if (source->IsDoubleRegister()) {
165975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org    __ Fmov(SavedFPValueRegister(), cgen_->ToDoubleRegister(source));
166f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  } else if (source->IsDoubleStackSlot()) {
167975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org    __ Load(SavedFPValueRegister(), cgen_->ToMemOperand(source));
168f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  } else {
169f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    UNREACHABLE();
170f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
171f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
172f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Mark this move as resolved.
173f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // This move will be actually performed by moving the saved value to this
174f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // move's destination in LGapResolver::RestoreValue().
175f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  moves_[index].Eliminate();
176f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
177f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
178f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
179f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid LGapResolver::RestoreValue() {
180e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(in_cycle_);
181e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(saved_destination_ != NULL);
182f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
183f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  if (saved_destination_->IsRegister()) {
184975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org    __ Mov(cgen_->ToRegister(saved_destination_), SavedValueRegister());
185975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org    ReleaseSavedValueRegister();
186f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  } else if (saved_destination_->IsStackSlot()) {
187975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org    __ Store(SavedValueRegister(), cgen_->ToMemOperand(saved_destination_));
188975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org    ReleaseSavedValueRegister();
189f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  } else if (saved_destination_->IsDoubleRegister()) {
190975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org    __ Fmov(cgen_->ToDoubleRegister(saved_destination_),
191975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org            SavedFPValueRegister());
192f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  } else if (saved_destination_->IsDoubleStackSlot()) {
193975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org    __ Store(SavedFPValueRegister(), cgen_->ToMemOperand(saved_destination_));
194f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  } else {
195f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    UNREACHABLE();
196f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
197f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
198f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  in_cycle_ = false;
199f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  saved_destination_ = NULL;
200f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
201f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
202f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
203f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid LGapResolver::EmitMove(int index) {
204f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  LOperand* source = moves_[index].source();
205f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  LOperand* destination = moves_[index].destination();
206f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
207f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Dispatch on the source and destination operand kinds.  Not all
208f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // combinations are possible.
209f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
210f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  if (source->IsRegister()) {
211f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    Register source_register = cgen_->ToRegister(source);
212f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (destination->IsRegister()) {
213f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      __ Mov(cgen_->ToRegister(destination), source_register);
214f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    } else {
215e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(destination->IsStackSlot());
216975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org      __ Store(source_register, cgen_->ToMemOperand(destination));
217f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
218f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
219f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  } else if (source->IsStackSlot()) {
220f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    MemOperand source_operand = cgen_->ToMemOperand(source);
221f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (destination->IsRegister()) {
222975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org      __ Load(cgen_->ToRegister(destination), source_operand);
223f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    } else {
224e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(destination->IsStackSlot());
225f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      EmitStackSlotMove(index);
226f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
227f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
228f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  } else if (source->IsConstantOperand()) {
229f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    LConstantOperand* constant_source = LConstantOperand::cast(source);
230f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (destination->IsRegister()) {
231f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      Register dst = cgen_->ToRegister(destination);
232f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      if (cgen_->IsSmi(constant_source)) {
2337010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org        __ Mov(dst, cgen_->ToSmi(constant_source));
234f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      } else if (cgen_->IsInteger32Constant(constant_source)) {
235f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        __ Mov(dst, cgen_->ToInteger32(constant_source));
236f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      } else {
237f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        __ LoadObject(dst, cgen_->ToHandle(constant_source));
238f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      }
239f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    } else if (destination->IsDoubleRegister()) {
240f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      DoubleRegister result = cgen_->ToDoubleRegister(destination);
241f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      __ Fmov(result, cgen_->ToDouble(constant_source));
242f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    } else {
243e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(destination->IsStackSlot());
244e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(!in_cycle_);  // Constant moves happen after all cycles are gone.
245f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      if (cgen_->IsSmi(constant_source)) {
246975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org        Smi* smi = cgen_->ToSmi(constant_source);
247975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org        __ StoreConstant(reinterpret_cast<intptr_t>(smi),
248975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org                         cgen_->ToMemOperand(destination));
249f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      } else if (cgen_->IsInteger32Constant(constant_source)) {
250975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org        __ StoreConstant(cgen_->ToInteger32(constant_source),
251975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org                         cgen_->ToMemOperand(destination));
252f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      } else {
253975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org        Handle<Object> handle = cgen_->ToHandle(constant_source);
254975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org        AllowDeferredHandleDereference smi_object_check;
255975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org        if (handle->IsSmi()) {
256975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org          Object* obj = *handle;
257e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org          DCHECK(!obj->IsHeapObject());
258975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org          __ StoreConstant(reinterpret_cast<intptr_t>(obj),
259975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org                           cgen_->ToMemOperand(destination));
260975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org        } else {
261975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org          AcquireSavedValueRegister();
262975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org          __ LoadObject(SavedValueRegister(), handle);
263975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org          __ Store(SavedValueRegister(), cgen_->ToMemOperand(destination));
264975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org          ReleaseSavedValueRegister();
265975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org        }
266f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      }
267f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
268f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
269f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  } else if (source->IsDoubleRegister()) {
270f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    DoubleRegister src = cgen_->ToDoubleRegister(source);
271f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (destination->IsDoubleRegister()) {
272f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      __ Fmov(cgen_->ToDoubleRegister(destination), src);
273f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    } else {
274e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(destination->IsDoubleStackSlot());
275975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org      __ Store(src, cgen_->ToMemOperand(destination));
276f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
277f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
278f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  } else if (source->IsDoubleStackSlot()) {
279f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    MemOperand src = cgen_->ToMemOperand(source);
280f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (destination->IsDoubleRegister()) {
281975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org      __ Load(cgen_->ToDoubleRegister(destination), src);
282f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    } else {
283e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(destination->IsDoubleStackSlot());
284f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      EmitStackSlotMove(index);
285f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
286f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
287f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  } else {
288f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    UNREACHABLE();
289f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
290f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
291f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // The move has been emitted, we can eliminate it.
292f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  moves_[index].Eliminate();
293f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
294f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
295f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} }  // namespace v8::internal
296