Title: [287968] trunk/Source/bmalloc
Revision
287968
Author
fpi...@apple.com
Date
2022-01-12 18:52:00 -0800 (Wed, 12 Jan 2022)

Log Message

[libpas] thread_local_cache should not be allocated in the compact heap (cherry pick 11afcedfb5968f6894379ff1a41dd449ba7745f6)
https://bugs.webkit.org/show_bug.cgi?id=235096

Reviewed by Yusuke Suzuki.

Thread local caches can get quite large because of how libpas uses them, we can allocate one per
thread, and we reallocate them with exponential resizing, so there's a lot of wasted space and a
decent amount of fragmentation. This shows up as occasional crashes trying to allocate a thread local
cache out of the compact heap.

This moves thread local caches out of the compact heap. They were only ever there because partial views
sometimes need to point to the local_allocator's bitvector, but that's part of the thread local cache.
So, that means that either the partial views' bits pointer cannot be a compact pointer, or the
thread_local_cache needs to be in the compact heap. So, the thread_local_cache ended up in the compact
heap to keep that pointer small.

This change works around the problem: it's rare that the partial views' bits pointer points at
the local_allocator's bits, and none of the fast path cases where we access that pointer will ever see
it in that state. So, this makes the pointer either point to a utility-heap-allocated box that contains
the full pointer, or it points at the actual array allocated in the compact heap. The utility heap is
in the compact heap, so the compact pointer can point at either one. The implementation of this is
encapsulated as pas_lenient_compact_ptr. It's a bit gross; storing to it only works when you're holding
the heap lock, for example.

