]> git.ipfire.org Git - thirdparty/LuaJIT.git/commitdiff
Change handling of nil value markers in template tables.
authorMike Pall <mike>
Sun, 9 Mar 2025 13:44:57 +0000 (14:44 +0100)
committerMike Pall <mike>
Sun, 9 Mar 2025 13:44:57 +0000 (14:44 +0100)
Reported by Bernhard M. Wiedemann. #1348 #1155

src/lj_bcread.c
src/lj_bcwrite.c
src/lj_opt_fold.c
src/lj_opt_mem.c
src/lj_parse.c
src/lj_tab.c

index ee7d7c1870168635c1f7afe5f7444b12c78fae84..37e909b39139da14fe7f7b89b37864ec5b238068 100644 (file)
@@ -179,7 +179,7 @@ static const void *bcread_varinfo(GCproto *pt)
 }
 
 /* Read a single constant key/value of a template table. */
-static void bcread_ktabk(LexState *ls, TValue *o)
+static void bcread_ktabk(LexState *ls, TValue *o, GCtab *t)
 {
   MSize tp = bcread_uleb128(ls);
   if (tp >= BCDUMP_KTAB_STR) {
@@ -191,6 +191,8 @@ static void bcread_ktabk(LexState *ls, TValue *o)
   } else if (tp == BCDUMP_KTAB_NUM) {
     o->u32.lo = bcread_uleb128(ls);
     o->u32.hi = bcread_uleb128(ls);
+  } else if (tp == BCDUMP_KTAB_NIL) { /* Restore nil value marker. */
+    settabV(ls->L, o, t);
   } else {
     lj_assertLS(tp <= BCDUMP_KTAB_TRUE, "bad constant type %d", tp);
     setpriV(o, ~tp);
@@ -207,15 +209,15 @@ static GCtab *bcread_ktab(LexState *ls)
     MSize i;
     TValue *o = tvref(t->array);
     for (i = 0; i < narray; i++, o++)
-      bcread_ktabk(ls, o);
+      bcread_ktabk(ls, o, t);
   }
   if (nhash) {  /* Read hash entries. */
     MSize i;
     for (i = 0; i < nhash; i++) {
       TValue key;
-      bcread_ktabk(ls, &key);
+      bcread_ktabk(ls, &key, t);
       lj_assertLS(!tvisnil(&key), "nil key");
-      bcread_ktabk(ls, lj_tab_set(ls->L, t, &key));
+      bcread_ktabk(ls, lj_tab_set(ls->L, t, &key), t);
     }
   }
   return t;
index de200ef4ad5cd6425155c674a419c97a86a21c2f..d5e10ab22ba071e39a8e06038d1df553dc7be4d1 100644 (file)
@@ -71,6 +71,8 @@ static void bcwrite_ktabk(BCWriteCtx *ctx, cTValue *o, int narrow)
     *p++ = BCDUMP_KTAB_NUM;
     p = lj_strfmt_wuleb128(p, o->u32.lo);
     p = lj_strfmt_wuleb128(p, o->u32.hi);
+  } else if (tvistab(o)) { /* Write the nil value marker as a nil. */
+    *p++ = BCDUMP_KTAB_NIL;
   } else {
     lj_assertBCW(tvispri(o), "unhandled type %d", itype(o));
     *p++ = BCDUMP_KTAB_NIL+~itype(o);
@@ -133,7 +135,7 @@ static void bcwrite_ktab_sorted_hash(BCWriteCtx *ctx, Node *node, MSize nhash)
   TValue **heap = ctx->heap;
   MSize i = nhash;
   for (;; node--) {  /* Build heap. */
-    if (!tvisnil(&node->key)) {
+    if (!tvisnil(&node->val)) {
       bcwrite_ktabk_heap_insert(heap, --i, nhash, &node->key);
       if (i == 0) break;
     }
@@ -163,7 +165,7 @@ static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t)
     MSize i, hmask = t->hmask;
     Node *node = noderef(t->node);
     for (i = 0; i <= hmask; i++)
-      nhash += !tvisnil(&node[i].key);
+      nhash += !tvisnil(&node[i].val);
   }
   /* Write number of array slots and hash slots. */
   p = lj_strfmt_wuleb128(p, narray);
index 36aacebb03732615a56f019da9bfe5ff52c0c141..6fdf45663fa8fe3f3fe3d915e236d674c389341c 100644 (file)
@@ -2217,9 +2217,11 @@ LJFOLD(HREF TDUP KNUM)
 LJFOLDF(fwd_href_tdup)
 {
   TValue keyv;
+  cTValue *val;
   lj_ir_kvalue(J->L, &keyv, fright);
-  if (lj_tab_get(J->L, ir_ktab(IR(fleft->op1)), &keyv) == niltvg(J2G(J)) &&
-      lj_opt_fwd_href_nokey(J))
+  val = lj_tab_get(J->L, ir_ktab(IR(fleft->op1)), &keyv);
+  /* Check for either nil or the nil value marker in the template table. */
+  if ((tvisnil(val) || tvistab(val)) && lj_opt_fwd_href_nokey(J))
     return lj_ir_kkptr(J, niltvg(J2G(J)));
   return NEXTFOLD;
 }
index 8cacfcfef9d475fa5f1eaf2f7d792e58e018c592..6f956b37e95ceaf9ea2c61e0baa37694c6061c6c 100644 (file)
@@ -233,7 +233,9 @@ static TRef fwd_ahload(jit_State *J, IRRef xref)
          return lj_ir_knum_u64(J, tv->u64);
        else if (tvisint(tv))
          return lj_ir_kint(J, intV(tv));
-       else if (tvisgcv(tv))
+       else if (tvistab(tv)) /* Template table nil value marker. */
+         return TREF_NIL;
+       else if (tvisstr(tv))
          return lj_ir_kstr(J, strV(tv));
       }
       /* Othwerwise: don't intern as a constant. */
index 70097598083ee43c87eeb7af3294dbf608314d08..f41163804aadeafa729801a956ca8fa7158cec0b 100644 (file)
@@ -1725,7 +1725,7 @@ static void expr_table(LexState *ls, ExpDesc *e)
   FuncState *fs = ls->fs;
   BCLine line = ls->linenumber;
   GCtab *t = NULL;
-  int vcall = 0, needarr = 0, fixt = 0;
+  int vcall = 0, needarr = 0;
   uint32_t narr = 1;  /* First array index. */
   uint32_t nhash = 0;  /* Number of hash entries. */
   BCReg freg = fs->freereg;
@@ -1769,9 +1769,10 @@ static void expr_table(LexState *ls, ExpDesc *e)
       lj_gc_anybarriert(fs->L, t);
       if (expr_isk_nojump(&val)) {  /* Add const key/value to template table. */
        expr_kvalue(fs, v, &val);
-      } else {  /* Otherwise create dummy string key (avoids lj_tab_newkey). */
-       settabV(fs->L, v, t);  /* Preserve key with table itself as value. */
-       fixt = 1;   /* Fix this later, after all resizes. */
+       /* Mark nil value with table value itself to preserve the key. */
+       if (key.k == VKSTR && tvisnil(v)) settabV(fs->L, v, t);
+      } else {  /* Preserve the key for the following non-const store.  */
+       settabV(fs->L, v, t);
        goto nonconst;
       }
     } else {
@@ -1813,17 +1814,6 @@ static void expr_table(LexState *ls, ExpDesc *e)
   } else {
     if (needarr && t->asize < narr)
       lj_tab_reasize(fs->L, t, narr-1);
-    if (fixt) {  /* Fix value for dummy keys in template table. */
-      Node *node = noderef(t->node);
-      uint32_t i, hmask = t->hmask;
-      for (i = 0; i <= hmask; i++) {
-       Node *n = &node[i];
-       if (tvistab(&n->val)) {
-         lj_assertFS(tabV(&n->val) == t, "bad dummy key in template table");
-         setnilV(&n->val);  /* Turn value into nil. */
-       }
-      }
-    }
     lj_gc_check(fs->L);
   }
 }
index 2d0805520689b4fe4dfac1a50e53804f7ea202d4..62e336111af5aa3163d459418c08ec128c796f7d 100644 (file)
@@ -194,6 +194,7 @@ GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt)
       Node *next = nextnode(kn);
       /* Don't use copyTV here, since it asserts on a copy of a dead key. */
       n->val = kn->val; n->key = kn->key;
+      if (tvistab(&n->val)) setnilV(&n->val); /* Replace nil value marker. */
       setmref(n->next, next == NULL? next : (Node *)((char *)next + d));
     }
   }