@@ -975,9 +975,9 @@ trait FromStrRadixHelper: PartialOrd + Copy {
975975 fn checked_mul ( & self , other : u32 ) -> Option < Self > ;
976976 fn checked_sub ( & self , other : u32 ) -> Option < Self > ;
977977 fn checked_add ( & self , other : u32 ) -> Option < Self > ;
978- unsafe fn unchecked_mul ( & self , other : u32 ) -> Self ;
979- unsafe fn unchecked_sub ( & self , other : u32 ) -> Self ;
980- unsafe fn unchecked_add ( & self , other : u32 ) -> Self ;
978+ unsafe fn unchecked_mul ( self , other : u32 ) -> Self ;
979+ unsafe fn unchecked_sub ( self , other : u32 ) -> Self ;
980+ unsafe fn unchecked_add ( self , other : u32 ) -> Self ;
981981}
982982
983983macro_rules! from_str_radix_int_impl {
@@ -993,7 +993,7 @@ macro_rules! from_str_radix_int_impl {
993993}
994994from_str_radix_int_impl ! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 }
995995
996- macro_rules! doit {
996+ macro_rules! impl_helper_for {
997997 ( $( $t: ty) * ) => ( $( impl FromStrRadixHelper for $t {
998998 const MIN : Self = Self :: MIN ;
999999 #[ inline]
@@ -1011,29 +1011,29 @@ macro_rules! doit {
10111011 Self :: checked_add( * self , other as Self )
10121012 }
10131013 #[ inline]
1014- unsafe fn unchecked_mul( & self , other: u32 ) -> Self {
1014+ unsafe fn unchecked_mul( self , other: u32 ) -> Self {
10151015 // SAFETY: Conditions of `Self::unchecked_mul` must be upheld by the caller.
10161016 unsafe {
1017- Self :: unchecked_mul( * self , other as Self )
1017+ Self :: unchecked_mul( self , other as Self )
10181018 }
10191019 }
10201020 #[ inline]
1021- unsafe fn unchecked_sub( & self , other: u32 ) -> Self {
1021+ unsafe fn unchecked_sub( self , other: u32 ) -> Self {
10221022 // SAFETY: Conditions of `Self::unchecked_sub` must be upheld by the caller.
10231023 unsafe {
1024- Self :: unchecked_sub( * self , other as Self )
1024+ Self :: unchecked_sub( self , other as Self )
10251025 }
10261026 }
10271027 #[ inline]
1028- unsafe fn unchecked_add( & self , other: u32 ) -> Self {
1028+ unsafe fn unchecked_add( self , other: u32 ) -> Self {
10291029 // SAFETY: Conditions of `Self::unchecked_add` must be upheld by the caller.
10301030 unsafe {
1031- Self :: unchecked_add( * self , other as Self )
1031+ Self :: unchecked_add( self , other as Self )
10321032 }
10331033 }
10341034 } ) * )
10351035}
1036- doit ! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
1036+ impl_helper_for ! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
10371037
10381038fn from_str_radix < T : FromStrRadixHelper > ( src : & str , radix : u32 ) -> Result < T , ParseIntError > {
10391039 use self :: IntErrorKind :: * ;
@@ -1078,41 +1078,49 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
10781078 // `u8::MAX` is `ff` - any str of len 2 is guaranteed to not overflow.
10791079 // `i8::MAX` is `7f` - only a str of len 1 is guaranteed to not overflow.
10801080 unsafe {
1081- macro_rules! run_loop {
1081+ macro_rules! run_unchecked_loop {
10821082 ( $unchecked_additive_op: ident) => {
10831083 for & c in digits {
10841084 result = result. unchecked_mul( radix) ;
10851085 let x = ( c as char ) . to_digit( radix) . ok_or( PIE { kind: InvalidDigit } ) ?;
1086- result = T :: $unchecked_additive_op( & result, x) ;
1086+ result = T :: $unchecked_additive_op( result, x) ;
10871087 }
10881088 } ;
10891089 }
10901090 if is_positive {
1091- run_loop ! ( unchecked_add)
1091+ run_unchecked_loop ! ( unchecked_add)
10921092 } else {
1093- run_loop ! ( unchecked_sub)
1093+ run_unchecked_loop ! ( unchecked_sub)
10941094 } ;
10951095 }
1096- } else {
1097- let additive_op = if is_positive { T :: checked_add } else { T :: checked_sub } ;
1098- let overflow_err = || PIE { kind : if is_positive { PosOverflow } else { NegOverflow } } ;
1099-
1100- for & c in digits {
1101- // When `radix` is passed in as a literal, rather than doing a slow `imul`
1102- // the compiler can use shifts if `radix` can be expressed as a
1103- // sum of powers of 2 (x*10 can be written as x*8 + x*2).
1104- // When the compiler can't use these optimisations,
1105- // the latency of the multiplication can be hidden by issuing it
1106- // before the result is needed to improve performance on
1107- // modern out-of-order CPU as multiplication here is slower
1108- // than the other instructions, we can get the end result faster
1109- // doing multiplication first and let the CPU spends other cycles
1110- // doing other computation and get multiplication result later.
1111- let mul = result. checked_mul ( radix) ;
1112- let x = ( c as char ) . to_digit ( radix) . ok_or ( PIE { kind : InvalidDigit } ) ?;
1113- result = mul. ok_or_else ( overflow_err) ?;
1114- result = additive_op ( & result, x) . ok_or_else ( overflow_err) ?;
1096+ } else {
1097+ macro_rules! run_checked_loop {
1098+ ( $checked_additive_op: ident, $overflow_err: ident) => {
1099+ for & c in digits {
1100+ // When `radix` is passed in as a literal, rather than doing a slow `imul`
1101+ // the compiler can use shifts if `radix` can be expressed as a
1102+ // sum of powers of 2 (x*10 can be written as x*8 + x*2).
1103+ // When the compiler can't use these optimisations,
1104+ // the latency of the multiplication can be hidden by issuing it
1105+ // before the result is needed to improve performance on
1106+ // modern out-of-order CPU as multiplication here is slower
1107+ // than the other instructions, we can get the end result faster
1108+ // doing multiplication first and let the CPU spends other cycles
1109+ // doing other computation and get multiplication result later.
1110+ let mul = result. checked_mul( radix) ;
1111+ let x = ( c as char ) . to_digit( radix) . ok_or( PIE { kind: InvalidDigit } ) ?;
1112+ result = mul. ok_or_else( $overflow_err) ?;
1113+ result = T :: $checked_additive_op( & result, x) . ok_or_else( $overflow_err) ?;
1114+ }
1115+ }
11151116 }
1117+ if is_positive {
1118+ let overflow_err = || PIE { kind : PosOverflow } ;
1119+ run_checked_loop ! ( checked_add, overflow_err)
1120+ } else {
1121+ let overflow_err = || PIE { kind : NegOverflow } ;
1122+ run_checked_loop ! ( checked_sub, overflow_err)
1123+ } ;
11161124 }
11171125 Ok ( result)
11181126}
0 commit comments