OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 3283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3294 // -- edx : receiver | 3294 // -- edx : receiver |
3295 // -- esp[0] : return address | 3295 // -- esp[0] : return address |
3296 // ----------------------------------- | 3296 // ----------------------------------- |
3297 | 3297 |
3298 Handle<Code> miss_force_generic_ic = | 3298 Handle<Code> miss_force_generic_ic = |
3299 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | 3299 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
3300 __ jmp(miss_force_generic_ic, RelocInfo::CODE_TARGET); | 3300 __ jmp(miss_force_generic_ic, RelocInfo::CODE_TARGET); |
3301 } | 3301 } |
3302 | 3302 |
3303 | 3303 |
| 3304 static void GenerateSmiKeyCheck(MacroAssembler* masm, |
| 3305 Register key, |
| 3306 Register scratch, |
| 3307 XMMRegister xmm_scratch0, |
| 3308 XMMRegister xmm_scratch1, |
| 3309 Label* fail) { |
| 3310 // Check that key is a smi and if SSE2 is available a heap number |
| 3311 // containing a smi and branch if the check fails. |
| 3312 if (CpuFeatures::IsSupported(SSE2)) { |
| 3313 CpuFeatures::Scope use_sse2(SSE2); |
| 3314 Label key_ok; |
| 3315 __ JumpIfSmi(key, &key_ok); |
| 3316 __ cmp(FieldOperand(key, HeapObject::kMapOffset), |
| 3317 Immediate(Handle<Map>(masm->isolate()->heap()->heap_number_map()))); |
| 3318 __ j(not_equal, fail); |
| 3319 __ movdbl(xmm_scratch0, FieldOperand(key, HeapNumber::kValueOffset)); |
| 3320 __ cvttsd2si(scratch, Operand(xmm_scratch0)); |
| 3321 __ cvtsi2sd(xmm_scratch1, scratch); |
| 3322 __ ucomisd(xmm_scratch1, xmm_scratch0); |
| 3323 __ j(not_equal, fail); |
| 3324 __ j(parity_even, fail); // NaN. |
| 3325 // Check if the key fits in the smi range. |
| 3326 __ cmp(scratch, 0xc0000000); |
| 3327 __ j(sign, fail); |
| 3328 __ SmiTag(scratch); |
| 3329 __ mov(key, scratch); |
| 3330 __ bind(&key_ok); |
| 3331 } else { |
| 3332 __ JumpIfNotSmi(key, fail); |
| 3333 } |
| 3334 } |
| 3335 |
| 3336 |
3304 void KeyedLoadStubCompiler::GenerateLoadExternalArray( | 3337 void KeyedLoadStubCompiler::GenerateLoadExternalArray( |
3305 MacroAssembler* masm, | 3338 MacroAssembler* masm, |
3306 ElementsKind elements_kind) { | 3339 ElementsKind elements_kind) { |
3307 // ----------- S t a t e ------------- | 3340 // ----------- S t a t e ------------- |
3308 // -- eax : key | 3341 // -- eax : key |
3309 // -- edx : receiver | 3342 // -- edx : receiver |
3310 // -- esp[0] : return address | 3343 // -- esp[0] : return address |
3311 // ----------------------------------- | 3344 // ----------------------------------- |
3312 Label miss_force_generic, failed_allocation, slow; | 3345 Label miss_force_generic, failed_allocation, slow; |
3313 | 3346 |
3314 // This stub is meant to be tail-jumped to, the receiver must already | 3347 // This stub is meant to be tail-jumped to, the receiver must already |
3315 // have been verified by the caller to not be a smi. | 3348 // have been verified by the caller to not be a smi. |
3316 | 3349 |
3317 // Check that the key is a smi. | 3350 // Check that the key is a smi or a heap number convertible to a smi. |
3318 __ JumpIfNotSmi(eax, &miss_force_generic); | 3351 GenerateSmiKeyCheck(masm, eax, ecx, xmm0, xmm1, &miss_force_generic); |
3319 | 3352 |
3320 // Check that the index is in range. | 3353 // Check that the index is in range. |
3321 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); | 3354 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); |
3322 __ cmp(eax, FieldOperand(ebx, ExternalArray::kLengthOffset)); | 3355 __ cmp(eax, FieldOperand(ebx, ExternalArray::kLengthOffset)); |
3323 // Unsigned comparison catches both negative and too-large values. | 3356 // Unsigned comparison catches both negative and too-large values. |
3324 __ j(above_equal, &miss_force_generic); | 3357 __ j(above_equal, &miss_force_generic); |
3325 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); | 3358 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); |
3326 // ebx: base pointer of external storage | 3359 // ebx: base pointer of external storage |
3327 switch (elements_kind) { | 3360 switch (elements_kind) { |
3328 case EXTERNAL_BYTE_ELEMENTS: | 3361 case EXTERNAL_BYTE_ELEMENTS: |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3360 // For floating-point array type: | 3393 // For floating-point array type: |
3361 // FP(0): value | 3394 // FP(0): value |
3362 | 3395 |
3363 if (elements_kind == EXTERNAL_INT_ELEMENTS || | 3396 if (elements_kind == EXTERNAL_INT_ELEMENTS || |
3364 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { | 3397 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
3365 // For the Int and UnsignedInt array types, we need to see whether | 3398 // For the Int and UnsignedInt array types, we need to see whether |
3366 // the value can be represented in a Smi. If not, we need to convert | 3399 // the value can be represented in a Smi. If not, we need to convert |
3367 // it to a HeapNumber. | 3400 // it to a HeapNumber. |
3368 Label box_int; | 3401 Label box_int; |
3369 if (elements_kind == EXTERNAL_INT_ELEMENTS) { | 3402 if (elements_kind == EXTERNAL_INT_ELEMENTS) { |
3370 __ cmp(ecx, 0xC0000000); | 3403 __ cmp(ecx, 0xc0000000); |
3371 __ j(sign, &box_int); | 3404 __ j(sign, &box_int); |
3372 } else { | 3405 } else { |
3373 ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); | 3406 ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); |
3374 // The test is different for unsigned int values. Since we need | 3407 // The test is different for unsigned int values. Since we need |
3375 // the value to be in the range of a positive smi, we can't | 3408 // the value to be in the range of a positive smi, we can't |
3376 // handle either of the top two bits being set in the value. | 3409 // handle either of the top two bits being set in the value. |
3377 __ test(ecx, Immediate(0xC0000000)); | 3410 __ test(ecx, Immediate(0xc0000000)); |
3378 __ j(not_zero, &box_int); | 3411 __ j(not_zero, &box_int); |
3379 } | 3412 } |
3380 | 3413 |
3381 __ mov(eax, ecx); | 3414 __ mov(eax, ecx); |
3382 __ SmiTag(eax); | 3415 __ SmiTag(eax); |
3383 __ ret(0); | 3416 __ ret(0); |
3384 | 3417 |
3385 __ bind(&box_int); | 3418 __ bind(&box_int); |
3386 | 3419 |
3387 // Allocate a HeapNumber for the int and perform int-to-double | 3420 // Allocate a HeapNumber for the int and perform int-to-double |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3452 Handle<Code> miss_ic = | 3485 Handle<Code> miss_ic = |
3453 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | 3486 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
3454 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | 3487 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
3455 } | 3488 } |
3456 | 3489 |
3457 | 3490 |
3458 void KeyedStoreStubCompiler::GenerateStoreExternalArray( | 3491 void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
3459 MacroAssembler* masm, | 3492 MacroAssembler* masm, |
3460 ElementsKind elements_kind) { | 3493 ElementsKind elements_kind) { |
3461 // ----------- S t a t e ------------- | 3494 // ----------- S t a t e ------------- |
3462 // -- eax : key | 3495 // -- eax : value |
| 3496 // -- ecx : key |
3463 // -- edx : receiver | 3497 // -- edx : receiver |
3464 // -- esp[0] : return address | 3498 // -- esp[0] : return address |
3465 // ----------------------------------- | 3499 // ----------------------------------- |
3466 Label miss_force_generic, slow, check_heap_number; | 3500 Label miss_force_generic, slow, check_heap_number; |
3467 | 3501 |
3468 // This stub is meant to be tail-jumped to, the receiver must already | 3502 // This stub is meant to be tail-jumped to, the receiver must already |
3469 // have been verified by the caller to not be a smi. | 3503 // have been verified by the caller to not be a smi. |
3470 | 3504 |
3471 // Check that the key is a smi. | 3505 // Check that the key is a smi or a heap number convertible to a smi. |
3472 __ JumpIfNotSmi(ecx, &miss_force_generic); | 3506 GenerateSmiKeyCheck(masm, ecx, ebx, xmm0, xmm1, &miss_force_generic); |
3473 | 3507 |
3474 // Check that the index is in range. | 3508 // Check that the index is in range. |
3475 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 3509 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
3476 __ cmp(ecx, FieldOperand(edi, ExternalArray::kLengthOffset)); | 3510 __ cmp(ecx, FieldOperand(edi, ExternalArray::kLengthOffset)); |
3477 // Unsigned comparison catches both negative and too-large values. | 3511 // Unsigned comparison catches both negative and too-large values. |
3478 __ j(above_equal, &slow); | 3512 __ j(above_equal, &slow); |
3479 | 3513 |
3480 // Handle both smis and HeapNumbers in the fast path. Go to the | 3514 // Handle both smis and HeapNumbers in the fast path. Go to the |
3481 // runtime for all other kinds of values. | 3515 // runtime for all other kinds of values. |
3482 // eax: value | 3516 // eax: value |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3657 // ----------- S t a t e ------------- | 3691 // ----------- S t a t e ------------- |
3658 // -- eax : key | 3692 // -- eax : key |
3659 // -- edx : receiver | 3693 // -- edx : receiver |
3660 // -- esp[0] : return address | 3694 // -- esp[0] : return address |
3661 // ----------------------------------- | 3695 // ----------------------------------- |
3662 Label miss_force_generic; | 3696 Label miss_force_generic; |
3663 | 3697 |
3664 // This stub is meant to be tail-jumped to, the receiver must already | 3698 // This stub is meant to be tail-jumped to, the receiver must already |
3665 // have been verified by the caller to not be a smi. | 3699 // have been verified by the caller to not be a smi. |
3666 | 3700 |
3667 // Check that the key is a smi. | 3701 // Check that the key is a smi or a heap number convertible to a smi. |
3668 __ JumpIfNotSmi(eax, &miss_force_generic); | 3702 GenerateSmiKeyCheck(masm, eax, ecx, xmm0, xmm1, &miss_force_generic); |
3669 | 3703 |
3670 // Get the elements array. | 3704 // Get the elements array. |
3671 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 3705 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
3672 __ AssertFastElements(ecx); | 3706 __ AssertFastElements(ecx); |
3673 | 3707 |
3674 // Check that the key is within bounds. | 3708 // Check that the key is within bounds. |
3675 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); | 3709 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); |
3676 __ j(above_equal, &miss_force_generic); | 3710 __ j(above_equal, &miss_force_generic); |
3677 | 3711 |
3678 // Load the result and make sure it's not the hole. | 3712 // Load the result and make sure it's not the hole. |
(...skipping 16 matching lines...) Expand all Loading... |
3695 // ----------- S t a t e ------------- | 3729 // ----------- S t a t e ------------- |
3696 // -- eax : key | 3730 // -- eax : key |
3697 // -- edx : receiver | 3731 // -- edx : receiver |
3698 // -- esp[0] : return address | 3732 // -- esp[0] : return address |
3699 // ----------------------------------- | 3733 // ----------------------------------- |
3700 Label miss_force_generic, slow_allocate_heapnumber; | 3734 Label miss_force_generic, slow_allocate_heapnumber; |
3701 | 3735 |
3702 // This stub is meant to be tail-jumped to, the receiver must already | 3736 // This stub is meant to be tail-jumped to, the receiver must already |
3703 // have been verified by the caller to not be a smi. | 3737 // have been verified by the caller to not be a smi. |
3704 | 3738 |
3705 // Check that the key is a smi. | 3739 // Check that the key is a smi or a heap number convertible to a smi. |
3706 __ JumpIfNotSmi(eax, &miss_force_generic); | 3740 GenerateSmiKeyCheck(masm, eax, ecx, xmm0, xmm1, &miss_force_generic); |
3707 | 3741 |
3708 // Get the elements array. | 3742 // Get the elements array. |
3709 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 3743 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
3710 __ AssertFastElements(ecx); | 3744 __ AssertFastElements(ecx); |
3711 | 3745 |
3712 // Check that the key is within bounds. | 3746 // Check that the key is within bounds. |
3713 __ cmp(eax, FieldOperand(ecx, FixedDoubleArray::kLengthOffset)); | 3747 __ cmp(eax, FieldOperand(ecx, FixedDoubleArray::kLengthOffset)); |
3714 __ j(above_equal, &miss_force_generic); | 3748 __ j(above_equal, &miss_force_generic); |
3715 | 3749 |
3716 // Check for the hole | 3750 // Check for the hole |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3764 // -- ecx : key | 3798 // -- ecx : key |
3765 // -- edx : receiver | 3799 // -- edx : receiver |
3766 // -- esp[0] : return address | 3800 // -- esp[0] : return address |
3767 // ----------------------------------- | 3801 // ----------------------------------- |
3768 Label miss_force_generic, grow, slow, transition_elements_kind; | 3802 Label miss_force_generic, grow, slow, transition_elements_kind; |
3769 Label check_capacity, prepare_slow, finish_store, commit_backing_store; | 3803 Label check_capacity, prepare_slow, finish_store, commit_backing_store; |
3770 | 3804 |
3771 // This stub is meant to be tail-jumped to, the receiver must already | 3805 // This stub is meant to be tail-jumped to, the receiver must already |
3772 // have been verified by the caller to not be a smi. | 3806 // have been verified by the caller to not be a smi. |
3773 | 3807 |
3774 // Check that the key is a smi. | 3808 // Check that the key is a smi or a heap number convertible to a smi. |
3775 __ JumpIfNotSmi(ecx, &miss_force_generic); | 3809 GenerateSmiKeyCheck(masm, ecx, ebx, xmm0, xmm1, &miss_force_generic); |
3776 | 3810 |
3777 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { | 3811 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { |
3778 __ JumpIfNotSmi(eax, &transition_elements_kind); | 3812 __ JumpIfNotSmi(eax, &transition_elements_kind); |
3779 } | 3813 } |
3780 | 3814 |
3781 // Get the elements array and make sure it is a fast element array, not 'cow'. | 3815 // Get the elements array and make sure it is a fast element array, not 'cow'. |
3782 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 3816 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
3783 if (is_js_array) { | 3817 if (is_js_array) { |
3784 // Check that the key is within bounds. | 3818 // Check that the key is within bounds. |
3785 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. | 3819 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3919 // -- ecx : key | 3953 // -- ecx : key |
3920 // -- edx : receiver | 3954 // -- edx : receiver |
3921 // -- esp[0] : return address | 3955 // -- esp[0] : return address |
3922 // ----------------------------------- | 3956 // ----------------------------------- |
3923 Label miss_force_generic, transition_elements_kind, grow, slow; | 3957 Label miss_force_generic, transition_elements_kind, grow, slow; |
3924 Label check_capacity, prepare_slow, finish_store, commit_backing_store; | 3958 Label check_capacity, prepare_slow, finish_store, commit_backing_store; |
3925 | 3959 |
3926 // This stub is meant to be tail-jumped to, the receiver must already | 3960 // This stub is meant to be tail-jumped to, the receiver must already |
3927 // have been verified by the caller to not be a smi. | 3961 // have been verified by the caller to not be a smi. |
3928 | 3962 |
3929 // Check that the key is a smi. | 3963 // Check that the key is a smi or a heap number convertible to a smi. |
3930 __ JumpIfNotSmi(ecx, &miss_force_generic); | 3964 GenerateSmiKeyCheck(masm, ecx, ebx, xmm0, xmm1, &miss_force_generic); |
3931 | 3965 |
3932 // Get the elements array. | 3966 // Get the elements array. |
3933 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 3967 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
3934 __ AssertFastElements(edi); | 3968 __ AssertFastElements(edi); |
3935 | 3969 |
3936 if (is_js_array) { | 3970 if (is_js_array) { |
3937 // Check that the key is within bounds. | 3971 // Check that the key is within bounds. |
3938 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. | 3972 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. |
3939 if (grow_mode == ALLOW_JSARRAY_GROWTH) { | 3973 if (grow_mode == ALLOW_JSARRAY_GROWTH) { |
3940 __ j(above_equal, &grow); | 3974 __ j(above_equal, &grow); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4036 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 4070 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
4037 } | 4071 } |
4038 } | 4072 } |
4039 | 4073 |
4040 | 4074 |
4041 #undef __ | 4075 #undef __ |
4042 | 4076 |
4043 } } // namespace v8::internal | 4077 } } // namespace v8::internal |
4044 | 4078 |
4045 #endif // V8_TARGET_ARCH_IA32 | 4079 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |