Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: src/code-stub-assembler.cc

Issue 2385423005: [stubs] Implement fast TF Builtin for Object.create (Closed)
Patch Set: rebasing Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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
5 #include "src/code-stub-assembler.h" 4 #include "src/code-stub-assembler.h"
6 #include "src/code-factory.h" 5 #include "src/code-factory.h"
7 #include "src/frames-inl.h" 6 #include "src/frames-inl.h"
8 #include "src/frames.h" 7 #include "src/frames.h"
9 #include "src/ic/handler-configuration.h" 8 #include "src/ic/handler-configuration.h"
10 #include "src/ic/stub-cache.h" 9 #include "src/ic/stub-cache.h"
11 10
12 namespace v8 { 11 namespace v8 {
13 namespace internal { 12 namespace internal {
14 13
(...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 GotoIf(Int32LessThanOrEqual(LoadMapInstanceType(prototype_map), 617 GotoIf(Int32LessThanOrEqual(LoadMapInstanceType(prototype_map),
619 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), 618 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)),
620 possibly_elements); 619 possibly_elements);
621 GotoIf(WordNotEqual(LoadElements(prototype), empty_elements), 620 GotoIf(WordNotEqual(LoadElements(prototype), empty_elements),
622 possibly_elements); 621 possibly_elements);
623 var_map.Bind(prototype_map); 622 var_map.Bind(prototype_map);
624 Goto(&loop_body); 623 Goto(&loop_body);
625 } 624 }
626 } 625 }
627 626
627 void CodeStubAssembler::BranchIfJSReceiver(Node* object, Label* if_true,
628 Label* if_false) {
629 GotoIf(TaggedIsSmi(object), if_false);
630 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
631 Branch(Int32GreaterThanOrEqual(LoadInstanceType(object),
632 Int32Constant(FIRST_JS_RECEIVER_TYPE)),
633 if_true, if_false);
634 }
635
636 void CodeStubAssembler::BranchIfJSObject(Node* object, Label* if_true,
637 Label* if_false) {
638 GotoIf(TaggedIsSmi(object), if_false);
639 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
640 Branch(Int32GreaterThanOrEqual(LoadInstanceType(object),
641 Int32Constant(FIRST_JS_OBJECT_TYPE)),
642 if_true, if_false);
643 }
644
628 void CodeStubAssembler::BranchIfFastJSArray(Node* object, Node* context, 645 void CodeStubAssembler::BranchIfFastJSArray(Node* object, Node* context,
629 Label* if_true, Label* if_false) { 646 Label* if_true, Label* if_false) {
630 // Bailout if receiver is a Smi. 647 // Bailout if receiver is a Smi.
631 GotoIf(TaggedIsSmi(object), if_false); 648 GotoIf(TaggedIsSmi(object), if_false);
632 649
633 Node* map = LoadMap(object); 650 Node* map = LoadMap(object);
634 651
635 // Bailout if instance type is not JS_ARRAY_TYPE. 652 // Bailout if instance type is not JS_ARRAY_TYPE.
636 GotoIf(WordNotEqual(LoadMapInstanceType(map), Int32Constant(JS_ARRAY_TYPE)), 653 GotoIf(WordNotEqual(LoadMapInstanceType(map), Int32Constant(JS_ARRAY_TYPE)),
637 if_false); 654 if_false);
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
778 } 795 }
779 796
780 Node* CodeStubAssembler::InnerAllocate(Node* previous, Node* offset) { 797 Node* CodeStubAssembler::InnerAllocate(Node* previous, Node* offset) {
781 return BitcastWordToTagged(IntPtrAdd(previous, offset)); 798 return BitcastWordToTagged(IntPtrAdd(previous, offset));
782 } 799 }
783 800
784 Node* CodeStubAssembler::InnerAllocate(Node* previous, int offset) { 801 Node* CodeStubAssembler::InnerAllocate(Node* previous, int offset) {
785 return InnerAllocate(previous, IntPtrConstant(offset)); 802 return InnerAllocate(previous, IntPtrConstant(offset));
786 } 803 }
787 804
805 Node* CodeStubAssembler::IsRegularHeapObjectSize(Node* size) {
806 return UintPtrLessThanOrEqual(size,
807 IntPtrConstant(kMaxRegularHeapObjectSize));
808 }
809
788 void CodeStubAssembler::BranchIfToBooleanIsTrue(Node* value, Label* if_true, 810 void CodeStubAssembler::BranchIfToBooleanIsTrue(Node* value, Label* if_true,
789 Label* if_false) { 811 Label* if_false) {
790 Label if_valueissmi(this), if_valueisnotsmi(this), if_valueisstring(this), 812 Label if_valueissmi(this), if_valueisnotsmi(this), if_valueisstring(this),
791 if_valueisheapnumber(this), if_valueisother(this); 813 if_valueisheapnumber(this), if_valueisother(this);
792 814
793 // Fast check for Boolean {value}s (common case). 815 // Fast check for Boolean {value}s (common case).
794 GotoIf(WordEqual(value, BooleanConstant(true)), if_true); 816 GotoIf(WordEqual(value, BooleanConstant(true)), if_true);
795 GotoIf(WordEqual(value, BooleanConstant(false)), if_false); 817 GotoIf(WordEqual(value, BooleanConstant(false)), if_false);
796 818
797 // Check if {value} is a Smi or a HeapObject. 819 // Check if {value} is a Smi or a HeapObject.
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
943 } 965 }
944 966
945 Node* CodeStubAssembler::LoadMap(Node* object) { 967 Node* CodeStubAssembler::LoadMap(Node* object) {
946 return LoadObjectField(object, HeapObject::kMapOffset); 968 return LoadObjectField(object, HeapObject::kMapOffset);
947 } 969 }
948 970
949 Node* CodeStubAssembler::LoadInstanceType(Node* object) { 971 Node* CodeStubAssembler::LoadInstanceType(Node* object) {
950 return LoadMapInstanceType(LoadMap(object)); 972 return LoadMapInstanceType(LoadMap(object));
951 } 973 }
952 974
975 Node* CodeStubAssembler::HasInstanceType(Node* object,
976 InstanceType instance_type) {
977 return Word32Equal(LoadInstanceType(object), Int32Constant(instance_type));
978 }
979
953 void CodeStubAssembler::AssertInstanceType(Node* object, 980 void CodeStubAssembler::AssertInstanceType(Node* object,
954 InstanceType instance_type) { 981 InstanceType instance_type) {
955 CSA_ASSERT( 982 CSA_ASSERT(HasInstanceType(object, instance_type));
956 Word32Equal(LoadInstanceType(object), Int32Constant(instance_type)));
957 } 983 }
958 984
959 Node* CodeStubAssembler::LoadProperties(Node* object) { 985 Node* CodeStubAssembler::LoadProperties(Node* object) {
960 return LoadObjectField(object, JSObject::kPropertiesOffset); 986 return LoadObjectField(object, JSObject::kPropertiesOffset);
961 } 987 }
962 988
963 Node* CodeStubAssembler::LoadElements(Node* object) { 989 Node* CodeStubAssembler::LoadElements(Node* object) {
964 return LoadObjectField(object, JSObject::kElementsOffset); 990 return LoadObjectField(object, JSObject::kElementsOffset);
965 } 991 }
966 992
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
998 } 1024 }
999 1025
1000 Node* CodeStubAssembler::LoadMapDescriptors(Node* map) { 1026 Node* CodeStubAssembler::LoadMapDescriptors(Node* map) {
1001 return LoadObjectField(map, Map::kDescriptorsOffset); 1027 return LoadObjectField(map, Map::kDescriptorsOffset);
1002 } 1028 }
1003 1029
1004 Node* CodeStubAssembler::LoadMapPrototype(Node* map) { 1030 Node* CodeStubAssembler::LoadMapPrototype(Node* map) {
1005 return LoadObjectField(map, Map::kPrototypeOffset); 1031 return LoadObjectField(map, Map::kPrototypeOffset);
1006 } 1032 }
1007 1033
1034 Node* CodeStubAssembler::LoadMapPrototypeInfo(Node* map,
1035 Label* if_no_proto_info) {
1036 Node* prototype_info =
1037 LoadObjectField(map, Map::kTransitionsOrPrototypeInfoOffset);
1038 GotoIf(TaggedIsSmi(prototype_info), if_no_proto_info);
1039 GotoUnless(WordEqual(LoadMap(prototype_info),
1040 LoadRoot(Heap::kPrototypeInfoMapRootIndex)),
1041 if_no_proto_info);
1042 return prototype_info;
1043 }
1044
1008 Node* CodeStubAssembler::LoadMapInstanceSize(Node* map) { 1045 Node* CodeStubAssembler::LoadMapInstanceSize(Node* map) {
1009 return ChangeUint32ToWord( 1046 return ChangeUint32ToWord(
1010 LoadObjectField(map, Map::kInstanceSizeOffset, MachineType::Uint8())); 1047 LoadObjectField(map, Map::kInstanceSizeOffset, MachineType::Uint8()));
1011 } 1048 }
1012 1049
1013 Node* CodeStubAssembler::LoadMapInobjectProperties(Node* map) { 1050 Node* CodeStubAssembler::LoadMapInobjectProperties(Node* map) {
1014 // See Map::GetInObjectProperties() for details. 1051 // See Map::GetInObjectProperties() for details.
1015 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); 1052 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
1016 CSA_ASSERT(Int32GreaterThanOrEqual(LoadMapInstanceType(map), 1053 CSA_ASSERT(Int32GreaterThanOrEqual(LoadMapInstanceType(map),
1017 Int32Constant(FIRST_JS_OBJECT_TYPE))); 1054 Int32Constant(FIRST_JS_OBJECT_TYPE)));
(...skipping 25 matching lines...) Expand all
1043 Word32Equal(LoadInstanceType(result.value()), Int32Constant(MAP_TYPE)); 1080 Word32Equal(LoadInstanceType(result.value()), Int32Constant(MAP_TYPE));
1044 GotoUnless(is_map_type, &done); 1081 GotoUnless(is_map_type, &done);
1045 result.Bind( 1082 result.Bind(
1046 LoadObjectField(result.value(), Map::kConstructorOrBackPointerOffset)); 1083 LoadObjectField(result.value(), Map::kConstructorOrBackPointerOffset));
1047 Goto(&loop); 1084 Goto(&loop);
1048 } 1085 }
1049 Bind(&done); 1086 Bind(&done);
1050 return result.value(); 1087 return result.value();
1051 } 1088 }
1052 1089
1090 Node* CodeStubAssembler::IsSpecialReceiverMap(Node* map) {
1091 Node* bit_field = LoadMapBitField(map);
1092 Node* mask = Int32Constant(1 << Map::kHasNamedInterceptor |
1093 1 << Map::kIsAccessCheckNeeded);
1094 Assert(Word32Equal(Word32And(bit_field, mask), Int32Constant(0)));
1095 return IsSpecialReceiverInstanceType(LoadMapInstanceType(map));
1096 }
1097
1098 Node* CodeStubAssembler::IsSpecialReceiverInstanceType(Node* instance_type) {
1099 STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE);
1100 return Int32LessThanOrEqual(instance_type,
1101 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE));
1102 }
1103
1053 Node* CodeStubAssembler::LoadNameHashField(Node* name) { 1104 Node* CodeStubAssembler::LoadNameHashField(Node* name) {
1054 return LoadObjectField(name, Name::kHashFieldOffset, MachineType::Uint32()); 1105 return LoadObjectField(name, Name::kHashFieldOffset, MachineType::Uint32());
1055 } 1106 }
1056 1107
1057 Node* CodeStubAssembler::LoadNameHash(Node* name, Label* if_hash_not_computed) { 1108 Node* CodeStubAssembler::LoadNameHash(Node* name, Label* if_hash_not_computed) {
1058 Node* hash_field = LoadNameHashField(name); 1109 Node* hash_field = LoadNameHashField(name);
1059 if (if_hash_not_computed != nullptr) { 1110 if (if_hash_not_computed != nullptr) {
1060 GotoIf(Word32Equal( 1111 GotoIf(Word32Equal(
1061 Word32And(hash_field, Int32Constant(Name::kHashNotComputedMask)), 1112 Word32And(hash_field, Int32Constant(Name::kHashNotComputedMask)),
1062 Int32Constant(0)), 1113 Int32Constant(0)),
(...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after
1597 AllocateFixedArray(elements_kind, length_intptr, parameter_mode); 1648 AllocateFixedArray(elements_kind, length_intptr, parameter_mode);
1598 StoreObjectField(result, JSArray::kElementsOffset, elements); 1649 StoreObjectField(result, JSArray::kElementsOffset, elements);
1599 1650
1600 // Fill in the elements with undefined. 1651 // Fill in the elements with undefined.
1601 FillFixedArrayWithValue(elements_kind, elements, zero, length_intptr, 1652 FillFixedArrayWithValue(elements_kind, elements, zero, length_intptr,
1602 Heap::kUndefinedValueRootIndex, parameter_mode); 1653 Heap::kUndefinedValueRootIndex, parameter_mode);
1603 1654
1604 return result; 1655 return result;
1605 } 1656 }
1606 1657
1658 Node* CodeStubAssembler::AllocateJSObjectFromMap(Node* map, Node* properties,
1659 Node* elements) {
1660 Node* size =
1661 IntPtrMul(LoadMapInstanceSize(map), IntPtrConstant(kPointerSize));
1662 CSA_ASSERT(IsRegularHeapObjectSize(size));
1663 Node* object = Allocate(size);
1664 StoreMapNoWriteBarrier(object, map);
1665 InitializeJSObjectFromMap(object, map, size, properties, elements);
1666 return object;
1667 }
1668
1669 void CodeStubAssembler::InitializeJSObjectFromMap(Node* object, Node* map,
1670 Node* size, Node* properties,
1671 Node* elements) {
1672 // This helper assumes that the object is in new-space, as guarded by the
1673 // check in AllocatedJSObjectFromMap.
1674 if (properties == nullptr) {
1675 StoreObjectFieldRoot(object, JSObject::kPropertiesOffset,
1676 Heap::kEmptyFixedArrayRootIndex);
1677 } else {
1678 StoreObjectFieldNoWriteBarrier(object, JSObject::kPropertiesOffset,
1679 properties);
1680 }
1681 if (elements == nullptr) {
1682 StoreObjectFieldRoot(object, JSObject::kElementsOffset,
1683 Heap::kEmptyFixedArrayRootIndex);
1684 } else {
1685 StoreObjectFieldNoWriteBarrier(object, JSObject::kElementsOffset, elements);
1686 }
1687 InitializeJSObjectBody(object, map, size, JSObject::kHeaderSize);
1688 }
1689
1690 void CodeStubAssembler::InitializeJSObjectBody(Node* object, Node* map,
1691 Node* size, int start_offset) {
1692 // TODO(cbruni): activate in-object slack tracking machinery.
1693 Comment("InitializeJSObjectBody");
1694 Node* filler = LoadRoot(Heap::kUndefinedValueRootIndex);
1695 // Calculate the untagged field addresses.
1696 Node* start_address = IntPtrAdd(object, IntPtrConstant(start_offset - 1));
Igor Sheludko 2016/10/19 06:50:56 s/1/kHeapObjectTag/
1697 Node* end_address = IntPtrSub(IntPtrAdd(object, size), IntPtrConstant(1));
Igor Sheludko 2016/10/19 06:50:56 Same here.
1698 StoreFieldsNoWriteBarrier(start_address, end_address, filler);
1699 }
1700
1701 void CodeStubAssembler::StoreFieldsNoWriteBarrier(Node* start_address,
1702 Node* end_address,
1703 Node* value) {
1704 Comment("StoreFieldsNoWriteBarrier");
1705
1706 Assert(IsWordAligned(start_address));
1707 Assert(IsWordAligned(end_address));
1708 BuildFastLoop(MachineType::PointerRepresentation(), start_address,
1709 end_address,
1710 [value](CodeStubAssembler* a, Node* current) {
1711 a->StoreNoWriteBarrier(MachineType::PointerRepresentation(),
1712 current, value);
1713 },
1714 kPointerSize, IndexAdvanceMode::kPost);
1715 }
1716
1607 Node* CodeStubAssembler::AllocateUninitializedJSArrayWithoutElements( 1717 Node* CodeStubAssembler::AllocateUninitializedJSArrayWithoutElements(
1608 ElementsKind kind, Node* array_map, Node* length, Node* allocation_site) { 1718 ElementsKind kind, Node* array_map, Node* length, Node* allocation_site) {
1609 Comment("begin allocation of JSArray without elements"); 1719 Comment("begin allocation of JSArray without elements");
1610 int base_size = JSArray::kSize; 1720 int base_size = JSArray::kSize;
1611 if (allocation_site != nullptr) { 1721 if (allocation_site != nullptr) {
1612 base_size += AllocationMemento::kSize; 1722 base_size += AllocationMemento::kSize;
1613 } 1723 }
1614 1724
1615 Node* size = IntPtrConstant(base_size); 1725 Node* size = IntPtrConstant(base_size);
1616 Node* array = AllocateUninitializedJSArray(kind, array_map, length, 1726 Node* array = AllocateUninitializedJSArray(kind, array_map, length,
(...skipping 6453 matching lines...) Expand 10 before | Expand all | Expand 10 after
8070 Node* buffer_bit_field = LoadObjectField( 8180 Node* buffer_bit_field = LoadObjectField(
8071 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); 8181 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32());
8072 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); 8182 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask);
8073 8183
8074 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), 8184 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask),
8075 Int32Constant(0)); 8185 Int32Constant(0));
8076 } 8186 }
8077 8187
8078 } // namespace internal 8188 } // namespace internal
8079 } // namespace v8 8189 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698