| 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 |