| 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 |