Chromium Code Reviews| 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 |