OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 3125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3136 __ Ret(); | 3136 __ Ret(); |
3137 | 3137 |
3138 __ bind(&miss); | 3138 __ bind(&miss); |
3139 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3139 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3140 | 3140 |
3141 // Return the generated code. | 3141 // Return the generated code. |
3142 return GetCode(NORMAL, NULL); | 3142 return GetCode(NORMAL, NULL); |
3143 } | 3143 } |
3144 | 3144 |
3145 | 3145 |
3146 MaybeObject* KeyedLoadStubCompiler::CompileLoadPixelArray(JSObject* receiver) { | |
3147 // ----------- S t a t e ------------- | |
3148 // -- lr : return address | |
3149 // -- r0 : key | |
3150 // -- r1 : receiver | |
3151 // ----------------------------------- | |
3152 Label miss; | |
3153 | |
3154 // Check that the map matches. | |
3155 __ CheckMap(r1, r2, Handle<Map>(receiver->map()), &miss, false); | |
3156 | |
3157 GenerateFastPixelArrayLoad(masm(), | |
3158 r1, | |
3159 r0, | |
3160 r2, | |
3161 r3, | |
3162 r4, | |
3163 r5, | |
3164 r0, | |
3165 &miss, | |
3166 &miss, | |
3167 &miss); | |
3168 | |
3169 __ bind(&miss); | |
3170 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Miss)); | |
3171 __ Jump(ic, RelocInfo::CODE_TARGET); | |
3172 | |
3173 // Return the generated code. | |
3174 return GetCode(NORMAL, NULL); | |
3175 } | |
3176 | |
3177 | |
3178 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, | 3146 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, |
3179 int index, | 3147 int index, |
3180 Map* transition, | 3148 Map* transition, |
3181 String* name) { | 3149 String* name) { |
3182 // ----------- S t a t e ------------- | 3150 // ----------- S t a t e ------------- |
3183 // -- r0 : value | 3151 // -- r0 : value |
3184 // -- r1 : name | 3152 // -- r1 : name |
3185 // -- r2 : receiver | 3153 // -- r2 : receiver |
3186 // -- lr : return address | 3154 // -- lr : return address |
3187 // ----------------------------------- | 3155 // ----------------------------------- |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3276 | 3244 |
3277 __ bind(&miss); | 3245 __ bind(&miss); |
3278 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); | 3246 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); |
3279 __ Jump(ic, RelocInfo::CODE_TARGET); | 3247 __ Jump(ic, RelocInfo::CODE_TARGET); |
3280 | 3248 |
3281 // Return the generated code. | 3249 // Return the generated code. |
3282 return GetCode(NORMAL, NULL); | 3250 return GetCode(NORMAL, NULL); |
3283 } | 3251 } |
3284 | 3252 |
3285 | 3253 |
3286 MaybeObject* KeyedStoreStubCompiler::CompileStorePixelArray( | |
3287 JSObject* receiver) { | |
3288 // ----------- S t a t e ------------- | |
3289 // -- r0 : value | |
3290 // -- r1 : key | |
3291 // -- r2 : receiver | |
3292 // -- r3 : scratch | |
3293 // -- r4 : scratch | |
3294 // -- r5 : scratch | |
3295 // -- r6 : scratch | |
3296 // -- lr : return address | |
3297 // ----------------------------------- | |
3298 Label miss; | |
3299 | |
3300 // Check that the map matches. | |
3301 __ CheckMap(r2, r6, Handle<Map>(receiver->map()), &miss, false); | |
3302 | |
3303 GenerateFastPixelArrayStore(masm(), | |
3304 r2, | |
3305 r1, | |
3306 r0, | |
3307 r3, | |
3308 r4, | |
3309 r5, | |
3310 r6, | |
3311 true, | |
3312 true, | |
3313 &miss, | |
3314 &miss, | |
3315 NULL, | |
3316 &miss); | |
3317 | |
3318 __ bind(&miss); | |
3319 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); | |
3320 __ Jump(ic, RelocInfo::CODE_TARGET); | |
3321 | |
3322 // Return the generated code. | |
3323 return GetCode(NORMAL, NULL); | |
3324 } | |
3325 | |
3326 | |
3327 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { | 3254 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { |
3328 // ----------- S t a t e ------------- | 3255 // ----------- S t a t e ------------- |
3329 // -- r0 : argc | 3256 // -- r0 : argc |
3330 // -- r1 : constructor | 3257 // -- r1 : constructor |
3331 // -- lr : return address | 3258 // -- lr : return address |
3332 // -- [sp] : last argument | 3259 // -- [sp] : last argument |
3333 // ----------------------------------- | 3260 // ----------------------------------- |
3334 Label generic_stub_call; | 3261 Label generic_stub_call; |
3335 | 3262 |
3336 // Use r7 for holding undefined which is used in several places below. | 3263 // Use r7 for holding undefined which is used in several places below. |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3481 return false; | 3408 return false; |
3482 | 3409 |
3483 default: | 3410 default: |
3484 UNREACHABLE(); | 3411 UNREACHABLE(); |
3485 return false; | 3412 return false; |
3486 } | 3413 } |
3487 } | 3414 } |
3488 | 3415 |
3489 | 3416 |
3490 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( | 3417 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( |
3491 ExternalArrayType array_type, Code::Flags flags) { | 3418 JSObject* receiver_object, |
| 3419 ExternalArrayType array_type, |
| 3420 Code::Flags flags) { |
3492 // ---------- S t a t e -------------- | 3421 // ---------- S t a t e -------------- |
3493 // -- lr : return address | 3422 // -- lr : return address |
3494 // -- r0 : key | 3423 // -- r0 : key |
3495 // -- r1 : receiver | 3424 // -- r1 : receiver |
3496 // ----------------------------------- | 3425 // ----------------------------------- |
3497 Label slow, failed_allocation; | 3426 Label slow, failed_allocation; |
3498 | 3427 |
3499 Register key = r0; | 3428 Register key = r0; |
3500 Register receiver = r1; | 3429 Register receiver = r1; |
3501 | 3430 |
3502 // Check that the object isn't a smi | 3431 // Check that the object isn't a smi |
3503 __ JumpIfSmi(receiver, &slow); | 3432 __ JumpIfSmi(receiver, &slow); |
3504 | 3433 |
3505 // Check that the key is a smi. | 3434 // Check that the key is a smi. |
3506 __ JumpIfNotSmi(key, &slow); | 3435 __ JumpIfNotSmi(key, &slow); |
3507 | 3436 |
3508 // Check that the object is a JS object. Load map into r2. | 3437 // Make sure that we've got the right map. |
3509 __ CompareObjectType(receiver, r2, r3, FIRST_JS_OBJECT_TYPE); | 3438 __ ldr(r2, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
3510 __ b(lt, &slow); | 3439 __ cmp(r2, Operand(Handle<Map>(receiver_object->map()))); |
3511 | |
3512 // Check that the receiver does not require access checks. We need | |
3513 // to check this explicitly since this generic stub does not perform | |
3514 // map checks. | |
3515 __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset)); | |
3516 __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded)); | |
3517 __ b(ne, &slow); | 3440 __ b(ne, &slow); |
3518 | 3441 |
3519 // Check that the elements array is the appropriate type of | |
3520 // ExternalArray. | |
3521 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 3442 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
3522 __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); | 3443 // r3: elements array |
3523 __ LoadRoot(ip, Heap::RootIndexForExternalArrayType(array_type)); | |
3524 __ cmp(r2, ip); | |
3525 __ b(ne, &slow); | |
3526 | 3444 |
3527 // Check that the index is in range. | 3445 // Check that the index is in range. |
3528 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); | 3446 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); |
3529 __ cmp(ip, Operand(key, ASR, kSmiTagSize)); | 3447 __ cmp(ip, Operand(key, ASR, kSmiTagSize)); |
3530 // Unsigned comparison catches both negative and too-large values. | 3448 // Unsigned comparison catches both negative and too-large values. |
3531 __ b(lo, &slow); | 3449 __ b(lo, &slow); |
3532 | 3450 |
3533 // r3: elements array | |
3534 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); | 3451 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); |
3535 // r3: base pointer of external storage | 3452 // r3: base pointer of external storage |
3536 | 3453 |
3537 // We are not untagging smi key and instead work with it | 3454 // We are not untagging smi key and instead work with it |
3538 // as if it was premultiplied by 2. | 3455 // as if it was premultiplied by 2. |
3539 ASSERT((kSmiTag == 0) && (kSmiTagSize == 1)); | 3456 ASSERT((kSmiTag == 0) && (kSmiTagSize == 1)); |
3540 | 3457 |
3541 Register value = r2; | 3458 Register value = r2; |
3542 switch (array_type) { | 3459 switch (array_type) { |
3543 case kExternalByteArray: | 3460 case kExternalByteArray: |
3544 __ ldrsb(value, MemOperand(r3, key, LSR, 1)); | 3461 __ ldrsb(value, MemOperand(r3, key, LSR, 1)); |
3545 break; | 3462 break; |
| 3463 case kExternalPixelArray: |
3546 case kExternalUnsignedByteArray: | 3464 case kExternalUnsignedByteArray: |
3547 __ ldrb(value, MemOperand(r3, key, LSR, 1)); | 3465 __ ldrb(value, MemOperand(r3, key, LSR, 1)); |
3548 break; | 3466 break; |
3549 case kExternalShortArray: | 3467 case kExternalShortArray: |
3550 __ ldrsh(value, MemOperand(r3, key, LSL, 0)); | 3468 __ ldrsh(value, MemOperand(r3, key, LSL, 0)); |
3551 break; | 3469 break; |
3552 case kExternalUnsignedShortArray: | 3470 case kExternalUnsignedShortArray: |
3553 __ ldrh(value, MemOperand(r3, key, LSL, 0)); | 3471 __ ldrh(value, MemOperand(r3, key, LSL, 0)); |
3554 break; | 3472 break; |
3555 case kExternalIntArray: | 3473 case kExternalIntArray: |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3761 | 3679 |
3762 __ Push(r1, r0); | 3680 __ Push(r1, r0); |
3763 | 3681 |
3764 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 3682 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
3765 | 3683 |
3766 return GetCode(flags); | 3684 return GetCode(flags); |
3767 } | 3685 } |
3768 | 3686 |
3769 | 3687 |
3770 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( | 3688 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( |
3771 ExternalArrayType array_type, Code::Flags flags) { | 3689 JSObject* receiver_object, |
| 3690 ExternalArrayType array_type, |
| 3691 Code::Flags flags) { |
3772 // ---------- S t a t e -------------- | 3692 // ---------- S t a t e -------------- |
3773 // -- r0 : value | 3693 // -- r0 : value |
3774 // -- r1 : key | 3694 // -- r1 : key |
3775 // -- r2 : receiver | 3695 // -- r2 : receiver |
3776 // -- lr : return address | 3696 // -- lr : return address |
3777 // ----------------------------------- | 3697 // ----------------------------------- |
3778 Label slow, check_heap_number; | 3698 Label slow, check_heap_number; |
3779 | 3699 |
3780 // Register usage. | 3700 // Register usage. |
3781 Register value = r0; | 3701 Register value = r0; |
3782 Register key = r1; | 3702 Register key = r1; |
3783 Register receiver = r2; | 3703 Register receiver = r2; |
3784 // r3 mostly holds the elements array or the destination external array. | 3704 // r3 mostly holds the elements array or the destination external array. |
3785 | 3705 |
3786 // Check that the object isn't a smi. | 3706 // Check that the object isn't a smi. |
3787 __ JumpIfSmi(receiver, &slow); | 3707 __ JumpIfSmi(receiver, &slow); |
3788 | 3708 |
3789 // Check that the object is a JS object. Load map into r3. | 3709 // Make sure that we've got the right map. |
3790 __ CompareObjectType(receiver, r3, r4, FIRST_JS_OBJECT_TYPE); | 3710 __ ldr(r3, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
3791 __ b(le, &slow); | 3711 __ cmp(r3, Operand(Handle<Map>(receiver_object->map()))); |
| 3712 __ b(ne, &slow); |
3792 | 3713 |
3793 // Check that the receiver does not require access checks. We need | 3714 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
3794 // to do this because this generic stub does not perform map checks. | |
3795 __ ldrb(ip, FieldMemOperand(r3, Map::kBitFieldOffset)); | |
3796 __ tst(ip, Operand(1 << Map::kIsAccessCheckNeeded)); | |
3797 __ b(ne, &slow); | |
3798 | 3715 |
3799 // Check that the key is a smi. | 3716 // Check that the key is a smi. |
3800 __ JumpIfNotSmi(key, &slow); | 3717 __ JumpIfNotSmi(key, &slow); |
3801 | 3718 |
3802 // Check that the elements array is the appropriate type of ExternalArray. | 3719 // Check that the index is in range |
3803 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 3720 __ SmiUntag(r4, key); |
3804 __ ldr(r4, FieldMemOperand(r3, HeapObject::kMapOffset)); | |
3805 __ LoadRoot(ip, Heap::RootIndexForExternalArrayType(array_type)); | |
3806 __ cmp(r4, ip); | |
3807 __ b(ne, &slow); | |
3808 | |
3809 // Check that the index is in range. | |
3810 __ mov(r4, Operand(key, ASR, kSmiTagSize)); // Untag the index. | |
3811 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); | 3721 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); |
3812 __ cmp(r4, ip); | 3722 __ cmp(r4, ip); |
3813 // Unsigned comparison catches both negative and too-large values. | 3723 // Unsigned comparison catches both negative and too-large values. |
3814 __ b(hs, &slow); | 3724 __ b(hs, &slow); |
3815 | 3725 |
3816 // Handle both smis and HeapNumbers in the fast path. Go to the | 3726 // Handle both smis and HeapNumbers in the fast path. Go to the |
3817 // runtime for all other kinds of values. | 3727 // runtime for all other kinds of values. |
3818 // r3: external array. | 3728 // r3: external array. |
3819 // r4: key (integer). | 3729 // r4: key (integer). |
3820 __ JumpIfNotSmi(value, &check_heap_number); | 3730 if (array_type == kExternalPixelArray) { |
3821 __ mov(r5, Operand(value, ASR, kSmiTagSize)); // Untag the value. | 3731 // Double to pixel conversion is only implemented in the runtime for now. |
| 3732 __ JumpIfNotSmi(value, &slow); |
| 3733 } else { |
| 3734 __ JumpIfNotSmi(value, &check_heap_number); |
| 3735 } |
| 3736 __ SmiUntag(r5, value); |
3822 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); | 3737 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); |
3823 | 3738 |
3824 // r3: base pointer of external storage. | 3739 // r3: base pointer of external storage. |
3825 // r4: key (integer). | 3740 // r4: key (integer). |
3826 // r5: value (integer). | 3741 // r5: value (integer). |
3827 switch (array_type) { | 3742 switch (array_type) { |
| 3743 case kExternalPixelArray: |
| 3744 // Clamp the value to [0..255]. |
| 3745 __ Usat(r5, 8, Operand(r5)); |
| 3746 __ strb(r5, MemOperand(r3, r4, LSL, 0)); |
| 3747 break; |
3828 case kExternalByteArray: | 3748 case kExternalByteArray: |
3829 case kExternalUnsignedByteArray: | 3749 case kExternalUnsignedByteArray: |
3830 __ strb(r5, MemOperand(r3, r4, LSL, 0)); | 3750 __ strb(r5, MemOperand(r3, r4, LSL, 0)); |
3831 break; | 3751 break; |
3832 case kExternalShortArray: | 3752 case kExternalShortArray: |
3833 case kExternalUnsignedShortArray: | 3753 case kExternalUnsignedShortArray: |
3834 __ strh(r5, MemOperand(r3, r4, LSL, 1)); | 3754 __ strh(r5, MemOperand(r3, r4, LSL, 1)); |
3835 break; | 3755 break; |
3836 case kExternalIntArray: | 3756 case kExternalIntArray: |
3837 case kExternalUnsignedIntArray: | 3757 case kExternalUnsignedIntArray: |
3838 __ str(r5, MemOperand(r3, r4, LSL, 2)); | 3758 __ str(r5, MemOperand(r3, r4, LSL, 2)); |
3839 break; | 3759 break; |
3840 case kExternalFloatArray: | 3760 case kExternalFloatArray: |
3841 // Perform int-to-float conversion and store to memory. | 3761 // Perform int-to-float conversion and store to memory. |
3842 StoreIntAsFloat(masm(), r3, r4, r5, r6, r7, r9); | 3762 StoreIntAsFloat(masm(), r3, r4, r5, r6, r7, r9); |
3843 break; | 3763 break; |
3844 default: | 3764 default: |
3845 UNREACHABLE(); | 3765 UNREACHABLE(); |
3846 break; | 3766 break; |
3847 } | 3767 } |
3848 | 3768 |
3849 // Entry registers are intact, r0 holds the value which is the return value. | 3769 // Entry registers are intact, r0 holds the value which is the return value. |
3850 __ Ret(); | 3770 __ Ret(); |
3851 | 3771 |
3852 | 3772 if (array_type != kExternalPixelArray) { |
3853 // r3: external array. | 3773 // r3: external array. |
3854 // r4: index (integer). | 3774 // r4: index (integer). |
3855 __ bind(&check_heap_number); | 3775 __ bind(&check_heap_number); |
3856 __ CompareObjectType(value, r5, r6, HEAP_NUMBER_TYPE); | 3776 __ CompareObjectType(value, r5, r6, HEAP_NUMBER_TYPE); |
3857 __ b(ne, &slow); | 3777 __ b(ne, &slow); |
3858 | 3778 |
3859 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); | 3779 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); |
3860 | 3780 |
3861 // r3: base pointer of external storage. | 3781 // r3: base pointer of external storage. |
3862 // r4: key (integer). | 3782 // r4: key (integer). |
3863 | 3783 |
3864 // The WebGL specification leaves the behavior of storing NaN and | 3784 // The WebGL specification leaves the behavior of storing NaN and |
3865 // +/-Infinity into integer arrays basically undefined. For more | 3785 // +/-Infinity into integer arrays basically undefined. For more |
3866 // reproducible behavior, convert these to zero. | 3786 // reproducible behavior, convert these to zero. |
3867 if (CpuFeatures::IsSupported(VFP3)) { | 3787 if (CpuFeatures::IsSupported(VFP3)) { |
3868 CpuFeatures::Scope scope(VFP3); | 3788 CpuFeatures::Scope scope(VFP3); |
3869 | 3789 |
3870 | 3790 |
3871 if (array_type == kExternalFloatArray) { | 3791 if (array_type == kExternalFloatArray) { |
3872 // vldr requires offset to be a multiple of 4 so we can not | 3792 // vldr requires offset to be a multiple of 4 so we can not |
3873 // include -kHeapObjectTag into it. | 3793 // include -kHeapObjectTag into it. |
3874 __ sub(r5, r0, Operand(kHeapObjectTag)); | 3794 __ sub(r5, r0, Operand(kHeapObjectTag)); |
3875 __ vldr(d0, r5, HeapNumber::kValueOffset); | 3795 __ vldr(d0, r5, HeapNumber::kValueOffset); |
3876 __ add(r5, r3, Operand(r4, LSL, 2)); | 3796 __ add(r5, r3, Operand(r4, LSL, 2)); |
3877 __ vcvt_f32_f64(s0, d0); | 3797 __ vcvt_f32_f64(s0, d0); |
3878 __ vstr(s0, r5, 0); | 3798 __ vstr(s0, r5, 0); |
3879 } else { | |
3880 // Need to perform float-to-int conversion. | |
3881 // Test for NaN or infinity (both give zero). | |
3882 __ ldr(r6, FieldMemOperand(value, HeapNumber::kExponentOffset)); | |
3883 | |
3884 // Hoisted load. vldr requires offset to be a multiple of 4 so we can not | |
3885 // include -kHeapObjectTag into it. | |
3886 __ sub(r5, value, Operand(kHeapObjectTag)); | |
3887 __ vldr(d0, r5, HeapNumber::kValueOffset); | |
3888 | |
3889 __ Sbfx(r6, r6, HeapNumber::kExponentShift, HeapNumber::kExponentBits); | |
3890 // NaNs and Infinities have all-one exponents so they sign extend to -1. | |
3891 __ cmp(r6, Operand(-1)); | |
3892 __ mov(r5, Operand(0), LeaveCC, eq); | |
3893 | |
3894 // Not infinity or NaN simply convert to int. | |
3895 if (IsElementTypeSigned(array_type)) { | |
3896 __ vcvt_s32_f64(s0, d0, kDefaultRoundToZero, ne); | |
3897 } else { | 3799 } else { |
3898 __ vcvt_u32_f64(s0, d0, kDefaultRoundToZero, ne); | 3800 // Need to perform float-to-int conversion. |
| 3801 // Test for NaN or infinity (both give zero). |
| 3802 __ ldr(r6, FieldMemOperand(value, HeapNumber::kExponentOffset)); |
| 3803 |
| 3804 // Hoisted load. vldr requires offset to be a multiple of 4 so we can |
| 3805 // not include -kHeapObjectTag into it. |
| 3806 __ sub(r5, value, Operand(kHeapObjectTag)); |
| 3807 __ vldr(d0, r5, HeapNumber::kValueOffset); |
| 3808 |
| 3809 __ Sbfx(r6, r6, HeapNumber::kExponentShift, HeapNumber::kExponentBits); |
| 3810 // NaNs and Infinities have all-one exponents so they sign extend to -1. |
| 3811 __ cmp(r6, Operand(-1)); |
| 3812 __ mov(r5, Operand(0), LeaveCC, eq); |
| 3813 |
| 3814 // Not infinity or NaN simply convert to int. |
| 3815 if (IsElementTypeSigned(array_type)) { |
| 3816 __ vcvt_s32_f64(s0, d0, kDefaultRoundToZero, ne); |
| 3817 } else { |
| 3818 __ vcvt_u32_f64(s0, d0, kDefaultRoundToZero, ne); |
| 3819 } |
| 3820 __ vmov(r5, s0, ne); |
| 3821 |
| 3822 switch (array_type) { |
| 3823 case kExternalByteArray: |
| 3824 case kExternalUnsignedByteArray: |
| 3825 __ strb(r5, MemOperand(r3, r4, LSL, 0)); |
| 3826 break; |
| 3827 case kExternalShortArray: |
| 3828 case kExternalUnsignedShortArray: |
| 3829 __ strh(r5, MemOperand(r3, r4, LSL, 1)); |
| 3830 break; |
| 3831 case kExternalIntArray: |
| 3832 case kExternalUnsignedIntArray: |
| 3833 __ str(r5, MemOperand(r3, r4, LSL, 2)); |
| 3834 break; |
| 3835 default: |
| 3836 UNREACHABLE(); |
| 3837 break; |
| 3838 } |
3899 } | 3839 } |
3900 __ vmov(r5, s0, ne); | 3840 |
3901 | |
3902 switch (array_type) { | |
3903 case kExternalByteArray: | |
3904 case kExternalUnsignedByteArray: | |
3905 __ strb(r5, MemOperand(r3, r4, LSL, 0)); | |
3906 break; | |
3907 case kExternalShortArray: | |
3908 case kExternalUnsignedShortArray: | |
3909 __ strh(r5, MemOperand(r3, r4, LSL, 1)); | |
3910 break; | |
3911 case kExternalIntArray: | |
3912 case kExternalUnsignedIntArray: | |
3913 __ str(r5, MemOperand(r3, r4, LSL, 2)); | |
3914 break; | |
3915 default: | |
3916 UNREACHABLE(); | |
3917 break; | |
3918 } | |
3919 } | |
3920 | |
3921 // Entry registers are intact, r0 holds the value which is the return value. | |
3922 __ Ret(); | |
3923 } else { | |
3924 // VFP3 is not available do manual conversions. | |
3925 __ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset)); | |
3926 __ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset)); | |
3927 | |
3928 if (array_type == kExternalFloatArray) { | |
3929 Label done, nan_or_infinity_or_zero; | |
3930 static const int kMantissaInHiWordShift = | |
3931 kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord; | |
3932 | |
3933 static const int kMantissaInLoWordShift = | |
3934 kBitsPerInt - kMantissaInHiWordShift; | |
3935 | |
3936 // Test for all special exponent values: zeros, subnormal numbers, NaNs | |
3937 // and infinities. All these should be converted to 0. | |
3938 __ mov(r7, Operand(HeapNumber::kExponentMask)); | |
3939 __ and_(r9, r5, Operand(r7), SetCC); | |
3940 __ b(eq, &nan_or_infinity_or_zero); | |
3941 | |
3942 __ teq(r9, Operand(r7)); | |
3943 __ mov(r9, Operand(kBinary32ExponentMask), LeaveCC, eq); | |
3944 __ b(eq, &nan_or_infinity_or_zero); | |
3945 | |
3946 // Rebias exponent. | |
3947 __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift)); | |
3948 __ add(r9, | |
3949 r9, | |
3950 Operand(kBinary32ExponentBias - HeapNumber::kExponentBias)); | |
3951 | |
3952 __ cmp(r9, Operand(kBinary32MaxExponent)); | |
3953 __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, gt); | |
3954 __ orr(r5, r5, Operand(kBinary32ExponentMask), LeaveCC, gt); | |
3955 __ b(gt, &done); | |
3956 | |
3957 __ cmp(r9, Operand(kBinary32MinExponent)); | |
3958 __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, lt); | |
3959 __ b(lt, &done); | |
3960 | |
3961 __ and_(r7, r5, Operand(HeapNumber::kSignMask)); | |
3962 __ and_(r5, r5, Operand(HeapNumber::kMantissaMask)); | |
3963 __ orr(r7, r7, Operand(r5, LSL, kMantissaInHiWordShift)); | |
3964 __ orr(r7, r7, Operand(r6, LSR, kMantissaInLoWordShift)); | |
3965 __ orr(r5, r7, Operand(r9, LSL, kBinary32ExponentShift)); | |
3966 | |
3967 __ bind(&done); | |
3968 __ str(r5, MemOperand(r3, r4, LSL, 2)); | |
3969 // Entry registers are intact, r0 holds the value which is the return | 3841 // Entry registers are intact, r0 holds the value which is the return |
3970 // value. | 3842 // value. |
3971 __ Ret(); | 3843 __ Ret(); |
3972 | |
3973 __ bind(&nan_or_infinity_or_zero); | |
3974 __ and_(r7, r5, Operand(HeapNumber::kSignMask)); | |
3975 __ and_(r5, r5, Operand(HeapNumber::kMantissaMask)); | |
3976 __ orr(r9, r9, r7); | |
3977 __ orr(r9, r9, Operand(r5, LSL, kMantissaInHiWordShift)); | |
3978 __ orr(r5, r9, Operand(r6, LSR, kMantissaInLoWordShift)); | |
3979 __ b(&done); | |
3980 } else { | 3844 } else { |
3981 bool is_signed_type = IsElementTypeSigned(array_type); | 3845 // VFP3 is not available do manual conversions. |
3982 int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt; | 3846 __ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset)); |
3983 int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000; | 3847 __ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset)); |
3984 | 3848 |
3985 Label done, sign; | 3849 if (array_type == kExternalFloatArray) { |
3986 | 3850 Label done, nan_or_infinity_or_zero; |
3987 // Test for all special exponent values: zeros, subnormal numbers, NaNs | 3851 static const int kMantissaInHiWordShift = |
3988 // and infinities. All these should be converted to 0. | 3852 kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord; |
3989 __ mov(r7, Operand(HeapNumber::kExponentMask)); | 3853 |
3990 __ and_(r9, r5, Operand(r7), SetCC); | 3854 static const int kMantissaInLoWordShift = |
3991 __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq); | 3855 kBitsPerInt - kMantissaInHiWordShift; |
3992 __ b(eq, &done); | 3856 |
3993 | 3857 // Test for all special exponent values: zeros, subnormal numbers, NaNs |
3994 __ teq(r9, Operand(r7)); | 3858 // and infinities. All these should be converted to 0. |
3995 __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq); | 3859 __ mov(r7, Operand(HeapNumber::kExponentMask)); |
3996 __ b(eq, &done); | 3860 __ and_(r9, r5, Operand(r7), SetCC); |
3997 | 3861 __ b(eq, &nan_or_infinity_or_zero); |
3998 // Unbias exponent. | 3862 |
3999 __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift)); | 3863 __ teq(r9, Operand(r7)); |
4000 __ sub(r9, r9, Operand(HeapNumber::kExponentBias), SetCC); | 3864 __ mov(r9, Operand(kBinary32ExponentMask), LeaveCC, eq); |
4001 // If exponent is negative then result is 0. | 3865 __ b(eq, &nan_or_infinity_or_zero); |
4002 __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, mi); | 3866 |
4003 __ b(mi, &done); | 3867 // Rebias exponent. |
4004 | 3868 __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift)); |
4005 // If exponent is too big then result is minimal value. | 3869 __ add(r9, |
4006 __ cmp(r9, Operand(meaningfull_bits - 1)); | 3870 r9, |
4007 __ mov(r5, Operand(min_value), LeaveCC, ge); | 3871 Operand(kBinary32ExponentBias - HeapNumber::kExponentBias)); |
4008 __ b(ge, &done); | 3872 |
4009 | 3873 __ cmp(r9, Operand(kBinary32MaxExponent)); |
4010 __ and_(r7, r5, Operand(HeapNumber::kSignMask), SetCC); | 3874 __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, gt); |
4011 __ and_(r5, r5, Operand(HeapNumber::kMantissaMask)); | 3875 __ orr(r5, r5, Operand(kBinary32ExponentMask), LeaveCC, gt); |
4012 __ orr(r5, r5, Operand(1u << HeapNumber::kMantissaBitsInTopWord)); | 3876 __ b(gt, &done); |
4013 | 3877 |
4014 __ rsb(r9, r9, Operand(HeapNumber::kMantissaBitsInTopWord), SetCC); | 3878 __ cmp(r9, Operand(kBinary32MinExponent)); |
4015 __ mov(r5, Operand(r5, LSR, r9), LeaveCC, pl); | 3879 __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, lt); |
4016 __ b(pl, &sign); | 3880 __ b(lt, &done); |
4017 | 3881 |
4018 __ rsb(r9, r9, Operand(0, RelocInfo::NONE)); | 3882 __ and_(r7, r5, Operand(HeapNumber::kSignMask)); |
4019 __ mov(r5, Operand(r5, LSL, r9)); | 3883 __ and_(r5, r5, Operand(HeapNumber::kMantissaMask)); |
4020 __ rsb(r9, r9, Operand(meaningfull_bits)); | 3884 __ orr(r7, r7, Operand(r5, LSL, kMantissaInHiWordShift)); |
4021 __ orr(r5, r5, Operand(r6, LSR, r9)); | 3885 __ orr(r7, r7, Operand(r6, LSR, kMantissaInLoWordShift)); |
4022 | 3886 __ orr(r5, r7, Operand(r9, LSL, kBinary32ExponentShift)); |
4023 __ bind(&sign); | 3887 |
4024 __ teq(r7, Operand(0, RelocInfo::NONE)); | 3888 __ bind(&done); |
4025 __ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne); | 3889 __ str(r5, MemOperand(r3, r4, LSL, 2)); |
4026 | 3890 // Entry registers are intact, r0 holds the value which is the return |
4027 __ bind(&done); | 3891 // value. |
4028 switch (array_type) { | 3892 __ Ret(); |
4029 case kExternalByteArray: | 3893 |
4030 case kExternalUnsignedByteArray: | 3894 __ bind(&nan_or_infinity_or_zero); |
4031 __ strb(r5, MemOperand(r3, r4, LSL, 0)); | 3895 __ and_(r7, r5, Operand(HeapNumber::kSignMask)); |
4032 break; | 3896 __ and_(r5, r5, Operand(HeapNumber::kMantissaMask)); |
4033 case kExternalShortArray: | 3897 __ orr(r9, r9, r7); |
4034 case kExternalUnsignedShortArray: | 3898 __ orr(r9, r9, Operand(r5, LSL, kMantissaInHiWordShift)); |
4035 __ strh(r5, MemOperand(r3, r4, LSL, 1)); | 3899 __ orr(r5, r9, Operand(r6, LSR, kMantissaInLoWordShift)); |
4036 break; | 3900 __ b(&done); |
4037 case kExternalIntArray: | 3901 } else { |
4038 case kExternalUnsignedIntArray: | 3902 bool is_signed_type = IsElementTypeSigned(array_type); |
4039 __ str(r5, MemOperand(r3, r4, LSL, 2)); | 3903 int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt; |
4040 break; | 3904 int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000; |
4041 default: | 3905 |
4042 UNREACHABLE(); | 3906 Label done, sign; |
4043 break; | 3907 |
| 3908 // Test for all special exponent values: zeros, subnormal numbers, NaNs |
| 3909 // and infinities. All these should be converted to 0. |
| 3910 __ mov(r7, Operand(HeapNumber::kExponentMask)); |
| 3911 __ and_(r9, r5, Operand(r7), SetCC); |
| 3912 __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq); |
| 3913 __ b(eq, &done); |
| 3914 |
| 3915 __ teq(r9, Operand(r7)); |
| 3916 __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq); |
| 3917 __ b(eq, &done); |
| 3918 |
| 3919 // Unbias exponent. |
| 3920 __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift)); |
| 3921 __ sub(r9, r9, Operand(HeapNumber::kExponentBias), SetCC); |
| 3922 // If exponent is negative then result is 0. |
| 3923 __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, mi); |
| 3924 __ b(mi, &done); |
| 3925 |
| 3926 // If exponent is too big then result is minimal value. |
| 3927 __ cmp(r9, Operand(meaningfull_bits - 1)); |
| 3928 __ mov(r5, Operand(min_value), LeaveCC, ge); |
| 3929 __ b(ge, &done); |
| 3930 |
| 3931 __ and_(r7, r5, Operand(HeapNumber::kSignMask), SetCC); |
| 3932 __ and_(r5, r5, Operand(HeapNumber::kMantissaMask)); |
| 3933 __ orr(r5, r5, Operand(1u << HeapNumber::kMantissaBitsInTopWord)); |
| 3934 |
| 3935 __ rsb(r9, r9, Operand(HeapNumber::kMantissaBitsInTopWord), SetCC); |
| 3936 __ mov(r5, Operand(r5, LSR, r9), LeaveCC, pl); |
| 3937 __ b(pl, &sign); |
| 3938 |
| 3939 __ rsb(r9, r9, Operand(0, RelocInfo::NONE)); |
| 3940 __ mov(r5, Operand(r5, LSL, r9)); |
| 3941 __ rsb(r9, r9, Operand(meaningfull_bits)); |
| 3942 __ orr(r5, r5, Operand(r6, LSR, r9)); |
| 3943 |
| 3944 __ bind(&sign); |
| 3945 __ teq(r7, Operand(0, RelocInfo::NONE)); |
| 3946 __ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne); |
| 3947 |
| 3948 __ bind(&done); |
| 3949 switch (array_type) { |
| 3950 case kExternalByteArray: |
| 3951 case kExternalUnsignedByteArray: |
| 3952 __ strb(r5, MemOperand(r3, r4, LSL, 0)); |
| 3953 break; |
| 3954 case kExternalShortArray: |
| 3955 case kExternalUnsignedShortArray: |
| 3956 __ strh(r5, MemOperand(r3, r4, LSL, 1)); |
| 3957 break; |
| 3958 case kExternalIntArray: |
| 3959 case kExternalUnsignedIntArray: |
| 3960 __ str(r5, MemOperand(r3, r4, LSL, 2)); |
| 3961 break; |
| 3962 default: |
| 3963 UNREACHABLE(); |
| 3964 break; |
| 3965 } |
4044 } | 3966 } |
4045 } | 3967 } |
4046 } | 3968 } |
4047 | 3969 |
4048 // Slow case: call runtime. | 3970 // Slow case: call runtime. |
4049 __ bind(&slow); | 3971 __ bind(&slow); |
4050 | 3972 |
4051 // Entry registers are intact. | 3973 // Entry registers are intact. |
4052 // ---------- S t a t e -------------- | 3974 // ---------- S t a t e -------------- |
4053 // -- r0 : value | 3975 // -- r0 : value |
(...skipping 14 matching lines...) Expand all Loading... |
4068 | 3990 |
4069 return GetCode(flags); | 3991 return GetCode(flags); |
4070 } | 3992 } |
4071 | 3993 |
4072 | 3994 |
4073 #undef __ | 3995 #undef __ |
4074 | 3996 |
4075 } } // namespace v8::internal | 3997 } } // namespace v8::internal |
4076 | 3998 |
4077 #endif // V8_TARGET_ARCH_ARM | 3999 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |