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:
parent
a18dee6bba
commit
c397d2951f
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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(); }
|
||||
};
|
||||
|
||||
|
||||
|
@ -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(¬_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, ¬_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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user