Chromium Code Reviews| 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..2e6270378cf5da6434fe64785d23ab9babb7ce6c 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 kSavedValue kRootRegister |
|
Benedikt Meurer
2014/04/26 10:14:38
Nit: Use kSavedValueRegister.
vincent.belliard
2014/04/28 08:20:29
Done.
|
| + |
| 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(kSavedValue.is(kRootRegister)); |
| + __ InitializeRootRegister(); |
| + need_to_restore_root_ = false; |
| + } |
| + |
| moves_.Rewind(0); |
| } |
| @@ -155,21 +172,22 @@ 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()) { |
| - __ mov(kSavedValueRegister, cgen_->ToRegister(source)); |
| + need_to_restore_root_ = true; |
| + __ mov(kSavedValue, cgen_->ToRegister(source)); |
| } else if (source->IsStackSlot()) { |
| - __ ldr(kSavedValueRegister, cgen_->ToMemOperand(source)); |
| + need_to_restore_root_ = true; |
| + __ ldr(kSavedValue, cgen_->ToMemOperand(source)); |
| } else if (source->IsDoubleRegister()) { |
| __ vmov(kScratchDoubleReg, cgen_->ToDoubleRegister(source)); |
| } else if (source->IsDoubleStackSlot()) { |
| @@ -186,11 +204,10 @@ 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); |
| + __ mov(cgen_->ToRegister(saved_destination_), kSavedValue); |
| } else if (saved_destination_->IsStackSlot()) { |
| - __ str(kSavedValueRegister, cgen_->ToMemOperand(saved_destination_)); |
| + __ str(kSavedValue, cgen_->ToMemOperand(saved_destination_)); |
| } else if (saved_destination_->IsDoubleRegister()) { |
| __ vmov(cgen_->ToDoubleRegister(saved_destination_), kScratchDoubleReg); |
| } else if (saved_destination_->IsDoubleStackSlot()) { |
| @@ -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,16 +273,16 @@ 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, |
| + __ mov(kSavedValue, |
| Operand(cgen_->ToRepresentation(constant_source, r))); |
| } else { |
| - __ Move(kSavedValueRegister, |
| - cgen_->ToHandle(constant_source)); |
| + __ Move(kSavedValue, cgen_->ToHandle(constant_source)); |
| } |
| - __ str(kSavedValueRegister, cgen_->ToMemOperand(destination)); |
| + __ str(kSavedValue, cgen_->ToMemOperand(destination)); |
| } |
| } else if (source->IsDoubleRegister()) { |
| @@ -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); |