[ppc] use Double instead of double in ppc compiler

The use of double variables to store bit patterns may lead to bit flips
when the stored bit pattern is a signaling NaN (sNaN). Operations on a
sNaN variable (even just returning the variable from a function) may
turn it into a quiet NaN (qNaN), flipping the signaling bit and
affecting the information stored in the variable.

We observed this behaviour on ia32 architectures and therefore in the
simulator builds for other platforms. The use of the wrapper class
Double should prevent this behaviour.

R=ahaas@chromium.org

Change-Id: Ibd1119924a59db771fd4c250689ad9c2a35fff75
Reviewed-on: https://chromium-review.googlesource.com/562771
Reviewed-by: Jaideep Bajwa <bjaideep@ca.ibm.com>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Commit-Queue: Enrico Bacis <enricobacis@google.com>
Cr-Commit-Position: refs/heads/master@{#46533}
This commit is contained in:
Enrico Bacis 2017-07-07 16:04:32 +02:00 committed by Commit Bot
parent b618aa8106
commit 5457e8a9b5
7 changed files with 35 additions and 29 deletions

View File

@ -1213,11 +1213,16 @@ class ConstantPoolBuilder BASE_EMBEDDED {
} }
// Add double constant to the embedded constant pool // Add double constant to the embedded constant pool
ConstantPoolEntry::Access AddEntry(int position, double value) { ConstantPoolEntry::Access AddEntry(int position, Double value) {
ConstantPoolEntry entry(position, Double(value)); ConstantPoolEntry entry(position, value);
return AddEntry(entry, ConstantPoolEntry::DOUBLE); return AddEntry(entry, ConstantPoolEntry::DOUBLE);
} }
// Add double constant to the embedded constant pool
ConstantPoolEntry::Access AddEntry(int position, double value) {
return AddEntry(position, Double(value));
}
// Previews the access type required for the next new entry to be added. // Previews the access type required for the next new entry to be added.
ConstantPoolEntry::Access NextAccess(ConstantPoolEntry::Type type) const; ConstantPoolEntry::Access NextAccess(ConstantPoolEntry::Type type) const;

View File

@ -9,6 +9,7 @@
#include "src/compiler/gap-resolver.h" #include "src/compiler/gap-resolver.h"
#include "src/compiler/node-matchers.h" #include "src/compiler/node-matchers.h"
#include "src/compiler/osr.h" #include "src/compiler/osr.h"
#include "src/double.h"
#include "src/ppc/macro-assembler-ppc.h" #include "src/ppc/macro-assembler-ppc.h"
namespace v8 { namespace v8 {
@ -124,8 +125,8 @@ class OutOfLineLoadNAN32 final : public OutOfLineCode {
: OutOfLineCode(gen), result_(result) {} : OutOfLineCode(gen), result_(result) {}
void Generate() final { void Generate() final {
__ LoadDoubleLiteral(result_, std::numeric_limits<float>::quiet_NaN(), __ LoadDoubleLiteral(
kScratchReg); result_, Double(std::numeric_limits<double>::quiet_NaN()), kScratchReg);
} }
private: private:
@ -139,8 +140,8 @@ class OutOfLineLoadNAN64 final : public OutOfLineCode {
: OutOfLineCode(gen), result_(result) {} : OutOfLineCode(gen), result_(result) {}
void Generate() final { void Generate() final {
__ LoadDoubleLiteral(result_, std::numeric_limits<double>::quiet_NaN(), __ LoadDoubleLiteral(
kScratchReg); result_, Double(std::numeric_limits<double>::quiet_NaN()), kScratchReg);
} }
private: private:
@ -2450,31 +2451,27 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
DoubleRegister dst = destination->IsFPRegister() DoubleRegister dst = destination->IsFPRegister()
? g.ToDoubleRegister(destination) ? g.ToDoubleRegister(destination)
: kScratchDoubleReg; : kScratchDoubleReg;
double value; Double value;
#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64 #if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
// casting double precision snan to single precision // casting double precision snan to single precision
// converts it to qnan on ia32/x64 // converts it to qnan on ia32/x64
if (src.type() == Constant::kFloat32) { if (src.type() == Constant::kFloat32) {
int32_t val = src.ToFloat32AsInt(); uint32_t val = src.ToFloat32AsInt();
if ((val & 0x7f800000) == 0x7f800000) { if ((val & 0x7f800000) == 0x7f800000) {
int64_t dval = static_cast<int64_t>(val); uint64_t dval = static_cast<uint64_t>(val);
dval = ((dval & 0xc0000000) << 32) | ((dval & 0x40000000) << 31) | dval = ((dval & 0xc0000000) << 32) | ((dval & 0x40000000) << 31) |
((dval & 0x40000000) << 30) | ((dval & 0x7fffffff) << 29); ((dval & 0x40000000) << 30) | ((dval & 0x7fffffff) << 29);
value = bit_cast<double, int64_t>(dval); value = Double(dval);
} else { } else {
value = src.ToFloat32(); value = Double(static_cast<double>(src.ToFloat32()));
} }
} else { } else {
int64_t val = src.ToFloat64AsInt(); value = Double(src.ToFloat64AsInt());
if ((val & 0x7f80000000000000) == 0x7f80000000000000) {
value = bit_cast<double, int64_t>(val);
} else {
value = src.ToFloat64();
}
} }
#else #else
value = (src.type() == Constant::kFloat32) ? src.ToFloat32() value = Double((src.type() == Constant::kFloat32)
: src.ToFloat64(); ? static_cast<double>(src.ToFloat32())
: src.ToFloat64());
#endif #endif
__ LoadDoubleLiteral(dst, value, kScratchReg); __ LoadDoubleLiteral(dst, value, kScratchReg);
if (destination->IsFPStackSlot()) { if (destination->IsFPStackSlot()) {

View File

@ -174,7 +174,9 @@ class Double {
static const int kMaxExponent = 0x7FF - kExponentBias; static const int kMaxExponent = 0x7FF - kExponentBias;
static const uint64_t kInfinity = V8_2PART_UINT64_C(0x7FF00000, 00000000); static const uint64_t kInfinity = V8_2PART_UINT64_C(0x7FF00000, 00000000);
const uint64_t d64_; // The field d64_ is not marked as const to permit the usage of the copy
// constructor.
uint64_t d64_;
static uint64_t DiyFpToUint64(DiyFp diy_fp) { static uint64_t DiyFpToUint64(DiyFp diy_fp) {
uint64_t significand = diy_fp.f(); uint64_t significand = diy_fp.f();

View File

@ -44,6 +44,7 @@
#include <vector> #include <vector>
#include "src/assembler.h" #include "src/assembler.h"
#include "src/double.h"
#include "src/ppc/constants-ppc.h" #include "src/ppc/constants-ppc.h"
#if V8_HOST_ARCH_PPC && \ #if V8_HOST_ARCH_PPC && \
@ -1374,7 +1375,7 @@ class Assembler : public AssemblerBase {
is_constant_pool_entry_sharing_blocked()); is_constant_pool_entry_sharing_blocked());
return constant_pool_builder_.AddEntry(pc_offset(), value, sharing_ok); return constant_pool_builder_.AddEntry(pc_offset(), value, sharing_ok);
} }
ConstantPoolEntry::Access ConstantPoolAddEntry(double value) { ConstantPoolEntry::Access ConstantPoolAddEntry(Double value) {
return constant_pool_builder_.AddEntry(pc_offset(), value); return constant_pool_builder_.AddEntry(pc_offset(), value);
} }

View File

@ -9,6 +9,7 @@
#include "src/base/bits.h" #include "src/base/bits.h"
#include "src/bootstrapper.h" #include "src/bootstrapper.h"
#include "src/codegen.h" #include "src/codegen.h"
#include "src/double.h"
#include "src/ic/handler-compiler.h" #include "src/ic/handler-compiler.h"
#include "src/ic/ic.h" #include "src/ic/ic.h"
#include "src/ic/stub-cache.h" #include "src/ic/stub-cache.h"
@ -1060,7 +1061,7 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// Save callee-saved double registers. // Save callee-saved double registers.
__ MultiPushDoubles(kCalleeSavedDoubles); __ MultiPushDoubles(kCalleeSavedDoubles);
// Set up the reserved register for 0.0. // Set up the reserved register for 0.0.
__ LoadDoubleLiteral(kDoubleRegZero, 0.0, r0); __ LoadDoubleLiteral(kDoubleRegZero, Double(0.0), r0);
// Push a frame with special values setup to mark it as an entry frame. // Push a frame with special values setup to mark it as an entry frame.
// r3: code entry // r3: code entry

View File

@ -3071,7 +3071,7 @@ void MacroAssembler::ClampDoubleToUint8(Register result_reg,
Label done; Label done;
Label in_bounds; Label in_bounds;
LoadDoubleLiteral(double_scratch, 0.0, result_reg); LoadDoubleLiteral(double_scratch, Double(0.0), result_reg);
fcmpu(input_reg, double_scratch); fcmpu(input_reg, double_scratch);
bgt(&above_zero); bgt(&above_zero);
@ -3081,7 +3081,7 @@ void MacroAssembler::ClampDoubleToUint8(Register result_reg,
// Double value is >= 255, return 255. // Double value is >= 255, return 255.
bind(&above_zero); bind(&above_zero);
LoadDoubleLiteral(double_scratch, 255.0, result_reg); LoadDoubleLiteral(double_scratch, Double(255.0), result_reg);
fcmpu(input_reg, double_scratch); fcmpu(input_reg, double_scratch);
ble(&in_bounds); ble(&in_bounds);
LoadIntLiteral(result_reg, 255); LoadIntLiteral(result_reg, 255);
@ -3191,8 +3191,7 @@ void MacroAssembler::LoadSmiLiteral(Register dst, Smi* smi) {
mov(dst, Operand(smi)); mov(dst, Operand(smi));
} }
void MacroAssembler::LoadDoubleLiteral(DoubleRegister result, Double value,
void MacroAssembler::LoadDoubleLiteral(DoubleRegister result, double value,
Register scratch) { Register scratch) {
if (FLAG_enable_embedded_constant_pool && is_constant_pool_available() && if (FLAG_enable_embedded_constant_pool && is_constant_pool_available() &&
!(scratch.is(r0) && ConstantPoolAccessIsInOverflow())) { !(scratch.is(r0) && ConstantPoolAccessIsInOverflow())) {
@ -3208,7 +3207,7 @@ void MacroAssembler::LoadDoubleLiteral(DoubleRegister result, double value,
// avoid gcc strict aliasing error using union cast // avoid gcc strict aliasing error using union cast
union { union {
double dval; uint64_t dval;
#if V8_TARGET_ARCH_PPC64 #if V8_TARGET_ARCH_PPC64
intptr_t ival; intptr_t ival;
#else #else
@ -3216,7 +3215,7 @@ void MacroAssembler::LoadDoubleLiteral(DoubleRegister result, double value,
#endif #endif
} litVal; } litVal;
litVal.dval = value; litVal.dval = value.AsUint64();
#if V8_TARGET_ARCH_PPC64 #if V8_TARGET_ARCH_PPC64
if (CpuFeatures::IsSupported(FPR_GPR_MOV)) { if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {

View File

@ -7,6 +7,7 @@
#include "src/assembler.h" #include "src/assembler.h"
#include "src/bailout-reason.h" #include "src/bailout-reason.h"
#include "src/double.h"
#include "src/frames.h" #include "src/frames.h"
#include "src/globals.h" #include "src/globals.h"
@ -494,7 +495,7 @@ class MacroAssembler : public Assembler {
void LoadSmiLiteral(Register dst, Smi* smi); void LoadSmiLiteral(Register dst, Smi* smi);
// load a literal double value <value> to FPR <result> // load a literal double value <value> to FPR <result>
void LoadDoubleLiteral(DoubleRegister result, double value, Register scratch); void LoadDoubleLiteral(DoubleRegister result, Double value, Register scratch);
void LoadWord(Register dst, const MemOperand& mem, Register scratch); void LoadWord(Register dst, const MemOperand& mem, Register scratch);
void LoadWordArith(Register dst, const MemOperand& mem, void LoadWordArith(Register dst, const MemOperand& mem,