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