Chromium Code Reviews| 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 3789 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3800 &if_keyisinvalid); | 3800 &if_keyisinvalid); |
| 3801 assembler->Bind(&if_keyispositivesmi); | 3801 assembler->Bind(&if_keyispositivesmi); |
| 3802 assembler->TailCallRuntime(Runtime::kLoadElementWithInterceptor, context, | 3802 assembler->TailCallRuntime(Runtime::kLoadElementWithInterceptor, context, |
| 3803 receiver, key); | 3803 receiver, key); |
| 3804 | 3804 |
| 3805 assembler->Bind(&if_keyisinvalid); | 3805 assembler->Bind(&if_keyisinvalid); |
| 3806 assembler->TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, key, | 3806 assembler->TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, key, |
| 3807 slot, vector); | 3807 slot, vector); |
| 3808 } | 3808 } |
| 3809 | 3809 |
| 3810 void FastCloneShallowObjectStub::GenerateAssembly( | 3810 // static |
| 3811 CodeStubAssembler* assembler) const { | 3811 bool FastCloneShallowObjectStub::IsSupported(ObjectLiteral* expr) { |
| 3812 typedef CodeStubAssembler::Label Label; | 3812 // FastCloneShallowObjectStub doesn't copy elements, and object literals don't |
| 3813 // support copy-on-write (COW) elements for now. | |
| 3814 // TODO(mvstanton): make object literals support COW elements. | |
| 3815 return expr->fast_elements() && expr->has_shallow_properties() && | |
| 3816 expr->properties_count() <= kMaximumClonedProperties; | |
| 3817 } | |
| 3818 | |
| 3819 // static | |
| 3820 int FastCloneShallowObjectStub::PropertiesCount(int literal_length) { | |
|
Michael Starzinger
2016/04/29 08:37:31
Non-actionable question just for my understanding:
Toon Verwaest
2016/04/29 09:07:10
Yes, they are the same; and they have to be the sa
Michael Starzinger
2016/04/29 09:51:36
Acknowledged. Thanks, makes sense. +1 on eventual
rmcilroy
2016/04/29 13:53:21
Ack. Added a TODO towards unification.
| |
| 3821 return literal_length == 0 | |
| 3822 ? JSObject::kInitialGlobalObjectUnusedPropertiesCount | |
| 3823 : literal_length; | |
| 3824 } | |
| 3825 | |
| 3826 // static | |
| 3827 compiler::Node* FastCloneShallowObjectStub::GenerateFastPath( | |
| 3828 CodeStubAssembler* assembler, compiler::CodeAssembler::Label* call_runtime, | |
| 3829 compiler::Node* closure, compiler::Node* literals_index, | |
| 3830 compiler::Node* properties_count) { | |
| 3813 typedef compiler::Node Node; | 3831 typedef compiler::Node Node; |
| 3814 Label call_runtime(assembler); | 3832 typedef compiler::CodeAssembler::Label Label; |
| 3815 Node* closure = assembler->Parameter(0); | 3833 typedef compiler::CodeAssembler::Variable Variable; |
| 3816 Node* literals_index = assembler->Parameter(1); | |
| 3817 | 3834 |
| 3818 Node* undefined = assembler->UndefinedConstant(); | 3835 Node* undefined = assembler->UndefinedConstant(); |
| 3819 Node* literals_array = | 3836 Node* literals_array = |
| 3820 assembler->LoadObjectField(closure, JSFunction::kLiteralsOffset); | 3837 assembler->LoadObjectField(closure, JSFunction::kLiteralsOffset); |
| 3821 Node* allocation_site = assembler->LoadFixedArrayElementSmiIndex( | 3838 Node* allocation_site = assembler->LoadFixedArrayElementSmiIndex( |
| 3822 literals_array, literals_index, | 3839 literals_array, literals_index, |
| 3823 LiteralsArray::kFirstLiteralIndex * kPointerSize); | 3840 LiteralsArray::kFirstLiteralIndex * kPointerSize); |
| 3824 assembler->GotoIf(assembler->WordEqual(allocation_site, undefined), | 3841 assembler->GotoIf(assembler->WordEqual(allocation_site, undefined), |
| 3825 &call_runtime); | 3842 call_runtime); |
| 3826 | 3843 |
| 3844 // Calculate the object and allocation size based on the properties count. | |
| 3845 Node* object_size = assembler->IntPtrAdd( | |
| 3846 assembler->WordShl(properties_count, kPointerSizeLog2), | |
| 3847 assembler->IntPtrConstant(JSObject::kHeaderSize)); | |
| 3848 Node* allocation_size = object_size; | |
| 3849 if (FLAG_allocation_site_pretenuring) { | |
| 3850 allocation_size = assembler->IntPtrAdd( | |
| 3851 object_size, assembler->IntPtrConstant(AllocationMemento::kSize)); | |
| 3852 } | |
| 3827 Node* boilerplate = assembler->LoadObjectField( | 3853 Node* boilerplate = assembler->LoadObjectField( |
| 3828 allocation_site, AllocationSite::kTransitionInfoOffset); | 3854 allocation_site, AllocationSite::kTransitionInfoOffset); |
| 3829 | |
| 3830 int length = this->length(); | |
| 3831 if (length == 0) { | |
| 3832 length = JSObject::kInitialGlobalObjectUnusedPropertiesCount; | |
| 3833 } | |
| 3834 int allocation_size = JSObject::kHeaderSize + length * kPointerSize; | |
| 3835 int object_size = allocation_size; | |
| 3836 if (FLAG_allocation_site_pretenuring) { | |
| 3837 allocation_size += AllocationMemento::kSize; | |
| 3838 } | |
| 3839 | |
| 3840 Node* boilerplate_map = assembler->LoadMap(boilerplate); | 3855 Node* boilerplate_map = assembler->LoadMap(boilerplate); |
| 3841 Node* instance_size = assembler->LoadMapInstanceSize(boilerplate_map); | 3856 Node* instance_size = assembler->LoadMapInstanceSize(boilerplate_map); |
| 3842 Node* size_in_words = | 3857 Node* size_in_words = assembler->WordShr(object_size, kPointerSizeLog2); |
| 3843 assembler->Int32Constant(object_size >> kPointerSizeLog2); | |
| 3844 assembler->GotoUnless(assembler->Word32Equal(instance_size, size_in_words), | 3858 assembler->GotoUnless(assembler->Word32Equal(instance_size, size_in_words), |
| 3845 &call_runtime); | 3859 call_runtime); |
| 3846 | 3860 |
| 3847 Node* copy = assembler->Allocate(allocation_size); | 3861 Node* copy = assembler->Allocate(allocation_size); |
| 3848 | 3862 |
| 3849 for (int i = 0; i < object_size; i += kPointerSize) { | 3863 // Copy boilerplate elements. |
| 3864 Variable offset(assembler, MachineType::PointerRepresentation()); | |
| 3865 offset.Bind(assembler->IntPtrConstant(-kHeapObjectTag)); | |
| 3866 Node* end_offset = assembler->IntPtrAdd(object_size, offset.value()); | |
| 3867 Label loop_body(assembler, &offset), loop_check(assembler, &offset); | |
| 3868 // We should always have an object size greater than zero. | |
| 3869 assembler->Goto(&loop_body); | |
| 3870 assembler->Bind(&loop_body); | |
| 3871 { | |
| 3850 // The Allocate above guarantees that the copy lies in new space. This | 3872 // The Allocate above guarantees that the copy lies in new space. This |
| 3851 // allows us to skip write barriers. This is necessary since we may also be | 3873 // allows us to skip write barriers. This is necessary since we may also be |
| 3852 // copying unboxed doubles. | 3874 // copying unboxed doubles. |
| 3853 Node* field = | 3875 Node* field = |
| 3854 assembler->LoadObjectField(boilerplate, i, MachineType::IntPtr()); | 3876 assembler->Load(MachineType::IntPtr(), boilerplate, offset.value()); |
| 3855 assembler->StoreObjectFieldNoWriteBarrier( | 3877 assembler->StoreNoWriteBarrier(MachineType::PointerRepresentation(), copy, |
| 3856 copy, i, field, MachineType::PointerRepresentation()); | 3878 offset.value(), field); |
| 3879 assembler->Goto(&loop_check); | |
| 3880 } | |
| 3881 assembler->Bind(&loop_check); | |
| 3882 { | |
| 3883 offset.Bind(assembler->IntPtrAdd(offset.value(), | |
| 3884 assembler->IntPtrConstant(kPointerSize))); | |
| 3885 assembler->GotoUnless( | |
| 3886 assembler->IntPtrGreaterThanOrEqual(offset.value(), end_offset), | |
| 3887 &loop_body); | |
| 3857 } | 3888 } |
| 3858 | 3889 |
| 3859 if (FLAG_allocation_site_pretenuring) { | 3890 if (FLAG_allocation_site_pretenuring) { |
| 3860 Node* memento = assembler->InnerAllocate(copy, object_size); | 3891 Node* memento = assembler->InnerAllocate(copy, object_size); |
| 3861 assembler->StoreObjectFieldNoWriteBarrier( | 3892 assembler->StoreObjectFieldNoWriteBarrier( |
| 3862 memento, HeapObject::kMapOffset, | 3893 memento, HeapObject::kMapOffset, |
| 3863 assembler->LoadRoot(Heap::kAllocationMementoMapRootIndex)); | 3894 assembler->LoadRoot(Heap::kAllocationMementoMapRootIndex)); |
| 3864 assembler->StoreObjectFieldNoWriteBarrier( | 3895 assembler->StoreObjectFieldNoWriteBarrier( |
| 3865 memento, AllocationMemento::kAllocationSiteOffset, allocation_site); | 3896 memento, AllocationMemento::kAllocationSiteOffset, allocation_site); |
| 3866 Node* memento_create_count = assembler->LoadObjectField( | 3897 Node* memento_create_count = assembler->LoadObjectField( |
| 3867 allocation_site, AllocationSite::kPretenureCreateCountOffset); | 3898 allocation_site, AllocationSite::kPretenureCreateCountOffset); |
| 3868 memento_create_count = assembler->SmiAdd( | 3899 memento_create_count = assembler->SmiAdd( |
| 3869 memento_create_count, assembler->SmiConstant(Smi::FromInt(1))); | 3900 memento_create_count, assembler->SmiConstant(Smi::FromInt(1))); |
| 3870 assembler->StoreObjectFieldNoWriteBarrier( | 3901 assembler->StoreObjectFieldNoWriteBarrier( |
| 3871 allocation_site, AllocationSite::kPretenureCreateCountOffset, | 3902 allocation_site, AllocationSite::kPretenureCreateCountOffset, |
| 3872 memento_create_count); | 3903 memento_create_count); |
| 3873 } | 3904 } |
| 3874 | 3905 |
| 3875 // TODO(verwaest): Allocate and fill in double boxes. | 3906 // TODO(verwaest): Allocate and fill in double boxes. |
| 3907 return copy; | |
| 3908 } | |
| 3909 | |
| 3910 void FastCloneShallowObjectStub::GenerateAssembly( | |
| 3911 CodeStubAssembler* assembler) const { | |
| 3912 typedef CodeStubAssembler::Label Label; | |
| 3913 typedef compiler::Node Node; | |
| 3914 Label call_runtime(assembler); | |
| 3915 Node* closure = assembler->Parameter(0); | |
| 3916 Node* literals_index = assembler->Parameter(1); | |
| 3917 | |
| 3918 Node* properties_count = | |
| 3919 assembler->IntPtrConstant(PropertiesCount(this->length())); | |
| 3920 Node* copy = GenerateFastPath(assembler, &call_runtime, closure, | |
| 3921 literals_index, properties_count); | |
| 3876 assembler->Return(copy); | 3922 assembler->Return(copy); |
| 3877 | 3923 |
| 3878 assembler->Bind(&call_runtime); | 3924 assembler->Bind(&call_runtime); |
| 3879 Node* constant_properties = assembler->Parameter(2); | 3925 Node* constant_properties = assembler->Parameter(2); |
| 3880 Node* flags = assembler->Parameter(3); | 3926 Node* flags = assembler->Parameter(3); |
| 3881 Node* context = assembler->Parameter(4); | 3927 Node* context = assembler->Parameter(4); |
| 3882 assembler->TailCallRuntime(Runtime::kCreateObjectLiteral, context, closure, | 3928 assembler->TailCallRuntime(Runtime::kCreateObjectLiteral, context, closure, |
| 3883 literals_index, constant_properties, flags); | 3929 literals_index, constant_properties, flags); |
| 3884 } | 3930 } |
| 3885 | 3931 |
| (...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4306 if (type->Is(Type::UntaggedPointer())) { | 4352 if (type->Is(Type::UntaggedPointer())) { |
| 4307 return Representation::External(); | 4353 return Representation::External(); |
| 4308 } | 4354 } |
| 4309 | 4355 |
| 4310 DCHECK(!type->Is(Type::Untagged())); | 4356 DCHECK(!type->Is(Type::Untagged())); |
| 4311 return Representation::Tagged(); | 4357 return Representation::Tagged(); |
| 4312 } | 4358 } |
| 4313 | 4359 |
| 4314 } // namespace internal | 4360 } // namespace internal |
| 4315 } // namespace v8 | 4361 } // namespace v8 |
| OLD | NEW |