x87: Use signaling NaN for holes in fixed double arrays.

Port 9eace97bba

BUG=
R=chunyang.dai@intel.com

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

Cr-Commit-Position: refs/heads/master@{#26445}
This commit is contained in:
Weiliang Lin 2015-02-05 10:54:13 +08:00
parent a18dee6bba
commit c397d2951f
4 changed files with 43 additions and 64 deletions

View File

@ -2001,10 +2001,9 @@ void LCodeGen::DoConstantS(LConstantS* instr) {
void LCodeGen::DoConstantD(LConstantD* instr) {
double v = instr->value();
uint64_t int_val = bit_cast<uint64_t, double>(v);
int32_t lower = static_cast<int32_t>(int_val);
int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
uint64_t const bits = instr->bits();
uint32_t const lower = static_cast<uint32_t>(bits);
uint32_t const upper = static_cast<uint32_t>(bits >> 32);
DCHECK(instr->result()->IsDoubleRegister());
__ push(Immediate(upper));
@ -2613,7 +2612,9 @@ void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
__ add(esp, Immediate(kDoubleSize));
int offset = sizeof(kHoleNanUpper32);
__ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32));
// x87 converts sNaN(0xfff7fffffff7ffff) to QNaN(0xfffffffffff7ffff),
// so we check the upper with 0xffffffff for hole as a temporary fix.
__ cmp(MemOperand(esp, -offset), Immediate(0xffffffff));
EmitBranch(instr, equal);
}
@ -4242,10 +4243,11 @@ void LCodeGen::DoMathLog(LMathLog* instr) {
__ jmp(&done, Label::kNear);
__ bind(&nan_result);
ExternalReference nan =
ExternalReference::address_of_canonical_non_hole_nan();
X87PrepareToWrite(input_reg);
__ fld_d(Operand::StaticVariable(nan));
__ push(Immediate(0xffffffff));
__ push(Immediate(0x7fffffff));
__ fld_d(MemOperand(esp, 0));
__ lea(esp, Operand(esp, kDoubleSize));
X87CommitWrite(input_reg);
__ jmp(&done, Label::kNear);
@ -4640,8 +4642,6 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
ExternalReference canonical_nan_reference =
ExternalReference::address_of_canonical_non_hole_nan();
Operand double_store_operand = BuildFastArrayOperand(
instr->elements(),
instr->key(),
@ -4649,25 +4649,21 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
FAST_DOUBLE_ELEMENTS,
instr->base_offset());
// Can't use SSE2 in the serializer
uint64_t int_val = kHoleNanInt64;
int32_t lower = static_cast<int32_t>(int_val);
int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
Operand double_store_operand2 = BuildFastArrayOperand(
instr->elements(), instr->key(),
instr->hydrogen()->key()->representation(), FAST_DOUBLE_ELEMENTS,
instr->base_offset() + kPointerSize);
if (instr->hydrogen()->IsConstantHoleStore()) {
// This means we should store the (double) hole. No floating point
// registers required.
double nan_double = FixedDoubleArray::hole_nan_as_double();
uint64_t int_val = bit_cast<uint64_t, double>(nan_double);
int32_t lower = static_cast<int32_t>(int_val);
int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
__ mov(double_store_operand, Immediate(lower));
Operand double_store_operand2 = BuildFastArrayOperand(
instr->elements(),
instr->key(),
instr->hydrogen()->key()->representation(),
FAST_DOUBLE_ELEMENTS,
instr->base_offset() + kPointerSize);
__ mov(double_store_operand2, Immediate(upper));
} else {
Label no_special_nan_handling;
Label no_special_nan_handling, done;
X87Register value = ToX87Register(instr->value());
X87Fxch(value);
@ -4675,23 +4671,27 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
__ fld(0);
__ fld(0);
__ FCmp();
__ j(parity_odd, &no_special_nan_handling, Label::kNear);
__ sub(esp, Immediate(kDoubleSize));
// All NaNs are Canonicalized to 0x7fffffffffffffff
__ mov(double_store_operand, Immediate(0xffffffff));
__ mov(double_store_operand2, Immediate(0x7fffffff));
__ jmp(&done, Label::kNear);
} else {
__ lea(esp, Operand(esp, -kDoubleSize));
__ fst_d(MemOperand(esp, 0));
__ cmp(MemOperand(esp, sizeof(kHoleNanLower32)),
Immediate(kHoleNanUpper32));
__ add(esp, Immediate(kDoubleSize));
Label canonicalize;
__ j(not_equal, &canonicalize, Label::kNear);
__ jmp(&no_special_nan_handling, Label::kNear);
__ bind(&canonicalize);
__ fstp(0);
__ fld_d(Operand::StaticVariable(canonical_nan_reference));
__ lea(esp, Operand(esp, kDoubleSize));
int offset = sizeof(kHoleNanUpper32);
// x87 converts sNaN(0xfff7fffffff7ffff) to QNaN(0xfffffffffff7ffff),
// so we check the upper with 0xffffffff for hole as a temporary fix.
__ cmp(MemOperand(esp, -offset), Immediate(0xffffffff));
__ j(not_equal, &no_special_nan_handling, Label::kNear);
__ mov(double_store_operand, Immediate(lower));
__ mov(double_store_operand2, Immediate(upper));
__ jmp(&done, Label::kNear);
}
__ bind(&no_special_nan_handling);
__ fst_d(double_store_operand);
__ bind(&done);
}
}
@ -5189,9 +5189,10 @@ void LCodeGen::EmitNumberUntagDNoSSE2(LNumberUntagD* instr, Register input_reg,
DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
__ bind(&convert);
ExternalReference nan =
ExternalReference::address_of_canonical_non_hole_nan();
__ fld_d(Operand::StaticVariable(nan));
__ push(Immediate(0xffffffff));
__ push(Immediate(0x7fffffff));
__ fld_d(MemOperand(esp, 0));
__ lea(esp, Operand(esp, kDoubleSize));
__ jmp(&done, Label::kNear);
__ bind(&heap_number);

View File

@ -1721,7 +1721,7 @@ LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
HCompareHoleAndBranch* instr) {
LOperand* value = UseRegisterAtStart(instr->value());
return new(zone()) LCmpHoleAndBranch(value);
return new (zone()) LCmpHoleAndBranch(value);
}

