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 3726 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3737 __ push(ecx); | 3737 __ push(ecx); |
3738 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi); | 3738 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi); |
3739 | 3739 |
3740 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 3740 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
3741 // tagged as a small integer. | 3741 // tagged as a small integer. |
3742 __ bind(&runtime); | 3742 __ bind(&runtime); |
3743 __ TailCallRuntime(Runtime::kHiddenStringCompare, 2, 1); | 3743 __ TailCallRuntime(Runtime::kHiddenStringCompare, 2, 1); |
3744 } | 3744 } |
3745 | 3745 |
3746 | 3746 |
3747 void ArrayPushStub::Generate(MacroAssembler* masm) { | |
3748 int argc = arguments_count(); | |
3749 | |
3750 if (argc == 0) { | |
3751 // Noop, return the length. | |
3752 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); | |
3753 __ ret((argc + 1) * kPointerSize); | |
3754 return; | |
3755 } | |
3756 | |
3757 Isolate* isolate = masm->isolate(); | |
3758 | |
3759 if (argc != 1) { | |
3760 __ TailCallExternalReference( | |
3761 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); | |
3762 return; | |
3763 } | |
3764 | |
3765 Label call_builtin, attempt_to_grow_elements, with_write_barrier; | |
3766 | |
3767 // Get the elements array of the object. | |
3768 __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset)); | |
3769 | |
3770 if (IsFastSmiOrObjectElementsKind(elements_kind())) { | |
3771 // Check that the elements are in fast mode and writable. | |
3772 __ cmp(FieldOperand(edi, HeapObject::kMapOffset), | |
3773 isolate->factory()->fixed_array_map()); | |
3774 __ j(not_equal, &call_builtin); | |
3775 } | |
3776 | |
3777 // Get the array's length into eax and calculate new length. | |
3778 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); | |
3779 STATIC_ASSERT(kSmiTagSize == 1); | |
3780 STATIC_ASSERT(kSmiTag == 0); | |
3781 __ add(eax, Immediate(Smi::FromInt(argc))); | |
3782 | |
3783 // Get the elements' length into ecx. | |
3784 __ mov(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); | |
3785 | |
3786 // Check if we could survive without allocation. | |
3787 __ cmp(eax, ecx); | |
3788 | |
3789 if (IsFastSmiOrObjectElementsKind(elements_kind())) { | |
3790 __ j(greater, &attempt_to_grow_elements); | |
3791 | |
3792 // Check if value is a smi. | |
3793 __ mov(ecx, Operand(esp, argc * kPointerSize)); | |
3794 __ JumpIfNotSmi(ecx, &with_write_barrier); | |
3795 | |
3796 // Store the value. | |
3797 __ mov(FieldOperand(edi, eax, times_half_pointer_size, | |
3798 FixedArray::kHeaderSize - argc * kPointerSize), | |
3799 ecx); | |
3800 } else { | |
3801 __ j(greater, &call_builtin); | |
3802 | |
3803 __ mov(ecx, Operand(esp, argc * kPointerSize)); | |
3804 __ StoreNumberToDoubleElements( | |
3805 ecx, edi, eax, ecx, xmm0, &call_builtin, true, argc * kDoubleSize); | |
3806 } | |
3807 | |
3808 // Save new length. | |
3809 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); | |
3810 __ ret((argc + 1) * kPointerSize); | |
3811 | |
3812 if (IsFastDoubleElementsKind(elements_kind())) { | |
3813 __ bind(&call_builtin); | |
3814 __ TailCallExternalReference( | |
3815 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); | |
3816 return; | |
3817 } | |
3818 | |
3819 __ bind(&with_write_barrier); | |
3820 | |
3821 if (IsFastSmiElementsKind(elements_kind())) { | |
3822 if (FLAG_trace_elements_transitions) __ jmp(&call_builtin); | |
3823 | |
3824 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | |
3825 isolate->factory()->heap_number_map()); | |
3826 __ j(equal, &call_builtin); | |
3827 | |
3828 ElementsKind target_kind = IsHoleyElementsKind(elements_kind()) | |
3829 ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS; | |
3830 __ mov(ebx, ContextOperand(esi, Context::GLOBAL_OBJECT_INDEX)); | |
3831 __ mov(ebx, FieldOperand(ebx, GlobalObject::kNativeContextOffset)); | |
3832 __ mov(ebx, ContextOperand(ebx, Context::JS_ARRAY_MAPS_INDEX)); | |
3833 const int header_size = FixedArrayBase::kHeaderSize; | |
3834 // Verify that the object can be transitioned in place. | |
3835 const int origin_offset = header_size + elements_kind() * kPointerSize; | |
3836 __ mov(edi, FieldOperand(ebx, origin_offset)); | |
3837 __ cmp(edi, FieldOperand(edx, HeapObject::kMapOffset)); | |
3838 __ j(not_equal, &call_builtin); | |
3839 | |
3840 const int target_offset = header_size + target_kind * kPointerSize; | |
3841 __ mov(ebx, FieldOperand(ebx, target_offset)); | |
3842 ElementsTransitionGenerator::GenerateMapChangeElementsTransition( | |
3843 masm, DONT_TRACK_ALLOCATION_SITE, NULL); | |
3844 // Restore edi used as a scratch register for the write barrier used while | |
3845 // setting the map. | |
3846 __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset)); | |
3847 } | |
3848 | |
3849 // Save new length. | |
3850 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); | |
3851 | |
3852 // Store the value. | |
3853 __ lea(edx, FieldOperand(edi, eax, times_half_pointer_size, | |
3854 FixedArray::kHeaderSize - argc * kPointerSize)); | |
3855 __ mov(Operand(edx, 0), ecx); | |
3856 | |
3857 __ RecordWrite(edi, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, | |
3858 OMIT_SMI_CHECK); | |
3859 | |
3860 __ ret((argc + 1) * kPointerSize); | |
3861 | |
3862 __ bind(&attempt_to_grow_elements); | |
3863 if (!FLAG_inline_new) { | |
3864 __ bind(&call_builtin); | |
3865 __ TailCallExternalReference( | |
3866 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); | |
3867 return; | |
3868 } | |
3869 | |
3870 __ mov(ebx, Operand(esp, argc * kPointerSize)); | |
3871 // Growing elements that are SMI-only requires special handling in case the | |
3872 // new element is non-Smi. For now, delegate to the builtin. | |
3873 if (IsFastSmiElementsKind(elements_kind())) { | |
3874 __ JumpIfNotSmi(ebx, &call_builtin); | |
3875 } | |
3876 | |
3877 // We could be lucky and the elements array could be at the top of new-space. | |
3878 // In this case we can just grow it in place by moving the allocation pointer | |
3879 // up. | |
3880 ExternalReference new_space_allocation_top = | |
3881 ExternalReference::new_space_allocation_top_address(isolate); | |
3882 ExternalReference new_space_allocation_limit = | |
3883 ExternalReference::new_space_allocation_limit_address(isolate); | |
3884 | |
3885 const int kAllocationDelta = 4; | |
3886 ASSERT(kAllocationDelta >= argc); | |
3887 // Load top. | |
3888 __ mov(ecx, Operand::StaticVariable(new_space_allocation_top)); | |
3889 | |
3890 // Check if it's the end of elements. | |
3891 __ lea(edx, FieldOperand(edi, eax, times_half_pointer_size, | |
3892 FixedArray::kHeaderSize - argc * kPointerSize)); | |
3893 __ cmp(edx, ecx); | |
3894 __ j(not_equal, &call_builtin); | |
3895 __ add(ecx, Immediate(kAllocationDelta * kPointerSize)); | |
3896 __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit)); | |
3897 __ j(above, &call_builtin); | |
3898 | |
3899 // We fit and could grow elements. | |
3900 __ mov(Operand::StaticVariable(new_space_allocation_top), ecx); | |
3901 | |
3902 // Push the argument... | |
3903 __ mov(Operand(edx, 0), ebx); | |
3904 // ... and fill the rest with holes. | |
3905 for (int i = 1; i < kAllocationDelta; i++) { | |
3906 __ mov(Operand(edx, i * kPointerSize), | |
3907 isolate->factory()->the_hole_value()); | |
3908 } | |
3909 | |
3910 if (IsFastObjectElementsKind(elements_kind())) { | |
3911 // We know the elements array is in new space so we don't need the | |
3912 // remembered set, but we just pushed a value onto it so we may have to tell | |
3913 // the incremental marker to rescan the object that we just grew. We don't | |
3914 // need to worry about the holes because they are in old space and already | |
3915 // marked black. | |
3916 __ RecordWrite(edi, edx, ebx, kDontSaveFPRegs, OMIT_REMEMBERED_SET); | |
3917 } | |
3918 | |
3919 // Restore receiver to edx as finish sequence assumes it's here. | |
3920 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | |
3921 | |
3922 // Increment element's and array's sizes. | |
3923 __ add(FieldOperand(edi, FixedArray::kLengthOffset), | |
3924 Immediate(Smi::FromInt(kAllocationDelta))); | |
3925 | |
3926 // NOTE: This only happen in new-space, where we don't care about the | |
3927 // black-byte-count on pages. Otherwise we should update that too if the | |
3928 // object is black. | |
3929 | |
3930 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); | |
3931 __ ret((argc + 1) * kPointerSize); | |
3932 | |
3933 __ bind(&call_builtin); | |
3934 __ TailCallExternalReference( | |
3935 ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); | |
3936 } | |
3937 | |
3938 | |
3939 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { | 3747 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { |
3940 // ----------- S t a t e ------------- | 3748 // ----------- S t a t e ------------- |
3941 // -- edx : left | 3749 // -- edx : left |
3942 // -- eax : right | 3750 // -- eax : right |
3943 // -- esp[0] : return address | 3751 // -- esp[0] : return address |
3944 // ----------------------------------- | 3752 // ----------------------------------- |
3945 Isolate* isolate = masm->isolate(); | 3753 Isolate* isolate = masm->isolate(); |
3946 | 3754 |
3947 // Load ecx with the allocation site. We stick an undefined dummy value here | 3755 // Load ecx with the allocation site. We stick an undefined dummy value here |
3948 // and replace it with the real allocation site later when we instantiate this | 3756 // and replace it with the real allocation site later when we instantiate this |
(...skipping 1413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5362 Operand(ebp, 7 * kPointerSize), | 5170 Operand(ebp, 7 * kPointerSize), |
5363 NULL); | 5171 NULL); |
5364 } | 5172 } |
5365 | 5173 |
5366 | 5174 |
5367 #undef __ | 5175 #undef __ |
5368 | 5176 |
5369 } } // namespace v8::internal | 5177 } } // namespace v8::internal |
5370 | 5178 |
5371 #endif // V8_TARGET_ARCH_IA32 | 5179 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |