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