OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 3577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3588 __ ret(0); | 3588 __ ret(0); |
3589 } else { | 3589 } else { |
3590 // Perform float-to-int conversion with truncation (round-to-zero) | 3590 // Perform float-to-int conversion with truncation (round-to-zero) |
3591 // behavior. | 3591 // behavior. |
3592 | 3592 |
3593 // For the moment we make the slow call to the runtime on | 3593 // For the moment we make the slow call to the runtime on |
3594 // processors that don't support SSE2. The code in IntegerConvert | 3594 // processors that don't support SSE2. The code in IntegerConvert |
3595 // (code-stubs-ia32.cc) is roughly what is needed here though the | 3595 // (code-stubs-ia32.cc) is roughly what is needed here though the |
3596 // conversion failure case does not need to be handled. | 3596 // conversion failure case does not need to be handled. |
3597 if (CpuFeatures::IsSupported(SSE2)) { | 3597 if (CpuFeatures::IsSupported(SSE2)) { |
3598 if (elements_kind != EXTERNAL_INT_ELEMENTS && | 3598 if ((elements_kind == EXTERNAL_INT_ELEMENTS || |
3599 elements_kind != EXTERNAL_UNSIGNED_INT_ELEMENTS) { | 3599 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) && |
| 3600 CpuFeatures::IsSupported(SSE3)) { |
| 3601 CpuFeatures::Scope scope(SSE3); |
| 3602 // fisttp stores values as signed integers. To represent the |
| 3603 // entire range of int and unsigned int arrays, store as a |
| 3604 // 64-bit int and discard the high 32 bits. |
| 3605 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 3606 __ sub(esp, Immediate(2 * kPointerSize)); |
| 3607 __ fisttp_d(Operand(esp, 0)); |
| 3608 |
| 3609 // If conversion failed (NaN, infinity, or a number outside |
| 3610 // signed int64 range), the result is 0x8000000000000000, and |
| 3611 // we must handle this case in the runtime. |
| 3612 Label ok; |
| 3613 __ cmp(Operand(esp, kPointerSize), Immediate(0x80000000u)); |
| 3614 __ j(not_equal, &ok); |
| 3615 __ cmp(Operand(esp, 0), Immediate(0)); |
| 3616 __ j(not_equal, &ok); |
| 3617 __ add(esp, Immediate(2 * kPointerSize)); // Restore the stack. |
| 3618 __ jmp(&slow); |
| 3619 |
| 3620 __ bind(&ok); |
| 3621 __ pop(ebx); |
| 3622 __ add(esp, Immediate(kPointerSize)); |
| 3623 __ mov(Operand(edi, ecx, times_2, 0), ebx); |
| 3624 } else { |
3600 ASSERT(CpuFeatures::IsSupported(SSE2)); | 3625 ASSERT(CpuFeatures::IsSupported(SSE2)); |
3601 CpuFeatures::Scope scope(SSE2); | 3626 CpuFeatures::Scope scope(SSE2); |
3602 __ cvttsd2si(ebx, FieldOperand(eax, HeapNumber::kValueOffset)); | 3627 __ cvttsd2si(ebx, FieldOperand(eax, HeapNumber::kValueOffset)); |
3603 // ecx: untagged integer value | 3628 __ cmp(ebx, 0x80000000u); |
| 3629 __ j(equal, &slow); |
| 3630 // ebx: untagged integer value |
3604 switch (elements_kind) { | 3631 switch (elements_kind) { |
3605 case EXTERNAL_PIXEL_ELEMENTS: | 3632 case EXTERNAL_PIXEL_ELEMENTS: |
3606 __ ClampUint8(ebx); | 3633 __ ClampUint8(ebx); |
3607 // Fall through. | 3634 // Fall through. |
3608 case EXTERNAL_BYTE_ELEMENTS: | 3635 case EXTERNAL_BYTE_ELEMENTS: |
3609 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3636 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
3610 __ SmiUntag(ecx); | 3637 __ SmiUntag(ecx); |
3611 __ mov_b(Operand(edi, ecx, times_1, 0), ebx); | 3638 __ mov_b(Operand(edi, ecx, times_1, 0), ebx); |
3612 break; | 3639 break; |
3613 case EXTERNAL_SHORT_ELEMENTS: | 3640 case EXTERNAL_SHORT_ELEMENTS: |
3614 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3641 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
3615 __ mov_w(Operand(edi, ecx, times_1, 0), ebx); | 3642 __ mov_w(Operand(edi, ecx, times_1, 0), ebx); |
3616 break; | 3643 break; |
| 3644 case EXTERNAL_INT_ELEMENTS: |
| 3645 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3646 __ mov(Operand(edi, ecx, times_2, 0), ebx); |
3617 default: | 3647 default: |
3618 UNREACHABLE(); | 3648 UNREACHABLE(); |
3619 break; | 3649 break; |
3620 } | 3650 } |
3621 } else { | |
3622 if (CpuFeatures::IsSupported(SSE3)) { | |
3623 CpuFeatures::Scope scope(SSE3); | |
3624 // fisttp stores values as signed integers. To represent the | |
3625 // entire range of int and unsigned int arrays, store as a | |
3626 // 64-bit int and discard the high 32 bits. | |
3627 // If the value is NaN or +/-infinity, the result is 0x80000000, | |
3628 // which is automatically zero when taken mod 2^n, n < 32. | |
3629 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | |
3630 __ sub(esp, Immediate(2 * kPointerSize)); | |
3631 __ fisttp_d(Operand(esp, 0)); | |
3632 __ pop(ebx); | |
3633 __ add(esp, Immediate(kPointerSize)); | |
3634 } else { | |
3635 ASSERT(CpuFeatures::IsSupported(SSE2)); | |
3636 CpuFeatures::Scope scope(SSE2); | |
3637 // We can easily implement the correct rounding behavior for the | |
3638 // range [0, 2^31-1]. For the time being, to keep this code simple, | |
3639 // make the slow runtime call for values outside this range. | |
3640 // Note: we could do better for signed int arrays. | |
3641 __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); | |
3642 // We will need the key if we have to make the slow runtime call. | |
3643 __ push(ebx); | |
3644 __ LoadPowerOf2(xmm1, ebx, 31); | |
3645 __ pop(ebx); | |
3646 __ ucomisd(xmm1, xmm0); | |
3647 __ j(above_equal, &slow); | |
3648 __ cvttsd2si(ebx, Operand(xmm0)); | |
3649 } | |
3650 // ebx: untagged integer value | |
3651 __ mov(Operand(edi, ecx, times_2, 0), ebx); | |
3652 } | 3651 } |
3653 __ ret(0); // Return original value. | 3652 __ ret(0); // Return original value. |
3654 } | 3653 } |
3655 } | 3654 } |
3656 } | 3655 } |
3657 | 3656 |
3658 // Slow case: call runtime. | 3657 // Slow case: call runtime. |
3659 __ bind(&slow); | 3658 __ bind(&slow); |
3660 Counters* counters = masm->isolate()->counters(); | 3659 Counters* counters = masm->isolate()->counters(); |
3661 __ IncrementCounter(counters->keyed_store_external_array_slow(), 1); | 3660 __ IncrementCounter(counters->keyed_store_external_array_slow(), 1); |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4067 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 4066 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
4068 } | 4067 } |
4069 } | 4068 } |
4070 | 4069 |
4071 | 4070 |
4072 #undef __ | 4071 #undef __ |
4073 | 4072 |
4074 } } // namespace v8::internal | 4073 } } // namespace v8::internal |
4075 | 4074 |
4076 #endif // V8_TARGET_ARCH_IA32 | 4075 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |