| Index: src/ia32/stub-cache-ia32.cc
|
| diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
|
| index 46de6a4fc1b8b527851d7eae0add0a025680d077..2629984c7666535bc33274b5e054a2c32ae47247 100644
|
| --- a/src/ia32/stub-cache-ia32.cc
|
| +++ b/src/ia32/stub-cache-ia32.cc
|
| @@ -3595,12 +3595,39 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
| // (code-stubs-ia32.cc) is roughly what is needed here though the
|
| // conversion failure case does not need to be handled.
|
| if (CpuFeatures::IsSupported(SSE2)) {
|
| - if (elements_kind != EXTERNAL_INT_ELEMENTS &&
|
| - elements_kind != EXTERNAL_UNSIGNED_INT_ELEMENTS) {
|
| + if ((elements_kind == EXTERNAL_INT_ELEMENTS ||
|
| + elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) &&
|
| + CpuFeatures::IsSupported(SSE3)) {
|
| + CpuFeatures::Scope scope(SSE3);
|
| + // fisttp stores values as signed integers. To represent the
|
| + // entire range of int and unsigned int arrays, store as a
|
| + // 64-bit int and discard the high 32 bits.
|
| + __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
|
| + __ sub(esp, Immediate(2 * kPointerSize));
|
| + __ fisttp_d(Operand(esp, 0));
|
| +
|
| + // If conversion failed (NaN, infinity, or a number outside
|
| + // signed int64 range), the result is 0x8000000000000000, and
|
| + // we must handle this case in the runtime.
|
| + Label ok;
|
| + __ cmp(Operand(esp, kPointerSize), Immediate(0x80000000u));
|
| + __ j(not_equal, &ok);
|
| + __ cmp(Operand(esp, 0), Immediate(0));
|
| + __ j(not_equal, &ok);
|
| + __ add(esp, Immediate(2 * kPointerSize)); // Restore the stack.
|
| + __ jmp(&slow);
|
| +
|
| + __ bind(&ok);
|
| + __ pop(ebx);
|
| + __ add(esp, Immediate(kPointerSize));
|
| + __ mov(Operand(edi, ecx, times_2, 0), ebx);
|
| + } else {
|
| ASSERT(CpuFeatures::IsSupported(SSE2));
|
| CpuFeatures::Scope scope(SSE2);
|
| __ cvttsd2si(ebx, FieldOperand(eax, HeapNumber::kValueOffset));
|
| - // ecx: untagged integer value
|
| + __ cmp(ebx, 0x80000000u);
|
| + __ j(equal, &slow);
|
| + // ebx: untagged integer value
|
| switch (elements_kind) {
|
| case EXTERNAL_PIXEL_ELEMENTS:
|
| __ ClampUint8(ebx);
|
| @@ -3614,41 +3641,13 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
| case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
| __ mov_w(Operand(edi, ecx, times_1, 0), ebx);
|
| break;
|
| + case EXTERNAL_INT_ELEMENTS:
|
| + case EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
| + __ mov(Operand(edi, ecx, times_2, 0), ebx);
|
| default:
|
| UNREACHABLE();
|
| break;
|
| }
|
| - } else {
|
| - if (CpuFeatures::IsSupported(SSE3)) {
|
| - CpuFeatures::Scope scope(SSE3);
|
| - // fisttp stores values as signed integers. To represent the
|
| - // entire range of int and unsigned int arrays, store as a
|
| - // 64-bit int and discard the high 32 bits.
|
| - // If the value is NaN or +/-infinity, the result is 0x80000000,
|
| - // which is automatically zero when taken mod 2^n, n < 32.
|
| - __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
|
| - __ sub(esp, Immediate(2 * kPointerSize));
|
| - __ fisttp_d(Operand(esp, 0));
|
| - __ pop(ebx);
|
| - __ add(esp, Immediate(kPointerSize));
|
| - } else {
|
| - ASSERT(CpuFeatures::IsSupported(SSE2));
|
| - CpuFeatures::Scope scope(SSE2);
|
| - // We can easily implement the correct rounding behavior for the
|
| - // range [0, 2^31-1]. For the time being, to keep this code simple,
|
| - // make the slow runtime call for values outside this range.
|
| - // Note: we could do better for signed int arrays.
|
| - __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
|
| - // We will need the key if we have to make the slow runtime call.
|
| - __ push(ebx);
|
| - __ LoadPowerOf2(xmm1, ebx, 31);
|
| - __ pop(ebx);
|
| - __ ucomisd(xmm1, xmm0);
|
| - __ j(above_equal, &slow);
|
| - __ cvttsd2si(ebx, Operand(xmm0));
|
| - }
|
| - // ebx: untagged integer value
|
| - __ mov(Operand(edi, ecx, times_2, 0), ebx);
|
| }
|
| __ ret(0); // Return original value.
|
| }
|
|
|