@@ -37,19 +37,33 @@ pub trait AllocBytes:
3737 /// Create a zeroed `AllocBytes` of the specified size and alignment.
3838 /// Returns `None` if we ran out of memory on the host.
3939 fn zeroed ( size : Size , _align : Align ) -> Option < Self > ;
40+
41+ /// Gives direct access to the raw underlying storage.
42+ ///
43+ /// Crucially this pointer is compatible with:
44+ /// - other pointers retunred by this method, and
45+ /// - references returned from `deref()`, as long as there was no write.
46+ fn as_mut_ptr ( & mut self ) -> * mut u8 ;
4047}
4148
42- // Default `bytes` for `Allocation` is a `Box<[u8]>`.
43- impl AllocBytes for Box < [ u8 ] > {
49+ /// Default `bytes` for `Allocation` is a `Vec<u8>`.
50+ ///
51+ /// We use `Vec`, not `Box`, since we need `Vec::as_mut_ptr` and how it interacts with other
52+ /// pointers to the backing buffer. `Box` has no corresponding method.
53+ impl AllocBytes for Vec < u8 > {
4454 fn from_bytes < ' a > ( slice : impl Into < Cow < ' a , [ u8 ] > > , _align : Align ) -> Self {
45- Box :: < [ u8 ] > :: from ( slice. into ( ) )
55+ slice. into ( ) . into_owned ( )
4656 }
4757
4858 fn zeroed ( size : Size , _align : Align ) -> Option < Self > {
4959 let bytes = Box :: < [ u8 ] > :: try_new_zeroed_slice ( size. bytes_usize ( ) ) . ok ( ) ?;
5060 // SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]>
5161 let bytes = unsafe { bytes. assume_init ( ) } ;
52- Some ( bytes)
62+ Some ( bytes. into ( ) )
63+ }
64+
65+ fn as_mut_ptr ( & mut self ) -> * mut u8 {
66+ Vec :: as_mut_ptr ( self )
5367 }
5468}
5569
@@ -62,7 +76,7 @@ impl AllocBytes for Box<[u8]> {
6276// hashed. (see the `Hash` impl below for more details), so the impl is not derived.
6377#[ derive( Clone , Eq , PartialEq , TyEncodable , TyDecodable ) ]
6478#[ derive( HashStable ) ]
65- pub struct Allocation < Prov : Provenance = CtfeProvenance , Extra = ( ) , Bytes = Box < [ u8 ] > > {
79+ pub struct Allocation < Prov : Provenance = CtfeProvenance , Extra = ( ) , Bytes = Vec < u8 > > {
6680 /// The actual bytes of the allocation.
6781 /// Note that the bytes of a pointer represent the offset of the pointer.
6882 bytes : Bytes ,
@@ -399,10 +413,6 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
399413
400414/// Byte accessors.
401415impl < Prov : Provenance , Extra , Bytes : AllocBytes > Allocation < Prov , Extra , Bytes > {
402- pub fn base_addr ( & self ) -> * const u8 {
403- self . bytes . as_ptr ( )
404- }
405-
406416 /// This is the entirely abstraction-violating way to just grab the raw bytes without
407417 /// caring about provenance or initialization.
408418 ///
@@ -452,13 +462,14 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
452462 Ok ( self . get_bytes_unchecked ( range) )
453463 }
454464
455- /// Just calling this already marks everything as defined and removes provenance,
456- /// so be sure to actually put data there!
465+ /// This is the entirely abstraction-violating way to just get mutable access to the raw bytes.
466+ /// Just calling this already marks everything as defined and removes provenance, so be sure to
467+ /// actually overwrite all the data there!
457468 ///
458469 /// It is the caller's responsibility to check bounds and alignment beforehand.
459470 /// Most likely, you want to use the `PlaceTy` and `OperandTy`-based methods
460471 /// on `InterpCx` instead.
461- pub fn get_bytes_mut (
472+ pub fn get_bytes_unchecked_for_overwrite (
462473 & mut self ,
463474 cx : & impl HasDataLayout ,
464475 range : AllocRange ,
@@ -469,8 +480,9 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
469480 Ok ( & mut self . bytes [ range. start . bytes_usize ( ) ..range. end ( ) . bytes_usize ( ) ] )
470481 }
471482
472- /// A raw pointer variant of `get_bytes_mut` that avoids invalidating existing aliases into this memory.
473- pub fn get_bytes_mut_ptr (
483+ /// A raw pointer variant of `get_bytes_unchecked_for_overwrite` that avoids invalidating existing immutable aliases
484+ /// into this memory.
485+ pub fn get_bytes_unchecked_for_overwrite_ptr (
474486 & mut self ,
475487 cx : & impl HasDataLayout ,
476488 range : AllocRange ,
@@ -479,10 +491,19 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
479491 self . provenance . clear ( range, cx) ?;
480492
481493 assert ! ( range. end( ) . bytes_usize( ) <= self . bytes. len( ) ) ; // need to do our own bounds-check
494+ // Cruciall, we go via `AllocBytes::as_mut_ptr`, not `AllocBytes::deref_mut`.
482495 let begin_ptr = self . bytes . as_mut_ptr ( ) . wrapping_add ( range. start . bytes_usize ( ) ) ;
483496 let len = range. end ( ) . bytes_usize ( ) - range. start . bytes_usize ( ) ;
484497 Ok ( ptr:: slice_from_raw_parts_mut ( begin_ptr, len) )
485498 }
499+
500+ /// This gives direct mutable access to the entire buffer, just exposing their internal state
501+ /// without reseting anything. Directly exposes `AllocBytes::as_mut_ptr`. Only works if
502+ /// `OFFSET_IS_ADDR` is true.
503+ pub fn get_bytes_unchecked_raw_mut ( & mut self ) -> * mut u8 {
504+ assert ! ( Prov :: OFFSET_IS_ADDR ) ;
505+ self . bytes . as_mut_ptr ( )
506+ }
486507}
487508
488509/// Reading and writing.
@@ -589,7 +610,8 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
589610 } ;
590611
591612 let endian = cx. data_layout ( ) . endian ;
592- let dst = self . get_bytes_mut ( cx, range) ?;
613+ // Yes we do overwrite all the bytes in `dst`.
614+ let dst = self . get_bytes_unchecked_for_overwrite ( cx, range) ?;
593615 write_target_uint ( endian, dst, bytes) . unwrap ( ) ;
594616
595617 // See if we have to also store some provenance.
0 commit comments