]> git.ipfire.org Git - thirdparty/LuaJIT.git/commitdiff
String buffer refactoring, part 2.
authorMike Pall <mike>
Wed, 27 Feb 2013 20:17:27 +0000 (21:17 +0100)
committerMike Pall <mike>
Wed, 27 Feb 2013 20:28:28 +0000 (21:28 +0100)
Switch to pointers for start/pos/end of buffer.
Abstract out some buffer writers.

18 files changed:
src/Makefile.dep
src/lib_string.c
src/lj_bcread.c
src/lj_bcwrite.c
src/lj_buf.c
src/lj_buf.h
src/lj_cparse.c
src/lj_debug.c
src/lj_gdbjit.c
src/lj_lex.c
src/lj_lex.h
src/lj_obj.h
src/lj_parse.c
src/lj_str.c
src/vm_arm.dasc
src/vm_mips.dasc
src/vm_ppc.dasc
src/vm_x86.dasc

index 565947046ee08ab72fea7903b31a31903c82b752..f841767be7b000bdce4a974da003f9866d59bed9 100644 (file)
@@ -17,8 +17,8 @@ lib_ffi.o: lib_ffi.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
  lj_ccallback.h lj_clib.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h
 lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h
 lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
- lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_state.h lj_ff.h \
- lj_ffdef.h lj_lib.h lj_libdef.h
+ lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_state.h \
+ lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h
 lib_jit.o: lib_jit.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h \
  lj_obj.h lj_def.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h \
  lj_bc.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_target.h \
@@ -31,8 +31,8 @@ lib_os.o: lib_os.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
 lib_package.o: lib_package.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
  lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_lib.h
 lib_string.o: lib_string.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
- lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h \
- lj_meta.h lj_state.h lj_ff.h lj_ffdef.h lj_bcdump.h lj_lex.h lj_buf.h \
+ lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h \
+ lj_tab.h lj_meta.h lj_state.h lj_ff.h lj_ffdef.h lj_bcdump.h lj_lex.h \
  lj_char.h lj_lib.h lj_libdef.h
 lib_table.o: lib_table.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
  lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_lib.h \
@@ -56,7 +56,7 @@ lj_bcwrite.o: lj_bcwrite.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
  lj_gc.h lj_buf.h lj_str.h lj_bc.h lj_ctype.h lj_dispatch.h lj_jit.h \
  lj_ir.h lj_bcdump.h lj_lex.h lj_err.h lj_errmsg.h lj_vm.h
 lj_buf.o: lj_buf.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
- lj_err.h lj_errmsg.h lj_buf.h
+ lj_err.h lj_errmsg.h lj_buf.h lj_str.h
 lj_carith.o: lj_carith.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
  lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_meta.h lj_ctype.h lj_cconv.h \
  lj_cdata.h lj_carith.h
@@ -91,8 +91,8 @@ lj_crecord.o: lj_crecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
 lj_ctype.o: lj_ctype.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
  lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_ccallback.h
 lj_debug.o: lj_debug.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
- lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h lj_state.h lj_frame.h \
- lj_bc.h lj_jit.h lj_ir.h
+ lj_err.h lj_errmsg.h lj_debug.h lj_buf.h lj_gc.h lj_str.h lj_tab.h \
+ lj_state.h lj_frame.h lj_bc.h lj_jit.h lj_ir.h
 lj_dispatch.o: lj_dispatch.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
  lj_err.h lj_errmsg.h lj_func.h lj_str.h lj_tab.h lj_meta.h lj_debug.h \
  lj_state.h lj_frame.h lj_bc.h lj_ff.h lj_ffdef.h lj_jit.h lj_ir.h \
@@ -115,19 +115,19 @@ lj_gc.o: lj_gc.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
  lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cdata.h lj_trace.h \
  lj_jit.h lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h
 lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
- lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_frame.h lj_bc.h lj_jit.h \
- lj_ir.h lj_dispatch.h
+ lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_frame.h lj_bc.h lj_buf.h \
+ lj_str.h lj_jit.h lj_ir.h lj_dispatch.h
 lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
  lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \
  lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h lj_carith.h \
  lj_vm.h lj_strscan.h lj_lib.h
 lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
- lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h lualib.h \
- lj_state.h lj_lex.h lj_buf.h lj_parse.h lj_char.h lj_strscan.h
+ lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h \
+ lualib.h lj_state.h lj_lex.h lj_parse.h lj_char.h lj_strscan.h
 lj_lib.o: lj_lib.c lauxlib.h lua.h luaconf.h lj_obj.h lj_def.h lj_arch.h \
  lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h lj_bc.h \
- lj_dispatch.h lj_jit.h lj_ir.h lj_vm.h lj_strscan.h lj_lex.h lj_buf.h \
- lj_bcdump.h lj_lib.h
+ lj_dispatch.h lj_jit.h lj_ir.h lj_vm.h lj_strscan.h lj_lex.h lj_bcdump.h \
+ lj_lib.h
 lj_load.o: lj_load.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \
  lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_func.h \
  lj_frame.h lj_bc.h lj_vm.h lj_lex.h lj_bcdump.h lj_parse.h
@@ -145,8 +145,9 @@ lj_opt_fold.o: lj_opt_fold.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
  lj_bc.h lj_traceerr.h lj_ctype.h lj_gc.h lj_carith.h lj_vm.h \
  lj_strscan.h lj_folddef.h
 lj_opt_loop.o: lj_opt_loop.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
- lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_ir.h lj_jit.h lj_iropt.h \
- lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_snap.h lj_vm.h
+ lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_ir.h lj_jit.h \
+ lj_iropt.h lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_snap.h \
+ lj_vm.h
 lj_opt_mem.o: lj_opt_mem.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
  lj_tab.h lj_ir.h lj_jit.h lj_iropt.h
 lj_opt_narrow.o: lj_opt_narrow.c lj_obj.h lua.h luaconf.h lj_def.h \
@@ -155,11 +156,11 @@ lj_opt_narrow.o: lj_opt_narrow.c lj_obj.h lua.h luaconf.h lj_def.h \
 lj_opt_sink.o: lj_opt_sink.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
  lj_ir.h lj_jit.h lj_iropt.h lj_target.h lj_target_*.h
 lj_opt_split.o: lj_opt_split.c lj_obj.h lua.h luaconf.h lj_def.h \
- lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_ir.h lj_jit.h \
- lj_ircall.h lj_iropt.h lj_vm.h
+ lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_ir.h \
+ lj_jit.h lj_ircall.h lj_iropt.h lj_vm.h
 lj_parse.o: lj_parse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
- lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h lj_func.h \
- lj_state.h lj_bc.h lj_ctype.h lj_lex.h lj_buf.h lj_parse.h lj_vm.h \
+ lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_buf.h lj_str.h lj_tab.h \
+ lj_func.h lj_state.h lj_bc.h lj_ctype.h lj_lex.h lj_parse.h lj_vm.h \
  lj_vmevent.h
 lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
  lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \
index 5fdfcd91addcfd0c9e2747198545bd11c63cab0b..36fd3f53f5ecc832f14e0e2fcc856c3514288646 100644 (file)
@@ -18,6 +18,7 @@
 #include "lj_obj.h"
 #include "lj_gc.h"
 #include "lj_err.h"
+#include "lj_buf.h"
 #include "lj_str.h"
 #include "lj_tab.h"
 #include "lj_meta.h"