This is perf-neutral on Speedometer. This is perf-neutral on JS2 cli with full JSC isoheaps (i.e. the
patch from bug 231938). It's a 0.4% regression on RAMification with full JSC isoheaps, but I'm not
going to worry about that because trunk doesn't have full JSC isoheaps, and JSC isoheaps requires some
change like this to work reliably (currently it'll randomly run out of compact heap).

* bmalloc.xcodeproj/project.pbxproj:
* libpas/libpas.xcodeproj/project.pbxproj:
* libpas/src/libpas/pas_enumerate_segregated_heaps.c:
(enumerate_partial_view):
* libpas/src/libpas/pas_full_alloc_bits_inlines.h:
(pas_full_alloc_bits_create_for_partial_but_not_primordial):
(pas_full_alloc_bits_create_for_partial):
* libpas/src/libpas/pas_lenient_compact_ptr.h: Added.
* libpas/src/libpas/pas_lenient_compact_ptr_inlines.h: Added.
* libpas/src/libpas/pas_lenient_compact_unsigned_ptr.c: Added.
* libpas/src/libpas/pas_lenient_compact_unsigned_ptr.h: Added.
* libpas/src/libpas/pas_local_allocator.c:
(pas_local_allocator_move):
* libpas/src/libpas/pas_local_allocator_inlines.h:
(pas_local_allocator_set_up_free_bits):
(pas_local_allocator_start_allocating_in_primordial_partial_view):
(pas_local_allocator_bless_primordial_partial_view_before_stopping):
* libpas/src/libpas/pas_segregated_partial_view.c:
(pas_segregated_partial_view_create):
(compute_summary):
* libpas/src/libpas/pas_segregated_partial_view.h:
* libpas/src/libpas/pas_segregated_view_allocator_inlines.h:
(pas_segregated_view_will_start_allocating):
* libpas/src/libpas/pas_thread_local_cache.c:
(deallocate):
(allocate_cache):
* libpas/src/test/LotsOfHeapsAndThreads.cpp: Added.
(std::testLotsOfHeapsAndThreads):
(addLotsOfHeapsAndThreadsTests):
* libpas/src/test/TestHarness.cpp:
(main):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/bmalloc/ChangeLog (287967 => 287968)


--- trunk/Source/bmalloc/ChangeLog	2022-01-13 02:17:09 UTC (rev 287967)
+++ trunk/Source/bmalloc/ChangeLog	2022-01-13 02:52:00 UTC (rev 287968)
@@ -1,3 +1,66 @@
+2022-01-12  Filip Pizlo  <fpi...@apple.com>
+
+        [libpas] thread_local_cache should not be allocated in the compact heap (cherry pick 11afcedfb5968f6894379ff1a41dd449ba7745f6)
+        https://bugs.webkit.org/show_bug.cgi?id=235096
+
+        Reviewed by Yusuke Suzuki.
+
+        Thread local caches can get quite large because of how libpas uses them, we can allocate one per
+        thread, and we reallocate them with exponential resizing, so there's a lot of wasted space and a
+        decent amount of fragmentation. This shows up as occasional crashes trying to allocate a thread local
+        cache out of the compact heap.
+
+        This moves thread local caches out of the compact heap. They were only ever there because partial views
+        sometimes need to point to the local_allocator's bitvector, but that's part of the thread local cache.
+        So, that means that either the partial views' bits pointer cannot be a compact pointer, or the
+        thread_local_cache needs to be in the compact heap. So, the thread_local_cache ended up in the compact
+        heap to keep that pointer small.
+
+        This change works around the problem: it's rare that the partial views' bits pointer points at
+        the local_allocator's bits, and none of the fast path cases where we access that pointer will ever see
+        it in that state. So, this makes the pointer either point to a utility-heap-allocated box that contains
+        the full pointer, or it points at the actual array allocated in the compact heap. The utility heap is
+        in the compact heap, so the compact pointer can point at either one. The implementation of this is
+        encapsulated as pas_lenient_compact_ptr. It's a bit gross; storing to it only works when you're holding
+        the heap lock, for example.
+
+        This is perf-neutral on Speedometer. This is perf-neutral on JS2 cli with full JSC isoheaps (i.e. the
+        patch from bug 231938). It's a 0.4% regression on RAMification with full JSC isoheaps, but I'm not
+        going to worry about that because trunk doesn't have full JSC isoheaps, and JSC isoheaps requires some
+        change like this to work reliably (currently it'll randomly run out of compact heap).
+
+        * bmalloc.xcodeproj/project.pbxproj:
+        * libpas/libpas.xcodeproj/project.pbxproj:
+        * libpas/src/libpas/pas_enumerate_segregated_heaps.c:
+        (enumerate_partial_view):
+        * libpas/src/libpas/pas_full_alloc_bits_inlines.h:
+        (pas_full_alloc_bits_create_for_partial_but_not_primordial):
+        (pas_full_alloc_bits_create_for_partial):
+        * libpas/src/libpas/pas_lenient_compact_ptr.h: Added.
+        * libpas/src/libpas/pas_lenient_compact_ptr_inlines.h: Added.
+        * libpas/src/libpas/pas_lenient_compact_unsigned_ptr.c: Added.
+        * libpas/src/libpas/pas_lenient_compact_unsigned_ptr.h: Added.
+        * libpas/src/libpas/pas_local_allocator.c:
+        (pas_local_allocator_move):
+        * libpas/src/libpas/pas_local_allocator_inlines.h:
+        (pas_local_allocator_set_up_free_bits):
+        (pas_local_allocator_start_allocating_in_primordial_partial_view):
+        (pas_local_allocator_bless_primordial_partial_view_before_stopping):
+        * libpas/src/libpas/pas_segregated_partial_view.c:
+        (pas_segregated_partial_view_create):
+        (compute_summary):
+        * libpas/src/libpas/pas_segregated_partial_view.h:
+        * libpas/src/libpas/pas_segregated_view_allocator_inlines.h:
+        (pas_segregated_view_will_start_allocating):
+        * libpas/src/libpas/pas_thread_local_cache.c:
+        (deallocate):
+        (allocate_cache):
+        * libpas/src/test/LotsOfHeapsAndThreads.cpp: Added.
+        (std::testLotsOfHeapsAndThreads):
+        (addLotsOfHeapsAndThreadsTests):
+        * libpas/src/test/TestHarness.cpp:
+        (main):
+
 2022-01-12  Elliott Williams  <e...@apple.com>
 
         [Xcode] Configure each project for the legacy build system

Modified: trunk/Source/bmalloc/bmalloc.xcodeproj/project.pbxproj (287967 => 287968)


--- trunk/Source/bmalloc/bmalloc.xcodeproj/project.pbxproj	2022-01-13 02:17:09 UTC (rev 287967)
+++ trunk/Source/bmalloc/bmalloc.xcodeproj/project.pbxproj	2022-01-13 02:52:00 UTC (rev 287968)
@@ -616,6 +616,10 @@
 		2C48134427406A3E006CAB55 /* pas_expendable_memory.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C48133E27406A3E006CAB55 /* pas_expendable_memory.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2C48134527406A3E006CAB55 /* pas_large_expendable_memory.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C48133F27406A3E006CAB55 /* pas_large_expendable_memory.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2C91E552271CE47A00D67FF9 /* pas_size_lookup_mode.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C91E551271CE47A00D67FF9 /* pas_size_lookup_mode.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		2C971D04278E798700C9E129 /* pas_lenient_compact_ptr_inlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C971D00278E798700C9E129 /* pas_lenient_compact_ptr_inlines.h */; };
+		2C971D05278E798700C9E129 /* pas_lenient_compact_ptr.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C971D01278E798700C9E129 /* pas_lenient_compact_ptr.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		2C971D06278E798700C9E129 /* pas_lenient_compact_unsigned_ptr.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C971D02278E798700C9E129 /* pas_lenient_compact_unsigned_ptr.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		2C971D07278E798700C9E129 /* pas_lenient_compact_unsigned_ptr.c in Sources */ = {isa = PBXBuildFile; fileRef = 2C971D03278E798700C9E129 /* pas_lenient_compact_unsigned_ptr.c */; };
 		2CE2AE2D27596DEB00D02BBC /* pas_segregated_page_role.h in Headers */ = {isa = PBXBuildFile; fileRef = 2CE2AE2627596DEA00D02BBC /* pas_segregated_page_role.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2CE2AE2E27596DEB00D02BBC /* pas_page_base_and_kind.h in Headers */ = {isa = PBXBuildFile; fileRef = 2CE2AE2727596DEA00D02BBC /* pas_page_base_and_kind.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		2CE2AE2F27596DEB00D02BBC /* pas_page_base_config.c in Sources */ = {isa = PBXBuildFile; fileRef = 2CE2AE2827596DEA00D02BBC /* pas_page_base_config.c */; };
@@ -1275,6 +1279,10 @@
 		2C48133E27406A3E006CAB55 /* pas_expendable_memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pas_expendable_memory.h; path = libpas/src/libpas/pas_expendable_memory.h; sourceTree = "<group>"; };
 		2C48133F27406A3E006CAB55 /* pas_large_expendable_memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pas_large_expendable_memory.h; path = libpas/src/libpas/pas_large_expendable_memory.h; sourceTree = "<group>"; };
 		2C91E551271CE47A00D67FF9 /* pas_size_lookup_mode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pas_size_lookup_mode.h; path = libpas/src/libpas/pas_size_lookup_mode.h; sourceTree = "<group>"; };
+		2C971D00278E798700C9E129 /* pas_lenient_compact_ptr_inlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pas_lenient_compact_ptr_inlines.h; path = libpas/src/libpas/pas_lenient_compact_ptr_inlines.h; sourceTree = "<group>"; };
+		2C971D01278E798700C9E129 /* pas_lenient_compact_ptr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pas_lenient_compact_ptr.h; path = libpas/src/libpas/pas_lenient_compact_ptr.h; sourceTree = "<group>"; };
+		2C971D02278E798700C9E129 /* pas_lenient_compact_unsigned_ptr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pas_lenient_compact_unsigned_ptr.h; path = libpas/src/libpas/pas_lenient_compact_unsigned_ptr.h; sourceTree = "<group>"; };
+		2C971D03278E798700C9E129 /* pas_lenient_compact_unsigned_ptr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pas_lenient_compact_unsigned_ptr.c; path = libpas/src/libpas/pas_lenient_compact_unsigned_ptr.c; sourceTree = "<group>"; };
 		2CE2AE2627596DEA00D02BBC /* pas_segregated_page_role.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pas_segregated_page_role.h; path = libpas/src/libpas/pas_segregated_page_role.h; sourceTree = "<group>"; };
 		2CE2AE2727596DEA00D02BBC /* pas_page_base_and_kind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pas_page_base_and_kind.h; path = libpas/src/libpas/pas_page_base_and_kind.h; sourceTree = "<group>"; };
 		2CE2AE2827596DEA00D02BBC /* pas_page_base_config.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pas_page_base_config.c; path = libpas/src/libpas/pas_page_base_config.c; sourceTree = "<group>"; };
@@ -1701,6 +1709,10 @@
 				0FC40A1D2451498400876DA0 /* pas_large_sharing_pool.h */,
 				0FC40AA32451498E00876DA0 /* pas_large_utility_free_heap.c */,
 				0FC40AF12451499300876DA0 /* pas_large_utility_free_heap.h */,
+				2C971D00278E798700C9E129 /* pas_lenient_compact_ptr_inlines.h */,
+				2C971D01278E798700C9E129 /* pas_lenient_compact_ptr.h */,
+				2C971D03278E798700C9E129 /* pas_lenient_compact_unsigned_ptr.c */,
+				2C971D02278E798700C9E129 /* pas_lenient_compact_unsigned_ptr.h */,
 				0F8A812425F83E2400790B4A /* pas_line_word_config.h */,
 				0FC40A7D2451498B00876DA0 /* pas_list_direction.h */,
 				0FC40A4C2451498800876DA0 /* pas_local_allocator_config_kind.h */,
@@ -2179,6 +2191,7 @@
 				0F7EB82D1F9541B000F1ABCB /* IsoTLSEntry.h in Headers */,
 				0F7EB8351F9541B000F1ABCB /* IsoTLSEntryInlines.h in Headers */,
 				0F7EB8461F9541B000F1ABCB /* IsoTLSInlines.h in Headers */,
+				2C971D04278E798700C9E129 /* pas_lenient_compact_ptr_inlines.h in Headers */,
 				0F7EB8401F9541B000F1ABCB /* IsoTLSLayout.h in Headers */,
 				0F5193EF266C42AD00483A2C /* jit_heap.h in Headers */,
 				0F5193EE266C42AD00483A2C /* jit_heap_config.h in Headers */,
@@ -2186,6 +2199,7 @@
 				144C07F51C7B70260051BB6A /* LargeMap.h in Headers */,
 				14C8992D1CC578330027A057 /* LargeRange.h in Headers */,
 				140FA00519CE4B6800FFD3C8 /* LineMetadata.h in Headers */,
+				2C971D06278E798700C9E129 /* pas_lenient_compact_unsigned_ptr.h in Headers */,
 				141D9B001C8E51C0000ABBA0 /* List.h in Headers */,
 				4426E2811C838EE0008EB042 /* Logging.h in Headers */,
 				14C8992B1CC485E70027A057 /* Map.h in Headers */,
@@ -2312,6 +2326,7 @@
 				0FC409EA2451496400876DA0 /* pas_ensure_heap_forced_into_reserved_memory.h in Headers */,
 				0FC409E92451496400876DA0 /* pas_ensure_heap_with_page_caches.h in Headers */,
 				0F87002C25AF89C9000E1ABF /* pas_enumerable_page_malloc.h in Headers */,
+				2C971D05278E798700C9E129 /* pas_lenient_compact_ptr.h in Headers */,
 				0F87002E25AF89C9000E1ABF /* pas_enumerable_range_list.h in Headers */,
 				0F87FFEC25AF897C000E1ABF /* pas_enumerate_bitfit_heaps.h in Headers */,
 				0F87000A25AF897C000E1ABF /* pas_enumerate_initially_unaccounted_pages.h in Headers */,
@@ -2683,6 +2698,7 @@
 				14F271C818EA3990008C152F /* ObjectType.cpp in Sources */,
 				E378A9DF246B68720029C2BB /* ObjectTypeTable.cpp in Sources */,
 				0F18F84725C3467700721C2A /* pagesize64k_heap.c in Sources */,
+				2C971D07278E798700C9E129 /* pas_lenient_compact_unsigned_ptr.c in Sources */,
 				0F18F84925C3467700721C2A /* pagesize64k_heap_config.c in Sources */,
 				0FC4095D2451494400876DA0 /* pas_alignment.c in Sources */,
 				0FC409642451494400876DA0 /* pas_all_heaps.c in Sources */,

Modified: trunk/Source/bmalloc/libpas/libpas.xcodeproj/project.pbxproj (287967 => 287968)


--- trunk/Source/bmalloc/libpas/libpas.xcodeproj/project.pbxproj	2022-01-13 02:17:09 UTC (rev 287967)
+++ trunk/Source/bmalloc/libpas/libpas.xcodeproj/project.pbxproj	2022-01-13 02:52:00 UTC (rev 287968)
@@ -571,6 +571,11 @@
 		2C48132D273F4159006CAB55 /* ExpendableMemoryTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2C48132C273F4159006CAB55 /* ExpendableMemoryTests.cpp */; };
 		2C85DC4127128F0F00367905 /* pas_try_allocate_intrinsic.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C85DC4027128F0F00367905 /* pas_try_allocate_intrinsic.h */; };
 		2C91E5502718DA9A00D67FF9 /* pas_size_lookup_mode.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C91E54F2718DA9A00D67FF9 /* pas_size_lookup_mode.h */; };
