@@ -8,7 +8,7 @@ use rustc::hir::{Mutability, MutMutable, MutImmutable};
8
8
use crate :: {
9
9
EvalResult , EvalErrorKind , MiriEvalContext , HelpersEvalContextExt , Evaluator , MutValueVisitor ,
10
10
MemoryKind , MiriMemoryKind , RangeMap , AllocId , Allocation , AllocationExtra ,
11
- Pointer , MemPlace , Scalar , Immediate , ImmTy , PlaceTy , MPlaceTy ,
11
+ Pointer , Immediate , ImmTy , PlaceTy , MPlaceTy ,
12
12
} ;
13
13
14
14
pub type Timestamp = u64 ;
@@ -539,19 +539,21 @@ pub trait EvalContextExt<'tcx> {
539
539
size : Size ,
540
540
fn_barrier : bool ,
541
541
new_bor : Borrow
542
- ) -> EvalResult < ' tcx , Pointer < Borrow > > ;
542
+ ) -> EvalResult < ' tcx > ;
543
543
544
544
/// Retag an indidual pointer, returning the retagged version.
545
545
fn retag_reference (
546
546
& mut self ,
547
547
ptr : ImmTy < ' tcx , Borrow > ,
548
548
mutbl : Mutability ,
549
549
fn_barrier : bool ,
550
+ two_phase : bool ,
550
551
) -> EvalResult < ' tcx , Immediate < Borrow > > ;
551
552
552
553
fn retag (
553
554
& mut self ,
554
555
fn_entry : bool ,
556
+ two_phase : bool ,
555
557
place : PlaceTy < ' tcx , Borrow >
556
558
) -> EvalResult < ' tcx > ;
557
559
@@ -649,9 +651,8 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
649
651
size : Size ,
650
652
fn_barrier : bool ,
651
653
new_bor : Borrow
652
- ) -> EvalResult < ' tcx , Pointer < Borrow > > {
654
+ ) -> EvalResult < ' tcx > {
653
655
let ptr = place. ptr . to_ptr ( ) ?;
654
- let new_ptr = Pointer :: new_with_tag ( ptr. alloc_id , ptr. offset , new_bor) ;
655
656
let barrier = if fn_barrier { Some ( self . frame ( ) . extra ) } else { None } ;
656
657
trace ! ( "reborrow: Creating new reference for {:?} (pointee {}): {:?}" ,
657
658
ptr, place. layout. ty, new_bor) ;
@@ -671,14 +672,15 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
671
672
let kind = if new_bor. is_unique ( ) { RefKind :: Unique } else { RefKind :: Raw } ;
672
673
alloc. extra . reborrow ( ptr, size, barrier, new_bor, kind) ?;
673
674
}
674
- Ok ( new_ptr )
675
+ Ok ( ( ) )
675
676
}
676
677
677
678
fn retag_reference (
678
679
& mut self ,
679
680
val : ImmTy < ' tcx , Borrow > ,
680
681
mutbl : Mutability ,
681
682
fn_barrier : bool ,
683
+ two_phase : bool ,
682
684
) -> EvalResult < ' tcx , Immediate < Borrow > > {
683
685
// We want a place for where the ptr *points to*, so we get one.
684
686
let place = self . ref_to_mplace ( val) ?;
@@ -698,16 +700,25 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
698
700
} ;
699
701
700
702
// Reborrow.
701
- let new_ptr = self . reborrow ( place, size, fn_barrier, new_bor) ?;
703
+ self . reborrow ( place, size, fn_barrier, new_bor) ?;
704
+ let new_place = place. with_tag ( new_bor) ;
705
+ // Handle two-phase borrows.
706
+ if two_phase {
707
+ assert ! ( mutbl == MutMutable , "two-phase shared borrows make no sense" ) ;
708
+ // We immediately share it, to allow read accesses
709
+ let two_phase_time = self . machine . stacked_borrows . increment_clock ( ) ;
710
+ let two_phase_bor = Borrow :: Shr ( Some ( two_phase_time) ) ;
711
+ self . reborrow ( new_place, size, /*fn_barrier*/ false , two_phase_bor) ?;
712
+ }
702
713
703
- // Return new ptr
704
- let new_place = MemPlace { ptr : Scalar :: Ptr ( new_ptr) , ..* place } ;
714
+ // Return new ptr.
705
715
Ok ( new_place. to_ref ( ) )
706
716
}
707
717
708
718
fn retag (
709
719
& mut self ,
710
720
fn_entry : bool ,
721
+ two_phase : bool ,
711
722
place : PlaceTy < ' tcx , Borrow >
712
723
) -> EvalResult < ' tcx > {
713
724
// Determine mutability and whether to add a barrier.
@@ -730,19 +741,20 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
730
741
if let Some ( ( mutbl, barrier) ) = qualify ( place. layout . ty , fn_entry) {
731
742
// fast path
732
743
let val = self . read_immediate ( self . place_to_op ( place) ?) ?;
733
- let val = self . retag_reference ( val, mutbl, barrier) ?;
744
+ let val = self . retag_reference ( val, mutbl, barrier, two_phase ) ?;
734
745
self . write_immediate ( val, place) ?;
735
746
return Ok ( ( ) ) ;
736
747
}
737
748
let place = self . force_allocation ( place) ?;
738
749
739
- let mut visitor = RetagVisitor { ecx : self , fn_entry } ;
750
+ let mut visitor = RetagVisitor { ecx : self , fn_entry, two_phase } ;
740
751
visitor. visit_value ( place) ?;
741
752
742
753
// The actual visitor
743
754
struct RetagVisitor < ' ecx , ' a , ' mir , ' tcx > {
744
755
ecx : & ' ecx mut MiriEvalContext < ' a , ' mir , ' tcx > ,
745
756
fn_entry : bool ,
757
+ two_phase : bool ,
746
758
}
747
759
impl < ' ecx , ' a , ' mir , ' tcx >
748
760
MutValueVisitor < ' a , ' mir , ' tcx , Evaluator < ' tcx > >
@@ -763,7 +775,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
763
775
// making it useless.
764
776
if let Some ( ( mutbl, barrier) ) = qualify ( place. layout . ty , self . fn_entry ) {
765
777
let val = self . ecx . read_immediate ( place. into ( ) ) ?;
766
- let val = self . ecx . retag_reference ( val, mutbl, barrier) ?;
778
+ let val = self . ecx . retag_reference ( val, mutbl, barrier, self . two_phase ) ?;
767
779
self . ecx . write_immediate ( val, place. into ( ) ) ?;
768
780
}
769
781
Ok ( ( ) )
0 commit comments