From 116cdd7e9a578efffa5a9ca38167d059d12296d7 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Wed, 27 Feb 2013 21:17:27 +0100 Subject: [PATCH] String buffer refactoring, part 2. Switch to pointers for start/pos/end of buffer. Abstract out some buffer writers. --- src/Makefile.dep | 39 ++++----- src/lib_string.c | 1 + src/lj_bcread.c | 21 ++--- src/lj_bcwrite.c | 204 +++++++++++++++++++++-------------------------- src/lj_buf.c | 64 ++++++++++++--- src/lj_buf.h | 60 ++++++++++++-- src/lj_cparse.c | 28 ++----- src/lj_debug.c | 19 +---- src/lj_gdbjit.c | 13 +-- src/lj_lex.c | 27 +++---- src/lj_lex.h | 1 - src/lj_obj.h | 6 +- src/lj_parse.c | 54 ++++--------- src/lj_str.c | 38 +++------ src/vm_arm.dasc | 21 ++--- src/vm_mips.dasc | 26 +++--- src/vm_ppc.dasc | 21 ++--- src/vm_x86.dasc | 27 ++++--- 18 files changed, 334 insertions(+), 336 deletions(-) diff --git a/src/Makefile.dep b/src/Makefile.dep index 56594704..f841767b 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -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 \ diff --git a/src/lib_string.c b/src/lib_string.c index 5fdfcd91..36fd3f53 100644 --- a/src/lib_string.c +++ b/src/lib_string.c @@ -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" diff --git a/src/lj_bcread.c b/src/lj_bcread.c index fabe76da..eda121e0 100644 --- a/src/lj_bcread.c +++ b/src/lj_bcread.c @@ -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; diff --git a/src/lj_bcwrite.c b/src/lj_bcwrite.c index 474234c5..71c86581 100644 --- a/src/lj_bcwrite.c +++ b/src/lj_bcwrite.c @@ -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); diff --git a/src/lj_buf.c b/src/lj_buf.c index 5d901d2a..a05dc22e 100644 --- a/src/lj_buf.c +++ b/src/lj_buf.c @@ -13,15 +13,20 @@ #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; +} + diff --git a/src/lj_buf.h b/src/lj_buf.h index 19f2bb0d..5a7eae31 100644 --- a/src/lj_buf.h +++ b/src/lj_buf.h @@ -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 diff --git a/src/lj_cparse.c b/src/lj_cparse.c index b88ce5d3..b8e31820 100644 --- a/src/lj_cparse.c +++ b/src/lj_cparse.c @@ -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; } diff --git a/src/lj_debug.c b/src/lj_debug.c index ec56b7d2..3f502864 100644 --- a/src/lj_debug.c +++ b/src/lj_debug.c @@ -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" diff --git a/src/lj_gdbjit.c b/src/lj_gdbjit.c index 284195a1..334a906e 100644 --- a/src/lj_gdbjit.c +++ b/src/lj_gdbjit.c @@ -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 diff --git a/src/lj_lex.c b/src/lj_lex.c index 3227cadd..c4d52da2 100644 --- a/src/lj_lex.c +++ b/src/lj_lex.c @@ -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); } diff --git a/src/lj_lex.h b/src/lj_lex.h index 7013f6eb..6e18e4b0 100644 --- a/src/lj_lex.h +++ b/src/lj_lex.h @@ -10,7 +10,6 @@ #include "lj_obj.h" #include "lj_err.h" -#include "lj_buf.h" /* Lua lexer tokens. */ #define TKDEF(_, __) \ diff --git a/src/lj_obj.h b/src/lj_obj.h index 6faedd10..4d7b9262 100644 --- a/src/lj_obj.h +++ b/src/lj_obj.h @@ -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 ----------------------------------------------------- */ diff --git a/src/lj_parse.c b/src/lj_parse.c index 3f992bec..64652ed2 100644 --- a/src/lj_parse.c +++ b/src/lj_parse.c @@ -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 diff --git a/src/lj_str.c b/src/lj_str.c index 623b362d..84bab864 100644 --- a/src/lj_str.c +++ b/src/lj_str.c @@ -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); } diff --git a/src/vm_arm.dasc b/src/vm_arm.dasc index 6928e03b..1d4b60f4 100644 --- a/src/vm_arm.dasc +++ b/src/vm_arm.dasc @@ -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] diff --git a/src/vm_mips.dasc b/src/vm_mips.dasc index 5808e182..53000411 100644 --- a/src/vm_mips.dasc +++ b/src/vm_mips.dasc @@ -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 diff --git a/src/vm_ppc.dasc b/src/vm_ppc.dasc index bff50c59..514bd231 100644 --- a/src/vm_ppc.dasc +++ b/src/vm_ppc.dasc @@ -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 diff --git a/src/vm_x86.dasc b/src/vm_x86.dasc index 0a53ffde..3fd897ec 100644 --- a/src/vm_x86.dasc +++ b/src/vm_x86.dasc @@ -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]