Title: [295008] trunk
Revision
295008
Author
yijia_hu...@apple.com
Date
2022-05-28 20:23:06 -0700 (Sat, 28 May 2022)

Log Message

Shrink Structure to 96 Bytes when addresses can be encoded in 36-bits
https://bugs.webkit.org/show_bug.cgi?id=240407

Reviewed by Yusuke Suzuki.

We have 2% RAMification regression on iOS, which needs a memory performance
improvement. To work towards resolving this regression, this patch is to
reduce JS object's structure size from 112 bytes to 96 bytes for iOS systems.

1. We can reduce 36-bit addresses into 4 bytes when dealing with pointers that
have 16-byte alignment.
2. StructureID can be removed from StructureIDBlob since we can directly compute
the id by encoding the Structure pointer.

CompactPtr and CompactRefPtr classes are introduced for pointers, which can
achieve 8 bytes in MacOS and 4 bytes in iOS.

* PerformanceTests/JetStream2/RexBench/OfflineAssembler/LowLevelInterpreter64.asm:
* PerformanceTests/JetStream2/RexBench/OfflineAssembler/LowLevelInterpreter64.js:
* PerformanceTests/JetStream2/RexBench/OfflineAssembler/expected.js:
* PerformanceTests/RexBench/OfflineAssembler/LowLevelInterpreter64.asm:
* PerformanceTests/RexBench/OfflineAssembler/LowLevelInterpreter64.js:
* PerformanceTests/RexBench/OfflineAssembler/expected.js:
* Source/_javascript_Core/CMakeLists.txt:
* Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj:
* Source/_javascript_Core/bytecode/GetByValHistory.h:
(JSC::GetByValHistory::observe):
* Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp:
* Source/_javascript_Core/ftl/FTLAbstractHeapRepository.cpp:
(JSC::FTL::AbstractHeapRepository::AbstractHeapRepository):
* Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h:
* Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
* Source/_javascript_Core/heap/ConservativeRoots.cpp:
(JSC::ConservativeRoots::genericAddPointer):
(JSC::ConservativeRoots::genericAddSpan):
* Source/_javascript_Core/heap/ConservativeRoots.h:
* Source/_javascript_Core/heap/HeapSnapshot.h:
* Source/_javascript_Core/heap/HeapUtil.h:
(JSC::HeapUtil::findGCObjectPointersForMarking):
(JSC::HeapUtil::isPointerGCObjectJSCell):
(JSC::HeapUtil::isValueGCObject):
* Source/_javascript_Core/heap/MarkedBlockSet.h:
(JSC::MarkedBlockSet::add):
(JSC::MarkedBlockSet::recomputeFilter):
(JSC::MarkedBlockSet::filter const):
* Source/_javascript_Core/heap/TinyBloomFilter.h:
(JSC::TinyBloomFilter<Bits>::TinyBloomFilter):
(JSC::TinyBloomFilter<Bits>::add):
(JSC::TinyBloomFilter<Bits>::ruleOut const):
(JSC::TinyBloomFilter<Bits>::reset):
(JSC::TinyBloomFilter::TinyBloomFilter): Deleted.
(JSC::TinyBloomFilter::add): Deleted.
(JSC::TinyBloomFilter::ruleOut const): Deleted.
(JSC::TinyBloomFilter::reset): Deleted.
* Source/_javascript_Core/jit/AssemblyHelpers.cpp:
(JSC::AssemblyHelpers::emitStoreStructureWithTypeInfo):
(JSC::AssemblyHelpers::emitEncodeStructure):
* Source/_javascript_Core/jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::emitStoreStructureWithTypeInfo):
(JSC::AssemblyHelpers::loadCompactPtr):
(JSC::AssemblyHelpers::branchCompactPtr):
* Source/_javascript_Core/jit/JITPropertyAccess.cpp:
(JSC::JIT::generateOpGetFromScopeThunk):
(JSC::JIT::emit_op_put_to_scope):
* Source/_javascript_Core/runtime/ClassInfo.h:
(JSC::ClassInfo::offsetOfParentClass): Deleted.
(JSC::ClassInfo::isSubClassOf const): Deleted.
* Source/_javascript_Core/runtime/SamplingProfiler.cpp:
(JSC::SamplingProfiler::processUnverifiedStackTraces):
* Source/_javascript_Core/runtime/Structure.cpp:
(JSC::Structure::Structure):
* Source/_javascript_Core/runtime/Structure.h:
(JSC::Structure::id const):
(JSC::Structure::typeInfoBlob const):
(JSC::Structure::classInfoForCells const):
(JSC::Structure::indexingModeIncludingHistoryOffset):
(JSC::Structure::objectInitializationBlob const): Deleted.
(JSC::Structure::idBlob const): Deleted.
(JSC::Structure::structureIDOffset): Deleted.
* Source/_javascript_Core/runtime/StructureInlines.h:
(JSC::Structure::get):
(JSC::Structure::add):
* Source/_javascript_Core/runtime/TypeInfoBlob.h: Renamed from Source/_javascript_Core/runtime/StructureIDBlob.h.
(JSC::TypeInfoBlob::TypeInfoBlob):
(JSC::TypeInfoBlob::operator=):
(JSC::TypeInfoBlob::indexingModeIncludingHistory const):
(JSC::TypeInfoBlob::fencedIndexingModeIncludingHistory):
(JSC::TypeInfoBlob::setIndexingModeIncludingHistory):
(JSC::TypeInfoBlob::type const):
(JSC::TypeInfoBlob::inlineTypeFlags const):
(JSC::TypeInfoBlob::typeInfo const):
(JSC::TypeInfoBlob::blob const):
(JSC::TypeInfoBlob::indexingModeIncludingHistoryOffset):
* Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp:
(JSC::WebAssemblyFunction::jsCallEntrypointSlow):
* Source/WTF/WTF.xcodeproj/project.pbxproj:
* Source/WTF/wtf/CMakeLists.txt:
* Source/WTF/wtf/CompactPtr.h: Added.
(WTF::CompactPtr::CompactPtr):
(WTF::CompactPtr::operator* const):
(WTF::CompactPtr::operator-> const):
(WTF::CompactPtr::operator! const):
(WTF::CompactPtr::operator bool const):
(WTF::CompactPtr::operator=):
(WTF::CompactPtr::get const):
(WTF::CompactPtr::set):
(WTF::CompactPtr::exchange):
(WTF::CompactPtr::swap):
(WTF::CompactPtr::encode):
(WTF::CompactPtr::encode const):
(WTF::CompactPtr::decode const):
(WTF::GetPtrHelper<CompactPtr<T>>::getPtr):
(WTF::CompactPtrTraits::exchange):
(WTF::CompactPtrTraits::swap):
(WTF::CompactPtrTraits::unwrap):
(WTF::CompactPtrTraits::hashTableDeletedValue):
(WTF::CompactPtrTraits::isHashTableDeletedValue):
* Source/WTF/wtf/CompactRefPtr.h: Copied from Source/_javascript_Core/heap/HeapSnapshot.h.
* Source/WTF/wtf/text/StringImpl.cpp:
* Source/WTF/wtf/text/StringImpl.h:
* Tools/TestWebKitAPI/CMakeLists.txt:
* Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* Tools/TestWebKitAPI/Tests/WTF/AlignedRefLogger.h: Copied from Source/_javascript_Core/heap/TinyBloomFilter.h.
(TestWebKitAPI::DerivedAlignedRefLogger::DerivedAlignedRefLogger):
* Tools/TestWebKitAPI/Tests/WTF/CompactPtr.cpp: Added.
(TestWebKitAPI::TEST):
* Tools/TestWebKitAPI/Tests/WTF/CompactRefPtr.cpp: Added.
(TestWebKitAPI::TEST):
(TestWebKitAPI::f1):
(TestWebKitAPI::returnConstRefCountedRef):
(TestWebKitAPI::returnRefCountedRef):
(TestWebKitAPI::CompactRefPtrCheckingAlignedRefLogger::CompactRefPtrCheckingAlignedRefLogger):
(TestWebKitAPI::loggerName):
(TestWebKitAPI::CompactRefPtrCheckingAlignedRefLogger::ref):
(TestWebKitAPI::CompactRefPtrCheckingAlignedRefLogger::deref):
* Tools/TestWebKitAPI/Tests/WTF/JSONValue.cpp:
(TestWebKitAPI::TEST):
* Websites/browserbench.org/JetStream2.0/RexBench/OfflineAssembler/LowLevelInterpreter64.asm:
* Websites/browserbench.org/JetStream2.0/RexBench/OfflineAssembler/LowLevelInterpreter64.js:
* Websites/browserbench.org/JetStream2.0/RexBench/OfflineAssembler/expected.js:

Canonical link: https://commits.webkit.org/251103@main

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (295007 => 295008)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2022-05-29 03:23:06 UTC (rev 295008)
@@ -1176,7 +1176,6 @@
     runtime/StructureCache.h
     runtime/StructureChain.h
     runtime/StructureID.h
-    runtime/StructureIDBlob.h
     runtime/StructureInlines.h
     runtime/StructureRareData.h
     runtime/StructureRareDataInlines.h
@@ -1193,6 +1192,7 @@
     runtime/ThrowScope.h
     runtime/ToNativeFromValue.h
     runtime/TypeError.h
+    runtime/TypeInfoBlob.h
     runtime/TypeSet.h
     runtime/TypedArrayAdaptersForwardDeclarations.h
     runtime/TypedArrayAdaptors.h

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (295007 => 295008)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2022-05-29 03:23:06 UTC (rev 295008)
@@ -838,7 +838,7 @@
 		2A4BB7F318A41179008A0FCD /* JSManagedValueInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A4BB7F218A41179008A0FCD /* JSManagedValueInternal.h */; };
 		2A83638618D7D0EE0000EBCC /* EdenGCActivityCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A83638418D7D0EE0000EBCC /* EdenGCActivityCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2A83638A18D7D0FE0000EBCC /* FullGCActivityCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A83638818D7D0FE0000EBCC /* FullGCActivityCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
-		2AAAA31218BD49D100394CC8 /* StructureIDBlob.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AAAA31018BD49D100394CC8 /* StructureIDBlob.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		2AAAA31218BD49D100394CC8 /* TypeInfoBlob.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AAAA31018BD49D100394CC8 /* TypeInfoBlob.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2AABCDE718EF294200002096 /* GCLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AABCDE618EF294200002096 /* GCLogging.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2AACE63D18CA5A0300ED0191 /* GCActivityCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AACE63B18CA5A0300ED0191 /* GCActivityCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2AD2EDFB19799E38004D6478 /* EnumerationMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AD2EDFA19799E38004D6478 /* EnumerationMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -3743,7 +3743,7 @@
 		2A83638418D7D0EE0000EBCC /* EdenGCActivityCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EdenGCActivityCallback.h; sourceTree = "<group>"; };
 		2A83638718D7D0FE0000EBCC /* FullGCActivityCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FullGCActivityCallback.cpp; sourceTree = "<group>"; };
 		2A83638818D7D0FE0000EBCC /* FullGCActivityCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FullGCActivityCallback.h; sourceTree = "<group>"; };
-		2AAAA31018BD49D100394CC8 /* StructureIDBlob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureIDBlob.h; sourceTree = "<group>"; };
+		2AAAA31018BD49D100394CC8 /* TypeInfoBlob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeInfoBlob.h; sourceTree = "<group>"; };
 		2AABCDE618EF294200002096 /* GCLogging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCLogging.h; sourceTree = "<group>"; };
 		2AACE63A18CA5A0300ED0191 /* GCActivityCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCActivityCallback.cpp; sourceTree = "<group>"; };
 		2AACE63B18CA5A0300ED0191 /* GCActivityCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCActivityCallback.h; sourceTree = "<group>"; };
@@ -8260,7 +8260,7 @@
 				7E4EE70E0EBB7A5B005934AA /* StructureChain.cpp */,
 				7E4EE7080EBB7963005934AA /* StructureChain.h */,
 				537FEEC82742BDA300C9EFEE /* StructureID.h */,
