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 if (receiver_map->has_fast_elements() || | 3401 Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); |
3402 receiver_map->has_external_array_elements()) { | 3402 |
3403 Handle<Code> stub = KeyedLoadFastElementStub( | 3403 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); |
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 } | |
3412 | 3404 |
3413 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3405 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3414 | 3406 |
3415 // Return the generated code. | 3407 // Return the generated code. |
3416 return GetCode(Code::NORMAL, factory()->empty_string()); | 3408 return GetCode(Code::NORMAL, factory()->empty_string()); |
3417 } | 3409 } |
3418 | 3410 |
3419 | 3411 |
3420 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( | 3412 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( |
3421 MapHandleList* receiver_maps, | 3413 MapHandleList* receiver_maps, |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3662 __ j(sign, fail); | 3654 __ j(sign, fail); |
3663 __ SmiTag(scratch); | 3655 __ SmiTag(scratch); |
3664 __ mov(key, scratch); | 3656 __ mov(key, scratch); |
3665 __ bind(&key_ok); | 3657 __ bind(&key_ok); |
3666 } else { | 3658 } else { |
3667 __ JumpIfNotSmi(key, fail); | 3659 __ JumpIfNotSmi(key, fail); |
3668 } | 3660 } |
3669 } | 3661 } |
3670 | 3662 |
3671 | 3663 |
| 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 |
3672 void KeyedStoreStubCompiler::GenerateStoreExternalArray( | 3815 void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
3673 MacroAssembler* masm, | 3816 MacroAssembler* masm, |
3674 ElementsKind elements_kind) { | 3817 ElementsKind elements_kind) { |
3675 // ----------- S t a t e ------------- | 3818 // ----------- S t a t e ------------- |
3676 // -- eax : value | 3819 // -- eax : value |
3677 // -- ecx : key | 3820 // -- ecx : key |
3678 // -- edx : receiver | 3821 // -- edx : receiver |
3679 // -- esp[0] : return address | 3822 // -- esp[0] : return address |
3680 // ----------------------------------- | 3823 // ----------------------------------- |
3681 Label miss_force_generic, slow, check_heap_number; | 3824 Label miss_force_generic, slow, check_heap_number; |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3861 // -- esp[0] : return address | 4004 // -- esp[0] : return address |
3862 // ----------------------------------- | 4005 // ----------------------------------- |
3863 | 4006 |
3864 __ bind(&miss_force_generic); | 4007 __ bind(&miss_force_generic); |
3865 Handle<Code> miss_ic = | 4008 Handle<Code> miss_ic = |
3866 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 4009 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
3867 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | 4010 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
3868 } | 4011 } |
3869 | 4012 |
3870 | 4013 |
| 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 |
3871 void KeyedStoreStubCompiler::GenerateStoreFastElement( | 4114 void KeyedStoreStubCompiler::GenerateStoreFastElement( |
3872 MacroAssembler* masm, | 4115 MacroAssembler* masm, |
3873 bool is_js_array, | 4116 bool is_js_array, |
3874 ElementsKind elements_kind, | 4117 ElementsKind elements_kind, |
3875 KeyedAccessGrowMode grow_mode) { | 4118 KeyedAccessGrowMode grow_mode) { |
3876 // ----------- S t a t e ------------- | 4119 // ----------- S t a t e ------------- |
3877 // -- eax : value | 4120 // -- eax : value |
3878 // -- ecx : key | 4121 // -- ecx : key |
3879 // -- edx : receiver | 4122 // -- edx : receiver |
3880 // -- esp[0] : return address | 4123 // -- esp[0] : return address |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4160 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 4403 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
4161 } | 4404 } |
4162 } | 4405 } |
4163 | 4406 |
4164 | 4407 |
4165 #undef __ | 4408 #undef __ |
4166 | 4409 |
4167 } } // namespace v8::internal | 4410 } } // namespace v8::internal |
4168 | 4411 |
4169 #endif // V8_TARGET_ARCH_IA32 | 4412 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |