OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/code-stubs.h" | 5 #include "src/code-stubs.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 3729 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3740 &if_keyisinvalid); | 3740 &if_keyisinvalid); |
3741 assembler->Bind(&if_keyispositivesmi); | 3741 assembler->Bind(&if_keyispositivesmi); |
3742 assembler->TailCallRuntime(Runtime::kLoadElementWithInterceptor, context, | 3742 assembler->TailCallRuntime(Runtime::kLoadElementWithInterceptor, context, |
3743 receiver, key); | 3743 receiver, key); |
3744 | 3744 |
3745 assembler->Bind(&if_keyisinvalid); | 3745 assembler->Bind(&if_keyisinvalid); |
3746 assembler->TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, key, | 3746 assembler->TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, key, |
3747 slot, vector); | 3747 slot, vector); |
3748 } | 3748 } |
3749 | 3749 |
3750 void FastCloneShallowObjectStub::GenerateAssembly( | 3750 // static |
3751 CodeStubAssembler* assembler) const { | 3751 bool FastCloneShallowObjectStub::IsSupported(ObjectLiteral* expr) { |
3752 typedef CodeStubAssembler::Label Label; | 3752 // FastCloneShallowObjectStub doesn't copy elements, and object literals don't |
| 3753 // support copy-on-write (COW) elements for now. |
| 3754 // TODO(mvstanton): make object literals support COW elements. |
| 3755 return expr->fast_elements() && expr->has_shallow_properties() && |
| 3756 expr->properties_count() <= kMaximumClonedProperties; |
| 3757 } |
| 3758 |
| 3759 // static |
| 3760 int FastCloneShallowObjectStub::PropertiesCount(int literal_length) { |
| 3761 // This heuristic of setting empty literals to have |
| 3762 // kInitialGlobalObjectUnusedPropertiesCount must remain in-sync with the |
| 3763 // runtime. |
| 3764 // TODO(verwaest): Unify this with the heuristic in the runtime. |
| 3765 return literal_length == 0 |
| 3766 ? JSObject::kInitialGlobalObjectUnusedPropertiesCount |
| 3767 : literal_length; |
| 3768 } |
| 3769 |
| 3770 // static |
| 3771 compiler::Node* FastCloneShallowObjectStub::GenerateFastPath( |
| 3772 CodeStubAssembler* assembler, compiler::CodeAssembler::Label* call_runtime, |
| 3773 compiler::Node* closure, compiler::Node* literals_index, |
| 3774 compiler::Node* properties_count) { |
3753 typedef compiler::Node Node; | 3775 typedef compiler::Node Node; |
3754 Label call_runtime(assembler); | 3776 typedef compiler::CodeAssembler::Label Label; |
3755 Node* closure = assembler->Parameter(0); | 3777 typedef compiler::CodeAssembler::Variable Variable; |
3756 Node* literals_index = assembler->Parameter(1); | |
3757 | 3778 |
3758 Node* undefined = assembler->UndefinedConstant(); | 3779 Node* undefined = assembler->UndefinedConstant(); |
3759 Node* literals_array = | 3780 Node* literals_array = |
3760 assembler->LoadObjectField(closure, JSFunction::kLiteralsOffset); | 3781 assembler->LoadObjectField(closure, JSFunction::kLiteralsOffset); |
3761 Node* allocation_site = assembler->LoadFixedArrayElementSmiIndex( | 3782 Node* allocation_site = assembler->LoadFixedArrayElementSmiIndex( |
3762 literals_array, literals_index, | 3783 literals_array, literals_index, |
3763 LiteralsArray::kFirstLiteralIndex * kPointerSize); | 3784 LiteralsArray::kFirstLiteralIndex * kPointerSize); |
3764 assembler->GotoIf(assembler->WordEqual(allocation_site, undefined), | 3785 assembler->GotoIf(assembler->WordEqual(allocation_site, undefined), |
3765 &call_runtime); | 3786 call_runtime); |
3766 | 3787 |
| 3788 // Calculate the object and allocation size based on the properties count. |
| 3789 Node* object_size = assembler->IntPtrAdd( |
| 3790 assembler->WordShl(properties_count, kPointerSizeLog2), |
| 3791 assembler->IntPtrConstant(JSObject::kHeaderSize)); |
| 3792 Node* allocation_size = object_size; |
| 3793 if (FLAG_allocation_site_pretenuring) { |
| 3794 allocation_size = assembler->IntPtrAdd( |
| 3795 object_size, assembler->IntPtrConstant(AllocationMemento::kSize)); |
| 3796 } |
3767 Node* boilerplate = assembler->LoadObjectField( | 3797 Node* boilerplate = assembler->LoadObjectField( |
3768 allocation_site, AllocationSite::kTransitionInfoOffset); | 3798 allocation_site, AllocationSite::kTransitionInfoOffset); |
3769 | |
3770 int length = this->length(); | |
3771 if (length == 0) { | |
3772 length = JSObject::kInitialGlobalObjectUnusedPropertiesCount; | |
3773 } | |
3774 int allocation_size = JSObject::kHeaderSize + length * kPointerSize; | |
3775 int object_size = allocation_size; | |
3776 if (FLAG_allocation_site_pretenuring) { | |
3777 allocation_size += AllocationMemento::kSize; | |
3778 } | |
3779 | |
3780 Node* boilerplate_map = assembler->LoadMap(boilerplate); | 3799 Node* boilerplate_map = assembler->LoadMap(boilerplate); |
3781 Node* instance_size = assembler->LoadMapInstanceSize(boilerplate_map); | 3800 Node* instance_size = assembler->LoadMapInstanceSize(boilerplate_map); |
3782 Node* size_in_words = | 3801 Node* size_in_words = assembler->WordShr(object_size, kPointerSizeLog2); |
3783 assembler->Int32Constant(object_size >> kPointerSizeLog2); | |
3784 assembler->GotoUnless(assembler->Word32Equal(instance_size, size_in_words), | 3802 assembler->GotoUnless(assembler->Word32Equal(instance_size, size_in_words), |
3785 &call_runtime); | 3803 call_runtime); |
3786 | 3804 |
3787 Node* copy = assembler->Allocate(allocation_size); | 3805 Node* copy = assembler->Allocate(allocation_size); |
3788 | 3806 |
3789 for (int i = 0; i < object_size; i += kPointerSize) { | 3807 // Copy boilerplate elements. |
| 3808 Variable offset(assembler, MachineType::PointerRepresentation()); |
| 3809 offset.Bind(assembler->IntPtrConstant(-kHeapObjectTag)); |
| 3810 Node* end_offset = assembler->IntPtrAdd(object_size, offset.value()); |
| 3811 Label loop_body(assembler, &offset), loop_check(assembler, &offset); |
| 3812 // We should always have an object size greater than zero. |
| 3813 assembler->Goto(&loop_body); |
| 3814 assembler->Bind(&loop_body); |
| 3815 { |
3790 // The Allocate above guarantees that the copy lies in new space. This | 3816 // The Allocate above guarantees that the copy lies in new space. This |
3791 // allows us to skip write barriers. This is necessary since we may also be | 3817 // allows us to skip write barriers. This is necessary since we may also be |
3792 // copying unboxed doubles. | 3818 // copying unboxed doubles. |
3793 Node* field = | 3819 Node* field = |
3794 assembler->LoadObjectField(boilerplate, i, MachineType::IntPtr()); | 3820 assembler->Load(MachineType::IntPtr(), boilerplate, offset.value()); |
3795 assembler->StoreObjectFieldNoWriteBarrier( | 3821 assembler->StoreNoWriteBarrier(MachineType::PointerRepresentation(), copy, |
3796 copy, i, field, MachineType::PointerRepresentation()); | 3822 offset.value(), field); |
| 3823 assembler->Goto(&loop_check); |
| 3824 } |
| 3825 assembler->Bind(&loop_check); |
| 3826 { |
| 3827 offset.Bind(assembler->IntPtrAdd(offset.value(), |
| 3828 assembler->IntPtrConstant(kPointerSize))); |
| 3829 assembler->GotoUnless( |
| 3830 assembler->IntPtrGreaterThanOrEqual(offset.value(), end_offset), |
| 3831 &loop_body); |
3797 } | 3832 } |
3798 | 3833 |
3799 if (FLAG_allocation_site_pretenuring) { | 3834 if (FLAG_allocation_site_pretenuring) { |
3800 Node* memento = assembler->InnerAllocate(copy, object_size); | 3835 Node* memento = assembler->InnerAllocate(copy, object_size); |
3801 assembler->StoreObjectFieldNoWriteBarrier( | 3836 assembler->StoreObjectFieldNoWriteBarrier( |
3802 memento, HeapObject::kMapOffset, | 3837 memento, HeapObject::kMapOffset, |
3803 assembler->LoadRoot(Heap::kAllocationMementoMapRootIndex)); | 3838 assembler->LoadRoot(Heap::kAllocationMementoMapRootIndex)); |
3804 assembler->StoreObjectFieldNoWriteBarrier( | 3839 assembler->StoreObjectFieldNoWriteBarrier( |
3805 memento, AllocationMemento::kAllocationSiteOffset, allocation_site); | 3840 memento, AllocationMemento::kAllocationSiteOffset, allocation_site); |
3806 Node* memento_create_count = assembler->LoadObjectField( | 3841 Node* memento_create_count = assembler->LoadObjectField( |
3807 allocation_site, AllocationSite::kPretenureCreateCountOffset); | 3842 allocation_site, AllocationSite::kPretenureCreateCountOffset); |
3808 memento_create_count = assembler->SmiAdd( | 3843 memento_create_count = assembler->SmiAdd( |
3809 memento_create_count, assembler->SmiConstant(Smi::FromInt(1))); | 3844 memento_create_count, assembler->SmiConstant(Smi::FromInt(1))); |
3810 assembler->StoreObjectFieldNoWriteBarrier( | 3845 assembler->StoreObjectFieldNoWriteBarrier( |
3811 allocation_site, AllocationSite::kPretenureCreateCountOffset, | 3846 allocation_site, AllocationSite::kPretenureCreateCountOffset, |
3812 memento_create_count); | 3847 memento_create_count); |
3813 } | 3848 } |
3814 | 3849 |
3815 // TODO(verwaest): Allocate and fill in double boxes. | 3850 // TODO(verwaest): Allocate and fill in double boxes. |
| 3851 return copy; |
| 3852 } |
| 3853 |
| 3854 void FastCloneShallowObjectStub::GenerateAssembly( |
| 3855 CodeStubAssembler* assembler) const { |
| 3856 typedef CodeStubAssembler::Label Label; |
| 3857 typedef compiler::Node Node; |
| 3858 Label call_runtime(assembler); |
| 3859 Node* closure = assembler->Parameter(0); |
| 3860 Node* literals_index = assembler->Parameter(1); |
| 3861 |
| 3862 Node* properties_count = |
| 3863 assembler->IntPtrConstant(PropertiesCount(this->length())); |
| 3864 Node* copy = GenerateFastPath(assembler, &call_runtime, closure, |
| 3865 literals_index, properties_count); |
3816 assembler->Return(copy); | 3866 assembler->Return(copy); |
3817 | 3867 |
3818 assembler->Bind(&call_runtime); | 3868 assembler->Bind(&call_runtime); |
3819 Node* constant_properties = assembler->Parameter(2); | 3869 Node* constant_properties = assembler->Parameter(2); |
3820 Node* flags = assembler->Parameter(3); | 3870 Node* flags = assembler->Parameter(3); |
3821 Node* context = assembler->Parameter(4); | 3871 Node* context = assembler->Parameter(4); |
3822 assembler->TailCallRuntime(Runtime::kCreateObjectLiteral, context, closure, | 3872 assembler->TailCallRuntime(Runtime::kCreateObjectLiteral, context, closure, |
3823 literals_index, constant_properties, flags); | 3873 literals_index, constant_properties, flags); |
3824 } | 3874 } |
3825 | 3875 |
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4246 if (type->Is(Type::UntaggedPointer())) { | 4296 if (type->Is(Type::UntaggedPointer())) { |
4247 return Representation::External(); | 4297 return Representation::External(); |
4248 } | 4298 } |
4249 | 4299 |
4250 DCHECK(!type->Is(Type::Untagged())); | 4300 DCHECK(!type->Is(Type::Untagged())); |
4251 return Representation::Tagged(); | 4301 return Representation::Tagged(); |
4252 } | 4302 } |
4253 | 4303 |
4254 } // namespace internal | 4304 } // namespace internal |
4255 } // namespace v8 | 4305 } // namespace v8 |
OLD | NEW |