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 3192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3203 | 3203 |
3204 | 3204 |
3205 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( | 3205 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
3206 Handle<Map> receiver_map) { | 3206 Handle<Map> receiver_map) { |
3207 // ----------- S t a t e ------------- | 3207 // ----------- S t a t e ------------- |
3208 // -- rax : key | 3208 // -- rax : key |
3209 // -- rdx : receiver | 3209 // -- rdx : receiver |
3210 // -- rsp[0] : return address | 3210 // -- rsp[0] : return address |
3211 // ----------------------------------- | 3211 // ----------------------------------- |
3212 ElementsKind elements_kind = receiver_map->elements_kind(); | 3212 ElementsKind elements_kind = receiver_map->elements_kind(); |
3213 if (receiver_map->has_fast_elements() || | 3213 Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); |
3214 receiver_map->has_external_array_elements()) { | |
3215 Handle<Code> stub = KeyedLoadFastElementStub( | |
3216 receiver_map->instance_type() == JS_ARRAY_TYPE, | |
3217 elements_kind).GetCode(); | |
3218 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); | |
3219 } else { | |
3220 Handle<Code> stub = | |
3221 KeyedLoadDictionaryElementStub().GetCode(); | |
3222 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); | |
3223 } | |
3224 | 3214 |
3225 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3215 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); |
| 3216 |
| 3217 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); |
| 3218 __ jmp(ic, RelocInfo::CODE_TARGET); |
3226 | 3219 |
3227 // Return the generated code. | 3220 // Return the generated code. |
3228 return GetCode(Code::NORMAL, factory()->empty_string()); | 3221 return GetCode(Code::NORMAL, factory()->empty_string()); |
3229 } | 3222 } |
3230 | 3223 |
3231 | 3224 |
3232 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( | 3225 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( |
3233 MapHandleList* receiver_maps, | 3226 MapHandleList* receiver_maps, |
3234 CodeHandleList* handler_ics) { | 3227 CodeHandleList* handler_ics) { |
3235 // ----------- S t a t e ------------- | 3228 // ----------- S t a t e ------------- |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3457 __ cvttsd2si(scratch, xmm_scratch0); | 3450 __ cvttsd2si(scratch, xmm_scratch0); |
3458 __ cvtlsi2sd(xmm_scratch1, scratch); | 3451 __ cvtlsi2sd(xmm_scratch1, scratch); |
3459 __ ucomisd(xmm_scratch1, xmm_scratch0); | 3452 __ ucomisd(xmm_scratch1, xmm_scratch0); |
3460 __ j(not_equal, fail); | 3453 __ j(not_equal, fail); |
3461 __ j(parity_even, fail); // NaN. | 3454 __ j(parity_even, fail); // NaN. |
3462 __ Integer32ToSmi(key, scratch); | 3455 __ Integer32ToSmi(key, scratch); |
3463 __ bind(&key_ok); | 3456 __ bind(&key_ok); |
3464 } | 3457 } |
3465 | 3458 |
3466 | 3459 |
| 3460 void KeyedLoadStubCompiler::GenerateLoadExternalArray( |
| 3461 MacroAssembler* masm, |
| 3462 ElementsKind elements_kind) { |
| 3463 // ----------- S t a t e ------------- |
| 3464 // -- rax : key |
| 3465 // -- rdx : receiver |
| 3466 // -- rsp[0] : return address |
| 3467 // ----------------------------------- |
| 3468 Label slow, miss_force_generic; |
| 3469 |
| 3470 // This stub is meant to be tail-jumped to, the receiver must already |
| 3471 // have been verified by the caller to not be a smi. |
| 3472 |
| 3473 // Check that the key is a smi or a heap number convertible to a smi. |
| 3474 GenerateSmiKeyCheck(masm, rax, rcx, xmm0, xmm1, &miss_force_generic); |
| 3475 |
| 3476 // Check that the index is in range. |
| 3477 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); |
| 3478 __ SmiToInteger32(rcx, rax); |
| 3479 __ cmpq(rax, FieldOperand(rbx, ExternalArray::kLengthOffset)); |
| 3480 // Unsigned comparison catches both negative and too-large values. |
| 3481 __ j(above_equal, &miss_force_generic); |
| 3482 |
| 3483 // rax: index (as a smi) |
| 3484 // rdx: receiver (JSObject) |
| 3485 // rcx: untagged index |
| 3486 // rbx: elements array |
| 3487 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); |
| 3488 // rbx: base pointer of external storage |
| 3489 switch (elements_kind) { |
| 3490 case EXTERNAL_BYTE_ELEMENTS: |
| 3491 __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0)); |
| 3492 break; |
| 3493 case EXTERNAL_PIXEL_ELEMENTS: |
| 3494 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3495 __ movzxbq(rcx, Operand(rbx, rcx, times_1, 0)); |
| 3496 break; |
| 3497 case EXTERNAL_SHORT_ELEMENTS: |
| 3498 __ movsxwq(rcx, Operand(rbx, rcx, times_2, 0)); |
| 3499 break; |
| 3500 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3501 __ movzxwq(rcx, Operand(rbx, rcx, times_2, 0)); |
| 3502 break; |
| 3503 case EXTERNAL_INT_ELEMENTS: |
| 3504 __ movsxlq(rcx, Operand(rbx, rcx, times_4, 0)); |
| 3505 break; |
| 3506 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3507 __ movl(rcx, Operand(rbx, rcx, times_4, 0)); |
| 3508 break; |
| 3509 case EXTERNAL_FLOAT_ELEMENTS: |
| 3510 __ cvtss2sd(xmm0, Operand(rbx, rcx, times_4, 0)); |
| 3511 break; |
| 3512 case EXTERNAL_DOUBLE_ELEMENTS: |
| 3513 __ movsd(xmm0, Operand(rbx, rcx, times_8, 0)); |
| 3514 break; |
| 3515 default: |
| 3516 UNREACHABLE(); |
| 3517 break; |
| 3518 } |
| 3519 |
| 3520 // rax: index |
| 3521 // rdx: receiver |
| 3522 // For integer array types: |
| 3523 // rcx: value |
| 3524 // For floating-point array type: |
| 3525 // xmm0: value as double. |
| 3526 |
| 3527 ASSERT(kSmiValueSize == 32); |
| 3528 if (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
| 3529 // For the UnsignedInt array type, we need to see whether |
| 3530 // the value can be represented in a Smi. If not, we need to convert |
| 3531 // it to a HeapNumber. |
| 3532 Label box_int; |
| 3533 |
| 3534 __ JumpIfUIntNotValidSmiValue(rcx, &box_int, Label::kNear); |
| 3535 |
| 3536 __ Integer32ToSmi(rax, rcx); |
| 3537 __ ret(0); |
| 3538 |
| 3539 __ bind(&box_int); |
| 3540 |
| 3541 // Allocate a HeapNumber for the int and perform int-to-double |
| 3542 // conversion. |
| 3543 // The value is zero-extended since we loaded the value from memory |
| 3544 // with movl. |
| 3545 __ cvtqsi2sd(xmm0, rcx); |
| 3546 |
| 3547 __ AllocateHeapNumber(rcx, rbx, &slow); |
| 3548 // Set the value. |
| 3549 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); |
| 3550 __ movq(rax, rcx); |
| 3551 __ ret(0); |
| 3552 } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || |
| 3553 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
| 3554 // For the floating-point array type, we need to always allocate a |
| 3555 // HeapNumber. |
| 3556 __ AllocateHeapNumber(rcx, rbx, &slow); |
| 3557 // Set the value. |
| 3558 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); |
| 3559 __ movq(rax, rcx); |
| 3560 __ ret(0); |
| 3561 } else { |
| 3562 __ Integer32ToSmi(rax, rcx); |
| 3563 __ ret(0); |
| 3564 } |
| 3565 |
| 3566 // Slow case: Jump to runtime. |
| 3567 __ bind(&slow); |
| 3568 Counters* counters = masm->isolate()->counters(); |
| 3569 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); |
| 3570 |
| 3571 // ----------- S t a t e ------------- |
| 3572 // -- rax : key |
| 3573 // -- rdx : receiver |
| 3574 // -- rsp[0] : return address |
| 3575 // ----------------------------------- |
| 3576 |
| 3577 Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow(); |
| 3578 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 3579 |
| 3580 // Miss case: Jump to runtime. |
| 3581 __ bind(&miss_force_generic); |
| 3582 |
| 3583 // ----------- S t a t e ------------- |
| 3584 // -- rax : key |
| 3585 // -- rdx : receiver |
| 3586 // -- rsp[0] : return address |
| 3587 // ----------------------------------- |
| 3588 Handle<Code> miss_ic = |
| 3589 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
| 3590 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
| 3591 } |
| 3592 |
| 3593 |
3467 void KeyedStoreStubCompiler::GenerateStoreExternalArray( | 3594 void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
3468 MacroAssembler* masm, | 3595 MacroAssembler* masm, |
3469 ElementsKind elements_kind) { | 3596 ElementsKind elements_kind) { |
3470 // ----------- S t a t e ------------- | 3597 // ----------- S t a t e ------------- |
3471 // -- rax : value | 3598 // -- rax : value |
3472 // -- rcx : key | 3599 // -- rcx : key |
3473 // -- rdx : receiver | 3600 // -- rdx : receiver |
3474 // -- rsp[0] : return address | 3601 // -- rsp[0] : return address |
3475 // ----------------------------------- | 3602 // ----------------------------------- |
3476 Label slow, miss_force_generic; | 3603 Label slow, miss_force_generic; |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3646 // -- rdx : receiver | 3773 // -- rdx : receiver |
3647 // -- rsp[0] : return address | 3774 // -- rsp[0] : return address |
3648 // ----------------------------------- | 3775 // ----------------------------------- |
3649 | 3776 |
3650 Handle<Code> miss_ic = | 3777 Handle<Code> miss_ic = |
3651 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 3778 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
3652 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | 3779 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
3653 } | 3780 } |
3654 | 3781 |
3655 | 3782 |
| 3783 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { |
| 3784 // ----------- S t a t e ------------- |
| 3785 // -- rax : key |
| 3786 // -- rdx : receiver |
| 3787 // -- rsp[0] : return address |
| 3788 // ----------------------------------- |
| 3789 Label miss_force_generic; |
| 3790 |
| 3791 // This stub is meant to be tail-jumped to, the receiver must already |
| 3792 // have been verified by the caller to not be a smi. |
| 3793 |
| 3794 // Check that the key is a smi or a heap number convertible to a smi. |
| 3795 GenerateSmiKeyCheck(masm, rax, rcx, xmm0, xmm1, &miss_force_generic); |
| 3796 |
| 3797 // Get the elements array. |
| 3798 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); |
| 3799 __ AssertFastElements(rcx); |
| 3800 |
| 3801 // Check that the key is within bounds. |
| 3802 __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); |
| 3803 __ j(above_equal, &miss_force_generic); |
| 3804 |
| 3805 // Load the result and make sure it's not the hole. |
| 3806 SmiIndex index = masm->SmiToIndex(rbx, rax, kPointerSizeLog2); |
| 3807 __ movq(rbx, FieldOperand(rcx, |
| 3808 index.reg, |
| 3809 index.scale, |
| 3810 FixedArray::kHeaderSize)); |
| 3811 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); |
| 3812 __ j(equal, &miss_force_generic); |
| 3813 __ movq(rax, rbx); |
| 3814 __ ret(0); |
| 3815 |
| 3816 __ bind(&miss_force_generic); |
| 3817 Code* code = masm->isolate()->builtins()->builtin( |
| 3818 Builtins::kKeyedLoadIC_MissForceGeneric); |
| 3819 Handle<Code> ic(code); |
| 3820 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 3821 } |
| 3822 |
| 3823 |
| 3824 void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( |
| 3825 MacroAssembler* masm) { |
| 3826 // ----------- S t a t e ------------- |
| 3827 // -- rax : key |
| 3828 // -- rdx : receiver |
| 3829 // -- rsp[0] : return address |
| 3830 // ----------------------------------- |
| 3831 Label miss_force_generic, slow_allocate_heapnumber; |
| 3832 |
| 3833 // This stub is meant to be tail-jumped to, the receiver must already |
| 3834 // have been verified by the caller to not be a smi. |
| 3835 |
| 3836 // Check that the key is a smi or a heap number convertible to a smi. |
| 3837 GenerateSmiKeyCheck(masm, rax, rcx, xmm0, xmm1, &miss_force_generic); |
| 3838 |
| 3839 // Get the elements array. |
| 3840 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); |
| 3841 __ AssertFastElements(rcx); |
| 3842 |
| 3843 // Check that the key is within bounds. |
| 3844 __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); |
| 3845 __ j(above_equal, &miss_force_generic); |
| 3846 |
| 3847 // Check for the hole |
| 3848 __ SmiToInteger32(kScratchRegister, rax); |
| 3849 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); |
| 3850 __ cmpl(FieldOperand(rcx, kScratchRegister, times_8, offset), |
| 3851 Immediate(kHoleNanUpper32)); |
| 3852 __ j(equal, &miss_force_generic); |
| 3853 |
| 3854 // Always allocate a heap number for the result. |
| 3855 __ movsd(xmm0, FieldOperand(rcx, kScratchRegister, times_8, |
| 3856 FixedDoubleArray::kHeaderSize)); |
| 3857 __ AllocateHeapNumber(rcx, rbx, &slow_allocate_heapnumber); |
| 3858 // Set the value. |
| 3859 __ movq(rax, rcx); |
| 3860 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); |
| 3861 __ ret(0); |
| 3862 |
| 3863 __ bind(&slow_allocate_heapnumber); |
| 3864 Handle<Code> slow_ic = |
| 3865 masm->isolate()->builtins()->KeyedLoadIC_Slow(); |
| 3866 __ jmp(slow_ic, RelocInfo::CODE_TARGET); |
| 3867 |
| 3868 __ bind(&miss_force_generic); |
| 3869 Handle<Code> miss_ic = |
| 3870 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
| 3871 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
| 3872 } |
| 3873 |
| 3874 |
3656 void KeyedStoreStubCompiler::GenerateStoreFastElement( | 3875 void KeyedStoreStubCompiler::GenerateStoreFastElement( |
3657 MacroAssembler* masm, | 3876 MacroAssembler* masm, |
3658 bool is_js_array, | 3877 bool is_js_array, |
3659 ElementsKind elements_kind, | 3878 ElementsKind elements_kind, |
3660 KeyedAccessGrowMode grow_mode) { | 3879 KeyedAccessGrowMode grow_mode) { |
3661 // ----------- S t a t e ------------- | 3880 // ----------- S t a t e ------------- |
3662 // -- rax : value | 3881 // -- rax : value |
3663 // -- rcx : key | 3882 // -- rcx : key |
3664 // -- rdx : receiver | 3883 // -- rdx : receiver |
3665 // -- rsp[0] : return address | 3884 // -- rsp[0] : return address |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3928 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 4147 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
3929 } | 4148 } |
3930 } | 4149 } |
3931 | 4150 |
3932 | 4151 |
3933 #undef __ | 4152 #undef __ |
3934 | 4153 |
3935 } } // namespace v8::internal | 4154 } } // namespace v8::internal |
3936 | 4155 |
3937 #endif // V8_TARGET_ARCH_X64 | 4156 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |