Title: [245214] trunk
Revision
245214
Author
[email protected]
Date
2019-05-12 15:50:21 -0700 (Sun, 12 May 2019)

Log Message

[JSC] Compress Watchpoint size by using enum type and Packed<> data structure
https://bugs.webkit.org/show_bug.cgi?id=197730

Reviewed by Filip Pizlo.

Source/_javascript_Core:

Watchpoint takes 5~ MB memory in Gmail (total memory starts with 400 - 500 MB), so 1~%. Since it is allocated massively,
reducing each size of Watchpoint reduces memory footprint significantly.

As a first step, this patch uses Packed<> and enum to reduce the size of Watchpoint.

1. Watchpoint should have enum type and should not use vtable. vtable takes one pointer, and it is too costly for such a
   memory sensitive objects. We perform downcast and dispatch the method of the derived classes based on this enum. Since
   the # of derived Watchpoint classes are limited (Only 8), we can list up them easily. One unfortunate thing is that
   we cannot do this for destructor so long as we use "delete" for deleting objects. If we dispatch the destructor of derived
   class in the destructor of the base class, we call the destructor of the base class multiple times. delete operator override
   does not help since custom delete operator is called after the destructor is called. While we can fix this issue by always
   using custom deleter, currently we do not since all the watchpoints do not have members which have non trivial destructor.
   Once it is strongly required, we can start using custom deleter, but for now, we do not need to do this.

2. We use Packed<> to compact pointers in Watchpoint. Since Watchpoint is a node of doubly linked list, each one has two
   pointers for prev and next. This is also too costly. PackedPtr reduces the size and makes alignment 1.S

3. We use PackedCellPtr<> for JSCells in Watchpoint. This leverages alignment information and makes pointers smaller in
   Darwin ARM64. One important thing to note here is that since this pointer is packed, it cannot be found by conservative
   GC scan. It is OK for watchpoint since they are allocated in the heap anyway.

We applied this change to Watchpoint and get the following memory reduction. The highlight is that CodeBlockJettisoningWatchpoint in
ARM64 only takes 2 pointers size.

                                                                      ORIGINAL    X86_64   ARM64
    WatchpointSet:                                                    40          32       28
    CodeBlockJettisoningWatchpoint:                                   32          19       15
    StructureStubClearingWatchpoint:                                  56          48       40
    AdaptiveInferredPropertyValueWatchpointBase::StructureWatchpoint: 24          13       11
    AdaptiveInferredPropertyValueWatchpointBase::PropertyWatchpoint:  24          13       11
    FunctionRareData::AllocationProfileClearingWatchpoint:            32          19       15
    ObjectToStringAdaptiveStructureWatchpoint:                        56          48       40
    LLIntPrototypeLoadAdaptiveStructureWatchpoint:                    64          48       48
    DFG::AdaptiveStructureWatchpoint:                                 56          48       40

While we will re-architect the mechanism of Watchpoint, anyway Packed<> mechanism and enum types will be used too.

* CMakeLists.txt:
* _javascript_Core.xcodeproj/project.pbxproj:
* Sources.txt:
* bytecode/AdaptiveInferredPropertyValueWatchpointBase.h:
* bytecode/CodeBlockJettisoningWatchpoint.h:
* bytecode/CodeOrigin.h:
* bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp:
(JSC::LLIntPrototypeLoadAdaptiveStructureWatchpoint::LLIntPrototypeLoadAdaptiveStructureWatchpoint):
(JSC::LLIntPrototypeLoadAdaptiveStructureWatchpoint::fireInternal):
* bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h:
* bytecode/StructureStubClearingWatchpoint.cpp:
(JSC::StructureStubClearingWatchpoint::fireInternal):
* bytecode/StructureStubClearingWatchpoint.h:
* bytecode/Watchpoint.cpp:
(JSC::Watchpoint::fire):
* bytecode/Watchpoint.h:
(JSC::Watchpoint::Watchpoint):
* dfg/DFGAdaptiveStructureWatchpoint.cpp:
(JSC::DFG::AdaptiveStructureWatchpoint::AdaptiveStructureWatchpoint):
* dfg/DFGAdaptiveStructureWatchpoint.h:
* heap/PackedCellPtr.h: Added.
* runtime/FunctionRareData.h:
* runtime/ObjectToStringAdaptiveStructureWatchpoint.cpp: Added.
(JSC::ObjectToStringAdaptiveStructureWatchpoint::ObjectToStringAdaptiveStructureWatchpoint):
(JSC::ObjectToStringAdaptiveStructureWatchpoint::install):
(JSC::ObjectToStringAdaptiveStructureWatchpoint::fireInternal):
* runtime/ObjectToStringAdaptiveStructureWatchpoint.h: Added.
* runtime/StructureRareData.cpp:
(JSC::StructureRareData::clearObjectToStringValue):
(JSC::ObjectToStringAdaptiveStructureWatchpoint::ObjectToStringAdaptiveStructureWatchpoint): Deleted.
(JSC::ObjectToStringAdaptiveStructureWatchpoint::install): Deleted.
(JSC::ObjectToStringAdaptiveStructureWatchpoint::fireInternal): Deleted.
* runtime/StructureRareData.h:

Source/WTF:

This patch introduces a new data structures, WTF::Packed, WTF::PackedPtr, and WTF::PackedAlignedPtr.

- WTF::Packed

    WTF::Packed is data storage. We can read and write trivial (in C++ term [1]) data to this storage. The difference to
    the usual storage is that the alignment of this storage is always 1. We access the underlying data by using unalignedLoad/unalignedStore.
    This class offers alignment = 1 data structure instead of missing the following characteristics.

        1. Load / Store are non atomic even if the data size is within a pointer width. We should not use this for a member which can be accessed
           in a racy way. (e.g. fields accessed optimistically from the concurrent compilers).

        2. We cannot take reference / pointer to the underlying storage since they are unaligned.

        3. Access to this storage is unaligned access. The code is using memcpy, and the compiler will convert to an appropriate unaligned access
           in certain architectures (x86_64 / ARM64). It could be slow. So use it for non performance sensitive & memory sensitive places.

- WTF::PackedPtr

    WTF::PackedPtr is a specialization of WTF::Packed<T*>. And it is basically WTF::PackedAlignedPtr with alignment = 1. We further compact
    the pointer by leveraging the platform specific knowledge. In 64bit architectures, the effective width of pointers are less than 64 bit.
    In x86_64, it is 48 bits. And Darwin ARM64 is further smaller, 36 bits. This information allows us to compact the pointer to 6 bytes in
    x86_64 and 5 bytes in Darwin ARM64.

- WTF::PackedAlignedPtr

    WTF::PackedAlignedPtr is the WTF::PackedPtr with alignment information of the T. If we use this alignment information, we could reduce the
    size of packed pointer further in some cases. For example, since we guarantee that JSCells are 16 byte aligned, low 4 bits are empty. Leveraging
    this information in Darwin ARM64 platform allows us to make packed JSCell pointer 4 bytes (36 - 4 bits). We do not use passed alignment
    information if it is not profitable.

We also have PackedPtrTraits. This is new PtrTraits and use it for various data structures such as Bag<>.

[1]: https://en.cppreference.com/w/cpp/types/is_trivial

* WTF.xcodeproj/project.pbxproj:
* wtf/Bag.h:
(WTF::Bag::clear):
(WTF::Bag::iterator::operator++):
* wtf/CMakeLists.txt:
* wtf/DumbPtrTraits.h:
* wtf/DumbValueTraits.h:
* wtf/MathExtras.h:
(WTF::clzConstexpr):
(WTF::clz):
(WTF::ctzConstexpr):
(WTF::ctz):
(WTF::getLSBSetConstexpr):
(WTF::getMSBSetConstexpr):
* wtf/Packed.h: Added.
(WTF::Packed::Packed):
(WTF::Packed::get const):
(WTF::Packed::set):
(WTF::Packed::operator=):
(WTF::Packed::exchange):
(WTF::Packed::swap):
(WTF::alignof):
(WTF::PackedPtrTraits::exchange):
(WTF::PackedPtrTraits::swap):
(WTF::PackedPtrTraits::unwrap):
* wtf/Platform.h:
* wtf/SentinelLinkedList.h:
(WTF::BasicRawSentinelNode::BasicRawSentinelNode):
(WTF::BasicRawSentinelNode::prev):
(WTF::BasicRawSentinelNode::next):
(WTF::PtrTraits>::remove):
(WTF::PtrTraits>::prepend):
(WTF::PtrTraits>::append):
(WTF::RawNode>::SentinelLinkedList):
(WTF::RawNode>::remove):
(WTF::BasicRawSentinelNode<T>::remove): Deleted.
(WTF::BasicRawSentinelNode<T>::prepend): Deleted.
(WTF::BasicRawSentinelNode<T>::append): Deleted.
* wtf/StdLibExtras.h:
(WTF::roundUpToMultipleOfImpl):
(WTF::roundUpToMultipleOfImpl0): Deleted.
* wtf/UnalignedAccess.h:
(WTF::unalignedLoad):
(WTF::unalignedStore):

Tools:

* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/MathExtras.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/Packed.cpp: Added.
(TestWebKitAPI::TEST):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (245213 => 245214)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2019-05-12 22:50:21 UTC (rev 245214)
@@ -606,6 +606,7 @@
     heap/MarkedSpace.h
     heap/MarkingConstraint.h
     heap/MutatorState.h
+    heap/PackedCellPtr.h
     heap/RegisterState.h
     heap/RunningScope.h
     heap/SimpleMarkingConstraint.h

Modified: trunk/Source/_javascript_Core/ChangeLog (245213 => 245214)


--- trunk/Source/_javascript_Core/ChangeLog	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-05-12 22:50:21 UTC (rev 245214)
@@ -1,5 +1,83 @@
 2019-05-12  Yusuke Suzuki  <[email protected]>
 
+        [JSC] Compress Watchpoint size by using enum type and Packed<> data structure
+        https://bugs.webkit.org/show_bug.cgi?id=197730
+
+        Reviewed by Filip Pizlo.
+
+        Watchpoint takes 5~ MB memory in Gmail (total memory starts with 400 - 500 MB), so 1~%. Since it is allocated massively,
+        reducing each size of Watchpoint reduces memory footprint significantly.
+
+        As a first step, this patch uses Packed<> and enum to reduce the size of Watchpoint.
+
+        1. Watchpoint should have enum type and should not use vtable. vtable takes one pointer, and it is too costly for such a
+           memory sensitive objects. We perform downcast and dispatch the method of the derived classes based on this enum. Since
+           the # of derived Watchpoint classes are limited (Only 8), we can list up them easily. One unfortunate thing is that
+           we cannot do this for destructor so long as we use "delete" for deleting objects. If we dispatch the destructor of derived
+           class in the destructor of the base class, we call the destructor of the base class multiple times. delete operator override
+           does not help since custom delete operator is called after the destructor is called. While we can fix this issue by always
+           using custom deleter, currently we do not since all the watchpoints do not have members which have non trivial destructor.
+           Once it is strongly required, we can start using custom deleter, but for now, we do not need to do this.
+
+        2. We use Packed<> to compact pointers in Watchpoint. Since Watchpoint is a node of doubly linked list, each one has two
+           pointers for prev and next. This is also too costly. PackedPtr reduces the size and makes alignment 1.S
+
+        3. We use PackedCellPtr<> for JSCells in Watchpoint. This leverages alignment information and makes pointers smaller in
+           Darwin ARM64. One important thing to note here is that since this pointer is packed, it cannot be found by conservative
+           GC scan. It is OK for watchpoint since they are allocated in the heap anyway.
+
+        We applied this change to Watchpoint and get the following memory reduction. The highlight is that CodeBlockJettisoningWatchpoint in
+        ARM64 only takes 2 pointers size.
+
+                                                                              ORIGINAL    X86_64   ARM64
+            WatchpointSet:                                                    40          32       28
+            CodeBlockJettisoningWatchpoint:                                   32          19       15
+            StructureStubClearingWatchpoint:                                  56          48       40
+            AdaptiveInferredPropertyValueWatchpointBase::StructureWatchpoint: 24          13       11
+            AdaptiveInferredPropertyValueWatchpointBase::PropertyWatchpoint:  24          13       11
+            FunctionRareData::AllocationProfileClearingWatchpoint:            32          19       15
+            ObjectToStringAdaptiveStructureWatchpoint:                        56          48       40
+            LLIntPrototypeLoadAdaptiveStructureWatchpoint:                    64          48       48
+            DFG::AdaptiveStructureWatchpoint:                                 56          48       40
+
+        While we will re-architect the mechanism of Watchpoint, anyway Packed<> mechanism and enum types will be used too.
+
+        * CMakeLists.txt:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * bytecode/AdaptiveInferredPropertyValueWatchpointBase.h:
+        * bytecode/CodeBlockJettisoningWatchpoint.h:
+        * bytecode/CodeOrigin.h:
+        * bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp:
+        (JSC::LLIntPrototypeLoadAdaptiveStructureWatchpoint::LLIntPrototypeLoadAdaptiveStructureWatchpoint):
+        (JSC::LLIntPrototypeLoadAdaptiveStructureWatchpoint::fireInternal):
+        * bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h:
+        * bytecode/StructureStubClearingWatchpoint.cpp:
+        (JSC::StructureStubClearingWatchpoint::fireInternal):
+        * bytecode/StructureStubClearingWatchpoint.h:
+        * bytecode/Watchpoint.cpp:
+        (JSC::Watchpoint::fire):
+        * bytecode/Watchpoint.h:
+        (JSC::Watchpoint::Watchpoint):
+        * dfg/DFGAdaptiveStructureWatchpoint.cpp:
+        (JSC::DFG::AdaptiveStructureWatchpoint::AdaptiveStructureWatchpoint):
+        * dfg/DFGAdaptiveStructureWatchpoint.h:
+        * heap/PackedCellPtr.h: Added.
+        * runtime/FunctionRareData.h:
+        * runtime/ObjectToStringAdaptiveStructureWatchpoint.cpp: Added.
+        (JSC::ObjectToStringAdaptiveStructureWatchpoint::ObjectToStringAdaptiveStructureWatchpoint):
+        (JSC::ObjectToStringAdaptiveStructureWatchpoint::install):
+        (JSC::ObjectToStringAdaptiveStructureWatchpoint::fireInternal):
+        * runtime/ObjectToStringAdaptiveStructureWatchpoint.h: Added.
+        * runtime/StructureRareData.cpp:
+        (JSC::StructureRareData::clearObjectToStringValue):
+        (JSC::ObjectToStringAdaptiveStructureWatchpoint::ObjectToStringAdaptiveStructureWatchpoint): Deleted.
+        (JSC::ObjectToStringAdaptiveStructureWatchpoint::install): Deleted.
+        (JSC::ObjectToStringAdaptiveStructureWatchpoint::fireInternal): Deleted.
+        * runtime/StructureRareData.h:
+
+2019-05-12  Yusuke Suzuki  <[email protected]>
+
         [JSC] Compact generator code's bytecode size
         https://bugs.webkit.org/show_bug.cgi?id=197822
 

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (245213 => 245214)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2019-05-12 22:50:21 UTC (rev 245214)
@@ -1779,6 +1779,7 @@
 		E354622B1B6065D100545386 /* ConstructAbility.h in Headers */ = {isa = PBXBuildFile; fileRef = E354622A1B6065D100545386 /* ConstructAbility.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E3555B8A1DAE03A500F36921 /* DOMJITCallDOMGetterSnippet.h in Headers */ = {isa = PBXBuildFile; fileRef = E3555B891DAE03A200F36921 /* DOMJITCallDOMGetterSnippet.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E355D38F22446877008F1AD6 /* GlobalExecutable.h in Headers */ = {isa = PBXBuildFile; fileRef = E355D38D2244686B008F1AD6 /* GlobalExecutable.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		E356987222841187008CDCCB /* PackedCellPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = E356987122841183008CDCCB /* PackedCellPtr.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E35A0B9D220AD87A00AC4474 /* ExecutableBaseInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E35A0B9C220AD87A00AC4474 /* ExecutableBaseInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E35CA1541DBC3A5C00F83516 /* DOMJITHeapRange.h in Headers */ = {isa = PBXBuildFile; fileRef = E35CA1521DBC3A5600F83516 /* DOMJITHeapRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E35CA1561DBC3A5F00F83516 /* DOMJITAbstractHeap.h in Headers */ = {isa = PBXBuildFile; fileRef = E35CA1501DBC3A5600F83516 /* DOMJITAbstractHeap.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -1792,6 +1793,7 @@
 		E393ADD81FE702D00022D681 /* WeakMapImplInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E393ADD71FE702CC0022D681 /* WeakMapImplInlines.h */; };
 		E39D45F51D39005600B3B377 /* InterpreterInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E39D9D841D39000600667282 /* InterpreterInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E39DA4A71B7E8B7C0084F33A /* JSModuleRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = E39DA4A51B7E8B7C0084F33A /* JSModuleRecord.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		E39EEAF322812450008474F4 /* ObjectToStringAdaptiveStructureWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = E39EEAF22281244C008474F4 /* ObjectToStringAdaptiveStructureWatchpoint.h */; };
 		E3A0531A21342B680022EC14 /* WasmStreamingParser.h in Headers */ = {isa = PBXBuildFile; fileRef = E3A0531621342B660022EC14 /* WasmStreamingParser.h */; };
 		E3A0531C21342B680022EC14 /* WasmSectionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = E3A0531821342B670022EC14 /* WasmSectionParser.h */; };
 		E3A32BC71FC83147007D7E76 /* WeakMapImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = E3A32BC61FC8312E007D7E76 /* WeakMapImpl.h */; };
@@ -4773,6 +4775,7 @@
 		E3555B891DAE03A200F36921 /* DOMJITCallDOMGetterSnippet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITCallDOMGetterSnippet.h; sourceTree = "<group>"; };
 		E355D38D2244686B008F1AD6 /* GlobalExecutable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GlobalExecutable.h; sourceTree = "<group>"; };
 		E355D38E2244686C008F1AD6 /* GlobalExecutable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = GlobalExecutable.cpp; sourceTree = "<group>"; };
+		E356987122841183008CDCCB /* PackedCellPtr.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PackedCellPtr.h; sourceTree = "<group>"; };
 		E35A0B9C220AD87A00AC4474 /* ExecutableBaseInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutableBaseInlines.h; sourceTree = "<group>"; };
 		E35CA14F1DBC3A5600F83516 /* DOMJITAbstractHeap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMJITAbstractHeap.cpp; sourceTree = "<group>"; };
 		E35CA1501DBC3A5600F83516 /* DOMJITAbstractHeap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITAbstractHeap.h; sourceTree = "<group>"; };
@@ -4799,6 +4802,8 @@
 		E39D9D841D39000600667282 /* InterpreterInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InterpreterInlines.h; sourceTree = "<group>"; };
 		E39DA4A41B7E8B7C0084F33A /* JSModuleRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSModuleRecord.cpp; sourceTree = "<group>"; };
 		E39DA4A51B7E8B7C0084F33A /* JSModuleRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSModuleRecord.h; sourceTree = "<group>"; };
+		E39EEAF12281244C008474F4 /* ObjectToStringAdaptiveStructureWatchpoint.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectToStringAdaptiveStructureWatchpoint.cpp; sourceTree = "<group>"; };
+		E39EEAF22281244C008474F4 /* ObjectToStringAdaptiveStructureWatchpoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ObjectToStringAdaptiveStructureWatchpoint.h; sourceTree = "<group>"; };
 		E3A0531621342B660022EC14 /* WasmStreamingParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmStreamingParser.h; sourceTree = "<group>"; };
 		E3A0531721342B660022EC14 /* WasmSectionParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmSectionParser.cpp; sourceTree = "<group>"; };
 		E3A0531821342B670022EC14 /* WasmSectionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmSectionParser.h; sourceTree = "<group>"; };
@@ -6025,6 +6030,7 @@
 				0F1FB3981E1F65F900A9BE50 /* MutatorScheduler.h */,
 				0FA762021DB9242300B7A2FD /* MutatorState.cpp */,
 				0FA762031DB9242300B7A2FD /* MutatorState.h */,
+				E356987122841183008CDCCB /* PackedCellPtr.h */,
 				0F9DAA081FD1C3C80079C5B2 /* ParallelSourceAdapter.h */,
 				0FBB73B61DEF3AAC002C009E /* PreventCollectionScope.h */,
 				0FD0E5EF1E46BF230006AB08 /* RegisterState.h */,
@@ -7174,6 +7180,8 @@
 				E3C295DC1ED2CBAA00D3016F /* ObjectPropertyChangeAdaptiveWatchpoint.h */,
 				BC2680C80E16D4E900A06E92 /* ObjectPrototype.cpp */,
 				BC2680C90E16D4E900A06E92 /* ObjectPrototype.h */,
+				E39EEAF12281244C008474F4 /* ObjectToStringAdaptiveStructureWatchpoint.cpp */,
+				E39EEAF22281244C008474F4 /* ObjectToStringAdaptiveStructureWatchpoint.h */,
 				F692A8770255597D01FF60F7 /* Operations.cpp */,
 				F692A8780255597D01FF60F7 /* Operations.h */,
 				0FE228EA1436AB2300196C48 /* Options.cpp */,
@@ -9660,6 +9668,7 @@
 				0FD3E40A1B618B6600C80E1E /* ObjectPropertyCondition.h in Headers */,
 				0FD3E40C1B618B6600C80E1E /* ObjectPropertyConditionSet.h in Headers */,
 				BC18C4460E16F5CD00B34460 /* ObjectPrototype.h in Headers */,
+				E39EEAF322812450008474F4 /* ObjectToStringAdaptiveStructureWatchpoint.h in Headers */,
 				E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */,
 				14F79F70216EAFD200046D39 /* Opcode.h in Headers */,
 				FE64872E2141D04800AB0D3E /* OpcodeInlines.h in Headers */,
@@ -9668,6 +9677,7 @@
 				A70447EA17A0BD4600F5898E /* OperandsInlines.h in Headers */,
 				BC18C4480E16F5CD00B34460 /* Operations.h in Headers */,
 				0FE228ED1436AB2700196C48 /* Options.h in Headers */,
+				E356987222841187008CDCCB /* PackedCellPtr.h in Headers */,
 				0F9DAA0A1FD1C3D30079C5B2 /* ParallelSourceAdapter.h in Headers */,
 				E34E657520668EAA00FB81AC /* ParseHash.h in Headers */,
 				37C738D21EDB56E4003F2B0B /* ParseInt.h in Headers */,

Modified: trunk/Source/_javascript_Core/Sources.txt (245213 => 245214)


--- trunk/Source/_javascript_Core/Sources.txt	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/_javascript_Core/Sources.txt	2019-05-12 22:50:21 UTC (rev 245214)
@@ -899,6 +899,7 @@
 runtime/ObjectConstructor.cpp
 runtime/ObjectInitializationScope.cpp
 runtime/ObjectPrototype.cpp
+runtime/ObjectToStringAdaptiveStructureWatchpoint.cpp
 runtime/Operations.cpp
 runtime/Options.cpp
 runtime/ProgramExecutable.cpp

Modified: trunk/Source/_javascript_Core/bytecode/AdaptiveInferredPropertyValueWatchpointBase.h (245213 => 245214)


--- trunk/Source/_javascript_Core/bytecode/AdaptiveInferredPropertyValueWatchpointBase.h	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/_javascript_Core/bytecode/AdaptiveInferredPropertyValueWatchpointBase.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -45,24 +45,33 @@
 
     virtual ~AdaptiveInferredPropertyValueWatchpointBase() = default;
 
-protected:
-    virtual bool isValid() const;
-    virtual void handleFire(VM&, const FireDetail&) = 0;
-
-private:
     class StructureWatchpoint final : public Watchpoint {
     public:
-        StructureWatchpoint() { }
-    protected:
-        void fireInternal(VM&, const FireDetail&) override;
+        StructureWatchpoint()
+            : Watchpoint(Watchpoint::Type::AdaptiveInferredPropertyValueStructure)
+        { }
+
+        void fireInternal(VM&, const FireDetail&);
     };
+    // Own destructor may not be called. Keep members trivially destructible.
+    static_assert(sizeof(StructureWatchpoint) == sizeof(Watchpoint), "");
+
     class PropertyWatchpoint final : public Watchpoint {
     public:
-        PropertyWatchpoint() { }
-    protected:
-        void fireInternal(VM&, const FireDetail&) override;
+        PropertyWatchpoint()
+            : Watchpoint(Watchpoint::Type::AdaptiveInferredPropertyValueProperty)
+        { }
+
+        void fireInternal(VM&, const FireDetail&);
     };
+    // Own destructor may not be called. Keep members trivially destructible.
+    static_assert(sizeof(PropertyWatchpoint) == sizeof(Watchpoint), "");
 
+protected:
+    virtual bool isValid() const;
+    virtual void handleFire(VM&, const FireDetail&) = 0;
+
+private:
     void fire(VM&, const FireDetail&);
 
     ObjectPropertyCondition m_key;

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlockJettisoningWatchpoint.h (245213 => 245214)


--- trunk/Source/_javascript_Core/bytecode/CodeBlockJettisoningWatchpoint.h	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlockJettisoningWatchpoint.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -25,6 +25,7 @@
 
 #pragma once
 
+#include "PackedCellPtr.h"
 #include "Watchpoint.h"
 
 namespace JSC {
@@ -34,15 +35,15 @@
 class CodeBlockJettisoningWatchpoint final : public Watchpoint {
 public:
     CodeBlockJettisoningWatchpoint(CodeBlock* codeBlock)
-        : m_codeBlock(codeBlock)
+        : Watchpoint(Watchpoint::Type::CodeBlockJettisoning)
+        , m_codeBlock(codeBlock)
     {
     }
     
-protected:
-    void fireInternal(VM&, const FireDetail&) override;
+    void fireInternal(VM&, const FireDetail&);
 
 private:
-    CodeBlock* m_codeBlock;
+    JSC_WATCHPOINT_FIELD(PackedCellPtr<CodeBlock>, m_codeBlock);
 };
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/bytecode/CodeOrigin.h (245213 => 245214)


--- trunk/Source/_javascript_Core/bytecode/CodeOrigin.h	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/_javascript_Core/bytecode/CodeOrigin.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -232,14 +232,9 @@
         return bitwise_cast<InlineCallFrame*>(value);
     }
 
-#if CPU(ARM64) && CPU(ADDRESS64)
-    static constexpr unsigned s_freeBitsAtTop = 28;
-    static constexpr uintptr_t s_maskCompositeValueForPointer = 0x0000000ffffffff8;
-#elif CPU(ADDRESS64)
-    static constexpr unsigned s_freeBitsAtTop = 16;
-    static constexpr uintptr_t s_maskCompositeValueForPointer = 0x0000fffffffffff8;
-#endif
 #if CPU(ADDRESS64)
+    static constexpr unsigned s_freeBitsAtTop = 64 - WTF_CPU_EFFECTIVE_ADDRESS_WIDTH;
+    static constexpr uintptr_t s_maskCompositeValueForPointer = ((1ULL << WTF_CPU_EFFECTIVE_ADDRESS_WIDTH) - 1) & ~(8ULL - 1);
     static uintptr_t buildCompositeValue(InlineCallFrame* inlineCallFrame, unsigned bytecodeIndex)
     {
         if (bytecodeIndex == s_invalidBytecodeIndex)

Modified: trunk/Source/_javascript_Core/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp (245213 => 245214)


--- trunk/Source/_javascript_Core/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/_javascript_Core/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp	2019-05-12 22:50:21 UTC (rev 245214)
@@ -33,9 +33,10 @@
 namespace JSC {
 
 LLIntPrototypeLoadAdaptiveStructureWatchpoint::LLIntPrototypeLoadAdaptiveStructureWatchpoint(CodeBlock* owner, const ObjectPropertyCondition& key, unsigned bytecodeOffset)
-    : m_owner(owner)
+    : Watchpoint(Watchpoint::Type::LLIntPrototypeLoadAdaptiveStructure)
+    , m_owner(owner)
+    , m_bytecodeOffset(bytecodeOffset)
     , m_key(key)
-    , m_bytecodeOffset(bytecodeOffset)
 {
     RELEASE_ASSERT(key.watchingRequiresStructureTransitionWatchpoint());
     RELEASE_ASSERT(!key.watchingRequiresReplacementWatchpoint());
@@ -58,8 +59,8 @@
         return;
     }
 
-    auto& instruction = m_owner->instructions().at(m_bytecodeOffset);
-    clearLLIntGetByIdCache(instruction->as<OpGetById>().metadata(m_owner));
+    auto& instruction = m_owner->instructions().at(m_bytecodeOffset.get());
+    clearLLIntGetByIdCache(instruction->as<OpGetById>().metadata(m_owner.get()));
 }
 
 void LLIntPrototypeLoadAdaptiveStructureWatchpoint::clearLLIntGetByIdCache(OpGetById::Metadata& metadata)

Modified: trunk/Source/_javascript_Core/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h (245213 => 245214)


--- trunk/Source/_javascript_Core/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/_javascript_Core/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -27,6 +27,7 @@
 
 #include "BytecodeStructs.h"
 #include "ObjectPropertyCondition.h"
+#include "PackedCellPtr.h"
 #include "Watchpoint.h"
 
 namespace JSC {
@@ -41,13 +42,13 @@
 
     const ObjectPropertyCondition& key() const { return m_key; }
 
-protected:
-    void fireInternal(VM&, const FireDetail&) override;
+    void fireInternal(VM&, const FireDetail&);
 
 private:
-    CodeBlock* m_owner;
-    ObjectPropertyCondition m_key;
-    unsigned m_bytecodeOffset;
+    // Own destructor may not be called. Keep members trivially destructible.
+    JSC_WATCHPOINT_FIELD(PackedCellPtr<CodeBlock>, m_owner);
+    JSC_WATCHPOINT_FIELD(Packed<unsigned>, m_bytecodeOffset);
+    JSC_WATCHPOINT_FIELD(ObjectPropertyCondition, m_key);
 };
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/bytecode/StructureStubClearingWatchpoint.cpp (245213 => 245214)


--- trunk/Source/_javascript_Core/bytecode/StructureStubClearingWatchpoint.cpp	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/_javascript_Core/bytecode/StructureStubClearingWatchpoint.cpp	2019-05-12 22:50:21 UTC (rev 245214)
@@ -36,7 +36,7 @@
 
 void StructureStubClearingWatchpoint::fireInternal(VM& vm, const FireDetail&)
 {
-    if (!m_holder.isValid())
+    if (!m_holder->isValid())
         return;
 
     if (!m_key || !m_key.isWatchable(PropertyCondition::EnsureWatchability)) {
@@ -43,8 +43,8 @@
         // This will implicitly cause my own demise: stub reset removes all watchpoints.
         // That works, because deleting a watchpoint removes it from the set's list, and
         // the set's list traversal for firing is robust against the set changing.
-        ConcurrentJSLocker locker(m_holder.codeBlock()->m_lock);
-        m_holder.stubInfo()->reset(m_holder.codeBlock());
+        ConcurrentJSLocker locker(m_holder->codeBlock()->m_lock);
+        m_holder->stubInfo()->reset(m_holder->codeBlock());
         return;
     }
 

Modified: trunk/Source/_javascript_Core/bytecode/StructureStubClearingWatchpoint.h (245213 => 245214)


--- trunk/Source/_javascript_Core/bytecode/StructureStubClearingWatchpoint.h	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/_javascript_Core/bytecode/StructureStubClearingWatchpoint.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -44,20 +44,19 @@
     WTF_MAKE_NONCOPYABLE(StructureStubClearingWatchpoint);
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    StructureStubClearingWatchpoint(
-        const ObjectPropertyCondition& key,
-        WatchpointsOnStructureStubInfo& holder)
-        : m_key(key)
-        , m_holder(holder)
+    StructureStubClearingWatchpoint(const ObjectPropertyCondition& key, WatchpointsOnStructureStubInfo& holder)
+        : Watchpoint(Watchpoint::Type::StructureStubClearing)
+        , m_holder(&holder)
+        , m_key(key)
     {
     }
 
-protected:
-    void fireInternal(VM&, const FireDetail&) override;
+    void fireInternal(VM&, const FireDetail&);
 
 private:
-    ObjectPropertyCondition m_key;
-    WatchpointsOnStructureStubInfo& m_holder;
+    // Own destructor may not be called. Keep members trivially destructible.
+    JSC_WATCHPOINT_FIELD(PackedPtr<WatchpointsOnStructureStubInfo>, m_holder);
+    JSC_WATCHPOINT_FIELD(ObjectPropertyCondition, m_key);
 };
 
 class WatchpointsOnStructureStubInfo {

Modified: trunk/Source/_javascript_Core/bytecode/Watchpoint.cpp (245213 => 245214)


--- trunk/Source/_javascript_Core/bytecode/Watchpoint.cpp	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/_javascript_Core/bytecode/Watchpoint.cpp	2019-05-12 22:50:21 UTC (rev 245214)
@@ -26,7 +26,14 @@
 #include "config.h"
 #include "Watchpoint.h"
 
+#include "AdaptiveInferredPropertyValueWatchpointBase.h"
+#include "CodeBlockJettisoningWatchpoint.h"
+#include "DFGAdaptiveStructureWatchpoint.h"
+#include "FunctionRareData.h"
 #include "HeapInlines.h"
+#include "LLIntPrototypeLoadAdaptiveStructureWatchpoint.h"
+#include "ObjectToStringAdaptiveStructureWatchpoint.h"
+#include "StructureStubClearingWatchpoint.h"
 #include "VM.h"
 #include <wtf/CompilationThread.h>
 
@@ -52,7 +59,14 @@
 void Watchpoint::fire(VM& vm, const FireDetail& detail)
 {
     RELEASE_ASSERT(!isOnList());
-    fireInternal(vm, detail);
+    switch (m_type) {
+#define JSC_DEFINE_WATCHPOINT_DISPATCH(type, cast) \
+    case Type::type: \
+        static_cast<cast*>(this)->fireInternal(vm, detail); \
+        break;
+    JSC_WATCHPOINT_TYPES(JSC_DEFINE_WATCHPOINT_DISPATCH)
+#undef JSC_DEFINE_WATCHPOINT_DISPATCH
+    }
 }
 
 WatchpointSet::WatchpointSet(WatchpointState state)

Modified: trunk/Source/_javascript_Core/bytecode/Watchpoint.h (245213 => 245214)


--- trunk/Source/_javascript_Core/bytecode/Watchpoint.h	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/_javascript_Core/bytecode/Watchpoint.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -90,21 +90,75 @@
 
 class WatchpointSet;
 
-class Watchpoint : public BasicRawSentinelNode<Watchpoint> {
+// Really unfortunately, we do not have the way to dispatch appropriate destructor in base class' destructor
+// based on enum type. If we call destructor explicitly in the base class, it ends up calling the base destructor
+// twice. C++20 allows this by using std::std::destroying_delete_t. But we are not using C++20 right now.
+//
+// Because we cannot dispatch destructors of derived classes in the destructor of the base class, what it means is,
+// 1. Calling Watchpoint::~Watchpoint directly is illegal.
+// 2. `delete watchpoint` where watchpoint is non-final derived class is illegal. If watchpoint is final derived class, it works.
+// 3. If we really want to do (2), we need to call `watchpoint->destroy()` instead, and dispatch an appropriate destructor in Watchpoint::destroy.
+//
+// Luckily, none of our derived watchpoint classes have members which require destructors. So we do not dispatch
+// the destructor call to the drived class in the base class. If it becomes really required, we can introduce
+// a custom deleter for some classes which directly call "delete" to the allocated non-final Watchpoint class
+// (e.g. std::unique_ptr<Watchpoint>, RefPtr<Watchpoint>), and call Watchpoint::destroy instead of "delete"
+// operator. But since we do not require it for now, we are doing the simplest thing.
+#define JSC_WATCHPOINT_TYPES_WITHOUT_JIT(macro) \
+    macro(AdaptiveInferredPropertyValueStructure, AdaptiveInferredPropertyValueWatchpointBase::StructureWatchpoint) \
+    macro(AdaptiveInferredPropertyValueProperty, AdaptiveInferredPropertyValueWatchpointBase::PropertyWatchpoint) \
+    macro(CodeBlockJettisoning, CodeBlockJettisoningWatchpoint) \
+    macro(LLIntPrototypeLoadAdaptiveStructure, LLIntPrototypeLoadAdaptiveStructureWatchpoint) \
+    macro(FunctionRareDataAllocationProfileClearing, FunctionRareData::AllocationProfileClearingWatchpoint) \
+    macro(ObjectToStringAdaptiveStructure, ObjectToStringAdaptiveStructureWatchpoint)
+
+#if ENABLE(JIT)
+#define JSC_WATCHPOINT_TYPES_WITHOUT_DFG(macro) \
+    JSC_WATCHPOINT_TYPES_WITHOUT_JIT(macro) \
+    macro(StructureStubClearing, StructureStubClearingWatchpoint)
+
+#if ENABLE(DFG_JIT)
+#define JSC_WATCHPOINT_TYPES(macro) \
+    JSC_WATCHPOINT_TYPES_WITHOUT_DFG(macro) \
+    macro(AdaptiveStructure, DFG::AdaptiveStructureWatchpoint)
+#else
+#define JSC_WATCHPOINT_TYPES(macro) \
+    JSC_WATCHPOINT_TYPES_WITHOUT_DFG(macro)
+#endif
+
+#else
+#define JSC_WATCHPOINT_TYPES(macro) \
+    JSC_WATCHPOINT_TYPES_WITHOUT_JIT(macro)
+#endif
+
+#define JSC_WATCHPOINT_FIELD(type, member) \
+    type member; \
+    static_assert(std::is_trivially_destructible<type>::value, ""); \
+
+
+class Watchpoint : public PackedRawSentinelNode<Watchpoint> {
     WTF_MAKE_NONCOPYABLE(Watchpoint);
     WTF_MAKE_NONMOVABLE(Watchpoint);
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    Watchpoint() = default;
-    
-    virtual ~Watchpoint();
+#define JSC_DEFINE_WATCHPOINT_TYPES(type, _) type,
+    enum class Type : uint8_t {
+        JSC_WATCHPOINT_TYPES(JSC_DEFINE_WATCHPOINT_TYPES)
+    };
+#undef JSC_DEFINE_WATCHPOINT_TYPES
 
+    Watchpoint(Type type)
+        : m_type(type)
+    { }
+
 protected:
-    virtual void fireInternal(VM&, const FireDetail&) = 0;
+    ~Watchpoint();
 
 private:
     friend class WatchpointSet;
     void fire(VM&, const FireDetail&);
+
+    Type m_type;
 };
 
 enum WatchpointState {
@@ -239,7 +293,7 @@
     int8_t m_state;
     int8_t m_setIsNotEmpty;
 
-    SentinelLinkedList<Watchpoint, BasicRawSentinelNode<Watchpoint>> m_set;
+    SentinelLinkedList<Watchpoint, PackedRawSentinelNode<Watchpoint>> m_set;
 };
 
 // InlineWatchpointSet is a low-overhead, non-copyable watchpoint set in which

Modified: trunk/Source/_javascript_Core/dfg/DFGAdaptiveStructureWatchpoint.cpp (245213 => 245214)


--- trunk/Source/_javascript_Core/dfg/DFGAdaptiveStructureWatchpoint.cpp	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/_javascript_Core/dfg/DFGAdaptiveStructureWatchpoint.cpp	2019-05-12 22:50:21 UTC (rev 245214)
@@ -33,11 +33,10 @@
 
 namespace JSC { namespace DFG {
 
-AdaptiveStructureWatchpoint::AdaptiveStructureWatchpoint(
-    const ObjectPropertyCondition& key,
-    CodeBlock* codeBlock)
-    : m_key(key)
+AdaptiveStructureWatchpoint::AdaptiveStructureWatchpoint(const ObjectPropertyCondition& key, CodeBlock* codeBlock)
+    : Watchpoint(Watchpoint::Type::AdaptiveStructure)
     , m_codeBlock(codeBlock)
+    , m_key(key)
 {
     RELEASE_ASSERT(key.watchingRequiresStructureTransitionWatchpoint());
     RELEASE_ASSERT(!key.watchingRequiresReplacementWatchpoint());

Modified: trunk/Source/_javascript_Core/dfg/DFGAdaptiveStructureWatchpoint.h (245213 => 245214)


--- trunk/Source/_javascript_Core/dfg/DFGAdaptiveStructureWatchpoint.h	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/_javascript_Core/dfg/DFGAdaptiveStructureWatchpoint.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -28,6 +28,7 @@
 #if ENABLE(DFG_JIT)
 
 #include "ObjectPropertyCondition.h"
+#include "PackedCellPtr.h"
 #include "Watchpoint.h"
 
 namespace JSC { namespace DFG {
@@ -40,12 +41,12 @@
     
     void install(VM&);
 
-protected:
-    void fireInternal(VM&, const FireDetail&) override;
+    void fireInternal(VM&, const FireDetail&);
 
 private:
-    ObjectPropertyCondition m_key;
-    CodeBlock* m_codeBlock;
+    // Own destructor may not be called. Keep members trivially destructible.
+    JSC_WATCHPOINT_FIELD(PackedCellPtr<CodeBlock>, m_codeBlock);
+    JSC_WATCHPOINT_FIELD(ObjectPropertyCondition, m_key);
 };
 
 } } // namespace JSC::DFG

Added: trunk/Source/_javascript_Core/heap/PackedCellPtr.h (0 => 245214)


--- trunk/Source/_javascript_Core/heap/PackedCellPtr.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/heap/PackedCellPtr.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "MarkedBlock.h"
+#include <wtf/Packed.h>
+
+namespace JSC {
+
+template<typename T>
+using PackedCellPtr = PackedAlignedPtr<T, MarkedBlock::atomSize>;
+
+} // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/FunctionRareData.h (245213 => 245214)


--- trunk/Source/_javascript_Core/runtime/FunctionRareData.h	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/_javascript_Core/runtime/FunctionRareData.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -28,6 +28,7 @@
 #include "InternalFunctionAllocationProfile.h"
 #include "JSCast.h"
 #include "ObjectAllocationProfile.h"
+#include "PackedCellPtr.h"
 #include "Watchpoint.h"
 
 namespace JSC {
@@ -110,23 +111,25 @@
         return m_allocationProfileClearingWatchpoint.get();
     }
 
-protected:
-    FunctionRareData(VM&);
-    ~FunctionRareData();
-
-private:
-
     class AllocationProfileClearingWatchpoint final : public Watchpoint {
     public:
         AllocationProfileClearingWatchpoint(FunctionRareData* rareData)
-            : m_rareData(rareData)
+            : Watchpoint(Watchpoint::Type::FunctionRareDataAllocationProfileClearing)
+            , m_rareData(rareData)
         { }
-    protected:
-        void fireInternal(VM&, const FireDetail&) override;
+
+        void fireInternal(VM&, const FireDetail&);
+
     private:
-        FunctionRareData* m_rareData;
+        // Own destructor may not be called. Keep members trivially destructible.
+        JSC_WATCHPOINT_FIELD(PackedCellPtr<FunctionRareData>, m_rareData);
     };
 
+protected:
+    FunctionRareData(VM&);
+    ~FunctionRareData();
+
+private:
     friend class LLIntOffsetsExtractor;
 
     // Ideally, there would only be one allocation profile for subclassing but due to Reflect.construct we

Added: trunk/Source/_javascript_Core/runtime/ObjectToStringAdaptiveStructureWatchpoint.cpp (0 => 245214)


--- trunk/Source/_javascript_Core/runtime/ObjectToStringAdaptiveStructureWatchpoint.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/ObjectToStringAdaptiveStructureWatchpoint.cpp	2019-05-12 22:50:21 UTC (rev 245214)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ObjectToStringAdaptiveStructureWatchpoint.h"
+
+#include "ObjectPropertyConditionSet.h"
+#include "StructureRareData.h"
+
+namespace JSC {
+
+ObjectToStringAdaptiveStructureWatchpoint::ObjectToStringAdaptiveStructureWatchpoint(const ObjectPropertyCondition& key, StructureRareData* structureRareData)
+    : Watchpoint(Watchpoint::Type::ObjectToStringAdaptiveStructure)
+    , m_structureRareData(structureRareData)
+    , m_key(key)
+{
+    RELEASE_ASSERT(key.watchingRequiresStructureTransitionWatchpoint());
+    RELEASE_ASSERT(!key.watchingRequiresReplacementWatchpoint());
+}
+
+void ObjectToStringAdaptiveStructureWatchpoint::install(VM& vm)
+{
+    RELEASE_ASSERT(m_key.isWatchable());
+
+    m_key.object()->structure(vm)->addTransitionWatchpoint(this);
+}
+
+void ObjectToStringAdaptiveStructureWatchpoint::fireInternal(VM& vm, const FireDetail&)
+{
+    if (!m_structureRareData->isLive())
+        return;
+
+    if (m_key.isWatchable(PropertyCondition::EnsureWatchability)) {
+        install(vm);
+        return;
+    }
+
+    m_structureRareData->clearObjectToStringValue();
+}
+
+} // namespace JSC

Added: trunk/Source/_javascript_Core/runtime/ObjectToStringAdaptiveStructureWatchpoint.h (0 => 245214)


--- trunk/Source/_javascript_Core/runtime/ObjectToStringAdaptiveStructureWatchpoint.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/ObjectToStringAdaptiveStructureWatchpoint.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "ObjectPropertyCondition.h"
+#include "PackedCellPtr.h"
+#include "Watchpoint.h"
+
+namespace JSC {
+
+class StructureRareData;
+
+class ObjectToStringAdaptiveStructureWatchpoint final : public Watchpoint {
+public:
+    ObjectToStringAdaptiveStructureWatchpoint(const ObjectPropertyCondition&, StructureRareData*);
+
+    void install(VM&);
+
+    const ObjectPropertyCondition& key() const { return m_key; }
+
+    void fireInternal(VM&, const FireDetail&);
+    
+private:
+    // Own destructor may not be called. Keep members trivially destructible.
+    JSC_WATCHPOINT_FIELD(PackedCellPtr<StructureRareData>, m_structureRareData);
+    JSC_WATCHPOINT_FIELD(ObjectPropertyCondition, m_key);
+};
+
+}

Modified: trunk/Source/_javascript_Core/runtime/StructureRareData.cpp (245213 => 245214)


--- trunk/Source/_javascript_Core/runtime/StructureRareData.cpp	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/_javascript_Core/runtime/StructureRareData.cpp	2019-05-12 22:50:21 UTC (rev 245214)
@@ -32,6 +32,7 @@
 #include "JSString.h"
 #include "JSCInlines.h"
 #include "ObjectPropertyConditionSet.h"
+#include "ObjectToStringAdaptiveStructureWatchpoint.h"
 
 namespace JSC {
 
@@ -90,22 +91,6 @@
     StructureRareData* m_structureRareData;
 };
 
-class ObjectToStringAdaptiveStructureWatchpoint final : public Watchpoint {
-public:
-    ObjectToStringAdaptiveStructureWatchpoint(const ObjectPropertyCondition&, StructureRareData*);
-
-    void install(VM&);
-
-    const ObjectPropertyCondition& key() const { return m_key; }
-
-protected:
-    void fireInternal(VM&, const FireDetail&) override;
-    
-private:
-    ObjectPropertyCondition m_key;
-    StructureRareData* m_structureRareData;
-};
-
 void StructureRareData::setObjectToStringValue(ExecState* exec, VM& vm, Structure* ownStructure, JSString* value, PropertySlot toStringTagSymbolSlot)
 {
     if (m_giveUpOnObjectToStringValueCache)
@@ -164,7 +149,7 @@
     m_objectToStringValue.set(vm, this, value);
 }
 
-inline void StructureRareData::clearObjectToStringValue()
+void StructureRareData::clearObjectToStringValue()
 {
     m_objectToStringAdaptiveWatchpointSet.clear();
     m_objectToStringAdaptiveInferredValueWatchpoint.reset();
@@ -189,34 +174,6 @@
 
 // ------------- Methods for Object.prototype.toString() helper watchpoint classes --------------
 
-ObjectToStringAdaptiveStructureWatchpoint::ObjectToStringAdaptiveStructureWatchpoint(const ObjectPropertyCondition& key, StructureRareData* structureRareData)
-    : m_key(key)
-    , m_structureRareData(structureRareData)
-{
-    RELEASE_ASSERT(key.watchingRequiresStructureTransitionWatchpoint());
-    RELEASE_ASSERT(!key.watchingRequiresReplacementWatchpoint());
-}
-
-void ObjectToStringAdaptiveStructureWatchpoint::install(VM& vm)
-{
-    RELEASE_ASSERT(m_key.isWatchable());
-
-    m_key.object()->structure(vm)->addTransitionWatchpoint(this);
-}
-
-void ObjectToStringAdaptiveStructureWatchpoint::fireInternal(VM& vm, const FireDetail&)
-{
-    if (!m_structureRareData->isLive())
-        return;
-
-    if (m_key.isWatchable(PropertyCondition::EnsureWatchability)) {
-        install(vm);
-        return;
-    }
-
-    m_structureRareData->clearObjectToStringValue();
-}
-
 ObjectToStringAdaptiveInferredPropertyValueWatchpoint::ObjectToStringAdaptiveInferredPropertyValueWatchpoint(const ObjectPropertyCondition& key, StructureRareData* structureRareData)
     : Base(key)
     , m_structureRareData(structureRareData)

Modified: trunk/Source/_javascript_Core/runtime/StructureRareData.h (245213 => 245214)


--- trunk/Source/_javascript_Core/runtime/StructureRareData.h	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/_javascript_Core/runtime/StructureRareData.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -35,8 +35,8 @@
 
 class JSPropertyNameEnumerator;
 class Structure;
+class ObjectToStringAdaptiveInferredPropertyValueWatchpoint;
 class ObjectToStringAdaptiveStructureWatchpoint;
-class ObjectToStringAdaptiveInferredPropertyValueWatchpoint;
 
 class StructureRareData final : public JSCell {
 public:

Modified: trunk/Source/WTF/ChangeLog (245213 => 245214)


--- trunk/Source/WTF/ChangeLog	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/WTF/ChangeLog	2019-05-12 22:50:21 UTC (rev 245214)
@@ -1,3 +1,89 @@
+2019-05-12  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Compress Watchpoint size by using enum type and Packed<> data structure
+        https://bugs.webkit.org/show_bug.cgi?id=197730
+
+        Reviewed by Filip Pizlo.
+
+        This patch introduces a new data structures, WTF::Packed, WTF::PackedPtr, and WTF::PackedAlignedPtr.
+
+        - WTF::Packed
+
+            WTF::Packed is data storage. We can read and write trivial (in C++ term [1]) data to this storage. The difference to
+            the usual storage is that the alignment of this storage is always 1. We access the underlying data by using unalignedLoad/unalignedStore.
+            This class offers alignment = 1 data structure instead of missing the following characteristics.
+
+                1. Load / Store are non atomic even if the data size is within a pointer width. We should not use this for a member which can be accessed
+                   in a racy way. (e.g. fields accessed optimistically from the concurrent compilers).
+
+                2. We cannot take reference / pointer to the underlying storage since they are unaligned.
+
+                3. Access to this storage is unaligned access. The code is using memcpy, and the compiler will convert to an appropriate unaligned access
+                   in certain architectures (x86_64 / ARM64). It could be slow. So use it for non performance sensitive & memory sensitive places.
+
+        - WTF::PackedPtr
+
+            WTF::PackedPtr is a specialization of WTF::Packed<T*>. And it is basically WTF::PackedAlignedPtr with alignment = 1. We further compact
+            the pointer by leveraging the platform specific knowledge. In 64bit architectures, the effective width of pointers are less than 64 bit.
+            In x86_64, it is 48 bits. And Darwin ARM64 is further smaller, 36 bits. This information allows us to compact the pointer to 6 bytes in
+            x86_64 and 5 bytes in Darwin ARM64.
+
+        - WTF::PackedAlignedPtr
+
+            WTF::PackedAlignedPtr is the WTF::PackedPtr with alignment information of the T. If we use this alignment information, we could reduce the
+            size of packed pointer further in some cases. For example, since we guarantee that JSCells are 16 byte aligned, low 4 bits are empty. Leveraging
+            this information in Darwin ARM64 platform allows us to make packed JSCell pointer 4 bytes (36 - 4 bits). We do not use passed alignment
+            information if it is not profitable.
+
+        We also have PackedPtrTraits. This is new PtrTraits and use it for various data structures such as Bag<>.
+
+        [1]: https://en.cppreference.com/w/cpp/types/is_trivial
+
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/Bag.h:
+        (WTF::Bag::clear):
+        (WTF::Bag::iterator::operator++):
+        * wtf/CMakeLists.txt:
+        * wtf/DumbPtrTraits.h:
+        * wtf/DumbValueTraits.h:
+        * wtf/MathExtras.h:
+        (WTF::clzConstexpr):
+        (WTF::clz):
+        (WTF::ctzConstexpr):
+        (WTF::ctz):
+        (WTF::getLSBSetConstexpr):
+        (WTF::getMSBSetConstexpr):
+        * wtf/Packed.h: Added.
+        (WTF::Packed::Packed):
+        (WTF::Packed::get const):
+        (WTF::Packed::set):
+        (WTF::Packed::operator=):
+        (WTF::Packed::exchange):
+        (WTF::Packed::swap):
+        (WTF::alignof):
+        (WTF::PackedPtrTraits::exchange):
+        (WTF::PackedPtrTraits::swap):
+        (WTF::PackedPtrTraits::unwrap):
+        * wtf/Platform.h:
+        * wtf/SentinelLinkedList.h:
+        (WTF::BasicRawSentinelNode::BasicRawSentinelNode):
+        (WTF::BasicRawSentinelNode::prev):
+        (WTF::BasicRawSentinelNode::next):
+        (WTF::PtrTraits>::remove):
+        (WTF::PtrTraits>::prepend):
+        (WTF::PtrTraits>::append):
+        (WTF::RawNode>::SentinelLinkedList):
+        (WTF::RawNode>::remove):
+        (WTF::BasicRawSentinelNode<T>::remove): Deleted.
+        (WTF::BasicRawSentinelNode<T>::prepend): Deleted.
+        (WTF::BasicRawSentinelNode<T>::append): Deleted.
+        * wtf/StdLibExtras.h:
+        (WTF::roundUpToMultipleOfImpl):
+        (WTF::roundUpToMultipleOfImpl0): Deleted.
+        * wtf/UnalignedAccess.h:
+        (WTF::unalignedLoad):
+        (WTF::unalignedStore):
+
 2019-05-10  Saam barati  <[email protected]>
 
         Bag's move operator= leaks memory

Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (245213 => 245214)


--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2019-05-12 22:50:21 UTC (rev 245214)
@@ -658,6 +658,7 @@
 		E311FB161F0A568B003C08DE /* ThreadGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadGroup.h; sourceTree = "<group>"; };
 		E3200AB41E9A536D003B59D2 /* PlatformRegisters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformRegisters.h; sourceTree = "<group>"; };
 		E33D5F871FBED66700BF625E /* RecursableLambda.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecursableLambda.h; sourceTree = "<group>"; };
+		E34CD0D022810A020020D299 /* Packed.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Packed.h; sourceTree = "<group>"; };
 		E360C7642127B85B00C90F0E /* UnalignedAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnalignedAccess.h; sourceTree = "<group>"; };
 		E360C7652127B85C00C90F0E /* Unexpected.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Unexpected.h; sourceTree = "<group>"; };
 		E388886D20C9095100E632BC /* WorkerPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WorkerPool.cpp; sourceTree = "<group>"; };
@@ -1056,6 +1057,7 @@
 				7CBBA07319BB7FDC00BBF025 /* OSObjectPtr.h */,
 				A8A472DA151A825B004123FF /* OSRandomSource.cpp */,
 				A8A472DB151A825B004123FF /* OSRandomSource.h */,
+				E34CD0D022810A020020D299 /* Packed.h */,
 				A8A472DF151A825B004123FF /* PackedIntVector.h */,
 				A8A472E0151A825B004123FF /* PageAllocation.h */,
 				A8A472E3151A825B004123FF /* PageBlock.cpp */,

Modified: trunk/Source/WTF/wtf/Bag.h (245213 => 245214)


--- trunk/Source/WTF/wtf/Bag.h	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/WTF/wtf/Bag.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -28,15 +28,18 @@
 #include <wtf/DumbPtrTraits.h>
 #include <wtf/FastMalloc.h>
 #include <wtf/Noncopyable.h>
+#include <wtf/Packed.h>
 
 namespace WTF {
 
 namespace Private {
 
-template<typename T>
+template<typename T, typename PassedPtrTraits = DumbPtrTraits<T>>
 class BagNode {
     WTF_MAKE_FAST_ALLOCATED;
 public:
+    using PtrTraits = typename PassedPtrTraits::template RebindTraits<BagNode>;
+
     template<typename... Args>
     BagNode(Args&&... args)
         : m_item(std::forward<Args>(args)...)
@@ -43,16 +46,17 @@
     { }
     
     T m_item;
-    BagNode* m_next { nullptr };
+    typename PtrTraits::StorageType m_next { nullptr };
 };
 
 } // namespace Private
 
-template<typename T, typename PtrTraits = DumbPtrTraits<Private::BagNode<T>>>
+template<typename T, typename PassedPtrTraits = DumbPtrTraits<T>>
 class Bag {
     WTF_MAKE_NONCOPYABLE(Bag);
     WTF_MAKE_FAST_ALLOCATED;
-    using Node = Private::BagNode<T>;
+    using Node = Private::BagNode<T, PassedPtrTraits>;
+    using PtrTraits = typename PassedPtrTraits::template RebindTraits<Node>;
 
 public:
     Bag() = default;
@@ -75,7 +79,7 @@
         Node* head = this->unwrappedHead();
         while (head) {
             Node* current = head;
-            head = current->m_next;
+            head = Node::PtrTraits::unwrap(current->m_next);
             delete current;
         }
         m_head = nullptr;
@@ -104,7 +108,7 @@
         
         iterator& operator++()
         {
-            m_node = m_node->m_next;
+            m_node = Node::PtrTraits::unwrap(m_node->m_next);
             return *this;
         }
         
@@ -148,6 +152,10 @@
     typename PtrTraits::StorageType m_head { nullptr };
 };
 
+template<typename T>
+using PackedBag = Bag<T, PackedPtrTraits<T>>;
+
 } // namespace WTF
 
 using WTF::Bag;
+using WTF::PackedBag;

Modified: trunk/Source/WTF/wtf/CMakeLists.txt (245213 => 245214)


--- trunk/Source/WTF/wtf/CMakeLists.txt	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/WTF/wtf/CMakeLists.txt	2019-05-12 22:50:21 UTC (rev 245214)
@@ -150,6 +150,7 @@
     OptionSet.h
     Optional.h
     OrderMaker.h
+    Packed.h
     PackedIntVector.h
     PageAllocation.h
     PageBlock.h

Modified: trunk/Source/WTF/wtf/DumbPtrTraits.h (245213 => 245214)


--- trunk/Source/WTF/wtf/DumbPtrTraits.h	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/WTF/wtf/DumbPtrTraits.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -32,6 +32,8 @@
     
 template<typename T>
 struct DumbPtrTraits {
+    template<typename U> using RebindTraits = DumbPtrTraits<U>;
+
     using StorageType = T*;
 
     template<typename U>

Modified: trunk/Source/WTF/wtf/DumbValueTraits.h (245213 => 245214)


--- trunk/Source/WTF/wtf/DumbValueTraits.h	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/WTF/wtf/DumbValueTraits.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -32,6 +32,8 @@
 
 template<typename T>
 struct DumbValueTraits {
+    template<typename U> using RebindTraits = DumbValueTraits<U>;
+
     using StorageType = T;
 
     template<typename U>

Modified: trunk/Source/WTF/wtf/MathExtras.h (245213 => 245214)


--- trunk/Source/WTF/wtf/MathExtras.h	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/WTF/wtf/MathExtras.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -615,6 +615,23 @@
     shuffleVector(vector, vector.size(), randomFunc);
 }
 
+template <typename T>
+constexpr unsigned clzConstexpr(T value)
+{
+    constexpr unsigned bitSize = sizeof(T) * CHAR_BIT;
+
+    using UT = typename std::make_unsigned<T>::type;
+    UT uValue = value;
+
+    unsigned zeroCount = 0;
+    for (int i = bitSize - 1; i >= 0; i--) {
+        if (uValue >> i)
+            break;
+        zeroCount++;
+    }
+    return zeroCount;
+}
+
 template<typename T>
 inline unsigned clz(T value)
 {
@@ -637,14 +654,29 @@
         return bitSize - 1 - ret;
     return bitSize;
 #else
+    UNUSED_PARAM(bitSize);
+    UNUSED_PARAM(uValue);
+    return clzConstexpr(value);
+#endif
+}
+
+template <typename T>
+constexpr unsigned ctzConstexpr(T value)
+{
+    constexpr unsigned bitSize = sizeof(T) * CHAR_BIT;
+
+    using UT = typename std::make_unsigned<T>::type;
+    UT uValue = value;
+
     unsigned zeroCount = 0;
-    for (int i = bitSize - 1; i >= 0; i--) {
-        if (uValue >> i)
+    for (unsigned i = 0; i < bitSize; i++) {
+        if (uValue & 1)
             break;
+
         zeroCount++;
+        uValue >>= 1;
     }
     return zeroCount;
-#endif
 }
 
 template<typename T>
@@ -665,15 +697,9 @@
         return ret;
     return bitSize;
 #else
-    unsigned zeroCount = 0;
-    for (unsigned i = 0; i < bitSize; i++) {
-        if (uValue & 1)
-            break;
-
-        zeroCount++;
-        uValue >>= 1;
-    }
-    return zeroCount;
+    UNUSED_PARAM(bitSize);
+    UNUSED_PARAM(uValue);
+    return ctzConstexpr(value);
 #endif
 }
 
@@ -685,6 +711,13 @@
 }
 
 template<typename T>
+constexpr unsigned getLSBSetConstexpr(T t)
+{
+    ASSERT_UNDER_CONSTEXPR_CONTEXT(t);
+    return ctzConstexpr(t);
+}
+
+template<typename T>
 inline unsigned getMSBSet(T t)
 {
     constexpr unsigned bitSize = sizeof(T) * CHAR_BIT;
@@ -692,6 +725,14 @@
     return bitSize - 1 - clz(t);
 }
 
+template<typename T>
+constexpr unsigned getMSBSetConstexpr(T t)
+{
+    constexpr unsigned bitSize = sizeof(T) * CHAR_BIT;
+    ASSERT_UNDER_CONSTEXPR_CONTEXT(t);
+    return bitSize - 1 - clzConstexpr(t);
+}
+
 } // namespace WTF
 
 using WTF::opaque;

Added: trunk/Source/WTF/wtf/Packed.h (0 => 245214)


--- trunk/Source/WTF/wtf/Packed.h	                        (rev 0)
+++ trunk/Source/WTF/wtf/Packed.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <array>
+#include <wtf/MathExtras.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/UnalignedAccess.h>
+
+namespace WTF {
+
+template<typename T>
+class Packed {
+public:
+    static constexpr bool isPackedType = true;
+
+    Packed()
+        : Packed(T { })
+    {
+    }
+
+    Packed(const T& value)
+    {
+        unalignedStore<T>(m_storage.data(), value);
+    }
+
+    T get() const
+    {
+        return unalignedLoad<T>(m_storage.data());
+    }
+
+    void set(const T& value)
+    {
+        unalignedStore<T>(m_storage.data(), value);
+    }
+
+    Packed<T>& operator=(const T& value)
+    {
+        set(value);
+        return *this;
+    }
+
+    template<class U>
+    T exchange(U&& newValue)
+    {
+        T oldValue = get();
+        set(std::forward<U>(newValue));
+        return oldValue;
+    }
+
+    void swap(Packed& other)
+    {
+        m_storage.swap(other.m_storage);
+    }
+
+    template<typename Other, typename = std::enable_if_t<Other::isPackedType>>
+    void swap(Other& other)
+    {
+        T t1 = get();
+        T t2 = other.get();
+        set(t2);
+        other.set(t1);
+    }
+
+    void swap(T& t2)
+    {
+        T t1 = get();
+        std::swap(t1, t2);
+        set(t1);
+    }
+
+private:
+    std::array<uint8_t, sizeof(T)> m_storage;
+};
+
+// PackedAlignedPtr can take alignment parameter too. PackedAlignedPtr only uses this alignment information if it is profitable: we use
+// alignment information only when we can reduce the size of the storage. Since the pointer width is 36 bits and JSCells are aligned to 16 bytes,
+// we can use 4 bits in Darwin ARM64, we can compact cell pointer into 4 bytes (32 bits).
+template<typename T, size_t alignment = alignof(T)>
+class PackedAlignedPtr {
+public:
+    static_assert(hasOneBitSet(alignment), "Alignment needs to be power-of-two");
+    static constexpr bool isPackedType = true;
+    static constexpr unsigned alignmentShiftSizeIfProfitable = getLSBSetConstexpr(alignment);
+    static constexpr unsigned storageSizeWithoutAlignmentShift = roundUpToMultipleOf<8>(WTF_CPU_EFFECTIVE_ADDRESS_WIDTH) / 8;
+    static constexpr unsigned storageSizeWithAlignmentShift = roundUpToMultipleOf<8>(WTF_CPU_EFFECTIVE_ADDRESS_WIDTH - alignmentShiftSizeIfProfitable) / 8;
+    static constexpr bool isAlignmentShiftProfitable = storageSizeWithoutAlignmentShift > storageSizeWithAlignmentShift;
+    static constexpr unsigned alignmentShiftSize = isAlignmentShiftProfitable ? alignmentShiftSizeIfProfitable : 0;
+    static constexpr unsigned storageSize = storageSizeWithAlignmentShift;
+
+    constexpr PackedAlignedPtr()
+        : m_storage()
+    {
+    }
+
+    constexpr PackedAlignedPtr(std::nullptr_t)
+        : m_storage()
+    {
+    }
+
+    PackedAlignedPtr(T* value)
+    {
+        set(value);
+    }
+
+    T* get() const
+    {
+        // FIXME: PackedPtr<> can load memory with one mov by checking page boundary.
+        // https://bugs.webkit.org/show_bug.cgi?id=197754
+        uintptr_t value = 0;
+#if CPU(LITTLE_ENDIAN)
+        memcpy(&value, m_storage.data(), storageSize);
+#else
+        memcpy(bitwise_cast<uint8_t*>(&value) + (sizeof(void*) - storageSize), m_storage.data(), storageSize);
+#endif
+        if (isAlignmentShiftProfitable)
+            value <<= alignmentShiftSize;
+        return bitwise_cast<T*>(value);
+    }
+
+    void set(T* passedValue)
+    {
+        uintptr_t value = bitwise_cast<uintptr_t>(passedValue);
+        if (isAlignmentShiftProfitable)
+            value >>= alignmentShiftSize;
+#if CPU(LITTLE_ENDIAN)
+        memcpy(m_storage.data(), &value, storageSize);
+#else
+        memcpy(m_storage.data(), bitwise_cast<uint8_t*>(&value) + (sizeof(void*) - storageSize));
+#endif
+    }
+
+    void clear()
+    {
+        set(nullptr);
+    }
+
+    T* operator->() const { return get(); }
+    T& operator*() const { return *get(); }
+    bool operator!() const { return !get(); }
+
+    PackedAlignedPtr& operator=(T* value)
+    {
+        set(value);
+        return *this;
+    }
+
+    template<class U>
+    T exchange(U&& newValue)
+    {
+        T oldValue = get();
+        set(std::forward<U>(newValue));
+        return oldValue;
+    }
+
+    void swap(std::nullptr_t) { clear(); }
+
+    void swap(PackedAlignedPtr& other)
+    {
+        m_storage.swap(other.m_storage);
+    }
+
+    template<typename Other, typename = std::enable_if_t<Other::isPackedType>>
+    void swap(Other& other)
+    {
+        T t1 = get();
+        T t2 = other.get();
+        set(t2);
+        other.set(t1);
+    }
+
+    void swap(T& t2)
+    {
+        T t1 = get();
+        std::swap(t1, t2);
+        set(t1);
+    }
+
+private:
+    std::array<uint8_t, storageSize> m_storage;
+};
+
+template<typename T>
+class Packed<T*> : public PackedAlignedPtr<T, 1> {
+public:
+    using Base = PackedAlignedPtr<T, 1>;
+    using Base::Base;
+};
+
+template<typename T>
+using PackedPtr = Packed<T*>;
+
+template<typename T>
+struct PackedPtrTraits {
+    template<typename U> using RebindTraits = PackedPtrTraits<U>;
+
+    using StorageType = PackedPtr<T>;
+
+    template<class U> static ALWAYS_INLINE T* exchange(StorageType& ptr, U&& newValue) { return ptr.exchange(newValue); }
+
+    template<typename Other> static ALWAYS_INLINE void swap(PackedPtr<T>& a, Other& b) { a.swap(b); }
+
+    static ALWAYS_INLINE T* unwrap(const StorageType& ptr) { return ptr.get(); }
+};
+
+} // namespace WTF
+
+using WTF::Packed;
+using WTF::PackedAlignedPtr;
+using WTF::PackedPtr;

Modified: trunk/Source/WTF/wtf/Platform.h (245213 => 245214)


--- trunk/Source/WTF/wtf/Platform.h	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/WTF/wtf/Platform.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -747,6 +747,17 @@
 #define USE_SYSTEM_MALLOC 1
 #endif
 
+#if CPU(ADDRESS64)
+#if OS(DARWIN) && CPU(ARM64)
+#define WTF_CPU_EFFECTIVE_ADDRESS_WIDTH 36
+#else
+/* We strongly assume that effective address width is <= 48 in 64bit architectures (e.g. NaN boxing). */
+#define WTF_CPU_EFFECTIVE_ADDRESS_WIDTH 48
+#endif
+#else
+#define WTF_CPU_EFFECTIVE_ADDRESS_WIDTH 32
+#endif
+
 #if !defined(USE_JSVALUE64) && !defined(USE_JSVALUE32_64)
 #if CPU(ADDRESS64) || CPU(ARM64)
 #define USE_JSVALUE64 1

Modified: trunk/Source/WTF/wtf/SentinelLinkedList.h (245213 => 245214)


--- trunk/Source/WTF/wtf/SentinelLinkedList.h	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/WTF/wtf/SentinelLinkedList.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -36,31 +36,29 @@
 
 #pragma once
 
+#include <wtf/Packed.h>
+
 namespace WTF {
 
 enum SentinelTag { Sentinel };
 
-template<typename T>
+template<typename T, typename PassedPtrTraits = DumbPtrTraits<T>>
 class BasicRawSentinelNode {
     WTF_MAKE_FAST_ALLOCATED;
 public:
+    using PtrTraits = typename PassedPtrTraits::template RebindTraits<BasicRawSentinelNode>;
+
     BasicRawSentinelNode(SentinelTag)
-        : m_next(0)
-        , m_prev(0)
     {
     }
     
-    BasicRawSentinelNode()
-        : m_next(0)
-        , m_prev(0)
-    {
-    }
+    BasicRawSentinelNode() = default;
     
     void setPrev(BasicRawSentinelNode* prev) { m_prev = prev; }
     void setNext(BasicRawSentinelNode* next) { m_next = next; }
     
-    T* prev() { return static_cast<T*>(m_prev); }
-    T* next() { return static_cast<T*>(m_next); }
+    T* prev() { return static_cast<T*>(PtrTraits::unwrap(m_prev)); }
+    T* next() { return static_cast<T*>(PtrTraits::unwrap(m_next)); }
     
     bool isOnList() const
     {
@@ -74,8 +72,8 @@
     void append(BasicRawSentinelNode*);
     
 private:
-    BasicRawSentinelNode* m_next;
-    BasicRawSentinelNode* m_prev;
+    typename PtrTraits::StorageType m_next { nullptr };
+    typename PtrTraits::StorageType m_prev { nullptr };
 };
 
 template <typename T, typename RawNode = T> class SentinelLinkedList {
@@ -118,20 +116,20 @@
     RawNode m_tailSentinel;
 };
 
-template <typename T> void BasicRawSentinelNode<T>::remove()
+template <typename T, typename PtrTraits> void BasicRawSentinelNode<T, PtrTraits>::remove()
 {
-    SentinelLinkedList<T, BasicRawSentinelNode<T>>::remove(static_cast<T*>(this));
+    SentinelLinkedList<T, BasicRawSentinelNode>::remove(static_cast<T*>(this));
 }
 
-template <typename T> void BasicRawSentinelNode<T>::prepend(BasicRawSentinelNode* node)
+template <typename T, typename PtrTraits> void BasicRawSentinelNode<T, PtrTraits>::prepend(BasicRawSentinelNode* node)
 {
-    SentinelLinkedList<T, BasicRawSentinelNode<T>>::prepend(
+    SentinelLinkedList<T, BasicRawSentinelNode>::prepend(
         static_cast<T*>(this), static_cast<T*>(node));
 }
 
-template <typename T> void BasicRawSentinelNode<T>::append(BasicRawSentinelNode* node)
+template <typename T, typename PtrTraits> void BasicRawSentinelNode<T, PtrTraits>::append(BasicRawSentinelNode* node)
 {
-    SentinelLinkedList<T, BasicRawSentinelNode<T>>::append(
+    SentinelLinkedList<T, BasicRawSentinelNode>::append(
         static_cast<T*>(this), static_cast<T*>(node));
 }
 
@@ -140,10 +138,10 @@
     , m_tailSentinel(Sentinel)
 {
     m_headSentinel.setNext(&m_tailSentinel);
-    m_headSentinel.setPrev(0);
+    m_headSentinel.setPrev(nullptr);
 
     m_tailSentinel.setPrev(&m_headSentinel);
-    m_tailSentinel.setNext(0);
+    m_tailSentinel.setNext(nullptr);
 }
 
 template <typename T, typename RawNode> inline typename SentinelLinkedList<T, RawNode>::iterator SentinelLinkedList<T, RawNode>::begin()
@@ -200,8 +198,8 @@
     prev->setNext(next);
     next->setPrev(prev);
     
-    node->setPrev(0);
-    node->setNext(0);
+    node->setPrev(nullptr);
+    node->setNext(nullptr);
 }
 
 template <typename T, typename RawNode>
@@ -271,7 +269,11 @@
     other.m_tailSentinel.setPrev(&other.m_headSentinel);
 }
 
+template<typename T>
+using PackedRawSentinelNode = BasicRawSentinelNode<T, PackedPtrTraits<T>>;
+
 }
 
 using WTF::BasicRawSentinelNode;
+using WTF::PackedRawSentinelNode;
 using WTF::SentinelLinkedList;

Modified: trunk/Source/WTF/wtf/StdLibExtras.h (245213 => 245214)


--- trunk/Source/WTF/wtf/StdLibExtras.h	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/WTF/wtf/StdLibExtras.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -172,16 +172,12 @@
 #endif
 #define WTF_ARRAY_LENGTH(array) sizeof(::WTF::ArrayLengthHelperFunction(array))
 
-ALWAYS_INLINE constexpr size_t roundUpToMultipleOfImpl0(size_t remainderMask, size_t x)
+ALWAYS_INLINE constexpr size_t roundUpToMultipleOfImpl(size_t divisor, size_t x)
 {
+    size_t remainderMask = divisor - 1;
     return (x + remainderMask) & ~remainderMask;
 }
 
-ALWAYS_INLINE constexpr size_t roundUpToMultipleOfImpl(size_t divisor, size_t x)
-{
-    return roundUpToMultipleOfImpl0(divisor - 1, x);
-}
-
 // Efficient implementation that takes advantage of powers of two.
 inline size_t roundUpToMultipleOf(size_t divisor, size_t x)
 {

Modified: trunk/Source/WTF/wtf/UnalignedAccess.h (245213 => 245214)


--- trunk/Source/WTF/wtf/UnalignedAccess.h	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Source/WTF/wtf/UnalignedAccess.h	2019-05-12 22:50:21 UTC (rev 245214)
@@ -31,20 +31,20 @@
 
 namespace WTF {
 
-template<typename IntegralType>
-inline IntegralType unalignedLoad(const void* pointer)
+template<typename Type>
+inline Type unalignedLoad(const void* pointer)
 {
-    static_assert(std::is_integral<IntegralType>::value || std::is_pointer<IntegralType>::value, "");
-    IntegralType result { };
-    memcpy(&result, pointer, sizeof(IntegralType));
+    static_assert(std::is_trivial<Type>::value, "");
+    Type result { };
+    memcpy(&result, pointer, sizeof(Type));
     return result;
 }
 
-template<typename IntegralType>
-inline void unalignedStore(void* pointer, IntegralType value)
+template<typename Type>
+inline void unalignedStore(void* pointer, Type value)
 {
-    static_assert(std::is_integral<IntegralType>::value || std::is_pointer<IntegralType>::value, "");
-    memcpy(pointer, &value, sizeof(IntegralType));
+    static_assert(std::is_trivial<Type>::value, "");
+    memcpy(pointer, &value, sizeof(Type));
 }
 
 } // namespace WTF

Modified: trunk/Tools/ChangeLog (245213 => 245214)


--- trunk/Tools/ChangeLog	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Tools/ChangeLog	2019-05-12 22:50:21 UTC (rev 245214)
@@ -1,3 +1,17 @@
+2019-05-12  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Compress Watchpoint size by using enum type and Packed<> data structure
+        https://bugs.webkit.org/show_bug.cgi?id=197730
+
+        Reviewed by Filip Pizlo.
+
+        * TestWebKitAPI/CMakeLists.txt:
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WTF/MathExtras.cpp:
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/Tests/WTF/Packed.cpp: Added.
+        (TestWebKitAPI::TEST):
+
 2019-05-10  Chris Dumez  <[email protected]>
 
         Unreviewed, fix ProcessSwap.OpenerLinkAfterAPIControlledProcessSwappingOfOpener API test

Modified: trunk/Tools/TestWebKitAPI/CMakeLists.txt (245213 => 245214)


--- trunk/Tools/TestWebKitAPI/CMakeLists.txt	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Tools/TestWebKitAPI/CMakeLists.txt	2019-05-12 22:50:21 UTC (rev 245214)
@@ -60,6 +60,7 @@
     Tests/WTF/NeverDestroyed.cpp
     Tests/WTF/OptionSet.cpp
     Tests/WTF/Optional.cpp
+    Tests/WTF/Packed.cpp
     Tests/WTF/ParkingLot.cpp
     Tests/WTF/PriorityQueue.cpp
     Tests/WTF/RedBlackTree.cpp

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (245213 => 245214)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2019-05-12 22:50:21 UTC (rev 245214)
@@ -860,6 +860,7 @@
 		E1220DCA155B28AA0013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = E1220DC9155B287D0013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.html */; };
 		E194E1BD177E53C7009C4D4E /* StopLoadingFromDidReceiveResponse.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = E194E1BC177E534A009C4D4E /* StopLoadingFromDidReceiveResponse.html */; };
 		E324A6F02041C82000A76593 /* UniqueArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E398BC0F2041C76300387136 /* UniqueArray.cpp */; };
+		E32B549222810AC4008AD702 /* Packed.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E32B549122810AC0008AD702 /* Packed.cpp */; };
 		E373D7911F2CF35200C6FAAF /* Signals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3953F951F2CF32100A76A2E /* Signals.cpp */; };
 		E38A0D351FD50CC300E98C8B /* Threading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38A0D341FD50CBC00E98C8B /* Threading.cpp */; };
 		E3A1E77F21B25B39008C6007 /* URLParserTextEncoding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3A1E77E21B25B39008C6007 /* URLParserTextEncoding.cpp */; };
@@ -2231,6 +2232,7 @@
 		E194E1BA177E5145009C4D4E /* StopLoadingFromDidReceiveResponse.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = StopLoadingFromDidReceiveResponse.mm; sourceTree = "<group>"; };
 		E194E1BC177E534A009C4D4E /* StopLoadingFromDidReceiveResponse.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = StopLoadingFromDidReceiveResponse.html; sourceTree = "<group>"; };
 		E19DB9781B32137C00DB38D4 /* NavigatorLanguage.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NavigatorLanguage.mm; sourceTree = "<group>"; };
+		E32B549122810AC0008AD702 /* Packed.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Packed.cpp; sourceTree = "<group>"; };
 		E388887020C9098100E632BC /* WorkerPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WorkerPool.cpp; sourceTree = "<group>"; };
 		E38A0D341FD50CBC00E98C8B /* Threading.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Threading.cpp; sourceTree = "<group>"; };
 		E3953F951F2CF32100A76A2E /* Signals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Signals.cpp; sourceTree = "<group>"; };
@@ -3349,6 +3351,7 @@
 				A57D54F21F338C3600A97AA7 /* NeverDestroyed.cpp */,
 				1AFDE6541953B2C000C48FFA /* Optional.cpp */,
 				CE50D8C81C8665CE0072EA5A /* OptionSet.cpp */,
+				E32B549122810AC0008AD702 /* Packed.cpp */,
 				0FE447971B76F1E3009498EB /* ParkingLot.cpp */,
 				53EC253F1E96BC80000831B9 /* PriorityQueue.cpp */,
 				0FC6C4CB141027E0005B7F0C /* RedBlackTree.cpp */,
@@ -3962,6 +3965,7 @@
 				7C83DF011D0A590C00FEBCF3 /* Optional.cpp in Sources */,
 				1A77BAA31D9AFFFC005FC568 /* OptionSet.cpp in Sources */,
 				7C83DF021D0A590C00FEBCF3 /* OSObjectPtr.cpp in Sources */,
+				E32B549222810AC4008AD702 /* Packed.cpp in Sources */,
 				7C83DF591D0A590C00FEBCF3 /* ParkingLot.cpp in Sources */,
 				53EC25411E96FD87000831B9 /* PriorityQueue.cpp in Sources */,
 				7C83DF131D0A590C00FEBCF3 /* RedBlackTree.cpp in Sources */,

Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/MathExtras.cpp (245213 => 245214)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/MathExtras.cpp	2019-05-12 19:43:16 UTC (rev 245213)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/MathExtras.cpp	2019-05-12 22:50:21 UTC (rev 245214)
@@ -507,4 +507,78 @@
     EXPECT_EQ(WTF::getMSBSet<uint64_t>(42), 5U);
 }
 
+TEST(WTF, clzConstexpr)
+{
+    EXPECT_EQ(WTF::clzConstexpr<int32_t>(1), 31U);
+    EXPECT_EQ(WTF::clzConstexpr<int32_t>(42), 26U);
+    EXPECT_EQ(WTF::clzConstexpr<uint32_t>(static_cast<uint32_t>(-1)), 0U);
+    EXPECT_EQ(WTF::clzConstexpr<uint32_t>(static_cast<uint32_t>(std::numeric_limits<int32_t>::min()) >> 1), 1U);
+    EXPECT_EQ(WTF::clzConstexpr<uint32_t>(0), 32U);
+
+    EXPECT_EQ(WTF::clzConstexpr<int8_t>(42), 2U);
+    EXPECT_EQ(WTF::clzConstexpr<int8_t>(3), 6U);
+    EXPECT_EQ(WTF::clzConstexpr<uint8_t>(static_cast<uint8_t>(-1)), 0U);
+    EXPECT_EQ(WTF::clzConstexpr<uint8_t>(0), 8U);
+
+    EXPECT_EQ(WTF::clzConstexpr<int64_t>(-1), 0U);
+    EXPECT_EQ(WTF::clzConstexpr<int64_t>(1), 63U);
+    EXPECT_EQ(WTF::clzConstexpr<int64_t>(3), 62U);
+    EXPECT_EQ(WTF::clzConstexpr<uint64_t>(42), 58U);
+    EXPECT_EQ(WTF::clzConstexpr<uint64_t>(0), 64U);
+}
+
+TEST(WTF, ctzConstexpr)
+{
+    EXPECT_EQ(WTF::ctzConstexpr<int32_t>(1), 0U);
+    EXPECT_EQ(WTF::ctzConstexpr<int32_t>(42), 1U);
+    EXPECT_EQ(WTF::ctzConstexpr<uint32_t>(static_cast<uint32_t>(-1)), 0U);
+    EXPECT_EQ(WTF::ctzConstexpr<uint32_t>(static_cast<uint32_t>(std::numeric_limits<int32_t>::min()) >> 1), 30U);
+    EXPECT_EQ(WTF::ctzConstexpr<uint32_t>(0), 32U);
+
+    EXPECT_EQ(WTF::ctzConstexpr<int8_t>(42), 1U);
+    EXPECT_EQ(WTF::ctzConstexpr<int8_t>(3), 0U);
+    EXPECT_EQ(WTF::ctzConstexpr<uint8_t>(static_cast<uint8_t>(-1)), 0U);
+    EXPECT_EQ(WTF::ctzConstexpr<uint8_t>(0), 8U);
+
+    EXPECT_EQ(WTF::ctzConstexpr<int64_t>(static_cast<uint32_t>(-1)), 0U);
+    EXPECT_EQ(WTF::ctzConstexpr<int64_t>(1), 0U);
+    EXPECT_EQ(WTF::ctzConstexpr<int64_t>(3), 0U);
+    EXPECT_EQ(WTF::ctzConstexpr<uint64_t>(42), 1U);
+    EXPECT_EQ(WTF::ctzConstexpr<uint64_t>(0), 64U);
+}
+
+TEST(WTF, getLSBSetConstexpr)
+{
+    EXPECT_EQ(WTF::getLSBSetConstexpr<int32_t>(1), 0U);
+    EXPECT_EQ(WTF::getLSBSetConstexpr<int32_t>(42), 1U);
+    EXPECT_EQ(WTF::getLSBSetConstexpr<uint32_t>(static_cast<uint32_t>(-1)), 0U);
+    EXPECT_EQ(WTF::getLSBSetConstexpr<uint32_t>(static_cast<uint32_t>(std::numeric_limits<int32_t>::min()) >> 1), 30U);
+
+    EXPECT_EQ(WTF::getLSBSetConstexpr<int8_t>(42), 1U);
+    EXPECT_EQ(WTF::getLSBSetConstexpr<int8_t>(3), 0U);
+    EXPECT_EQ(WTF::getLSBSetConstexpr<uint8_t>(static_cast<uint8_t>(-1)), 0U);
+
+    EXPECT_EQ(WTF::getLSBSetConstexpr<int64_t>(-1), 0U);
+    EXPECT_EQ(WTF::getLSBSetConstexpr<int64_t>(1), 0U);
+    EXPECT_EQ(WTF::getLSBSetConstexpr<int64_t>(3), 0U);
+    EXPECT_EQ(WTF::getLSBSetConstexpr<uint64_t>(42), 1U);
+}
+
+TEST(WTF, getMSBSetConstexpr)
+{
+    EXPECT_EQ(WTF::getMSBSetConstexpr<int32_t>(1), 0U);
+    EXPECT_EQ(WTF::getMSBSetConstexpr<int32_t>(42), 5U);
+    EXPECT_EQ(WTF::getMSBSetConstexpr<uint32_t>(static_cast<uint32_t>(-1)), 31U);
+    EXPECT_EQ(WTF::getMSBSetConstexpr<uint32_t>(static_cast<uint32_t>(std::numeric_limits<int32_t>::min()) >> 1), 30U);
+
+    EXPECT_EQ(WTF::getMSBSetConstexpr<int8_t>(42), 5U);
+    EXPECT_EQ(WTF::getMSBSetConstexpr<int8_t>(3), 1U);
+    EXPECT_EQ(WTF::getMSBSetConstexpr<uint8_t>(static_cast<uint8_t>(-1)), 7U);
+
+    EXPECT_EQ(WTF::getMSBSetConstexpr<int64_t>(-1), 63U);
+    EXPECT_EQ(WTF::getMSBSetConstexpr<int64_t>(1), 0U);
+    EXPECT_EQ(WTF::getMSBSetConstexpr<int64_t>(3), 1U);
+    EXPECT_EQ(WTF::getMSBSetConstexpr<uint64_t>(42), 5U);
+}
+
 } // namespace TestWebKitAPI

Added: trunk/Tools/TestWebKitAPI/Tests/WTF/Packed.cpp (0 => 245214)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/Packed.cpp	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/Packed.cpp	2019-05-12 22:50:21 UTC (rev 245214)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <wtf/Packed.h>
+
+namespace TestWebKitAPI {
+
+struct PackedPair {
+    PackedPtr<uint8_t> key { nullptr };
+    PackedPtr<uint8_t> value { nullptr };
+};
+
+TEST(WTF_Packed, StructSize)
+{
+    EXPECT_EQ(alignof(PackedPair), 1U);
+#if CPU(X86_64)
+    EXPECT_EQ(sizeof(PackedPair), 12U);
+#endif
+    {
+        Packed<double> value;
+        value = 4.2;
+        EXPECT_EQ(value.get(), 4.2);
+    }
+    {
+        uint64_t originalValue = 0xff00ff00dd00dd00UL;
+        Packed<uint64_t> value;
+        value = originalValue;
+        EXPECT_EQ(value.get(), originalValue);
+        EXPECT_EQ(alignof(Packed<uint64_t>), 1U);
+        EXPECT_EQ(sizeof(Packed<uint64_t>), sizeof(uint64_t));
+    }
+}
+
+TEST(WTF_Packed, AssignAndGet)
+{
+    {
+        PackedPtr<uint8_t> key { nullptr };
+        static_assert(WTF_CPU_EFFECTIVE_ADDRESS_WIDTH != 64, "");
+        uint8_t* max = bitwise_cast<uint8_t*>(static_cast<uintptr_t>(((1ULL) << WTF_CPU_EFFECTIVE_ADDRESS_WIDTH) - 1));
+        key = max;
+        EXPECT_EQ(key.get(), max);
+    }
+}
+
+TEST(WTF_Packed, PackedAlignedPtr)
+{
+    {
+        PackedAlignedPtr<uint8_t, 256> key { nullptr };
+        EXPECT_LE(sizeof(key), 5U);
+    }
+    {
+        PackedAlignedPtr<uint8_t, 16> key { nullptr };
+#if OS(DARWIN) && CPU(ARM64)
+        EXPECT_EQ(sizeof(key), 4U);
+#else
+        EXPECT_LE(sizeof(key), 6U);
+#endif
+    }
+}
+
+} // namespace TestWebKitAPI
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to