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