<!DOCTYPE html>
<html data-lt-installed="true">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body style="padding-bottom: 1px;">
    <p>Hi, Maxim,</p>
    <p>thanks for the patch!</p>
    <p>The patch below is quite similar to the patch in OpenResty [1].</p>
    <p>Have you used it? <br>
    </p>
    <p>1.
<a class="moz-txt-link-freetext" href="https://github.com/openresty/luajit2/commit/6315a752274f3a4db6827b64788173f40733204e">https://github.com/openresty/luajit2/commit/6315a752274f3a4db6827b64788173f40733204e</a><br>
    </p>
    <div class="moz-cite-prefix">On 26.06.2024 15:27, mandesero--- via
      Tarantool-patches wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:20240626122735.165672-2-mandesero@gmail.com">
      <pre class="moz-quote-pre" wrap="">From: mandesero <a class="moz-txt-link-rfc2396E" href="mailto:mandesero@gmail.com"><mandesero@gmail.com></a>

---
 src/lj_str.c | 43 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 41 insertions(+), 2 deletions(-)

diff --git a/src/lj_str.c b/src/lj_str.c
index 321e8c4f..00cced03 100644
--- a/src/lj_str.c
+++ b/src/lj_str.c
@@ -26,10 +26,29 @@ static LJ_AINLINE int str_fastcmp(const char *a, const char *b, MSize len)
 
 /* -- String helpers ------------------------------------------------------ */
 
+#if LUAJIT_USE_VALGRIND
+int lj_str_cmp_no_opt(const char *a, const char *b, MSize len)
+{
+  for (MSize i = 0; i < len; i++)
+    if (a[i] != b[i])
+      return 1;
+  return 0;
+}
+#endif
+
 /* Ordered compare of strings. Assumes string data is 4-byte aligned. */
 int32_t LJ_FASTCALL lj_str_cmp(GCstr *a, GCstr *b)
 {
   MSize i, n = a->len > b->len ? b->len : a->len;
+#if LUAJIT_USE_VALGRIND
+  const uint8_t *sa = (const uint8_t *)strdata(a);
+  const uint8_t *sb = (const uint8_t *)strdata(b);
+  
+  for (i = 0; i < n; i++) {
+    if (sa[i] != sb[i])
+      return (uint8_t)sa[i] < (uint8_t)sb[i] ? -1 : 1;
+  }
+#else
   for (i = 0; i < n; i += 4) {
     /* Note: innocuous access up to end of string + 3. */
     uint32_t va = *(const uint32_t *)(strdata(a)+i);
@@ -46,6 +65,7 @@ int32_t LJ_FASTCALL lj_str_cmp(GCstr *a, GCstr *b)
       return va < vb ? -1 : 1;
     }
   }
+#endif
   return (int32_t)(a->len - b->len);
 }
 
@@ -53,6 +73,12 @@ int32_t LJ_FASTCALL lj_str_cmp(GCstr *a, GCstr *b)
 static LJ_AINLINE int str_fastcmp(const char *a, const char *b, MSize len)
 {
   MSize i = 0;
+#if LUAJIT_USE_VALGRIND
+  for (i = 0; i < len; i++) {
+    if (a[i] != b[i])
+      return (uint8_t)a[i] < (uint8_t)b[i] ? -1 : 1;
+  }
+#else
   lj_assertX(len > 0, "fast string compare with zero length");
   lj_assertX((((uintptr_t)a+len-1) & (LJ_PAGESIZE-1)) <= LJ_PAGESIZE-4,
             "fast string compare crossing page boundary");
@@ -68,6 +94,7 @@ static LJ_AINLINE int str_fastcmp(const char *a, const char *b, MSize len)
     }
     i += 4;
   } while (i < len);
+#endif
   return 0;
 }
 
@@ -83,7 +110,11 @@ const char *lj_str_find(const char *s, const char *p, MSize slen, MSize plen)
       while (slen) {
        const char *q = (const char *)memchr(s, c, slen);
        if (!q) break;
+#if LUAJIT_USE_VALGRIND
+  if (lj_str_cmp_no_opt(q+1, p, plen) == 0) return q;
+#else
        if (memcmp(q+1, p, plen) == 0) return q;
+#endif
        q++; slen -= (MSize)(q-s); s = q;
       }
     }
@@ -232,8 +263,13 @@ GCstr *lj_str_new(lua_State *L, const char *str, size_t lenx)
   } else {  /* Slow path: end of string is too close to a page boundary. */
     while (o != NULL) {
       GCstr *sx = gco2str(o);
+#if LUAJIT_USE_VALGRIND
+      if (sx->hash == h && sx->len == len && inc_collision_hard() &&
+                      lj_str_cmp_no_opt(str, strdata(sx), len) == 0) {
+#else
       if (sx->hash == h && sx->len == len && inc_collision_hard() &&
                       memcmp(str, strdata(sx), len) == 0) {
+#endif
        /* Resurrect if dead. Can only happen with fixstring() (keywords). */
        if (isdead(g, o)) flipwhite(o);
        g->strhash_hit++;
@@ -277,7 +313,11 @@ GCstr *lj_str_new(lua_State *L, const char *str, size_t lenx)
        } else {  /* Slow path: end of string is too close to a page boundary. */
          while (o != NULL) {
            GCstr *sx = gco2str(o);
+#if LUAJIT_USE_VALGRIND
+           if (sx->hash == fh && sx->len == len && lj_str_cmp_no_opt(str, strdata(sx), len) == 0) {
+#else
            if (sx->hash == fh && sx->len == len && memcmp(str, strdata(sx), len) == 0) {
+#endif
              /* Resurrect if dead. Can only happen with fixstring() (keywords). */
              if (isdead(g, o)) flipwhite(o);
              g->strhash_hit++;
@@ -323,5 +363,4 @@ void LJ_FASTCALL lj_str_free(global_State *g, GCstr *s)
 {
   g->strnum--;
   lj_mem_free(g, s, sizestring(s));
-}
-
+}
\ No newline at end of file
</pre>
    </blockquote>
  </body>
  <lt-container></lt-container>
</html>