From 337d93bcea2ccd19218ed465775884200d5a3a06 Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Sat, 21 Jun 2025 21:59:21 -0400 Subject: [PATCH] simd scan with dfa as fallback --- src/parser3.h | 53 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/src/parser3.h b/src/parser3.h index 7da709e..311d2bb 100644 --- a/src/parser3.h +++ b/src/parser3.h @@ -782,10 +782,27 @@ inline PRESERVE_NONE WeaselJsonStatus n_number(Parser3 *self, char *buf, // Advance buf until double quote, backslash, invalid utf8, or codepoint < // 0x20 -inline PRESERVE_NONE WeaselJsonStatus n_scan_string(Parser3 *self, char *&buf, - char *bufEnd) { +template +inline PRESERVE_NONE WeaselJsonStatus scan_string_impl(Parser3 *self, + char *&buf, + char *bufEnd) { const auto before = buf; + // Advance buf past normal characters + for (;;) { + if (bufEnd - buf < V::lanes) [[unlikely]] { + break; + } + auto v = V{(int8_t *)buf}; + int normal = + (v != V::splat('"') & v != V::splat('\\') & v >= V::splat(0x20)) + .count_leading_nonzero_lanes(); + buf += normal; + if (normal < V::lanes) { + break; + } + } + buf = (char *)self->strDfa.scan(buf, bufEnd); int len = buf - before; @@ -805,6 +822,34 @@ inline PRESERVE_NONE WeaselJsonStatus n_scan_string(Parser3 *self, char *&buf, return WeaselJson_OK; } +#ifdef __x86_64__ +constexpr int kLanes = 32; +template WeaselJsonStatus +scan_string_impl>(Parser3 *, char *&, + char *); + +template __attribute__((target("avx2"))) WeaselJsonStatus +scan_string_impl>(Parser3 *, char *&, + char *); + +__attribute__((target("default"))) inline PRESERVE_NONE WeaselJsonStatus +scan_string(Parser3 *self, char *&buf, char *bufEnd) { + MUSTTAIL return scan_string_impl>( + self, buf, bufEnd); +} + +__attribute__((target("avx2"))) inline PRESERVE_NONE WeaselJsonStatus +scan_string(Parser3 *self, char *&buf, char *bufEnd) { + MUSTTAIL return scan_string_impl>( + self, buf, bufEnd); +} +#else +inline PRESERVE_NONE WeaselJsonStatus scan_string(Parser3 *self, char *buf, + char *bufEnd) { + MUSTTAIL return scan_string_impl>(self, buf, bufEnd); +} +#endif + inline PRESERVE_NONE WeaselJsonStatus n_value(Parser3 *self, char *buf, char *bufEnd) { assert(bufEnd - buf != 0); @@ -836,7 +881,7 @@ inline PRESERVE_NONE WeaselJsonStatus n_value(Parser3 *self, char *buf, self->dataBegin = self->writeBuf = buf; self->pop(); self->strDfa.reset(); - if (auto s = n_scan_string(self, buf, bufEnd)) { + if (auto s = scan_string(self, buf, bufEnd)) { if (s == WeaselJson_AGAIN) { if (auto s2 = self->push({N_STRING2})) { return s2; @@ -1072,7 +1117,7 @@ inline PRESERVE_NONE WeaselJsonStatus n_string(Parser3 *self, char *buf, inline PRESERVE_NONE WeaselJsonStatus n_string2(Parser3 *self, char *buf, char *bufEnd) { - if (auto s = n_scan_string(self, buf, bufEnd)) { + if (auto s = scan_string(self, buf, bufEnd)) { return s; } switch (*buf) {