+		2C971CFA278E11C300C9E129 /* pas_lenient_compact_ptr.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C971CF8278E11C300C9E129 /* pas_lenient_compact_ptr.h */; };
+		2C971CFB278E11C300C9E129 /* pas_lenient_compact_unsigned_ptr.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C971CF9278E11C300C9E129 /* pas_lenient_compact_unsigned_ptr.h */; };
+		2C971CFE278E136300C9E129 /* pas_lenient_compact_unsigned_ptr.c in Sources */ = {isa = PBXBuildFile; fileRef = 2C971CFC278E136300C9E129 /* pas_lenient_compact_unsigned_ptr.c */; };
+		2C971CFF278E136300C9E129 /* pas_lenient_compact_ptr_inlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C971CFD278E136300C9E129 /* pas_lenient_compact_ptr_inlines.h */; };
+		2CB9B153278F6C85003A8C1B /* LotsOfHeapsAndThreads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2CB9B152278F6C85003A8C1B /* LotsOfHeapsAndThreads.cpp */; };
 		2CE2AE35275A953E00D02BBC /* BitfitTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2CE2AE34275A953E00D02BBC /* BitfitTests.cpp */; };
 /* End PBXBuildFile section */
 
@@ -1259,6 +1264,11 @@
 		2C48132C273F4159006CAB55 /* ExpendableMemoryTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExpendableMemoryTests.cpp; sourceTree = "<group>"; };
 		2C85DC4027128F0F00367905 /* pas_try_allocate_intrinsic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pas_try_allocate_intrinsic.h; sourceTree = "<group>"; };
 		2C91E54F2718DA9A00D67FF9 /* pas_size_lookup_mode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pas_size_lookup_mode.h; sourceTree = "<group>"; };
+		2C971CF8278E11C300C9E129 /* pas_lenient_compact_ptr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pas_lenient_compact_ptr.h; sourceTree = "<group>"; };
+		2C971CF9278E11C300C9E129 /* pas_lenient_compact_unsigned_ptr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pas_lenient_compact_unsigned_ptr.h; sourceTree = "<group>"; };
+		2C971CFC278E136300C9E129 /* pas_lenient_compact_unsigned_ptr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pas_lenient_compact_unsigned_ptr.c; sourceTree = "<group>"; };
+		2C971CFD278E136300C9E129 /* pas_lenient_compact_ptr_inlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pas_lenient_compact_ptr_inlines.h; sourceTree = "<group>"; };
+		2CB9B152278F6C85003A8C1B /* LotsOfHeapsAndThreads.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LotsOfHeapsAndThreads.cpp; sourceTree = "<group>"; };
 		2CE2AE34275A953E00D02BBC /* BitfitTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BitfitTests.cpp; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
@@ -1354,7 +1364,6 @@
 				0FDEA45D228B651B0085E340 /* BitfieldVectorTests.cpp */,
 				2CE2AE34275A953E00D02BBC /* BitfitTests.cpp */,
 				0F53181022C954ED003F7B6A /* BitvectorTests.cpp */,
-				2B2A589B2742D815005EE07C /* PGMTests.cpp */,
 				0F31A66723E8B336002C0CA3 /* CartesianTreeTests.cpp */,
 				0FC682362129D4EB003C6A13 /* CoalignTests.cpp */,
 				2C48132C273F4159006CAB55 /* ExpendableMemoryTests.cpp */,
@@ -1368,13 +1377,14 @@
 				0FD48B6623B589910026C46D /* IsoHeapPartialAndBaselineTests.cpp */,
 				0F5B6093235E919900CAE629 /* IsoHeapReservedMemoryTests.cpp */,
 				0F5193E6266AE5D400483A2C /* JITHeapTests.cpp */,
-				2B8BCAC62739A47900B1A46F /* PGMTests.cpp */,
 				0FC64190213745FA0040CE5E /* LargeFreeHeapTests.cpp */,
 				0FEB6666231C87BC009C001B /* LargeSharingPoolDump.cpp */,
 				0FEB6667231C87BC009C001B /* LargeSharingPoolDump.h */,
 				0FEB6669231DA86F009C001B /* LargeSharingPoolTests.cpp */,
 				0FEA45BE236CDAED00B5A375 /* LockFreeReadPtrPtrHashtableTests.cpp */,
+				2CB9B152278F6C85003A8C1B /* LotsOfHeapsAndThreads.cpp */,
 				0FD22D0722CD8A7500B21841 /* MinHeapTests.cpp */,
+				2B2A589B2742D815005EE07C /* PGMTests.cpp */,
 				0F5E483923D69F610046DA5C /* RaceTests.cpp */,
 				0FF08F3522A59DB300386575 /* RedBlackTreeTests.cpp */,
 				0FDE52552342B7C400A0808F /* SuspendScavenger.h */,
@@ -1410,8 +1420,6 @@
 				0F5FE7A325B614F2001859FC /* iso_heap_inlines.h */,
 				0F516EE624561A60004E2B8D /* iso_heap_innards.h */,
 				0F529DDE2455460C00385A8C /* iso_heap_ref.h */,
