| Index: src/x64/ic-x64.cc
|
| diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc
|
| index e17ff1fa4ba50315fb2d071e732e8d6ed0f86d56..31a806a36beed98c6ea7719b6891c190b9070c0c 100644
|
| --- a/src/x64/ic-x64.cc
|
| +++ b/src/x64/ic-x64.cc
|
| @@ -791,7 +791,6 @@ void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm,
|
|
|
| // Allocate a HeapNumber for the int and perform int-to-double
|
| // conversion.
|
| - ASSERT(array_type == kExternalUnsignedIntArray);
|
| // The value is zero-extended since we loaded the value from memory
|
| // with movl.
|
| __ cvtqsi2sd(xmm0, rcx);
|
| @@ -1121,55 +1120,41 @@ void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
|
| // The WebGL specification leaves the behavior of storing NaN and
|
| // +/-Infinity into integer arrays basically undefined. For more
|
| // reproducible behavior, convert these to zero.
|
| - __ fld_d(FieldOperand(rax, HeapNumber::kValueOffset));
|
| + __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
|
| __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
|
| // rdi: untagged index
|
| // rbx: base pointer of external storage
|
| // top of FPU stack: value
|
| if (array_type == kExternalFloatArray) {
|
| - __ fstp_s(Operand(rbx, rdi, times_4, 0));
|
| + __ cvtsd2ss(xmm0, xmm0);
|
| + __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
|
| __ ret(0);
|
| } else {
|
| // Need to perform float-to-int conversion.
|
| - // Test the top of the FP stack for NaN.
|
| - Label is_nan;
|
| - __ fucomi(0);
|
| - __ j(parity_even, &is_nan);
|
| -
|
| - __ push(rdx); // Make room on the stack. Receiver is no longer needed.
|
| - // TODO(lrn): If the rounding of this conversion is not deliberate, maybe
|
| - // switch to xmm registers.
|
| - __ fistp_d(Operand(rsp, 0));
|
| - __ pop(rdx);
|
| + // Test the value for NaN.
|
| +
|
| + // Convert to int32 and store the low byte/word.
|
| + // If the value is NaN or +/-infinity, the result is 0x80000000,
|
| + // which is automatically zero when taken mod 2^n, n < 32.
|
| // rdx: value (converted to an untagged integer)
|
| // rdi: untagged index
|
| // rbx: base pointer of external storage
|
| switch (array_type) {
|
| case kExternalByteArray:
|
| case kExternalUnsignedByteArray:
|
| + __ cvtsd2si(rdx, xmm0);
|
| __ movb(Operand(rbx, rdi, times_1, 0), rdx);
|
| break;
|
| case kExternalShortArray:
|
| case kExternalUnsignedShortArray:
|
| + __ cvtsd2si(rdx, xmm0);
|
| __ movw(Operand(rbx, rdi, times_2, 0), rdx);
|
| break;
|
| case kExternalIntArray:
|
| case kExternalUnsignedIntArray: {
|
| - // We also need to explicitly check for +/-Infinity. These are
|
| - // converted to MIN_INT, but we need to be careful not to
|
| - // confuse with legal uses of MIN_INT. Since MIN_INT truncated
|
| - // to 8 or 16 bits is zero, we only perform this test when storing
|
| - // 32-bit ints.
|
| - Label not_infinity;
|
| - // This test would apparently detect both NaN and Infinity,
|
| - // but we've already checked for NaN using the FPU hardware
|
| - // above.
|
| - __ movzxwq(rcx, FieldOperand(rax, HeapNumber::kValueOffset + 6));
|
| - __ and_(rcx, Immediate(0x7FF0));
|
| - __ cmpw(rcx, Immediate(0x7FF0));
|
| - __ j(not_equal, ¬_infinity);
|
| - __ movq(rdx, Immediate(0));
|
| - __ bind(¬_infinity);
|
| + // Convert to int64, so that NaN and infinities become
|
| + // 0x8000000000000000, which is zero mod 2^32.
|
| + __ cvtsd2siq(rdx, xmm0);
|
| __ movl(Operand(rbx, rdi, times_4, 0), rdx);
|
| break;
|
| }
|
| @@ -1178,31 +1163,6 @@ void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
|
| break;
|
| }
|
| __ ret(0);
|
| -
|
| - __ bind(&is_nan);
|
| - // rdi: untagged index
|
| - // rbx: base pointer of external storage
|
| - __ ffree();
|
| - __ fincstp();
|
| - __ Set(rdx, 0);
|
| - switch (array_type) {
|
| - case kExternalByteArray:
|
| - case kExternalUnsignedByteArray:
|
| - __ movb(Operand(rbx, rdi, times_1, 0), rdx);
|
| - break;
|
| - case kExternalShortArray:
|
| - case kExternalUnsignedShortArray:
|
| - __ movw(Operand(rbx, rdi, times_2, 0), rdx);
|
| - break;
|
| - case kExternalIntArray:
|
| - case kExternalUnsignedIntArray:
|
| - __ movl(Operand(rbx, rdi, times_4, 0), rdx);
|
| - break;
|
| - default:
|
| - UNREACHABLE();
|
| - break;
|
| - }
|
| - __ ret(0);
|
| }
|
|
|
| // Slow case: call runtime.
|
|
|