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 3348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3359 | 3359 |
3360 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( | 3360 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
3361 Handle<Map> receiver_map) { | 3361 Handle<Map> receiver_map) { |
3362 // ----------- S t a t e ------------- | 3362 // ----------- S t a t e ------------- |
3363 // -- ecx : key | 3363 // -- ecx : key |
3364 // -- edx : receiver | 3364 // -- edx : receiver |
3365 // -- esp[0] : return address | 3365 // -- esp[0] : return address |
3366 // ----------------------------------- | 3366 // ----------------------------------- |
3367 | 3367 |
3368 ElementsKind elements_kind = receiver_map->elements_kind(); | 3368 ElementsKind elements_kind = receiver_map->elements_kind(); |
3369 Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); | 3369 if (receiver_map->has_fast_elements() || |
3370 | 3370 receiver_map->has_external_array_elements()) { |
3371 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); | 3371 Handle<Code> stub = KeyedLoadFastElementStub( |
| 3372 receiver_map->instance_type() == JS_ARRAY_TYPE, |
| 3373 elements_kind).GetCode(); |
| 3374 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); |
| 3375 } else { |
| 3376 Handle<Code> stub = |
| 3377 KeyedLoadDictionaryElementStub().GetCode(); |
| 3378 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); |
| 3379 } |
3372 | 3380 |
3373 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3381 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3374 | 3382 |
3375 // Return the generated code. | 3383 // Return the generated code. |
3376 return GetCode(Code::NORMAL, factory()->empty_string()); | 3384 return GetCode(Code::NORMAL, factory()->empty_string()); |
3377 } | 3385 } |
3378 | 3386 |
3379 | 3387 |
3380 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( | 3388 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( |
3381 MapHandleList* receiver_maps, | 3389 MapHandleList* receiver_maps, |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3622 __ j(sign, fail); | 3630 __ j(sign, fail); |
3623 __ SmiTag(scratch); | 3631 __ SmiTag(scratch); |
3624 __ mov(key, scratch); | 3632 __ mov(key, scratch); |
3625 __ bind(&key_ok); | 3633 __ bind(&key_ok); |
3626 } else { | 3634 } else { |
3627 __ JumpIfNotSmi(key, fail); | 3635 __ JumpIfNotSmi(key, fail); |
3628 } | 3636 } |
3629 } | 3637 } |
3630 | 3638 |
3631 | 3639 |
3632 void KeyedLoadStubCompiler::GenerateLoadExternalArray( | |
3633 MacroAssembler* masm, | |
3634 ElementsKind elements_kind) { | |
3635 // ----------- S t a t e ------------- | |
3636 // -- ecx : key | |
3637 // -- edx : receiver | |
3638 // -- esp[0] : return address | |
3639 // ----------------------------------- | |
3640 Label miss_force_generic, failed_allocation, slow; | |
3641 | |
3642 // This stub is meant to be tail-jumped to, the receiver must already | |
3643 // have been verified by the caller to not be a smi. | |
3644 | |
3645 // Check that the key is a smi or a heap number convertible to a smi. | |
3646 GenerateSmiKeyCheck(masm, ecx, eax, xmm0, xmm1, &miss_force_generic); | |
3647 | |
3648 // Check that the index is in range. | |
3649 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); | |
3650 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); | |
3651 // Unsigned comparison catches both negative and too-large values. | |
3652 __ j(above_equal, &miss_force_generic); | |
3653 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); | |
3654 // ebx: base pointer of external storage | |
3655 switch (elements_kind) { | |
3656 case EXTERNAL_BYTE_ELEMENTS: | |
3657 __ SmiUntag(ecx); // Untag the index. | |
3658 __ movsx_b(eax, Operand(ebx, ecx, times_1, 0)); | |
3659 break; | |
3660 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
3661 case EXTERNAL_PIXEL_ELEMENTS: | |
3662 __ SmiUntag(ecx); // Untag the index. | |
3663 __ movzx_b(eax, Operand(ebx, ecx, times_1, 0)); | |
3664 break; | |
3665 case EXTERNAL_SHORT_ELEMENTS: | |
3666 __ movsx_w(eax, Operand(ebx, ecx, times_1, 0)); | |
3667 break; | |
3668 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
3669 __ movzx_w(eax, Operand(ebx, ecx, times_1, 0)); | |
3670 break; | |
3671 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
3672 case EXTERNAL_INT_ELEMENTS: | |
3673 __ mov(eax, Operand(ebx, ecx, times_2, 0)); | |
3674 break; | |
3675 case EXTERNAL_FLOAT_ELEMENTS: | |
3676 __ fld_s(Operand(ebx, ecx, times_2, 0)); | |
3677 break; | |
3678 case EXTERNAL_DOUBLE_ELEMENTS: | |
3679 __ fld_d(Operand(ebx, ecx, times_4, 0)); | |
3680 break; | |
3681 default: | |
3682 UNREACHABLE(); | |
3683 break; | |
3684 } | |
3685 | |
3686 // For integer array types: | |
3687 // eax: value | |
3688 // For floating-point array type: | |
3689 // FP(0): value | |
3690 | |
3691 if (elements_kind == EXTERNAL_INT_ELEMENTS || | |
3692 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { | |
3693 // For the Int and UnsignedInt array types, we need to see whether | |
3694 // the value can be represented in a Smi. If not, we need to convert | |
3695 // it to a HeapNumber. | |
3696 Label box_int; | |
3697 if (elements_kind == EXTERNAL_INT_ELEMENTS) { | |
3698 __ cmp(eax, 0xc0000000); | |
3699 __ j(sign, &box_int); | |
3700 } else { | |
3701 ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); | |
3702 // The test is different for unsigned int values. Since we need | |
3703 // the value to be in the range of a positive smi, we can't | |
3704 // handle either of the top two bits being set in the value. | |
3705 __ test(eax, Immediate(0xc0000000)); | |
3706 __ j(not_zero, &box_int); | |
3707 } | |
3708 | |
3709 __ SmiTag(eax); | |
3710 __ ret(0); | |
3711 | |
3712 __ bind(&box_int); | |
3713 | |
3714 // Allocate a HeapNumber for the int and perform int-to-double | |
3715 // conversion. | |
3716 if (elements_kind == EXTERNAL_INT_ELEMENTS) { | |
3717 __ push(eax); | |
3718 __ fild_s(Operand(esp, 0)); | |
3719 __ pop(eax); | |
3720 } else { | |
3721 ASSERT_EQ(EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); | |
3722 // Need to zero-extend the value. | |
3723 // There's no fild variant for unsigned values, so zero-extend | |
3724 // to a 64-bit int manually. | |
3725 __ push(Immediate(0)); | |
3726 __ push(eax); | |
3727 __ fild_d(Operand(esp, 0)); | |
3728 __ pop(eax); | |
3729 __ pop(eax); | |
3730 } | |
3731 // FP(0): value | |
3732 __ AllocateHeapNumber(eax, ebx, edi, &failed_allocation); | |
3733 // Set the value. | |
3734 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | |
3735 __ ret(0); | |
3736 } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | |
3737 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | |
3738 // For the floating-point array type, we need to always allocate a | |
3739 // HeapNumber. | |
3740 __ AllocateHeapNumber(eax, ebx, edi, &failed_allocation); | |
3741 // Set the value. | |
3742 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | |
3743 __ ret(0); | |
3744 } else { | |
3745 __ SmiTag(eax); | |
3746 __ ret(0); | |
3747 } | |
3748 | |
3749 // If we fail allocation of the HeapNumber, we still have a value on | |
3750 // top of the FPU stack. Remove it. | |
3751 __ bind(&failed_allocation); | |
3752 __ fstp(0); | |
3753 // Fall through to slow case. | |
3754 | |
3755 // Slow case: Jump to runtime. | |
3756 __ bind(&slow); | |
3757 Counters* counters = masm->isolate()->counters(); | |
3758 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); | |
3759 | |
3760 // ----------- S t a t e ------------- | |
3761 // -- ecx : key | |
3762 // -- edx : receiver | |
3763 // -- esp[0] : return address | |
3764 // ----------------------------------- | |
3765 | |
3766 Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow(); | |
3767 __ jmp(ic, RelocInfo::CODE_TARGET); | |
3768 | |
3769 // ----------- S t a t e ------------- | |
3770 // -- ecx : key | |
3771 // -- edx : receiver | |
3772 // -- esp[0] : return address | |
3773 // ----------------------------------- | |
3774 | |
3775 // Miss case: Jump to runtime. | |
3776 __ bind(&miss_force_generic); | |
3777 Handle<Code> miss_ic = | |
3778 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | |
3779 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | |
3780 } | |
3781 | |
3782 | |
3783 void KeyedStoreStubCompiler::GenerateStoreExternalArray( | 3640 void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
3784 MacroAssembler* masm, | 3641 MacroAssembler* masm, |
3785 ElementsKind elements_kind) { | 3642 ElementsKind elements_kind) { |
3786 // ----------- S t a t e ------------- | 3643 // ----------- S t a t e ------------- |
3787 // -- eax : value | 3644 // -- eax : value |
3788 // -- ecx : key | 3645 // -- ecx : key |
3789 // -- edx : receiver | 3646 // -- edx : receiver |
3790 // -- esp[0] : return address | 3647 // -- esp[0] : return address |
3791 // ----------------------------------- | 3648 // ----------------------------------- |
3792 Label miss_force_generic, slow, check_heap_number; | 3649 Label miss_force_generic, slow, check_heap_number; |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3972 // -- esp[0] : return address | 3829 // -- esp[0] : return address |
3973 // ----------------------------------- | 3830 // ----------------------------------- |
3974 | 3831 |
3975 __ bind(&miss_force_generic); | 3832 __ bind(&miss_force_generic); |
3976 Handle<Code> miss_ic = | 3833 Handle<Code> miss_ic = |
3977 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 3834 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
3978 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | 3835 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
3979 } | 3836 } |
3980 | 3837 |
3981 | 3838 |
3982 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { | |
3983 // ----------- S t a t e ------------- | |
3984 // -- ecx : key | |
3985 // -- edx : receiver | |
3986 // -- esp[0] : return address | |
3987 // ----------------------------------- | |
3988 Label miss_force_generic; | |
3989 | |
3990 // This stub is meant to be tail-jumped to, the receiver must already | |
3991 // have been verified by the caller to not be a smi. | |
3992 | |
3993 // Check that the key is a smi or a heap number convertible to a smi. | |
3994 GenerateSmiKeyCheck(masm, ecx, eax, xmm0, xmm1, &miss_force_generic); | |
3995 | |
3996 // Get the elements array. | |
3997 __ mov(eax, FieldOperand(edx, JSObject::kElementsOffset)); | |
3998 __ AssertFastElements(eax); | |
3999 | |
4000 // Check that the key is within bounds. | |
4001 __ cmp(ecx, FieldOperand(eax, FixedArray::kLengthOffset)); | |
4002 __ j(above_equal, &miss_force_generic); | |
4003 | |
4004 // Load the result and make sure it's not the hole. | |
4005 __ mov(ebx, Operand(eax, ecx, times_2, | |
4006 FixedArray::kHeaderSize - kHeapObjectTag)); | |
4007 __ cmp(ebx, masm->isolate()->factory()->the_hole_value()); | |
4008 __ j(equal, &miss_force_generic); | |
4009 __ mov(eax, ebx); | |
4010 __ ret(0); | |
4011 | |
4012 __ bind(&miss_force_generic); | |
4013 Handle<Code> miss_ic = | |
4014 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | |
4015 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | |
4016 } | |
4017 | |
4018 | |
4019 void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( | |
4020 MacroAssembler* masm) { | |
4021 // ----------- S t a t e ------------- | |
4022 // -- ecx : key | |
4023 // -- edx : receiver | |
4024 // -- esp[0] : return address | |
4025 // ----------------------------------- | |
4026 Label miss_force_generic, slow_allocate_heapnumber; | |
4027 | |
4028 // This stub is meant to be tail-jumped to, the receiver must already | |
4029 // have been verified by the caller to not be a smi. | |
4030 | |
4031 // Check that the key is a smi or a heap number convertible to a smi. | |
4032 GenerateSmiKeyCheck(masm, ecx, eax, xmm0, xmm1, &miss_force_generic); | |
4033 | |
4034 // Get the elements array. | |
4035 __ mov(eax, FieldOperand(edx, JSObject::kElementsOffset)); | |
4036 __ AssertFastElements(eax); | |
4037 | |
4038 // Check that the key is within bounds. | |
4039 __ cmp(ecx, FieldOperand(eax, FixedDoubleArray::kLengthOffset)); | |
4040 __ j(above_equal, &miss_force_generic); | |
4041 | |
4042 // Check for the hole | |
4043 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); | |
4044 __ cmp(FieldOperand(eax, ecx, times_4, offset), Immediate(kHoleNanUpper32)); | |
4045 __ j(equal, &miss_force_generic); | |
4046 | |
4047 // Always allocate a heap number for the result. | |
4048 if (CpuFeatures::IsSupported(SSE2)) { | |
4049 CpuFeatures::Scope use_sse2(SSE2); | |
4050 __ movdbl(xmm0, FieldOperand(eax, ecx, times_4, | |
4051 FixedDoubleArray::kHeaderSize)); | |
4052 } else { | |
4053 __ fld_d(FieldOperand(eax, ecx, times_4, FixedDoubleArray::kHeaderSize)); | |
4054 } | |
4055 __ AllocateHeapNumber(eax, ebx, edi, &slow_allocate_heapnumber); | |
4056 // Set the value. | |
4057 if (CpuFeatures::IsSupported(SSE2)) { | |
4058 CpuFeatures::Scope use_sse2(SSE2); | |
4059 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | |
4060 } else { | |
4061 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | |
4062 } | |
4063 __ ret(0); | |
4064 | |
4065 __ bind(&slow_allocate_heapnumber); | |
4066 // A value was pushed on the floating point stack before the allocation, if | |
4067 // the allocation fails it needs to be removed. | |
4068 if (!CpuFeatures::IsSupported(SSE2)) { | |
4069 __ fstp(0); | |
4070 } | |
4071 Handle<Code> slow_ic = | |
4072 masm->isolate()->builtins()->KeyedLoadIC_Slow(); | |
4073 __ jmp(slow_ic, RelocInfo::CODE_TARGET); | |
4074 | |
4075 __ bind(&miss_force_generic); | |
4076 Handle<Code> miss_ic = | |
4077 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | |
4078 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | |
4079 } | |
4080 | |
4081 | |
4082 void KeyedStoreStubCompiler::GenerateStoreFastElement( | 3839 void KeyedStoreStubCompiler::GenerateStoreFastElement( |
4083 MacroAssembler* masm, | 3840 MacroAssembler* masm, |
4084 bool is_js_array, | 3841 bool is_js_array, |
4085 ElementsKind elements_kind, | 3842 ElementsKind elements_kind, |
4086 KeyedAccessGrowMode grow_mode) { | 3843 KeyedAccessGrowMode grow_mode) { |
4087 // ----------- S t a t e ------------- | 3844 // ----------- S t a t e ------------- |
4088 // -- eax : value | 3845 // -- eax : value |
4089 // -- ecx : key | 3846 // -- ecx : key |
4090 // -- edx : receiver | 3847 // -- edx : receiver |
4091 // -- esp[0] : return address | 3848 // -- esp[0] : return address |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4362 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 4119 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
4363 } | 4120 } |
4364 } | 4121 } |
4365 | 4122 |
4366 | 4123 |
4367 #undef __ | 4124 #undef __ |
4368 | 4125 |
4369 } } // namespace v8::internal | 4126 } } // namespace v8::internal |
4370 | 4127 |
4371 #endif // V8_TARGET_ARCH_IA32 | 4128 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |