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 Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); | 3213 if (receiver_map->has_fast_elements() || |
| 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 } |
3214 | 3224 |
3215 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); | 3225 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3216 | |
3217 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); | |
3218 __ jmp(ic, RelocInfo::CODE_TARGET); | |
3219 | 3226 |
3220 // Return the generated code. | 3227 // Return the generated code. |
3221 return GetCode(Code::NORMAL, factory()->empty_string()); | 3228 return GetCode(Code::NORMAL, factory()->empty_string()); |
3222 } | 3229 } |
3223 | 3230 |
3224 | 3231 |
3225 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( | 3232 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( |
3226 MapHandleList* receiver_maps, | 3233 MapHandleList* receiver_maps, |
3227 CodeHandleList* handler_ics) { | 3234 CodeHandleList* handler_ics) { |
3228 // ----------- S t a t e ------------- | 3235 // ----------- S t a t e ------------- |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3450 __ cvttsd2si(scratch, xmm_scratch0); | 3457 __ cvttsd2si(scratch, xmm_scratch0); |
3451 __ cvtlsi2sd(xmm_scratch1, scratch); | 3458 __ cvtlsi2sd(xmm_scratch1, scratch); |
3452 __ ucomisd(xmm_scratch1, xmm_scratch0); | 3459 __ ucomisd(xmm_scratch1, xmm_scratch0); |
3453 __ j(not_equal, fail); | 3460 __ j(not_equal, fail); |
3454 __ j(parity_even, fail); // NaN. | 3461 __ j(parity_even, fail); // NaN. |
3455 __ Integer32ToSmi(key, scratch); | 3462 __ Integer32ToSmi(key, scratch); |
3456 __ bind(&key_ok); | 3463 __ bind(&key_ok); |
3457 } | 3464 } |
3458 | 3465 |
3459 | 3466 |
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 | |
3594 void KeyedStoreStubCompiler::GenerateStoreExternalArray( | 3467 void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
3595 MacroAssembler* masm, | 3468 MacroAssembler* masm, |
3596 ElementsKind elements_kind) { | 3469 ElementsKind elements_kind) { |
3597 // ----------- S t a t e ------------- | 3470 // ----------- S t a t e ------------- |
3598 // -- rax : value | 3471 // -- rax : value |
3599 // -- rcx : key | 3472 // -- rcx : key |
3600 // -- rdx : receiver | 3473 // -- rdx : receiver |
3601 // -- rsp[0] : return address | 3474 // -- rsp[0] : return address |
3602 // ----------------------------------- | 3475 // ----------------------------------- |
3603 Label slow, miss_force_generic; | 3476 Label slow, miss_force_generic; |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3773 // -- rdx : receiver | 3646 // -- rdx : receiver |
3774 // -- rsp[0] : return address | 3647 // -- rsp[0] : return address |
3775 // ----------------------------------- | 3648 // ----------------------------------- |
3776 | 3649 |
3777 Handle<Code> miss_ic = | 3650 Handle<Code> miss_ic = |
3778 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 3651 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
3779 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | 3652 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
3780 } | 3653 } |
3781 | 3654 |
3782 | 3655 |
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 | |
3875 void KeyedStoreStubCompiler::GenerateStoreFastElement( | 3656 void KeyedStoreStubCompiler::GenerateStoreFastElement( |
3876 MacroAssembler* masm, | 3657 MacroAssembler* masm, |
3877 bool is_js_array, | 3658 bool is_js_array, |
3878 ElementsKind elements_kind, | 3659 ElementsKind elements_kind, |
3879 KeyedAccessGrowMode grow_mode) { | 3660 KeyedAccessGrowMode grow_mode) { |
3880 // ----------- S t a t e ------------- | 3661 // ----------- S t a t e ------------- |
3881 // -- rax : value | 3662 // -- rax : value |
3882 // -- rcx : key | 3663 // -- rcx : key |
3883 // -- rdx : receiver | 3664 // -- rdx : receiver |
3884 // -- rsp[0] : return address | 3665 // -- rsp[0] : return address |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4147 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 3928 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
4148 } | 3929 } |
4149 } | 3930 } |
4150 | 3931 |
4151 | 3932 |
4152 #undef __ | 3933 #undef __ |
4153 | 3934 |
4154 } } // namespace v8::internal | 3935 } } // namespace v8::internal |
4155 | 3936 |
4156 #endif // V8_TARGET_ARCH_X64 | 3937 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |