Skip to content

Commit 6a488fa

Browse files
committed
WIP
1 parent 062fcdd commit 6a488fa

3 files changed

Lines changed: 49 additions & 51 deletions

File tree

ext/json/ext/generator/generator.c

Lines changed: 46 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,10 @@ typedef struct _search_state {
118118
#ifdef HAVE_SIMD
119119
const char *chunk_base;
120120
const char *chunk_end;
121-
bool has_matches;
121+
// bool has_matches;
122122

123123
#if defined(HAVE_SIMD_NEON)
124-
uint64_t matches_mask;
124+
// uint64_t matches_mask;
125125
#elif defined(HAVE_SIMD_SSE2)
126126
int matches_mask;
127127
#else
@@ -174,21 +174,23 @@ static inline unsigned char search_escape_basic(search_state *search)
174174
ALWAYS_INLINE(static) void escape_UTF8_char_basic(search_state *search)
175175
{
176176
const unsigned char ch = (unsigned char)*search->ptr;
177+
fbuffer_inc_capa(search->buffer, 6);
178+
fbuffer_append_reserved_char(search->buffer, '\\');
177179
switch (ch) {
178-
case '"': fbuffer_append(search->buffer, "\\\"", 2); break;
179-
case '\\': fbuffer_append(search->buffer, "\\\\", 2); break;
180-
case '/': fbuffer_append(search->buffer, "\\/", 2); break;
181-
case '\b': fbuffer_append(search->buffer, "\\b", 2); break;
182-
case '\f': fbuffer_append(search->buffer, "\\f", 2); break;
183-
case '\n': fbuffer_append(search->buffer, "\\n", 2); break;
184-
case '\r': fbuffer_append(search->buffer, "\\r", 2); break;
185-
case '\t': fbuffer_append(search->buffer, "\\t", 2); break;
180+
case '"': fbuffer_append_reserved_char(search->buffer, '"'); break;
181+
case '\\': fbuffer_append_reserved_char(search->buffer, '\\'); break;
182+
case '/': fbuffer_append_reserved_char(search->buffer, '/'); break;
183+
case '\b': fbuffer_append_reserved_char(search->buffer, 'b'); break;
184+
case '\f': fbuffer_append_reserved_char(search->buffer, 'f'); break;
185+
case '\n': fbuffer_append_reserved_char(search->buffer, 'n'); break;
186+
case '\r': fbuffer_append_reserved_char(search->buffer, 'r'); break;
187+
case '\t': fbuffer_append_reserved_char(search->buffer, 't'); break;
186188
default: {
187189
const char *hexdig = "0123456789abcdef";
188-
char scratch[6] = { '\\', 'u', '0', '0', 0, 0 };
189-
scratch[4] = hexdig[(ch >> 4) & 0xf];
190-
scratch[5] = hexdig[ch & 0xf];
191-
fbuffer_append(search->buffer, scratch, 6);
190+
char scratch[5] = { 'u', '0', '0', 0, 0 };
191+
scratch[3] = hexdig[(ch >> 4) & 0xf];
192+
scratch[4] = hexdig[ch & 0xf];
193+
fbuffer_append(search->buffer, scratch, 5);
192194
break;
193195
}
194196
}
@@ -215,7 +217,8 @@ ALWAYS_INLINE(static) void escape_UTF8_char_basic(search_state *search)
215217

216218

217219
#if defined(HAVE_SIMD_NEON)
218-
static inline unsigned char search_escape_basic_neon(search_state *search);
220+
static inline uint64_t search_escape_basic_neon(search_state *search);
221+
static inline uint64_t neon_next_match(uint64_t mask, search_state *search);
219222
#elif defined(HAVE_SIMD_SSE2)
220223
static inline unsigned char search_escape_basic_sse2(search_state *search);
221224
#endif
@@ -226,8 +229,19 @@ static inline void convert_UTF8_to_JSON(search_state *search)
226229
{
227230
#ifdef HAVE_SIMD
228231
#if defined(HAVE_SIMD_NEON)
229-
while (search_escape_basic_neon(search)) {
230-
escape_UTF8_char_basic(search);
232+
uint64_t mask;
233+
while ((mask = search_escape_basic_neon(search))) {
234+
while (mask > 0) {
235+
mask = neon_next_match(mask, search);
236+
escape_UTF8_char_basic(search);
237+
}
238+
search->ptr = search->chunk_end;
239+
}
240+
241+
if (search->ptr < search->end) {
242+
while (search_escape_basic(search)) {
243+
escape_UTF8_char_basic(search);
244+
}
231245
}
232246
#elif defined(HAVE_SIMD_SSE2)
233247
if (simd_impl == SIMD_SSE2) {
@@ -317,9 +331,8 @@ ALWAYS_INLINE(static) char *copy_remaining_bytes(search_state *search, unsigned
317331

318332
#ifdef HAVE_SIMD_NEON
319333

320-
ALWAYS_INLINE(static) unsigned char neon_next_match(search_state *search)
334+
ALWAYS_INLINE(static) uint64_t neon_next_match(uint64_t mask, search_state *search)
321335
{
322-
uint64_t mask = search->matches_mask;
323336
uint32_t index = trailing_zeros64(mask) >> 2;
324337

325338
// It is assumed escape_UTF8_char_basic will only ever increase search->ptr by at most one character.
@@ -329,26 +342,15 @@ ALWAYS_INLINE(static) unsigned char neon_next_match(search_state *search)
329342
// is one byte after the previous match then:
330343
// search->chunk_base + index == search->ptr
331344
search->ptr = search->chunk_base + index;
332-
mask &= mask - 1;
333-
search->matches_mask = mask;
334345
search_flush(search);
335-
return 1;
346+
347+
mask &= mask - 1;
348+
// search->matches_mask = mask;
349+
return mask;
336350
}
337351

338-
static inline unsigned char search_escape_basic_neon(search_state *search)
352+
static inline uint64_t search_escape_basic_neon(search_state *search)
339353
{
340-
if (RB_UNLIKELY(search->has_matches)) {
341-
// There are more matches if search->matches_mask > 0.
342-
if (search->matches_mask > 0) {
343-
return neon_next_match(search);
344-
} else {
345-
// neon_next_match will only advance search->ptr up to the last matching character.
346-
// Skip over any characters in the last chunk that occur after the last match.
347-
search->has_matches = false;
348-
search->ptr = search->chunk_end;
349-
}
350-
}
351-
352354
/*
353355
* The code below implements an SIMD-based algorithm to determine if N bytes at a time
354356
* need to be escaped.
@@ -390,11 +392,12 @@ static inline unsigned char search_escape_basic_neon(search_state *search)
390392
* have at least one byte that needs to be escaped.
391393
*/
392394

393-
if (string_scan_simd_neon(&search->ptr, search->end, &search->matches_mask)) {
394-
search->has_matches = true;
395+
uint64_t matches_mask = 0;
396+
if ((matches_mask = string_scan_simd_neon(&search->ptr, search->end))) {
397+
// search->has_matches = true;
395398
search->chunk_base = search->ptr;
396399
search->chunk_end = search->ptr + sizeof(uint8x16_t);
397-
return neon_next_match(search);
400+
return matches_mask;
398401
}
399402

400403
// There are fewer than 16 bytes left.
@@ -413,15 +416,11 @@ static inline unsigned char search_escape_basic_neon(search_state *search)
413416
return 0;
414417
}
415418

416-
search->matches_mask = mask;
417-
search->has_matches = true;
419+
// search->matches_mask = mask;
420+
// search->has_matches = true;
418421
search->chunk_end = search->end;
419422
search->chunk_base = search->ptr;
420-
return neon_next_match(search);
421-
}
422-
423-
if (search->ptr < search->end) {
424-
return search_escape_basic(search);
423+
return mask;
425424
}
426425

427426
search_flush(search);
@@ -1124,8 +1123,8 @@ static void raw_generate_json_string(FBuffer *buffer, struct generate_json_data
11241123
search.end = search.ptr + len;
11251124

11261125
#ifdef HAVE_SIMD
1127-
search.matches_mask = 0;
1128-
search.has_matches = false;
1126+
// search.matches_mask = 0;
1127+
// search.has_matches = false;
11291128
search.chunk_base = NULL;
11301129
search.chunk_end = NULL;
11311130
#endif /* HAVE_SIMD */

ext/json/ext/parser/parser.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -954,7 +954,7 @@ ALWAYS_INLINE(static) bool string_scan(JSON_ParserState *state)
954954
#if defined(HAVE_SIMD_NEON)
955955

956956
uint64_t mask = 0;
957-
if (string_scan_simd_neon(&state->cursor, state->end, &mask)) {
957+
if ((mask = string_scan_simd_neon(&state->cursor, state->end))) {
958958
state->cursor += trailing_zeros64(mask) >> 2;
959959
return true;
960960
}

ext/json/ext/simd/simd.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,12 @@ ALWAYS_INLINE(static) uint64_t compute_chunk_mask_neon(const char *ptr)
120120
return neon_match_mask(needs_escape);
121121
}
122122

123-
ALWAYS_INLINE(static) int string_scan_simd_neon(const char **ptr, const char *end, uint64_t *mask)
123+
ALWAYS_INLINE(static) uint64_t string_scan_simd_neon(const char **ptr, const char *end)
124124
{
125125
while (*ptr + sizeof(uint8x16_t) <= end) {
126126
uint64_t chunk_mask = compute_chunk_mask_neon(*ptr);
127127
if (chunk_mask) {
128-
*mask = chunk_mask;
129-
return 1;
128+
return chunk_mask;
130129
}
131130
*ptr += sizeof(uint8x16_t);
132131
}

0 commit comments

Comments
 (0)