v1-verify-utf8-sse-ascii.patch
application/x-patch
Filename: v1-verify-utf8-sse-ascii.patch
Type: application/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v1
| File | + | − |
|---|---|---|
| src/common/wchar.c | 81 | 2 |
diff --git a/src/common/wchar.c b/src/common/wchar.c
index 6e7d731e02..12b3a5e1a2 100644
--- a/src/common/wchar.c
+++ b/src/common/wchar.c
@@ -13,6 +13,10 @@
#include "c.h"
#include "mb/pg_wchar.h"
+#include "port/pg_bitutils.h"
+
+/* FIXME -- should go in src/include/port */
+#include <emmintrin.h>
/*
@@ -1762,6 +1766,80 @@ pg_utf8_verifystr(const unsigned char *s, int len)
{
const unsigned char *start = s;
+#ifdef __x86_64__
+
+
+ const __m128i zero = _mm_setzero_si128();
+ __m128i chunk,
+ cmp;
+
+ const int chunk_size = sizeof(__m128i);
+ int zero_mask,
+ highbit_mask,
+ ascii_count,
+ remainder;
+
+ while (len >= chunk_size)
+ {
+ /* load next chunk */
+ chunk = _mm_loadu_si128((const __m128i *) s);
+
+ /* first detect any zero bytes */
+ cmp = _mm_cmpeq_epi8(chunk, zero);
+ zero_mask = _mm_movemask_epi8(cmp);
+
+ /* if there is a zero byte, let the slow path encounter it */
+ if (zero_mask)
+ break;
+
+ /* now check for non-ascii bytes */
+ highbit_mask = _mm_movemask_epi8(chunk);
+
+ if (!highbit_mask)
+ {
+ /* all ascii, so advance to the next chunk */
+ s += chunk_size;
+ len -= chunk_size;
+ continue;
+ }
+
+ /*
+ * if not all ascii, maybe there is a solid block of ascii
+ * at the beginning of the chunk. if so, skip it
+ */
+ ascii_count = pg_rightmost_one_pos32(highbit_mask);
+
+ s += ascii_count;
+ len -= ascii_count;
+ remainder = chunk_size - ascii_count;
+
+ /* found non-ascii, so handle the remainder in the normal way */
+ while (remainder > 0)
+ {
+ int l;
+
+ /*
+ * fast path for ASCII-subset characters
+ * we already know they're non-zero
+ */
+ if (!IS_HIGHBIT_SET(*s))
+ l = 1;
+ else
+ {
+ l = pg_utf8_verifychar(s, len);
+ if (l == -1)
+ goto finish;
+ }
+ s += l;
+ len -= l;
+ remainder -= l;
+
+ }
+ }
+
+#endif /* __x86_64__ */
+
+ /* handle last few bytes */
while (len > 0)
{
int l;
@@ -1770,19 +1848,20 @@ pg_utf8_verifystr(const unsigned char *s, int len)
if (!IS_HIGHBIT_SET(*s))
{
if (*s == '\0')
- break;
+ goto finish;
l = 1;
}
else
{
l = pg_utf8_verifychar(s, len);
if (l == -1)
- break;
+ goto finish;
}
s += l;
len -= l;
}
+finish:
return s - start;
}