ARM: don't use r9 anymore for gap resolution

BUG=
R=bmeurer@chromium.org, ulan@chromium.org

Review URL: https://codereview.chromium.org/255883002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@21008 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 9aaa5367
......@@ -33,11 +33,22 @@
namespace v8 {
namespace internal {
static const Register kSavedValueRegister = { 9 };
// We use the root register to spill a value while breaking a cycle in parallel
// moves. We don't need access to roots while resolving the move list and using
// the root register has two advantages:
// - It is not in crankshaft allocatable registers list, so it can't interfere
// with any of the moves we are resolving.
// - We don't need to push it on the stack, as we can reload it with its value
// once we have resolved a cycle.
#define kSavedValueRegister kRootRegister
LGapResolver::LGapResolver(LCodeGen* owner)
: cgen_(owner), moves_(32, owner->zone()), root_index_(0), in_cycle_(false),
saved_destination_(NULL) { }
saved_destination_(NULL), need_to_restore_root_(false) { }
#define __ ACCESS_MASM(cgen_->masm())
void LGapResolver::Resolve(LParallelMove* parallel_move) {
......@@ -67,6 +78,12 @@ void LGapResolver::Resolve(LParallelMove* parallel_move) {
}
}
if (need_to_restore_root_) {
ASSERT(kSavedValueRegister.is(kRootRegister));
__ InitializeRootRegister();
need_to_restore_root_ = false;
}
moves_.Rewind(0);
}
......@@ -155,20 +172,21 @@ void LGapResolver::Verify() {
#endif
}
#define __ ACCESS_MASM(cgen_->masm())
void LGapResolver::BreakCycle(int index) {
// We save in a register the value that should end up in the source of
// moves_[root_index]. After performing all moves in the tree rooted
// in that move, we save the value to that source.
// We save in a register the source of that move and we remember its
// destination. Then we mark this move as resolved so the cycle is
// broken and we can perform the other moves.
ASSERT(moves_[index].destination()->Equals(moves_[root_index_].source()));
ASSERT(!in_cycle_);
in_cycle_ = true;
LOperand* source = moves_[index].source();
saved_destination_ = moves_[index].destination();
if (source->IsRegister()) {
need_to_restore_root_ = true;
__ mov(kSavedValueRegister, cgen_->ToRegister(source));
} else if (source->IsStackSlot()) {
need_to_restore_root_ = true;
__ ldr(kSavedValueRegister, cgen_->ToMemOperand(source));
} else if (source->IsDoubleRegister()) {
__ vmov(kScratchDoubleReg, cgen_->ToDoubleRegister(source));
......@@ -186,7 +204,6 @@ void LGapResolver::RestoreValue() {
ASSERT(in_cycle_);
ASSERT(saved_destination_ != NULL);
// Spilled value is in kSavedValueRegister or kSavedDoubleValueRegister.
if (saved_destination_->IsRegister()) {
__ mov(cgen_->ToRegister(saved_destination_), kSavedValueRegister);
} else if (saved_destination_->IsStackSlot()) {
......@@ -226,20 +243,15 @@ void LGapResolver::EmitMove(int index) {
} else {
ASSERT(destination->IsStackSlot());
MemOperand destination_operand = cgen_->ToMemOperand(destination);
if (in_cycle_) {
if (!destination_operand.OffsetIsUint12Encodable()) {
// ip is overwritten while saving the value to the destination.
// Therefore we can't use ip. It is OK if the read from the source
// destroys ip, since that happens before the value is read.
__ vldr(kScratchDoubleReg.low(), source_operand);
__ vstr(kScratchDoubleReg.low(), destination_operand);
} else {
__ ldr(ip, source_operand);
__ str(ip, destination_operand);
}
if (!destination_operand.OffsetIsUint12Encodable()) {
// ip is overwritten while saving the value to the destination.
// Therefore we can't use ip. It is OK if the read from the source
// destroys ip, since that happens before the value is read.
__ vldr(kScratchDoubleReg.low(), source_operand);
__ vstr(kScratchDoubleReg.low(), destination_operand);
} else {
__ ldr(kSavedValueRegister, source_operand);
__ str(kSavedValueRegister, destination_operand);
__ ldr(ip, source_operand);
__ str(ip, destination_operand);
}
}
......@@ -261,14 +273,14 @@ void LGapResolver::EmitMove(int index) {
} else {
ASSERT(destination->IsStackSlot());
ASSERT(!in_cycle_); // Constant moves happen after all cycles are gone.
need_to_restore_root_ = true;
Representation r = cgen_->IsSmi(constant_source)
? Representation::Smi() : Representation::Integer32();
if (cgen_->IsInteger32(constant_source)) {
__ mov(kSavedValueRegister,
Operand(cgen_->ToRepresentation(constant_source, r)));
} else {
__ Move(kSavedValueRegister,
cgen_->ToHandle(constant_source));
__ Move(kSavedValueRegister, cgen_->ToHandle(constant_source));
}
__ str(kSavedValueRegister, cgen_->ToMemOperand(destination));
}
......@@ -290,16 +302,11 @@ void LGapResolver::EmitMove(int index) {
ASSERT(destination->IsDoubleStackSlot());
MemOperand destination_operand = cgen_->ToMemOperand(destination);
if (in_cycle_) {
// kSavedDoubleValueRegister was used to break the cycle,
// but kSavedValueRegister is free.
MemOperand source_high_operand =
cgen_->ToHighMemOperand(source);
MemOperand destination_high_operand =
cgen_->ToHighMemOperand(destination);
__ ldr(kSavedValueRegister, source_operand);
__ str(kSavedValueRegister, destination_operand);
__ ldr(kSavedValueRegister, source_high_operand);
__ str(kSavedValueRegister, destination_high_operand);
// kScratchDoubleReg was used to break the cycle.
__ vstm(db_w, sp, kScratchDoubleReg, kScratchDoubleReg);
__ vldr(kScratchDoubleReg, source_operand);
__ vstr(kScratchDoubleReg, destination_operand);
__ vldm(ia_w, sp, kScratchDoubleReg, kScratchDoubleReg);
} else {
__ vldr(kScratchDoubleReg, source_operand);
__ vstr(kScratchDoubleReg, destination_operand);
......
......@@ -76,6 +76,10 @@ class LGapResolver V8_FINAL BASE_EMBEDDED {
int root_index_;
bool in_cycle_;
LOperand* saved_destination_;
// We use the root register as a scratch in a few places. When that happens,
// this flag is set to indicate that it needs to be restored.
bool need_to_restore_root_;
};
} } // namespace v8::internal
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment