@@ -242,7 +242,7 @@ pub(crate) trait Stage1Parse {
242
242
type Utf8Validator : ChunkedUtf8Validator ;
243
243
type SimdRepresentation ;
244
244
245
- unsafe fn new ( ptr : & [ u8 ] ) -> Self ;
245
+ unsafe fn new ( ptr : [ u8 ; SIMDINPUT_LENGTH ] ) -> Self ;
246
246
247
247
unsafe fn compute_quote_mask ( quote_bits : u64 ) -> u64 ;
248
248
@@ -799,10 +799,11 @@ impl<'de> Deserializer<'de> {
799
799
#[ cfg( all( target_arch = "aarch64" , not( feature = "portable" ) ) ) ]
800
800
#[ cfg_attr( not( feature = "no-inline" ) , inline) ]
801
801
pub ( crate ) unsafe fn find_structural_bits (
802
- input : & [ u8 ] ,
802
+ input : & AlignedBuf ,
803
+ len : usize ,
803
804
structural_indexes : & mut Vec < u32 > ,
804
805
) -> std:: result:: Result < ( ) , ErrorType > {
805
- Self :: _find_structural_bits :: < impls:: neon:: SimdInput > ( input, structural_indexes)
806
+ Self :: _find_structural_bits :: < impls:: neon:: SimdInput > ( input, len , structural_indexes)
806
807
}
807
808
808
809
#[ cfg( all( target_feature = "simd128" , not( feature = "portable" ) ) ) ]
@@ -859,7 +860,7 @@ impl<'de> Deserializer<'de> {
859
860
buffer : & mut Buffers ,
860
861
tape : & mut Vec < Node < ' de > > ,
861
862
) -> Result < ( ) > {
862
- const LOTS_OF_ZOERS : [ u8 ; SIMDINPUT_LENGTH ] = [ 0 ; SIMDINPUT_LENGTH ] ;
863
+ const LOTS_OF_ZOERS : [ u8 ; SIMDINPUT_LENGTH ] = [ 0x20 ; SIMDINPUT_LENGTH ] ;
863
864
let len = input. len ( ) ;
864
865
let simd_safe_len = len + SIMDINPUT_LENGTH ;
865
866
@@ -894,7 +895,7 @@ impl<'de> Deserializer<'de> {
894
895
// safety: all bytes are initialized
895
896
input_buffer. set_len ( simd_safe_len) ;
896
897
897
- Self :: find_structural_bits ( input, & mut buffer. structural_indexes )
898
+ Self :: find_structural_bits ( input_buffer , input. len ( ) , & mut buffer. structural_indexes )
898
899
. map_err ( Error :: generic) ?;
899
900
} ;
900
901
@@ -945,10 +946,11 @@ impl<'de> Deserializer<'de> {
945
946
#[ cfg_attr( not( feature = "no-inline" ) , inline) ]
946
947
#[ allow( clippy:: cast_possible_truncation) ]
947
948
pub ( crate ) unsafe fn _find_structural_bits < S : Stage1Parse > (
948
- input : & [ u8 ] ,
949
+ input : & AlignedBuf ,
950
+ len : usize ,
949
951
structural_indexes : & mut Vec < u32 > ,
950
952
) -> std:: result:: Result < ( ) , ErrorType > {
951
- let len = input. len ( ) ;
953
+ // let len = input.len();
952
954
// 8 is a heuristic number to estimate it turns out a rate of 1/8 structural characters
953
955
// leads almost never to relocations.
954
956
structural_indexes. clear ( ) ;
@@ -980,18 +982,18 @@ impl<'de> Deserializer<'de> {
980
982
// expensive carryless multiply in the previous step with this work
981
983
let mut structurals: u64 = 0 ;
982
984
983
- let lenminus64: usize = if len < 64 { 0 } else { len - 64 } ;
985
+ // let lenminus64: usize = if len < 64 { 0 } else { len - 64 };
984
986
let mut idx: usize = 0 ;
985
987
let mut error_mask: u64 = 0 ; // for unescaped characters within strings (ASCII code points < 0x20)
986
988
987
- while idx < lenminus64 {
989
+ while idx <= len / SIMDINPUT_LENGTH {
988
990
/*
989
991
#ifndef _MSC_VER
990
992
__builtin_prefetch(buf + idx + 128);
991
993
#endif
992
994
*/
993
- let chunk = input. get_kinda_unchecked ( idx..idx + 64 ) ;
994
- utf8_validator. update_from_chunks ( chunk) ;
995
+ let chunk: [ u8 ; SIMDINPUT_LENGTH ] = input. load_register ( idx) ;
996
+ utf8_validator. update_from_chunks ( & chunk) ;
995
997
996
998
let input = S :: new ( chunk) ;
997
999
// detect odd sequences of backslashes
@@ -1010,7 +1012,7 @@ impl<'de> Deserializer<'de> {
1010
1012
1011
1013
// take the previous iterations structural bits, not our current iteration,
1012
1014
// and flatten
1013
- S :: flatten_bits ( structural_indexes, idx as u32 , structurals) ;
1015
+ S :: flatten_bits ( structural_indexes, ( idx * 64 ) as u32 , structurals) ;
1014
1016
1015
1017
let mut whitespace: u64 = 0 ;
1016
1018
input. find_whitespace_and_structurals ( & mut whitespace, & mut structurals) ;
@@ -1023,58 +1025,15 @@ impl<'de> Deserializer<'de> {
1023
1025
quote_bits,
1024
1026
& mut prev_iter_ends_pseudo_pred,
1025
1027
) ;
1026
- idx += SIMDINPUT_LENGTH ;
1028
+ idx += 1 ;
1027
1029
}
1028
1030
1029
- // we use a giant copy-paste which is ugly.
1030
- // but otherwise the string needs to be properly padded or else we
1031
- // risk invalidating the UTF-8 checks.
1032
- if idx < len {
1033
- let mut tmpbuf: [ u8 ; SIMDINPUT_LENGTH ] = [ 0x20 ; SIMDINPUT_LENGTH ] ;
1034
- tmpbuf
1035
- . as_mut_ptr ( )
1036
- . copy_from ( input. as_ptr ( ) . add ( idx) , len - idx) ;
1037
- utf8_validator. update_from_chunks ( & tmpbuf) ;
1038
-
1039
- let input = S :: new ( & tmpbuf) ;
1040
-
1041
- // detect odd sequences of backslashes
1042
- let odd_ends: u64 =
1043
- input. find_odd_backslash_sequences ( & mut prev_iter_ends_odd_backslash) ;
1044
-
1045
- // detect insides of quote pairs ("quote_mask") and also our quote_bits
1046
- // themselves
1047
- let mut quote_bits: u64 = 0 ;
1048
- let quote_mask: u64 = input. find_quote_mask_and_bits (
1049
- odd_ends,
1050
- & mut prev_iter_inside_quote,
1051
- & mut quote_bits,
1052
- & mut error_mask,
1053
- ) ;
1054
-
1055
- // take the previous iterations structural bits, not our current iteration,
1056
- // and flatten
1057
- S :: flatten_bits ( structural_indexes, idx as u32 , structurals) ;
1058
-
1059
- let mut whitespace: u64 = 0 ;
1060
- input. find_whitespace_and_structurals ( & mut whitespace, & mut structurals) ;
1061
-
1062
- // fixup structurals to reflect quotes and add pseudo-structural characters
1063
- structurals = S :: finalize_structurals (
1064
- structurals,
1065
- whitespace,
1066
- quote_mask,
1067
- quote_bits,
1068
- & mut prev_iter_ends_pseudo_pred,
1069
- ) ;
1070
- idx += SIMDINPUT_LENGTH ;
1071
- }
1072
1031
// This test isn't in upstream, for some reason the error mask is et for then.
1073
1032
if prev_iter_inside_quote != 0 {
1074
1033
return Err ( ErrorType :: Syntax ) ;
1075
1034
}
1076
1035
// finally, flatten out the remaining structurals from the last iteration
1077
- S :: flatten_bits ( structural_indexes, idx as u32 , structurals) ;
1036
+ S :: flatten_bits ( structural_indexes, ( idx * 64 ) as u32 , structurals) ;
1078
1037
1079
1038
// a valid JSON file cannot have zero structural indexes - we should have
1080
1039
// found something (note that we compare to 1 as we always add the root!)
@@ -1113,13 +1072,21 @@ impl AlignedBuf {
1113
1072
/// Creates a new buffer that is aligned with the simd register size
1114
1073
#[ must_use]
1115
1074
pub fn with_capacity ( capacity : usize ) -> Self {
1116
- let layout = match Layout :: from_size_align ( capacity, SIMDJSON_PADDING ) {
1117
- Ok ( layout) => layout,
1118
- Err ( _) => Self :: capacity_overflow ( ) ,
1075
+ let offset = capacity % SIMDINPUT_LENGTH ;
1076
+ let capacity = if offset == 0 {
1077
+ capacity
1078
+ } else {
1079
+ capacity + SIMDINPUT_LENGTH - offset
1119
1080
} ;
1081
+
1120
1082
if mem:: size_of :: < usize > ( ) < 8 && capacity > isize:: MAX as usize {
1121
1083
Self :: capacity_overflow ( )
1122
1084
}
1085
+ let layout = match Layout :: from_size_align ( capacity, SIMDINPUT_LENGTH ) {
1086
+ Ok ( layout) => layout,
1087
+ Err ( _) => Self :: capacity_overflow ( ) ,
1088
+ } ;
1089
+
1123
1090
let inner = match unsafe { NonNull :: new ( alloc ( layout) ) } {
1124
1091
Some ( ptr) => ptr,
1125
1092
None => handle_alloc_error ( layout) ,
@@ -1132,6 +1099,14 @@ impl AlignedBuf {
1132
1099
}
1133
1100
}
1134
1101
1102
+ unsafe fn load_register ( & self , idx : usize ) -> [ u8 ; SIMDINPUT_LENGTH ] {
1103
+ self . inner
1104
+ . as_ptr ( )
1105
+ . cast :: < [ u8 ; SIMDINPUT_LENGTH ] > ( )
1106
+ . add ( idx)
1107
+ . read ( )
1108
+ }
1109
+
1135
1110
fn as_mut_ptr ( & mut self ) -> * mut u8 {
1136
1111
self . inner . as_ptr ( )
1137
1112
}
0 commit comments