@@ -60,30 +60,35 @@ struct SlotVTable {
6060 /// [`Slot`] methods
6161 memos : SlotMemosFnRaw ,
6262 memos_mut : SlotMemosMutFnRaw ,
63+ /// The type name of what is stored as entries in data.
64+ type_name : fn ( ) -> & ' static str ,
6365 /// A drop impl to call when the own page drops
64- /// SAFETY: The caller is required to supply a correct data pointer to a `Box<PageDataEntry<T>>` and initialized length,
65- /// and correct memo types.
66+ /// SAFETY: The caller is required to supply a valid pointer to a `Box<PageDataEntry<T>>`, and
67+ /// the correct initialized length and memo types.
6668 drop_impl : unsafe fn ( data : * mut ( ) , initialized : usize , memo_types : & MemoTableTypes ) ,
6769}
6870
6971impl SlotVTable {
7072 const fn of < T : Slot > ( ) -> & ' static Self {
7173 const {
7274 & Self {
73- drop_impl : |data, initialized, memo_types|
74- // SAFETY: The caller is required to supply a correct data pointer and initialized length
75- unsafe {
76- let data = Box :: from_raw ( data. cast :: < PageData < T > > ( ) ) ;
75+ drop_impl : |data, initialized, memo_types| {
76+ // SAFETY: The caller is required to provide a valid data pointer.
77+ let data = unsafe { Box :: from_raw ( data. cast :: < PageData < T > > ( ) ) } ;
7778 for i in 0 ..initialized {
7879 let item = data[ i] . get ( ) . cast :: < T > ( ) ;
79- memo_types. attach_memos_mut ( ( * item) . memos_mut ( ) ) . drop ( ) ;
80- ptr:: drop_in_place ( item) ;
80+ // SAFETY: The caller is required to provide a valid initialized length.
81+ unsafe {
82+ memo_types. attach_memos_mut ( ( * item) . memos_mut ( ) ) . drop ( ) ;
83+ ptr:: drop_in_place ( item) ;
84+ }
8185 }
8286 } ,
8387 layout : Layout :: new :: < T > ( ) ,
84- // SAFETY: The signatures are compatible
88+ type_name : std:: any:: type_name :: < T > ,
89+ // SAFETY: The signatures are ABI-compatible.
8590 memos : unsafe { mem:: transmute :: < SlotMemosFn < T > , SlotMemosFnRaw > ( T :: memos) } ,
86- // SAFETY: The signatures are compatible
91+ // SAFETY: The signatures are ABI- compatible.
8792 memos_mut : unsafe {
8893 mem:: transmute :: < SlotMemosMutFn < T > , SlotMemosMutFnRaw > ( T :: memos_mut)
8994 } ,
@@ -102,16 +107,6 @@ struct Page {
102107 /// Number of elements of `data` that are initialized.
103108 allocated : AtomicUsize ,
104109
105- /// The "allocation lock" is held when we allocate a new entry.
106- ///
107- /// It ensures that we can load the index, initialize it, and then update the length atomically
108- /// with respect to other allocations.
109- ///
110- /// We could avoid it if we wanted, we'd just have to be a bit fancier in our reasoning
111- /// (for example, the bounds check in `Page::get` no longer suffices to truly guarantee
112- /// that the data is initialized).
113- allocation_lock : Mutex < ( ) > ,
114-
115110 /// The potentially uninitialized data of this page. As we initialize new entries, we increment `allocated`.
116111 /// This is a box allocated `PageData<SlotType>`
117112 data : NonNull < ( ) > ,
@@ -121,9 +116,6 @@ struct Page {
121116 /// The type id of what is stored as entries in data.
122117 // FIXME: Move this into SlotVTable once const stable
123118 slot_type_id : TypeId ,
124- /// The type name of what is stored as entries in data.
125- // FIXME: Move this into SlotVTable once const stable
126- slot_type_name : & ' static str ,
127119
128120 memo_types : Arc < MemoTableTypes > ,
129121}
@@ -329,12 +321,17 @@ impl<'db, T: Slot> PageView<'db, T> {
329321 unsafe { slice:: from_raw_parts ( self . 0 . data . cast :: < T > ( ) . as_ptr ( ) , len) }
330322 }
331323
324+ /// Allocate a value in this page.
325+ ///
326+ /// # Safety
327+ ///
328+ /// The caller must be the unique writer to this page, i.e. `allocate` cannot be called
329+ /// concurrently by multiple threads. Concurrent readers however, are fine.
332330 #[ inline]
333- pub ( crate ) fn allocate < V > ( & self , page : PageIndex , value : V ) -> Result < ( Id , & ' db T ) , V >
331+ pub ( crate ) unsafe fn allocate < V > ( & self , page : PageIndex , value : V ) -> Result < ( Id , & ' db T ) , V >
334332 where
335333 V : FnOnce ( Id ) -> T ,
336334 {
337- let _guard = self . 0 . allocation_lock . lock ( ) ;
338335 let index = self . 0 . allocated . load ( Ordering :: Acquire ) ;
339336 if index >= PAGE_LEN {
340337 return Err ( value) ;
@@ -347,15 +344,14 @@ impl<'db, T: Slot> PageView<'db, T> {
347344 // SAFETY: `index` is also guaranteed to be in bounds as per the check above.
348345 let entry = unsafe { & * data. as_ptr ( ) . add ( index) } ;
349346
350- // SAFETY: We acquired the allocation lock, so we have unique access to the UnsafeCell
351- // interior
347+ // SAFETY: The caller guarantees we are the unique writer, and readers will not attempt to
348+ // access this index until we have updated the length.
352349 unsafe { ( * entry. get ( ) ) . write ( value ( id) ) } ;
353350
354351 // SAFETY: We just initialized the value above.
355352 let value = unsafe { ( * entry. get ( ) ) . assume_init_ref ( ) } ;
356353
357- // Update the length (this must be done after initialization as otherwise an uninitialized
358- // read could occur!)
354+ // Update the length now that we have initialized the value.
359355 self . 0 . allocated . store ( index + 1 , Ordering :: Release ) ;
360356
361357 Ok ( ( id, value) )
@@ -383,14 +379,12 @@ impl Page {
383379 } ;
384380
385381 Self {
382+ ingredient,
383+ memo_types,
386384 slot_vtable : SlotVTable :: of :: < T > ( ) ,
387385 slot_type_id : TypeId :: of :: < T > ( ) ,
388- slot_type_name : std:: any:: type_name :: < T > ( ) ,
389- ingredient,
390- allocated : Default :: default ( ) ,
391- allocation_lock : Default :: default ( ) ,
386+ allocated : AtomicUsize :: new ( 0 ) ,
392387 data : NonNull :: from ( Box :: leak ( data) ) . cast :: < ( ) > ( ) ,
393- memo_types,
394388 }
395389 }
396390
@@ -439,7 +433,7 @@ impl Page {
439433fn type_assert_failed < T : ' static > ( page : & Page ) -> ! {
440434 panic ! (
441435 "page has slot type `{:?}` but `{:?}` was expected" ,
442- page. slot_type_name ,
436+ ( page. slot_vtable . type_name ) ( ) ,
443437 std:: any:: type_name:: <T >( ) ,
444438 )
445439}
0 commit comments