index fabe76dacec23022bc43637145bcdf38e598c726..eda121e011b6d15182cc287ee87a0531023c64f0 100644 (file)
@@ -53,27 +53,28 @@ static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need)
     const char *buf;
     size_t size;
     if (ls->n) {  /* Copy remainder to buffer. */
-      if (ls->sb.n) {  /* Move down in buffer. */
-       lua_assert(ls->p + ls->n == ls->sb.buf + ls->sb.n);
-       if (ls->n != ls->sb.n)
-         memmove(ls->sb.buf, ls->p, ls->n);
+      if (sbuflen(&ls->sb)) {  /* Move down in buffer. */
+       lua_assert(ls->p + ls->n == sbufP(&ls->sb));
+       if (ls->n != sbuflen(&ls->sb))
+         memmove(sbufB(&ls->sb), ls->p, ls->n);
       } else {  /* Copy from buffer provided by reader. */
        memcpy(lj_buf_need(ls->L, &ls->sb, len), ls->p, ls->n);
       }
-      ls->p = ls->sb.buf;
+      ls->p = sbufB(&ls->sb);
     }
-    ls->sb.n = ls->n;
+    setsbufP(&ls->sb, sbufB(&ls->sb) + ls->n);
     buf = ls->rfunc(ls->L, ls->rdata, &size);  /* Get more data from reader. */
     if (buf == NULL || size == 0) {  /* EOF? */
       if (need) bcread_error(ls, LJ_ERR_BCBAD);
       ls->current = -1;  /* Only bad if we get called again. */
       break;
     }
-    if (ls->sb.n) {  /* Append to buffer. */
-      MSize n = ls->sb.n + (MSize)size;
+    if (sbuflen(&ls->sb)) {  /* Append to buffer. */
+      MSize n = sbuflen(&ls->sb) + (MSize)size;
       char *p = lj_buf_need(ls->L, &ls->sb, n < len ? len : n);
-      memcpy(p + ls->sb.n, buf, size);
-      ls->n = ls->sb.n = n;
+      memcpy(sbufP(&ls->sb), buf, size);
+      setsbufP(&ls->sb, sbufB(&ls->sb) + n);
+      ls->n = n;
       ls->p = p;
     } else {  /* Return buffer provided by reader. */
       ls->n = (MSize)size;
index 474234c5f33da70d50474addb8d7fc833fbcfaf0..71c865815b4ef05af480b6560877b35f3efff9db 100644 (file)
@@ -32,76 +32,44 @@ typedef struct BCWriteCtx {
   int status;                  /* Status from writer callback. */
 } BCWriteCtx;
 
-/* -- Output buffer handling ---------------------------------------------- */
-
-/* Ensure a certain amount of buffer space. */
-static LJ_AINLINE void bcwrite_need(BCWriteCtx *ctx, MSize len)
-{
-  lj_buf_need(ctx->L, &ctx->sb, ctx->sb.n + len);
-}
-
-/* Add memory block to buffer. */
-static void bcwrite_block(BCWriteCtx *ctx, const void *p, MSize len)
-{
-  uint8_t *q = (uint8_t *)(ctx->sb.buf + ctx->sb.n);
-  MSize i;
-  ctx->sb.n += len;
-  for (i = 0; i < len; i++) q[i] = ((uint8_t *)p)[i];
-}
-
-/* Add byte to buffer. */
-static LJ_AINLINE void bcwrite_byte(BCWriteCtx *ctx, uint8_t b)
-{
-  ctx->sb.buf[ctx->sb.n++] = b;
-}
-
-/* Add ULEB128 value to buffer. */
-static void bcwrite_uleb128(BCWriteCtx *ctx, uint32_t v)
-{
-  MSize n = ctx->sb.n;
-  uint8_t *p = (uint8_t *)ctx->sb.buf;
-  for (; v >= 0x80; v >>= 7)
-    p[n++] = (uint8_t)((v & 0x7f) | 0x80);
-  p[n++] = (uint8_t)v;
-  ctx->sb.n = n;
-}
-
 /* -- Bytecode writer ----------------------------------------------------- */
 
 /* Write a single constant key/value of a template table. */
 static void bcwrite_ktabk(BCWriteCtx *ctx, cTValue *o, int narrow)
 {
-  bcwrite_need(ctx, 1+10);
+  char *p = lj_buf_more(ctx->L, &ctx->sb, 1+10);
   if (tvisstr(o)) {
     const GCstr *str = strV(o);
     MSize len = str->len;
-    bcwrite_need(ctx, 5+len);
-    bcwrite_uleb128(ctx, BCDUMP_KTAB_STR+len);
-    bcwrite_block(ctx, strdata(str), len);
+    p = lj_buf_more(ctx->L, &ctx->sb, 5+len);
+    p = lj_buf_wuleb128(p, BCDUMP_KTAB_STR+len);
+    p = lj_buf_wmem(p, strdata(str), len);
   } else if (tvisint(o)) {
-    bcwrite_byte(ctx, BCDUMP_KTAB_INT);
-    bcwrite_uleb128(ctx, intV(o));
+    *p++ = BCDUMP_KTAB_INT;
+    p = lj_buf_wuleb128(p, intV(o));
   } else if (tvisnum(o)) {
     if (!LJ_DUALNUM && narrow) {  /* Narrow number constants to integers. */
       lua_Number num = numV(o);
       int32_t k = lj_num2int(num);
       if (num == (lua_Number)k) {  /* -0 is never a constant. */
-       bcwrite_byte(ctx, BCDUMP_KTAB_INT);
-       bcwrite_uleb128(ctx, k);
+       *p++ = BCDUMP_KTAB_INT;
+       p = lj_buf_wuleb128(p, k);
+       setsbufP(&ctx->sb, p);
        return;
       }
     }
-    bcwrite_byte(ctx, BCDUMP_KTAB_NUM);
-    bcwrite_uleb128(ctx, o->u32.lo);
-    bcwrite_uleb128(ctx, o->u32.hi);
+    *p++ = BCDUMP_KTAB_NUM;
+    p = lj_buf_wuleb128(p, o->u32.lo);
+    p = lj_buf_wuleb128(p, o->u32.hi);
   } else {
     lua_assert(tvispri(o));
-    bcwrite_byte(ctx, BCDUMP_KTAB_NIL+~itype(o));
+    *p++ = BCDUMP_KTAB_NIL+~itype(o);
   }
+  setsbufP(&ctx->sb, p);
 }
 
 /* Write a template table. */
-static void bcwrite_ktab(BCWriteCtx *ctx, const GCtab *t)
+static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t)
 {
   MSize narray = 0, nhash = 0;
   if (t->asize > 0) {  /* Determine max. length of array part. */
@@ -119,8 +87,9 @@ static void bcwrite_ktab(BCWriteCtx *ctx, const GCtab *t)
       nhash += !tvisnil(&node[i].val);
   }
   /* Write number of array slots and hash slots. */
-  bcwrite_uleb128(ctx, narray);
-  bcwrite_uleb128(ctx, nhash);
+  p = lj_buf_wuleb128(p, narray);
+  p = lj_buf_wuleb128(p, nhash);
+  setsbufP(&ctx->sb, p);
   if (narray) {  /* Write array entries (may contain nil). */
     MSize i;
     TValue *o = tvref(t->array);
@@ -147,6 +116,7 @@ static void bcwrite_kgc(BCWriteCtx *ctx, GCproto *pt)
   for (i = 0; i < sizekgc; i++, kr++) {
     GCobj *o = gcref(*kr);
     MSize tp, need = 1;
+    char *p;
     /* Determine constant type and needed size. */
     if (o->gch.gct == ~LJ_TSTR) {
       tp = BCDUMP_KGC_STR + gco2str(o)->len;
@@ -173,24 +143,26 @@ static void bcwrite_kgc(BCWriteCtx *ctx, GCproto *pt)
       need = 1+2*5;
     }
     /* Write constant type. */
-    bcwrite_need(ctx, need);
-    bcwrite_uleb128(ctx, tp);
+    p = lj_buf_more(ctx->L, &ctx->sb, need);
+    p = lj_buf_wuleb128(p, tp);
     /* Write constant data (if any). */
     if (tp >= BCDUMP_KGC_STR) {
-      bcwrite_block(ctx, strdata(gco2str(o)), gco2str(o)->len);
+      p = lj_buf_wmem(p, strdata(gco2str(o)), gco2str(o)->len);
     } else if (tp == BCDUMP_KGC_TAB) {
-      bcwrite_ktab(ctx, gco2tab(o));
+      bcwrite_ktab(ctx, p, gco2tab(o));
+      continue;
 #if LJ_HASFFI
     } else if (tp != BCDUMP_KGC_CHILD) {
-      cTValue *p = (TValue *)cdataptr(gco2cd(o));
-      bcwrite_uleb128(ctx, p[0].u32.lo);
-      bcwrite_uleb128(ctx, p[0].u32.hi);
+      cTValue *q = (TValue *)cdataptr(gco2cd(o));
+      p = lj_buf_wuleb128(p, q[0].u32.lo);
+      p = lj_buf_wuleb128(p, q[0].u32.hi);
       if (tp == BCDUMP_KGC_COMPLEX) {
-       bcwrite_uleb128(ctx, p[1].u32.lo);
-       bcwrite_uleb128(ctx, p[1].u32.hi);
+       p = lj_buf_wuleb128(p, q[1].u32.lo);
+       p = lj_buf_wuleb128(p, q[1].u32.hi);
       }
 #endif
     }
+    setsbufP(&ctx->sb, p);
   }
 }
 
@@ -199,7 +171,7 @@ static void bcwrite_knum(BCWriteCtx *ctx, GCproto *pt)
 {
   MSize i, sizekn = pt->sizekn;
   cTValue *o = mref(pt->k, TValue);
-  bcwrite_need(ctx, 10*sizekn);
+  char *p = lj_buf_more(ctx->L, &ctx->sb, 10*sizekn);
   for (i = 0; i < sizekn; i++, o++) {
     int32_t k;
     if (tvisint(o)) {
@@ -212,58 +184,58 @@ static void bcwrite_knum(BCWriteCtx *ctx, GCproto *pt)
        k = lj_num2int(num);
        if (num == (lua_Number)k) {  /* -0 is never a constant. */
        save_int:
-         bcwrite_uleb128(ctx, 2*(uint32_t)k | ((uint32_t)k & 0x80000000u));
-         if (k < 0) {
-           char *p = &ctx->sb.buf[ctx->sb.n-1];
-           *p = (*p & 7) | ((k>>27) & 0x18);
-         }
+         p = lj_buf_wuleb128(p, 2*(uint32_t)k | ((uint32_t)k & 0x80000000u));
+         if (k < 0)
+           p[-1] = (p[-1] & 7) | ((k>>27) & 0x18);
          continue;
        }
       }
-      bcwrite_uleb128(ctx, 1+(2*o->u32.lo | (o->u32.lo & 0x80000000u)));
-      if (o->u32.lo >= 0x80000000u) {
-       char *p = &ctx->sb.buf[ctx->sb.n-1];
-       *p = (*p & 7) | ((o->u32.lo>>27) & 0x18);
-      }
-      bcwrite_uleb128(ctx, o->u32.hi);
+      p = lj_buf_wuleb128(p, 1+(2*o->u32.lo | (o->u32.lo & 0x80000000u)));
+      if (o->u32.lo >= 0x80000000u)
+       p[-1] = (p[-1] & 7) | ((o->u32.lo>>27) & 0x18);
+      p = lj_buf_wuleb128(p, o->u32.hi);
     }
   }
+  setsbufP(&ctx->sb, p);
 }
 
 /* Write bytecode instructions. */
-static void bcwrite_bytecode(BCWriteCtx *ctx, GCproto *pt)
+static char *bcwrite_bytecode(BCWriteCtx *ctx, char *p, GCproto *pt)
 {
   MSize nbc = pt->sizebc-1;  /* Omit the [JI]FUNC* header. */
 #if LJ_HASJIT
-  uint8_t *p = (uint8_t *)&ctx->sb.buf[ctx->sb.n];
+  uint8_t *q = (uint8_t *)p;
 #endif
-  bcwrite_block(ctx, proto_bc(pt)+1, nbc*(MSize)sizeof(BCIns));
+  p = lj_buf_wmem(p, proto_bc(pt)+1, nbc*(MSize)sizeof(BCIns));
+  UNUSED(ctx);
 #if LJ_HASJIT
   /* Unpatch modified bytecode containing ILOOP/JLOOP etc. */
   if ((pt->flags & PROTO_ILOOP) || pt->trace) {
     jit_State *J = L2J(ctx->L);
     MSize i;
-    for (i = 0; i < nbc; i++, p += sizeof(BCIns)) {
-      BCOp op = (BCOp)p[LJ_ENDIAN_SELECT(0, 3)];
+    for (i = 0; i < nbc; i++, q += sizeof(BCIns)) {
+      BCOp op = (BCOp)q[LJ_ENDIAN_SELECT(0, 3)];
       if (op == BC_IFORL || op == BC_IITERL || op == BC_ILOOP ||
          op == BC_JFORI) {
-       p[LJ_ENDIAN_SELECT(0, 3)] = (uint8_t)(op-BC_IFORL+BC_FORL);
+       q[LJ_ENDIAN_SELECT(0, 3)] = (uint8_t)(op-BC_IFORL+BC_FORL);
       } else if (op == BC_JFORL || op == BC_JITERL || op == BC_JLOOP) {
-       BCReg rd = p[LJ_ENDIAN_SELECT(2, 1)] + (p[LJ_ENDIAN_SELECT(3, 0)] << 8);
+       BCReg rd = q[LJ_ENDIAN_SELECT(2, 1)] + (q[LJ_ENDIAN_SELECT(3, 0)] << 8);
        BCIns ins = traceref(J, rd)->startins;
-       p[LJ_ENDIAN_SELECT(0, 3)] = (uint8_t)(op-BC_JFORL+BC_FORL);
-       p[LJ_ENDIAN_SELECT(2, 1)] = bc_c(ins);
-       p[LJ_ENDIAN_SELECT(3, 0)] = bc_b(ins);
+       q[LJ_ENDIAN_SELECT(0, 3)] = (uint8_t)(op-BC_JFORL+BC_FORL);
+       q[LJ_ENDIAN_SELECT(2, 1)] = bc_c(ins);
+       q[LJ_ENDIAN_SELECT(3, 0)] = bc_b(ins);
       }
     }
   }
 #endif
+  return p;
 }
 
 /* Write prototype. */
 static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt)
 {
   MSize sizedbg = 0;
+  char *p;
 
   /* Recursively write children of prototype. */
   if ((pt->flags & PROTO_CHILD)) {
@@ -277,31 +249,32 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt)
   }
 
   /* Start writing the prototype info to a buffer. */
-  lj_buf_reset(&ctx->sb);
-  ctx->sb.n = 5;  /* Leave room for final size. */
-  bcwrite_need(ctx, 4+6*5+(pt->sizebc-1)*(MSize)sizeof(BCIns)+pt->sizeuv*2);
+  p = lj_buf_need(ctx->L, &ctx->sb,
+                 5+4+6*5+(pt->sizebc-1)*(MSize)sizeof(BCIns)+pt->sizeuv*2);
+  p += 5;  /* Leave room for final size. */
 
   /* Write prototype header. */
-  bcwrite_byte(ctx, (pt->flags & (PROTO_CHILD|PROTO_VARARG|PROTO_FFI)));
-  bcwrite_byte(ctx, pt->numparams);
-  bcwrite_byte(ctx, pt->framesize);
-  bcwrite_byte(ctx, pt->sizeuv);
-  bcwrite_uleb128(ctx, pt->sizekgc);
-  bcwrite_uleb128(ctx, pt->sizekn);
-  bcwrite_uleb128(ctx, pt->sizebc-1);
+  *p++ = (pt->flags & (PROTO_CHILD|PROTO_VARARG|PROTO_FFI));
+  *p++ = pt->numparams;
+  *p++ = pt->framesize;
+  *p++ = pt->sizeuv;
+  p = lj_buf_wuleb128(p, pt->sizekgc);
+  p = lj_buf_wuleb128(p, pt->sizekn);
+  p = lj_buf_wuleb128(p, pt->sizebc-1);
   if (!ctx->strip) {
     if (proto_lineinfo(pt))
       sizedbg = pt->sizept - (MSize)((char *)proto_lineinfo(pt) - (char *)pt);
-    bcwrite_uleb128(ctx, sizedbg);
+    p = lj_buf_wuleb128(p, sizedbg);
     if (sizedbg) {
-      bcwrite_uleb128(ctx, pt->firstline);
-      bcwrite_uleb128(ctx, pt->numline);
+      p = lj_buf_wuleb128(p, pt->firstline);
+      p = lj_buf_wuleb128(p, pt->numline);
     }
   }
 
   /* Write bytecode instructions and upvalue refs. */
-  bcwrite_bytecode(ctx, pt);
-  bcwrite_block(ctx, proto_uv(pt), pt->sizeuv*2);
+  p = bcwrite_bytecode(ctx, p, pt);
+  p = lj_buf_wmem(p, proto_uv(pt), pt->sizeuv*2);
+  setsbufP(&ctx->sb, p);
 
   /* Write constants. */
   bcwrite_kgc(ctx, pt);
@@ -309,18 +282,19 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt)
 
   /* Write debug info, if not stripped. */
   if (sizedbg) {
-    bcwrite_need(ctx, sizedbg);
-    bcwrite_block(ctx, proto_lineinfo(pt), sizedbg);
+    p = lj_buf_more(ctx->L, &ctx->sb, sizedbg);
+    p = lj_buf_wmem(p, proto_lineinfo(pt), sizedbg);
+    setsbufP(&ctx->sb, p);
   }
 
   /* Pass buffer to writer function. */
   if (ctx->status == 0) {
-    MSize n = ctx->sb.n - 5;
+    MSize n = sbuflen(&ctx->sb) - 5;
     MSize nn = (lj_fls(n)+8)*9 >> 6;
-    ctx->sb.n = 5 - nn;
-    bcwrite_uleb128(ctx, n);  /* Fill in final size. */
-    lua_assert(ctx->sb.n == 5);
-    ctx->status = ctx->wfunc(ctx->L, ctx->sb.buf+5-nn, nn+n, ctx->wdata);
+    char *q = sbufB(&ctx->sb) + (5 - nn);
+    p = lj_buf_wuleb128(q, n);  /* Fill in final size. */
+    lua_assert(p == sbufB(&ctx->sb) + 5);
+    ctx->status = ctx->wfunc(ctx->L, q, nn+n, ctx->wdata);
   }
 }
 
@@ -330,20 +304,20 @@ static void bcwrite_header(BCWriteCtx *ctx)
   GCstr *chunkname = proto_chunkname(ctx->pt);
   const char *name = strdata(chunkname);
   MSize len = chunkname->len;
-  lj_buf_reset(&ctx->sb);
-  bcwrite_need(ctx, 5+5+len);
-  bcwrite_byte(ctx, BCDUMP_HEAD1);
-  bcwrite_byte(ctx, BCDUMP_HEAD2);
-  bcwrite_byte(ctx, BCDUMP_HEAD3);
-  bcwrite_byte(ctx, BCDUMP_VERSION);
-  bcwrite_byte(ctx, (ctx->strip ? BCDUMP_F_STRIP : 0) +
-                  (LJ_BE ? BCDUMP_F_BE : 0) +
-                  ((ctx->pt->flags & PROTO_FFI) ? BCDUMP_F_FFI : 0));
+  char *p = lj_buf_need(ctx->L, &ctx->sb, 5+5+len);
+  *p++ = BCDUMP_HEAD1;
+  *p++ = BCDUMP_HEAD2;
+  *p++ = BCDUMP_HEAD3;
+  *p++ = BCDUMP_VERSION;
+  *p++ = (ctx->strip ? BCDUMP_F_STRIP : 0) +
+                      (LJ_BE ? BCDUMP_F_BE : 0) +
+                      ((ctx->pt->flags & PROTO_FFI) ? BCDUMP_F_FFI : 0);
   if (!ctx->strip) {
-    bcwrite_uleb128(ctx, len);
-    bcwrite_block(ctx, name, len);
+    p = lj_buf_wuleb128(p, len);
+    p = lj_buf_wmem(p, name, len);
   }
-  ctx->status = ctx->wfunc(ctx->L, ctx->sb.buf, ctx->sb.n, ctx->wdata);
+  ctx->status = ctx->wfunc(ctx->L, sbufB(&ctx->sb),
+                          (MSize)(p - sbufB(&ctx->sb)), ctx->wdata);
 }
 
 /* Write footer of bytecode dump. */
@@ -360,7 +334,7 @@ static TValue *cpwriter(lua_State *L, lua_CFunction dummy, void *ud)
 {
   BCWriteCtx *ctx = (BCWriteCtx *)ud;
   UNUSED(dummy);
-  lj_buf_grow(L, &ctx->sb, 1024);  /* Avoids resize for most prototypes. */
+  lj_buf_need(L, &ctx->sb, 1024);  /* Avoids resize for most prototypes. */
   bcwrite_header(ctx);
   bcwrite_proto(ctx, ctx->pt);
   bcwrite_footer(ctx);
index 5d901d2a988a1e96661a826c171965fa9873a8f4..a05dc22e1fb708382c69615182517b0927c0ac9a 100644 (file)
 #include "lj_err.h"
 #include "lj_buf.h"
 
-LJ_NOINLINE void lj_buf_grow(lua_State *L, SBuf *sb, MSize sz)
+LJ_NOINLINE void lj_buf_grow(lua_State *L, SBuf *sb, char *en)
 {
-  MSize bsz = sb->sz * 2;
+  char *b = sbufB(sb);
+  MSize sz = (MSize)(en - b);
+  MSize osz = (MSize)(sbufE(sb) - b), nsz = osz;
+  MSize n = (MSize)(sbufP(sb) - b);
   if (LJ_UNLIKELY(sz > LJ_MAX_MEM))
     lj_err_mem(L);
-  if (bsz < LJ_MIN_SBUF) bsz = LJ_MIN_SBUF;
-  while (bsz < sz) bsz += bsz;
-  sb->buf = lj_mem_realloc(L, sb->buf, sb->sz, bsz);
-  sb->sz = bsz;
+  if (nsz < LJ_MIN_SBUF) nsz = LJ_MIN_SBUF;
+  while (nsz < sz) nsz += nsz;
+  b = (char *)lj_mem_realloc(L, b, osz, nsz);
+  setmref(sb->b, b);
+  setmref(sb->p, b + n);
+  setmref(sb->e, b + nsz);
 }
 
 char *lj_buf_tmp(lua_State *L, MSize sz)
@@ -31,10 +36,49 @@ char *lj_buf_tmp(lua_State *L, MSize sz)
 
 void lj_buf_shrink(lua_State *L, SBuf *sb)
 {
-  MSize sz = sb->sz;
-  if (sz > 2*LJ_MIN_SBUF) {
-    sb->buf = lj_mem_realloc(L, sb->buf, sz, (sz >> 1));
-    sb->sz = (sz >> 1);
+  char *b = sbufB(sb);
+  MSize osz = (MSize)(sbufE(sb) - b);
+  if (osz > 2*LJ_MIN_SBUF) {
+    MSize n = (MSize)(sbufP(sb) - b);
+    b = lj_mem_realloc(L, b, osz, (osz >> 1));
+    setmref(sb->b, b);
+    setmref(sb->p, b + n);
+    setmref(sb->e, b + (osz >> 1));
   }
 }
 
+char *lj_buf_wmem(char *p, const void *q, MSize len)
+{
+  const char *s = (const char *)q, *e = s + len;
+  while (s < e) *p++ = *s++;
+  return p;
+}
+
+void lj_buf_putmem(lua_State *L, SBuf *sb, const void *q, MSize len)
+{
+  char *p = lj_buf_more(L, sb, len);
+  p = lj_buf_wmem(p, q, len);
+  setsbufP(sb, p);
+}
+
+uint32_t lj_buf_ruleb128(const char **pp)
+{
+  const uint8_t *p = (const uint8_t *)*pp;
+  uint32_t v = *p++;
+  if (LJ_UNLIKELY(v >= 0x80)) {
+    int sh = 0;
+    v &= 0x7f;
+    do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80);
+  }
+  *pp = (const char *)p;
+  return v;
+}
+
+char *lj_buf_wuleb128(char *p, uint32_t v)
+{
+  for (; v >= 0x80; v >>= 7)
+    *p++ = (char)((v & 0x7f) | 0x80);
+  *p++ = (char)v;
+  return p;
+}
+
index 19f2bb0d8dd35ea3efa17a327f29bff99b4769f4..5a7eae312afec0af9759013430c988c0b5e0d262 100644 (file)
@@ -7,21 +7,67 @@
 #define _LJ_BUF_H
 
 #include "lj_obj.h"
+#include "lj_gc.h"
+#include "lj_str.h"
 
 /* Resizable string buffers. Struct definition in lj_obj.h. */
+#define sbufB(sb)      (mref((sb)->b, char))
+#define sbufP(sb)      (mref((sb)->p, char))
+#define sbufE(sb)      (mref((sb)->e, char))
+#define sbufsz(sb)     ((MSize)(sbufE((sb)) - sbufB((sb))))
+#define sbuflen(sb)    ((MSize)(sbufP((sb)) - sbufB((sb))))
+#define setsbufP(sb, q)        (setmref((sb)->p, (q)))
+
 LJ_FUNC char *lj_buf_tmp(lua_State *L, MSize sz);
-LJ_FUNC void lj_buf_grow(lua_State *L, SBuf *sb, MSize sz);
+LJ_FUNC void lj_buf_grow(lua_State *L, SBuf *sb, char *en);
 LJ_FUNC void lj_buf_shrink(lua_State *L, SBuf *sb);
 
-#define lj_buf_init(sb)                ((sb)->buf = NULL, (sb)->sz = 0)
-#define lj_buf_reset(sb)       ((sb)->n = 0)
-#define lj_buf_free(g, sb)     lj_mem_free(g, (void *)(sb)->buf, (sb)->sz)
+LJ_FUNC char *lj_buf_wmem(char *p, const void *q, MSize len);
+LJ_FUNC void lj_buf_putmem(lua_State *L, SBuf *sb, const void *q, MSize len);
+LJ_FUNC uint32_t lj_buf_ruleb128(const char **pp);
+LJ_FUNC char *lj_buf_wuleb128(char *p, uint32_t v);
+
+static LJ_AINLINE void lj_buf_init(SBuf *sb)
+{
+  setmref(sb->p, NULL); setmref(sb->e, NULL); setmref(sb->b, NULL);
+}
+
+static LJ_AINLINE void lj_buf_reset(SBuf *sb)
+{
+  setmrefr(sb->p, sb->b);
+}
+
+static LJ_AINLINE void lj_buf_free(global_State *g, SBuf *sb)
+{
+  lj_mem_free(g, sbufB(sb), sbufsz(sb));
+}
+
+static LJ_AINLINE GCstr *lj_buf_str(lua_State *L, SBuf *sb)
+{
+  return lj_str_new(L, sbufB(sb), sbuflen(sb));
+}
 
 static LJ_AINLINE char *lj_buf_need(lua_State *L, SBuf *sb, MSize sz)
 {
-  if (LJ_UNLIKELY(sz > sb->sz))
-    lj_buf_grow(L, sb, sz);
-  return sb->buf;
+  char *en = sbufB(sb) + sz;
+  if (LJ_UNLIKELY(en > sbufE(sb)))
+    lj_buf_grow(L, sb, en);
+  return sbufB(sb);
+}
+
+static LJ_AINLINE char *lj_buf_more(lua_State *L, SBuf *sb, MSize sz)
+{
+  char *en = sbufP(sb) + sz;
+  if (LJ_UNLIKELY(en > sbufE(sb)))
+    lj_buf_grow(L, sb, en);
+  return sbufP(sb);
+}
+
+static LJ_AINLINE void lj_buf_putb(lua_State *L, SBuf *sb, int c)
+{
+  char *p = lj_buf_more(L, sb, 1);
+  *p++ = (char)c;
+  setsbufP(sb, p);
 }
 
 #endif
index b88ce5d375b04a3b5095340bbcb4457291d15fe9..b8e31820fec7911f8ca11407f9f1d2f5323a0f1f 100644 (file)
@@ -86,22 +86,10 @@ static LJ_AINLINE CPChar cp_get(CPState *cp)
   return cp_get_bs(cp);
 }
 
-/* Grow save buffer. */
-static LJ_NOINLINE void cp_save_grow(CPState *cp, CPChar c)
-{
-  if (cp->sb.sz >= CPARSE_MAX_BUF/2)
-    cp_err(cp, LJ_ERR_XELEM);
-  lj_buf_grow(cp->L, &cp->sb, 0);
-  cp->sb.buf[cp->sb.n++] = (char)c;
-}
-
 /* Save character in buffer. */
 static LJ_AINLINE void cp_save(CPState *cp, CPChar c)
 {
-  if (LJ_UNLIKELY(cp->sb.n + 1 > cp->sb.sz))
-    cp_save_grow(cp, c);
-  else
-    cp->sb.buf[cp->sb.n++] = (char)c;
+  lj_buf_putb(cp->L, &cp->sb, c);
 }
 
 /* Skip line break. Handles "\n", "\r", "\r\n" or "\n\r". */
@@ -121,9 +109,9 @@ LJ_NORET static void cp_errmsg(CPState *cp, CPToken tok, ErrMsg em, ...)
     tokstr = NULL;
   } else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING ||
             tok >= CTOK_FIRSTDECL) {
-    if (cp->sb.n == 0) cp_save(cp, '$');
+    if (sbufP(&cp->sb) == sbufB(&cp->sb)) cp_save(cp, '$');
     cp_save(cp, '\0');
-    tokstr = cp->sb.buf;
+    tokstr = sbufB(&cp->sb);
   } else {
     tokstr = cp_tok2str(cp, tok);
   }
@@ -163,7 +151,7 @@ static CPToken cp_number(CPState *cp)
   TValue o;
   do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp)));
   cp_save(cp, '\0');
-  fmt = lj_strscan_scan((const uint8_t *)cp->sb.buf, &o, STRSCAN_OPT_C);
+  fmt = lj_strscan_scan((const uint8_t *)sbufB(&cp->sb), &o, STRSCAN_OPT_C);
   if (fmt == STRSCAN_INT) cp->val.id = CTID_INT32;
   else if (fmt == STRSCAN_U32) cp->val.id = CTID_UINT32;
   else if (!(cp->mode & CPARSE_MODE_SKIP))
@@ -176,7 +164,7 @@ static CPToken cp_number(CPState *cp)
 static CPToken cp_ident(CPState *cp)
 {
   do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp)));
-  cp->str = lj_str_new(cp->L, cp->sb.buf, cp->sb.n);
+  cp->str = lj_buf_str(cp->L, &cp->sb);
   cp->val.id = lj_ctype_getname(cp->cts, &cp->ct, cp->str, cp->tmask);
   if (ctype_type(cp->ct->info) == CT_KW)
     return ctype_cid(cp->ct->info);
@@ -262,11 +250,11 @@ static CPToken cp_string(CPState *cp)
   }
   cp_get(cp);
   if (delim == '"') {
-    cp->str = lj_str_new(cp->L, cp->sb.buf, cp->sb.n);
+    cp->str = lj_buf_str(cp->L, &cp->sb);
     return CTOK_STRING;
   } else {
-    if (cp->sb.n != 1) cp_err_token(cp, '\'');
-    cp->val.i32 = (int32_t)(char)cp->sb.buf[0];
+    if (sbuflen(&cp->sb) != 1) cp_err_token(cp, '\'');
+    cp->val.i32 = (int32_t)(char)*sbufB(&cp->sb);
     cp->val.id = CTID_INT32;
     return CTOK_INTEGER;
   }
index ec56b7d2c23f72d0664d518676ae852569f6a3a4..3f5028646d8e65500e4a02dccad013a5a3a5d40c 100644 (file)
@@ -9,6 +9,7 @@
 #include "lj_obj.h"
 #include "lj_err.h"
 #include "lj_debug.h"
+#include "lj_buf.h"
 #include "lj_str.h"
 #include "lj_tab.h"
 #include "lj_state.h"
@@ -133,20 +134,6 @@ static BCLine debug_frameline(lua_State *L, GCfunc *fn, cTValue *nextframe)
 
 /* -- Variable names ------------------------------------------------------ */
 
-/* Read ULEB128 value. */
-static uint32_t debug_read_uleb128(const uint8_t **pp)
-{
-  const uint8_t *p = *pp;
-  uint32_t v = *p++;
-  if (LJ_UNLIKELY(v >= 0x80)) {
-    int sh = 0;
-    v &= 0x7f;
-    do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80);
-  }
-  *pp = p;
-  return v;
-}
-
 /* Get name of a local variable from slot number and PC. */
 static const char *debug_varname(const GCproto *pt, BCPos pc, BCReg slot)
 {
@@ -162,9 +149,9 @@ static const char *debug_varname(const GCproto *pt, BCPos pc, BCReg slot)
       } else {
        while (*p++) ;  /* Skip over variable name string. */
       }
-      lastpc = startpc = lastpc + debug_read_uleb128(&p);
+      lastpc = startpc = lastpc + lj_buf_ruleb128((const char **)&p);
       if (startpc > pc) break;
-      endpc = startpc + debug_read_uleb128(&p);
+      endpc = startpc + lj_buf_ruleb128((const char **)&p);
       if (pc < endpc && slot-- == 0) {
        if (vn < VARNAME__MAX) {
 #define VARNAMESTR(name, str)  str "\0"
index 284195a15d2d4c18c4e8843eaa5fb3ec6f74e467..334a906e219080809c8bb6382256f6d98e93b219 100644 (file)
@@ -14,6 +14,7 @@
 #include "lj_err.h"
 #include "lj_debug.h"
 #include "lj_frame.h"
+#include "lj_buf.h"
 #include "lj_jit.h"
 #include "lj_dispatch.h"
 
@@ -426,16 +427,6 @@ static void gdbjit_catnum(GDBJITctx *ctx, uint32_t n)
   *ctx->p++ = '0' + n;
 }
 
-/* Add a ULEB128 value. */
-static void gdbjit_uleb128(GDBJITctx *ctx, uint32_t v)
-{
-  uint8_t *p = ctx->p;
-  for (; v >= 0x80; v >>= 7)
-    *p++ = (uint8_t)((v & 0x7f) | 0x80);
-  *p++ = (uint8_t)v;
-  ctx->p = p;
-}
-
 /* Add a SLEB128 value. */
 static void gdbjit_sleb128(GDBJITctx *ctx, int32_t v)
 {
@@ -452,7 +443,7 @@ static void gdbjit_sleb128(GDBJITctx *ctx, int32_t v)
 #define DU16(x)                (*(uint16_t *)p = (x), p += 2)
 #define DU32(x)                (*(uint32_t *)p = (x), p += 4)
 #define DADDR(x)       (*(uintptr_t *)p = (x), p += sizeof(uintptr_t))
-#define DUV(x)         (ctx->p = p, gdbjit_uleb128(ctx, (x)), p = ctx->p)
+#define DUV(x)         (p = (uint8_t *)lj_buf_wuleb128((char *)p, (x)))
 #define DSV(x)         (ctx->p = p, gdbjit_sleb128(ctx, (x)), p = ctx->p)
 #define DSTR(str)      (ctx->p = p, gdbjit_strz(ctx, (str)), p = ctx->p)
 #define DALIGNNOP(s)   while ((uintptr_t)p & ((s)-1)) *p++ = DW_CFA_nop
index 3227cadd17e04852e3b6d6262722035279b043a3..c4d52da241a72af58372edb59713102b24f2f7ee 100644 (file)
@@ -12,6 +12,7 @@
 #include "lj_obj.h"
 #include "lj_gc.h"
 #include "lj_err.h"
+#include "lj_buf.h"
 #include "lj_str.h"
 #if LJ_HASFFI
 #include "lj_tab.h"
@@ -54,20 +55,9 @@ static int fillbuf(LexState *ls)
   return char2int(*(ls->p++));
 }
 
-static LJ_NOINLINE void save_grow(LexState *ls, int c)
-{
-  if (ls->sb.sz >= LJ_MAX_STR/2)
-    lj_lex_error(ls, 0, LJ_ERR_XELEM);
-  lj_buf_grow(ls->L, &ls->sb, 0);
-  ls->sb.buf[ls->sb.n++] = (char)c;
-}
-
 static LJ_AINLINE void save(LexState *ls, int c)
 {
-  if (LJ_UNLIKELY(ls->sb.n + 1 > ls->sb.sz))
-    save_grow(ls, c);
-  else
-    ls->sb.buf[ls->sb.n++] = (char)c;
+  lj_buf_putb(ls->L, &ls->sb, c);
 }
 
 static void inclinenumber(LexState *ls)
@@ -99,7 +89,7 @@ static void lex_number(LexState *ls, TValue *tv)
     save_and_next(ls);
   }
   save(ls, '\0');
-  fmt = lj_strscan_scan((const uint8_t *)ls->sb.buf, tv,
+  fmt = lj_strscan_scan((const uint8_t *)sbufB(&ls->sb), tv,
          (LJ_DUALNUM ? STRSCAN_OPT_TOINT : STRSCAN_OPT_TONUM) |
          (LJ_HASFFI ? (STRSCAN_OPT_LL|STRSCAN_OPT_IMAG) : 0));
   if (LJ_DUALNUM && fmt == STRSCAN_INT) {
@@ -174,8 +164,8 @@ static void read_long_string(LexState *ls, TValue *tv, int sep)
     }
   } endloop:
   if (tv) {
-    GCstr *str = lj_parse_keepstr(ls, ls->sb.buf + (2 + (MSize)sep),
-                                     ls->sb.n - 2*(2 + (MSize)sep));
+    GCstr *str = lj_parse_keepstr(ls, sbufB(&ls->sb) + (2 + (MSize)sep),
+                                     sbuflen(&ls->sb) - 2*(2 + (MSize)sep));
     setstrV(ls->L, tv, str);
   }
 }
@@ -250,7 +240,8 @@ static void read_string(LexState *ls, int delim, TValue *tv)
     }
   }
   save_and_next(ls);  /* skip delimiter */
-  setstrV(ls->L, tv, lj_parse_keepstr(ls, ls->sb.buf + 1, ls->sb.n - 2));
+  setstrV(ls->L, tv,
+         lj_parse_keepstr(ls, sbufB(&ls->sb)+1, sbuflen(&ls->sb)-2));
 }
 
 /* -- Main lexical scanner ------------------------------------------------ */
@@ -269,7 +260,7 @@ static int llex(LexState *ls, TValue *tv)
       do {
        save_and_next(ls);
       } while (lj_char_isident(ls->current));
-      s = lj_parse_keepstr(ls, ls->sb.buf, ls->sb.n);
+      s = lj_parse_keepstr(ls, sbufB(&ls->sb), sbuflen(&ls->sb));
       setstrV(ls->L, tv, s);
       if (s->reserved > 0)  /* Reserved word? */
        return TK_OFS + s->reserved;
@@ -457,7 +448,7 @@ void lj_lex_error(LexState *ls, LexToken token, ErrMsg em, ...)
     tok = NULL;
   } else if (token == TK_name || token == TK_string || token == TK_number) {
     save(ls, '\0');
-    tok = ls->sb.buf;
+    tok = sbufB(&ls->sb);
   } else {
     tok = lj_lex_token2str(ls, token);
   }
index 7013f6eb75f20fb8d8f3b61c9b765df2bda03534..6e18e4b080b3ab0acaffd6db310e8e1f627c59bb 100644 (file)
@@ -10,7 +10,6 @@
 
 #include "lj_obj.h"
 #include "lj_err.h"
-#include "lj_buf.h"
 
 /* Lua lexer tokens. */
 #define TKDEF(_, __) \
index 6faedd10ffea263920db5bb2f8d288cf8e9afcd9..4d7b92627a338ac2f00cbc630ea10cd5d458fc9a 100644 (file)
@@ -121,9 +121,9 @@ typedef void (*ASMFunction)(void);
 
 /* Resizable string buffer. Need this here, details in lj_buf.h. */
 typedef struct SBuf {
-  char *buf;           /* String buffer base. */
-  MSize n;             /* String buffer length. */
-  MSize sz;            /* String buffer size. */
+  MRef p;              /* String buffer pointer. */
+  MRef e;              /* String buffer end pointer. */
+  MRef b;              /* String buffer base. */
 } SBuf;
 
 /* -- Tags and values ----------------------------------------------------- */
index 3f992becae58badee7aa598ac5f66d67021c1ce0..64652ed29b9428072c4568c8d89985c048210274 100644 (file)
@@ -13,6 +13,7 @@
 #include "lj_gc.h"
 #include "lj_err.h"
 #include "lj_debug.h"
+#include "lj_buf.h"
 #include "lj_str.h"
 #include "lj_tab.h"
 #include "lj_func.h"
@@ -1429,31 +1430,6 @@ static void fs_fixup_line(FuncState *fs, GCproto *pt,
   }
 }
 
-static LJ_AINLINE void fs_buf_need(LexState *ls, MSize len)
-{
-  lj_buf_need(ls->L, &ls->sb, ls->sb.n + len);
-}
-
-/* Add string to buffer. */
-static void fs_buf_str(LexState *ls, const char *str, MSize len)
-{
-  char *p = ls->sb.buf + ls->sb.n;
-  MSize i;
-  ls->sb.n += len;
-  for (i = 0; i < len; i++) p[i] = str[i];
-}
-
-/* Add ULEB128 value to buffer. */
-static void fs_buf_uleb128(LexState *ls, uint32_t v)
-{
-  MSize n = ls->sb.n;
-  uint8_t *p = (uint8_t *)ls->sb.buf;
-  for (; v >= 0x80; v >>= 7)
-    p[n++] = (uint8_t)((v & 0x7f) | 0x80);
-  p[n++] = (uint8_t)v;
-  ls->sb.n = n;
-}
-
 /* Prepare variable info for prototype. */
 static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar)
 {
@@ -1465,33 +1441,35 @@ static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar)
   for (i = 0, n = fs->nuv; i < n; i++) {
     GCstr *s = strref(vs[fs->uvmap[i]].name);
     MSize len = s->len+1;
-    fs_buf_need(ls, len);
-    fs_buf_str(ls, strdata(s), len);
+    char *p = lj_buf_more(ls->L, &ls->sb, len);
+    p = lj_buf_wmem(p, strdata(s), len);
+    setsbufP(&ls->sb, p);
   }
-  *ofsvar = ls->sb.n;
+  *ofsvar = sbuflen(&ls->sb);
   lastpc = 0;
   /* Store local variable names and compressed ranges. */
   for (ve = vs + ls->vtop, vs += fs->vbase; vs < ve; vs++) {
     if (!gola_isgotolabel(vs)) {
       GCstr *s = strref(vs->name);
       BCPos startpc;
+      char *p;
       if ((uintptr_t)s < VARNAME__MAX) {
-       fs_buf_need(ls, 1 + 2*5);
-       ls->sb.buf[ls->sb.n++] = (uint8_t)(uintptr_t)s;
+       p = lj_buf_more(ls->L, &ls->sb, 1 + 2*5);
+       *p++ = (char)(uintptr_t)s;
       } else {
        MSize len = s->len+1;
-       fs_buf_need(ls, len + 2*5);
-       fs_buf_str(ls, strdata(s), len);
+       p = lj_buf_more(ls->L, &ls->sb, len + 2*5);
+       p = lj_buf_wmem(p, strdata(s), len);
       }
       startpc = vs->startpc;
-      fs_buf_uleb128(ls, startpc-lastpc);
-      fs_buf_uleb128(ls, vs->endpc-startpc);
+      p = lj_buf_wuleb128(p, startpc-lastpc);
+      p = lj_buf_wuleb128(p, vs->endpc-startpc);
+      setsbufP(&ls->sb, p);
       lastpc = startpc;
     }
   }
-  fs_buf_need(ls, 1);
-  ls->sb.buf[ls->sb.n++] = '\0';  /* Terminator for varinfo. */
-  return ls->sb.n;
+  lj_buf_putb(ls->L, &ls->sb, '\0');  /* Terminator for varinfo. */
+  return sbuflen(&ls->sb);
 }
 
 /* Fixup variable info for prototype. */
@@ -1499,7 +1477,7 @@ static void fs_fixup_var(LexState *ls, GCproto *pt, uint8_t *p, size_t ofsvar)
 {
   setmref(pt->uvinfo, p);
   setmref(pt->varinfo, (char *)p + ofsvar);
-  memcpy(p, ls->sb.buf, ls->sb.n);  /* Copy from temp. string buffer. */
+  memcpy(p, sbufB(&ls->sb), sbuflen(&ls->sb));  /* Copy from temp. buffer. */
 }
 #else
 
index 623b362d85ee40272a50a8a3de3f25a8f84f8865..84bab864a322128a785889418709f78635cc411c 100644 (file)
@@ -218,20 +218,6 @@ GCstr * LJ_FASTCALL lj_str_fromnumber(lua_State *L, cTValue *o)
 
 /* -- String formatting --------------------------------------------------- */
 
-static void addstr(lua_State *L, SBuf *sb, const char *str, MSize len)
-{
-  MSize i;
-  char *p = lj_buf_need(L, sb, sb->n+len) + sb->n;
-  sb->n += len;
-  for (i = 0; i < len; i++) p[i] = str[i];
-}
-
-static void addchar(lua_State *L, SBuf *sb, int c)
-{
-  char *p = lj_buf_need(L, sb, sb->n+1);
-  p[sb->n++] = (char)c;
-}
-
 /* Push formatted message as a string object to Lua stack. va_list variant. */
 const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp)
 {
@@ -241,22 +227,22 @@ const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp)
   for (;;) {
     const char *e = strchr(fmt, '%');
     if (e == NULL) break;
-    addstr(L, sb, fmt, (MSize)(e-fmt));
+    lj_buf_putmem(L, sb, fmt, (MSize)(e-fmt));
     /* This function only handles %s, %c, %d, %f and %p formats. */
     switch (e[1]) {
     case 's': {
       const char *s = va_arg(argp, char *);
       if (s == NULL) s = "(null)";
-      addstr(L, sb, s, (MSize)strlen(s));
+      lj_buf_putmem(L, sb, s, (MSize)strlen(s));
       break;
       }
     case 'c':
-      addchar(L, sb, va_arg(argp, int));
+      lj_buf_putb(L, sb, va_arg(argp, int));
       break;
     case 'd': {
       char buf[LJ_STR_INTBUF];
       char *p = lj_str_bufint(buf, va_arg(argp, int32_t));
-      addstr(L, sb, p, (MSize)(buf+LJ_STR_INTBUF-p));
+      lj_buf_putmem(L, sb, p, (MSize)(buf+LJ_STR_INTBUF-p));
       break;
       }
     case 'f': {
@@ -265,7 +251,7 @@ const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp)
       MSize len;
       tv.n = (lua_Number)(va_arg(argp, LUAI_UACNUMBER));
       len = (MSize)lj_str_bufnum(buf, &tv);
-      addstr(L, sb, buf, len);
+      lj_buf_putmem(L, sb, buf, len);
       break;
       }
     case 'p': {
@@ -274,7 +260,7 @@ const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp)
       ptrdiff_t p = (ptrdiff_t)(va_arg(argp, void *));
       ptrdiff_t i, lasti = 2+FMTP_CHARS;
       if (p == 0) {
-       addstr(L, sb, "NULL", 4);
+       lj_buf_putmem(L, sb, "NULL", 4);
        break;
       }
 #if LJ_64
@@ -285,21 +271,21 @@ const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp)
       buf[1] = 'x';
       for (i = lasti-1; i >= 2; i--, p >>= 4)
        buf[i] = "0123456789abcdef"[(p & 15)];
-      addstr(L, sb, buf, (MSize)lasti);
+      lj_buf_putmem(L, sb, buf, (MSize)lasti);
       break;
       }
     case '%':
-      addchar(L, sb, '%');
+      lj_buf_putb(L, sb, '%');
       break;
     default:
-      addchar(L, sb, '%');
-      addchar(L, sb, e[1]);
+      lj_buf_putb(L, sb, '%');
+      lj_buf_putb(L, sb, e[1]);
       break;
     }
     fmt = e+2;
   }
-  addstr(L, sb, fmt, (MSize)strlen(fmt));
-  setstrV(L, L->top, lj_str_new(L, sb->buf, sb->n));
+  lj_buf_putmem(L, sb, fmt, (MSize)strlen(fmt));
+  setstrV(L, L->top, lj_buf_str(L, sb));
   incr_top(L);
   return strVdata(L->top - 1);
 }
index 6928e03bc6acefceb48d63da252dcf2edd51ca3a..1d4b60f433eb8a8464341f9a29994da22f74d43c 100644 (file)
@@ -1801,10 +1801,11 @@ static void build_subroutines(BuildCtx *ctx)
   |   cmp CARG2, #1
   |   blo ->fff_emptystr               // Zero-length string?
   |   bne ->fff_fallback               // Fallback for > 1-char strings.
-  |  ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.sz)]
-  |   ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.buf)]
+  |  ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.b)]
+  |   ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.e)]
   |   ldr CARG1, STR:CARG1[1]
-  |  cmp RB, CARG3
+  |  add INS, CARG2, CARG3
+  |  cmp RB, INS
   |  blo ->fff_fallback
   |1:  // Fill buffer with char.
   |   strb CARG1, [CARG2, CARG4]
@@ -1819,11 +1820,12 @@ static void build_subroutines(BuildCtx *ctx)
   |   blo ->fff_fallback
   |  checkstr CARG2, ->fff_fallback
   |  ldr CARG3, STR:CARG1->len
-  |   ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.sz)]
-  |    ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.buf)]
+  |   ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.b)]
+  |    ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.e)]
   |  mov CARG4, CARG3
   |  add CARG1, STR:CARG1, #sizeof(GCstr)
-  |   cmp RB, CARG3
+  |   add INS, CARG2, CARG3
+  |   cmp RB, INS
   |   blo ->fff_fallback
   |1:  // Reverse string copy.
   |  ldrb RB, [CARG1], #1
@@ -1840,11 +1842,12 @@ static void build_subroutines(BuildCtx *ctx)
   |   blo ->fff_fallback
   |  checkstr CARG2, ->fff_fallback
   |  ldr CARG3, STR:CARG1->len
-  |   ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.sz)]
-  |    ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.buf)]
+  |   ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.b)]
+  |    ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.e)]
   |  mov CARG4, #0
   |  add CARG1, STR:CARG1, #sizeof(GCstr)
-  |   cmp RB, CARG3
+  |   add INS, CARG2, CARG3
+  |   cmp RB, INS
   |   blo ->fff_fallback
   |1:  // ASCII case conversion.
   |  ldrb RB, [CARG1, CARG4]
index 5808e18245f06d22d2ec9a826ceaf27f98d00b1e..53000411efbb7cca216009a122f69c2a2c7004b4 100644 (file)
@@ -1736,14 +1736,15 @@ static void build_subroutines(BuildCtx *ctx)
   |  beqz AT, ->fff_fallback
   |.  lw TMP0, STR:CARG1->len
   |   mfc1 CARG3, f0
-  |  lw TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH)
+  |  lw CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH)
+  |   lw TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH)
   |  li AT, 1
   |   blez CARG3, ->fff_emptystr       // Count <= 0?
   |.   sltu AT, AT, TMP0
   |  beqz TMP0, ->fff_emptystr         // Zero length string?
-  |.  sltu TMP0, TMP1, CARG3
+  |.  addu TMP3, CARG2, CARG3
+  |  sltu TMP0, TMP1, TMP3
   |  or AT, AT, TMP0
-  |   lw CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH)
   |  bnez AT, ->fff_fallback           // Fallback for > 1-char strings.
   |.  lbu TMP0, STR:CARG1[1]
   |  addu TMP2, CARG2, CARG3
@@ -1762,14 +1763,14 @@ static void build_subroutines(BuildCtx *ctx)
   |  beqz NARGS8:RC, ->fff_fallback
   |.  li AT, LJ_TSTR
   |  bne CARG3, AT, ->fff_fallback
-  |.  lw TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH)
-  |  lw CARG3, STR:CARG1->len
+  |.  lw CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH)
+  |   lw CARG3, STR:CARG1->len
+  |  lw TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH)
   |   addiu CARG1, STR:CARG1, #STR
-  |   lw CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH)
-  |  sltu AT, TMP1, CARG3
+  |   addu CARG4, CARG2, CARG3
+  |  sltu AT, TMP1, CARG4
   |  bnez AT, ->fff_fallback
   |.  addu TMP3, CARG1, CARG3
-  |  addu CARG4, CARG2, CARG3
   |1:  // Reverse string copy.
   |   lbu TMP1, 0(CARG1)
   |  sltu AT, CARG1, TMP3
@@ -1787,11 +1788,12 @@ static void build_subroutines(BuildCtx *ctx)
   |  beqz NARGS8:RC, ->fff_fallback
   |.  li AT, LJ_TSTR
   |  bne CARG3, AT, ->fff_fallback
-  |.  lw TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH)
-  |  lw CARG3, STR:CARG1->len
+  |.  lw CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH)
+  |   lw CARG3, STR:CARG1->len
+  |  lw TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH)
   |   addiu CARG1, STR:CARG1, #STR
-  |   lw CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH)
-  |  sltu AT, TMP1, CARG3
+  |   addu TMP3, CARG2, CARG3
+  |  sltu AT, TMP1, TMP3
   |  bnez AT, ->fff_fallback
   |.  addu TMP3, CARG1, CARG3
   |  move CARG4, CARG2
index bff50c59ab052448b3180b4eccf4111026937c8c..514bd2312c817d741c8f70786ebe009bccde25f3 100644 (file)
@@ -2201,15 +2201,16 @@ static void build_subroutines(BuildCtx *ctx)
   |.endif
   |   lwz TMP0, STR:CARG1->len
   |  cmpwi CARG3, 0
-  |   lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH)
+  |   lwz TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH)
+  |   lwz CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH)
   |  ble >2                            // Count <= 0? (or non-int)
   |   cmplwi TMP0, 1
+  |   add TMP3, CARG2, CARG3
   |  subi TMP2, CARG3, 1
   |   blt >2                           // Zero length string?
-  |  cmplw cr1, TMP1, CARG3
+  |  cmplw cr1, TMP1, TMP3
   |   bne ->fff_fallback               // Fallback for > 1-char strings.
   |   lbz TMP0, STR:CARG1[1]
-  |   lp CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH)
   |  blt cr1, ->fff_fallback
   |1:  // Fill buffer with char. Yes, this is suboptimal code (do you care?).
   |  cmplwi TMP2, 0
@@ -2229,13 +2230,14 @@ static void build_subroutines(BuildCtx *ctx)
   |    lwz STR:CARG1, 4(BASE)
   |  blt ->fff_fallback
   |  checkstr CARG3
-  |   lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH)
+  |   lwz CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH)
+  |   lwz TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH)
   |  bne ->fff_fallback
   |  lwz CARG3, STR:CARG1->len
   |   la CARG1, #STR(STR:CARG1)
-  |   lp CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH)
   |   li TMP2, 0
-  |  cmplw TMP1, CARG3
+  |   add TMP3, CARG2, CARG3
+  |  cmplw TMP1, TMP3
   |   subi TMP3, CARG3, 1
   |  blt ->fff_fallback
   |1:  // Reverse string copy.
@@ -2255,13 +2257,14 @@ static void build_subroutines(BuildCtx *ctx)
   |    lwz STR:CARG1, 4(BASE)
   |  blt ->fff_fallback
   |  checkstr CARG3
-  |   lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH)
+  |   lwz CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH)
+  |   lwz TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH)
   |  bne ->fff_fallback
   |  lwz CARG3, STR:CARG1->len
   |   la CARG1, #STR(STR:CARG1)
-  |   lp CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH)
-  |  cmplw TMP1, CARG3
   |   li TMP2, 0
+  |   add TMP3, CARG2, CARG3
+  |  cmplw TMP1, TMP3
   |  blt ->fff_fallback
   |1:  // ASCII case conversion.
   |  cmplw TMP2, CARG3
index 0a53ffde24e3b9f51fd9151702d779cafcab158c..3fd897ec62a4ebe9dcfaf07d90dcc172c8e29cb8 100644 (file)
@@ -2356,20 +2356,21 @@ static void build_subroutines(BuildCtx *ctx)
   |  cmp dword STR:RB->len, 1
   |  jb ->fff_emptystr                 // Zero length string?
   |  jne ->fff_fallback_2              // Fallback for > 1-char strings.
-  |  cmp [DISPATCH+DISPATCH_GL(tmpbuf.sz)], RC;  jb ->fff_fallback_2
   |  movzx RA, byte STR:RB[1]
-  |  mov RB, [DISPATCH+DISPATCH_GL(tmpbuf.buf)]
+  |  mov RB, [DISPATCH+DISPATCH_GL(tmpbuf.b)]
+  |  add RB, RC
+  |  cmp [DISPATCH+DISPATCH_GL(tmpbuf.e)], RB;  jb ->fff_fallback_2
   |.if X64
   |  mov TMP3, RC
   |.else
   |  mov ARG3, RC
   |.endif
-  |1:  // Fill buffer with char. Yes, this is suboptimal code (do you care?).
-  |  mov [RB], RAL
-  |  add RB, 1
+  |1:  // Fill buffer with char.
+  |  sub RB, 1
   |  sub RC, 1
+  |  mov [RB], RAL
   |  jnz <1
-  |  mov RD, [DISPATCH+DISPATCH_GL(tmpbuf.buf)]
+  |  mov RD, [DISPATCH+DISPATCH_GL(tmpbuf.b)]
   |  jmp ->fff_newstr
   |
   |.ffunc_1 string_reverse
@@ -2379,15 +2380,16 @@ static void build_subroutines(BuildCtx *ctx)
   |  mov RC, STR:RB->len
   |  test RC, RC
   |  jz ->fff_emptystr                 // Zero length string?
-  |  cmp [DISPATCH+DISPATCH_GL(tmpbuf.sz)], RC;  jb ->fff_fallback_1
-  |  add RB, #STR
   |  mov TMP2, PC                      // Need another temp register.
+  |  mov PC, [DISPATCH+DISPATCH_GL(tmpbuf.b)]
+  |  lea RA, [PC+RC]
+  |  cmp [DISPATCH+DISPATCH_GL(tmpbuf.e)], RA;  jb ->fff_fallback_1
+  |  add RB, #STR
   |.if X64
   |  mov TMP3, RC
   |.else
   |  mov ARG3, RC
   |.endif
-  |  mov PC, [DISPATCH+DISPATCH_GL(tmpbuf.buf)]
   |1:
   |  movzx RA, byte [RB]
   |  add RB, 1
@@ -2402,17 +2404,18 @@ static void build_subroutines(BuildCtx *ctx)
   |  .ffunc_1 name
   |  ffgccheck
   |  cmp dword [BASE+4], LJ_TSTR;  jne ->fff_fallback
+  |  mov TMP2, PC                      // Need another temp register.
   |  mov STR:RB, [BASE]
   |  mov RC, STR:RB->len
-  |  cmp [DISPATCH+DISPATCH_GL(tmpbuf.sz)], RC;  jb ->fff_fallback_1
+  |  mov PC, [DISPATCH+DISPATCH_GL(tmpbuf.b)]
+  |  lea RA, [PC+RC]
+  |  cmp [DISPATCH+DISPATCH_GL(tmpbuf.e)], RA;  jb ->fff_fallback_1
   |  add RB, #STR
-  |  mov TMP2, PC                      // Need another temp register.
   |.if X64
   |  mov TMP3, RC
   |.else
   |  mov ARG3, RC
   |.endif
-  |  mov PC, [DISPATCH+DISPATCH_GL(tmpbuf.buf)]
   |  jmp >3
   |1:  // ASCII case conversion. Yes, this is suboptimal code (do you care?).
   |  movzx RA, byte [RB+RC]