-				2B2A58982742D802005EE07C /* pas_probabilistic_guard_malloc_allocator.c */,
-				2B2A58972742D802005EE07C /* pas_probabilistic_guard_malloc_allocator.h */,
 				0FE7EE74229F010F004F4166 /* iso_heap.c */,
 				0FE7EE75229F010F004F4166 /* iso_heap.h */,
 				0F5E5CE823BEF35F00AA0B6F /* iso_test_heap_config.c */,
@@ -1685,6 +1693,10 @@
 				0FCFA498238352EB00CCD726 /* pas_large_sharing_pool.h */,
 				0F6D547523C573E000F40DBB /* pas_large_utility_free_heap.c */,
 				0F6D547223C573E000F40DBB /* pas_large_utility_free_heap.h */,
+				2C971CFD278E136300C9E129 /* pas_lenient_compact_ptr_inlines.h */,
+				2C971CF8278E11C300C9E129 /* pas_lenient_compact_ptr.h */,
+				2C971CFC278E136300C9E129 /* pas_lenient_compact_unsigned_ptr.c */,
+				2C971CF9278E11C300C9E129 /* pas_lenient_compact_unsigned_ptr.h */,
 				0F8A802725EC588800790B4A /* pas_line_word_config.h */,
 				0F31A64323E3509E002C0CA3 /* pas_list_direction.h */,
 				0FD48B0223A9ABB00026C46D /* pas_local_allocator_config_kind.h */,
@@ -1742,13 +1754,13 @@
 				0FD22CFD22CC01D300B21841 /* pas_page_sharing_pool.h */,
 				0F4F61C925A4CD3B008B4A82 /* pas_payload_reservation_page_list.c */,
 				0F4F61C825A4CD3B008B4A82 /* pas_payload_reservation_page_list.h */,
-				2B8BCAC32739A45900B1A46F /* pas_probabilistic_guard_malloc_allocator.c */,
-				2B8BCAC22739A45900B1A46F /* pas_probabilistic_guard_malloc_allocator.h */,
 				0F6D547323C573E000F40DBB /* pas_physical_memory_synchronization_style.h */,
 				0FF248F722FC9EDA0077202E /* pas_physical_memory_transaction.c */,
 				0F78088622FA2E4900F37451 /* pas_physical_memory_transaction.h */,
 				0FDEA578228E23450085E340 /* pas_primitive_heap_ref.c */,
 				0FDEA577228E23440085E340 /* pas_primitive_heap_ref.h */,
+				2B2A58982742D802005EE07C /* pas_probabilistic_guard_malloc_allocator.c */,
+				2B2A58972742D802005EE07C /* pas_probabilistic_guard_malloc_allocator.h */,
 				0F9A1CAD2559961300C8D11B /* pas_promote_intrinsic_heap.h */,
 				0F4F615A259BF6EC008B4A82 /* pas_ptr_hash_map.h */,
 				0F4F6146259BB109008B4A82 /* pas_ptr_hash_set.h */,
@@ -2050,6 +2062,7 @@
 				0F9A1D41255AF27900C8D11B /* pas_bitfit_view_inlines.h in Headers */,
 				0FE7EE0422960142004F4166 /* pas_bitvector.h in Headers */,
 				0FE7EE0522960142004F4166 /* pas_bootstrap_free_heap.h in Headers */,
+				2C971CFB278E11C300C9E129 /* pas_lenient_compact_unsigned_ptr.h in Headers */,
 				0F5B6084235E572000CAE629 /* pas_bootstrap_heap_page_provider.h in Headers */,
 				0FE7EE0822960142004F4166 /* pas_cares_about_size_mode.h in Headers */,
 				0F31A66623E8A942002C0CA3 /* pas_cartesian_tree.h in Headers */,
@@ -2146,6 +2159,7 @@
 				0FD48B5823A9ABB30026C46D /* pas_full_alloc_bits.h in Headers */,
 				0FD48B3A23A9ABB30026C46D /* pas_full_alloc_bits_inlines.h in Headers */,
 				0FF08F3A22A5B40300386575 /* pas_generic_large_free_heap.h in Headers */,
+				2C971CFA278E11C300C9E129 /* pas_lenient_compact_ptr.h in Headers */,
 				0FE7EE60229E14FA004F4166 /* pas_get_allocation_size.h in Headers */,
 				0FE7EE64229E14FA004F4166 /* pas_get_heap.h in Headers */,
 				0F9A1D4D255F2CD700C8D11B /* pas_get_object_kind.h in Headers */,
@@ -2253,6 +2267,7 @@
 				0F4F60FB25979BC8008B4A82 /* pas_root.h in Headers */,
 				0F19326C22F73E8500FBA713 /* pas_scavenger.h in Headers */,
 				0F68127222BD4BF40036A02B /* pas_segmented_vector.h in Headers */,
+				2C971CFF278E136300C9E129 /* pas_lenient_compact_ptr_inlines.h in Headers */,
 				0F148710269B7518006887A9 /* pas_segregated_deallocation_mode.h in Headers */,
 				0FD48B5623A9ABB30026C46D /* pas_segregated_directory.h in Headers */,
 				0FD48B4723A9ABB30026C46D /* pas_segregated_directory_bit_reference.h in Headers */,
@@ -2599,6 +2614,7 @@
 				0FA18546236B3C82003609AD /* IsoHeapChaosTests.cpp in Sources */,
 				0FF248FD230CC4CB0077202E /* IsoHeapPageSharingTests.cpp in Sources */,
 				0FD48B6723B589910026C46D /* IsoHeapPartialAndBaselineTests.cpp in Sources */,
+				2CB9B153278F6C85003A8C1B /* LotsOfHeapsAndThreads.cpp in Sources */,
 				0F5B6094235E919900CAE629 /* IsoHeapReservedMemoryTests.cpp in Sources */,
 				2CE2AE35275A953E00D02BBC /* BitfitTests.cpp in Sources */,
 				0F5193E7266AE5D400483A2C /* JITHeapTests.cpp in Sources */,
@@ -2681,6 +2697,7 @@
 				0F4F611B259838B1008B4A82 /* pas_enumerator_region.c in Sources */,
 				0F19325622ED04A600FBA713 /* pas_epoch.c in Sources */,
 				0FD48B3423A9ABB30026C46D /* pas_exclusive_view_template_memo_table.c in Sources */,
+				2C971CFE278E136300C9E129 /* pas_lenient_compact_unsigned_ptr.c in Sources */,
 				2C481328273F341A006CAB55 /* pas_expendable_memory.c in Sources */,
 				0FE7EDBA22960142004F4166 /* pas_extended_gcd.c in Sources */,
 				0FF08F4322A627C100386575 /* pas_fast_large_free_heap.c in Sources */,

Modified: trunk/Source/bmalloc/libpas/src/libpas/pas_enumerate_segregated_heaps.c (287967 => 287968)


--- trunk/Source/bmalloc/libpas/src/libpas/pas_enumerate_segregated_heaps.c	2022-01-13 02:17:09 UTC (rev 287967)
+++ trunk/Source/bmalloc/libpas/src/libpas/pas_enumerate_segregated_heaps.c	2022-01-13 02:52:00 UTC (rev 287968)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020-2021 Apple Inc. All rights reserved.
+ * Copyright (c) 2020-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
@@ -515,7 +515,11 @@
     if (verbose)
         pas_log("Found allocator = %p\n", allocator);
 
-    full_alloc_bits.bits = pas_compact_tagged_unsigned_ptr_load_remote(enumerator, &view->alloc_bits);
+    /* This is so weird: the size we pass is only valid when view->alloc_bits is pointing at the
+       local_allocator's bits. But that's the only time that load_remote will go down the path where it needs
+       to know the size. So, it's fine, I guess. */
+    full_alloc_bits.bits = pas_lenient_compact_unsigned_ptr_load_remote(
+        enumerator, &view->alloc_bits, pas_segregated_page_config_num_alloc_bytes(*page_config));
     full_alloc_bits.word_index_begin = view->alloc_bits_offset;
     full_alloc_bits.word_index_end = view->alloc_bits_offset + view->alloc_bits_size;
     record_page_objects(

Modified: trunk/Source/bmalloc/libpas/src/libpas/pas_full_alloc_bits_inlines.h (287967 => 287968)


--- trunk/Source/bmalloc/libpas/src/libpas/pas_full_alloc_bits_inlines.h	2022-01-13 02:17:09 UTC (rev 287967)
+++ trunk/Source/bmalloc/libpas/src/libpas/pas_full_alloc_bits_inlines.h	2022-01-13 02:52:00 UTC (rev 287968)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020 Apple Inc. All rights reserved.
+ * Copyright (c) 2019-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
@@ -49,6 +49,19 @@
 }
 
 static PAS_ALWAYS_INLINE pas_full_alloc_bits
+pas_full_alloc_bits_create_for_partial_but_not_primordial(pas_segregated_view view)
+{
+    pas_segregated_partial_view* partial_view;
+    
+    partial_view = pas_segregated_view_get_partial(view);
+
+    return pas_full_alloc_bits_create(
+        pas_lenient_compact_unsigned_ptr_load_compact_non_null(&partial_view->alloc_bits),
+        partial_view->alloc_bits_offset,
+        partial_view->alloc_bits_offset + partial_view->alloc_bits_size);
+}
+
+static PAS_ALWAYS_INLINE pas_full_alloc_bits
 pas_full_alloc_bits_create_for_partial(pas_segregated_view view)
 {
     pas_segregated_partial_view* partial_view;
@@ -56,7 +69,7 @@
     partial_view = pas_segregated_view_get_partial(view);
 
     return pas_full_alloc_bits_create(
-        pas_compact_tagged_unsigned_ptr_load_non_null(&partial_view->alloc_bits),
+        pas_lenient_compact_unsigned_ptr_load(&partial_view->alloc_bits),
         partial_view->alloc_bits_offset,
         partial_view->alloc_bits_offset + partial_view->alloc_bits_size);
 }

Added: trunk/Source/bmalloc/libpas/src/libpas/pas_lenient_compact_ptr.h (0 => 287968)


--- trunk/Source/bmalloc/libpas/src/libpas/pas_lenient_compact_ptr.h	                        (rev 0)
+++ trunk/Source/bmalloc/libpas/src/libpas/pas_lenient_compact_ptr.h	2022-01-13 02:52:00 UTC (rev 287968)
@@ -0,0 +1,80 @@
+/*
+ * 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. 
+ */
+
+#ifndef PAS_LENIENT_COMPACT_PTR_H
+#define PAS_LENIENT_COMPACT_PTR_H
+
+#include "pas_compact_tagged_atomic_ptr.h"
+
+PAS_BEGIN_EXTERN_C;
+
+/* You can use this pointer to point at something that is likely to be in the compact heap but that
+   sometimes won't be. To make this work, it's necessary to be able to destruct the pointer, and it's
+   not legal to pass the pointer around by value. Also, the thing being pointed to must have the lowest
+   bit available (i.e. that bit must always be zero). */
+
+#define PAS_LENIENT_COMPACT_PTR_INITIALIZER { .ptr = PAS_COMPACT_TAGGED_ATOMIC_PTR_INITIALIZER }
+
+#define PAS_LENIENT_COMPACT_PTR_FULL_PTR_BIT ((uintptr_t)1)
+
+#define PAS_DECLARE_LENIENT_COMPACT_PTR(type, name) \
+    \
+    PAS_DEFINE_COMPACT_TAGGED_ATOMIC_PTR(type*, name ## _compact_tagged_atomic_ptr); \
+    \
+    struct name; \
+    typedef struct name name; \
+    \
+    struct name { \
+        name ## _compact_tagged_atomic_ptr ptr; \
+    }; \
+    \
+    PAS_API void name ## _destruct(name* ptr); \
+    PAS_API void name ## _store(name* ptr, type* value); \
+    PAS_API type* name ## _load(name* ptr); \
+    \
+    static inline type* name ## _load_compact(name* ptr) \
+    { \
+        type* result; \
+        result = name ## _compact_tagged_atomic_ptr_load(&ptr->ptr); \
+        PAS_TESTING_ASSERT(!((uintptr_t)result & PAS_LENIENT_COMPACT_PTR_FULL_PTR_BIT)); \
+        return result; \
+    } \
+    \
+    static inline type* name ## _load_compact_non_null(name* ptr) \
+    { \
+        type* result; \
+        result = name ## _compact_tagged_atomic_ptr_load_non_null(&ptr->ptr); \
+        PAS_TESTING_ASSERT(!((uintptr_t)result & PAS_LENIENT_COMPACT_PTR_FULL_PTR_BIT)); \
+        return result; \
+    } \
+    \
+    PAS_API type* name ## _load_remote(pas_enumerator* enumerator, name* ptr, size_t size); \
+    \
+    struct pas_dummy
+
+PAS_END_EXTERN_C;
+
+#endif /* PAS_LENIENT_COMPACT_PTR_H */
+

Added: trunk/Source/bmalloc/libpas/src/libpas/pas_lenient_compact_ptr_inlines.h (0 => 287968)


--- trunk/Source/bmalloc/libpas/src/libpas/pas_lenient_compact_ptr_inlines.h	                        (rev 0)
+++ trunk/Source/bmalloc/libpas/src/libpas/pas_lenient_compact_ptr_inlines.h	2022-01-13 02:52:00 UTC (rev 287968)
@@ -0,0 +1,86 @@
+/*
+ * 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. 
+ */
+
+#ifndef PAS_LENIENT_COMPACT_PTR_INLINES_H
+#define PAS_LENIENT_COMPACT_PTR_INLINES_H
+
+#include "pas_lenient_compact_ptr.h"
+#include "pas_utility_heap.h"
+
+PAS_BEGIN_EXTERN_C;
+
+#define PAS_DEFINE_LENIENT_COMPACT_PTR(type, name) \
+    void name ## _destruct(name* ptr) \
+    { \
+        type* old_value; \
+        old_value = name ## _compact_tagged_atomic_ptr_load(&ptr->ptr); \
+        if ((uintptr_t)old_value & PAS_LENIENT_COMPACT_PTR_FULL_PTR_BIT) { \
+            pas_utility_heap_deallocate( \
+                (void*)((uintptr_t)old_value & ~PAS_LENIENT_COMPACT_PTR_FULL_PTR_BIT)); \
+        } \
+    } \
+    \
+    void name ## _store(name* ptr, type* value) \
+    { \
+        PAS_TESTING_ASSERT(!((uintptr_t)value & PAS_LENIENT_COMPACT_PTR_FULL_PTR_BIT)); \
+        name ## _destruct(ptr); \
+        if ((uintptr_t)value >= PAS_INTERNAL_MIN_ALIGN \
+            && (uintptr_t)value - pas_compact_heap_reservation_base >= pas_compact_heap_reservation_size) { \
+            type** box; \
+            box = pas_utility_heap_allocate(sizeof(type*), #name "/box"); \
+            *box = value; \
+            value = (type*)((uintptr_t)box | PAS_LENIENT_COMPACT_PTR_FULL_PTR_BIT); \
+        } \
+        name ## _compact_tagged_atomic_ptr_store(&ptr->ptr, value); \
+    } \
+    \
+    type* name ## _load(name* ptr) \
+    { \
+        type* result; \
+        result = name ## _compact_tagged_atomic_ptr_load(&ptr->ptr); \
+        if ((uintptr_t)result & PAS_LENIENT_COMPACT_PTR_FULL_PTR_BIT) \
+            return *(type**)((uintptr_t)result & ~PAS_LENIENT_COMPACT_PTR_FULL_PTR_BIT); \
+        return result; \
+    } \
+    \
+    type* name ## _load_remote(pas_enumerator* enumerator, name* ptr, size_t size) \
+    { \
+        type* result; \
+        result = name ## _compact_tagged_atomic_ptr_load_remote(enumerator, &ptr->ptr); \
+        if ((uintptr_t)result & PAS_LENIENT_COMPACT_PTR_FULL_PTR_BIT) { \
+            return (type*)pas_enumerator_read( \
+                enumerator, \
+                *(type**)((uintptr_t)result & ~PAS_LENIENT_COMPACT_PTR_FULL_PTR_BIT), \
+                size); \
+        } \
+        return result; \
+    } \
+    \
+    struct pas_dummy
+
+PAS_END_EXTERN_C;
+
+#endif /* PAS_LENIENT_COMPACT_PTR_INLINES_H */
+

Added: trunk/Source/bmalloc/libpas/src/libpas/pas_lenient_compact_unsigned_ptr.c (0 => 287968)


--- trunk/Source/bmalloc/libpas/src/libpas/pas_lenient_compact_unsigned_ptr.c	                        (rev 0)
+++ trunk/Source/bmalloc/libpas/src/libpas/pas_lenient_compact_unsigned_ptr.c	2022-01-13 02:52:00 UTC (rev 287968)
@@ -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. 
+ */
+
+#include "pas_config.h"
+
+#if LIBPAS_ENABLED
+
+#include "pas_lenient_compact_unsigned_ptr.h"
+
+#include "pas_lenient_compact_ptr_inlines.h"
+
+PAS_DEFINE_LENIENT_COMPACT_PTR(unsigned, pas_lenient_compact_unsigned_ptr);
+
+#endif /* LIBPAS_ENABLED */
+
+

Added: trunk/Source/bmalloc/libpas/src/libpas/pas_lenient_compact_unsigned_ptr.h (0 => 287968)


--- trunk/Source/bmalloc/libpas/src/libpas/pas_lenient_compact_unsigned_ptr.h	                        (rev 0)
+++ trunk/Source/bmalloc/libpas/src/libpas/pas_lenient_compact_unsigned_ptr.h	2022-01-13 02:52:00 UTC (rev 287968)
@@ -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. 
+ */
+
+#ifndef PAS_LENIENT_COMPACT_UNSIGNED_PTR_H
+#define PAS_LENIENT_COMPACT_UNSIGNED_PTR_H
+
+#include "pas_lenient_compact_ptr.h"
+
+PAS_BEGIN_EXTERN_C;
+
+PAS_DECLARE_LENIENT_COMPACT_PTR(unsigned, pas_lenient_compact_unsigned_ptr);
+
+PAS_END_EXTERN_C;
+
+#endif /* PAS_LENIENT_COMPACT_UNSIGNED_PTR_H */
+

Modified: trunk/Source/bmalloc/libpas/src/libpas/pas_local_allocator.c (287967 => 287968)


--- trunk/Source/bmalloc/libpas/src/libpas/pas_local_allocator.c	2022-01-13 02:17:09 UTC (rev 287967)
+++ trunk/Source/bmalloc/libpas/src/libpas/pas_local_allocator.c	2022-01-13 02:52:00 UTC (rev 287968)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2021 Apple Inc. All rights reserved.
+ * Copyright (c) 2018-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
@@ -118,6 +118,8 @@
     pas_segregated_partial_view* partial_view;
     pas_segregated_shared_view* shared_view;
 
+    pas_heap_lock_assert_held(); /* Needed to modify a lenient_compact_ptr. */
+
     directory = pas_segregated_view_get_size_directory(src->view);
     
     size = pas_segregated_size_directory_local_allocator_size(directory);
@@ -135,8 +137,8 @@
        is the only client of partial_view->alloc_bits being right during primordial mode, and it
        happens to hold the ownership lock. */
     pas_lock_lock(&shared_view->ownership_lock);
-    if (pas_compact_tagged_unsigned_ptr_load(&partial_view->alloc_bits) == (unsigned*)src->bits)
-        pas_compact_tagged_unsigned_ptr_store(&partial_view->alloc_bits, (unsigned*)dst->bits);
+    if (pas_lenient_compact_unsigned_ptr_load(&partial_view->alloc_bits) == (unsigned*)src->bits)
+        pas_lenient_compact_unsigned_ptr_store(&partial_view->alloc_bits, (unsigned*)dst->bits);
     pas_lock_unlock(&shared_view->ownership_lock);
 }
 

Modified: trunk/Source/bmalloc/libpas/src/libpas/pas_local_allocator_inlines.h (287967 => 287968)


--- trunk/Source/bmalloc/libpas/src/libpas/pas_local_allocator_inlines.h	2022-01-13 02:17:09 UTC (rev 287967)
+++ trunk/Source/bmalloc/libpas/src/libpas/pas_local_allocator_inlines.h	2022-01-13 02:52:00 UTC (rev 287968)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2021 Apple Inc. All rights reserved.
+ * Copyright (c) 2018-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
@@ -352,7 +352,7 @@
 
     partial_view_as_view = pas_segregated_partial_view_as_view((pas_segregated_partial_view*)view);
     
-    full_alloc_bits = pas_full_alloc_bits_create_for_partial(partial_view_as_view);
+    full_alloc_bits = pas_full_alloc_bits_create_for_partial_but_not_primordial(partial_view_as_view);
     
     allocator->view = partial_view_as_view;
 
@@ -599,21 +599,16 @@
         shared_page_directory = page_config.shared_page_directory_selector(heap, size_directory);
         
         shared_view = pas_segregated_shared_page_directory_find_first_eligible(
-            shared_page_directory, size, alignment,
-            pas_segregated_page_config_heap_lock_hold_mode(page_config));
+            shared_page_directory, size, alignment, pas_lock_is_not_held);
 
         PAS_ASSERT(shared_view);
         
-        pas_lock_lock_conditionally(
-            &shared_view->commit_lock,
-            pas_segregated_page_config_heap_lock_hold_mode(page_config));
+        pas_lock_lock(&shared_view->commit_lock);
 
         handle = pas_segregated_shared_view_commit_page_if_necessary(
             shared_view, heap, shared_page_directory, view, page_config);
         if (!handle) {
-            pas_lock_unlock_conditionally(
-                &shared_view->commit_lock,
-                pas_segregated_page_config_heap_lock_hold_mode(page_config));
+            pas_lock_unlock(&shared_view->commit_lock);
             return false;
         }
 
@@ -663,13 +658,6 @@
 
         pas_zero_memory(allocator->bits, pas_segregated_page_config_num_alloc_bytes(page_config));
 
-        /* Doing this helps heap introspection but isn't otherwise necessary. */
-        pas_compact_tagged_unsigned_ptr_store(&view->alloc_bits, (unsigned*)allocator->bits);
-        PAS_ASSERT(!view->alloc_bits_offset);
-        PAS_ASSERT((uint8_t)pas_segregated_page_config_num_alloc_words(page_config)
-                   == pas_segregated_page_config_num_alloc_words(page_config));
-        view->alloc_bits_size = (uint8_t)pas_segregated_page_config_num_alloc_words(page_config);
-
         pas_local_allocator_set_up_primordial_bump(
             allocator, view, handle, page, &held_lock, bump_result,
             pas_local_allocator_primordial_bump_stash_whole_allocation,
@@ -679,11 +667,37 @@
 
         view->is_attached_to_shared_handle = true;
 
+        pas_lock_unlock(&shared_view->commit_lock);
+
+        /* This code to set the view's alloc_bits is primarily for heap enumeration.
+           
+           If the enumerator ran right now then (before we do this stuff), then it would see:
+        
+           - A bunch of page alloc bits set for the objects we are about to allocate.
+           - No partial views say that they own those objects.
+           - Local allocator claims to own those objects.
+        
+           So, we would report that those objects are not live right now. I believe they would show up
+           as "meta" allocations, not even as objects.
+        
+           Immediately after settings the view's alloc_bits and alloc_bits_size, we will know that the
+           objects exist (view alloc bits are set), but they are dead (despite page alloc bits also being
+           set, the objects are part of the bump range). */
+        if (!pas_heap_lock_try_lock()) {
+            pas_lock_switch(&held_lock, NULL);
+            pas_heap_lock_lock();
+            pas_segregated_page_switch_lock(page, &held_lock, page_config);
+        }
+
+        pas_lenient_compact_unsigned_ptr_store(&view->alloc_bits, (unsigned*)allocator->bits);
+        PAS_ASSERT(!view->alloc_bits_offset);
+        PAS_ASSERT((uint8_t)pas_segregated_page_config_num_alloc_words(page_config)
+                   == pas_segregated_page_config_num_alloc_words(page_config));
+        pas_compiler_fence();
+        view->alloc_bits_size = (uint8_t)pas_segregated_page_config_num_alloc_words(page_config);
         pas_lock_switch(&held_lock, NULL);
-        pas_lock_unlock_conditionally(
-            &shared_view->commit_lock,
-            pas_segregated_page_config_heap_lock_hold_mode(page_config));
-        
+        pas_heap_lock_unlock();
+
         return true;
     }
 }
@@ -775,30 +789,28 @@
     
     PAS_ASSERT((uint8_t)alloc_bits_offset == alloc_bits_offset);
     view->alloc_bits_offset = (uint8_t)alloc_bits_offset;
+    
+    /* We hold the page lock. Lock ordering says that we cannot acquire the heap lock when
+       we are holding the page lock.
+       
+       Luckily, this is a fine place to drop the page lock.
+       
+       Therefore, we try-lock the heap lock. It's always safe to do that. Usually it will just
+       succeed. But if it fails, we will drop the page lock and then acquire both of them. */
+    if (!pas_heap_lock_try_lock_conditionally(heap_lock_hold_mode)) {
+        pas_segregated_page_unlock(page, page_config);
+        pas_heap_lock_lock();
+        pas_segregated_page_lock(page, page_config);
+    }
 
     if (alloc_bits_size == 1)
         alloc_bits = &view->inline_alloc_bits - alloc_bits_offset;
     else {
-        /* We hold the page lock. Lock ordering says that we cannot acquire the heap lock when
-           we are holding the page lock.
-           
-           Luckily, this is a fine place to drop the page lock.
-           
-           Therefore, we try-lock the heap lock. It's always safe to do that. Usually it will just
-           succeed. But if it fails, we will drop the page lock and then acquire both of them. */
-        if (!pas_heap_lock_try_lock_conditionally(heap_lock_hold_mode)) {
-            pas_segregated_page_unlock(page, page_config);
-            pas_heap_lock_lock();
-            pas_segregated_page_lock(page, page_config);
-        }
-
         alloc_bits = (unsigned*)pas_immortal_heap_allocate_with_manual_alignment(
             alloc_bits_size * sizeof(unsigned),
             sizeof(unsigned),
             "pas_segregated_partial_view/alloc_bits",
             pas_object_allocation) - alloc_bits_offset;
-
-        pas_heap_lock_unlock_conditionally(heap_lock_hold_mode);
     }
     
     memcpy(alloc_bits + alloc_bits_offset,
@@ -807,7 +819,9 @@
 
     pas_store_store_fence();
 
-    pas_compact_tagged_unsigned_ptr_store(&view->alloc_bits, alloc_bits);
+    pas_lenient_compact_unsigned_ptr_store(&view->alloc_bits, alloc_bits);
+    
+    pas_heap_lock_unlock_conditionally(heap_lock_hold_mode);
 }
 
 static PAS_ALWAYS_INLINE pas_allocation_result

Modified: trunk/Source/bmalloc/libpas/src/libpas/pas_segregated_partial_view.c (287967 => 287968)


--- trunk/Source/bmalloc/libpas/src/libpas/pas_segregated_partial_view.c	2022-01-13 02:17:09 UTC (rev 287967)
+++ trunk/Source/bmalloc/libpas/src/libpas/pas_segregated_partial_view.c	2022-01-13 02:52:00 UTC (rev 287968)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020 Apple Inc. All rights reserved.
+ * Copyright (c) 2019-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
@@ -64,7 +64,7 @@
 
     result->alloc_bits_offset = 0;
     result->alloc_bits_size = 0;
-    pas_compact_tagged_unsigned_ptr_store(&result->alloc_bits, NULL);
+    pas_lenient_compact_unsigned_ptr_store(&result->alloc_bits, NULL);
 
     result->inline_alloc_bits = 0; /* There isn't a real big need to do this, but it helps keep
                                       things sane. */
@@ -186,7 +186,7 @@
 
     shared_view = pas_compact_segregated_shared_view_ptr_load_non_null(&view->shared_view);
 
-    full_alloc_bits = pas_compact_tagged_unsigned_ptr_load_non_null(&view->alloc_bits);
+    full_alloc_bits = pas_lenient_compact_unsigned_ptr_load(&view->alloc_bits);
 
     if (shared_view->is_owned) {
         page_boundary = (uintptr_t)pas_shared_handle_or_page_boundary_get_page_boundary(

Modified: trunk/Source/bmalloc/libpas/src/libpas/pas_segregated_partial_view.h (287967 => 287968)


--- trunk/Source/bmalloc/libpas/src/libpas/pas_segregated_partial_view.h	2022-01-13 02:17:09 UTC (rev 287967)
+++ trunk/Source/bmalloc/libpas/src/libpas/pas_segregated_partial_view.h	2022-01-13 02:52:00 UTC (rev 287968)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020 Apple Inc. All rights reserved.
+ * Copyright (c) 2019-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
@@ -28,9 +28,9 @@
 
 #include "pas_compact_segregated_shared_view_ptr.h"
 #include "pas_compact_segregated_size_directory_ptr.h"
-#include "pas_compact_tagged_unsigned_ptr.h"
+#include "pas_lenient_compact_unsigned_ptr.h"
+#include "pas_page_granule_use_count.h"
 #include "pas_segregated_page_config.h"
-#include "pas_page_granule_use_count.h"
 #include "pas_segregated_view.h"
 #include "pas_utils.h"
 
@@ -48,7 +48,7 @@
     
     pas_compact_segregated_shared_view_ptr shared_view;
     pas_compact_segregated_size_directory_ptr directory;
-    pas_compact_tagged_unsigned_ptr alloc_bits;
+    pas_lenient_compact_unsigned_ptr alloc_bits;
 
     /* The index can be small since we would never create a high-indexed partial view. That would not
        have a meaningful effect on the footprint of the directory.

Modified: trunk/Source/bmalloc/libpas/src/libpas/pas_segregated_view_allocator_inlines.h (287967 => 287968)


--- trunk/Source/bmalloc/libpas/src/libpas/pas_segregated_view_allocator_inlines.h	2022-01-13 02:17:09 UTC (rev 287967)
+++ trunk/Source/bmalloc/libpas/src/libpas/pas_segregated_view_allocator_inlines.h	2022-01-13 02:52:00 UTC (rev 287968)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Apple Inc. All rights reserved.
+ * Copyright (c) 2021-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
@@ -262,7 +262,7 @@
             unsigned end_word_index;
             unsigned word_index;
         
-            full_alloc_bits = pas_compact_tagged_unsigned_ptr_load_non_null(&partial->alloc_bits);
+            full_alloc_bits = pas_lenient_compact_unsigned_ptr_load_compact_non_null(&partial->alloc_bits);
         
             begin_word_index = partial->alloc_bits_offset;
             end_word_index = begin_word_index + partial->alloc_bits_size;

Modified: trunk/Source/bmalloc/libpas/src/libpas/pas_thread_local_cache.c (287967 => 287968)


--- trunk/Source/bmalloc/libpas/src/libpas/pas_thread_local_cache.c	2022-01-13 02:17:09 UTC (rev 287967)
+++ trunk/Source/bmalloc/libpas/src/libpas/pas_thread_local_cache.c	2022-01-13 02:52:00 UTC (rev 287968)
@@ -30,9 +30,9 @@
 #include "pas_thread_local_cache.h"
 
 #include "pas_all_heap_configs.h"
-#include "pas_compact_large_utility_free_heap.h"
 #include "pas_debug_heap.h"
 #include "pas_heap_lock.h"
+#include "pas_large_utility_free_heap.h"
 #include "pas_log.h"
 #include "pas_monotonic_time.h"
 #include "pas_scavenger.h"
@@ -63,12 +63,12 @@
 {
     char* begin;
 
-    pas_compact_large_utility_free_heap_deallocate(
+    pas_large_utility_free_heap_deallocate(
         thread_local_cache->should_stop_bitvector,
         PAS_BITVECTOR_NUM_BYTES(thread_local_cache->allocator_index_capacity));
     
     begin = (char*)thread_local_cache;
-    pas_compact_large_utility_free_heap_deallocate(
+    pas_large_utility_free_heap_deallocate(
         begin,
         pas_thread_local_cache_size_for_allocator_index_capacity(
             thread_local_cache->allocator_index_capacity));
@@ -129,11 +129,11 @@
     if (verbose)
         printf("Cache size: %zu\n", size);
     
-    result = (pas_thread_local_cache*)pas_compact_large_utility_free_heap_allocate(size, "pas_thread_local_cache");
+    result = (pas_thread_local_cache*)pas_large_utility_free_heap_allocate(size, "pas_thread_local_cache");
 
     pas_zero_memory(result, size);
 
-    result->should_stop_bitvector = (unsigned int*)pas_compact_large_utility_free_heap_allocate(
+    result->should_stop_bitvector = (unsigned int*)pas_large_utility_free_heap_allocate(
         PAS_BITVECTOR_NUM_BYTES(allocator_index_capacity),
         "pas_thread_local_cache/should_stop_bitvector");
 

Added: trunk/Source/bmalloc/libpas/src/test/LotsOfHeapsAndThreads.cpp (0 => 287968)


--- trunk/Source/bmalloc/libpas/src/test/LotsOfHeapsAndThreads.cpp	                        (rev 0)
+++ trunk/Source/bmalloc/libpas/src/test/LotsOfHeapsAndThreads.cpp	2022-01-13 02:52:00 UTC (rev 287968)
@@ -0,0 +1,78 @@
+/*
+ * 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. 
+ */
+
+#include "TestHarness.h"
+
+#if PAS_ENABLE_BMALLOC
+
+#include "bmalloc_heap.h"
+#include "bmalloc_heap_config.h"
+#include "pas_get_heap.h"
+#include <thread>
+
+using namespace std;
+
+namespace {
+
+void testLotsOfHeapsAndThreads(unsigned numHeaps, unsigned numThreads, unsigned count)
+{
+    thread* threads = new thread[numThreads];
+    pas_heap_ref* heaps = new pas_heap_ref[numHeaps];
+
+    for (unsigned i = numHeaps; i--;)
+        heaps[i] = BMALLOC_HEAP_REF_INITIALIZER(new bmalloc_type(BMALLOC_TYPE_INITIALIZER(16, 16, "test")));
+
+    for (unsigned i = numThreads; i--;) {
+        threads[i] = thread([&] () {
+            for (unsigned j = count; j--;) {
+                for (unsigned k = numHeaps; k--;) {
+                    void* ptr = bmalloc_iso_allocate(heaps + k);
+                    CHECK_EQUAL(pas_get_heap(ptr, BMALLOC_HEAP_CONFIG),
+                                bmalloc_heap_ref_get_heap(heaps + k));
+                    bmalloc_deallocate(ptr);
+                }
+            }
+        });
+    }
+
+    for (unsigned i = numThreads; i--;)
+        threads[i].join();
+}
+
+} // anonymous namespace
+
+#endif // PAS_ENABLE_BMALLOC
+
+void addLotsOfHeapsAndThreadsTests()
+{
+#if PAS_ENABLE_BMALLOC
+    ForceTLAs forceTLAs;
+    ForcePartials forcePartials;
+    
+    ADD_TEST(testLotsOfHeapsAndThreads(10000, 100, 10));
+    ADD_TEST(testLotsOfHeapsAndThreads(25000, 100, 10));
+    ADD_TEST(testLotsOfHeapsAndThreads(30000, 100, 10)); // This is about as high as we can reliably go right now!
+#endif // PAS_ENABLE_BMALLOC
+}

Modified: trunk/Source/bmalloc/libpas/src/test/TestHarness.cpp (287967 => 287968)


--- trunk/Source/bmalloc/libpas/src/test/TestHarness.cpp	2022-01-13 02:17:09 UTC (rev 287967)
+++ trunk/Source/bmalloc/libpas/src/test/TestHarness.cpp	2022-01-13 02:52:00 UTC (rev 287968)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2021 Apple Inc. All rights reserved.
+ * Copyright (c) 2018-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
@@ -353,6 +353,7 @@
 void addLargeFreeHeapTests();
 void addLargeSharingPoolTests();
 void addLockFreeReadPtrPtrHashtableTests();
+void addLotsOfHeapsAndThreadsTests();
 void addMinHeapTests();
 void addPGMTests();
 void addRaceTests();
@@ -717,6 +718,7 @@
     ADD_SUITE(LargeFreeHeap);
     ADD_SUITE(LargeSharingPool);
     ADD_SUITE(LockFreeReadPtrPtrHashtable);
+    ADD_SUITE(LotsOfHeapsAndThreads);
     ADD_SUITE(MinHeap);
     ADD_SUITE(PGM);
     ADD_SUITE(Race);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to