MIPS: Fix for an ARM register allocation bug.

Port r10374 (03bbe39).

Note: the MIPS version was not affected by the bug. This is merely a style cleanup.

Original commit message:
An off-by-one in the register allocator could lead to allocating (and
clobbering) the reserved 0.0 double register.  This required a function with
14 or more live double values.

BUG=
TEST=

Review URL: https://chromiumcodereview.appspot.com/9150025
Patch from Daniel Kalmar <kalmard@homejinni.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10440 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
kmillikin@chromium.org 2012-01-19 13:41:11 +00:00
parent 77f6a6fc31
commit b571bd2ce9
4 changed files with 32 additions and 30 deletions

View File

@ -30,7 +30,7 @@
// The original source code covered by the above license above has been // The original source code covered by the above license above has been
// modified significantly by Google Inc. // modified significantly by Google Inc.
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
#ifndef V8_MIPS_ASSEMBLER_MIPS_INL_H_ #ifndef V8_MIPS_ASSEMBLER_MIPS_INL_H_
@ -78,6 +78,16 @@ bool Operand::is_reg() const {
} }
int FPURegister::ToAllocationIndex(FPURegister reg) {
ASSERT(reg.code() % 2 == 0);
ASSERT(reg.code() / 2 < kNumAllocatableRegisters);
ASSERT(reg.is_valid());
ASSERT(!reg.is(kDoubleRegZero));
ASSERT(!reg.is(kLithiumScratchDouble));
return (reg.code() / 2);
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// RelocInfo. // RelocInfo.

View File

@ -30,7 +30,7 @@
// The original source code covered by the above license above has been // The original source code covered by the above license above has been
// modified significantly by Google Inc. // modified significantly by Google Inc.
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
#ifndef V8_MIPS_ASSEMBLER_MIPS_H_ #ifndef V8_MIPS_ASSEMBLER_MIPS_H_
@ -182,12 +182,7 @@ struct FPURegister {
kNumReservedRegisters; kNumReservedRegisters;
static int ToAllocationIndex(FPURegister reg) { inline static int ToAllocationIndex(FPURegister reg);
ASSERT(reg.code() % 2 == 0);
ASSERT(reg.code() / 2 < kNumAllocatableRegisters);
ASSERT(reg.is_valid());
return (reg.code() / 2);
}
static FPURegister FromAllocationIndex(int index) { static FPURegister FromAllocationIndex(int index) {
ASSERT(index >= 0 && index < kNumAllocatableRegisters); ASSERT(index >= 0 && index < kNumAllocatableRegisters);
@ -302,6 +297,14 @@ const FPURegister f29 = { 29 };
const FPURegister f30 = { 30 }; const FPURegister f30 = { 30 };
const FPURegister f31 = { 31 }; const FPURegister f31 = { 31 };
// Register aliases.
// cp is assumed to be a callee saved register.
static const Register& kLithiumScratchReg = s3; // Scratch register.
static const Register& kLithiumScratchReg2 = s4; // Scratch register.
static const Register& kRootRegister = s6; // Roots array pointer.
static const Register& cp = s7; // JavaScript context pointer.
static const Register& fp = s8_fp; // Alias for fp.
static const DoubleRegister& kLithiumScratchDouble = f30;
static const FPURegister& kDoubleRegZero = f28; static const FPURegister& kDoubleRegZero = f28;
// FPU (coprocessor 1) control registers. // FPU (coprocessor 1) control registers.

View File

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -34,7 +34,6 @@ namespace v8 {
namespace internal { namespace internal {
static const Register kSavedValueRegister = kLithiumScratchReg; static const Register kSavedValueRegister = kLithiumScratchReg;
static const DoubleRegister kSavedDoubleValueRegister = kLithiumScratchDouble;
LGapResolver::LGapResolver(LCodeGen* owner) LGapResolver::LGapResolver(LCodeGen* owner)
: cgen_(owner), : cgen_(owner),
@ -175,9 +174,9 @@ void LGapResolver::BreakCycle(int index) {
} else if (source->IsStackSlot()) { } else if (source->IsStackSlot()) {
__ lw(kSavedValueRegister, cgen_->ToMemOperand(source)); __ lw(kSavedValueRegister, cgen_->ToMemOperand(source));
} else if (source->IsDoubleRegister()) { } else if (source->IsDoubleRegister()) {
__ mov_d(kSavedDoubleValueRegister, cgen_->ToDoubleRegister(source)); __ mov_d(kLithiumScratchDouble, cgen_->ToDoubleRegister(source));
} else if (source->IsDoubleStackSlot()) { } else if (source->IsDoubleStackSlot()) {
__ ldc1(kSavedDoubleValueRegister, cgen_->ToMemOperand(source)); __ ldc1(kLithiumScratchDouble, cgen_->ToMemOperand(source));
} else { } else {
UNREACHABLE(); UNREACHABLE();
} }
@ -190,16 +189,16 @@ void LGapResolver::RestoreValue() {
ASSERT(in_cycle_); ASSERT(in_cycle_);
ASSERT(saved_destination_ != NULL); ASSERT(saved_destination_ != NULL);
// Spilled value is in kSavedValueRegister or kSavedDoubleValueRegister. // Spilled value is in kSavedValueRegister or kLithiumScratchDouble.
if (saved_destination_->IsRegister()) { if (saved_destination_->IsRegister()) {
__ mov(cgen_->ToRegister(saved_destination_), kSavedValueRegister); __ mov(cgen_->ToRegister(saved_destination_), kSavedValueRegister);
} else if (saved_destination_->IsStackSlot()) { } else if (saved_destination_->IsStackSlot()) {
__ sw(kSavedValueRegister, cgen_->ToMemOperand(saved_destination_)); __ sw(kSavedValueRegister, cgen_->ToMemOperand(saved_destination_));
} else if (saved_destination_->IsDoubleRegister()) { } else if (saved_destination_->IsDoubleRegister()) {
__ mov_d(cgen_->ToDoubleRegister(saved_destination_), __ mov_d(cgen_->ToDoubleRegister(saved_destination_),
kSavedDoubleValueRegister); kLithiumScratchDouble);
} else if (saved_destination_->IsDoubleStackSlot()) { } else if (saved_destination_->IsDoubleStackSlot()) {
__ sdc1(kSavedDoubleValueRegister, __ sdc1(kLithiumScratchDouble,
cgen_->ToMemOperand(saved_destination_)); cgen_->ToMemOperand(saved_destination_));
} else { } else {
UNREACHABLE(); UNREACHABLE();
@ -239,8 +238,8 @@ void LGapResolver::EmitMove(int index) {
// Therefore we can't use 'at'. It is OK if the read from the source // Therefore we can't use 'at'. It is OK if the read from the source
// destroys 'at', since that happens before the value is read. // destroys 'at', since that happens before the value is read.
// This uses only a single reg of the double reg-pair. // This uses only a single reg of the double reg-pair.
__ lwc1(kSavedDoubleValueRegister, source_operand); __ lwc1(kLithiumScratchDouble, source_operand);
__ swc1(kSavedDoubleValueRegister, destination_operand); __ swc1(kLithiumScratchDouble, destination_operand);
} else { } else {
__ lw(at, source_operand); __ lw(at, source_operand);
__ sw(at, destination_operand); __ sw(at, destination_operand);
@ -291,7 +290,7 @@ void LGapResolver::EmitMove(int index) {
ASSERT(destination->IsDoubleStackSlot()); ASSERT(destination->IsDoubleStackSlot());
MemOperand destination_operand = cgen_->ToMemOperand(destination); MemOperand destination_operand = cgen_->ToMemOperand(destination);
if (in_cycle_) { if (in_cycle_) {
// kSavedDoubleValueRegister was used to break the cycle, // kLithiumScratchDouble was used to break the cycle,
// but kSavedValueRegister is free. // but kSavedValueRegister is free.
MemOperand source_high_operand = MemOperand source_high_operand =
cgen_->ToHighMemOperand(source); cgen_->ToHighMemOperand(source);
@ -302,8 +301,8 @@ void LGapResolver::EmitMove(int index) {
__ lw(kSavedValueRegister, source_high_operand); __ lw(kSavedValueRegister, source_high_operand);
__ sw(kSavedValueRegister, destination_high_operand); __ sw(kSavedValueRegister, destination_high_operand);
} else { } else {
__ ldc1(kSavedDoubleValueRegister, source_operand); __ ldc1(kLithiumScratchDouble, source_operand);
__ sdc1(kSavedDoubleValueRegister, destination_operand); __ sdc1(kLithiumScratchDouble, destination_operand);
} }
} }
} else { } else {

View File

@ -51,16 +51,6 @@ class JumpTarget;
// MIPS generated code calls C code, it must be via t9 register. // MIPS generated code calls C code, it must be via t9 register.
// Register aliases.
// cp is assumed to be a callee saved register.
const Register kLithiumScratchReg = s3; // Scratch register.
const Register kLithiumScratchReg2 = s4; // Scratch register.
const Register kCondReg = s5; // Simulated (partial) condition code for mips.
const Register kRootRegister = s6; // Roots array pointer.
const Register cp = s7; // JavaScript context pointer.
const Register fp = s8_fp; // Alias for fp.
const DoubleRegister kLithiumScratchDouble = f30; // Double scratch register.
// Flags used for the AllocateInNewSpace functions. // Flags used for the AllocateInNewSpace functions.
enum AllocationFlags { enum AllocationFlags {
// No special flags. // No special flags.