Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |