@@ -24,17 +24,29 @@ pub struct Heap {
24
24
25
25
impl Drop for Heap {
26
26
fn drop ( & mut self ) {
27
- unsafe {
28
- let layout = alloc:: Layout :: array :: < u8 > ( self . inner . byte_cap ) . unwrap ( ) ;
29
- alloc:: dealloc ( self . inner . ptr , layout) ;
27
+ if !self . inner . ptr . is_null ( ) {
28
+ unsafe {
29
+ let layout = alloc:: Layout :: array :: < u8 > ( self . inner . byte_cap ) . unwrap ( ) ;
30
+ alloc:: dealloc ( self . inner . ptr , layout) ;
31
+ }
30
32
}
31
33
}
32
34
}
33
35
36
+ // TODO: verify the soundness of the various accesses to `ptr`,
37
+ // or rely on a Vec-like library with fallible allocations.
34
38
#[ derive( Debug ) ]
35
39
struct InnerHeap {
36
40
ptr : * mut u8 ,
41
+
42
+ /// # Safety
43
+ ///
44
+ /// Must be equal to zero when `ptr.is_null()`.
37
45
byte_len : usize ,
46
+
47
+ /// # Safety
48
+ ///
49
+ /// Must be equal to zero when `ptr.is_null()`.
38
50
byte_cap : usize ,
39
51
}
40
52
@@ -341,15 +353,7 @@ impl<'a> ReservedHeapSection<'a> {
341
353
342
354
let zero_region_idx = heap_index ! ( self . heap_cell_len) + str_byte_len;
343
355
344
- let align_offset = self . heap_ptr
345
- . add ( zero_region_idx)
346
- . align_offset ( ALIGN_CELL ) ;
347
-
348
- let align_offset = if align_offset == 0 {
349
- ALIGN_CELL
350
- } else {
351
- align_offset
352
- } ;
356
+ let align_offset = pstr_sentinel_length ( zero_region_idx) ;
353
357
354
358
ptr:: write_bytes (
355
359
self . heap_ptr . add ( zero_region_idx) ,
@@ -469,6 +473,22 @@ impl<'a> Index<usize> for ReservedHeapSection<'a> {
469
473
}
470
474
}
471
475
476
+ /// Computes the number of bytes required to pad a string of length `chunk_len`
477
+ /// with zeroes, such that `chunk_len + pstr_sentinel_length(chunk_len)` is a
478
+ /// multiple of `Heap::heap_cell_alignement()`.
479
+ fn pstr_sentinel_length ( chunk_len : usize ) -> usize {
480
+ const ALIGN : usize = Heap :: heap_cell_alignment ( ) ;
481
+
482
+ let res = chunk_len. next_multiple_of ( ALIGN ) - chunk_len;
483
+
484
+ // No bytes available in last chunk
485
+ if res == 0 {
486
+ ALIGN
487
+ } else {
488
+ res
489
+ }
490
+ }
491
+
472
492
#[ must_use]
473
493
#[ derive( Debug ) ]
474
494
pub struct HeapWriter < ' a > {
@@ -623,7 +643,7 @@ impl Heap {
623
643
if self . free_space ( ) >= len {
624
644
section = ReservedHeapSection {
625
645
heap_ptr : self . inner . ptr ,
626
- heap_cell_len : cell_index ! ( self . inner . byte_len ) ,
646
+ heap_cell_len : self . cell_len ( ) ,
627
647
pstr_vec : & mut self . pstr_vec ,
628
648
} ;
629
649
break ;
@@ -798,6 +818,11 @@ impl Heap {
798
818
}
799
819
}
800
820
821
+ // SAFETY:
822
+ // - Postcondition: from `self.grow()`, `self.inner.byte_len + size_of::<HeapCellValue>()`
823
+ // is strictly less than `self.inner.byte_cap`.
824
+ // - Asserted: `self.cell_len() * size_of::<HeapCellvalue>() <= self.inner.byte_cap`.
825
+ // - Invariant: from `InnerHeap`, `self.inner.byte_cap < isize::MAX`.
801
826
let cell_ptr = ( self . inner . ptr as * mut HeapCellValue ) . add ( self . cell_len ( ) ) ;
802
827
cell_ptr. write ( cell) ;
803
828
self . pstr_vec . push ( false ) ;
@@ -954,17 +979,7 @@ impl Heap {
954
979
955
980
const ALIGN_CELL : usize = Heap :: heap_cell_alignment ( ) ;
956
981
957
- let align_offset = unsafe {
958
- self . inner . ptr
959
- . add ( self . inner . byte_len + s_len)
960
- . align_offset ( ALIGN_CELL )
961
- } ;
962
-
963
- let align_offset = if align_offset == 0 {
964
- ALIGN_CELL
965
- } else {
966
- align_offset
967
- } ;
982
+ let align_offset = pstr_sentinel_length ( s_len) ;
968
983
969
984
let copy_size = s_len + align_offset;
970
985
@@ -1027,7 +1042,8 @@ impl Heap {
1027
1042
Ok ( ( ) )
1028
1043
}
1029
1044
1030
- pub ( crate ) const fn compute_pstr_size ( src : & str ) -> usize {
1045
+ /// Returns the number of bytes needed to store `src` as a `PStr`.
1046
+ pub ( crate ) fn compute_pstr_size ( src : & str ) -> usize {
1031
1047
const ALIGN_CELL : usize = Heap :: heap_cell_alignment ( ) ;
1032
1048
1033
1049
let mut byte_size = 0 ;
@@ -1044,7 +1060,7 @@ impl Heap {
1044
1060
null_idx += 1 ;
1045
1061
}
1046
1062
1047
- byte_size += ( null_idx & ! ( ALIGN_CELL - 1 ) ) + ALIGN_CELL ;
1063
+ byte_size += null_idx. next_multiple_of ( ALIGN_CELL ) ;
1048
1064
byte_size += mem:: size_of :: < HeapCellValue > ( ) ;
1049
1065
1050
1066
if null_idx + 1 >= src. len ( ) {
0 commit comments