| Index: src/arm/lithium-gap-resolver-arm.cc
|
| diff --git a/src/arm/lithium-gap-resolver-arm.cc b/src/arm/lithium-gap-resolver-arm.cc
|
| index 0c6b2adadfdf45c549f1b7c749fc00def5d7172f..59ef878b305a6f318f85974cc71c3b0627ed0052 100644
|
| --- a/src/arm/lithium-gap-resolver-arm.cc
|
| +++ b/src/arm/lithium-gap-resolver-arm.cc
|
| @@ -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);
|
|
|