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