Index: src/x64/macro-assembler-x64.cc |
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc |
index eb4b9f1f23718343029c3b1735e88f21edb602ae..7fe6d5821ea665ab722b4efd65eef3420b0fe1f1 100644 |
--- a/src/x64/macro-assembler-x64.cc |
+++ b/src/x64/macro-assembler-x64.cc |
@@ -2680,6 +2680,59 @@ void MacroAssembler::CheckFastSmiOnlyElements(Register map, |
} |
+void MacroAssembler::StoreNumberToDoubleElements( |
+ Register maybe_number, |
+ Register elements, |
+ Register key, |
+ XMMRegister xmm_scratch, |
+ Label* fail) { |
+ Label smi_value, is_nan, maybe_nan, not_nan, have_double_value, done; |
+ |
+ JumpIfSmi(maybe_number, &smi_value, Label::kNear); |
+ |
+ CheckMap(maybe_number, |
+ isolate()->factory()->heap_number_map(), |
+ fail, |
+ DONT_DO_SMI_CHECK); |
+ |
+ // Double value, canonicalize NaN. |
+ uint32_t offset = HeapNumber::kValueOffset + sizeof(kHoleNanLower32); |
+ cmpl(FieldOperand(maybe_number, offset), |
+ Immediate(kNaNOrInfinityLowerBoundUpper32)); |
+ j(greater_equal, &maybe_nan, Label::kNear); |
+ |
+ bind(¬_nan); |
+ movsd(xmm_scratch, FieldOperand(maybe_number, HeapNumber::kValueOffset)); |
+ bind(&have_double_value); |
+ movsd(FieldOperand(elements, key, times_8, FixedDoubleArray::kHeaderSize), |
+ xmm_scratch); |
+ 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); |
+ cmpl(FieldOperand(maybe_number, HeapNumber::kValueOffset), Immediate(0)); |
+ j(zero, ¬_nan); |
+ bind(&is_nan); |
+ // Convert all NaNs to the same canonical NaN value when they are stored in |
+ // the double array. |
+ Set(kScratchRegister, BitCast<uint64_t>( |
+ FixedDoubleArray::canonical_not_the_hole_nan_as_double())); |
+ movq(xmm_scratch, kScratchRegister); |
+ jmp(&have_double_value, Label::kNear); |
+ |
+ bind(&smi_value); |
+ // Value is a smi. convert to a double and store. |
+ // Preserve original value. |
+ SmiToInteger32(kScratchRegister, maybe_number); |
+ cvtlsi2sd(xmm_scratch, kScratchRegister); |
+ movsd(FieldOperand(elements, key, times_8, FixedDoubleArray::kHeaderSize), |
+ xmm_scratch); |
+ bind(&done); |
+} |
+ |
+ |
void MacroAssembler::CheckMap(Register obj, |
Handle<Map> map, |
Label* fail, |