@@ -141,7 +141,7 @@ pub(crate) trait Stage1Parse {
141141 type Utf8Validator : ChunkedUtf8Validator ;
142142 type SimdRepresentation ;
143143
144- unsafe fn new ( ptr : & [ u8 ] ) -> Self ;
144+ unsafe fn new ( ptr : [ u8 ; SIMDINPUT_LENGTH ] ) -> Self ;
145145
146146 unsafe fn compute_quote_mask ( quote_bits : u64 ) -> u64 ;
147147
@@ -698,10 +698,11 @@ impl<'de> Deserializer<'de> {
698698 #[ cfg( all( target_arch = "aarch64" , not( feature = "portable" ) ) ) ]
699699 #[ cfg_attr( not( feature = "no-inline" ) , inline) ]
700700 pub ( crate ) unsafe fn find_structural_bits (
701- input : & [ u8 ] ,
701+ input : & AlignedBuf ,
702+ len : usize ,
702703 structural_indexes : & mut Vec < u32 > ,
703704 ) -> std:: result:: Result < ( ) , ErrorType > {
704- Self :: _find_structural_bits :: < impls:: neon:: SimdInput > ( input, structural_indexes)
705+ Self :: _find_structural_bits :: < impls:: neon:: SimdInput > ( input, len , structural_indexes)
705706 }
706707
707708 #[ cfg( all( target_feature = "simd128" , not( feature = "portable" ) ) ) ]
@@ -758,7 +759,7 @@ impl<'de> Deserializer<'de> {
758759 buffer : & mut Buffers ,
759760 tape : & mut Vec < Node < ' de > > ,
760761 ) -> Result < ( ) > {
761- const LOTS_OF_ZOERS : [ u8 ; SIMDINPUT_LENGTH ] = [ 0 ; SIMDINPUT_LENGTH ] ;
762+ const LOTS_OF_ZOERS : [ u8 ; SIMDINPUT_LENGTH ] = [ 0x20 ; SIMDINPUT_LENGTH ] ;
762763 let len = input. len ( ) ;
763764 let simd_safe_len = len + SIMDINPUT_LENGTH ;
764765
@@ -793,7 +794,7 @@ impl<'de> Deserializer<'de> {
793794 // safety: all bytes are initialized
794795 input_buffer. set_len ( simd_safe_len) ;
795796
796- Self :: find_structural_bits ( input, & mut buffer. structural_indexes )
797+ Self :: find_structural_bits ( input_buffer , input. len ( ) , & mut buffer. structural_indexes )
797798 . map_err ( Error :: generic) ?;
798799 } ;
799800
@@ -844,10 +845,11 @@ impl<'de> Deserializer<'de> {
844845 #[ cfg_attr( not( feature = "no-inline" ) , inline) ]
845846 #[ allow( clippy:: cast_possible_truncation) ]
846847 pub ( crate ) unsafe fn _find_structural_bits < S : Stage1Parse > (
847- input : & [ u8 ] ,
848+ input : & AlignedBuf ,
849+ len : usize ,
848850 structural_indexes : & mut Vec < u32 > ,
849851 ) -> std:: result:: Result < ( ) , ErrorType > {
850- let len = input. len ( ) ;
852+ // let len = input.len();
851853 // 8 is a heuristic number to estimate it turns out a rate of 1/8 structural characters
852854 // leads almost never to relocations.
853855 structural_indexes. clear ( ) ;
@@ -879,18 +881,18 @@ impl<'de> Deserializer<'de> {
879881 // expensive carryless multiply in the previous step with this work
880882 let mut structurals: u64 = 0 ;
881883
882- let lenminus64: usize = if len < 64 { 0 } else { len - 64 } ;
884+ // let lenminus64: usize = if len < 64 { 0 } else { len - 64 };
883885 let mut idx: usize = 0 ;
884886 let mut error_mask: u64 = 0 ; // for unescaped characters within strings (ASCII code points < 0x20)
885887
886- while idx < lenminus64 {
888+ while idx <= len / SIMDINPUT_LENGTH {
887889 /*
888890 #ifndef _MSC_VER
889891 __builtin_prefetch(buf + idx + 128);
890892 #endif
891893 */
892- let chunk = input. get_kinda_unchecked ( idx..idx + 64 ) ;
893- utf8_validator. update_from_chunks ( chunk) ;
894+ let chunk: [ u8 ; SIMDINPUT_LENGTH ] = input. load_register ( idx) ;
895+ utf8_validator. update_from_chunks ( & chunk) ;
894896
895897 let input = S :: new ( chunk) ;
896898 // detect odd sequences of backslashes
@@ -909,7 +911,7 @@ impl<'de> Deserializer<'de> {
909911
910912 // take the previous iterations structural bits, not our current iteration,
911913 // and flatten
912- S :: flatten_bits ( structural_indexes, idx as u32 , structurals) ;
914+ S :: flatten_bits ( structural_indexes, ( idx * 64 ) as u32 , structurals) ;
913915
914916 let mut whitespace: u64 = 0 ;
915917 input. find_whitespace_and_structurals ( & mut whitespace, & mut structurals) ;
@@ -922,58 +924,15 @@ impl<'de> Deserializer<'de> {
922924 quote_bits,
923925 & mut prev_iter_ends_pseudo_pred,
924926 ) ;
925- idx += SIMDINPUT_LENGTH ;
927+ idx += 1 ;
926928 }
927929
928- // we use a giant copy-paste which is ugly.
929- // but otherwise the string needs to be properly padded or else we
930- // risk invalidating the UTF-8 checks.
931- if idx < len {
932- let mut tmpbuf: [ u8 ; SIMDINPUT_LENGTH ] = [ 0x20 ; SIMDINPUT_LENGTH ] ;
933- tmpbuf
934- . as_mut_ptr ( )
935- . copy_from ( input. as_ptr ( ) . add ( idx) , len - idx) ;
936- utf8_validator. update_from_chunks ( & tmpbuf) ;
937-
938- let input = S :: new ( & tmpbuf) ;
939-
940- // detect odd sequences of backslashes
941- let odd_ends: u64 =
942- input. find_odd_backslash_sequences ( & mut prev_iter_ends_odd_backslash) ;
943-
944- // detect insides of quote pairs ("quote_mask") and also our quote_bits
945- // themselves
946- let mut quote_bits: u64 = 0 ;
947- let quote_mask: u64 = input. find_quote_mask_and_bits (
948- odd_ends,
949- & mut prev_iter_inside_quote,
950- & mut quote_bits,
951- & mut error_mask,
952- ) ;
953-
954- // take the previous iterations structural bits, not our current iteration,
955- // and flatten
956- S :: flatten_bits ( structural_indexes, idx as u32 , structurals) ;
957-
958- let mut whitespace: u64 = 0 ;
959- input. find_whitespace_and_structurals ( & mut whitespace, & mut structurals) ;
960-
961- // fixup structurals to reflect quotes and add pseudo-structural characters
962- structurals = S :: finalize_structurals (
963- structurals,
964- whitespace,
965- quote_mask,
966- quote_bits,
967- & mut prev_iter_ends_pseudo_pred,
968- ) ;
969- idx += SIMDINPUT_LENGTH ;
970- }
971930 // This test isn't in upstream, for some reason the error mask is et for then.
972931 if prev_iter_inside_quote != 0 {
973932 return Err ( ErrorType :: Syntax ) ;
974933 }
975934 // finally, flatten out the remaining structurals from the last iteration
976- S :: flatten_bits ( structural_indexes, idx as u32 , structurals) ;
935+ S :: flatten_bits ( structural_indexes, ( idx * 64 ) as u32 , structurals) ;
977936
978937 // a valid JSON file cannot have zero structural indexes - we should have
979938 // found something (note that we compare to 1 as we always add the root!)
@@ -1012,13 +971,21 @@ impl AlignedBuf {
1012971 /// Creates a new buffer that is aligned with the simd register size
1013972 #[ must_use]
1014973 pub fn with_capacity ( capacity : usize ) -> Self {
1015- let layout = match Layout :: from_size_align ( capacity, SIMDJSON_PADDING ) {
1016- Ok ( layout) => layout,
1017- Err ( _) => Self :: capacity_overflow ( ) ,
974+ let offset = capacity % SIMDINPUT_LENGTH ;
975+ let capacity = if offset == 0 {
976+ capacity
977+ } else {
978+ capacity + SIMDINPUT_LENGTH - offset
1018979 } ;
980+
1019981 if mem:: size_of :: < usize > ( ) < 8 && capacity > isize:: MAX as usize {
1020982 Self :: capacity_overflow ( )
1021983 }
984+ let layout = match Layout :: from_size_align ( capacity, SIMDINPUT_LENGTH ) {
985+ Ok ( layout) => layout,
986+ Err ( _) => Self :: capacity_overflow ( ) ,
987+ } ;
988+
1022989 let inner = match unsafe { NonNull :: new ( alloc ( layout) ) } {
1023990 Some ( ptr) => ptr,
1024991 None => handle_alloc_error ( layout) ,
@@ -1031,6 +998,14 @@ impl AlignedBuf {
1031998 }
1032999 }
10331000
1001+ unsafe fn load_register ( & self , idx : usize ) -> [ u8 ; SIMDINPUT_LENGTH ] {
1002+ self . inner
1003+ . as_ptr ( )
1004+ . cast :: < [ u8 ; SIMDINPUT_LENGTH ] > ( )
1005+ . add ( idx)
1006+ . read ( )
1007+ }
1008+
10341009 fn as_mut_ptr ( & mut self ) -> * mut u8 {
10351010 self . inner . as_ptr ( )
10361011 }
0 commit comments