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 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 Node* CodeStubAssembler::TaggedIsSmi(Node* a) { | 517 Node* CodeStubAssembler::TaggedIsSmi(Node* a) { |
519 return WordEqual(WordAnd(BitcastTaggedToWord(a), IntPtrConstant(kSmiTagMask)), | 518 return WordEqual(WordAnd(BitcastTaggedToWord(a), IntPtrConstant(kSmiTagMask)), |
520 IntPtrConstant(0)); | 519 IntPtrConstant(0)); |
521 } | 520 } |
522 | 521 |
523 Node* CodeStubAssembler::WordIsPositiveSmi(Node* a) { | 522 Node* CodeStubAssembler::WordIsPositiveSmi(Node* a) { |
524 return WordEqual(WordAnd(a, IntPtrConstant(kSmiTagMask | kSmiSignMask)), | 523 return WordEqual(WordAnd(a, IntPtrConstant(kSmiTagMask | kSmiSignMask)), |
525 IntPtrConstant(0)); | 524 IntPtrConstant(0)); |
526 } | 525 } |
527 | 526 |
| 527 Node* CodeStubAssembler::WordIsWordAligned(Node* word) { |
| 528 return WordEqual(IntPtrConstant(0), |
| 529 WordAnd(word, IntPtrConstant((1 << kPointerSizeLog2) - 1))); |
| 530 } |
| 531 |
528 void CodeStubAssembler::BranchIfSimd128Equal(Node* lhs, Node* lhs_map, | 532 void CodeStubAssembler::BranchIfSimd128Equal(Node* lhs, Node* lhs_map, |
529 Node* rhs, Node* rhs_map, | 533 Node* rhs, Node* rhs_map, |
530 Label* if_equal, | 534 Label* if_equal, |
531 Label* if_notequal) { | 535 Label* if_notequal) { |
532 Label if_mapsame(this), if_mapnotsame(this); | 536 Label if_mapsame(this), if_mapnotsame(this); |
533 Branch(WordEqual(lhs_map, rhs_map), &if_mapsame, &if_mapnotsame); | 537 Branch(WordEqual(lhs_map, rhs_map), &if_mapsame, &if_mapnotsame); |
534 | 538 |
535 Bind(&if_mapsame); | 539 Bind(&if_mapsame); |
536 { | 540 { |
537 // Both {lhs} and {rhs} are Simd128Values with the same map, need special | 541 // Both {lhs} and {rhs} are Simd128Values with the same map, need special |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
618 GotoIf(Int32LessThanOrEqual(LoadMapInstanceType(prototype_map), | 622 GotoIf(Int32LessThanOrEqual(LoadMapInstanceType(prototype_map), |
619 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), | 623 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), |
620 possibly_elements); | 624 possibly_elements); |
621 GotoIf(WordNotEqual(LoadElements(prototype), empty_elements), | 625 GotoIf(WordNotEqual(LoadElements(prototype), empty_elements), |
622 possibly_elements); | 626 possibly_elements); |
623 var_map.Bind(prototype_map); | 627 var_map.Bind(prototype_map); |
624 Goto(&loop_body); | 628 Goto(&loop_body); |
625 } | 629 } |
626 } | 630 } |
627 | 631 |
| 632 void CodeStubAssembler::BranchIfJSReceiver(Node* object, Label* if_true, |
| 633 Label* if_false) { |
| 634 GotoIf(TaggedIsSmi(object), if_false); |
| 635 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
| 636 Branch(Int32GreaterThanOrEqual(LoadInstanceType(object), |
| 637 Int32Constant(FIRST_JS_RECEIVER_TYPE)), |
| 638 if_true, if_false); |
| 639 } |
| 640 |
| 641 void CodeStubAssembler::BranchIfJSObject(Node* object, Label* if_true, |
| 642 Label* if_false) { |
| 643 GotoIf(TaggedIsSmi(object), if_false); |
| 644 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); |
| 645 Branch(Int32GreaterThanOrEqual(LoadInstanceType(object), |
| 646 Int32Constant(FIRST_JS_OBJECT_TYPE)), |
| 647 if_true, if_false); |
| 648 } |
| 649 |
628 void CodeStubAssembler::BranchIfFastJSArray(Node* object, Node* context, | 650 void CodeStubAssembler::BranchIfFastJSArray(Node* object, Node* context, |
629 Label* if_true, Label* if_false) { | 651 Label* if_true, Label* if_false) { |
630 // Bailout if receiver is a Smi. | 652 // Bailout if receiver is a Smi. |
631 GotoIf(TaggedIsSmi(object), if_false); | 653 GotoIf(TaggedIsSmi(object), if_false); |
632 | 654 |
633 Node* map = LoadMap(object); | 655 Node* map = LoadMap(object); |
634 | 656 |
635 // Bailout if instance type is not JS_ARRAY_TYPE. | 657 // Bailout if instance type is not JS_ARRAY_TYPE. |
636 GotoIf(WordNotEqual(LoadMapInstanceType(map), Int32Constant(JS_ARRAY_TYPE)), | 658 GotoIf(WordNotEqual(LoadMapInstanceType(map), Int32Constant(JS_ARRAY_TYPE)), |
637 if_false); | 659 if_false); |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
778 } | 800 } |
779 | 801 |
780 Node* CodeStubAssembler::InnerAllocate(Node* previous, Node* offset) { | 802 Node* CodeStubAssembler::InnerAllocate(Node* previous, Node* offset) { |
781 return BitcastWordToTagged(IntPtrAdd(previous, offset)); | 803 return BitcastWordToTagged(IntPtrAdd(previous, offset)); |
782 } | 804 } |
783 | 805 |
784 Node* CodeStubAssembler::InnerAllocate(Node* previous, int offset) { | 806 Node* CodeStubAssembler::InnerAllocate(Node* previous, int offset) { |
785 return InnerAllocate(previous, IntPtrConstant(offset)); | 807 return InnerAllocate(previous, IntPtrConstant(offset)); |
786 } | 808 } |
787 | 809 |
| 810 Node* CodeStubAssembler::IsRegularHeapObjectSize(Node* size) { |
| 811 return UintPtrLessThanOrEqual(size, |
| 812 IntPtrConstant(kMaxRegularHeapObjectSize)); |
| 813 } |
| 814 |
788 void CodeStubAssembler::BranchIfToBooleanIsTrue(Node* value, Label* if_true, | 815 void CodeStubAssembler::BranchIfToBooleanIsTrue(Node* value, Label* if_true, |
789 Label* if_false) { | 816 Label* if_false) { |
790 Label if_valueissmi(this), if_valueisnotsmi(this), if_valueisstring(this), | 817 Label if_valueissmi(this), if_valueisnotsmi(this), if_valueisstring(this), |
791 if_valueisheapnumber(this), if_valueisother(this); | 818 if_valueisheapnumber(this), if_valueisother(this); |
792 | 819 |
793 // Fast check for Boolean {value}s (common case). | 820 // Fast check for Boolean {value}s (common case). |
794 GotoIf(WordEqual(value, BooleanConstant(true)), if_true); | 821 GotoIf(WordEqual(value, BooleanConstant(true)), if_true); |
795 GotoIf(WordEqual(value, BooleanConstant(false)), if_false); | 822 GotoIf(WordEqual(value, BooleanConstant(false)), if_false); |
796 | 823 |
797 // Check if {value} is a Smi or a HeapObject. | 824 // Check if {value} is a Smi or a HeapObject. |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
943 } | 970 } |
944 | 971 |
945 Node* CodeStubAssembler::LoadMap(Node* object) { | 972 Node* CodeStubAssembler::LoadMap(Node* object) { |
946 return LoadObjectField(object, HeapObject::kMapOffset); | 973 return LoadObjectField(object, HeapObject::kMapOffset); |
947 } | 974 } |
948 | 975 |
949 Node* CodeStubAssembler::LoadInstanceType(Node* object) { | 976 Node* CodeStubAssembler::LoadInstanceType(Node* object) { |
950 return LoadMapInstanceType(LoadMap(object)); | 977 return LoadMapInstanceType(LoadMap(object)); |
951 } | 978 } |
952 | 979 |
| 980 Node* CodeStubAssembler::HasInstanceType(Node* object, |
| 981 InstanceType instance_type) { |
| 982 return Word32Equal(LoadInstanceType(object), Int32Constant(instance_type)); |
| 983 } |
| 984 |
953 void CodeStubAssembler::AssertInstanceType(Node* object, | 985 void CodeStubAssembler::AssertInstanceType(Node* object, |
954 InstanceType instance_type) { | 986 InstanceType instance_type) { |
955 CSA_ASSERT( | 987 CSA_ASSERT(HasInstanceType(object, instance_type)); |
956 Word32Equal(LoadInstanceType(object), Int32Constant(instance_type))); | |
957 } | 988 } |
958 | 989 |
959 Node* CodeStubAssembler::LoadProperties(Node* object) { | 990 Node* CodeStubAssembler::LoadProperties(Node* object) { |
960 return LoadObjectField(object, JSObject::kPropertiesOffset); | 991 return LoadObjectField(object, JSObject::kPropertiesOffset); |
961 } | 992 } |
962 | 993 |
963 Node* CodeStubAssembler::LoadElements(Node* object) { | 994 Node* CodeStubAssembler::LoadElements(Node* object) { |
964 return LoadObjectField(object, JSObject::kElementsOffset); | 995 return LoadObjectField(object, JSObject::kElementsOffset); |
965 } | 996 } |
966 | 997 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
998 } | 1029 } |
999 | 1030 |
1000 Node* CodeStubAssembler::LoadMapDescriptors(Node* map) { | 1031 Node* CodeStubAssembler::LoadMapDescriptors(Node* map) { |
1001 return LoadObjectField(map, Map::kDescriptorsOffset); | 1032 return LoadObjectField(map, Map::kDescriptorsOffset); |
1002 } | 1033 } |
1003 | 1034 |
1004 Node* CodeStubAssembler::LoadMapPrototype(Node* map) { | 1035 Node* CodeStubAssembler::LoadMapPrototype(Node* map) { |
1005 return LoadObjectField(map, Map::kPrototypeOffset); | 1036 return LoadObjectField(map, Map::kPrototypeOffset); |
1006 } | 1037 } |
1007 | 1038 |
| 1039 Node* CodeStubAssembler::LoadMapPrototypeInfo(Node* map, |
| 1040 Label* if_no_proto_info) { |
| 1041 Node* prototype_info = |
| 1042 LoadObjectField(map, Map::kTransitionsOrPrototypeInfoOffset); |
| 1043 GotoIf(TaggedIsSmi(prototype_info), if_no_proto_info); |
| 1044 GotoUnless(WordEqual(LoadMap(prototype_info), |
| 1045 LoadRoot(Heap::kPrototypeInfoMapRootIndex)), |
| 1046 if_no_proto_info); |
| 1047 return prototype_info; |
| 1048 } |
| 1049 |
1008 Node* CodeStubAssembler::LoadMapInstanceSize(Node* map) { | 1050 Node* CodeStubAssembler::LoadMapInstanceSize(Node* map) { |
1009 return ChangeUint32ToWord( | 1051 return ChangeUint32ToWord( |
1010 LoadObjectField(map, Map::kInstanceSizeOffset, MachineType::Uint8())); | 1052 LoadObjectField(map, Map::kInstanceSizeOffset, MachineType::Uint8())); |
1011 } | 1053 } |
1012 | 1054 |
1013 Node* CodeStubAssembler::LoadMapInobjectProperties(Node* map) { | 1055 Node* CodeStubAssembler::LoadMapInobjectProperties(Node* map) { |
1014 // See Map::GetInObjectProperties() for details. | 1056 // See Map::GetInObjectProperties() for details. |
1015 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); | 1057 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); |
1016 CSA_ASSERT(Int32GreaterThanOrEqual(LoadMapInstanceType(map), | 1058 CSA_ASSERT(Int32GreaterThanOrEqual(LoadMapInstanceType(map), |
1017 Int32Constant(FIRST_JS_OBJECT_TYPE))); | 1059 Int32Constant(FIRST_JS_OBJECT_TYPE))); |
(...skipping 25 matching lines...) Expand all Loading... |
1043 Word32Equal(LoadInstanceType(result.value()), Int32Constant(MAP_TYPE)); | 1085 Word32Equal(LoadInstanceType(result.value()), Int32Constant(MAP_TYPE)); |
1044 GotoUnless(is_map_type, &done); | 1086 GotoUnless(is_map_type, &done); |
1045 result.Bind( | 1087 result.Bind( |
1046 LoadObjectField(result.value(), Map::kConstructorOrBackPointerOffset)); | 1088 LoadObjectField(result.value(), Map::kConstructorOrBackPointerOffset)); |
1047 Goto(&loop); | 1089 Goto(&loop); |
1048 } | 1090 } |
1049 Bind(&done); | 1091 Bind(&done); |
1050 return result.value(); | 1092 return result.value(); |
1051 } | 1093 } |
1052 | 1094 |
| 1095 Node* CodeStubAssembler::IsSpecialReceiverMap(Node* map) { |
| 1096 Node* bit_field = LoadMapBitField(map); |
| 1097 Node* mask = Int32Constant(1 << Map::kHasNamedInterceptor | |
| 1098 1 << Map::kIsAccessCheckNeeded); |
| 1099 Assert(Word32Equal(Word32And(bit_field, mask), Int32Constant(0))); |
| 1100 return IsSpecialReceiverInstanceType(LoadMapInstanceType(map)); |
| 1101 } |
| 1102 |
| 1103 Node* CodeStubAssembler::IsSpecialReceiverInstanceType(Node* instance_type) { |
| 1104 STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE); |
| 1105 return Int32LessThanOrEqual(instance_type, |
| 1106 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)); |
| 1107 } |
| 1108 |
1053 Node* CodeStubAssembler::LoadNameHashField(Node* name) { | 1109 Node* CodeStubAssembler::LoadNameHashField(Node* name) { |
1054 return LoadObjectField(name, Name::kHashFieldOffset, MachineType::Uint32()); | 1110 return LoadObjectField(name, Name::kHashFieldOffset, MachineType::Uint32()); |
1055 } | 1111 } |
1056 | 1112 |
1057 Node* CodeStubAssembler::LoadNameHash(Node* name, Label* if_hash_not_computed) { | 1113 Node* CodeStubAssembler::LoadNameHash(Node* name, Label* if_hash_not_computed) { |
1058 Node* hash_field = LoadNameHashField(name); | 1114 Node* hash_field = LoadNameHashField(name); |
1059 if (if_hash_not_computed != nullptr) { | 1115 if (if_hash_not_computed != nullptr) { |
1060 GotoIf(Word32Equal( | 1116 GotoIf(Word32Equal( |
1061 Word32And(hash_field, Int32Constant(Name::kHashNotComputedMask)), | 1117 Word32And(hash_field, Int32Constant(Name::kHashNotComputedMask)), |
1062 Int32Constant(0)), | 1118 Int32Constant(0)), |
(...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1597 AllocateFixedArray(elements_kind, length_intptr, parameter_mode); | 1653 AllocateFixedArray(elements_kind, length_intptr, parameter_mode); |
1598 StoreObjectField(result, JSArray::kElementsOffset, elements); | 1654 StoreObjectField(result, JSArray::kElementsOffset, elements); |
1599 | 1655 |
1600 // Fill in the elements with undefined. | 1656 // Fill in the elements with undefined. |
1601 FillFixedArrayWithValue(elements_kind, elements, zero, length_intptr, | 1657 FillFixedArrayWithValue(elements_kind, elements, zero, length_intptr, |
1602 Heap::kUndefinedValueRootIndex, parameter_mode); | 1658 Heap::kUndefinedValueRootIndex, parameter_mode); |
1603 | 1659 |
1604 return result; | 1660 return result; |
1605 } | 1661 } |
1606 | 1662 |
| 1663 Node* CodeStubAssembler::AllocateJSObjectFromMap(Node* map, Node* properties, |
| 1664 Node* elements) { |
| 1665 Node* size = |
| 1666 IntPtrMul(LoadMapInstanceSize(map), IntPtrConstant(kPointerSize)); |
| 1667 CSA_ASSERT(IsRegularHeapObjectSize(size)); |
| 1668 Node* object = Allocate(size); |
| 1669 StoreMapNoWriteBarrier(object, map); |
| 1670 InitializeJSObjectFromMap(object, map, size, properties, elements); |
| 1671 return object; |
| 1672 } |
| 1673 |
| 1674 void CodeStubAssembler::InitializeJSObjectFromMap(Node* object, Node* map, |
| 1675 Node* size, Node* properties, |
| 1676 Node* elements) { |
| 1677 // This helper assumes that the object is in new-space, as guarded by the |
| 1678 // check in AllocatedJSObjectFromMap. |
| 1679 if (properties == nullptr) { |
| 1680 StoreObjectFieldRoot(object, JSObject::kPropertiesOffset, |
| 1681 Heap::kEmptyFixedArrayRootIndex); |
| 1682 } else { |
| 1683 StoreObjectFieldNoWriteBarrier(object, JSObject::kPropertiesOffset, |
| 1684 properties); |
| 1685 } |
| 1686 if (elements == nullptr) { |
| 1687 StoreObjectFieldRoot(object, JSObject::kElementsOffset, |
| 1688 Heap::kEmptyFixedArrayRootIndex); |
| 1689 } else { |
| 1690 StoreObjectFieldNoWriteBarrier(object, JSObject::kElementsOffset, elements); |
| 1691 } |
| 1692 InitializeJSObjectBody(object, map, size, JSObject::kHeaderSize); |
| 1693 } |
| 1694 |
| 1695 void CodeStubAssembler::InitializeJSObjectBody(Node* object, Node* map, |
| 1696 Node* size, int start_offset) { |
| 1697 // TODO(cbruni): activate in-object slack tracking machinery. |
| 1698 Comment("InitializeJSObjectBody"); |
| 1699 Node* filler = LoadRoot(Heap::kUndefinedValueRootIndex); |
| 1700 // Calculate the untagged field addresses. |
| 1701 Node* start_address = |
| 1702 IntPtrAdd(object, IntPtrConstant(start_offset - kHeapObjectTag)); |
| 1703 Node* end_address = |
| 1704 IntPtrSub(IntPtrAdd(object, size), IntPtrConstant(kHeapObjectTag)); |
| 1705 StoreFieldsNoWriteBarrier(start_address, end_address, filler); |
| 1706 } |
| 1707 |
| 1708 void CodeStubAssembler::StoreFieldsNoWriteBarrier(Node* start_address, |
| 1709 Node* end_address, |
| 1710 Node* value) { |
| 1711 Comment("StoreFieldsNoWriteBarrier"); |
| 1712 CSA_ASSERT(WordIsWordAligned(start_address)); |
| 1713 CSA_ASSERT(WordIsWordAligned(end_address)); |
| 1714 BuildFastLoop(MachineType::PointerRepresentation(), start_address, |
| 1715 end_address, |
| 1716 [value](CodeStubAssembler* a, Node* current) { |
| 1717 a->StoreNoWriteBarrier(MachineType::PointerRepresentation(), |
| 1718 current, value); |
| 1719 }, |
| 1720 kPointerSize, IndexAdvanceMode::kPost); |
| 1721 } |
| 1722 |
1607 Node* CodeStubAssembler::AllocateUninitializedJSArrayWithoutElements( | 1723 Node* CodeStubAssembler::AllocateUninitializedJSArrayWithoutElements( |
1608 ElementsKind kind, Node* array_map, Node* length, Node* allocation_site) { | 1724 ElementsKind kind, Node* array_map, Node* length, Node* allocation_site) { |
1609 Comment("begin allocation of JSArray without elements"); | 1725 Comment("begin allocation of JSArray without elements"); |
1610 int base_size = JSArray::kSize; | 1726 int base_size = JSArray::kSize; |
1611 if (allocation_site != nullptr) { | 1727 if (allocation_site != nullptr) { |
1612 base_size += AllocationMemento::kSize; | 1728 base_size += AllocationMemento::kSize; |
1613 } | 1729 } |
1614 | 1730 |
1615 Node* size = IntPtrConstant(base_size); | 1731 Node* size = IntPtrConstant(base_size); |
1616 Node* array = AllocateUninitializedJSArray(kind, array_map, length, | 1732 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( | 8186 Node* buffer_bit_field = LoadObjectField( |
8071 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); | 8187 buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32()); |
8072 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); | 8188 Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask); |
8073 | 8189 |
8074 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), | 8190 return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask), |
8075 Int32Constant(0)); | 8191 Int32Constant(0)); |
8076 } | 8192 } |
8077 | 8193 |
8078 } // namespace internal | 8194 } // namespace internal |
8079 } // namespace v8 | 8195 } // namespace v8 |
OLD | NEW |