@@ -37,19 +37,30 @@ pub trait AllocBytes:
37
37
/// Create a zeroed `AllocBytes` of the specified size and alignment.
38
38
/// Returns `None` if we ran out of memory on the host.
39
39
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 ;
40
47
}
41
48
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
+ impl AllocBytes for Vec < u8 > {
44
51
fn from_bytes < ' a > ( slice : impl Into < Cow < ' a , [ u8 ] > > , _align : Align ) -> Self {
45
- Box :: < [ u8 ] > :: from ( slice. into ( ) )
52
+ slice. into ( ) . into_owned ( )
46
53
}
47
54
48
55
fn zeroed ( size : Size , _align : Align ) -> Option < Self > {
49
56
let bytes = Box :: < [ u8 ] > :: try_new_zeroed_slice ( size. bytes_usize ( ) ) . ok ( ) ?;
50
57
// SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]>
51
58
let bytes = unsafe { bytes. assume_init ( ) } ;
52
- Some ( bytes)
59
+ Some ( bytes. into ( ) )
60
+ }
61
+
62
+ fn as_mut_ptr ( & mut self ) -> * mut u8 {
63
+ Vec :: as_mut_ptr ( self )
53
64
}
54
65
}
55
66
@@ -62,7 +73,7 @@ impl AllocBytes for Box<[u8]> {
62
73
// hashed. (see the `Hash` impl below for more details), so the impl is not derived.
63
74
#[ derive( Clone , Eq , PartialEq , TyEncodable , TyDecodable ) ]
64
75
#[ derive( HashStable ) ]
65
- pub struct Allocation < Prov : Provenance = CtfeProvenance , Extra = ( ) , Bytes = Box < [ u8 ] > > {
76
+ pub struct Allocation < Prov : Provenance = CtfeProvenance , Extra = ( ) , Bytes = Vec < u8 > > {
66
77
/// The actual bytes of the allocation.
67
78
/// Note that the bytes of a pointer represent the offset of the pointer.
68
79
bytes : Bytes ,
@@ -399,10 +410,6 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
399
410
400
411
/// Byte accessors.
401
412
impl < Prov : Provenance , Extra , Bytes : AllocBytes > Allocation < Prov , Extra , Bytes > {
402
- pub fn base_addr ( & self ) -> * const u8 {
403
- self . bytes . as_ptr ( )
404
- }
405
-
406
413
/// This is the entirely abstraction-violating way to just grab the raw bytes without
407
414
/// caring about provenance or initialization.
408
415
///
@@ -452,13 +459,14 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
452
459
Ok ( self . get_bytes_unchecked ( range) )
453
460
}
454
461
455
- /// Just calling this already marks everything as defined and removes provenance,
456
- /// so be sure to actually put data there!
462
+ /// This is the entirely abstraction-violating way to just get mutable access to the raw bytes.
463
+ /// Just calling this already marks everything as defined and removes provenance, so be sure to
464
+ /// actually overwrite all the data there!
457
465
///
458
466
/// It is the caller's responsibility to check bounds and alignment beforehand.
459
467
/// Most likely, you want to use the `PlaceTy` and `OperandTy`-based methods
460
468
/// on `InterpCx` instead.
461
- pub fn get_bytes_mut (
469
+ pub fn get_bytes_unchecked_for_overwrite (
462
470
& mut self ,
463
471
cx : & impl HasDataLayout ,
464
472
range : AllocRange ,
@@ -469,8 +477,9 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
469
477
Ok ( & mut self . bytes [ range. start . bytes_usize ( ) ..range. end ( ) . bytes_usize ( ) ] )
470
478
}
471
479
472
- /// A raw pointer variant of `get_bytes_mut` that avoids invalidating existing aliases into this memory.
473
- pub fn get_bytes_mut_ptr (
480
+ /// A raw pointer variant of `get_bytes_unchecked_for_overwrite` that avoids invalidating existing immutable aliases
481
+ /// into this memory.
482
+ pub fn get_bytes_unchecked_for_overwrite_ptr (
474
483
& mut self ,
475
484
cx : & impl HasDataLayout ,
476
485
range : AllocRange ,
@@ -479,10 +488,19 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
479
488
self . provenance . clear ( range, cx) ?;
480
489
481
490
assert ! ( range. end( ) . bytes_usize( ) <= self . bytes. len( ) ) ; // need to do our own bounds-check
491
+ // Cruciall, we go via `AllocBytes::as_mut_ptr`, not `AllocBytes::deref_mut`.
482
492
let begin_ptr = self . bytes . as_mut_ptr ( ) . wrapping_add ( range. start . bytes_usize ( ) ) ;
483
493
let len = range. end ( ) . bytes_usize ( ) - range. start . bytes_usize ( ) ;
484
494
Ok ( ptr:: slice_from_raw_parts_mut ( begin_ptr, len) )
485
495
}
496
+
497
+ /// This gives direct mutable access to the entire buffer, just exposing their internal state
498
+ /// without reseting anything. Directly exposes `AllocBytes::as_mut_ptr`. Only works if
499
+ /// `OFFSET_IS_ADDR` is true.
500
+ pub fn get_bytes_unchecked_raw_mut ( & mut self ) -> * mut u8 {
501
+ assert ! ( Prov :: OFFSET_IS_ADDR ) ;
502
+ self . bytes . as_mut_ptr ( )
503
+ }
486
504
}
487
505
488
506
/// Reading and writing.
@@ -589,7 +607,8 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
589
607
} ;
590
608
591
609
let endian = cx. data_layout ( ) . endian ;
592
- let dst = self . get_bytes_mut ( cx, range) ?;
610
+ // Yes we do overwrite all the bytes in `dst`.
611
+ let dst = self . get_bytes_unchecked_for_overwrite ( cx, range) ?;
593
612
write_target_uint ( endian, dst, bytes) . unwrap ( ) ;
594
613
595
614
// See if we have to also store some provenance.
0 commit comments