@@ -95,6 +95,12 @@ static rb_encoding *enc_utf8;
9595
9696#define JSON_RVALUE_CACHE_MAX_ENTRY_LENGTH 55
9797
98+ #if (defined(__GNUC__ ) || defined(__clang__ ))
99+ #define FORCE_INLINE __attribute__((always_inline))
100+ #else
101+ #define FORCE_INLINE
102+ #endif
103+
98104static inline VALUE build_interned_string (const char * str , const long length )
99105{
100106# ifdef HAVE_RB_ENC_INTERNED_STR
@@ -117,17 +123,51 @@ static void rvalue_cache_insert_at(rvalue_cache *cache, int index, VALUE rstring
117123 cache -> entries [index ] = rstring ;
118124}
119125
120- static inline int rstring_cache_cmp (const char * str , const long length , VALUE rstring )
126+ static inline FORCE_INLINE int rstring_cache_cmp (const char * str , const long length , VALUE rstring )
121127{
128+ #if defined(__BYTE_ORDER__ ) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) && defined(__has_builtin ) && __has_builtin (__builtin_bswap64 )
129+ const char * rptr ;
130+ long rstring_length ;
131+
132+ RSTRING_GETMEM (rstring , rptr , rstring_length );
133+
134+ if (length != rstring_length ) {
135+ return (int )(length - rstring_length );
136+ }
137+
138+ long i = 0 ;
139+
140+ for (; i + 8 <= length ; i += 8 ) {
141+ uint64_t a , b ;
142+ memcpy (& a , str + i , 8 );
143+ memcpy (& b , rptr + i , 8 );
144+ if (a != b ) {
145+ a = __builtin_bswap64 (a );
146+ b = __builtin_bswap64 (b );
147+ return (a < b ) ? -1 : 1 ;
148+ }
149+ }
150+
151+ for (; i < length ; i ++ ) {
152+ unsigned char ca = (unsigned char )str [i ];
153+ unsigned char cb = (unsigned char )rptr [i ];
154+ if (ca != cb ) {
155+ return (ca < cb ) ? -1 : 1 ;
156+ }
157+ }
158+
159+ return 0 ;
160+ #else
122161 long rstring_length = RSTRING_LEN (rstring );
123162 if (length == rstring_length ) {
124163 return memcmp (str , RSTRING_PTR (rstring ), length );
125164 } else {
126165 return (int )(length - rstring_length );
127166 }
167+ #endif
128168}
129169
130- static VALUE rstring_cache_fetch (rvalue_cache * cache , const char * str , const long length )
170+ static inline FORCE_INLINE VALUE rstring_cache_fetch (rvalue_cache * cache , const char * str , const long length )
131171{
132172 if (RB_UNLIKELY (length > JSON_RVALUE_CACHE_MAX_ENTRY_LENGTH )) {
133173 // Common names aren't likely to be very long. So we just don't
@@ -144,37 +184,25 @@ static VALUE rstring_cache_fetch(rvalue_cache *cache, const char *str, const lon
144184
145185 int low = 0 ;
146186 int high = cache -> length - 1 ;
147- int mid = 0 ;
148- int last_cmp = 0 ;
149187
150188 while (low <= high ) {
151- mid = (high + low ) >> 1 ;
189+ int mid = (high + low ) >> 1 ;
152190 VALUE entry = cache -> entries [mid ];
153- last_cmp = rstring_cache_cmp (str , length , entry );
191+ int cmp = rstring_cache_cmp (str , length , entry );
154192
155- if (last_cmp == 0 ) {
193+ if (cmp == 0 ) {
156194 return entry ;
157- } else if (last_cmp > 0 ) {
195+ } else if (cmp > 0 ) {
158196 low = mid + 1 ;
159197 } else {
160198 high = mid - 1 ;
161199 }
162200 }
163201
164- if (RB_UNLIKELY (memchr (str , '\\' , length ))) {
165- // We assume the overwhelming majority of names don't need to be escaped.
166- // But if they do, we have to fallback to the slow path.
167- return Qfalse ;
168- }
169-
170202 VALUE rstring = build_interned_string (str , length );
171203
172204 if (cache -> length < JSON_RVALUE_CACHE_CAPA ) {
173- if (last_cmp > 0 ) {
174- mid += 1 ;
175- }
176-
177- rvalue_cache_insert_at (cache , mid , rstring );
205+ rvalue_cache_insert_at (cache , low , rstring );
178206 }
179207 return rstring ;
180208}
@@ -596,7 +624,7 @@ json_eat_comments(JSON_ParserState *state)
596624 }
597625}
598626
599- static inline void
627+ static inline FORCE_INLINE void
600628json_eat_whitespace (JSON_ParserState * state )
601629{
602630 while (true) {
@@ -985,12 +1013,6 @@ static const bool string_scan_table[256] = {
9851013 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
9861014};
9871015
988- #if (defined(__GNUC__ ) || defined(__clang__ ))
989- #define FORCE_INLINE __attribute__((always_inline))
990- #else
991- #define FORCE_INLINE
992- #endif
993-
9941016#ifdef HAVE_SIMD
9951017static SIMD_Implementation simd_impl = SIMD_NONE ;
9961018#endif /* HAVE_SIMD */
0 commit comments