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 3380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3391 | 3391 |
3392 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( | 3392 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
3393 Handle<Map> receiver_map) { | 3393 Handle<Map> receiver_map) { |
3394 // ----------- S t a t e ------------- | 3394 // ----------- S t a t e ------------- |
3395 // -- ecx : key | 3395 // -- ecx : key |
3396 // -- edx : receiver | 3396 // -- edx : receiver |
3397 // -- esp[0] : return address | 3397 // -- esp[0] : return address |
3398 // ----------------------------------- | 3398 // ----------------------------------- |
3399 | 3399 |
3400 ElementsKind elements_kind = receiver_map->elements_kind(); | 3400 ElementsKind elements_kind = receiver_map->elements_kind(); |
3401 Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); | 3401 if (receiver_map->has_fast_elements() || |
3402 | 3402 receiver_map->has_external_array_elements()) { |
3403 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); | 3403 Handle<Code> stub = KeyedLoadFastElementStub( |
| 3404 receiver_map->instance_type() == JS_ARRAY_TYPE, |
| 3405 elements_kind).GetCode(); |
| 3406 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); |
| 3407 } else { |
| 3408 Handle<Code> stub = |
| 3409 KeyedLoadDictionaryElementStub().GetCode(); |
| 3410 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); |
| 3411 } |
3404 | 3412 |
3405 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3413 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3406 | 3414 |
3407 // Return the generated code. | 3415 // Return the generated code. |
3408 return GetCode(Code::NORMAL, factory()->empty_string()); | 3416 return GetCode(Code::NORMAL, factory()->empty_string()); |
3409 } | 3417 } |
3410 | 3418 |
3411 | 3419 |
3412 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( | 3420 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( |
3413 MapHandleList* receiver_maps, | 3421 MapHandleList* receiver_maps, |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3654 __ j(sign, fail); | 3662 __ j(sign, fail); |
3655 __ SmiTag(scratch); | 3663 __ SmiTag(scratch); |
3656 __ mov(key, scratch); | 3664 __ mov(key, scratch); |
3657 __ bind(&key_ok); | 3665 __ bind(&key_ok); |
3658 } else { | 3666 } else { |
3659 __ JumpIfNotSmi(key, fail); | 3667 __ JumpIfNotSmi(key, fail); |
3660 } | 3668 } |
3661 } | 3669 } |
3662 | 3670 |
3663 | 3671 |
3664 void KeyedLoadStubCompiler::GenerateLoadExternalArray( | |
3665 MacroAssembler* masm, | |
3666 ElementsKind elements_kind) { | |
3667 // ----------- S t a t e ------------- | |
3668 // -- ecx : key | |
3669 // -- edx : receiver | |
3670 // -- esp[0] : return address | |
3671 // ----------------------------------- | |
3672 Label miss_force_generic, failed_allocation, slow; | |
3673 | |
3674 // This stub is meant to be tail-jumped to, the receiver must already | |
3675 // have been verified by the caller to not be a smi. | |
3676 | |
3677 // Check that the key is a smi or a heap number convertible to a smi. | |
3678 GenerateSmiKeyCheck(masm, ecx, eax, xmm0, xmm1, &miss_force_generic); | |
3679 | |
3680 // Check that the index is in range. | |
3681 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); | |
3682 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); | |
3683 // Unsigned comparison catches both negative and too-large values. | |
3684 __ j(above_equal, &miss_force_generic); | |
3685 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); | |
3686 // ebx: base pointer of external storage | |
3687 switch (elements_kind) { | |
3688 case EXTERNAL_BYTE_ELEMENTS: | |
3689 __ SmiUntag(ecx); // Untag the index. | |
3690 __ movsx_b(eax, Operand(ebx, ecx, times_1, 0)); | |
3691 break; | |
3692 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
3693 case EXTERNAL_PIXEL_ELEMENTS: | |
3694 __ SmiUntag(ecx); // Untag the index. | |
3695 __ movzx_b(eax, Operand(ebx, ecx, times_1, 0)); | |
3696 break; | |
3697 case EXTERNAL_SHORT_ELEMENTS: | |
3698 __ movsx_w(eax, Operand(ebx, ecx, times_1, 0)); | |
3699 break; | |
3700 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
3701 __ movzx_w(eax, Operand(ebx, ecx, times_1, 0)); | |
3702 break; | |
3703 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
3704 case EXTERNAL_INT_ELEMENTS: | |
3705 __ mov(eax, Operand(ebx, ecx, times_2, 0)); | |
3706 break; | |
3707 case EXTERNAL_FLOAT_ELEMENTS: | |
3708 __ fld_s(Operand(ebx, ecx, times_2, 0)); | |
3709 break; | |
3710 case EXTERNAL_DOUBLE_ELEMENTS: | |
3711 __ fld_d(Operand(ebx, ecx, times_4, 0)); | |
3712 break; | |
3713 default: | |
3714 UNREACHABLE(); | |
3715 break; | |
3716 } | |
3717 | |
3718 // For integer array types: | |
3719 // eax: value | |
3720 // For floating-point array type: | |
3721 // FP(0): value | |
3722 | |
3723 if (elements_kind == EXTERNAL_INT_ELEMENTS || | |
3724 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { | |
3725 // For the Int and UnsignedInt array types, we need to see whether | |
3726 // the value can be represented in a Smi. If not, we need to convert | |
3727 // it to a HeapNumber. | |
3728 Label box_int; | |
3729 if (elements_kind == EXTERNAL_INT_ELEMENTS) { | |
3730 __ cmp(eax, 0xc0000000); | |
3731 __ j(sign, &box_int); | |
3732 } else { | |
3733 ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); | |
3734 // The test is different for unsigned int values. Since we need | |
3735 // the value to be in the range of a positive smi, we can't | |
3736 // handle either of the top two bits being set in the value. | |
3737 __ test(eax, Immediate(0xc0000000)); | |
3738 __ j(not_zero, &box_int); | |
3739 } | |
3740 | |
3741 __ SmiTag(eax); | |
3742 __ ret(0); | |
3743 | |
3744 __ bind(&box_int); | |
3745 | |
3746 // Allocate a HeapNumber for the int and perform int-to-double | |
3747 // conversion. | |
3748 if (elements_kind == EXTERNAL_INT_ELEMENTS) { | |
3749 __ push(eax); | |
3750 __ fild_s(Operand(esp, 0)); | |
3751 __ pop(eax); | |
3752 } else { | |
3753 ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); | |
3754 // Need to zero-extend the value. | |
3755 // There's no fild variant for unsigned values, so zero-extend | |
3756 // to a 64-bit int manually. | |
3757 __ push(Immediate(0)); | |
3758 __ push(eax); | |
3759 __ fild_d(Operand(esp, 0)); | |
3760 __ pop(eax); | |
3761 __ pop(eax); | |
3762 } | |
3763 // FP(0): value | |
3764 __ AllocateHeapNumber(eax, ebx, edi, &failed_allocation); | |
3765 // Set the value. | |
3766 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | |
3767 __ ret(0); | |
3768 } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | |
3769 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | |
3770 // For the floating-point array type, we need to always allocate a | |
3771 // HeapNumber. | |
3772 __ AllocateHeapNumber(eax, ebx, edi, &failed_allocation); | |
3773 // Set the value. | |
3774 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | |
3775 __ ret(0); | |
3776 } else { | |
3777 __ SmiTag(eax); | |
3778 __ ret(0); | |
3779 } | |
3780 | |
3781 // If we fail allocation of the HeapNumber, we still have a value on | |
3782 // top of the FPU stack. Remove it. | |
3783 __ bind(&failed_allocation); | |
3784 __ fstp(0); | |
3785 // Fall through to slow case. | |
3786 | |
3787 // Slow case: Jump to runtime. | |
3788 __ bind(&slow); | |
3789 Counters* counters = masm->isolate()->counters(); | |
3790 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); | |
3791 | |
3792 // ----------- S t a t e ------------- | |
3793 // -- ecx : key | |
3794 // -- edx : receiver | |
3795 // -- esp[0] : return address | |
3796 // ----------------------------------- | |
3797 | |
3798 Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow(); | |
3799 __ jmp(ic, RelocInfo::CODE_TARGET); | |
3800 | |
3801 // ----------- S t a t e ------------- | |
3802 // -- ecx : key | |
3803 // -- edx : receiver | |
3804 // -- esp[0] : return address | |
3805 // ----------------------------------- | |
3806 | |
3807 // Miss case: Jump to runtime. | |
3808 __ bind(&miss_force_generic); | |
3809 Handle<Code> miss_ic = | |
3810 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | |
3811 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | |
3812 } | |
3813 | |
3814 | |
3815 void KeyedStoreStubCompiler::GenerateStoreExternalArray( | 3672 void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
3816 MacroAssembler* masm, | 3673 MacroAssembler* masm, |
3817 ElementsKind elements_kind) { | 3674 ElementsKind elements_kind) { |
3818 // ----------- S t a t e ------------- | 3675 // ----------- S t a t e ------------- |
3819 // -- eax : value | 3676 // -- eax : value |
3820 // -- ecx : key | 3677 // -- ecx : key |
3821 // -- edx : receiver | 3678 // -- edx : receiver |
3822 // -- esp[0] : return address | 3679 // -- esp[0] : return address |
3823 // ----------------------------------- | 3680 // ----------------------------------- |
3824 Label miss_force_generic, slow, check_heap_number; | 3681 Label miss_force_generic, slow, check_heap_number; |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4004 // -- esp[0] : return address | 3861 // -- esp[0] : return address |
4005 // ----------------------------------- | 3862 // ----------------------------------- |
4006 | 3863 |
4007 __ bind(&miss_force_generic); | 3864 __ bind(&miss_force_generic); |
4008 Handle<Code> miss_ic = | 3865 Handle<Code> miss_ic = |
4009 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 3866 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
4010 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | 3867 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
4011 } | 3868 } |
4012 | 3869 |
4013 | 3870 |
4014 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { | |
4015 // ----------- S t a t e ------------- | |
4016 // -- ecx : key | |
4017 // -- edx : receiver | |
4018 // -- esp[0] : return address | |
4019 // ----------------------------------- | |
4020 Label miss_force_generic; | |
4021 | |
4022 // This stub is meant to be tail-jumped to, the receiver must already | |
4023 // have been verified by the caller to not be a smi. | |
4024 | |
4025 // Check that the key is a smi or a heap number convertible to a smi. | |
4026 GenerateSmiKeyCheck(masm, ecx, eax, xmm0, xmm1, &miss_force_generic); | |
4027 | |
4028 // Get the elements array. | |
4029 __ mov(eax, FieldOperand(edx, JSObject::kElementsOffset)); | |
4030 __ AssertFastElements(eax); | |
4031 | |
4032 // Check that the key is within bounds. | |
4033 __ cmp(ecx, FieldOperand(eax, FixedArray::kLengthOffset)); | |
4034 __ j(above_equal, &miss_force_generic); | |
4035 | |
4036 // Load the result and make sure it's not the hole. | |
4037 __ mov(ebx, Operand(eax, ecx, times_2, | |
4038 FixedArray::kHeaderSize - kHeapObjectTag)); | |
4039 __ cmp(ebx, masm->isolate()->factory()->the_hole_value()); | |
4040 __ j(equal, &miss_force_generic); | |
4041 __ mov(eax, ebx); | |
4042 __ ret(0); | |
4043 | |
4044 __ bind(&miss_force_generic); | |
4045 Handle<Code> miss_ic = | |
4046 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | |
4047 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | |
4048 } | |
4049 | |
4050 | |
4051 void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( | |
4052 MacroAssembler* masm) { | |
4053 // ----------- S t a t e ------------- | |
4054 // -- ecx : key | |
4055 // -- edx : receiver | |
4056 // -- esp[0] : return address | |
4057 // ----------------------------------- | |
4058 Label miss_force_generic, slow_allocate_heapnumber; | |
4059 | |
4060 // This stub is meant to be tail-jumped to, the receiver must already | |
4061 // have been verified by the caller to not be a smi. | |
4062 | |
4063 // Check that the key is a smi or a heap number convertible to a smi. | |
4064 GenerateSmiKeyCheck(masm, ecx, eax, xmm0, xmm1, &miss_force_generic); | |
4065 | |
4066 // Get the elements array. | |
4067 __ mov(eax, FieldOperand(edx, JSObject::kElementsOffset)); | |
4068 __ AssertFastElements(eax); | |
4069 | |
4070 // Check that the key is within bounds. | |
4071 __ cmp(ecx, FieldOperand(eax, FixedDoubleArray::kLengthOffset)); | |
4072 __ j(above_equal, &miss_force_generic); | |
4073 | |
4074 // Check for the hole | |
4075 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); | |
4076 __ cmp(FieldOperand(eax, ecx, times_4, offset), Immediate(kHoleNanUpper32)); | |
4077 __ j(equal, &miss_force_generic); | |
4078 | |
4079 // Always allocate a heap number for the result. | |
4080 if (CpuFeatures::IsSupported(SSE2)) { | |
4081 CpuFeatures::Scope use_sse2(SSE2); | |
4082 __ movdbl(xmm0, FieldOperand(eax, ecx, times_4, | |
4083 FixedDoubleArray::kHeaderSize)); | |
4084 } else { | |
4085 __ fld_d(FieldOperand(eax, ecx, times_4, FixedDoubleArray::kHeaderSize)); | |
4086 } | |
4087 __ AllocateHeapNumber(eax, ebx, edi, &slow_allocate_heapnumber); | |
4088 // Set the value. | |
4089 if (CpuFeatures::IsSupported(SSE2)) { | |
4090 CpuFeatures::Scope use_sse2(SSE2); | |
4091 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | |
4092 } else { | |
4093 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | |
4094 } | |
4095 __ ret(0); | |
4096 | |
4097 __ bind(&slow_allocate_heapnumber); | |
4098 // A value was pushed on the floating point stack before the allocation, if | |
4099 // the allocation fails it needs to be removed. | |
4100 if (!CpuFeatures::IsSupported(SSE2)) { | |
4101 __ fstp(0); | |
4102 } | |
4103 Handle<Code> slow_ic = | |
4104 masm->isolate()->builtins()->KeyedLoadIC_Slow(); | |
4105 __ jmp(slow_ic, RelocInfo::CODE_TARGET); | |
4106 | |
4107 __ bind(&miss_force_generic); | |
4108 Handle<Code> miss_ic = | |
4109 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | |
4110 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | |
4111 } | |
4112 | |
4113 | |
4114 void KeyedStoreStubCompiler::GenerateStoreFastElement( | 3871 void KeyedStoreStubCompiler::GenerateStoreFastElement( |
4115 MacroAssembler* masm, | 3872 MacroAssembler* masm, |
4116 bool is_js_array, | 3873 bool is_js_array, |
4117 ElementsKind elements_kind, | 3874 ElementsKind elements_kind, |
4118 KeyedAccessGrowMode grow_mode) { | 3875 KeyedAccessGrowMode grow_mode) { |
4119 // ----------- S t a t e ------------- | 3876 // ----------- S t a t e ------------- |
4120 // -- eax : value | 3877 // -- eax : value |
4121 // -- ecx : key | 3878 // -- ecx : key |
4122 // -- edx : receiver | 3879 // -- edx : receiver |
4123 // -- esp[0] : return address | 3880 // -- esp[0] : return address |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4403 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 4160 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
4404 } | 4161 } |
4405 } | 4162 } |
4406 | 4163 |
4407 | 4164 |
4408 #undef __ | 4165 #undef __ |
4409 | 4166 |
4410 } } // namespace v8::internal | 4167 } } // namespace v8::internal |
4411 | 4168 |
4412 #endif // V8_TARGET_ARCH_IA32 | 4169 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |