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));
__ 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);
}
__ 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);
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(),
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);
__ 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);
}
}
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);
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.
push(scratch);
fild_s(Operand(esp, 0));
pop(scratch);
+ bind(&done);
fstp_d(FieldOperand(elements, key, times_4,
FixedDoubleArray::kHeaderSize - elements_offset));
- bind(&done);
}