aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2013-02-27 21:17:27 +0100
committerMike Pall <mike>2013-02-27 21:28:28 +0100
commit116cdd7e9a578efffa5a9ca38167d059d12296d7 (patch)
treecc78e44c4b7a2175f2b16bc5f8898597a72bb228
parent28cfcf77445e144335961a020e3e08d84cf0091f (diff)
downloadluajit-116cdd7e9a578efffa5a9ca38167d059d12296d7.tar.gz
luajit-116cdd7e9a578efffa5a9ca38167d059d12296d7.tar.bz2
luajit-116cdd7e9a578efffa5a9ca38167d059d12296d7.zip
String buffer refactoring, part 2.
Switch to pointers for start/pos/end of buffer. Abstract out some buffer writers.
-rw-r--r--src/Makefile.dep39
-rw-r--r--src/lib_string.c1
-rw-r--r--src/lj_bcread.c21
-rw-r--r--src/lj_bcwrite.c204
-rw-r--r--src/lj_buf.c64
-rw-r--r--src/lj_buf.h60
-rw-r--r--src/lj_cparse.c28
-rw-r--r--src/lj_debug.c19
-rw-r--r--src/lj_gdbjit.c13
-rw-r--r--src/lj_lex.c27
-rw-r--r--src/lj_lex.h1
-rw-r--r--src/lj_obj.h6
-rw-r--r--src/lj_parse.c54
-rw-r--r--src/lj_str.c38
-rw-r--r--src/vm_arm.dasc21
-rw-r--r--src/vm_mips.dasc26
-rw-r--r--src/vm_ppc.dasc21
-rw-r--r--src/vm_x86.dasc27
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 \
17 lj_ccallback.h lj_clib.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h 17 lj_ccallback.h lj_clib.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h
18lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h 18lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h
19lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ 19lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
20 lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_state.h lj_ff.h \ 20 lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_state.h \
21 lj_ffdef.h lj_lib.h lj_libdef.h 21 lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h
22lib_jit.o: lib_jit.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h \ 22lib_jit.o: lib_jit.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h \
23 lj_obj.h lj_def.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h \ 23 lj_obj.h lj_def.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h \
24 lj_bc.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_target.h \ 24 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 \
31lib_package.o: lib_package.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ 31lib_package.o: lib_package.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
32 lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_lib.h 32 lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_lib.h
33lib_string.o: lib_string.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ 33lib_string.o: lib_string.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
34 lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h \ 34 lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h \
35 lj_meta.h lj_state.h lj_ff.h lj_ffdef.h lj_bcdump.h lj_lex.h lj_buf.h \ 35 lj_tab.h lj_meta.h lj_state.h lj_ff.h lj_ffdef.h lj_bcdump.h lj_lex.h \
36 lj_char.h lj_lib.h lj_libdef.h 36 lj_char.h lj_lib.h lj_libdef.h
37lib_table.o: lib_table.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ 37lib_table.o: lib_table.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
38 lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_lib.h \ 38 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 \
56 lj_gc.h lj_buf.h lj_str.h lj_bc.h lj_ctype.h lj_dispatch.h lj_jit.h \ 56 lj_gc.h lj_buf.h lj_str.h lj_bc.h lj_ctype.h lj_dispatch.h lj_jit.h \
57 lj_ir.h lj_bcdump.h lj_lex.h lj_err.h lj_errmsg.h lj_vm.h 57 lj_ir.h lj_bcdump.h lj_lex.h lj_err.h lj_errmsg.h lj_vm.h
58lj_buf.o: lj_buf.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 58lj_buf.o: lj_buf.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
59 lj_err.h lj_errmsg.h lj_buf.h 59 lj_err.h lj_errmsg.h lj_buf.h lj_str.h
60lj_carith.o: lj_carith.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 60lj_carith.o: lj_carith.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
61 lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_meta.h lj_ctype.h lj_cconv.h \ 61 lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_meta.h lj_ctype.h lj_cconv.h \
62 lj_cdata.h lj_carith.h 62 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 \
91lj_ctype.o: lj_ctype.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 91lj_ctype.o: lj_ctype.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
92 lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_ccallback.h 92 lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_ccallback.h
93lj_debug.o: lj_debug.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 93lj_debug.o: lj_debug.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
94 lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h lj_state.h lj_frame.h \ 94 lj_err.h lj_errmsg.h lj_debug.h lj_buf.h lj_gc.h lj_str.h lj_tab.h \
95 lj_bc.h lj_jit.h lj_ir.h 95 lj_state.h lj_frame.h lj_bc.h lj_jit.h lj_ir.h
96lj_dispatch.o: lj_dispatch.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 96lj_dispatch.o: lj_dispatch.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
97 lj_err.h lj_errmsg.h lj_func.h lj_str.h lj_tab.h lj_meta.h lj_debug.h \ 97 lj_err.h lj_errmsg.h lj_func.h lj_str.h lj_tab.h lj_meta.h lj_debug.h \
98 lj_state.h lj_frame.h lj_bc.h lj_ff.h lj_ffdef.h lj_jit.h lj_ir.h \ 98 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 \
115 lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cdata.h lj_trace.h \ 115 lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cdata.h lj_trace.h \
116 lj_jit.h lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h 116 lj_jit.h lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h
117lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 117lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
118 lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_frame.h lj_bc.h lj_jit.h \ 118 lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_frame.h lj_bc.h lj_buf.h \
119 lj_ir.h lj_dispatch.h 119 lj_str.h lj_jit.h lj_ir.h lj_dispatch.h
120lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 120lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
121 lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \ 121 lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \
122 lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h lj_carith.h \ 122 lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h lj_carith.h \
123 lj_vm.h lj_strscan.h lj_lib.h 123 lj_vm.h lj_strscan.h lj_lib.h
124lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 124lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
125 lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h lualib.h \ 125 lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h \
126 lj_state.h lj_lex.h lj_buf.h lj_parse.h lj_char.h lj_strscan.h 126 lualib.h lj_state.h lj_lex.h lj_parse.h lj_char.h lj_strscan.h
127lj_lib.o: lj_lib.c lauxlib.h lua.h luaconf.h lj_obj.h lj_def.h lj_arch.h \ 127lj_lib.o: lj_lib.c lauxlib.h lua.h luaconf.h lj_obj.h lj_def.h lj_arch.h \
128 lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h lj_bc.h \ 128 lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h lj_bc.h \
129 lj_dispatch.h lj_jit.h lj_ir.h lj_vm.h lj_strscan.h lj_lex.h lj_buf.h \ 129 lj_dispatch.h lj_jit.h lj_ir.h lj_vm.h lj_strscan.h lj_lex.h lj_bcdump.h \
130 lj_bcdump.h lj_lib.h 130 lj_lib.h
131lj_load.o: lj_load.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \ 131lj_load.o: lj_load.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \
132 lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_func.h \ 132 lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_func.h \
133 lj_frame.h lj_bc.h lj_vm.h lj_lex.h lj_bcdump.h lj_parse.h 133 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 \
145 lj_bc.h lj_traceerr.h lj_ctype.h lj_gc.h lj_carith.h lj_vm.h \ 145 lj_bc.h lj_traceerr.h lj_ctype.h lj_gc.h lj_carith.h lj_vm.h \
146 lj_strscan.h lj_folddef.h 146 lj_strscan.h lj_folddef.h
147lj_opt_loop.o: lj_opt_loop.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 147lj_opt_loop.o: lj_opt_loop.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
148 lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_ir.h lj_jit.h lj_iropt.h \ 148 lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_ir.h lj_jit.h \
149 lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_snap.h lj_vm.h 149 lj_iropt.h lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_snap.h \
150 lj_vm.h
150lj_opt_mem.o: lj_opt_mem.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 151lj_opt_mem.o: lj_opt_mem.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
151 lj_tab.h lj_ir.h lj_jit.h lj_iropt.h 152 lj_tab.h lj_ir.h lj_jit.h lj_iropt.h
152lj_opt_narrow.o: lj_opt_narrow.c lj_obj.h lua.h luaconf.h lj_def.h \ 153lj_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 \
155lj_opt_sink.o: lj_opt_sink.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 156lj_opt_sink.o: lj_opt_sink.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
156 lj_ir.h lj_jit.h lj_iropt.h lj_target.h lj_target_*.h 157 lj_ir.h lj_jit.h lj_iropt.h lj_target.h lj_target_*.h
157lj_opt_split.o: lj_opt_split.c lj_obj.h lua.h luaconf.h lj_def.h \ 158lj_opt_split.o: lj_opt_split.c lj_obj.h lua.h luaconf.h lj_def.h \
158 lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_ir.h lj_jit.h \ 159 lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_ir.h \
159 lj_ircall.h lj_iropt.h lj_vm.h 160 lj_jit.h lj_ircall.h lj_iropt.h lj_vm.h
160lj_parse.o: lj_parse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 161lj_parse.o: lj_parse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
161 lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h lj_func.h \ 162 lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_buf.h lj_str.h lj_tab.h \
162 lj_state.h lj_bc.h lj_ctype.h lj_lex.h lj_buf.h lj_parse.h lj_vm.h \ 163 lj_func.h lj_state.h lj_bc.h lj_ctype.h lj_lex.h lj_parse.h lj_vm.h \
163 lj_vmevent.h 164 lj_vmevent.h
164lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 165lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
165 lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \ 166 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 @@
18#include "lj_obj.h" 18#include "lj_obj.h"
19#include "lj_gc.h" 19#include "lj_gc.h"
20#include "lj_err.h" 20#include "lj_err.h"
21#include "lj_buf.h"
21#include "lj_str.h" 22#include "lj_str.h"
22#include "lj_tab.h" 23#include "lj_tab.h"
23#include "lj_meta.h" 24#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)
53 const char *buf; 53 const char *buf;
54 size_t size; 54 size_t size;
55 if (ls->n) { /* Copy remainder to buffer. */ 55 if (ls->n) { /* Copy remainder to buffer. */
56 if (ls->sb.n) { /* Move down in buffer. */ 56 if (sbuflen(&ls->sb)) { /* Move down in buffer. */
57 lua_assert(ls->p + ls->n == ls->sb.buf + ls->sb.n); 57 lua_assert(ls->p + ls->n == sbufP(&ls->sb));
58 if (ls->n != ls->sb.n) 58 if (ls->n != sbuflen(&ls->sb))
59 memmove(ls->sb.buf, ls->p, ls->n); 59 memmove(sbufB(&ls->sb), ls->p, ls->n);
60 } else { /* Copy from buffer provided by reader. */ 60 } else { /* Copy from buffer provided by reader. */
61 memcpy(lj_buf_need(ls->L, &ls->sb, len), ls->p, ls->n); 61 memcpy(lj_buf_need(ls->L, &ls->sb, len), ls->p, ls->n);
62 } 62 }
63 ls->p = ls->sb.buf; 63 ls->p = sbufB(&ls->sb);
64 } 64 }
65 ls->sb.n = ls->n; 65 setsbufP(&ls->sb, sbufB(&ls->sb) + ls->n);
66 buf = ls->rfunc(ls->L, ls->rdata, &size); /* Get more data from reader. */ 66 buf = ls->rfunc(ls->L, ls->rdata, &size); /* Get more data from reader. */
67 if (buf == NULL || size == 0) { /* EOF? */ 67 if (buf == NULL || size == 0) { /* EOF? */
68 if (need) bcread_error(ls, LJ_ERR_BCBAD); 68 if (need) bcread_error(ls, LJ_ERR_BCBAD);
69 ls->current = -1; /* Only bad if we get called again. */ 69 ls->current = -1; /* Only bad if we get called again. */
70 break; 70 break;
71 } 71 }
72 if (ls->sb.n) { /* Append to buffer. */ 72 if (sbuflen(&ls->sb)) { /* Append to buffer. */
73 MSize n = ls->sb.n + (MSize)size; 73 MSize n = sbuflen(&ls->sb) + (MSize)size;
74 char *p = lj_buf_need(ls->L, &ls->sb, n < len ? len : n); 74 char *p = lj_buf_need(ls->L, &ls->sb, n < len ? len : n);
75 memcpy(p + ls->sb.n, buf, size); 75 memcpy(sbufP(&ls->sb), buf, size);
76 ls->n = ls->sb.n = n; 76 setsbufP(&ls->sb, sbufB(&ls->sb) + n);
77 ls->n = n;
77 ls->p = p; 78 ls->p = p;
78 } else { /* Return buffer provided by reader. */ 79 } else { /* Return buffer provided by reader. */
79 ls->n = (MSize)size; 80 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 {
32 int status; /* Status from writer callback. */ 32 int status; /* Status from writer callback. */
33} BCWriteCtx; 33} BCWriteCtx;
34 34
35/* -- Output buffer handling ---------------------------------------------- */
36
37/* Ensure a certain amount of buffer space. */
38static LJ_AINLINE void bcwrite_need(BCWriteCtx *ctx, MSize len)
39{
40 lj_buf_need(ctx->L, &ctx->sb, ctx->sb.n + len);
41}
42
43/* Add memory block to buffer. */
44static void bcwrite_block(BCWriteCtx *ctx, const void *p, MSize len)
45{
46 uint8_t *q = (uint8_t *)(ctx->sb.buf + ctx->sb.n);
47 MSize i;
48 ctx->sb.n += len;
49 for (i = 0; i < len; i++) q[i] = ((uint8_t *)p)[i];
50}
51
52/* Add byte to buffer. */
53static LJ_AINLINE void bcwrite_byte(BCWriteCtx *ctx, uint8_t b)
54{
55 ctx->sb.buf[ctx->sb.n++] = b;
56}
57
58/* Add ULEB128 value to buffer. */
59static void bcwrite_uleb128(BCWriteCtx *ctx, uint32_t v)
60{
61 MSize n = ctx->sb.n;
62 uint8_t *p = (uint8_t *)ctx->sb.buf;
63 for (; v >= 0x80; v >>= 7)
64 p[n++] = (uint8_t)((v & 0x7f) | 0x80);
65 p[n++] = (uint8_t)v;
66 ctx->sb.n = n;
67}
68
69/* -- Bytecode writer ----------------------------------------------------- */ 35/* -- Bytecode writer ----------------------------------------------------- */
70 36
71/* Write a single constant key/value of a template table. */ 37/* Write a single constant key/value of a template table. */
72static void bcwrite_ktabk(BCWriteCtx *ctx, cTValue *o, int narrow) 38static void bcwrite_ktabk(BCWriteCtx *ctx, cTValue *o, int narrow)
73{ 39{
74 bcwrite_need(ctx, 1+10); 40 char *p = lj_buf_more(ctx->L, &ctx->sb, 1+10);
75 if (tvisstr(o)) { 41 if (tvisstr(o)) {
76 const GCstr *str = strV(o); 42 const GCstr *str = strV(o);
77 MSize len = str->len; 43 MSize len = str->len;
78 bcwrite_need(ctx, 5+len); 44 p = lj_buf_more(ctx->L, &ctx->sb, 5+len);
79 bcwrite_uleb128(ctx, BCDUMP_KTAB_STR+len); 45 p = lj_buf_wuleb128(p, BCDUMP_KTAB_STR+len);
80 bcwrite_block(ctx, strdata(str), len); 46 p = lj_buf_wmem(p, strdata(str), len);
81 } else if (tvisint(o)) { 47 } else if (tvisint(o)) {
82 bcwrite_byte(ctx, BCDUMP_KTAB_INT); 48 *p++ = BCDUMP_KTAB_INT;
83 bcwrite_uleb128(ctx, intV(o)); 49 p = lj_buf_wuleb128(p, intV(o));
84 } else if (tvisnum(o)) { 50 } else if (tvisnum(o)) {
85 if (!LJ_DUALNUM && narrow) { /* Narrow number constants to integers. */ 51 if (!LJ_DUALNUM && narrow) { /* Narrow number constants to integers. */
86 lua_Number num = numV(o); 52 lua_Number num = numV(o);
87 int32_t k = lj_num2int(num); 53 int32_t k = lj_num2int(num);
88 if (num == (lua_Number)k) { /* -0 is never a constant. */ 54 if (num == (lua_Number)k) { /* -0 is never a constant. */
89 bcwrite_byte(ctx, BCDUMP_KTAB_INT); 55 *p++ = BCDUMP_KTAB_INT;
90 bcwrite_uleb128(ctx, k); 56 p = lj_buf_wuleb128(p, k);
57 setsbufP(&ctx->sb, p);
91 return; 58 return;
92 } 59 }
93 } 60 }
94 bcwrite_byte(ctx, BCDUMP_KTAB_NUM); 61 *p++ = BCDUMP_KTAB_NUM;
95 bcwrite_uleb128(ctx, o->u32.lo); 62 p = lj_buf_wuleb128(p, o->u32.lo);
96 bcwrite_uleb128(ctx, o->u32.hi); 63 p = lj_buf_wuleb128(p, o->u32.hi);
97 } else { 64 } else {
98 lua_assert(tvispri(o)); 65 lua_assert(tvispri(o));
99 bcwrite_byte(ctx, BCDUMP_KTAB_NIL+~itype(o)); 66 *p++ = BCDUMP_KTAB_NIL+~itype(o);
100 } 67 }
68 setsbufP(&ctx->sb, p);
101} 69}
102 70
103/* Write a template table. */ 71/* Write a template table. */
104static void bcwrite_ktab(BCWriteCtx *ctx, const GCtab *t) 72static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t)
105{ 73{
106 MSize narray = 0, nhash = 0; 74 MSize narray = 0, nhash = 0;
107 if (t->asize > 0) { /* Determine max. length of array part. */ 75 if (t->asize > 0) { /* Determine max. length of array part. */
@@ -119,8 +87,9 @@ static void bcwrite_ktab(BCWriteCtx *ctx, const GCtab *t)
119 nhash += !tvisnil(&node[i].val); 87 nhash += !tvisnil(&node[i].val);
120 } 88 }
121 /* Write number of array slots and hash slots. */ 89 /* Write number of array slots and hash slots. */
122 bcwrite_uleb128(ctx, narray); 90 p = lj_buf_wuleb128(p, narray);
123 bcwrite_uleb128(ctx, nhash); 91 p = lj_buf_wuleb128(p, nhash);
92 setsbufP(&ctx->sb, p);
124 if (narray) { /* Write array entries (may contain nil). */ 93 if (narray) { /* Write array entries (may contain nil). */
125 MSize i; 94 MSize i;
126 TValue *o = tvref(t->array); 95 TValue *o = tvref(t->array);
@@ -147,6 +116,7 @@ static void bcwrite_kgc(BCWriteCtx *ctx, GCproto *pt)
147 for (i = 0; i < sizekgc; i++, kr++) { 116 for (i = 0; i < sizekgc; i++, kr++) {
148 GCobj *o = gcref(*kr); 117 GCobj *o = gcref(*kr);
149 MSize tp, need = 1; 118 MSize tp, need = 1;
119 char *p;
150 /* Determine constant type and needed size. */ 120 /* Determine constant type and needed size. */
151 if (o->gch.gct == ~LJ_TSTR) { 121 if (o->gch.gct == ~LJ_TSTR) {
152 tp = BCDUMP_KGC_STR + gco2str(o)->len; 122 tp = BCDUMP_KGC_STR + gco2str(o)->len;
@@ -173,24 +143,26 @@ static void bcwrite_kgc(BCWriteCtx *ctx, GCproto *pt)
173 need = 1+2*5; 143 need = 1+2*5;
174 } 144 }
175 /* Write constant type. */ 145 /* Write constant type. */
176 bcwrite_need(ctx, need); 146 p = lj_buf_more(ctx->L, &ctx->sb, need);
177 bcwrite_uleb128(ctx, tp); 147 p = lj_buf_wuleb128(p, tp);
178 /* Write constant data (if any). */ 148 /* Write constant data (if any). */
179 if (tp >= BCDUMP_KGC_STR) { 149 if (tp >= BCDUMP_KGC_STR) {
180 bcwrite_block(ctx, strdata(gco2str(o)), gco2str(o)->len); 150 p = lj_buf_wmem(p, strdata(gco2str(o)), gco2str(o)->len);
181 } else if (tp == BCDUMP_KGC_TAB) { 151 } else if (tp == BCDUMP_KGC_TAB) {
182 bcwrite_ktab(ctx, gco2tab(o)); 152 bcwrite_ktab(ctx, p, gco2tab(o));
153 continue;
183#if LJ_HASFFI 154#if LJ_HASFFI
184 } else if (tp != BCDUMP_KGC_CHILD) { 155 } else if (tp != BCDUMP_KGC_CHILD) {
185 cTValue *p = (TValue *)cdataptr(gco2cd(o)); 156 cTValue *q = (TValue *)cdataptr(gco2cd(o));
186 bcwrite_uleb128(ctx, p[0].u32.lo); 157 p = lj_buf_wuleb128(p, q[0].u32.lo);
187 bcwrite_uleb128(ctx, p[0].u32.hi); 158 p = lj_buf_wuleb128(p, q[0].u32.hi);
188 if (tp == BCDUMP_KGC_COMPLEX) { 159 if (tp == BCDUMP_KGC_COMPLEX) {
189 bcwrite_uleb128(ctx, p[1].u32.lo); 160 p = lj_buf_wuleb128(p, q[1].u32.lo);
190 bcwrite_uleb128(ctx, p[1].u32.hi); 161 p = lj_buf_wuleb128(p, q[1].u32.hi);
191 } 162 }
192#endif 163#endif
193 } 164 }
165 setsbufP(&ctx->sb, p);
194 } 166 }
195} 167}
196 168
@@ -199,7 +171,7 @@ static void bcwrite_knum(BCWriteCtx *ctx, GCproto *pt)
199{ 171{
200 MSize i, sizekn = pt->sizekn; 172 MSize i, sizekn = pt->sizekn;
201 cTValue *o = mref(pt->k, TValue); 173 cTValue *o = mref(pt->k, TValue);
202 bcwrite_need(ctx, 10*sizekn); 174 char *p = lj_buf_more(ctx->L, &ctx->sb, 10*sizekn);
203 for (i = 0; i < sizekn; i++, o++) { 175 for (i = 0; i < sizekn; i++, o++) {
204 int32_t k; 176 int32_t k;
205 if (tvisint(o)) { 177 if (tvisint(o)) {
@@ -212,58 +184,58 @@ static void bcwrite_knum(BCWriteCtx *ctx, GCproto *pt)
212 k = lj_num2int(num); 184 k = lj_num2int(num);
213 if (num == (lua_Number)k) { /* -0 is never a constant. */ 185 if (num == (lua_Number)k) { /* -0 is never a constant. */
214 save_int: 186 save_int:
215 bcwrite_uleb128(ctx, 2*(uint32_t)k | ((uint32_t)k & 0x80000000u)); 187 p = lj_buf_wuleb128(p, 2*(uint32_t)k | ((uint32_t)k & 0x80000000u));
216 if (k < 0) { 188 if (k < 0)
217 char *p = &ctx->sb.buf[ctx->sb.n-1]; 189 p[-1] = (p[-1] & 7) | ((k>>27) & 0x18);
218 *p = (*p & 7) | ((k>>27) & 0x18);
219 }
220 continue; 190 continue;
221 } 191 }
222 } 192 }
223 bcwrite_uleb128(ctx, 1+(2*o->u32.lo | (o->u32.lo & 0x80000000u))); 193 p = lj_buf_wuleb128(p, 1+(2*o->u32.lo | (o->u32.lo & 0x80000000u)));
224 if (o->u32.lo >= 0x80000000u) { 194 if (o->u32.lo >= 0x80000000u)
225 char *p = &ctx->sb.buf[ctx->sb.n-1]; 195 p[-1] = (p[-1] & 7) | ((o->u32.lo>>27) & 0x18);
226 *p = (*p & 7) | ((o->u32.lo>>27) & 0x18); 196 p = lj_buf_wuleb128(p, o->u32.hi);
227 }
228 bcwrite_uleb128(ctx, o->u32.hi);
229 } 197 }
230 } 198 }
199 setsbufP(&ctx->sb, p);
231} 200}
232 201
233/* Write bytecode instructions. */ 202/* Write bytecode instructions. */
234static void bcwrite_bytecode(BCWriteCtx *ctx, GCproto *pt) 203static char *bcwrite_bytecode(BCWriteCtx *ctx, char *p, GCproto *pt)
235{ 204{
236 MSize nbc = pt->sizebc-1; /* Omit the [JI]FUNC* header. */ 205 MSize nbc = pt->sizebc-1; /* Omit the [JI]FUNC* header. */
237#if LJ_HASJIT 206#if LJ_HASJIT
238 uint8_t *p = (uint8_t *)&ctx->sb.buf[ctx->sb.n]; 207 uint8_t *q = (uint8_t *)p;
239#endif 208#endif
240 bcwrite_block(ctx, proto_bc(pt)+1, nbc*(MSize)sizeof(BCIns)); 209 p = lj_buf_wmem(p, proto_bc(pt)+1, nbc*(MSize)sizeof(BCIns));
210 UNUSED(ctx);
241#if LJ_HASJIT 211#if LJ_HASJIT
242 /* Unpatch modified bytecode containing ILOOP/JLOOP etc. */ 212 /* Unpatch modified bytecode containing ILOOP/JLOOP etc. */
243 if ((pt->flags & PROTO_ILOOP) || pt->trace) { 213 if ((pt->flags & PROTO_ILOOP) || pt->trace) {
244 jit_State *J = L2J(ctx->L); 214 jit_State *J = L2J(ctx->L);
245 MSize i; 215 MSize i;
246 for (i = 0; i < nbc; i++, p += sizeof(BCIns)) { 216 for (i = 0; i < nbc; i++, q += sizeof(BCIns)) {
247 BCOp op = (BCOp)p[LJ_ENDIAN_SELECT(0, 3)]; 217 BCOp op = (BCOp)q[LJ_ENDIAN_SELECT(0, 3)];
248 if (op == BC_IFORL || op == BC_IITERL || op == BC_ILOOP || 218 if (op == BC_IFORL || op == BC_IITERL || op == BC_ILOOP ||
249 op == BC_JFORI) { 219 op == BC_JFORI) {
250 p[LJ_ENDIAN_SELECT(0, 3)] = (uint8_t)(op-BC_IFORL+BC_FORL); 220 q[LJ_ENDIAN_SELECT(0, 3)] = (uint8_t)(op-BC_IFORL+BC_FORL);
251 } else if (op == BC_JFORL || op == BC_JITERL || op == BC_JLOOP) { 221 } else if (op == BC_JFORL || op == BC_JITERL || op == BC_JLOOP) {
252 BCReg rd = p[LJ_ENDIAN_SELECT(2, 1)] + (p[LJ_ENDIAN_SELECT(3, 0)] << 8); 222 BCReg rd = q[LJ_ENDIAN_SELECT(2, 1)] + (q[LJ_ENDIAN_SELECT(3, 0)] << 8);
253 BCIns ins = traceref(J, rd)->startins; 223 BCIns ins = traceref(J, rd)->startins;
254 p[LJ_ENDIAN_SELECT(0, 3)] = (uint8_t)(op-BC_JFORL+BC_FORL); 224 q[LJ_ENDIAN_SELECT(0, 3)] = (uint8_t)(op-BC_JFORL+BC_FORL);
255 p[LJ_ENDIAN_SELECT(2, 1)] = bc_c(ins); 225 q[LJ_ENDIAN_SELECT(2, 1)] = bc_c(ins);
256 p[LJ_ENDIAN_SELECT(3, 0)] = bc_b(ins); 226 q[LJ_ENDIAN_SELECT(3, 0)] = bc_b(ins);
257 } 227 }
258 } 228 }
259 } 229 }
260#endif 230#endif
231 return p;
261} 232}
262 233
263/* Write prototype. */ 234/* Write prototype. */
264static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt) 235static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt)
265{ 236{
266 MSize sizedbg = 0; 237 MSize sizedbg = 0;
238 char *p;
267 239
268 /* Recursively write children of prototype. */ 240 /* Recursively write children of prototype. */
269 if ((pt->flags & PROTO_CHILD)) { 241 if ((pt->flags & PROTO_CHILD)) {
@@ -277,31 +249,32 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt)
277 } 249 }
278 250
279 /* Start writing the prototype info to a buffer. */ 251 /* Start writing the prototype info to a buffer. */
280 lj_buf_reset(&ctx->sb); 252 p = lj_buf_need(ctx->L, &ctx->sb,
281 ctx->sb.n = 5; /* Leave room for final size. */ 253 5+4+6*5+(pt->sizebc-1)*(MSize)sizeof(BCIns)+pt->sizeuv*2);
282 bcwrite_need(ctx, 4+6*5+(pt->sizebc-1)*(MSize)sizeof(BCIns)+pt->sizeuv*2); 254 p += 5; /* Leave room for final size. */
283 255
284 /* Write prototype header. */ 256 /* Write prototype header. */
285 bcwrite_byte(ctx, (pt->flags & (PROTO_CHILD|PROTO_VARARG|PROTO_FFI))); 257 *p++ = (pt->flags & (PROTO_CHILD|PROTO_VARARG|PROTO_FFI));
286 bcwrite_byte(ctx, pt->numparams); 258 *p++ = pt->numparams;
287 bcwrite_byte(ctx, pt->framesize); 259 *p++ = pt->framesize;
288 bcwrite_byte(ctx, pt->sizeuv); 260 *p++ = pt->sizeuv;
289 bcwrite_uleb128(ctx, pt->sizekgc); 261 p = lj_buf_wuleb128(p, pt->sizekgc);
290 bcwrite_uleb128(ctx, pt->sizekn); 262 p = lj_buf_wuleb128(p, pt->sizekn);
291 bcwrite_uleb128(ctx, pt->sizebc-1); 263 p = lj_buf_wuleb128(p, pt->sizebc-1);
292 if (!ctx->strip) { 264 if (!ctx->strip) {
293 if (proto_lineinfo(pt)) 265 if (proto_lineinfo(pt))
294 sizedbg = pt->sizept - (MSize)((char *)proto_lineinfo(pt) - (char *)pt); 266 sizedbg = pt->sizept - (MSize)((char *)proto_lineinfo(pt) - (char *)pt);
295 bcwrite_uleb128(ctx, sizedbg); 267 p = lj_buf_wuleb128(p, sizedbg);
296 if (sizedbg) { 268 if (sizedbg) {
297 bcwrite_uleb128(ctx, pt->firstline); 269 p = lj_buf_wuleb128(p, pt->firstline);
298 bcwrite_uleb128(ctx, pt->numline); 270 p = lj_buf_wuleb128(p, pt->numline);
299 } 271 }
300 } 272 }
301 273
302 /* Write bytecode instructions and upvalue refs. */ 274 /* Write bytecode instructions and upvalue refs. */
303 bcwrite_bytecode(ctx, pt); 275 p = bcwrite_bytecode(ctx, p, pt);
304 bcwrite_block(ctx, proto_uv(pt), pt->sizeuv*2); 276 p = lj_buf_wmem(p, proto_uv(pt), pt->sizeuv*2);
277 setsbufP(&ctx->sb, p);
305 278
306 /* Write constants. */ 279 /* Write constants. */
307 bcwrite_kgc(ctx, pt); 280 bcwrite_kgc(ctx, pt);
@@ -309,18 +282,19 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt)
309 282
310 /* Write debug info, if not stripped. */ 283 /* Write debug info, if not stripped. */
311 if (sizedbg) { 284 if (sizedbg) {
312 bcwrite_need(ctx, sizedbg); 285 p = lj_buf_more(ctx->L, &ctx->sb, sizedbg);
313 bcwrite_block(ctx, proto_lineinfo(pt), sizedbg); 286 p = lj_buf_wmem(p, proto_lineinfo(pt), sizedbg);
287 setsbufP(&ctx->sb, p);
314 } 288 }
315 289
316 /* Pass buffer to writer function. */ 290 /* Pass buffer to writer function. */
317 if (ctx->status == 0) { 291 if (ctx->status == 0) {
318 MSize n = ctx->sb.n - 5; 292 MSize n = sbuflen(&ctx->sb) - 5;
319 MSize nn = (lj_fls(n)+8)*9 >> 6; 293 MSize nn = (lj_fls(n)+8)*9 >> 6;
320 ctx->sb.n = 5 - nn; 294 char *q = sbufB(&ctx->sb) + (5 - nn);
321 bcwrite_uleb128(ctx, n); /* Fill in final size. */ 295 p = lj_buf_wuleb128(q, n); /* Fill in final size. */
322 lua_assert(ctx->sb.n == 5); 296 lua_assert(p == sbufB(&ctx->sb) + 5);
323 ctx->status = ctx->wfunc(ctx->L, ctx->sb.buf+5-nn, nn+n, ctx->wdata); 297 ctx->status = ctx->wfunc(ctx->L, q, nn+n, ctx->wdata);
324 } 298 }
325} 299}
326 300
@@ -330,20 +304,20 @@ static void bcwrite_header(BCWriteCtx *ctx)
330 GCstr *chunkname = proto_chunkname(ctx->pt); 304 GCstr *chunkname = proto_chunkname(ctx->pt);
331 const char *name = strdata(chunkname); 305 const char *name = strdata(chunkname);
332 MSize len = chunkname->len; 306 MSize len = chunkname->len;
333 lj_buf_reset(&ctx->sb); 307 char *p = lj_buf_need(ctx->L, &ctx->sb, 5+5+len);
334 bcwrite_need(ctx, 5+5+len); 308 *p++ = BCDUMP_HEAD1;
335 bcwrite_byte(ctx, BCDUMP_HEAD1); 309 *p++ = BCDUMP_HEAD2;
336 bcwrite_byte(ctx, BCDUMP_HEAD2); 310 *p++ = BCDUMP_HEAD3;
337 bcwrite_byte(ctx, BCDUMP_HEAD3); 311 *p++ = BCDUMP_VERSION;
338 bcwrite_byte(ctx, BCDUMP_VERSION); 312 *p++ = (ctx->strip ? BCDUMP_F_STRIP : 0) +
339 bcwrite_byte(ctx, (ctx->strip ? BCDUMP_F_STRIP : 0) + 313 (LJ_BE ? BCDUMP_F_BE : 0) +
340 (LJ_BE ? BCDUMP_F_BE : 0) + 314 ((ctx->pt->flags & PROTO_FFI) ? BCDUMP_F_FFI : 0);
341 ((ctx->pt->flags & PROTO_FFI) ? BCDUMP_F_FFI : 0));
342 if (!ctx->strip) { 315 if (!ctx->strip) {
343 bcwrite_uleb128(ctx, len); 316 p = lj_buf_wuleb128(p, len);
344 bcwrite_block(ctx, name, len); 317 p = lj_buf_wmem(p, name, len);
345 } 318 }
346 ctx->status = ctx->wfunc(ctx->L, ctx->sb.buf, ctx->sb.n, ctx->wdata); 319 ctx->status = ctx->wfunc(ctx->L, sbufB(&ctx->sb),
320 (MSize)(p - sbufB(&ctx->sb)), ctx->wdata);
347} 321}
348 322
349/* Write footer of bytecode dump. */ 323/* Write footer of bytecode dump. */
@@ -360,7 +334,7 @@ static TValue *cpwriter(lua_State *L, lua_CFunction dummy, void *ud)
360{ 334{
361 BCWriteCtx *ctx = (BCWriteCtx *)ud; 335 BCWriteCtx *ctx = (BCWriteCtx *)ud;
362 UNUSED(dummy); 336 UNUSED(dummy);
363 lj_buf_grow(L, &ctx->sb, 1024); /* Avoids resize for most prototypes. */ 337 lj_buf_need(L, &ctx->sb, 1024); /* Avoids resize for most prototypes. */
364 bcwrite_header(ctx); 338 bcwrite_header(ctx);
365 bcwrite_proto(ctx, ctx->pt); 339 bcwrite_proto(ctx, ctx->pt);
366 bcwrite_footer(ctx); 340 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 @@
13#include "lj_err.h" 13#include "lj_err.h"
14#include "lj_buf.h" 14#include "lj_buf.h"
15 15
16LJ_NOINLINE void lj_buf_grow(lua_State *L, SBuf *sb, MSize sz) 16LJ_NOINLINE void lj_buf_grow(lua_State *L, SBuf *sb, char *en)
17{ 17{
18 MSize bsz = sb->sz * 2; 18 char *b = sbufB(sb);
19 MSize sz = (MSize)(en - b);
20 MSize osz = (MSize)(sbufE(sb) - b), nsz = osz;
21 MSize n = (MSize)(sbufP(sb) - b);
19 if (LJ_UNLIKELY(sz > LJ_MAX_MEM)) 22 if (LJ_UNLIKELY(sz > LJ_MAX_MEM))
20 lj_err_mem(L); 23 lj_err_mem(L);
21 if (bsz < LJ_MIN_SBUF) bsz = LJ_MIN_SBUF; 24 if (nsz < LJ_MIN_SBUF) nsz = LJ_MIN_SBUF;
22 while (bsz < sz) bsz += bsz; 25 while (nsz < sz) nsz += nsz;
23 sb->buf = lj_mem_realloc(L, sb->buf, sb->sz, bsz); 26 b = (char *)lj_mem_realloc(L, b, osz, nsz);
24 sb->sz = bsz; 27 setmref(sb->b, b);
28 setmref(sb->p, b + n);
29 setmref(sb->e, b + nsz);
25} 30}
26 31
27char *lj_buf_tmp(lua_State *L, MSize sz) 32char *lj_buf_tmp(lua_State *L, MSize sz)
@@ -31,10 +36,49 @@ char *lj_buf_tmp(lua_State *L, MSize sz)
31 36
32void lj_buf_shrink(lua_State *L, SBuf *sb) 37void lj_buf_shrink(lua_State *L, SBuf *sb)
33{ 38{
34 MSize sz = sb->sz; 39 char *b = sbufB(sb);
35 if (sz > 2*LJ_MIN_SBUF) { 40 MSize osz = (MSize)(sbufE(sb) - b);
36 sb->buf = lj_mem_realloc(L, sb->buf, sz, (sz >> 1)); 41 if (osz > 2*LJ_MIN_SBUF) {
37 sb->sz = (sz >> 1); 42 MSize n = (MSize)(sbufP(sb) - b);
43 b = lj_mem_realloc(L, b, osz, (osz >> 1));
44 setmref(sb->b, b);
45 setmref(sb->p, b + n);
46 setmref(sb->e, b + (osz >> 1));
38 } 47 }
39} 48}
40 49
50char *lj_buf_wmem(char *p, const void *q, MSize len)
51{
52 const char *s = (const char *)q, *e = s + len;
53 while (s < e) *p++ = *s++;
54 return p;
55}
56
57void lj_buf_putmem(lua_State *L, SBuf *sb, const void *q, MSize len)
58{
59 char *p = lj_buf_more(L, sb, len);
60 p = lj_buf_wmem(p, q, len);
61 setsbufP(sb, p);
62}
63
64uint32_t lj_buf_ruleb128(const char **pp)
65{
66 const uint8_t *p = (const uint8_t *)*pp;
67 uint32_t v = *p++;
68 if (LJ_UNLIKELY(v >= 0x80)) {
69 int sh = 0;
70 v &= 0x7f;
71 do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80);
72 }
73 *pp = (const char *)p;
74 return v;
75}
76
77char *lj_buf_wuleb128(char *p, uint32_t v)
78{
79 for (; v >= 0x80; v >>= 7)
80 *p++ = (char)((v & 0x7f) | 0x80);
81 *p++ = (char)v;
82 return p;
83}
84
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 @@
7#define _LJ_BUF_H 7#define _LJ_BUF_H
8 8
9#include "lj_obj.h" 9#include "lj_obj.h"
10#include "lj_gc.h"
11#include "lj_str.h"
10 12
11/* Resizable string buffers. Struct definition in lj_obj.h. */ 13/* Resizable string buffers. Struct definition in lj_obj.h. */
14#define sbufB(sb) (mref((sb)->b, char))
15#define sbufP(sb) (mref((sb)->p, char))
16#define sbufE(sb) (mref((sb)->e, char))
17#define sbufsz(sb) ((MSize)(sbufE((sb)) - sbufB((sb))))
18#define sbuflen(sb) ((MSize)(sbufP((sb)) - sbufB((sb))))
19#define setsbufP(sb, q) (setmref((sb)->p, (q)))
20
12LJ_FUNC char *lj_buf_tmp(lua_State *L, MSize sz); 21LJ_FUNC char *lj_buf_tmp(lua_State *L, MSize sz);
13LJ_FUNC void lj_buf_grow(lua_State *L, SBuf *sb, MSize sz); 22LJ_FUNC void lj_buf_grow(lua_State *L, SBuf *sb, char *en);
14LJ_FUNC void lj_buf_shrink(lua_State *L, SBuf *sb); 23LJ_FUNC void lj_buf_shrink(lua_State *L, SBuf *sb);
15 24
16#define lj_buf_init(sb) ((sb)->buf = NULL, (sb)->sz = 0) 25LJ_FUNC char *lj_buf_wmem(char *p, const void *q, MSize len);
17#define lj_buf_reset(sb) ((sb)->n = 0) 26LJ_FUNC void lj_buf_putmem(lua_State *L, SBuf *sb, const void *q, MSize len);
18#define lj_buf_free(g, sb) lj_mem_free(g, (void *)(sb)->buf, (sb)->sz) 27LJ_FUNC uint32_t lj_buf_ruleb128(const char **pp);
28LJ_FUNC char *lj_buf_wuleb128(char *p, uint32_t v);
29
30static LJ_AINLINE void lj_buf_init(SBuf *sb)
31{
32 setmref(sb->p, NULL); setmref(sb->e, NULL); setmref(sb->b, NULL);
33}
34
35static LJ_AINLINE void lj_buf_reset(SBuf *sb)
36{
37 setmrefr(sb->p, sb->b);
38}
39
40static LJ_AINLINE void lj_buf_free(global_State *g, SBuf *sb)
41{
42 lj_mem_free(g, sbufB(sb), sbufsz(sb));
43}
44
45static LJ_AINLINE GCstr *lj_buf_str(lua_State *L, SBuf *sb)
46{
47 return lj_str_new(L, sbufB(sb), sbuflen(sb));
48}
19 49
20static LJ_AINLINE char *lj_buf_need(lua_State *L, SBuf *sb, MSize sz) 50static LJ_AINLINE char *lj_buf_need(lua_State *L, SBuf *sb, MSize sz)
21{ 51{
22 if (LJ_UNLIKELY(sz > sb->sz)) 52 char *en = sbufB(sb) + sz;
23 lj_buf_grow(L, sb, sz); 53 if (LJ_UNLIKELY(en > sbufE(sb)))
24 return sb->buf; 54 lj_buf_grow(L, sb, en);
55 return sbufB(sb);
56}
57
58static LJ_AINLINE char *lj_buf_more(lua_State *L, SBuf *sb, MSize sz)
59{
60 char *en = sbufP(sb) + sz;
61 if (LJ_UNLIKELY(en > sbufE(sb)))
62 lj_buf_grow(L, sb, en);
63 return sbufP(sb);
64}
65
66static LJ_AINLINE void lj_buf_putb(lua_State *L, SBuf *sb, int c)
67{
68 char *p = lj_buf_more(L, sb, 1);
69 *p++ = (char)c;
70 setsbufP(sb, p);
25} 71}
26 72
27#endif 73#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)
86 return cp_get_bs(cp); 86 return cp_get_bs(cp);
87} 87}
88 88
89/* Grow save buffer. */
90static LJ_NOINLINE void cp_save_grow(CPState *cp, CPChar c)
91{
92 if (cp->sb.sz >= CPARSE_MAX_BUF/2)
93 cp_err(cp, LJ_ERR_XELEM);
94 lj_buf_grow(cp->L, &cp->sb, 0);
95 cp->sb.buf[cp->sb.n++] = (char)c;
96}
97
98/* Save character in buffer. */ 89/* Save character in buffer. */
99static LJ_AINLINE void cp_save(CPState *cp, CPChar c) 90static LJ_AINLINE void cp_save(CPState *cp, CPChar c)
100{ 91{
101 if (LJ_UNLIKELY(cp->sb.n + 1 > cp->sb.sz)) 92 lj_buf_putb(cp->L, &cp->sb, c);
102 cp_save_grow(cp, c);
103 else
104 cp->sb.buf[cp->sb.n++] = (char)c;
105} 93}
106 94
107/* Skip line break. Handles "\n", "\r", "\r\n" or "\n\r". */ 95/* 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, ...)
121 tokstr = NULL; 109 tokstr = NULL;
122 } else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING || 110 } else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING ||
123 tok >= CTOK_FIRSTDECL) { 111 tok >= CTOK_FIRSTDECL) {
124 if (cp->sb.n == 0) cp_save(cp, '$'); 112 if (sbufP(&cp->sb) == sbufB(&cp->sb)) cp_save(cp, '$');
125 cp_save(cp, '\0'); 113 cp_save(cp, '\0');
126 tokstr = cp->sb.buf; 114 tokstr = sbufB(&cp->sb);
127 } else { 115 } else {
128 tokstr = cp_tok2str(cp, tok); 116 tokstr = cp_tok2str(cp, tok);
129 } 117 }
@@ -163,7 +151,7 @@ static CPToken cp_number(CPState *cp)
163 TValue o; 151 TValue o;
164 do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp))); 152 do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp)));
165 cp_save(cp, '\0'); 153 cp_save(cp, '\0');
166 fmt = lj_strscan_scan((const uint8_t *)cp->sb.buf, &o, STRSCAN_OPT_C); 154 fmt = lj_strscan_scan((const uint8_t *)sbufB(&cp->sb), &o, STRSCAN_OPT_C);
167 if (fmt == STRSCAN_INT) cp->val.id = CTID_INT32; 155 if (fmt == STRSCAN_INT) cp->val.id = CTID_INT32;
168 else if (fmt == STRSCAN_U32) cp->val.id = CTID_UINT32; 156 else if (fmt == STRSCAN_U32) cp->val.id = CTID_UINT32;
169 else if (!(cp->mode & CPARSE_MODE_SKIP)) 157 else if (!(cp->mode & CPARSE_MODE_SKIP))
@@ -176,7 +164,7 @@ static CPToken cp_number(CPState *cp)
176static CPToken cp_ident(CPState *cp) 164static CPToken cp_ident(CPState *cp)
177{ 165{
178 do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp))); 166 do { cp_save(cp, cp->c); } while (lj_char_isident(cp_get(cp)));
179 cp->str = lj_str_new(cp->L, cp->sb.buf, cp->sb.n); 167 cp->str = lj_buf_str(cp->L, &cp->sb);
180 cp->val.id = lj_ctype_getname(cp->cts, &cp->ct, cp->str, cp->tmask); 168 cp->val.id = lj_ctype_getname(cp->cts, &cp->ct, cp->str, cp->tmask);
181 if (ctype_type(cp->ct->info) == CT_KW) 169 if (ctype_type(cp->ct->info) == CT_KW)
182 return ctype_cid(cp->ct->info); 170 return ctype_cid(cp->ct->info);
@@ -262,11 +250,11 @@ static CPToken cp_string(CPState *cp)
262 } 250 }
263 cp_get(cp); 251 cp_get(cp);
264 if (delim == '"') { 252 if (delim == '"') {
265 cp->str = lj_str_new(cp->L, cp->sb.buf, cp->sb.n); 253 cp->str = lj_buf_str(cp->L, &cp->sb);
266 return CTOK_STRING; 254 return CTOK_STRING;
267 } else { 255 } else {
268 if (cp->sb.n != 1) cp_err_token(cp, '\''); 256 if (sbuflen(&cp->sb) != 1) cp_err_token(cp, '\'');
269 cp->val.i32 = (int32_t)(char)cp->sb.buf[0]; 257 cp->val.i32 = (int32_t)(char)*sbufB(&cp->sb);
270 cp->val.id = CTID_INT32; 258 cp->val.id = CTID_INT32;
271 return CTOK_INTEGER; 259 return CTOK_INTEGER;
272 } 260 }
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 @@
9#include "lj_obj.h" 9#include "lj_obj.h"
10#include "lj_err.h" 10#include "lj_err.h"
11#include "lj_debug.h" 11#include "lj_debug.h"
12#include "lj_buf.h"
12#include "lj_str.h" 13#include "lj_str.h"
13#include "lj_tab.h" 14#include "lj_tab.h"
14#include "lj_state.h" 15#include "lj_state.h"
@@ -133,20 +134,6 @@ static BCLine debug_frameline(lua_State *L, GCfunc *fn, cTValue *nextframe)
133 134
134/* -- Variable names ------------------------------------------------------ */ 135/* -- Variable names ------------------------------------------------------ */
135 136
136/* Read ULEB128 value. */
137static uint32_t debug_read_uleb128(const uint8_t **pp)
138{
139 const uint8_t *p = *pp;
140 uint32_t v = *p++;
141 if (LJ_UNLIKELY(v >= 0x80)) {
142 int sh = 0;
143 v &= 0x7f;
144 do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80);
145 }
146 *pp = p;
147 return v;
148}
149
150/* Get name of a local variable from slot number and PC. */ 137/* Get name of a local variable from slot number and PC. */
151static const char *debug_varname(const GCproto *pt, BCPos pc, BCReg slot) 138static const char *debug_varname(const GCproto *pt, BCPos pc, BCReg slot)
152{ 139{
@@ -162,9 +149,9 @@ static const char *debug_varname(const GCproto *pt, BCPos pc, BCReg slot)
162 } else { 149 } else {
163 while (*p++) ; /* Skip over variable name string. */ 150 while (*p++) ; /* Skip over variable name string. */
164 } 151 }
165 lastpc = startpc = lastpc + debug_read_uleb128(&p); 152 lastpc = startpc = lastpc + lj_buf_ruleb128((const char **)&p);
166 if (startpc > pc) break; 153 if (startpc > pc) break;
167 endpc = startpc + debug_read_uleb128(&p); 154 endpc = startpc + lj_buf_ruleb128((const char **)&p);
168 if (pc < endpc && slot-- == 0) { 155 if (pc < endpc && slot-- == 0) {
169 if (vn < VARNAME__MAX) { 156 if (vn < VARNAME__MAX) {
170#define VARNAMESTR(name, str) str "\0" 157#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 @@
14#include "lj_err.h" 14#include "lj_err.h"
15#include "lj_debug.h" 15#include "lj_debug.h"
16#include "lj_frame.h" 16#include "lj_frame.h"
17#include "lj_buf.h"
17#include "lj_jit.h" 18#include "lj_jit.h"
18#include "lj_dispatch.h" 19#include "lj_dispatch.h"
19 20
@@ -426,16 +427,6 @@ static void gdbjit_catnum(GDBJITctx *ctx, uint32_t n)
426 *ctx->p++ = '0' + n; 427 *ctx->p++ = '0' + n;
427} 428}
428 429
429/* Add a ULEB128 value. */
430static void gdbjit_uleb128(GDBJITctx *ctx, uint32_t v)
431{
432 uint8_t *p = ctx->p;
433 for (; v >= 0x80; v >>= 7)
434 *p++ = (uint8_t)((v & 0x7f) | 0x80);
435 *p++ = (uint8_t)v;
436 ctx->p = p;
437}
438
439/* Add a SLEB128 value. */ 430/* Add a SLEB128 value. */
440static void gdbjit_sleb128(GDBJITctx *ctx, int32_t v) 431static void gdbjit_sleb128(GDBJITctx *ctx, int32_t v)
441{ 432{
@@ -452,7 +443,7 @@ static void gdbjit_sleb128(GDBJITctx *ctx, int32_t v)
452#define DU16(x) (*(uint16_t *)p = (x), p += 2) 443#define DU16(x) (*(uint16_t *)p = (x), p += 2)
453#define DU32(x) (*(uint32_t *)p = (x), p += 4) 444#define DU32(x) (*(uint32_t *)p = (x), p += 4)
454#define DADDR(x) (*(uintptr_t *)p = (x), p += sizeof(uintptr_t)) 445#define DADDR(x) (*(uintptr_t *)p = (x), p += sizeof(uintptr_t))
455#define DUV(x) (ctx->p = p, gdbjit_uleb128(ctx, (x)), p = ctx->p) 446#define DUV(x) (p = (uint8_t *)lj_buf_wuleb128((char *)p, (x)))
456#define DSV(x) (ctx->p = p, gdbjit_sleb128(ctx, (x)), p = ctx->p) 447#define DSV(x) (ctx->p = p, gdbjit_sleb128(ctx, (x)), p = ctx->p)
457#define DSTR(str) (ctx->p = p, gdbjit_strz(ctx, (str)), p = ctx->p) 448#define DSTR(str) (ctx->p = p, gdbjit_strz(ctx, (str)), p = ctx->p)
458#define DALIGNNOP(s) while ((uintptr_t)p & ((s)-1)) *p++ = DW_CFA_nop 449#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 @@
12#include "lj_obj.h" 12#include "lj_obj.h"
13#include "lj_gc.h" 13#include "lj_gc.h"
14#include "lj_err.h" 14#include "lj_err.h"
15#include "lj_buf.h"
15#include "lj_str.h" 16#include "lj_str.h"
16#if LJ_HASFFI 17#if LJ_HASFFI
17#include "lj_tab.h" 18#include "lj_tab.h"
@@ -54,20 +55,9 @@ static int fillbuf(LexState *ls)
54 return char2int(*(ls->p++)); 55 return char2int(*(ls->p++));
55} 56}
56 57
57static LJ_NOINLINE void save_grow(LexState *ls, int c)
58{
59 if (ls->sb.sz >= LJ_MAX_STR/2)
60 lj_lex_error(ls, 0, LJ_ERR_XELEM);
61 lj_buf_grow(ls->L, &ls->sb, 0);
62 ls->sb.buf[ls->sb.n++] = (char)c;
63}
64
65static LJ_AINLINE void save(LexState *ls, int c) 58static LJ_AINLINE void save(LexState *ls, int c)
66{ 59{
67 if (LJ_UNLIKELY(ls->sb.n + 1 > ls->sb.sz)) 60 lj_buf_putb(ls->L, &ls->sb, c);
68 save_grow(ls, c);
69 else
70 ls->sb.buf[ls->sb.n++] = (char)c;
71} 61}
72 62
73static void inclinenumber(LexState *ls) 63static void inclinenumber(LexState *ls)
@@ -99,7 +89,7 @@ static void lex_number(LexState *ls, TValue *tv)
99 save_and_next(ls); 89 save_and_next(ls);
100 } 90 }
101 save(ls, '\0'); 91 save(ls, '\0');
102 fmt = lj_strscan_scan((const uint8_t *)ls->sb.buf, tv, 92 fmt = lj_strscan_scan((const uint8_t *)sbufB(&ls->sb), tv,
103 (LJ_DUALNUM ? STRSCAN_OPT_TOINT : STRSCAN_OPT_TONUM) | 93 (LJ_DUALNUM ? STRSCAN_OPT_TOINT : STRSCAN_OPT_TONUM) |
104 (LJ_HASFFI ? (STRSCAN_OPT_LL|STRSCAN_OPT_IMAG) : 0)); 94 (LJ_HASFFI ? (STRSCAN_OPT_LL|STRSCAN_OPT_IMAG) : 0));
105 if (LJ_DUALNUM && fmt == STRSCAN_INT) { 95 if (LJ_DUALNUM && fmt == STRSCAN_INT) {
@@ -174,8 +164,8 @@ static void read_long_string(LexState *ls, TValue *tv, int sep)
174 } 164 }
175 } endloop: 165 } endloop:
176 if (tv) { 166 if (tv) {
177 GCstr *str = lj_parse_keepstr(ls, ls->sb.buf + (2 + (MSize)sep), 167 GCstr *str = lj_parse_keepstr(ls, sbufB(&ls->sb) + (2 + (MSize)sep),
178 ls->sb.n - 2*(2 + (MSize)sep)); 168 sbuflen(&ls->sb) - 2*(2 + (MSize)sep));
179 setstrV(ls->L, tv, str); 169 setstrV(ls->L, tv, str);
180 } 170 }
181} 171}
@@ -250,7 +240,8 @@ static void read_string(LexState *ls, int delim, TValue *tv)
250 } 240 }
251 } 241 }
252 save_and_next(ls); /* skip delimiter */ 242 save_and_next(ls); /* skip delimiter */
253 setstrV(ls->L, tv, lj_parse_keepstr(ls, ls->sb.buf + 1, ls->sb.n - 2)); 243 setstrV(ls->L, tv,
244 lj_parse_keepstr(ls, sbufB(&ls->sb)+1, sbuflen(&ls->sb)-2));
254} 245}
255 246
256/* -- Main lexical scanner ------------------------------------------------ */ 247/* -- Main lexical scanner ------------------------------------------------ */
@@ -269,7 +260,7 @@ static int llex(LexState *ls, TValue *tv)
269 do { 260 do {
270 save_and_next(ls); 261 save_and_next(ls);
271 } while (lj_char_isident(ls->current)); 262 } while (lj_char_isident(ls->current));
272 s = lj_parse_keepstr(ls, ls->sb.buf, ls->sb.n); 263 s = lj_parse_keepstr(ls, sbufB(&ls->sb), sbuflen(&ls->sb));
273 setstrV(ls->L, tv, s); 264 setstrV(ls->L, tv, s);
274 if (s->reserved > 0) /* Reserved word? */ 265 if (s->reserved > 0) /* Reserved word? */
275 return TK_OFS + s->reserved; 266 return TK_OFS + s->reserved;
@@ -457,7 +448,7 @@ void lj_lex_error(LexState *ls, LexToken token, ErrMsg em, ...)
457 tok = NULL; 448 tok = NULL;
458 } else if (token == TK_name || token == TK_string || token == TK_number) { 449 } else if (token == TK_name || token == TK_string || token == TK_number) {
459 save(ls, '\0'); 450 save(ls, '\0');
460 tok = ls->sb.buf; 451 tok = sbufB(&ls->sb);
461 } else { 452 } else {
462 tok = lj_lex_token2str(ls, token); 453 tok = lj_lex_token2str(ls, token);
463 } 454 }
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 @@
10 10
11#include "lj_obj.h" 11#include "lj_obj.h"
12#include "lj_err.h" 12#include "lj_err.h"
13#include "lj_buf.h"
14 13
15/* Lua lexer tokens. */ 14/* Lua lexer tokens. */
16#define TKDEF(_, __) \ 15#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);
121 121
122/* Resizable string buffer. Need this here, details in lj_buf.h. */ 122/* Resizable string buffer. Need this here, details in lj_buf.h. */
123typedef struct SBuf { 123typedef struct SBuf {
124 char *buf; /* String buffer base. */ 124 MRef p; /* String buffer pointer. */
125 MSize n; /* String buffer length. */ 125 MRef e; /* String buffer end pointer. */
126 MSize sz; /* String buffer size. */ 126 MRef b; /* String buffer base. */
127} SBuf; 127} SBuf;
128 128
129/* -- Tags and values ----------------------------------------------------- */ 129/* -- 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 @@
13#include "lj_gc.h" 13#include "lj_gc.h"
14#include "lj_err.h" 14#include "lj_err.h"
15#include "lj_debug.h" 15#include "lj_debug.h"
16#include "lj_buf.h"
16#include "lj_str.h" 17#include "lj_str.h"
17#include "lj_tab.h" 18#include "lj_tab.h"
18#include "lj_func.h" 19#include "lj_func.h"
@@ -1429,31 +1430,6 @@ static void fs_fixup_line(FuncState *fs, GCproto *pt,
1429 } 1430 }
1430} 1431}
1431 1432
1432static LJ_AINLINE void fs_buf_need(LexState *ls, MSize len)
1433{
1434 lj_buf_need(ls->L, &ls->sb, ls->sb.n + len);
1435}
1436
1437/* Add string to buffer. */
1438static void fs_buf_str(LexState *ls, const char *str, MSize len)
1439{
1440 char *p = ls->sb.buf + ls->sb.n;
1441 MSize i;
1442 ls->sb.n += len;
1443 for (i = 0; i < len; i++) p[i] = str[i];
1444}
1445
1446/* Add ULEB128 value to buffer. */
1447static void fs_buf_uleb128(LexState *ls, uint32_t v)
1448{
1449 MSize n = ls->sb.n;
1450 uint8_t *p = (uint8_t *)ls->sb.buf;
1451 for (; v >= 0x80; v >>= 7)
1452 p[n++] = (uint8_t)((v & 0x7f) | 0x80);
1453 p[n++] = (uint8_t)v;
1454 ls->sb.n = n;
1455}
1456
1457/* Prepare variable info for prototype. */ 1433/* Prepare variable info for prototype. */
1458static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar) 1434static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar)
1459{ 1435{
@@ -1465,33 +1441,35 @@ static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar)
1465 for (i = 0, n = fs->nuv; i < n; i++) { 1441 for (i = 0, n = fs->nuv; i < n; i++) {
1466 GCstr *s = strref(vs[fs->uvmap[i]].name); 1442 GCstr *s = strref(vs[fs->uvmap[i]].name);
1467 MSize len = s->len+1; 1443 MSize len = s->len+1;
1468 fs_buf_need(ls, len); 1444 char *p = lj_buf_more(ls->L, &ls->sb, len);
1469 fs_buf_str(ls, strdata(s), len); 1445 p = lj_buf_wmem(p, strdata(s), len);
1446 setsbufP(&ls->sb, p);
1470 } 1447 }
1471 *ofsvar = ls->sb.n; 1448 *ofsvar = sbuflen(&ls->sb);
1472 lastpc = 0; 1449 lastpc = 0;
1473 /* Store local variable names and compressed ranges. */ 1450 /* Store local variable names and compressed ranges. */
1474 for (ve = vs + ls->vtop, vs += fs->vbase; vs < ve; vs++) { 1451 for (ve = vs + ls->vtop, vs += fs->vbase; vs < ve; vs++) {
1475 if (!gola_isgotolabel(vs)) { 1452 if (!gola_isgotolabel(vs)) {
1476 GCstr *s = strref(vs->name); 1453 GCstr *s = strref(vs->name);
1477 BCPos startpc; 1454 BCPos startpc;
1455 char *p;
1478 if ((uintptr_t)s < VARNAME__MAX) { 1456 if ((uintptr_t)s < VARNAME__MAX) {
1479 fs_buf_need(ls, 1 + 2*5); 1457 p = lj_buf_more(ls->L, &ls->sb, 1 + 2*5);
1480 ls->sb.buf[ls->sb.n++] = (uint8_t)(uintptr_t)s; 1458 *p++ = (char)(uintptr_t)s;
1481 } else { 1459 } else {
1482 MSize len = s->len+1; 1460 MSize len = s->len+1;
1483 fs_buf_need(ls, len + 2*5); 1461 p = lj_buf_more(ls->L, &ls->sb, len + 2*5);
1484 fs_buf_str(ls, strdata(s), len); 1462 p = lj_buf_wmem(p, strdata(s), len);
1485 } 1463 }
1486 startpc = vs->startpc; 1464 startpc = vs->startpc;
1487 fs_buf_uleb128(ls, startpc-lastpc); 1465 p = lj_buf_wuleb128(p, startpc-lastpc);
1488 fs_buf_uleb128(ls, vs->endpc-startpc); 1466 p = lj_buf_wuleb128(p, vs->endpc-startpc);
1467 setsbufP(&ls->sb, p);
1489 lastpc = startpc; 1468 lastpc = startpc;
1490 } 1469 }
1491 } 1470 }
1492 fs_buf_need(ls, 1); 1471 lj_buf_putb(ls->L, &ls->sb, '\0'); /* Terminator for varinfo. */
1493 ls->sb.buf[ls->sb.n++] = '\0'; /* Terminator for varinfo. */ 1472 return sbuflen(&ls->sb);
1494 return ls->sb.n;
1495} 1473}
1496 1474
1497/* Fixup variable info for prototype. */ 1475/* Fixup variable info for prototype. */
@@ -1499,7 +1477,7 @@ static void fs_fixup_var(LexState *ls, GCproto *pt, uint8_t *p, size_t ofsvar)
1499{ 1477{
1500 setmref(pt->uvinfo, p); 1478 setmref(pt->uvinfo, p);
1501 setmref(pt->varinfo, (char *)p + ofsvar); 1479 setmref(pt->varinfo, (char *)p + ofsvar);
1502 memcpy(p, ls->sb.buf, ls->sb.n); /* Copy from temp. string buffer. */ 1480 memcpy(p, sbufB(&ls->sb), sbuflen(&ls->sb)); /* Copy from temp. buffer. */
1503} 1481}
1504#else 1482#else
1505 1483
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)
218 218
219/* -- String formatting --------------------------------------------------- */ 219/* -- String formatting --------------------------------------------------- */
220 220
221static void addstr(lua_State *L, SBuf *sb, const char *str, MSize len)
222{
223 MSize i;
224 char *p = lj_buf_need(L, sb, sb->n+len) + sb->n;
225 sb->n += len;
226 for (i = 0; i < len; i++) p[i] = str[i];
227}
228
229static void addchar(lua_State *L, SBuf *sb, int c)
230{
231 char *p = lj_buf_need(L, sb, sb->n+1);
232 p[sb->n++] = (char)c;
233}
234
235/* Push formatted message as a string object to Lua stack. va_list variant. */ 221/* Push formatted message as a string object to Lua stack. va_list variant. */
236const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp) 222const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp)
237{ 223{
@@ -241,22 +227,22 @@ const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp)
241 for (;;) { 227 for (;;) {
242 const char *e = strchr(fmt, '%'); 228 const char *e = strchr(fmt, '%');
243 if (e == NULL) break; 229 if (e == NULL) break;
244 addstr(L, sb, fmt, (MSize)(e-fmt)); 230 lj_buf_putmem(L, sb, fmt, (MSize)(e-fmt));
245 /* This function only handles %s, %c, %d, %f and %p formats. */ 231 /* This function only handles %s, %c, %d, %f and %p formats. */
246 switch (e[1]) { 232 switch (e[1]) {
247 case 's': { 233 case 's': {
248 const char *s = va_arg(argp, char *); 234 const char *s = va_arg(argp, char *);
249 if (s == NULL) s = "(null)"; 235 if (s == NULL) s = "(null)";
250 addstr(L, sb, s, (MSize)strlen(s)); 236 lj_buf_putmem(L, sb, s, (MSize)strlen(s));
251 break; 237 break;
252 } 238 }
253 case 'c': 239 case 'c':
254 addchar(L, sb, va_arg(argp, int)); 240 lj_buf_putb(L, sb, va_arg(argp, int));
255 break; 241 break;
256 case 'd': { 242 case 'd': {
257 char buf[LJ_STR_INTBUF]; 243 char buf[LJ_STR_INTBUF];
258 char *p = lj_str_bufint(buf, va_arg(argp, int32_t)); 244 char *p = lj_str_bufint(buf, va_arg(argp, int32_t));
259 addstr(L, sb, p, (MSize)(buf+LJ_STR_INTBUF-p)); 245 lj_buf_putmem(L, sb, p, (MSize)(buf+LJ_STR_INTBUF-p));
260 break; 246 break;
261 } 247 }
262 case 'f': { 248 case 'f': {
@@ -265,7 +251,7 @@ const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp)
265 MSize len; 251 MSize len;
266 tv.n = (lua_Number)(va_arg(argp, LUAI_UACNUMBER)); 252 tv.n = (lua_Number)(va_arg(argp, LUAI_UACNUMBER));
267 len = (MSize)lj_str_bufnum(buf, &tv); 253 len = (MSize)lj_str_bufnum(buf, &tv);
268 addstr(L, sb, buf, len); 254 lj_buf_putmem(L, sb, buf, len);
269 break; 255 break;
270 } 256 }
271 case 'p': { 257 case 'p': {
@@ -274,7 +260,7 @@ const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp)
274 ptrdiff_t p = (ptrdiff_t)(va_arg(argp, void *)); 260 ptrdiff_t p = (ptrdiff_t)(va_arg(argp, void *));
275 ptrdiff_t i, lasti = 2+FMTP_CHARS; 261 ptrdiff_t i, lasti = 2+FMTP_CHARS;
276 if (p == 0) { 262 if (p == 0) {
277 addstr(L, sb, "NULL", 4); 263 lj_buf_putmem(L, sb, "NULL", 4);
278 break; 264 break;
279 } 265 }
280#if LJ_64 266#if LJ_64
@@ -285,21 +271,21 @@ const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp)
285 buf[1] = 'x'; 271 buf[1] = 'x';
286 for (i = lasti-1; i >= 2; i--, p >>= 4) 272 for (i = lasti-1; i >= 2; i--, p >>= 4)
287 buf[i] = "0123456789abcdef"[(p & 15)]; 273 buf[i] = "0123456789abcdef"[(p & 15)];
288 addstr(L, sb, buf, (MSize)lasti); 274 lj_buf_putmem(L, sb, buf, (MSize)lasti);
289 break; 275 break;
290 } 276 }
291 case '%': 277 case '%':
292 addchar(L, sb, '%'); 278 lj_buf_putb(L, sb, '%');
293 break; 279 break;
294 default: 280 default:
295 addchar(L, sb, '%'); 281 lj_buf_putb(L, sb, '%');
296 addchar(L, sb, e[1]); 282 lj_buf_putb(L, sb, e[1]);
297 break; 283 break;
298 } 284 }
299 fmt = e+2; 285 fmt = e+2;
300 } 286 }
301 addstr(L, sb, fmt, (MSize)strlen(fmt)); 287 lj_buf_putmem(L, sb, fmt, (MSize)strlen(fmt));
302 setstrV(L, L->top, lj_str_new(L, sb->buf, sb->n)); 288 setstrV(L, L->top, lj_buf_str(L, sb));
303 incr_top(L); 289 incr_top(L);
304 return strVdata(L->top - 1); 290 return strVdata(L->top - 1);
305} 291}
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)
1801 | cmp CARG2, #1 1801 | cmp CARG2, #1
1802 | blo ->fff_emptystr // Zero-length string? 1802 | blo ->fff_emptystr // Zero-length string?
1803 | bne ->fff_fallback // Fallback for > 1-char strings. 1803 | bne ->fff_fallback // Fallback for > 1-char strings.
1804 | ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.sz)] 1804 | ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.b)]
1805 | ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.buf)] 1805 | ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.e)]
1806 | ldr CARG1, STR:CARG1[1] 1806 | ldr CARG1, STR:CARG1[1]
1807 | cmp RB, CARG3 1807 | add INS, CARG2, CARG3
1808 | cmp RB, INS
1808 | blo ->fff_fallback 1809 | blo ->fff_fallback
1809 |1: // Fill buffer with char. 1810 |1: // Fill buffer with char.
1810 | strb CARG1, [CARG2, CARG4] 1811 | strb CARG1, [CARG2, CARG4]
@@ -1819,11 +1820,12 @@ static void build_subroutines(BuildCtx *ctx)
1819 | blo ->fff_fallback 1820 | blo ->fff_fallback
1820 | checkstr CARG2, ->fff_fallback 1821 | checkstr CARG2, ->fff_fallback
1821 | ldr CARG3, STR:CARG1->len 1822 | ldr CARG3, STR:CARG1->len
1822 | ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.sz)] 1823 | ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.b)]
1823 | ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.buf)] 1824 | ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.e)]
1824 | mov CARG4, CARG3 1825 | mov CARG4, CARG3
1825 | add CARG1, STR:CARG1, #sizeof(GCstr) 1826 | add CARG1, STR:CARG1, #sizeof(GCstr)
1826 | cmp RB, CARG3 1827 | add INS, CARG2, CARG3
1828 | cmp RB, INS
1827 | blo ->fff_fallback 1829 | blo ->fff_fallback
1828 |1: // Reverse string copy. 1830 |1: // Reverse string copy.
1829 | ldrb RB, [CARG1], #1 1831 | ldrb RB, [CARG1], #1
@@ -1840,11 +1842,12 @@ static void build_subroutines(BuildCtx *ctx)
1840 | blo ->fff_fallback 1842 | blo ->fff_fallback
1841 | checkstr CARG2, ->fff_fallback 1843 | checkstr CARG2, ->fff_fallback
1842 | ldr CARG3, STR:CARG1->len 1844 | ldr CARG3, STR:CARG1->len
1843 | ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.sz)] 1845 | ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.b)]
1844 | ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.buf)] 1846 | ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.e)]
1845 | mov CARG4, #0 1847 | mov CARG4, #0
1846 | add CARG1, STR:CARG1, #sizeof(GCstr) 1848 | add CARG1, STR:CARG1, #sizeof(GCstr)
1847 | cmp RB, CARG3 1849 | add INS, CARG2, CARG3
1850 | cmp RB, INS
1848 | blo ->fff_fallback 1851 | blo ->fff_fallback
1849 |1: // ASCII case conversion. 1852 |1: // ASCII case conversion.
1850 | ldrb RB, [CARG1, CARG4] 1853 | 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)
1736 | beqz AT, ->fff_fallback 1736 | beqz AT, ->fff_fallback
1737 |. lw TMP0, STR:CARG1->len 1737 |. lw TMP0, STR:CARG1->len
1738 | mfc1 CARG3, f0 1738 | mfc1 CARG3, f0
1739 | lw TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) 1739 | lw CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH)
1740 | lw TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH)
1740 | li AT, 1 1741 | li AT, 1
1741 | blez CARG3, ->fff_emptystr // Count <= 0? 1742 | blez CARG3, ->fff_emptystr // Count <= 0?
1742 |. sltu AT, AT, TMP0 1743 |. sltu AT, AT, TMP0
1743 | beqz TMP0, ->fff_emptystr // Zero length string? 1744 | beqz TMP0, ->fff_emptystr // Zero length string?
1744 |. sltu TMP0, TMP1, CARG3 1745 |. addu TMP3, CARG2, CARG3
1746 | sltu TMP0, TMP1, TMP3
1745 | or AT, AT, TMP0 1747 | or AT, AT, TMP0
1746 | lw CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH)
1747 | bnez AT, ->fff_fallback // Fallback for > 1-char strings. 1748 | bnez AT, ->fff_fallback // Fallback for > 1-char strings.
1748 |. lbu TMP0, STR:CARG1[1] 1749 |. lbu TMP0, STR:CARG1[1]
1749 | addu TMP2, CARG2, CARG3 1750 | addu TMP2, CARG2, CARG3
@@ -1762,14 +1763,14 @@ static void build_subroutines(BuildCtx *ctx)
1762 | beqz NARGS8:RC, ->fff_fallback 1763 | beqz NARGS8:RC, ->fff_fallback
1763 |. li AT, LJ_TSTR 1764 |. li AT, LJ_TSTR
1764 | bne CARG3, AT, ->fff_fallback 1765 | bne CARG3, AT, ->fff_fallback
1765 |. lw TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) 1766 |. lw CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH)
1766 | lw CARG3, STR:CARG1->len 1767 | lw CARG3, STR:CARG1->len
1768 | lw TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH)
1767 | addiu CARG1, STR:CARG1, #STR 1769 | addiu CARG1, STR:CARG1, #STR
1768 | lw CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) 1770 | addu CARG4, CARG2, CARG3
1769 | sltu AT, TMP1, CARG3 1771 | sltu AT, TMP1, CARG4
1770 | bnez AT, ->fff_fallback 1772 | bnez AT, ->fff_fallback
1771 |. addu TMP3, CARG1, CARG3 1773 |. addu TMP3, CARG1, CARG3
1772 | addu CARG4, CARG2, CARG3
1773 |1: // Reverse string copy. 1774 |1: // Reverse string copy.
1774 | lbu TMP1, 0(CARG1) 1775 | lbu TMP1, 0(CARG1)
1775 | sltu AT, CARG1, TMP3 1776 | sltu AT, CARG1, TMP3
@@ -1787,11 +1788,12 @@ static void build_subroutines(BuildCtx *ctx)
1787 | beqz NARGS8:RC, ->fff_fallback 1788 | beqz NARGS8:RC, ->fff_fallback
1788 |. li AT, LJ_TSTR 1789 |. li AT, LJ_TSTR
1789 | bne CARG3, AT, ->fff_fallback 1790 | bne CARG3, AT, ->fff_fallback
1790 |. lw TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) 1791 |. lw CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH)
1791 | lw CARG3, STR:CARG1->len 1792 | lw CARG3, STR:CARG1->len
1793 | lw TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH)
1792 | addiu CARG1, STR:CARG1, #STR 1794 | addiu CARG1, STR:CARG1, #STR
1793 | lw CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH) 1795 | addu TMP3, CARG2, CARG3
1794 | sltu AT, TMP1, CARG3 1796 | sltu AT, TMP1, TMP3
1795 | bnez AT, ->fff_fallback 1797 | bnez AT, ->fff_fallback
1796 |. addu TMP3, CARG1, CARG3 1798 |. addu TMP3, CARG1, CARG3
1797 | move CARG4, CARG2 1799 | 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)
2201 |.endif 2201 |.endif
2202 | lwz TMP0, STR:CARG1->len 2202 | lwz TMP0, STR:CARG1->len
2203 | cmpwi CARG3, 0 2203 | cmpwi CARG3, 0
2204 | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) 2204 | lwz TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH)
2205 | lwz CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH)
2205 | ble >2 // Count <= 0? (or non-int) 2206 | ble >2 // Count <= 0? (or non-int)
2206 | cmplwi TMP0, 1 2207 | cmplwi TMP0, 1
2208 | add TMP3, CARG2, CARG3
2207 | subi TMP2, CARG3, 1 2209 | subi TMP2, CARG3, 1
2208 | blt >2 // Zero length string? 2210 | blt >2 // Zero length string?
2209 | cmplw cr1, TMP1, CARG3 2211 | cmplw cr1, TMP1, TMP3
2210 | bne ->fff_fallback // Fallback for > 1-char strings. 2212 | bne ->fff_fallback // Fallback for > 1-char strings.
2211 | lbz TMP0, STR:CARG1[1] 2213 | lbz TMP0, STR:CARG1[1]
2212 | lp CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH)
2213 | blt cr1, ->fff_fallback 2214 | blt cr1, ->fff_fallback
2214 |1: // Fill buffer with char. Yes, this is suboptimal code (do you care?). 2215 |1: // Fill buffer with char. Yes, this is suboptimal code (do you care?).
2215 | cmplwi TMP2, 0 2216 | cmplwi TMP2, 0
@@ -2229,13 +2230,14 @@ static void build_subroutines(BuildCtx *ctx)
2229 | lwz STR:CARG1, 4(BASE) 2230 | lwz STR:CARG1, 4(BASE)
2230 | blt ->fff_fallback 2231 | blt ->fff_fallback
2231 | checkstr CARG3 2232 | checkstr CARG3
2232 | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) 2233 | lwz CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH)
2234 | lwz TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH)
2233 | bne ->fff_fallback 2235 | bne ->fff_fallback
2234 | lwz CARG3, STR:CARG1->len 2236 | lwz CARG3, STR:CARG1->len
2235 | la CARG1, #STR(STR:CARG1) 2237 | la CARG1, #STR(STR:CARG1)
2236 | lp CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH)
2237 | li TMP2, 0 2238 | li TMP2, 0
2238 | cmplw TMP1, CARG3 2239 | add TMP3, CARG2, CARG3
2240 | cmplw TMP1, TMP3
2239 | subi TMP3, CARG3, 1 2241 | subi TMP3, CARG3, 1
2240 | blt ->fff_fallback 2242 | blt ->fff_fallback
2241 |1: // Reverse string copy. 2243 |1: // Reverse string copy.
@@ -2255,13 +2257,14 @@ static void build_subroutines(BuildCtx *ctx)
2255 | lwz STR:CARG1, 4(BASE) 2257 | lwz STR:CARG1, 4(BASE)
2256 | blt ->fff_fallback 2258 | blt ->fff_fallback
2257 | checkstr CARG3 2259 | checkstr CARG3
2258 | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH) 2260 | lwz CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH)
2261 | lwz TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH)
2259 | bne ->fff_fallback 2262 | bne ->fff_fallback
2260 | lwz CARG3, STR:CARG1->len 2263 | lwz CARG3, STR:CARG1->len
2261 | la CARG1, #STR(STR:CARG1) 2264 | la CARG1, #STR(STR:CARG1)
2262 | lp CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH)
2263 | cmplw TMP1, CARG3
2264 | li TMP2, 0 2265 | li TMP2, 0
2266 | add TMP3, CARG2, CARG3
2267 | cmplw TMP1, TMP3
2265 | blt ->fff_fallback 2268 | blt ->fff_fallback
2266 |1: // ASCII case conversion. 2269 |1: // ASCII case conversion.
2267 | cmplw TMP2, CARG3 2270 | 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)
2356 | cmp dword STR:RB->len, 1 2356 | cmp dword STR:RB->len, 1
2357 | jb ->fff_emptystr // Zero length string? 2357 | jb ->fff_emptystr // Zero length string?
2358 | jne ->fff_fallback_2 // Fallback for > 1-char strings. 2358 | jne ->fff_fallback_2 // Fallback for > 1-char strings.
2359 | cmp [DISPATCH+DISPATCH_GL(tmpbuf.sz)], RC; jb ->fff_fallback_2
2360 | movzx RA, byte STR:RB[1] 2359 | movzx RA, byte STR:RB[1]
2361 | mov RB, [DISPATCH+DISPATCH_GL(tmpbuf.buf)] 2360 | mov RB, [DISPATCH+DISPATCH_GL(tmpbuf.b)]
2361 | add RB, RC
2362 | cmp [DISPATCH+DISPATCH_GL(tmpbuf.e)], RB; jb ->fff_fallback_2
2362 |.if X64 2363 |.if X64
2363 | mov TMP3, RC 2364 | mov TMP3, RC
2364 |.else 2365 |.else
2365 | mov ARG3, RC 2366 | mov ARG3, RC
2366 |.endif 2367 |.endif
2367 |1: // Fill buffer with char. Yes, this is suboptimal code (do you care?). 2368 |1: // Fill buffer with char.
2368 | mov [RB], RAL 2369 | sub RB, 1
2369 | add RB, 1
2370 | sub RC, 1 2370 | sub RC, 1
2371 | mov [RB], RAL
2371 | jnz <1 2372 | jnz <1
2372 | mov RD, [DISPATCH+DISPATCH_GL(tmpbuf.buf)] 2373 | mov RD, [DISPATCH+DISPATCH_GL(tmpbuf.b)]
2373 | jmp ->fff_newstr 2374 | jmp ->fff_newstr
2374 | 2375 |
2375 |.ffunc_1 string_reverse 2376 |.ffunc_1 string_reverse
@@ -2379,15 +2380,16 @@ static void build_subroutines(BuildCtx *ctx)
2379 | mov RC, STR:RB->len 2380 | mov RC, STR:RB->len
2380 | test RC, RC 2381 | test RC, RC
2381 | jz ->fff_emptystr // Zero length string? 2382 | jz ->fff_emptystr // Zero length string?
2382 | cmp [DISPATCH+DISPATCH_GL(tmpbuf.sz)], RC; jb ->fff_fallback_1
2383 | add RB, #STR
2384 | mov TMP2, PC // Need another temp register. 2383 | mov TMP2, PC // Need another temp register.
2384 | mov PC, [DISPATCH+DISPATCH_GL(tmpbuf.b)]
2385 | lea RA, [PC+RC]
2386 | cmp [DISPATCH+DISPATCH_GL(tmpbuf.e)], RA; jb ->fff_fallback_1
2387 | add RB, #STR
2385 |.if X64 2388 |.if X64
2386 | mov TMP3, RC 2389 | mov TMP3, RC
2387 |.else 2390 |.else
2388 | mov ARG3, RC 2391 | mov ARG3, RC
2389 |.endif 2392 |.endif
2390 | mov PC, [DISPATCH+DISPATCH_GL(tmpbuf.buf)]
2391 |1: 2393 |1:
2392 | movzx RA, byte [RB] 2394 | movzx RA, byte [RB]
2393 | add RB, 1 2395 | add RB, 1
@@ -2402,17 +2404,18 @@ static void build_subroutines(BuildCtx *ctx)
2402 | .ffunc_1 name 2404 | .ffunc_1 name
2403 | ffgccheck 2405 | ffgccheck
2404 | cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback 2406 | cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback
2407 | mov TMP2, PC // Need another temp register.
2405 | mov STR:RB, [BASE] 2408 | mov STR:RB, [BASE]
2406 | mov RC, STR:RB->len 2409 | mov RC, STR:RB->len
2407 | cmp [DISPATCH+DISPATCH_GL(tmpbuf.sz)], RC; jb ->fff_fallback_1 2410 | mov PC, [DISPATCH+DISPATCH_GL(tmpbuf.b)]
2411 | lea RA, [PC+RC]
2412 | cmp [DISPATCH+DISPATCH_GL(tmpbuf.e)], RA; jb ->fff_fallback_1
2408 | add RB, #STR 2413 | add RB, #STR
2409 | mov TMP2, PC // Need another temp register.
2410 |.if X64 2414 |.if X64
2411 | mov TMP3, RC 2415 | mov TMP3, RC
2412 |.else 2416 |.else
2413 | mov ARG3, RC 2417 | mov ARG3, RC
2414 |.endif 2418 |.endif
2415 | mov PC, [DISPATCH+DISPATCH_GL(tmpbuf.buf)]
2416 | jmp >3 2419 | jmp >3
2417 |1: // ASCII case conversion. Yes, this is suboptimal code (do you care?). 2420 |1: // ASCII case conversion. Yes, this is suboptimal code (do you care?).
2418 | movzx RA, byte [RB+RC] 2421 | movzx RA, byte [RB+RC]