@@ -881,27 +881,45 @@ enum RawMarkState {
881
881
/// Normally this marks the white state
882
882
///
883
883
/// If we're inverted, this marks black
884
- Red ,
884
+ Red = 0 ,
885
885
/// This always marks the grey state
886
886
///
887
887
/// Inverting the mark bit doesn't affect the
888
888
/// grey state
889
- Grey ,
889
+ Grey = 3 ,
890
890
/// Normally this marks the blue state
891
891
///
892
892
/// If we're inverted, this marks white
893
- Blue
893
+ Blue = 1
894
894
}
895
895
impl RawMarkState {
896
896
#[ inline]
897
897
fn resolve ( self , inverted_mark : bool ) -> MarkState {
898
- match ( self , inverted_mark) {
899
- ( RawMarkState :: Red , false ) => MarkState :: White ,
900
- ( RawMarkState :: Red , true ) => MarkState :: Black ,
901
- ( RawMarkState :: Grey , _) => MarkState :: Grey ,
902
- ( RawMarkState :: Blue , false ) => MarkState :: Black ,
903
- ( RawMarkState :: Blue , true ) => MarkState :: White
898
+ let expected: MarkState ;
899
+ #[ cfg( debug_assertions) ] {
900
+ expected = match ( self , inverted_mark) {
901
+ ( RawMarkState :: Red , false ) => MarkState :: White ,
902
+ ( RawMarkState :: Red , true ) => MarkState :: Black ,
903
+ ( RawMarkState :: Grey , _) => MarkState :: Grey ,
904
+ ( RawMarkState :: Blue , false ) => MarkState :: Black ,
905
+ ( RawMarkState :: Blue , true ) => MarkState :: White
906
+ } ;
907
+ }
908
+ /*
909
+ * Bit magic works as expected (both ways):
910
+ * (self as u8) ^ (inverted_mark as u8) => (res_bits as MarkState)
911
+ * (Red => 0u8) ^ (false as 0u8) => (0u8 as White)
912
+ * (Red => 0u8) ^ (true as 1u8) => (1u8 as Black)
913
+ * (Grey => 3u8) ^ (false as 0u8) => (3u8 as Grey)
914
+ * (Grey => 3u8) ^ (true as 1u8) => (3u8 as Grey)
915
+ * (Blue => 1u8) ^ (false as 0u8) => (1u8 as Black)
916
+ * (Blue => 1u8) ^ (true as 1u8) => (0u8 as White)
917
+ */
918
+ let bits = ( self as u8 ) ^ ( inverted_mark as u8 ) ;
919
+ #[ cfg( debug_assertions) ] {
920
+ debug_assert_eq ! ( expected as u8 , bits) ;
904
921
}
922
+ unsafe { std:: mem:: transmute :: < u8 , MarkState > ( bits) }
905
923
}
906
924
}
907
925
@@ -915,25 +933,37 @@ enum MarkState {
915
933
///
916
934
/// Once all the objects have been marked,
917
935
/// all remaining white objects will be freed.
918
- White ,
936
+ White = 0 ,
919
937
/// The object is in the gray set and needs to be traversed to look for reachable memory
920
938
///
921
939
/// After being scanned this object will end up in the black set.
922
- Grey ,
940
+ Grey = 3 ,
923
941
/// The object is in the black set and is reachable from the roots.
924
942
///
925
943
/// This object cannot be freed.
926
- Black
944
+ Black = 1
927
945
}
928
946
impl MarkState {
929
947
#[ inline]
930
948
fn to_raw ( self , inverted_mark : bool ) -> RawMarkState {
931
- match ( self , inverted_mark) {
932
- ( MarkState :: White , false ) => RawMarkState :: Red ,
933
- ( MarkState :: White , true ) => RawMarkState :: Blue ,
934
- ( MarkState :: Grey , _) => RawMarkState :: Grey ,
935
- ( MarkState :: Black , false ) => RawMarkState :: Blue ,
936
- ( MarkState :: Black , true ) => RawMarkState :: Red ,
949
+ let expected: RawMarkState ;
950
+ #[ cfg( debug_assertions) ] {
951
+ expected = match ( self , inverted_mark) {
952
+ ( MarkState :: White , false ) => RawMarkState :: Red ,
953
+ ( MarkState :: White , true ) => RawMarkState :: Blue ,
954
+ ( MarkState :: Grey , _) => RawMarkState :: Grey ,
955
+ ( MarkState :: Black , false ) => RawMarkState :: Blue ,
956
+ ( MarkState :: Black , true ) => RawMarkState :: Red ,
957
+ } ;
958
+ }
959
+ /*
960
+ * Bit magic is reverse of `RawMarkState::resolved`
961
+ * The justification there works two ways
962
+ */
963
+ let bits = ( self as u8 ) ^ ( inverted_mark as u8 ) ;
964
+ #[ cfg( debug_assertions) ] {
965
+ debug_assert_eq ! ( expected as u8 , bits) ;
937
966
}
967
+ unsafe { std:: mem:: transmute :: < u8 , RawMarkState > ( bits) }
938
968
}
939
969
}
0 commit comments