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