-				2AAAA31018BD49D100394CC8 /* StructureIDBlob.h */,
+				2AAAA31018BD49D100394CC8 /* TypeInfoBlob.h */,
 				0FD2C92316D01EE900C7803F /* StructureInlines.h */,
 				C2F0F2D016BAEEE900187C19 /* StructureRareData.cpp */,
 				C2FE18A316BAEC4000AF3061 /* StructureRareData.h */,
@@ -11100,7 +11100,7 @@
 				7986943B1F8C0ACC009232AE /* StructureCache.h in Headers */,
 				7E4EE7090EBB7963005934AA /* StructureChain.h in Headers */,
 				537FEEC92742BDA300C9EFEE /* StructureID.h in Headers */,
-				2AAAA31218BD49D100394CC8 /* StructureIDBlob.h in Headers */,
+				2AAAA31218BD49D100394CC8 /* TypeInfoBlob.h in Headers */,
 				0FD2C92416D01EE900C7803F /* StructureInlines.h in Headers */,
 				C2FE18A416BAEC4000AF3061 /* StructureRareData.h in Headers */,
 				C20BA92D16BB1C1500B3AEA2 /* StructureRareDataInlines.h in Headers */,

Modified: trunk/Source/_javascript_Core/bytecode/GetByValHistory.h (295007 => 295008)


--- trunk/Source/_javascript_Core/bytecode/GetByValHistory.h	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/bytecode/GetByValHistory.h	2022-05-29 03:23:06 UTC (rev 295008)
@@ -47,7 +47,7 @@
         uintptr_t count = this->count();
         uintptr_t filter = this->filter();
 