View File

@ -1350,7 +1350,7 @@ class LConstantD FINAL : public LTemplateInstruction<1, 0, 1> {
DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d")
DECLARE_HYDROGEN_ACCESSOR(Constant)
double value() const { return hydrogen()->DoubleValue(); }
uint64_t bits() const { return hydrogen()->DoubleValueAsBits(); }
};

View File

@ -597,30 +597,8 @@ void MacroAssembler::StoreNumberToDoubleElements(
fail,
DONT_DO_SMI_CHECK);
// Double value, canonicalize NaN.
uint32_t offset = HeapNumber::kValueOffset + sizeof(kHoleNanLower32);
cmp(FieldOperand(maybe_number, offset),
Immediate(kNaNOrInfinityLowerBoundUpper32));
j(greater_equal, &maybe_nan, Label::kNear);
bind(&not_nan);
ExternalReference canonical_nan_reference =
ExternalReference::address_of_canonical_non_hole_nan();
fld_d(FieldOperand(maybe_number, HeapNumber::kValueOffset));
bind(&have_double_value);
fstp_d(FieldOperand(elements, key, times_4,
FixedDoubleArray::kHeaderSize - elements_offset));
jmp(&done);
bind(&maybe_nan);
// Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
// it's an Infinity, and the non-NaN code path applies.
j(greater, &is_nan, Label::kNear);
cmp(FieldOperand(maybe_number, HeapNumber::kValueOffset), Immediate(0));
j(zero, &not_nan);
bind(&is_nan);
fld_d(Operand::StaticVariable(canonical_nan_reference));
jmp(&have_double_value, Label::kNear);
jmp(&done, Label::kNear);
bind(&smi_value);
// Value is a smi. Convert to a double and store.
@ -630,9 +608,9 @@ void MacroAssembler::StoreNumberToDoubleElements(
push(scratch);
fild_s(Operand(esp, 0));
pop(scratch);
bind(&done);
fstp_d(FieldOperand(elements, key, times_4,
FixedDoubleArray::kHeaderSize - elements_offset));
bind(&done);
}