-        TinyBloomFilter bloomFilter(filter);
+        TinyBloomFilter<uintptr_t> bloomFilter(filter);
         uintptr_t implBits = bitwise_cast<uintptr_t>(impl);
         ASSERT(((static_cast<uint64_t>(implBits) << 8) >> 8) == static_cast<uint64_t>(implBits));
         if (bloomFilter.ruleOut(implBits)) {

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (295007 => 295008)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2022-05-29 03:23:06 UTC (rev 295008)
@@ -11106,7 +11106,7 @@
         GPRReg specifiedGPR = specified.gpr();
 
         m_jit.emitLoadStructure(vm(), baseGPR, otherGPR);
-        m_jit.loadPtr(CCallHelpers::Address(otherGPR, Structure::classInfoOffset()), otherGPR);
+        m_jit.loadCompactPtr(CCallHelpers::Address(otherGPR, Structure::classInfoOffset()), otherGPR);
         m_jit.move(TrustedImmPtr(node->classInfo()), specifiedGPR);
 
         CCallHelpers::Label loop = m_jit.label();
@@ -11317,7 +11317,7 @@
     speculateFunction(node->child1(), function.gpr());
 
     m_jit.emitLoadStructure(vm(), function.gpr(), result.gpr());
-    m_jit.loadPtr(JITCompiler::Address(result.gpr(), Structure::classInfoOffset()), result.gpr());
+    m_jit.loadCompactPtr(JITCompiler::Address(result.gpr(), Structure::classInfoOffset()), result.gpr());
     static_assert(std::is_final_v<JSBoundFunction>, "We don't handle subclasses when comparing classInfo below");
     slowCases.append(m_jit.branchPtr(CCallHelpers::Equal, result.gpr(), TrustedImmPtr(JSBoundFunction::info())));
 
@@ -14886,7 +14886,7 @@
     slowCases.append(m_jit.branchTest32(CCallHelpers::Zero, structureGPR));
     m_jit.emitNonNullDecodeZeroExtendedStructureID(structureGPR, structureGPR);
     m_jit.move(TrustedImmPtr(node->isInternalPromise() ? JSInternalPromise::info() : JSPromise::info()), scratch1GPR);
-    slowCases.append(m_jit.branchPtr(CCallHelpers::NotEqual, scratch1GPR, CCallHelpers::Address(structureGPR, Structure::classInfoOffset())));
+    slowCases.append(m_jit.branchCompactPtr(CCallHelpers::NotEqual, scratch1GPR, CCallHelpers::Address(structureGPR, Structure::classInfoOffset()), scratch2GPR));
     m_jit.loadLinkableConstant(JITCompiler::LinkableConstant(m_jit, globalObject), scratch1GPR);
     slowCases.append(m_jit.branchPtr(CCallHelpers::NotEqual, scratch1GPR, CCallHelpers::Address(structureGPR, Structure::globalObjectOffset())));
 
@@ -14935,7 +14935,7 @@
     slowCases.append(m_jit.branchTest32(CCallHelpers::Zero, structureGPR));
     m_jit.emitNonNullDecodeZeroExtendedStructureID(structureGPR, structureGPR);
     m_jit.move(TrustedImmPtr(JSClass::info()), scratch1GPR);
-    slowCases.append(m_jit.branchPtr(CCallHelpers::NotEqual, scratch1GPR, CCallHelpers::Address(structureGPR, Structure::classInfoOffset())));
+    slowCases.append(m_jit.branchCompactPtr(CCallHelpers::NotEqual, scratch1GPR, CCallHelpers::Address(structureGPR, Structure::classInfoOffset()), scratch2GPR));
     m_jit.loadLinkableConstant(JITCompiler::LinkableConstant(m_jit, globalObject), scratch1GPR);
     slowCases.append(m_jit.branchPtr(CCallHelpers::NotEqual, scratch1GPR, CCallHelpers::Address(structureGPR, Structure::globalObjectOffset())));
 

Modified: trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.cpp (295007 => 295008)


--- trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.cpp	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.cpp	2022-05-29 03:23:06 UTC (rev 295008)
@@ -76,7 +76,7 @@
     JSCell_header.changeParent(&JSCellHeaderAndNamedProperties);
     properties.atAnyNumber().changeParent(&JSCellHeaderAndNamedProperties);
 
-    // Make sure that our explicit assumptions about the StructureIDBlob match reality.
+    // Make sure that our explicit assumptions about the TypeInfoBlob match reality.
     RELEASE_ASSERT(!(JSCell_indexingTypeAndMisc.offset() & (sizeof(int32_t) - 1)));
     RELEASE_ASSERT(JSCell_indexingTypeAndMisc.offset() + 1 == JSCell_typeInfoType.offset());
     RELEASE_ASSERT(JSCell_indexingTypeAndMisc.offset() + 2 == JSCell_typeInfoFlags.offset());

Modified: trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h (295007 => 295008)


--- trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h	2022-05-29 03:23:06 UTC (rev 295008)
@@ -147,7 +147,6 @@
     macro(Structure_outOfLineTypeFlags, Structure::outOfLineTypeFlagsOffset()) \
     macro(Structure_previousOrRareData, Structure::previousOrRareDataOffset()) \
     macro(Structure_prototype, Structure::prototypeOffset()) \
-    macro(Structure_structureID, Structure::structureIDOffset()) \
     macro(StructureRareData_cachedKeys, StructureRareData::offsetOfCachedPropertyNames(CachedPropertyNamesKind::Keys)) \
     macro(StructureRareData_cachedGetOwnPropertyNames, StructureRareData::offsetOfCachedPropertyNames(CachedPropertyNamesKind::GetOwnPropertyNames)) \
     macro(StructureRareData_cachedPropertyNameEnumeratorAndFlag, StructureRareData::offsetOfCachedPropertyNameEnumeratorAndFlag()) \

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (295007 => 295008)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2022-05-29 03:23:06 UTC (rev 295008)
@@ -16839,10 +16839,21 @@
     {
         m_out.store32(m_out.constInt32(structure->id().bits()), object, m_heaps.JSCell_structureID);
         m_out.store32(
-            m_out.constInt32(structure->objectInitializationBlob()),
+            m_out.constInt32(structure->typeInfoBlob()),
             object, m_heaps.JSCell_usefulBytes);
     }
 
+    LValue encodeStructureID(LValue structure)
+    {
+#if ENABLE(STRUCTURE_ID_WITH_SHIFT)
+        return m_out.castToInt32(m_out.lShr(structure, m_out.constInt32(StructureID::encodeShiftAmount)));
+#elif CPU(ADDRESS64)
+        return m_out.castToInt32(m_out.bitAnd(structure, m_out.constInt64(StructureID::structureIDMask)));
+#else
+        return m_out.castToInt32(structure);
+#endif
+    }
+
     void storeStructure(LValue object, LValue structure)
     {
         if (structure->hasIntPtr()) {
@@ -16850,7 +16861,7 @@
             return;
         }
 
-        LValue id = m_out.load32(structure, m_heaps.Structure_structureID);
+        LValue id = encodeStructureID(structure);
         m_out.store32(id, object, m_heaps.JSCell_structureID);
 
         LValue blob = m_out.load32(structure, m_heaps.Structure_indexingModeIncludingHistory);

Modified: trunk/Source/_javascript_Core/heap/ConservativeRoots.cpp (295007 => 295008)


--- trunk/Source/_javascript_Core/heap/ConservativeRoots.cpp	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/heap/ConservativeRoots.cpp	2022-05-29 03:23:06 UTC (rev 295008)
@@ -63,7 +63,7 @@
 }
 
 template<typename MarkHook>
-inline void ConservativeRoots::genericAddPointer(void* p, HeapVersion markingVersion, HeapVersion newlyAllocatedVersion, TinyBloomFilter filter, MarkHook& markHook)
+inline void ConservativeRoots::genericAddPointer(void* p, HeapVersion markingVersion, HeapVersion newlyAllocatedVersion, TinyBloomFilter<uintptr_t> filter, MarkHook& markHook)
 {
     p = removeArrayPtrTag(p);
     markHook.mark(p);
@@ -94,7 +94,7 @@
     RELEASE_ASSERT(isPointerAligned(begin));
     RELEASE_ASSERT(isPointerAligned(end));
 
-    TinyBloomFilter filter = m_heap.objectSpace().blocks().filter(); // Make a local copy of filter to show the compiler it won't alias, and can be register-allocated.
+    TinyBloomFilter<uintptr_t> filter = m_heap.objectSpace().blocks().filter(); // Make a local copy of filter to show the compiler it won't alias, and can be register-allocated.
     HeapVersion markingVersion = m_heap.objectSpace().markingVersion();
     HeapVersion newlyAllocatedVersion = m_heap.objectSpace().newlyAllocatedVersion();
     for (char** it = static_cast<char**>(begin); it != static_cast<char**>(end); ++it)

Modified: trunk/Source/_javascript_Core/heap/ConservativeRoots.h (295007 => 295008)


--- trunk/Source/_javascript_Core/heap/ConservativeRoots.h	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/heap/ConservativeRoots.h	2022-05-29 03:23:06 UTC (rev 295008)
@@ -48,7 +48,7 @@
     static constexpr size_t inlineCapacity = 2048;
     
     template<typename MarkHook>
-    void genericAddPointer(void*, HeapVersion markingVersion, HeapVersion newlyAllocatedVersion, TinyBloomFilter, MarkHook&);
+    void genericAddPointer(void*, HeapVersion markingVersion, HeapVersion newlyAllocatedVersion, TinyBloomFilter<uintptr_t>, MarkHook&);
 
     template<typename MarkHook>
     void genericAddSpan(void*, void* end, MarkHook&);

Modified: trunk/Source/_javascript_Core/heap/HeapSnapshot.h (295007 => 295008)


--- trunk/Source/_javascript_Core/heap/HeapSnapshot.h	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/heap/HeapSnapshot.h	2022-05-29 03:23:06 UTC (rev 295008)
@@ -52,7 +52,7 @@
     static constexpr intptr_t CellToSweepTag = 1;
 
     Vector<HeapSnapshotNode> m_nodes;
-    TinyBloomFilter m_filter;
+    TinyBloomFilter<uintptr_t> m_filter;
     HeapSnapshot* m_previous { nullptr };
     unsigned m_firstObjectIdentifier { 0 };
     unsigned m_lastObjectIdentifier { 0 };

Modified: trunk/Source/_javascript_Core/heap/HeapUtil.h (295007 => 295008)


--- trunk/Source/_javascript_Core/heap/HeapUtil.h	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/heap/HeapUtil.h	2022-05-29 03:23:06 UTC (rev 295008)
@@ -46,7 +46,7 @@
     // before liveness data is cleared to be accurate.
     template<typename Func>
     static void findGCObjectPointersForMarking(
-        Heap& heap, HeapVersion markingVersion, HeapVersion newlyAllocatedVersion, TinyBloomFilter filter,
+        Heap& heap, HeapVersion markingVersion, HeapVersion newlyAllocatedVersion, TinyBloomFilter<uintptr_t> filter,
         void* passedPointer, const Func& func)
     {
         const HashSet<MarkedBlock*>& set = heap.objectSpace().blocks().set();
@@ -86,7 +86,7 @@
             // We may be interested in the last cell of the previous MarkedBlock.
             char* previousPointer = bitwise_cast<char*>(bitwise_cast<uintptr_t>(pointer) - sizeof(IndexingHeader) - 1);
             MarkedBlock* previousCandidate = MarkedBlock::blockFor(previousPointer);
-            if (!filter.ruleOut(bitwise_cast<Bits>(previousCandidate))
+            if (!filter.ruleOut(bitwise_cast<uintptr_t>(previousCandidate))
                 && set.contains(previousCandidate)
                 && mayHaveIndexingHeader(previousCandidate->handle().cellKind())) {
                 previousPointer = static_cast<char*>(previousCandidate->handle().cellAlign(previousPointer));
@@ -95,7 +95,7 @@
             }
         }
     
-        if (filter.ruleOut(bitwise_cast<Bits>(candidate))) {
+        if (filter.ruleOut(bitwise_cast<uintptr_t>(candidate))) {
             ASSERT(!candidate || !set.contains(candidate));
             return;
         }
@@ -134,7 +134,7 @@
             tryPointer(alignedPointer - candidate->cellSize());
     }
     
-    static bool isPointerGCObjectJSCell(Heap& heap, TinyBloomFilter filter, JSCell* pointer)
+    static bool isPointerGCObjectJSCell(Heap& heap, TinyBloomFilter<uintptr_t> filter, JSCell* pointer)
     {
         // It could point to a large allocation.
         if (pointer->isPreciseAllocation()) {
@@ -148,7 +148,7 @@
         const HashSet<MarkedBlock*>& set = heap.objectSpace().blocks().set();
         
         MarkedBlock* candidate = MarkedBlock::blockFor(pointer);
-        if (filter.ruleOut(bitwise_cast<Bits>(candidate))) {
+        if (filter.ruleOut(bitwise_cast<uintptr_t>(candidate))) {
             ASSERT(!candidate || !set.contains(candidate));
             return false;
         }
@@ -170,7 +170,7 @@
     
     // This does not find the cell if the pointer is pointing at the middle of a JSCell.
     static bool isValueGCObject(
-        Heap& heap, TinyBloomFilter filter, JSValue value)
+        Heap& heap, TinyBloomFilter<uintptr_t> filter, JSValue value)
     {
         ASSERT(heap.objectSpace().preciseAllocationSet());
         if (!value.isCell())

Modified: trunk/Source/_javascript_Core/heap/MarkedBlockSet.h (295007 => 295008)


--- trunk/Source/_javascript_Core/heap/MarkedBlockSet.h	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/heap/MarkedBlockSet.h	2022-05-29 03:23:06 UTC (rev 295008)
@@ -38,19 +38,19 @@
     void add(MarkedBlock*);
     void remove(MarkedBlock*);
 
-    TinyBloomFilter filter() const;
+    TinyBloomFilter<uintptr_t> filter() const;
     const HashSet<MarkedBlock*>& set() const;
 
 private:
     void recomputeFilter();
 
-    TinyBloomFilter m_filter;
+    TinyBloomFilter<uintptr_t> m_filter;
     HashSet<MarkedBlock*> m_set;
 };
 
 inline void MarkedBlockSet::add(MarkedBlock* block)
 {
-    m_filter.add(reinterpret_cast<Bits>(block));
+    m_filter.add(reinterpret_cast<uintptr_t>(block));
     m_set.add(block);
 }
 
@@ -64,13 +64,13 @@
 
 inline void MarkedBlockSet::recomputeFilter()
 {
-    TinyBloomFilter filter;
+    TinyBloomFilter<uintptr_t> filter;
     for (HashSet<MarkedBlock*>::iterator it = m_set.begin(); it != m_set.end(); ++it)
-        filter.add(reinterpret_cast<Bits>(*it));
+        filter.add(reinterpret_cast<uintptr_t>(*it));
     m_filter = filter;
 }
 
-inline TinyBloomFilter MarkedBlockSet::filter() const
+inline TinyBloomFilter<uintptr_t> MarkedBlockSet::filter() const
 {
     return m_filter;
 }

Modified: trunk/Source/_javascript_Core/heap/TinyBloomFilter.h (295007 => 295008)


--- trunk/Source/_javascript_Core/heap/TinyBloomFilter.h	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/heap/TinyBloomFilter.h	2022-05-29 03:23:06 UTC (rev 295008)
@@ -27,8 +27,7 @@
 
 namespace JSC {
 
-typedef uintptr_t Bits;
-
+template <typename Bits = uintptr_t>
 class TinyBloomFilter {
 public:
     TinyBloomFilter() = default;
@@ -44,22 +43,26 @@
     Bits m_bits { 0 };
 };
 
-inline TinyBloomFilter::TinyBloomFilter(Bits bits)
+template <typename Bits>
+inline TinyBloomFilter<Bits>::TinyBloomFilter(Bits bits)
     : m_bits(bits)
 {
 }
 
-inline void TinyBloomFilter::add(Bits bits)
+template <typename Bits>
+inline void TinyBloomFilter<Bits>::add(Bits bits)
 {
     m_bits |= bits;
 }
 
-inline void TinyBloomFilter::add(TinyBloomFilter& other)
+template <typename Bits>
+inline void TinyBloomFilter<Bits>::add(TinyBloomFilter& other)
 {
     m_bits |= other.m_bits;
 }
 
-inline bool TinyBloomFilter::ruleOut(Bits bits) const
+template <typename Bits>
+inline bool TinyBloomFilter<Bits>::ruleOut(Bits bits) const
 {
     if (!bits)
         return true;
@@ -70,7 +73,8 @@
     return false;
 }
 
-inline void TinyBloomFilter::reset()
+template <typename Bits>
+inline void TinyBloomFilter<Bits>::reset()
 {
     m_bits = 0;
 }

Modified: trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp (295007 => 295008)


--- trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp	2022-05-29 03:23:06 UTC (rev 295008)
@@ -332,7 +332,8 @@
 {
     const Structure* structurePtr = reinterpret_cast<const Structure*>(structure.m_value);
 #if USE(JSVALUE64)
-    jit.store64(TrustedImm64(structurePtr->idBlob()), MacroAssembler::Address(dest, JSCell::structureIDOffset()));
+    jit.store32(TrustedImm32(structurePtr->id().bits()), MacroAssembler::Address(dest, JSCell::structureIDOffset()));
+    jit.store32(TrustedImm32(structurePtr->typeInfoBlob()), MacroAssembler::Address(dest, JSCell::indexingTypeAndMiscOffset()));
     if (ASSERT_ENABLED) {
         Jump correctStructure = jit.branch32(Equal, MacroAssembler::Address(dest, JSCell::structureIDOffset()), TrustedImm32(structurePtr->id().bits()));
         jit.abortWithReason(AHStructureIDIsValid);
@@ -352,7 +353,7 @@
     }
 #else
     // Do a 32-bit wide store to initialize the cell's fields.
-    jit.store32(TrustedImm32(structurePtr->objectInitializationBlob()), MacroAssembler::Address(dest, JSCell::indexingTypeAndMiscOffset()));
+    jit.store32(TrustedImm32(structurePtr->typeInfoBlob()), MacroAssembler::Address(dest, JSCell::indexingTypeAndMiscOffset()));
     jit.storePtr(structure, MacroAssembler::Address(dest, JSCell::structureIDOffset()));
 #endif
 }
@@ -428,6 +429,19 @@
     emitNonNullDecodeZeroExtendedStructureID(dest, dest);
 }
 
+void AssemblyHelpers::emitEncodeStructureID(RegisterID source, RegisterID dest)
+{
+#if ENABLE(STRUCTURE_ID_WITH_SHIFT)
+    urshift64(source, TrustedImm32(StructureID::encodeShiftAmount), dest);
+#elif CPU(ADDRESS64)
+    move(source, dest);
+    static_assert(StructureID::structureIDMask <= UINT32_MAX);
+    and64(TrustedImm32(static_cast<uint32_t>(StructureID::structureIDMask)), dest);
+#else
+    move(source, dest);
+#endif
+}
+
 void AssemblyHelpers::emitLoadPrototype(VM& vm, GPRReg objectGPR, JSValueRegs resultRegs, JumpList& slowPath)
 {
     ASSERT(resultRegs.payloadGPR() != objectGPR);

Modified: trunk/Source/_javascript_Core/jit/AssemblyHelpers.h (295007 => 295008)


--- trunk/Source/_javascript_Core/jit/AssemblyHelpers.h	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/jit/AssemblyHelpers.h	2022-05-29 03:23:06 UTC (rev 295008)
@@ -1613,6 +1613,7 @@
     void emitNonNullDecodeZeroExtendedStructureID(RegisterID source, RegisterID dest);
     void emitLoadStructure(VM&, RegisterID source, RegisterID dest);
     void emitLoadPrototype(VM&, GPRReg objectGPR, JSValueRegs resultRegs, JumpList& slowPath);
+    void emitEncodeStructureID(RegisterID source, RegisterID dest);
 
     void emitStoreStructureWithTypeInfo(TrustedImmPtr structure, RegisterID dest, RegisterID)
     {
@@ -1621,17 +1622,16 @@
 
     void emitStoreStructureWithTypeInfo(RegisterID structure, RegisterID dest, RegisterID scratch)
     {
+        // Store the StructureID
 #if USE(JSVALUE64)
-        load64(MacroAssembler::Address(structure, Structure::structureIDOffset()), scratch);
-        store64(scratch, MacroAssembler::Address(dest, JSCell::structureIDOffset()));
+        emitEncodeStructureID(structure, scratch);
+        store32(scratch, MacroAssembler::Address(dest, JSCell::structureIDOffset()));
 #else
+        storePtr(structure, MacroAssembler::Address(dest, JSCell::structureIDOffset()));
+#endif
         // Store all the info flags using a single 32-bit wide load and store.
         load32(MacroAssembler::Address(structure, Structure::indexingModeIncludingHistoryOffset()), scratch);
         store32(scratch, MacroAssembler::Address(dest, JSCell::indexingTypeAndMiscOffset()));
-
-        // Store the StructureID
-        storePtr(structure, MacroAssembler::Address(dest, JSCell::structureIDOffset()));
-#endif
     }
 
     static void emitStoreStructureWithTypeInfo(AssemblyHelpers& jit, TrustedImmPtr structure, RegisterID dest);
@@ -1914,7 +1914,30 @@
         for (unsigned i = 0; i < outOfLineCapacity; ++i)
             storeTrustedValue(JSValue(), Address(butterflyGPR, -sizeof(IndexingHeader) - (i + 1) * sizeof(EncodedJSValue)));
     }
-    
+
+    void loadCompactPtr(Address address, GPRReg dest)
+    {
+#if HAVE(36BIT_ADDRESS)
+        load32(address, dest);
+        lshift64(TrustedImm32(4), dest);
+#else
+        loadPtr(address, dest);
+#endif
+    }
+
+    Jump branchCompactPtr(RelationalCondition cond, GPRReg left, Address right, GPRReg scratch)
+    {
+#if HAVE(36BIT_ADDRESS)
+        ASSERT(left != scratch);
+        load32(right, scratch);
+        lshift64(TrustedImm32(4), scratch);
+        return branchPtr(cond, left, Address(scratch));
+#else
+        UNUSED_PARAM(scratch);
+        return branchPtr(cond, left, right);
+#endif
+    }
+
 #if USE(JSVALUE64)
     void wangsInt64Hash(GPRReg inputAndResult, GPRReg scratch);
 #endif

Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp (295007 => 295008)


--- trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2022-05-29 03:23:06 UTC (rev 295008)
@@ -1740,7 +1740,7 @@
             // Structure check covers var injection since we don't cache structures for anything but the GlobalObject. Additionally, resolve_scope handles checking for the var injection.
             jit.loadPtr(Address(metadataGPR, OpGetFromScope::Metadata::offsetOfStructure()), scratchGPR);
             slowCase.append(jit.branchTestPtr(Zero, scratchGPR));
-            jit.load32(Address(scratchGPR, Structure::structureIDOffset()), scratchGPR);
+            jit.emitEncodeStructureID(scratchGPR, scratchGPR);
             slowCase.append(jit.branch32(NotEqual, Address(scopeGPR, JSCell::structureIDOffset()), scratchGPR));
 
             jit.jitAssert(scopedLambda<Jump(void)>([&] () -> Jump {
@@ -1913,7 +1913,7 @@
             loadPtrFromMetadata(bytecode, OpPutToScope::Metadata::offsetOfStructure(), scratchGPR1);
             emitGetVirtualRegisterPayload(scope, scopeGPR);
             addSlowCase(branchTestPtr(Zero, scratchGPR1));
-            load32(Address(scratchGPR1, Structure::structureIDOffset()), scratchGPR1);
+            emitEncodeStructureID(scratchGPR1, scratchGPR1);
             addSlowCase(branch32(NotEqual, Address(scopeGPR, JSCell::structureIDOffset()), scratchGPR1));
 
             emitGetVirtualRegister(value, valueJSR);

Modified: trunk/Source/_javascript_Core/runtime/ClassInfo.h (295007 => 295008)


--- trunk/Source/_javascript_Core/runtime/ClassInfo.h	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/runtime/ClassInfo.h	2022-05-29 03:23:06 UTC (rev 295008)
@@ -24,8 +24,15 @@
 
 #include "ConstructData.h"
 #include "JSCast.h"
+#include <wtf/CompactPtr.h>
 #include <wtf/PtrTag.h>
 
+#if HAVE(36BIT_ADDRESS)
+#define CLASS_INFO_ALIGNMENT alignas(16)
+#else
+#define CLASS_INFO_ALIGNMENT
+#endif
+
 namespace WTF {
 class PrintStream;
 };
@@ -172,7 +179,7 @@
     ClassName::TypedArrayStorageType, \
     sizeof(ClassName),
 
-struct ClassInfo {
+struct CLASS_INFO_ALIGNMENT ClassInfo {
     using CheckJSCastSnippetFunctionPtr = Ref<Snippet> (*)(void);
 
     // A string denoting the class name. Example: "Window".

Modified: trunk/Source/_javascript_Core/runtime/SamplingProfiler.cpp (295007 => 295008)


--- trunk/Source/_javascript_Core/runtime/SamplingProfiler.cpp	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/runtime/SamplingProfiler.cpp	2022-05-29 03:23:06 UTC (rev 295008)
@@ -468,7 +468,7 @@
     // This function needs to be called from the JSC execution thread.
     RELEASE_ASSERT(m_lock.isLocked());
 
-    TinyBloomFilter filter = m_vm.heap.objectSpace().blocks().filter();
+    TinyBloomFilter<uintptr_t> filter = m_vm.heap.objectSpace().blocks().filter();
 
     for (UnprocessedStackTrace& unprocessedStackTrace : m_unprocessedStackTraces) {
         m_stackTraces.append(StackTrace());

Modified: trunk/Source/_javascript_Core/runtime/Structure.cpp (295007 => 295008)


--- trunk/Source/_javascript_Core/runtime/Structure.cpp	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/runtime/Structure.cpp	2022-05-29 03:23:06 UTC (rev 295008)
@@ -197,15 +197,15 @@
 
 Structure::Structure(VM& vm, JSGlobalObject* globalObject, JSValue prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo, IndexingType indexingType, unsigned inlineCapacity)
     : JSCell(vm, vm.structureStructure.get())
-    , m_blob(StructureID::encode(this), indexingType, typeInfo)
+    , m_blob(indexingType, typeInfo)
     , m_outOfLineTypeFlags(typeInfo.outOfLineTypeFlags())
     , m_inlineCapacity(inlineCapacity)
     , m_bitField(0)
+    , m_propertyHash(0)
     , m_globalObject(vm, this, globalObject, WriteBarrier<JSGlobalObject>::MayBeNull)
     , m_prototype(vm, this, prototype)
     , m_classInfo(classInfo)
     , m_transitionWatchpointSet(IsWatched)
-    , m_propertyHash(0)
 {
     setDictionaryKind(NoneDictionaryKind);
     setIsPinnedPropertyTable(false);
@@ -244,10 +244,10 @@
     : JSCell(CreatingEarlyCell)
     , m_inlineCapacity(0)
     , m_bitField(0)
+    , m_propertyHash(0)
     , m_prototype(vm, this, jsNull())
     , m_classInfo(info())
     , m_transitionWatchpointSet(IsWatched)
-    , m_propertyHash(0)
 {
     setDictionaryKind(NoneDictionaryKind);
     setIsPinnedPropertyTable(false);
@@ -268,7 +268,7 @@
     setMaxOffset(vm, invalidOffset);
  
     TypeInfo typeInfo = TypeInfo(StructureType, StructureFlags);
-    m_blob = StructureIDBlob(StructureID::encode(this), 0, typeInfo);
+    m_blob = TypeInfoBlob(0, typeInfo);
     m_outOfLineTypeFlags = typeInfo.outOfLineTypeFlags();
 
     ASSERT(hasReadOnlyOrGetterSetterPropertiesExcludingProto() || !m_classInfo->hasStaticSetterOrReadonlyProperties());
@@ -284,11 +284,11 @@
     : JSCell(vm, vm.structureStructure.get())
     , m_inlineCapacity(previous->m_inlineCapacity)
     , m_bitField(0)
+    , m_propertyHash(previous->m_propertyHash)
+    , m_seenProperties(previous->m_seenProperties)
     , m_prototype(vm, this, previous->m_prototype.get())
     , m_classInfo(previous->m_classInfo)
     , m_transitionWatchpointSet(IsWatched)
-    , m_propertyHash(previous->m_propertyHash)
-    , m_seenProperties(previous->m_seenProperties)
 {
     setDictionaryKind(previous->dictionaryKind());
     setIsPinnedPropertyTable(false);
@@ -309,7 +309,7 @@
     setMaxOffset(vm, invalidOffset);
  
     TypeInfo typeInfo = previous->typeInfo();
-    m_blob = StructureIDBlob(StructureID::encode(this), previous->indexingModeIncludingHistory(), typeInfo);
+    m_blob = TypeInfoBlob(previous->indexingModeIncludingHistory(), typeInfo);
     m_outOfLineTypeFlags = typeInfo.outOfLineTypeFlags();
 
     ASSERT(!previous->typeInfo().structureIsImmortal());

Modified: trunk/Source/_javascript_Core/runtime/Structure.h (295007 => 295008)


--- trunk/Source/_javascript_Core/runtime/Structure.h	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/runtime/Structure.h	2022-05-29 03:23:06 UTC (rev 295008)
@@ -38,14 +38,15 @@
 #include "PropertyNameArray.h"
 #include "PropertyOffset.h"
 #include "PutPropertySlot.h"
-#include "StructureIDBlob.h"
 #include "StructureRareData.h"
 #include "StructureTransitionTable.h"
-#include "TinyBloomFilter.h"
+#include "TypeInfoBlob.h"
 #include "Watchpoint.h"
 #include "WriteBarrierInlines.h"
 #include <wtf/Atomics.h>
 #include <wtf/CompactPointerTuple.h>
+#include <wtf/CompactPtr.h>
+#include <wtf/CompactRefPtr.h>
 #include <wtf/PrintStream.h>
 
 namespace WTF {
@@ -230,10 +231,10 @@
     void validateFlags();
 
 public:
-    StructureID id() const { ASSERT(m_blob.structureID() == StructureID::encode(this)); return m_blob.structureID(); }
-    int32_t objectInitializationBlob() const { return m_blob.blobExcludingStructureID(); }
-    int64_t idBlob() const { return m_blob.blob(); }
+    StructureID id() const { return StructureID::encode(this); }
 
+    int32_t typeInfoBlob() const { return m_blob.blob(); }
+
     bool isProxy() const
     {
         JSType type = m_blob.type();
@@ -330,7 +331,7 @@
     // Type accessors.
     TypeInfo typeInfo() const { return m_blob.typeInfo(m_outOfLineTypeFlags); }
     bool isObject() const { return typeInfo().isObject(); }
-    const ClassInfo* classInfoForCells() const { return m_classInfo; }
+    const ClassInfo* classInfoForCells() const { return m_classInfo.get(); }
 protected:
     // You probably want typeInfo().type()
     JSType type() { return JSCell::type(); }
@@ -649,11 +650,6 @@
     }
     void cacheSpecialProperty(JSGlobalObject*, VM&, JSValue, CachedSpecialPropertyKey, const PropertySlot&);
 
-    static ptrdiff_t structureIDOffset()
-    {
-        return OBJECT_OFFSETOF(Structure, m_blob) + StructureIDBlob::structureIDOffset();
-    }
-
     static ptrdiff_t prototypeOffset()
     {
         return OBJECT_OFFSETOF(Structure, m_prototype);
@@ -676,7 +672,7 @@
 
     static ptrdiff_t indexingModeIncludingHistoryOffset()
     {
-        return OBJECT_OFFSETOF(Structure, m_blob) + StructureIDBlob::indexingModeIncludingHistoryOffset();
+        return OBJECT_OFFSETOF(Structure, m_blob) + TypeInfoBlob::indexingModeIncludingHistoryOffset();
     }
     
     static ptrdiff_t propertyTableUnsafeOffset()
@@ -957,7 +953,7 @@
 
     // These need to be properly aligned at the beginning of the 'Structure'
     // part of the object.
-    StructureIDBlob m_blob;
+    TypeInfoBlob m_blob;
     TypeInfo::OutOfLineTypeFlags m_outOfLineTypeFlags;
 
     uint8_t m_inlineCapacity;
@@ -966,6 +962,13 @@
 
     uint32_t m_bitField;
 
+    uint16_t m_transitionOffset;
+    uint16_t m_maxOffset;
+
+    uint32_t m_propertyHash;
+    TinyBloomFilter<CompactPtr<UniquedStringImpl>::StorageType> m_seenProperties;
+
+
     WriteBarrier<JSGlobalObject> m_globalObject;
     WriteBarrier<Unknown> m_prototype;
     mutable WriteBarrier<StructureChain> m_cachedPrototypeChain;
@@ -972,9 +975,9 @@
 
     WriteBarrier<JSCell> m_previousOrRareData;
 
-    RefPtr<UniquedStringImpl> m_transitionPropertyName;
+    CompactRefPtr<UniquedStringImpl> m_transitionPropertyName;
 
-    const ClassInfo* m_classInfo;
+    CompactPtr<const ClassInfo> m_classInfo;
 
     StructureTransitionTable m_transitionTable;
 
@@ -986,12 +989,6 @@
 
     static_assert(firstOutOfLineOffset < 256);
 
-    uint16_t m_transitionOffset;
-    uint16_t m_maxOffset;
-
-    uint32_t m_propertyHash;
-    TinyBloomFilter m_seenProperties;
-
     friend class VMInspector;
     friend class JSDollarVMHelper;
     friend class Integrity::Analyzer;

Deleted: trunk/Source/_javascript_Core/runtime/StructureIDBlob.h (295007 => 295008)


--- trunk/Source/_javascript_Core/runtime/StructureIDBlob.h	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/runtime/StructureIDBlob.h	2022-05-29 03:23:06 UTC (rev 295008)
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2014-2017 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 "CellState.h"
-#include "IndexingType.h"
-#include "JSTypeInfo.h"
-#include "StructureID.h"
-
-namespace JSC {
-
-class StructureIDBlob {
-    friend class LLIntOffsetsExtractor;
-public:
-    StructureIDBlob() = default;
-
-    StructureIDBlob(StructureID structureID, IndexingType indexingModeIncludingHistory, const TypeInfo& typeInfo)
-    {
-        u.fields.structureID = structureID;
-        u.fields.indexingModeIncludingHistory = indexingModeIncludingHistory;
-        u.fields.type = typeInfo.type();
-        u.fields.inlineTypeFlags = typeInfo.inlineTypeFlags();
-        u.fields.defaultCellState = CellState::DefinitelyWhite;
-    }
-
-    void operator=(const StructureIDBlob& other) { u.doubleWord = other.u.doubleWord; }
-    
-    StructureID structureID() const { return u.fields.structureID; }
-    IndexingType indexingModeIncludingHistory() const { return u.fields.indexingModeIncludingHistory; }
-    Dependency fencedIndexingModeIncludingHistory(IndexingType& indexingType)
-    {
-        return Dependency::loadAndFence(&u.fields.indexingModeIncludingHistory, indexingType);
-    }
-    void setIndexingModeIncludingHistory(IndexingType indexingModeIncludingHistory) { u.fields.indexingModeIncludingHistory = indexingModeIncludingHistory; }
-    JSType type() const { return u.fields.type; }
-    TypeInfo::InlineTypeFlags inlineTypeFlags() const { return u.fields.inlineTypeFlags; }
-    
-    TypeInfo typeInfo(TypeInfo::OutOfLineTypeFlags outOfLineTypeFlags) const { return TypeInfo(type(), inlineTypeFlags(), outOfLineTypeFlags); }
-    
-    int32_t blobExcludingStructureID() const { return u.words.word2; }
-    int64_t blob() const { return u.doubleWord; }
-    
-    static ptrdiff_t structureIDOffset()
-    {
-        return OBJECT_OFFSETOF(StructureIDBlob, u.fields.structureID);
-    }
-
-    static ptrdiff_t indexingModeIncludingHistoryOffset()
-    {
-        return OBJECT_OFFSETOF(StructureIDBlob, u.fields.indexingModeIncludingHistory);
-    }
-
-private:
-    union Data {
-        struct {
-            // FIXME: We should remove this since the structureID can be directly computed from the Structure*
-            StructureID structureID;
-            IndexingType indexingModeIncludingHistory;
-            JSType type;
-            TypeInfo::InlineTypeFlags inlineTypeFlags;
-            CellState defaultCellState;
-        } fields;
-        struct {
-            int32_t word1;
-            int32_t word2;
-        } words;
-        int64_t doubleWord;
-
-        Data() { doubleWord = 0xbbadbeef; }
-    };
-
-    Data u;
-};
-
-} // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/StructureInlines.h (295007 => 295008)


--- trunk/Source/_javascript_Core/runtime/StructureInlines.h	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/runtime/StructureInlines.h	2022-05-29 03:23:06 UTC (rev 295008)
@@ -33,6 +33,7 @@
 #include "Structure.h"
 #include "StructureChain.h"
 #include "StructureRareDataInlines.h"
+#include <wtf/CompactRefPtr.h>
 #include <wtf/Threading.h>
 
 namespace JSC {
@@ -164,7 +165,7 @@
     ASSERT(!isCompilationThread());
     ASSERT(structure()->classInfoForCells() == info());
 
-    if (m_seenProperties.ruleOut(bitwise_cast<uintptr_t>(propertyName.uid())))
+    if (m_seenProperties.ruleOut(CompactPtr<UniquedStringImpl>::encode(propertyName.uid())))
         return invalidOffset;
 
     PropertyTable* propertyTable = ensurePropertyTableIfNotEmpty(vm);
@@ -489,7 +490,7 @@
     PropertyOffset newOffset = table->nextOffset(m_inlineCapacity);
 
     m_propertyHash = m_propertyHash ^ rep->existingSymbolAwareHash();
-    m_seenProperties.add(bitwise_cast<uintptr_t>(rep));
+    m_seenProperties.add(CompactPtr<UniquedStringImpl>::encode(rep));
 
     auto [offset, attribute, result] = table->add(vm, PropertyTableEntry(rep, newOffset, attributes));
     ASSERT_UNUSED(result, result);

Copied: trunk/Source/_javascript_Core/runtime/TypeInfoBlob.h (from rev 295007, trunk/Source/_javascript_Core/runtime/StructureIDBlob.h) (0 => 295008)


--- trunk/Source/_javascript_Core/runtime/TypeInfoBlob.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/TypeInfoBlob.h	2022-05-29 03:23:06 UTC (rev 295008)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2014-2017 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 "CellState.h"
+#include "IndexingType.h"
+#include "JSTypeInfo.h"
+#include "StructureID.h"
+
+namespace JSC {
+
+class TypeInfoBlob {
+    friend class LLIntOffsetsExtractor;
+public:
+    TypeInfoBlob() = default;
+
+    TypeInfoBlob(IndexingType indexingModeIncludingHistory, const TypeInfo& typeInfo)
+    {
+        u.fields.indexingModeIncludingHistory = indexingModeIncludingHistory;
+        u.fields.type = typeInfo.type();
+        u.fields.inlineTypeFlags = typeInfo.inlineTypeFlags();
+        u.fields.defaultCellState = CellState::DefinitelyWhite;
+    }
+
+    void operator=(const TypeInfoBlob& other) { u.word = other.u.word; }
+
+    IndexingType indexingModeIncludingHistory() const { return u.fields.indexingModeIncludingHistory; }
+    Dependency fencedIndexingModeIncludingHistory(IndexingType& indexingType)
+    {
+        return Dependency::loadAndFence(&u.fields.indexingModeIncludingHistory, indexingType);
+    }
+    void setIndexingModeIncludingHistory(IndexingType indexingModeIncludingHistory) { u.fields.indexingModeIncludingHistory = indexingModeIncludingHistory; }
+    JSType type() const { return u.fields.type; }
+    TypeInfo::InlineTypeFlags inlineTypeFlags() const { return u.fields.inlineTypeFlags; }
+    
+    TypeInfo typeInfo(TypeInfo::OutOfLineTypeFlags outOfLineTypeFlags) const { return TypeInfo(type(), inlineTypeFlags(), outOfLineTypeFlags); }
+
+    int32_t blob() const { return u.word; }
+
+    static ptrdiff_t indexingModeIncludingHistoryOffset()
+    {
+        return OBJECT_OFFSETOF(TypeInfoBlob, u.fields.indexingModeIncludingHistory);
+    }
+
+private:
+    union Data {
+        struct {
+            IndexingType indexingModeIncludingHistory;
+            JSType type;
+            TypeInfo::InlineTypeFlags inlineTypeFlags;
+            CellState defaultCellState;
+        } fields;
+        int32_t word;
+
+        Data() { word = 0xbbadbeef; }
+    };
+
+    Data u;
+};
+
+} // namespace JSC

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp (295007 => 295008)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp	2022-05-29 03:23:06 UTC (rev 295008)
@@ -268,7 +268,7 @@
 
                 stackLimitGPRIsClobbered = true;
                 jit.emitLoadStructure(vm, scratchGPR, scratchGPR);
-                jit.loadPtr(CCallHelpers::Address(scratchGPR, Structure::classInfoOffset()), scratchGPR);
+                jit.loadCompactPtr(CCallHelpers::Address(scratchGPR, Structure::classInfoOffset()), scratchGPR);
 
                 static_assert(std::is_final<WebAssemblyFunction>::value, "We do not check for subtypes below");
                 static_assert(std::is_final<WebAssemblyWrapperFunction>::value, "We do not check for subtypes below");

Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (295007 => 295008)


--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2022-05-29 03:23:06 UTC (rev 295008)
@@ -811,6 +811,8 @@
 		FE35D09227DC5ECC009DFA5B /* StackCheck.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE35D09127DC5ECC009DFA5B /* StackCheck.cpp */; };
 		FEDACD3D1630F83F00C69634 /* StackStats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEDACD3B1630F83F00C69634 /* StackStats.cpp */; };
 		FEEA4DF9216D7BE400AC0602 /* StackPointer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEEA4DF8216D7BE400AC0602 /* StackPointer.cpp */; };
+		FF895F11282AB96400E7BAE8 /* CompactRefPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = FF895F10282AB96400E7BAE8 /* CompactRefPtr.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		FFEE46F42825DF80003BC981 /* CompactPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = FFEE46F32825DF80003BC981 /* CompactPtr.h */; settings = {ATTRIBUTES = (Private, ); }; };
 /* End PBXBuildFile section */
 
 /* Begin PBXBuildRule section */
@@ -1714,6 +1716,8 @@
 		FEEA4DF8216D7BE400AC0602 /* StackPointer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StackPointer.cpp; sourceTree = "<group>"; };
 		FEF295BF20B49DCB00CF283A /* UTF8ConversionError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UTF8ConversionError.h; sourceTree = "<group>"; };
 		FF0A436588954F3CB07DBECA /* StdList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StdList.h; sourceTree = "<group>"; };
+		FF895F10282AB96400E7BAE8 /* CompactRefPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompactRefPtr.h; sourceTree = "<group>"; };
+		FFEE46F32825DF80003BC981 /* CompactPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompactPtr.h; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -1930,6 +1934,8 @@
 				0F66B2811DC97BAB004A1D3F /* ClockType.h */,
 				0FC4EDE51696149600F65041 /* CommaPrinter.h */,
 				E3CF76902115D6BA0091DE48 /* CompactPointerTuple.h */,
+				FFEE46F32825DF80003BC981 /* CompactPtr.h */,
+				FF895F10282AB96400E7BAE8 /* CompactRefPtr.h */,
 				E38020DB2401C0930037CA9E /* CompactRefPtrTuple.h */,
 				9B96E9B324FF77B8001756C3 /* CompactUniquePtrTuple.h */,
 				0F8F2B8F172E00F0007DBDA5 /* CompilationThread.cpp */,
@@ -2861,6 +2867,8 @@
 				DDF307F427C086EA006A526F /* Collator.h in Headers */,
 				DD3DC91627A4BF8E007E5B61 /* CommaPrinter.h in Headers */,
 				DD3DC8F627A4BF8E007E5B61 /* CompactPointerTuple.h in Headers */,
+				FFEE46F42825DF80003BC981 /* CompactPtr.h in Headers */,
+				FF895F11282AB96400E7BAE8 /* CompactRefPtr.h in Headers */,
 				DD3DC93927A4BF8E007E5B61 /* CompactRefPtrTuple.h in Headers */,
 				DD3DC93527A4BF8E007E5B61 /* CompactUniquePtrTuple.h in Headers */,
 				DD3DC90727A4BF8E007E5B61 /* CompilationThread.h in Headers */,

Modified: trunk/Source/WTF/wtf/CMakeLists.txt (295007 => 295008)


--- trunk/Source/WTF/wtf/CMakeLists.txt	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/WTF/wtf/CMakeLists.txt	2022-05-29 03:23:06 UTC (rev 295008)
@@ -35,6 +35,8 @@
     ClockType.h
     CommaPrinter.h
     CompactPointerTuple.h
+    CompactPtr.h
+    CompactRefPtr.h
     CompactRefPtrTuple.h
     CompactUniquePtrTuple.h
     CompilationThread.h

Added: trunk/Source/WTF/wtf/CompactPtr.h (0 => 295008)


--- trunk/Source/WTF/wtf/CompactPtr.h	                        (rev 0)
+++ trunk/Source/WTF/wtf/CompactPtr.h	2022-05-29 03:23:06 UTC (rev 295008)
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2022 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 <cstdint>
+#include <utility>
+#include <wtf/RawPtrTraits.h>
+#include <wtf/StdLibExtras.h>
+
+#if OS(DARWIN)
+#include <mach/vm_param.h>
+#endif
+
+namespace WTF {
+
+#if CPU(ADDRESS64)
+#if CPU(ARM64) && OS(DARWIN)
+#if MACH_VM_MAX_ADDRESS_RAW < (1ULL << 36)
+#define HAVE_36BIT_ADDRESS 1
+#endif
+#endif
+#endif // CPU(ADDRESS64)
+
+template <typename T>
+class CompactPtr {
+    WTF_MAKE_FAST_ALLOCATED;
+
+public:
+#if HAVE(36BIT_ADDRESS)
+    // The CompactPtr algorithm relies on being able to shift
+    // a 36-bit address right by 4 in order to fit in 32-bits.
+    // The only way this is an ok thing to do without information
+    // loss is if the if the address is always 16 bytes aligned i.e.
+    // the lower 4 bits is always 0.
+    using StorageType = uint32_t;
+#else
+    using StorageType = uintptr_t;
+#endif
+    static constexpr bool isCompactedType = true;
+
+    ALWAYS_INLINE constexpr CompactPtr() = default;
+
+    ALWAYS_INLINE constexpr CompactPtr(std::nullptr_t) { }
+
+    ALWAYS_INLINE CompactPtr(T* ptr) { set(ptr); }
+
+    ALWAYS_INLINE constexpr CompactPtr(const CompactPtr& o) : m_ptr(o.m_ptr) { }
+
+    template <typename X>
+    ALWAYS_INLINE constexpr CompactPtr(const CompactPtr<X>& o) : m_ptr(o.m_ptr) { static_assert(std::is_convertible_v<X*, T*>); }
+
+    ALWAYS_INLINE CompactPtr(CompactPtr&& o) { swap(o); }
+
+    template <typename X>
+    ALWAYS_INLINE CompactPtr(CompactPtr<X>&& o)
+        : m_ptr(o.m_ptr)
+    { 
+        static_assert(std::is_convertible_v<X*, T*>);
+        std::exchange(o.m_ptr, 0);
+    }
+
+    ALWAYS_INLINE ~CompactPtr() = default;
+
+    T& operator*() const { return *get(); }
+
+    ALWAYS_INLINE T* operator->() const { return get(); }
+
+    bool operator!() const { return !get(); }
+
+    explicit operator bool() const { return !!get(); }
+
+    CompactPtr<T>& operator=(std::nullptr_t)
+    {
+        exchange(nullptr);
+        return *this;
+    }
+
+    CompactPtr<T>& operator=(const CompactPtr& o)
+    {
+        CompactPtr copy(o);
+        swap(copy);
+        return *this;
+    }
+
+    template <typename X>
+    CompactPtr<T>& operator=(const CompactPtr<X>& o)
+    {
+        static_assert(std::is_convertible_v<X*, T*>);
+        CompactPtr copy(o);
+        swap(copy);
+        return *this;
+    }
+
+    CompactPtr<T>& operator=(T* optr)
+    {
+        CompactPtr copy(optr);
+        swap(copy);
+        return *this;
+    }
+
+    CompactPtr<T>& operator=(CompactPtr&& o)
+    {
+        CompactPtr moved(WTFMove(o));
+        swap(moved);
+        return *this;
+    }
+
+    template <typename X>
+    CompactPtr<T>& operator=(CompactPtr<X>&& o)
+    {
+        static_assert(std::is_convertible_v<X*, T*>);
+        CompactPtr moved(WTFMove(o));
+        swap(moved);
+        return *this;
+    }
+
+    T* get() const { return decode(m_ptr); }
+
+    void set(T* ptr) { m_ptr = encode(ptr); }
+
+    template <class U>
+    T* exchange(U&& newValue)
+    {
+        T* oldValue = get();
+        set(std::forward<U>(newValue));
+        return oldValue;
+    }
+
+    void swap(nullptr_t) { set(nullptr); }
+
+    void swap(CompactPtr& other) { std::swap(m_ptr, other.m_ptr); }
+
+    template <typename Other, typename = std::enable_if_t<Other::isCompactedType>>
+    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);
+    }
+
+    static ALWAYS_INLINE constexpr StorageType encode(T* ptr)
+    {
+        uintptr_t intPtr = bitwise_cast<uintptr_t>(ptr);
+#if HAVE(36BIT_ADDRESS)
+        ASSERT_UNDER_CONSTEXPR_CONTEXT(!(intPtr & alignmentMask));
+        StorageType encoded = static_cast<uint32_t>(intPtr >> bitsShift);
+        ASSERT_UNDER_CONSTEXPR_CONTEXT(decode(encoded) == ptr);
+        return encoded;
+#else
+        return intPtr;
+#endif
+    }
+
+    ALWAYS_INLINE constexpr T* decode(const StorageType& ptr) const
+    {
+#if HAVE(36BIT_ADDRESS)
+        return reinterpret_cast<T*>(static_cast<uintptr_t>(ptr) << bitsShift);
+#else
+        return reinterpret_cast<T*>(ptr);
+#endif
+    }
+
+private:
+    template <typename X>
+    friend class CompactPtr;
+
+    static constexpr uint32_t bitsShift = 4;
+    static constexpr uintptr_t alignmentMask = (1ull << bitsShift) - 1;
+
+    StorageType m_ptr { 0 };
+};
+
+template <typename T>
+struct GetPtrHelper<CompactPtr<T>> {
+    using PtrType = T*;
+    static T* getPtr(const CompactPtr<T>& p) { return const_cast<T*>(p.get()); }
+};
+
+template <typename T>
+struct IsSmartPtr<CompactPtr<T>> {
+    static constexpr bool value = true;
+};
+
+template <typename T>
+struct CompactPtrTraits {
+    template <typename U>
+    using RebindTraits = RawPtrTraits<U>;
+
+    using StorageType = CompactPtr<T>;
+
+    template <typename U>
+    static ALWAYS_INLINE T* exchange(StorageType& ptr, U&& newValue) { return ptr.exchange(newValue); }
+
+    template <typename Other>
+    static ALWAYS_INLINE void swap(StorageType& a, Other& b) { a.swap(b); }
+
+    static ALWAYS_INLINE T* unwrap(const StorageType& ptr) { return ptr.get(); }
+
+    static StorageType hashTableDeletedValue() { return bitwise_cast<StorageType>(static_cast<StorageType>(-1)); }
+    static ALWAYS_INLINE bool isHashTableDeletedValue(const StorageType& ptr) { return ptr == hashTableDeletedValue(); }
+};
+
+} // namespace WTF
+
+using WTF::CompactPtr;
+using WTF::CompactPtrTraits;

Copied: trunk/Source/WTF/wtf/CompactRefPtr.h (from rev 295007, trunk/Source/_javascript_Core/heap/HeapSnapshot.h) (0 => 295008)


--- trunk/Source/WTF/wtf/CompactRefPtr.h	                        (rev 0)
+++ trunk/Source/WTF/wtf/CompactRefPtr.h	2022-05-29 03:23:06 UTC (rev 295008)
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 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 <wtf/CompactPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WTF {
+
+template <typename T>
+using CompactRefPtr = RefPtr<T, CompactPtrTraits<T>>;
+
+} // namespace WTF
+
+using WTF::CompactRefPtr;

Modified: trunk/Source/WTF/wtf/text/StringImpl.cpp (295007 => 295008)


--- trunk/Source/WTF/wtf/text/StringImpl.cpp	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/WTF/wtf/text/StringImpl.cpp	2022-05-29 03:23:06 UTC (rev 295008)
@@ -45,8 +45,14 @@
 
 using namespace Unicode;
 
-static_assert(sizeof(StringImpl) == 2 * sizeof(int) + 2 * sizeof(void*), "StringImpl should stay small");
+#if HAVE(36BIT_ADDRESS)
+#define STRING_IMPL_SIZE(n) roundUpToMultipleOfImpl(16, n)
+#else
+#define STRING_IMPL_SIZE(n) n
+#endif
 
+static_assert(sizeof(StringImpl) == STRING_IMPL_SIZE(2 * sizeof(int) + 2 * sizeof(void*)), "StringImpl should stay small");
+
 #if STRING_STATS
 StringStats StringImpl::m_stringStats;
 

Modified: trunk/Source/WTF/wtf/text/StringImpl.h (295007 => 295008)


--- trunk/Source/WTF/wtf/text/StringImpl.h	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Source/WTF/wtf/text/StringImpl.h	2022-05-29 03:23:06 UTC (rev 295008)
@@ -26,6 +26,7 @@
 #include <unicode/ustring.h>
 #include <wtf/ASCIICType.h>
 #include <wtf/CheckedArithmetic.h>
+#include <wtf/CompactPtr.h>
 #include <wtf/DebugHeap.h>
 #include <wtf/Expected.h>
 #include <wtf/MathExtras.h>
@@ -48,6 +49,12 @@
 @class NSString;
 #endif
 
+#if HAVE(36BIT_ADDRESS)
+#define STRING_IMPL_ALIGNMENT alignas(16)
+#else
+#define STRING_IMPL_ALIGNMENT
+#endif
+
 namespace JSC {
 namespace LLInt { class Data; }
 class LLIntOffsetsExtractor;
@@ -132,7 +139,7 @@
 
 #endif
 
-class StringImplShape {
+class STRING_IMPL_ALIGNMENT StringImplShape {
     WTF_MAKE_NONCOPYABLE(StringImplShape);
 public:
     static constexpr unsigned MaxLength = std::numeric_limits<int32_t>::max();

Modified: trunk/Tools/TestWebKitAPI/CMakeLists.txt (295007 => 295008)


--- trunk/Tools/TestWebKitAPI/CMakeLists.txt	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Tools/TestWebKitAPI/CMakeLists.txt	2022-05-29 03:23:06 UTC (rev 295008)
@@ -29,6 +29,8 @@
     Tests/WTF/BumpPointerAllocator.cpp
     Tests/WTF/CString.cpp
     Tests/WTF/CheckedArithmeticOperations.cpp
+    Tests/WTF/CompactPtr.cpp
+    Tests/WTF/CompactRefPtr.cpp
     Tests/WTF/CompactRefPtrTuple.cpp
     Tests/WTF/CompactUniquePtrTuple.cpp
     Tests/WTF/ConcurrentPtrHashSet.cpp

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (295007 => 295008)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2022-05-29 03:23:06 UTC (rev 295008)
@@ -1167,6 +1167,8 @@
 		FE2D9474245EB2F400E48135 /* Bitmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE2D9473245EB2DF00E48135 /* Bitmap.cpp */; };
 		FEC2A85424CE975F00ADBC35 /* DisallowVMEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEC2A85324CE974E00ADBC35 /* DisallowVMEntry.cpp */; };
 		FEC2A85624CEB65F00ADBC35 /* PropertySlot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEC2A85524CEB65F00ADBC35 /* PropertySlot.cpp */; };
+		FF10AAF92831B1E600B9875B /* CompactPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FF10AAF82831B1E600B9875B /* CompactPtr.cpp */; };
+		FF5D0CB4283221AD00F3278A /* CompactRefPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FF5D0CB3283221AD00F3278A /* CompactRefPtr.cpp */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -3235,6 +3237,9 @@
 		FEB6F74E1B2BA44E009E4922 /* NakedPtr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NakedPtr.cpp; sourceTree = "<group>"; };
 		FEC2A85324CE974E00ADBC35 /* DisallowVMEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DisallowVMEntry.cpp; sourceTree = "<group>"; };
 		FEC2A85524CEB65F00ADBC35 /* PropertySlot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PropertySlot.cpp; sourceTree = "<group>"; };
+		FF10AAF82831B1E600B9875B /* CompactPtr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompactPtr.cpp; sourceTree = "<group>"; };
+		FF25942A2834B7A7006892D6 /* AlignedRefLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlignedRefLogger.h; sourceTree = "<group>"; };
+		FF5D0CB3283221AD00F3278A /* CompactRefPtr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompactRefPtr.cpp; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -4655,6 +4660,8 @@
 				A7A966DA140ECCC8005EF9B4 /* CheckedArithmeticOperations.cpp */,
 				9BBCA4DE265ACA5B00DFE723 /* CheckedPtr.cpp */,
 				9BF00132267C4C5900DCFB3F /* CheckedRef.cpp */,
+				FF10AAF82831B1E600B9875B /* CompactPtr.cpp */,
+				FF5D0CB3283221AD00F3278A /* CompactRefPtr.cpp */,
 				E302BDA92404B92300865277 /* CompactRefPtrTuple.cpp */,
 				9B0C051824FDFB7000F2FE31 /* CompactUniquePtrTuple.cpp */,
 				0F30CB5B1FCE1792004B5323 /* ConcurrentPtrHashSet.cpp */,
@@ -4662,6 +4669,7 @@
 				278DE64B22B8D611004E0E7A /* CrossThreadCopier.cpp */,
 				51714EB91D087416004723C4 /* CrossThreadTask.cpp */,
 				26A2C72E15E2E73C005B1A14 /* CString.cpp */,
+				FF25942A2834B7A7006892D6 /* AlignedRefLogger.h */,
 				7AA021BA1AB09EA70052953F /* DateMath.cpp */,
 				1A3524A91D627BD40031729B /* DeletedAddressOfOperator.h */,
 				E4A757D3178AEA5B00B5D7A4 /* Deque.cpp */,
@@ -5454,6 +5462,8 @@
 				7C83DEA01D0A590C00FEBCF3 /* CheckedArithmeticOperations.cpp in Sources */,
 				9BBCA4DF265ACA5B00DFE723 /* CheckedPtr.cpp in Sources */,
 				9BF00133267C4C5900DCFB3F /* CheckedRef.cpp in Sources */,
+				FF10AAF92831B1E600B9875B /* CompactPtr.cpp in Sources */,
+				FF5D0CB4283221AD00F3278A /* CompactRefPtr.cpp in Sources */,
 				E302BDAA2404B92400865277 /* CompactRefPtrTuple.cpp in Sources */,
 				9B0C051924FDFB7D00F2FE31 /* CompactUniquePtrTuple.cpp in Sources */,
 				0F30CB5C1FCE1796004B5323 /* ConcurrentPtrHashSet.cpp in Sources */,

Copied: trunk/Tools/TestWebKitAPI/Tests/WTF/AlignedRefLogger.h (from rev 295007, trunk/Source/_javascript_Core/heap/TinyBloomFilter.h) (0 => 295008)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/AlignedRefLogger.h	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/AlignedRefLogger.h	2022-05-29 03:23:06 UTC (rev 295008)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2022 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 "Logger.h"
+
+namespace TestWebKitAPI {
+
+struct alignas(16) AlignedRefLogger {
+    AlignedRefLogger(const char* name)
+        : name { *name }
+    {
+    }
+
+    void ref()
+    {
+        log() << "ref(" << &name << ") ";
+    }
+
+    void deref()
+    {
+        log() << "deref(" << &name << ") ";
+    }
+
+    const char& name;
+};
+
+struct DerivedAlignedRefLogger : AlignedRefLogger {
+    DerivedAlignedRefLogger(const char* name)
+        : AlignedRefLogger { name }
+    {
+    }
+};
+
+}

Added: trunk/Tools/TestWebKitAPI/Tests/WTF/CompactPtr.cpp (0 => 295008)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/CompactPtr.cpp	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/CompactPtr.cpp	2022-05-29 03:23:06 UTC (rev 295008)
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2022 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/CompactPtr.h>
+
+#include "AlignedRefLogger.h"
+#include "Utilities.h"
+#include <wtf/MainThread.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RunLoop.h>
+#include <wtf/ThreadSafeRefCounted.h>
+#include <wtf/Threading.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF_CompactPtr, Basic)
+{
+    DerivedAlignedRefLogger a("a");
+
+    CompactPtr<AlignedRefLogger> empty;
+    EXPECT_EQ(nullptr, empty.get());
+
+    {
+        CompactPtr<AlignedRefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        EXPECT_EQ(&a, &*ptr);
+        EXPECT_EQ(&a.name, &ptr->name);
+    }
+
+    {
+        CompactPtr<AlignedRefLogger> ptr = &a;
+        EXPECT_EQ(&a, ptr.get());
+    }
+
+    {
+        CompactPtr<AlignedRefLogger> p1 = &a;
+        CompactPtr<AlignedRefLogger> p2(p1);
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+
+    {
+        CompactPtr<AlignedRefLogger> p1 = &a;
+        CompactPtr<AlignedRefLogger> p2 = p1;
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+
+    {
+        CompactPtr<AlignedRefLogger> p1 = &a;
+        CompactPtr<AlignedRefLogger> p2 = WTFMove(p1);
+        EXPECT_EQ(nullptr, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+
+    {
+        CompactPtr<AlignedRefLogger> p1 = &a;
+        CompactPtr<AlignedRefLogger> p2(WTFMove(p1));
+        EXPECT_EQ(nullptr, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+
+    {
+        CompactPtr<DerivedAlignedRefLogger> p1 = &a;
+        CompactPtr<AlignedRefLogger> p2 = p1;
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+
+    {
+        CompactPtr<DerivedAlignedRefLogger> p1 = &a;
+        CompactPtr<AlignedRefLogger> p2 = WTFMove(p1);
+        EXPECT_EQ(nullptr, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+
+    {
+        CompactPtr<AlignedRefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        ptr = nullptr;
+        EXPECT_EQ(nullptr, ptr.get());
+    }
+
+    {
+        CompactPtr<AlignedRefLogger> ptr(nullptr);
+        EXPECT_EQ(nullptr, ptr.get());
+        EXPECT_EQ(false, static_cast<bool>(ptr));
+    }
+
+    {
+        CompactPtr<AlignedRefLogger> ptr = nullptr;
+        EXPECT_EQ(nullptr, ptr.get());
+        EXPECT_EQ(true, !ptr);
+    }
+
+    {
+        DerivedAlignedRefLogger b("b");
+        DerivedAlignedRefLogger* p1 = &a;
+        CompactPtr<DerivedAlignedRefLogger> p2(&b);
+        p2.swap(p1);
+        EXPECT_EQ(p1, &b);
+        EXPECT_EQ(p2.get(), &a);
+    }
+}
+
+TEST(WTF_CompactPtr, Assignment)
+{
+    DerivedAlignedRefLogger a("a");
+    AlignedRefLogger b("b");
+    DerivedAlignedRefLogger c("c");
+
+    {
+        CompactPtr<AlignedRefLogger> p1 = &a;
+        CompactPtr<AlignedRefLogger> p2 = &b;
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        p1 = p2;
+        EXPECT_EQ(&b, p1.get());
+        EXPECT_EQ(&b, p2.get());
+    }
+
+    {
+        CompactPtr<AlignedRefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        ptr = &b;
+        EXPECT_EQ(&b, ptr.get());
+    }
+
+    {
+        CompactPtr<AlignedRefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        ptr = nullptr;
+        EXPECT_EQ(nullptr, ptr.get());
+    }
+
+    {
+        CompactPtr<AlignedRefLogger> p1 = &a;
+        CompactPtr<AlignedRefLogger> p2 = &b;
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        p1 = WTFMove(p2);
+        EXPECT_EQ(&b, p1.get());
+        EXPECT_EQ(nullptr, p2.get());
+    }
+
+    {
+        CompactPtr<AlignedRefLogger> p1 = &a;
+        CompactPtr<DerivedAlignedRefLogger> p2 = &c;
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&c, p2.get());
+        p1 = p2;
+        EXPECT_EQ(&c, p1.get());
+        EXPECT_EQ(&c, p2.get());
+    }
+
+    {
+        CompactPtr<AlignedRefLogger> p1 = &a;
+        CompactPtr<DerivedAlignedRefLogger> p2 = &c;
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&c, p2.get());
+        p1 = WTFMove(p2);
+        EXPECT_EQ(&c, p1.get());
+        EXPECT_EQ(nullptr, p2.get());
+    }
+
+    {
+        CompactPtr<AlignedRefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        ptr = &c;
+        EXPECT_EQ(&c, ptr.get());
+    }
+}
+
+} // namespace TestWebKitAPI

Added: trunk/Tools/TestWebKitAPI/Tests/WTF/CompactRefPtr.cpp (0 => 295008)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/CompactRefPtr.cpp	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/CompactRefPtr.cpp	2022-05-29 03:23:06 UTC (rev 295008)
@@ -0,0 +1,567 @@
+/*
+ * Copyright (C) 2022 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/CompactRefPtr.h>
+
+#include "AlignedRefLogger.h"
+#include "Utilities.h"
+#include <wtf/MainThread.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RunLoop.h>
+#include <wtf/ThreadSafeRefCounted.h>
+#include <wtf/Threading.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF_CompactRefPtr, Basic)
+{
+    DerivedAlignedRefLogger a("a");
+
+    CompactRefPtr<AlignedRefLogger> empty;
+    EXPECT_EQ(nullptr, empty.get());
+
+    {
+        CompactRefPtr<AlignedRefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        EXPECT_EQ(&a, &*ptr);
+        EXPECT_EQ(&a.name, &ptr->name);
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> ptr = &a;
+        EXPECT_EQ(&a, ptr.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> p1 = &a;
+        CompactRefPtr<AlignedRefLogger> p2(p1);
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+    EXPECT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> p1 = &a;
+        CompactRefPtr<AlignedRefLogger> p2 = p1;
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+    EXPECT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> p1 = &a;
+        CompactRefPtr<AlignedRefLogger> p2 = WTFMove(p1);
+        EXPECT_EQ(nullptr, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> p1 = &a;
+        CompactRefPtr<AlignedRefLogger> p2(WTFMove(p1));
+        EXPECT_EQ(nullptr, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<DerivedAlignedRefLogger> p1 = &a;
+        CompactRefPtr<AlignedRefLogger> p2 = p1;
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+    EXPECT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<DerivedAlignedRefLogger> p1 = &a;
+        CompactRefPtr<AlignedRefLogger> p2 = WTFMove(p1);
+        EXPECT_EQ(nullptr, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        ptr = nullptr;
+        EXPECT_EQ(nullptr, ptr.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> ptr(nullptr);
+        EXPECT_EQ(nullptr, ptr.get());
+        EXPECT_EQ(false, static_cast<bool>(ptr));
+    }
+    EXPECT_STREQ("", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> ptr = nullptr;
+        EXPECT_EQ(nullptr, ptr.get());
+        EXPECT_EQ(true, !ptr);
+    }
+    EXPECT_STREQ("", takeLogStr().c_str());
+}
+
+TEST(WTF_CompactRefPtr, AssignPassRefToCompactRefPtr)
+{
+    DerivedAlignedRefLogger a("a");
+    {
+        Ref<AlignedRefLogger> passRef(a);
+        CompactRefPtr<AlignedRefLogger> ptr = WTFMove(passRef);
+        EXPECT_EQ(&a, ptr.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_CompactRefPtr, Adopt)
+{
+    DerivedAlignedRefLogger a("a");
+
+    CompactRefPtr<AlignedRefLogger> empty;
+    EXPECT_EQ(nullptr, empty.get());
+
+    {
+        CompactRefPtr<AlignedRefLogger> ptr(adoptRef(&a));
+        EXPECT_EQ(&a, ptr.get());
+        EXPECT_EQ(&a, &*ptr);
+        EXPECT_EQ(&a.name, &ptr->name);
+    }
+    EXPECT_STREQ("deref(a) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> ptr = adoptRef(&a);
+        EXPECT_EQ(&a, ptr.get());
+    }
+    EXPECT_STREQ("deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_CompactRefPtr, Assignment)
+{
+    DerivedAlignedRefLogger a("a");
+    AlignedRefLogger b("b");
+    DerivedAlignedRefLogger c("c");
+
+    {
+        CompactRefPtr<AlignedRefLogger> p1(&a);
+        CompactRefPtr<AlignedRefLogger> p2(&b);
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        log() << "| ";
+        p1 = p2;
+        EXPECT_EQ(&b, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(b) | ref(b) deref(a) | deref(b) deref(b) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        log() << "| ";
+        ptr = &b;
+        EXPECT_EQ(&b, ptr.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | ref(b) deref(a) | deref(b) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        log() << "| ";
+        ptr = adoptRef(&b);
+        EXPECT_EQ(&b, ptr.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | deref(a) | deref(b) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        ptr = nullptr;
+        EXPECT_EQ(nullptr, ptr.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> p1(&a);
+        CompactRefPtr<AlignedRefLogger> p2(&b);
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        log() << "| ";
+        p1 = WTFMove(p2);
+        EXPECT_EQ(&b, p1.get());
+        EXPECT_EQ(nullptr, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(b) | deref(a) | deref(b) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> p1(&a);
+        CompactRefPtr<DerivedAlignedRefLogger> p2(&c);
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&c, p2.get());
+        log() << "| ";
+        p1 = p2;
+        EXPECT_EQ(&c, p1.get());
+        EXPECT_EQ(&c, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(c) | ref(c) deref(a) | deref(c) deref(c) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        log() << "| ";
+        ptr = &c;
+        EXPECT_EQ(&c, ptr.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | ref(c) deref(a) | deref(c) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        log() << "| ";
+        ptr = adoptRef(&c);
+        EXPECT_EQ(&c, ptr.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | deref(a) | deref(c) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> p1(&a);
+        CompactRefPtr<DerivedAlignedRefLogger> p2(&c);
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&c, p2.get());
+        log() << "| ";
+        p1 = WTFMove(p2);
+        EXPECT_EQ(&c, p1.get());
+        EXPECT_EQ(nullptr, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(c) | deref(a) | deref(c) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        log() << "| ";
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wunknown-warning-option"
+#pragma clang diagnostic ignored "-Wself-assign-overloaded"
+#endif
+        ptr = ptr;
+#if COMPILER(CLANG)
+#pragma clang diagnostic pop
+#endif
+        EXPECT_EQ(&a, ptr.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | ref(a) deref(a) | deref(a) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wself-move"
+#endif
+        ptr = WTFMove(ptr);
+#if COMPILER(CLANG)
+#pragma clang diagnostic pop
+#endif
+        EXPECT_EQ(&a, ptr.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_CompactRefPtr, Swap)
+{
+    AlignedRefLogger a("a");
+    AlignedRefLogger b("b");
+
+    {
+        CompactRefPtr<AlignedRefLogger> p1(&a);
+        CompactRefPtr<AlignedRefLogger> p2(&b);
+        log() << "| ";
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        p1.swap(p2);
+        EXPECT_EQ(&b, p1.get());
+        EXPECT_EQ(&a, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(b) | | deref(a) deref(b) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> p1(&a);
+        CompactRefPtr<AlignedRefLogger> p2(&b);
+        log() << "| ";
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        std::swap(p1, p2);
+        EXPECT_EQ(&b, p1.get());
+        EXPECT_EQ(&a, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(b) | | deref(a) deref(b) ", takeLogStr().c_str());
+}
+
+TEST(WTF_CompactRefPtr, ReleaseNonNull)
+{
+    AlignedRefLogger a("a");
+
+    {
+        CompactRefPtr<AlignedRefLogger> refPtr = &a;
+        CompactRefPtr<AlignedRefLogger> ref = refPtr.releaseNonNull();
+    }
+
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_CompactRefPtr, Release)
+{
+    DerivedAlignedRefLogger a("a");
+    AlignedRefLogger b("b");
+    DerivedAlignedRefLogger c("c");
+
+    {
+        CompactRefPtr<AlignedRefLogger> p1 = &a;
+        CompactRefPtr<AlignedRefLogger> p2 = WTFMove(p1);
+        EXPECT_EQ(nullptr, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> p1 = &a;
+        CompactRefPtr<AlignedRefLogger> p2(WTFMove(p1));
+        EXPECT_EQ(nullptr, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<DerivedAlignedRefLogger> p1 = &a;
+        CompactRefPtr<AlignedRefLogger> p2 = WTFMove(p1);
+        EXPECT_EQ(nullptr, p1.get());
+        EXPECT_EQ(&a, p2.get());
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> p1(&a);
+        CompactRefPtr<AlignedRefLogger> p2(&b);
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        log() << "| ";
+        p1 = WTFMove(p2);
+        EXPECT_EQ(&b, p1.get());
+        EXPECT_EQ(nullptr, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(b) | deref(a) | deref(b) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<AlignedRefLogger> p1(&a);
+        CompactRefPtr<DerivedAlignedRefLogger> p2(&c);
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&c, p2.get());
+        log() << "| ";
+        p1 = WTFMove(p2);
+        EXPECT_EQ(&c, p1.get());
+        EXPECT_EQ(nullptr, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(c) | deref(a) | deref(c) ", takeLogStr().c_str());
+}
+
+static CompactRefPtr<AlignedRefLogger> f1(AlignedRefLogger& logger)
+{
+    return CompactRefPtr<AlignedRefLogger>(&logger);
+}
+
+TEST(WTF_CompactRefPtr, ReturnValue)
+{
+    DerivedAlignedRefLogger a("a");
+
+    {
+        f1(a);
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+    {
+        auto ptr = f1(a);
+    }
+    EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+struct alignas(16) ConstRefCounted
+    : RefCounted<ConstRefCounted> {
+    static Ref<ConstRefCounted> create() { return adoptRef(*new ConstRefCounted); }
+};
+
+static const ConstRefCounted& returnConstRefCountedRef()
+{
+    static NeverDestroyed<ConstRefCounted> instance;
+    return instance.get();
+}
+static ConstRefCounted& returnRefCountedRef()
+{
+    static NeverDestroyed<ConstRefCounted> instance;
+    return instance.get();
+}
+
+TEST(WTF_CompactRefPtr, Const)
+{
+    // This test passes if it compiles without an error.
+    auto a = ConstRefCounted::create();
+    Ref<const ConstRefCounted> b = WTFMove(a);
+    CompactRefPtr<const ConstRefCounted> c = b.ptr();
+    Ref<const ConstRefCounted> d = returnConstRefCountedRef();
+    CompactRefPtr<const ConstRefCounted> e = &returnConstRefCountedRef();
+    CompactRefPtr<ConstRefCounted> f = ConstRefCounted::create();
+    CompactRefPtr<const ConstRefCounted> g = f;
+    CompactRefPtr<const ConstRefCounted> h(f);
+    Ref<const ConstRefCounted> i(returnRefCountedRef());
+}
+
+struct CompactRefPtrCheckingAlignedRefLogger : AlignedRefLogger {
+    CompactRefPtrCheckingAlignedRefLogger(const char* name);
+    void ref();
+    void deref();
+    const CompactRefPtr<CompactRefPtrCheckingAlignedRefLogger>* slotToCheck { nullptr };
+};
+
+CompactRefPtrCheckingAlignedRefLogger::CompactRefPtrCheckingAlignedRefLogger(const char* name)
+    : AlignedRefLogger { name }
+{
+}
+
+static const char* loggerName(const CompactRefPtr<CompactRefPtrCheckingAlignedRefLogger>& pointer)
+{
+    return pointer ? &pointer->name : "null";
+}
+
+void CompactRefPtrCheckingAlignedRefLogger::ref()
+{
+    if (slotToCheck)
+        log() << "slot=" << loggerName(*slotToCheck) << " ";
+    AlignedRefLogger::ref();
+}
+
+void CompactRefPtrCheckingAlignedRefLogger::deref()
+{
+    if (slotToCheck)
+        log() << "slot=" << loggerName(*slotToCheck) << " ";
+    AlignedRefLogger::deref();
+}
+
+TEST(WTF_CompactRefPtr, AssignBeforeDeref)
+{
+    CompactRefPtrCheckingAlignedRefLogger a("a");
+    CompactRefPtrCheckingAlignedRefLogger b("b");
+
+    {
+        CompactRefPtr<CompactRefPtrCheckingAlignedRefLogger> p1(&a);
+        CompactRefPtr<CompactRefPtrCheckingAlignedRefLogger> p2(&b);
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        log() << "| ";
+        a.slotToCheck = &p1;
+        b.slotToCheck = &p1;
+        p1 = p2;
+        a.slotToCheck = nullptr;
+        b.slotToCheck = nullptr;
+        EXPECT_EQ(&b, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(b) | slot=a ref(b) slot=b deref(a) | deref(b) deref(b) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<CompactRefPtrCheckingAlignedRefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        log() << "| ";
+        a.slotToCheck = &ptr;
+        b.slotToCheck = &ptr;
+        ptr = &b;
+        a.slotToCheck = nullptr;
+        b.slotToCheck = nullptr;
+        EXPECT_EQ(&b, ptr.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) | slot=a ref(b) slot=b deref(a) | deref(b) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<CompactRefPtrCheckingAlignedRefLogger> ptr(&a);
+        EXPECT_EQ(&a, ptr.get());
+        a.slotToCheck = &ptr;
+        ptr = nullptr;
+        a.slotToCheck = nullptr;
+        EXPECT_EQ(nullptr, ptr.get());
+    }
+    EXPECT_STREQ("ref(a) slot=null deref(a) ", takeLogStr().c_str());
+
+    {
+        CompactRefPtr<CompactRefPtrCheckingAlignedRefLogger> p1(&a);
+        CompactRefPtr<CompactRefPtrCheckingAlignedRefLogger> p2(&b);
+        EXPECT_EQ(&a, p1.get());
+        EXPECT_EQ(&b, p2.get());
+        log() << "| ";
+        a.slotToCheck = &p1;
+        b.slotToCheck = &p1;
+        p1 = WTFMove(p2);
+        a.slotToCheck = nullptr;
+        b.slotToCheck = nullptr;
+        EXPECT_EQ(&b, p1.get());
+        EXPECT_EQ(nullptr, p2.get());
+        log() << "| ";
+    }
+    EXPECT_STREQ("ref(a) ref(b) | slot=b deref(a) | deref(b) ", takeLogStr().c_str());
+}
+
+TEST(WTF_CompactRefPtr, ReleaseNonNullBeforeDeref)
+{
+    CompactRefPtrCheckingAlignedRefLogger a("a");
+
+    {
+        CompactRefPtr<CompactRefPtrCheckingAlignedRefLogger> refPtr = &a;
+        a.slotToCheck = &refPtr;
+        refPtr.releaseNonNull();
+        a.slotToCheck = nullptr;
+    }
+
+    EXPECT_STREQ("ref(a) slot=null deref(a) ", takeLogStr().c_str());
+}
+
+} // namespace TestWebKitAPI

Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/JSONValue.cpp (295007 => 295008)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/JSONValue.cpp	2022-05-29 02:03:33 UTC (rev 295007)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/JSONValue.cpp	2022-05-29 03:23:06 UTC (rev 295008)
@@ -700,7 +700,11 @@
         Ref<JSON::Value> value = JSON::Value::create(makeString("test"_s));
         size_t memoryCost = value->memoryCost();
         EXPECT_GT(memoryCost, 0U);
+#if HAVE(36BIT_ADDRESS)
+        EXPECT_LE(memoryCost, 44U);
+#else
         EXPECT_LE(memoryCost, 36U);
+#endif
     }
 
     {
@@ -707,7 +711,11 @@
         Ref<JSON::Value> value = JSON::Value::create(emptyString());
         size_t memoryCost = value->memoryCost();
         EXPECT_GT(memoryCost, 0U);
+#if HAVE(36BIT_ADDRESS)
+        EXPECT_LE(memoryCost, 40U);
+#else
         EXPECT_LE(memoryCost, 32U);
+#endif
     }
 
     {
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to