diff options
| -rw-r--r-- | src/Makefile.dep | 12 | ||||
| -rw-r--r-- | src/host/buildvm_lib.c | 2 | ||||
| -rw-r--r-- | src/lib_buffer.c | 52 | ||||
| -rw-r--r-- | src/lj_buf.c | 36 | ||||
| -rw-r--r-- | src/lj_buf.h | 12 | ||||
| -rw-r--r-- | src/lj_crecord.c | 17 | ||||
| -rw-r--r-- | src/lj_crecord.h | 4 | ||||
| -rw-r--r-- | src/lj_err.c | 36 | ||||
| -rw-r--r-- | src/lj_ffrecord.c | 345 | ||||
| -rw-r--r-- | src/lj_ir.c | 1 | ||||
| -rw-r--r-- | src/lj_ir.h | 9 | ||||
| -rw-r--r-- | src/lj_ircall.h | 18 | ||||
| -rw-r--r-- | src/lj_iropt.h | 1 | ||||
| -rw-r--r-- | src/lj_opt_fold.c | 57 | ||||
| -rw-r--r-- | src/lj_opt_mem.c | 28 | ||||
| -rw-r--r-- | src/lj_record.c | 10 | ||||
| -rw-r--r-- | src/lj_serialize.c | 65 | ||||
| -rw-r--r-- | src/lj_serialize.h | 7 |
18 files changed, 625 insertions, 87 deletions
diff --git a/src/Makefile.dep b/src/Makefile.dep index dd74c677..1ad6701a 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep | |||
| @@ -114,10 +114,10 @@ lj_err.o: lj_err.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_err.h \ | |||
| 114 | lj_ff.h lj_ffdef.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \ | 114 | lj_ff.h lj_ffdef.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \ |
| 115 | lj_traceerr.h lj_vm.h lj_strfmt.h | 115 | lj_traceerr.h lj_vm.h lj_strfmt.h |
| 116 | lj_ffrecord.o: lj_ffrecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 116 | lj_ffrecord.o: lj_ffrecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
| 117 | lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ff.h \ | 117 | lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_tab.h lj_frame.h \ |
| 118 | lj_ffdef.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \ | 118 | lj_bc.h lj_ff.h lj_ffdef.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \ |
| 119 | lj_dispatch.h lj_traceerr.h lj_record.h lj_ffrecord.h lj_crecord.h \ | 119 | lj_trace.h lj_dispatch.h lj_traceerr.h lj_record.h lj_ffrecord.h \ |
| 120 | lj_vm.h lj_strscan.h lj_strfmt.h lj_recdef.h | 120 | lj_crecord.h lj_vm.h lj_strscan.h lj_strfmt.h lj_serialize.h lj_recdef.h |
| 121 | lj_func.o: lj_func.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 121 | lj_func.o: lj_func.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
| 122 | lj_func.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h \ | 122 | lj_func.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h \ |
| 123 | lj_traceerr.h lj_vm.h | 123 | lj_traceerr.h lj_vm.h |
| @@ -131,7 +131,7 @@ lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | |||
| 131 | lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 131 | lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
| 132 | lj_buf.h lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \ | 132 | lj_buf.h lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \ |
| 133 | lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h \ | 133 | lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h \ |
| 134 | lj_carith.h lj_vm.h lj_strscan.h lj_strfmt.h lj_prng.h | 134 | lj_carith.h lj_vm.h lj_strscan.h lj_serialize.h lj_strfmt.h lj_prng.h |
| 135 | lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 135 | lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
| 136 | lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h \ | 136 | lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h \ |
| 137 | lualib.h lj_state.h lj_lex.h lj_parse.h lj_char.h lj_strscan.h \ | 137 | lualib.h lj_state.h lj_lex.h lj_parse.h lj_char.h lj_strscan.h \ |
| @@ -185,7 +185,7 @@ lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | |||
| 185 | lj_record.h lj_ffrecord.h lj_snap.h lj_vm.h lj_prng.h | 185 | lj_record.h lj_ffrecord.h lj_snap.h lj_vm.h lj_prng.h |
| 186 | lj_serialize.o: lj_serialize.c lj_obj.h lua.h luaconf.h lj_def.h \ | 186 | lj_serialize.o: lj_serialize.c lj_obj.h lua.h luaconf.h lj_def.h \ |
| 187 | lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_tab.h \ | 187 | lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_tab.h \ |
| 188 | lj_udata.h lj_ctype.h lj_cdata.h lj_serialize.h | 188 | lj_udata.h lj_ctype.h lj_cdata.h lj_ir.h lj_serialize.h |
| 189 | lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 189 | lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
| 190 | lj_tab.h lj_state.h lj_frame.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h \ | 190 | lj_tab.h lj_state.h lj_frame.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h \ |
| 191 | lj_trace.h lj_dispatch.h lj_traceerr.h lj_snap.h lj_target.h \ | 191 | lj_trace.h lj_dispatch.h lj_traceerr.h lj_snap.h lj_target.h \ |
diff --git a/src/host/buildvm_lib.c b/src/host/buildvm_lib.c index 17e0111c..20bb77cd 100644 --- a/src/host/buildvm_lib.c +++ b/src/host/buildvm_lib.c | |||
| @@ -385,6 +385,8 @@ void emit_lib(BuildCtx *ctx) | |||
| 385 | ok = LJ_HASJIT; | 385 | ok = LJ_HASJIT; |
| 386 | else if (!strcmp(buf, "#if LJ_HASFFI\n")) | 386 | else if (!strcmp(buf, "#if LJ_HASFFI\n")) |
| 387 | ok = LJ_HASFFI; | 387 | ok = LJ_HASFFI; |
| 388 | else if (!strcmp(buf, "#if LJ_HASBUFFER\n")) | ||
| 389 | ok = LJ_HASBUFFER; | ||
| 388 | if (!ok) { | 390 | if (!ok) { |
| 389 | int lvl = 1; | 391 | int lvl = 1; |
| 390 | while (fgets(buf, sizeof(buf), fp) != NULL) { | 392 | while (fgets(buf, sizeof(buf), fp) != NULL) { |
diff --git a/src/lib_buffer.c b/src/lib_buffer.c index cb7531a2..ae065759 100644 --- a/src/lib_buffer.c +++ b/src/lib_buffer.c | |||
| @@ -61,7 +61,7 @@ LJLIB_CF(buffer_method_free) | |||
| 61 | return 1; | 61 | return 1; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | LJLIB_CF(buffer_method_reset) | 64 | LJLIB_CF(buffer_method_reset) LJLIB_REC(.) |
| 65 | { | 65 | { |
| 66 | SBufExt *sbx = buffer_tobuf(L); | 66 | SBufExt *sbx = buffer_tobuf(L); |
| 67 | lj_bufx_reset(sbx); | 67 | lj_bufx_reset(sbx); |
| @@ -69,7 +69,7 @@ LJLIB_CF(buffer_method_reset) | |||
| 69 | return 1; | 69 | return 1; |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | LJLIB_CF(buffer_method_skip) | 72 | LJLIB_CF(buffer_method_skip) LJLIB_REC(.) |
| 73 | { | 73 | { |
| 74 | SBufExt *sbx = buffer_tobuf(L); | 74 | SBufExt *sbx = buffer_tobuf(L); |
| 75 | MSize n = (MSize)lj_lib_checkintrange(L, 2, 0, LJ_MAX_BUF); | 75 | MSize n = (MSize)lj_lib_checkintrange(L, 2, 0, LJ_MAX_BUF); |
| @@ -83,7 +83,7 @@ LJLIB_CF(buffer_method_skip) | |||
| 83 | return 1; | 83 | return 1; |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | LJLIB_CF(buffer_method_set) | 86 | LJLIB_CF(buffer_method_set) LJLIB_REC(.) |
| 87 | { | 87 | { |
| 88 | SBufExt *sbx = buffer_tobuf(L); | 88 | SBufExt *sbx = buffer_tobuf(L); |
| 89 | GCobj *ref; | 89 | GCobj *ref; |
| @@ -111,7 +111,7 @@ LJLIB_CF(buffer_method_set) | |||
| 111 | return 1; | 111 | return 1; |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | LJLIB_CF(buffer_method_put) | 114 | LJLIB_CF(buffer_method_put) LJLIB_REC(.) |
| 115 | { | 115 | { |
| 116 | SBufExt *sbx = buffer_tobufw(L); | 116 | SBufExt *sbx = buffer_tobufw(L); |
| 117 | ptrdiff_t arg, narg = L->top - L->base; | 117 | ptrdiff_t arg, narg = L->top - L->base; |
| @@ -147,7 +147,7 @@ LJLIB_CF(buffer_method_put) | |||
| 147 | return 1; | 147 | return 1; |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | LJLIB_CF(buffer_method_putf) | 150 | LJLIB_CF(buffer_method_putf) LJLIB_REC(.) |
| 151 | { | 151 | { |
| 152 | SBufExt *sbx = buffer_tobufw(L); | 152 | SBufExt *sbx = buffer_tobufw(L); |
| 153 | lj_strfmt_putarg(L, (SBuf *)sbx, 2, 2); | 153 | lj_strfmt_putarg(L, (SBuf *)sbx, 2, 2); |
| @@ -156,7 +156,7 @@ LJLIB_CF(buffer_method_putf) | |||
| 156 | return 1; | 156 | return 1; |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | LJLIB_CF(buffer_method_get) | 159 | LJLIB_CF(buffer_method_get) LJLIB_REC(.) |
| 160 | { | 160 | { |
| 161 | SBufExt *sbx = buffer_tobuf(L); | 161 | SBufExt *sbx = buffer_tobuf(L); |
| 162 | ptrdiff_t arg, narg = L->top - L->base; | 162 | ptrdiff_t arg, narg = L->top - L->base; |
| @@ -179,7 +179,7 @@ LJLIB_CF(buffer_method_get) | |||
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | #if LJ_HASFFI | 181 | #if LJ_HASFFI |
| 182 | LJLIB_CF(buffer_method_putcdata) | 182 | LJLIB_CF(buffer_method_putcdata) LJLIB_REC(.) |
| 183 | { | 183 | { |
| 184 | SBufExt *sbx = buffer_tobufw(L); | 184 | SBufExt *sbx = buffer_tobufw(L); |
| 185 | const char *p; | 185 | const char *p; |
| @@ -197,12 +197,12 @@ LJLIB_CF(buffer_method_putcdata) | |||
| 197 | return 1; | 197 | return 1; |
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | LJLIB_CF(buffer_method_reserve) | 200 | LJLIB_CF(buffer_method_reserve) LJLIB_REC(.) |
| 201 | { | 201 | { |
| 202 | SBufExt *sbx = buffer_tobufw(L); | 202 | SBufExt *sbx = buffer_tobufw(L); |
| 203 | MSize len = (MSize)lj_lib_checkintrange(L, 2, 0, LJ_MAX_BUF); | 203 | MSize sz = (MSize)lj_lib_checkintrange(L, 2, 0, LJ_MAX_BUF); |
| 204 | GCcdata *cd; | 204 | GCcdata *cd; |
| 205 | lj_buf_more((SBuf *)sbx, len); | 205 | lj_buf_more((SBuf *)sbx, sz); |
| 206 | ctype_loadffi(L); | 206 | ctype_loadffi(L); |
| 207 | cd = lj_cdata_new_(L, CTID_P_UINT8, CTSIZE_PTR); | 207 | cd = lj_cdata_new_(L, CTID_P_UINT8, CTSIZE_PTR); |
| 208 | *(void **)cdataptr(cd) = sbx->w; | 208 | *(void **)cdataptr(cd) = sbx->w; |
| @@ -211,7 +211,7 @@ LJLIB_CF(buffer_method_reserve) | |||
| 211 | return 2; | 211 | return 2; |
| 212 | } | 212 | } |
| 213 | 213 | ||
| 214 | LJLIB_CF(buffer_method_commit) | 214 | LJLIB_CF(buffer_method_commit) LJLIB_REC(.) |
| 215 | { | 215 | { |
| 216 | SBufExt *sbx = buffer_tobuf(L); | 216 | SBufExt *sbx = buffer_tobuf(L); |
| 217 | MSize len = (MSize)lj_lib_checkintrange(L, 2, 0, LJ_MAX_BUF); | 217 | MSize len = (MSize)lj_lib_checkintrange(L, 2, 0, LJ_MAX_BUF); |
| @@ -221,7 +221,7 @@ LJLIB_CF(buffer_method_commit) | |||
| 221 | return 1; | 221 | return 1; |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | LJLIB_CF(buffer_method_ref) | 224 | LJLIB_CF(buffer_method_ref) LJLIB_REC(.) |
| 225 | { | 225 | { |
| 226 | SBufExt *sbx = buffer_tobuf(L); | 226 | SBufExt *sbx = buffer_tobuf(L); |
| 227 | GCcdata *cd; | 227 | GCcdata *cd; |
| @@ -234,7 +234,7 @@ LJLIB_CF(buffer_method_ref) | |||
| 234 | } | 234 | } |
| 235 | #endif | 235 | #endif |
| 236 | 236 | ||
| 237 | LJLIB_CF(buffer_method_encode) | 237 | LJLIB_CF(buffer_method_encode) LJLIB_REC(.) |
| 238 | { | 238 | { |
| 239 | SBufExt *sbx = buffer_tobufw(L); | 239 | SBufExt *sbx = buffer_tobufw(L); |
| 240 | cTValue *o = lj_lib_checkany(L, 2); | 240 | cTValue *o = lj_lib_checkany(L, 2); |
| @@ -244,11 +244,11 @@ LJLIB_CF(buffer_method_encode) | |||
| 244 | return 1; | 244 | return 1; |
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | LJLIB_CF(buffer_method_decode) | 247 | LJLIB_CF(buffer_method_decode) LJLIB_REC(.) |
| 248 | { | 248 | { |
| 249 | SBufExt *sbx = buffer_tobufw(L); | 249 | SBufExt *sbx = buffer_tobufw(L); |
| 250 | setnilV(L->top++); | 250 | setnilV(L->top++); |
| 251 | lj_serialize_get(sbx, L->top-1); | 251 | sbx->r = lj_serialize_get(sbx, L->top-1); |
| 252 | lj_gc_check(L); | 252 | lj_gc_check(L); |
| 253 | return 1; | 253 | return 1; |
| 254 | } | 254 | } |
| @@ -260,7 +260,7 @@ LJLIB_CF(buffer_method___gc) | |||
| 260 | return 0; | 260 | return 0; |
| 261 | } | 261 | } |
| 262 | 262 | ||
| 263 | LJLIB_CF(buffer_method___tostring) | 263 | LJLIB_CF(buffer_method___tostring) LJLIB_REC(.) |
| 264 | { | 264 | { |
| 265 | SBufExt *sbx = buffer_tobuf(L); | 265 | SBufExt *sbx = buffer_tobuf(L); |
| 266 | setstrV(L, L->top-1, lj_str_new(L, sbx->r, sbufxlen(sbx))); | 266 | setstrV(L, L->top-1, lj_str_new(L, sbx->r, sbufxlen(sbx))); |
| @@ -268,7 +268,7 @@ LJLIB_CF(buffer_method___tostring) | |||
| 268 | return 1; | 268 | return 1; |
| 269 | } | 269 | } |
| 270 | 270 | ||
| 271 | LJLIB_CF(buffer_method___len) | 271 | LJLIB_CF(buffer_method___len) LJLIB_REC(.) |
| 272 | { | 272 | { |
| 273 | SBufExt *sbx = buffer_tobuf(L); | 273 | SBufExt *sbx = buffer_tobuf(L); |
| 274 | setintV(L->top-1, (int32_t)sbufxlen(sbx)); | 274 | setintV(L->top-1, (int32_t)sbufxlen(sbx)); |
| @@ -317,29 +317,19 @@ LJLIB_CF(buffer_new) | |||
| 317 | return 1; | 317 | return 1; |
| 318 | } | 318 | } |
| 319 | 319 | ||
| 320 | LJLIB_CF(buffer_encode) | 320 | LJLIB_CF(buffer_encode) LJLIB_REC(.) |
| 321 | { | 321 | { |
| 322 | cTValue *o = lj_lib_checkany(L, 1); | 322 | cTValue *o = lj_lib_checkany(L, 1); |
| 323 | SBufExt sbx; | 323 | setstrV(L, L->top++, lj_serialize_encode(L, o)); |
| 324 | memset(&sbx, 0, sizeof(SBufExt)); | ||
| 325 | lj_bufx_set_borrow(L, &sbx, &G(L)->tmpbuf); | ||
| 326 | lj_serialize_put(&sbx, o); | ||
| 327 | setstrV(L, L->top++, lj_buf_str(L, (SBuf *)&sbx)); | ||
| 328 | lj_gc_check(L); | 324 | lj_gc_check(L); |
| 329 | return 1; | 325 | return 1; |
| 330 | } | 326 | } |
| 331 | 327 | ||
| 332 | LJLIB_CF(buffer_decode) | 328 | LJLIB_CF(buffer_decode) LJLIB_REC(.) |
| 333 | { | 329 | { |
| 334 | GCstr *str = lj_lib_checkstrx(L, 1); | 330 | GCstr *str = lj_lib_checkstrx(L, 1); |
| 335 | SBufExt sbx; | ||
| 336 | memset(&sbx, 0, sizeof(SBufExt)); | ||
| 337 | lj_bufx_set_cow(L, &sbx, strdata(str), str->len); | ||
| 338 | /* No need to set sbx.cowref here. */ | ||
| 339 | setnilV(L->top++); | 331 | setnilV(L->top++); |
| 340 | lj_serialize_get(&sbx, L->top-1); | 332 | lj_serialize_decode(L, L->top-1, str); |
| 341 | lj_gc_check(L); | ||
| 342 | if (sbx.r != sbx.w) lj_err_caller(L, LJ_ERR_BUFFER_LEFTOV); | ||
| 343 | return 1; | 333 | return 1; |
| 344 | } | 334 | } |
| 345 | 335 | ||
diff --git a/src/lj_buf.c b/src/lj_buf.c index 889ccbca..d31bd99e 100644 --- a/src/lj_buf.c +++ b/src/lj_buf.c | |||
| @@ -108,6 +108,25 @@ char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz) | |||
| 108 | return lj_buf_need(sb, sz); | 108 | return lj_buf_need(sb, sz); |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | #if LJ_HASBUFFER && LJ_HASJIT | ||
| 112 | void lj_bufx_set(SBufExt *sbx, const char *p, MSize len, GCobj *ref) | ||
| 113 | { | ||
| 114 | lua_State *L = sbufL(sbx); | ||
| 115 | lj_bufx_free(L, sbx); | ||
| 116 | lj_bufx_set_cow(L, sbx, p, len); | ||
| 117 | setgcref(sbx->cowref, ref); | ||
| 118 | lj_gc_objbarrier(L, (GCudata *)sbx - 1, ref); | ||
| 119 | } | ||
| 120 | |||
| 121 | #if LJ_HASFFI | ||
| 122 | MSize LJ_FASTCALL lj_bufx_more(SBufExt *sbx, MSize sz) | ||
| 123 | { | ||
| 124 | lj_buf_more((SBuf *)sbx, sz); | ||
| 125 | return sbufleft(sbx); | ||
| 126 | } | ||
| 127 | #endif | ||
| 128 | #endif | ||
| 129 | |||
| 111 | /* -- Low-level buffer put operations ------------------------------------- */ | 130 | /* -- Low-level buffer put operations ------------------------------------- */ |
| 112 | 131 | ||
| 113 | SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len) | 132 | SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len) |
| @@ -118,14 +137,27 @@ SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len) | |||
| 118 | return sb; | 137 | return sb; |
| 119 | } | 138 | } |
| 120 | 139 | ||
| 121 | SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c) | 140 | #if LJ_HASJIT || LJ_HASFFI |
| 141 | static LJ_NOINLINE SBuf * LJ_FASTCALL lj_buf_putchar2(SBuf *sb, int c) | ||
| 122 | { | 142 | { |
| 123 | char *w = lj_buf_more(sb, 1); | 143 | char *w = lj_buf_more2(sb, 1); |
| 124 | *w++ = (char)c; | 144 | *w++ = (char)c; |
| 125 | sb->w = w; | 145 | sb->w = w; |
| 126 | return sb; | 146 | return sb; |
| 127 | } | 147 | } |
| 128 | 148 | ||
| 149 | SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c) | ||
| 150 | { | ||
| 151 | char *w = sb->w; | ||
| 152 | if (LJ_LIKELY(w < sb->e)) { | ||
| 153 | *w++ = (char)c; | ||
| 154 | sb->w = w; | ||
| 155 | return sb; | ||
| 156 | } | ||
| 157 | return lj_buf_putchar2(sb, c); | ||
| 158 | } | ||
| 159 | #endif | ||
| 160 | |||
| 129 | SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s) | 161 | SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s) |
| 130 | { | 162 | { |
| 131 | MSize len = s->len; | 163 | MSize len = s->len; |
diff --git a/src/lj_buf.h b/src/lj_buf.h index b97d55ef..4ace2685 100644 --- a/src/lj_buf.h +++ b/src/lj_buf.h | |||
| @@ -55,6 +55,7 @@ typedef struct SBufExt { | |||
| 55 | #define sbufisext(sb) (sbufflag((sb)) & SBUF_FLAG_EXT) | 55 | #define sbufisext(sb) (sbufflag((sb)) & SBUF_FLAG_EXT) |
| 56 | #define sbufiscow(sb) (sbufflag((sb)) & SBUF_FLAG_COW) | 56 | #define sbufiscow(sb) (sbufflag((sb)) & SBUF_FLAG_COW) |
| 57 | #define sbufisborrow(sb) (sbufflag((sb)) & SBUF_FLAG_BORROW) | 57 | #define sbufisborrow(sb) (sbufflag((sb)) & SBUF_FLAG_BORROW) |
| 58 | #define sbufiscoworborrow(sb) (sbufflag((sb)) & (SBUF_FLAG_COW|SBUF_FLAG_BORROW)) | ||
| 58 | #define sbufX(sb) \ | 59 | #define sbufX(sb) \ |
| 59 | (lj_assertG_(G(sbufL(sb)), sbufisext(sb), "not an SBufExt"), (SBufExt *)(sb)) | 60 | (lj_assertG_(G(sbufL(sb)), sbufisext(sb), "not an SBufExt"), (SBufExt *)(sb)) |
| 60 | #define setsbufflag(sb, flag) (setmrefu((sb)->L, (flag))) | 61 | #define setsbufflag(sb, flag) (setmrefu((sb)->L, (flag))) |
| @@ -143,15 +144,24 @@ static LJ_AINLINE void lj_bufx_reset(SBufExt *sbx) | |||
| 143 | 144 | ||
| 144 | static LJ_AINLINE void lj_bufx_free(lua_State *L, SBufExt *sbx) | 145 | static LJ_AINLINE void lj_bufx_free(lua_State *L, SBufExt *sbx) |
| 145 | { | 146 | { |
| 146 | if (!sbufiscow(sbx)) lj_mem_free(G(L), sbx->b, sbufsz(sbx)); | 147 | if (!sbufiscoworborrow(sbx)) lj_mem_free(G(L), sbx->b, sbufsz(sbx)); |
| 147 | setsbufXL(sbx, L, SBUF_FLAG_EXT); | 148 | setsbufXL(sbx, L, SBUF_FLAG_EXT); |
| 148 | setgcrefnull(sbx->cowref); | 149 | setgcrefnull(sbx->cowref); |
| 149 | sbx->r = sbx->w = sbx->b = sbx->e = NULL; | 150 | sbx->r = sbx->w = sbx->b = sbx->e = NULL; |
| 150 | } | 151 | } |
| 151 | 152 | ||
| 153 | #if LJ_HASBUFFER && LJ_HASJIT | ||
| 154 | LJ_FUNC void lj_bufx_set(SBufExt *sbx, const char *p, MSize len, GCobj *o); | ||
| 155 | #if LJ_HASFFI | ||
| 156 | LJ_FUNC MSize LJ_FASTCALL lj_bufx_more(SBufExt *sbx, MSize sz); | ||
| 157 | #endif | ||
| 158 | #endif | ||
| 159 | |||
| 152 | /* Low-level buffer put operations */ | 160 | /* Low-level buffer put operations */ |
| 153 | LJ_FUNC SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len); | 161 | LJ_FUNC SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len); |
| 162 | #if LJ_HASJIT || LJ_HASFFI | ||
| 154 | LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c); | 163 | LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c); |
| 164 | #endif | ||
| 155 | LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s); | 165 | LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s); |
| 156 | 166 | ||
| 157 | static LJ_AINLINE char *lj_buf_wmem(char *p, const void *q, MSize len) | 167 | static LJ_AINLINE char *lj_buf_wmem(char *p, const void *q, MSize len) |
diff --git a/src/lj_crecord.c b/src/lj_crecord.c index aa4c5842..95850611 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c | |||
| @@ -621,7 +621,7 @@ static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, cTValue *sval) | |||
| 621 | emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, ud->udtype)); | 621 | emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, ud->udtype)); |
| 622 | sp = emitir(IRT(IR_FLOAD, IRT_PTR), sp, | 622 | sp = emitir(IRT(IR_FLOAD, IRT_PTR), sp, |
| 623 | ud->udtype == UDTYPE_IO_FILE ? IRFL_UDATA_FILE : | 623 | ud->udtype == UDTYPE_IO_FILE ? IRFL_UDATA_FILE : |
| 624 | IRFL_UDATA_BUF_R); | 624 | IRFL_SBUF_R); |
| 625 | } else { | 625 | } else { |
| 626 | sp = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, sizeof(GCudata))); | 626 | sp = emitir(IRT(IR_ADD, IRT_PTR), sp, lj_ir_kintp(J, sizeof(GCudata))); |
| 627 | } | 627 | } |
| @@ -1918,10 +1918,25 @@ TRef lj_crecord_loadiu64(jit_State *J, TRef tr, cTValue *o) | |||
| 1918 | CTypeID id = argv2cdata(J, tr, o)->ctypeid; | 1918 | CTypeID id = argv2cdata(J, tr, o)->ctypeid; |
| 1919 | if (!(id == CTID_INT64 || id == CTID_UINT64)) | 1919 | if (!(id == CTID_INT64 || id == CTID_UINT64)) |
| 1920 | lj_trace_err(J, LJ_TRERR_BADTYPE); | 1920 | lj_trace_err(J, LJ_TRERR_BADTYPE); |
| 1921 | lj_needsplit(J); | ||
| 1921 | return emitir(IRT(IR_FLOAD, id == CTID_INT64 ? IRT_I64 : IRT_U64), tr, | 1922 | return emitir(IRT(IR_FLOAD, id == CTID_INT64 ? IRT_I64 : IRT_U64), tr, |
| 1922 | IRFL_CDATA_INT64); | 1923 | IRFL_CDATA_INT64); |
| 1923 | } | 1924 | } |
| 1924 | 1925 | ||
| 1926 | #if LJ_HASBUFFER | ||
| 1927 | TRef lj_crecord_topcvoid(jit_State *J, TRef tr, cTValue *o) | ||
| 1928 | { | ||
| 1929 | CTState *cts = ctype_ctsG(J2G(J)); | ||
| 1930 | if (!tref_iscdata(tr)) lj_trace_err(J, LJ_TRERR_BADTYPE); | ||
| 1931 | return crec_ct_tv(J, ctype_get(cts, CTID_P_CVOID), 0, tr, o); | ||
| 1932 | } | ||
| 1933 | |||
| 1934 | TRef lj_crecord_topuint8(jit_State *J, TRef tr) | ||
| 1935 | { | ||
| 1936 | return emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, CTID_P_UINT8), tr); | ||
| 1937 | } | ||
| 1938 | #endif | ||
| 1939 | |||
| 1925 | #undef IR | 1940 | #undef IR |
| 1926 | #undef emitir | 1941 | #undef emitir |
| 1927 | #undef emitconv | 1942 | #undef emitconv |
diff --git a/src/lj_crecord.h b/src/lj_crecord.h index 1a3427bd..e1a2d9c0 100644 --- a/src/lj_crecord.h +++ b/src/lj_crecord.h | |||
| @@ -34,6 +34,10 @@ LJ_FUNC TRef recff_bit64_tohex(jit_State *J, RecordFFData *rd, TRef hdr); | |||
| 34 | 34 | ||
| 35 | LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd); | 35 | LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd); |
| 36 | LJ_FUNC TRef lj_crecord_loadiu64(jit_State *J, TRef tr, cTValue *o); | 36 | LJ_FUNC TRef lj_crecord_loadiu64(jit_State *J, TRef tr, cTValue *o); |
| 37 | #if LJ_HASBUFFER | ||
| 38 | LJ_FUNC TRef lj_crecord_topcvoid(jit_State *J, TRef tr, cTValue *o); | ||
| 39 | LJ_FUNC TRef lj_crecord_topuint8(jit_State *J, TRef tr); | ||
| 40 | #endif | ||
| 37 | #endif | 41 | #endif |
| 38 | 42 | ||
| 39 | #endif | 43 | #endif |
diff --git a/src/lj_err.c b/src/lj_err.c index 1a518d9c..fda4a59c 100644 --- a/src/lj_err.c +++ b/src/lj_err.c | |||
| @@ -941,25 +941,27 @@ LJ_NOINLINE void lj_err_optype_call(lua_State *L, TValue *o) | |||
| 941 | /* Error in context of caller. */ | 941 | /* Error in context of caller. */ |
| 942 | LJ_NOINLINE void lj_err_callermsg(lua_State *L, const char *msg) | 942 | LJ_NOINLINE void lj_err_callermsg(lua_State *L, const char *msg) |
| 943 | { | 943 | { |
| 944 | TValue *frame = L->base-1; | 944 | TValue *frame = NULL, *pframe = NULL; |
| 945 | TValue *pframe = NULL; | 945 | if (!(LJ_HASJIT && tvref(G(L)->jit_base))) { |
| 946 | if (frame_islua(frame)) { | 946 | frame = L->base-1; |
| 947 | pframe = frame_prevl(frame); | 947 | if (frame_islua(frame)) { |
| 948 | } else if (frame_iscont(frame)) { | 948 | pframe = frame_prevl(frame); |
| 949 | if (frame_iscont_fficb(frame)) { | 949 | } else if (frame_iscont(frame)) { |
| 950 | pframe = frame; | 950 | if (frame_iscont_fficb(frame)) { |
| 951 | frame = NULL; | 951 | pframe = frame; |
| 952 | } else { | 952 | frame = NULL; |
| 953 | pframe = frame_prevd(frame); | 953 | } else { |
| 954 | pframe = frame_prevd(frame); | ||
| 954 | #if LJ_HASFFI | 955 | #if LJ_HASFFI |
| 955 | /* Remove frame for FFI metamethods. */ | 956 | /* Remove frame for FFI metamethods. */ |
| 956 | if (frame_func(frame)->c.ffid >= FF_ffi_meta___index && | 957 | if (frame_func(frame)->c.ffid >= FF_ffi_meta___index && |
| 957 | frame_func(frame)->c.ffid <= FF_ffi_meta___tostring) { | 958 | frame_func(frame)->c.ffid <= FF_ffi_meta___tostring) { |
| 958 | L->base = pframe+1; | 959 | L->base = pframe+1; |
| 959 | L->top = frame; | 960 | L->top = frame; |
| 960 | setcframe_pc(cframe_raw(L->cframe), frame_contpc(frame)); | 961 | setcframe_pc(cframe_raw(L->cframe), frame_contpc(frame)); |
| 961 | } | 962 | } |
| 962 | #endif | 963 | #endif |
| 964 | } | ||
| 963 | } | 965 | } |
| 964 | } | 966 | } |
| 965 | lj_debug_addloc(L, msg, pframe, frame); | 967 | lj_debug_addloc(L, msg, pframe, frame); |
diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c index 26af7d84..770b1586 100644 --- a/src/lj_ffrecord.c +++ b/src/lj_ffrecord.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #if LJ_HASJIT | 11 | #if LJ_HASJIT |
| 12 | 12 | ||
| 13 | #include "lj_err.h" | 13 | #include "lj_err.h" |
| 14 | #include "lj_buf.h" | ||
| 14 | #include "lj_str.h" | 15 | #include "lj_str.h" |
| 15 | #include "lj_tab.h" | 16 | #include "lj_tab.h" |
| 16 | #include "lj_frame.h" | 17 | #include "lj_frame.h" |
| @@ -28,6 +29,7 @@ | |||
| 28 | #include "lj_vm.h" | 29 | #include "lj_vm.h" |
| 29 | #include "lj_strscan.h" | 30 | #include "lj_strscan.h" |
| 30 | #include "lj_strfmt.h" | 31 | #include "lj_strfmt.h" |
| 32 | #include "lj_serialize.h" | ||
| 31 | 33 | ||
| 32 | /* Some local macros to save typing. Undef'd at the end. */ | 34 | /* Some local macros to save typing. Undef'd at the end. */ |
| 33 | #define IR(ref) (&J->cur.ir[(ref)]) | 35 | #define IR(ref) (&J->cur.ir[(ref)]) |
| @@ -941,20 +943,18 @@ static void LJ_FASTCALL recff_string_find(jit_State *J, RecordFFData *rd) | |||
| 941 | } | 943 | } |
| 942 | } | 944 | } |
| 943 | 945 | ||
| 944 | static void LJ_FASTCALL recff_string_format(jit_State *J, RecordFFData *rd) | 946 | static void recff_format(jit_State *J, RecordFFData *rd, TRef hdr, int sbufx) |
| 945 | { | 947 | { |
| 946 | TRef trfmt = lj_ir_tostr(J, J->base[0]); | 948 | ptrdiff_t arg = sbufx; |
| 947 | GCstr *fmt = argv2str(J, &rd->argv[0]); | 949 | TRef tr = hdr, trfmt = lj_ir_tostr(J, J->base[arg]); |
| 948 | int arg = 1; | 950 | GCstr *fmt = argv2str(J, &rd->argv[arg]); |
| 949 | TRef hdr, tr; | ||
| 950 | FormatState fs; | 951 | FormatState fs; |
| 951 | SFormat sf; | 952 | SFormat sf; |
| 952 | /* Specialize to the format string. */ | 953 | /* Specialize to the format string. */ |
| 953 | emitir(IRTG(IR_EQ, IRT_STR), trfmt, lj_ir_kstr(J, fmt)); | 954 | emitir(IRTG(IR_EQ, IRT_STR), trfmt, lj_ir_kstr(J, fmt)); |
| 954 | tr = hdr = recff_bufhdr(J); | ||
| 955 | lj_strfmt_init(&fs, strdata(fmt), fmt->len); | 955 | lj_strfmt_init(&fs, strdata(fmt), fmt->len); |
| 956 | while ((sf = lj_strfmt_parse(&fs)) != STRFMT_EOF) { /* Parse format. */ | 956 | while ((sf = lj_strfmt_parse(&fs)) != STRFMT_EOF) { /* Parse format. */ |
| 957 | TRef tra = sf == STRFMT_LIT ? 0 : J->base[arg++]; | 957 | TRef tra = sf == STRFMT_LIT ? 0 : J->base[++arg]; |
| 958 | TRef trsf = lj_ir_kint(J, (int32_t)sf); | 958 | TRef trsf = lj_ir_kint(J, (int32_t)sf); |
| 959 | IRCallID id; | 959 | IRCallID id; |
| 960 | switch (STRFMT_TYPE(sf)) { | 960 | switch (STRFMT_TYPE(sf)) { |
| @@ -968,9 +968,8 @@ static void LJ_FASTCALL recff_string_format(jit_State *J, RecordFFData *rd) | |||
| 968 | if (!tref_isinteger(tra)) { | 968 | if (!tref_isinteger(tra)) { |
| 969 | #if LJ_HASFFI | 969 | #if LJ_HASFFI |
| 970 | if (tref_iscdata(tra)) { | 970 | if (tref_iscdata(tra)) { |
| 971 | tra = lj_crecord_loadiu64(J, tra, &rd->argv[arg-1]); | 971 | tra = lj_crecord_loadiu64(J, tra, &rd->argv[arg]); |
| 972 | tr = lj_ir_call(J, IRCALL_lj_strfmt_putfxint, tr, trsf, tra); | 972 | tr = lj_ir_call(J, IRCALL_lj_strfmt_putfxint, tr, trsf, tra); |
| 973 | lj_needsplit(J); | ||
| 974 | break; | 973 | break; |
| 975 | } | 974 | } |
| 976 | #endif | 975 | #endif |
| @@ -1004,6 +1003,7 @@ static void LJ_FASTCALL recff_string_format(jit_State *J, RecordFFData *rd) | |||
| 1004 | case STRFMT_STR: | 1003 | case STRFMT_STR: |
| 1005 | if (!tref_isstr(tra)) { | 1004 | if (!tref_isstr(tra)) { |
| 1006 | recff_nyiu(J, rd); /* NYI: __tostring and non-string types for %s. */ | 1005 | recff_nyiu(J, rd); /* NYI: __tostring and non-string types for %s. */ |
| 1006 | /* NYI: also buffers. */ | ||
| 1007 | return; | 1007 | return; |
| 1008 | } | 1008 | } |
| 1009 | if (sf == STRFMT_STR) /* Shortcut for plain %s. */ | 1009 | if (sf == STRFMT_STR) /* Shortcut for plain %s. */ |
| @@ -1028,9 +1028,334 @@ static void LJ_FASTCALL recff_string_format(jit_State *J, RecordFFData *rd) | |||
| 1028 | return; | 1028 | return; |
| 1029 | } | 1029 | } |
| 1030 | } | 1030 | } |
| 1031 | J->base[0] = emitir(IRTG(IR_BUFSTR, IRT_STR), tr, hdr); | 1031 | if (sbufx) { |
| 1032 | emitir(IRT(IR_USE, IRT_NIL), tr, 0); | ||
| 1033 | } else { | ||
| 1034 | J->base[0] = emitir(IRTG(IR_BUFSTR, IRT_STR), tr, hdr); | ||
| 1035 | } | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | static void LJ_FASTCALL recff_string_format(jit_State *J, RecordFFData *rd) | ||
| 1039 | { | ||
| 1040 | recff_format(J, rd, recff_bufhdr(J), 0); | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | /* -- Buffer library fast functions --------------------------------------- */ | ||
| 1044 | |||
| 1045 | #if LJ_HASBUFFER | ||
| 1046 | |||
| 1047 | static LJ_AINLINE TRef recff_sbufx_get_L(jit_State *J, TRef ud) | ||
| 1048 | { | ||
| 1049 | return emitir(IRT(IR_FLOAD, IRT_PGC), ud, IRFL_SBUF_L); | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | static LJ_AINLINE void recff_sbufx_set_L(jit_State *J, TRef ud, TRef val) | ||
| 1053 | { | ||
| 1054 | TRef fref = emitir(IRT(IR_FREF, IRT_PGC), ud, IRFL_SBUF_L); | ||
| 1055 | emitir(IRT(IR_FSTORE, IRT_PGC), fref, val); | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | static LJ_AINLINE TRef recff_sbufx_get_ptr(jit_State *J, TRef ud, IRFieldID fl) | ||
| 1059 | { | ||
| 1060 | return emitir(IRT(IR_FLOAD, IRT_PTR), ud, fl); | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | static LJ_AINLINE void recff_sbufx_set_ptr(jit_State *J, TRef ud, IRFieldID fl, TRef val) | ||
| 1064 | { | ||
| 1065 | TRef fref = emitir(IRT(IR_FREF, IRT_PTR), ud, fl); | ||
| 1066 | emitir(IRT(IR_FSTORE, IRT_PTR), fref, val); | ||
| 1067 | } | ||
| 1068 | |||
| 1069 | static LJ_AINLINE TRef recff_sbufx_len(jit_State *J, TRef trr, TRef trw) | ||
| 1070 | { | ||
| 1071 | TRef len = emitir(IRT(IR_SUB, IRT_INTP), trw, trr); | ||
| 1072 | if (LJ_64) | ||
| 1073 | len = emitir(IRTI(IR_CONV), len, (IRT_INT<<5)|IRT_INTP|IRCONV_NONE); | ||
| 1074 | return len; | ||
| 1075 | } | ||
| 1076 | |||
| 1077 | /* Emit typecheck for string buffer. */ | ||
| 1078 | static TRef recff_sbufx_check(jit_State *J, RecordFFData *rd, int arg) | ||
| 1079 | { | ||
| 1080 | TRef trtype, ud = J->base[arg]; | ||
| 1081 | if (!tvisbuf(&rd->argv[arg])) lj_trace_err(J, LJ_TRERR_BADTYPE); | ||
| 1082 | trtype = emitir(IRT(IR_FLOAD, IRT_U8), ud, IRFL_UDATA_UDTYPE); | ||
| 1083 | emitir(IRTGI(IR_EQ), trtype, lj_ir_kint(J, UDTYPE_BUFFER)); | ||
| 1084 | return ud; | ||
| 1085 | } | ||
| 1086 | |||
| 1087 | /* Emit BUFHDR for write to extended string buffer. */ | ||
| 1088 | static TRef recff_sbufx_write(jit_State *J, TRef ud) | ||
| 1089 | { | ||
| 1090 | TRef trbuf = emitir(IRT(IR_ADD, IRT_PGC), ud, lj_ir_kint(J, sizeof(GCudata))); | ||
| 1091 | return emitir(IRT(IR_BUFHDR, IRT_PGC), trbuf, IRBUFHDR_WRITE); | ||
| 1092 | } | ||
| 1093 | |||
| 1094 | /* Check for integer in range for the buffer API. */ | ||
| 1095 | static TRef recff_sbufx_checkint(jit_State *J, RecordFFData *rd, int arg) | ||
| 1096 | { | ||
| 1097 | TRef tr = J->base[arg]; | ||
| 1098 | TRef trlim = lj_ir_kint(J, LJ_MAX_BUF); | ||
| 1099 | if (tref_isinteger(tr)) { | ||
| 1100 | emitir(IRTGI(IR_ULE), tr, trlim); | ||
| 1101 | } else if (tref_isnum(tr)) { | ||
| 1102 | tr = emitir(IRTI(IR_CONV), tr, IRCONV_INT_NUM|IRCONV_ANY); | ||
| 1103 | emitir(IRTGI(IR_ULE), tr, trlim); | ||
| 1104 | #if LJ_HASFFI | ||
| 1105 | } else if (tref_iscdata(tr)) { | ||
| 1106 | tr = lj_crecord_loadiu64(J, tr, &rd->argv[arg]); | ||
| 1107 | emitir(IRTG(IR_ULE, IRT_U64), tr, lj_ir_kint64(J, LJ_MAX_BUF)); | ||
| 1108 | tr = emitir(IRTI(IR_CONV), tr, (IRT_INT<<5)|IRT_I64|IRCONV_NONE); | ||
| 1109 | #else | ||
| 1110 | UNUSED(rd); | ||
| 1111 | #endif | ||
| 1112 | } else { | ||
| 1113 | lj_trace_err(J, LJ_TRERR_BADTYPE); | ||
| 1114 | } | ||
| 1115 | return tr; | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | static void LJ_FASTCALL recff_buffer_method_reset(jit_State *J, RecordFFData *rd) | ||
| 1119 | { | ||
| 1120 | TRef ud = recff_sbufx_check(J, rd, 0); | ||
| 1121 | SBufExt *sbx = bufV(&rd->argv[0]); | ||
| 1122 | int iscow = (int)sbufiscow(sbx); | ||
| 1123 | TRef trl = recff_sbufx_get_L(J, ud); | ||
| 1124 | TRef trcow = emitir(IRT(IR_BAND, IRT_IGC), trl, lj_ir_kint(J, SBUF_FLAG_COW)); | ||
| 1125 | TRef zero = lj_ir_kint(J, 0); | ||
| 1126 | emitir(IRTG(iscow ? IR_NE : IR_EQ, IRT_IGC), trcow, zero); | ||
| 1127 | if (iscow) { | ||
| 1128 | trl = emitir(IRT(IR_BXOR, IRT_IGC), trl, | ||
| 1129 | LJ_GC64 ? lj_ir_kint64(J, SBUF_FLAG_COW) : | ||
| 1130 | lj_ir_kint(J, SBUF_FLAG_COW)); | ||
| 1131 | recff_sbufx_set_ptr(J, ud, IRFL_SBUF_W, zero); | ||
| 1132 | recff_sbufx_set_ptr(J, ud, IRFL_SBUF_E, zero); | ||
| 1133 | recff_sbufx_set_ptr(J, ud, IRFL_SBUF_B, zero); | ||
| 1134 | recff_sbufx_set_L(J, ud, trl); | ||
| 1135 | emitir(IRT(IR_FSTORE, IRT_PGC), | ||
| 1136 | emitir(IRT(IR_FREF, IRT_PGC), ud, IRFL_SBUF_REF), zero); | ||
| 1137 | recff_sbufx_set_ptr(J, ud, IRFL_SBUF_R, zero); | ||
| 1138 | } else { | ||
| 1139 | TRef trb = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_B); | ||
| 1140 | recff_sbufx_set_ptr(J, ud, IRFL_SBUF_W, trb); | ||
| 1141 | recff_sbufx_set_ptr(J, ud, IRFL_SBUF_R, trb); | ||
| 1142 | } | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | static void LJ_FASTCALL recff_buffer_method_skip(jit_State *J, RecordFFData *rd) | ||
| 1146 | { | ||
| 1147 | TRef ud = recff_sbufx_check(J, rd, 0); | ||
| 1148 | TRef trr = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_R); | ||
| 1149 | TRef trw = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_W); | ||
| 1150 | TRef len = recff_sbufx_len(J, trr, trw); | ||
| 1151 | TRef trn = recff_sbufx_checkint(J, rd, 1); | ||
| 1152 | len = emitir(IRTI(IR_MIN), len, trn); | ||
| 1153 | trr = emitir(IRT(IR_ADD, IRT_PTR), trr, len); | ||
| 1154 | recff_sbufx_set_ptr(J, ud, IRFL_SBUF_R, trr); | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | static void LJ_FASTCALL recff_buffer_method_set(jit_State *J, RecordFFData *rd) | ||
| 1158 | { | ||
| 1159 | TRef ud = recff_sbufx_check(J, rd, 0); | ||
| 1160 | TRef trbuf = recff_sbufx_write(J, ud); | ||
| 1161 | TRef tr = J->base[1]; | ||
| 1162 | if (tref_isstr(tr)) { | ||
| 1163 | TRef trp = emitir(IRT(IR_STRREF, IRT_PGC), tr, lj_ir_kint(J, 0)); | ||
| 1164 | TRef len = emitir(IRTI(IR_FLOAD), tr, IRFL_STR_LEN); | ||
| 1165 | lj_ir_call(J, IRCALL_lj_bufx_set, trbuf, trp, len, tr); | ||
| 1166 | #if LJ_HASFFI | ||
| 1167 | } else if (tref_iscdata(tr)) { | ||
| 1168 | TRef trp = lj_crecord_topcvoid(J, tr, &rd->argv[1]); | ||
| 1169 | TRef len = recff_sbufx_checkint(J, rd, 2); | ||
| 1170 | lj_ir_call(J, IRCALL_lj_bufx_set, trbuf, trp, len, tr); | ||
| 1171 | #endif | ||
| 1172 | } /* else: Interpreter will throw. */ | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | static void LJ_FASTCALL recff_buffer_method_put(jit_State *J, RecordFFData *rd) | ||
| 1176 | { | ||
| 1177 | TRef ud = recff_sbufx_check(J, rd, 0); | ||
| 1178 | TRef trbuf = recff_sbufx_write(J, ud); | ||
| 1179 | TRef tr; | ||
| 1180 | ptrdiff_t arg; | ||
| 1181 | if (!J->base[1]) return; | ||
| 1182 | for (arg = 1; (tr = J->base[arg]); arg++) { | ||
| 1183 | if (tref_isstr(tr)) { | ||
| 1184 | trbuf = emitir(IRTG(IR_BUFPUT, IRT_PGC), trbuf, tr); | ||
| 1185 | } else if (tref_isnumber(tr)) { | ||
| 1186 | trbuf = emitir(IRTG(IR_BUFPUT, IRT_PGC), trbuf, | ||
| 1187 | emitir(IRT(IR_TOSTR, IRT_STR), tr, | ||
| 1188 | tref_isnum(tr) ? IRTOSTR_NUM : IRTOSTR_INT)); | ||
| 1189 | } else if (tref_isudata(tr)) { | ||
| 1190 | TRef ud2 = recff_sbufx_check(J, rd, arg); | ||
| 1191 | TRef trr = recff_sbufx_get_ptr(J, ud2, IRFL_SBUF_R); | ||
| 1192 | TRef trw = recff_sbufx_get_ptr(J, ud2, IRFL_SBUF_W); | ||
| 1193 | TRef len = recff_sbufx_len(J, trr, trw); | ||
| 1194 | emitir(IRTG(IR_NE, IRT_PGC), ud, ud2); | ||
| 1195 | trbuf = lj_ir_call(J, IRCALL_lj_buf_putmem, trbuf, trr, len); | ||
| 1196 | } else { | ||
| 1197 | recff_nyiu(J, rd); | ||
| 1198 | } | ||
| 1199 | } | ||
| 1200 | emitir(IRT(IR_USE, IRT_NIL), trbuf, 0); | ||
| 1201 | } | ||
| 1202 | |||
| 1203 | static void LJ_FASTCALL recff_buffer_method_putf(jit_State *J, RecordFFData *rd) | ||
| 1204 | { | ||
| 1205 | TRef ud = recff_sbufx_check(J, rd, 0); | ||
| 1206 | TRef trbuf = recff_sbufx_write(J, ud); | ||
| 1207 | recff_format(J, rd, trbuf, 1); | ||
| 1032 | } | 1208 | } |
| 1033 | 1209 | ||
| 1210 | static void LJ_FASTCALL recff_buffer_method_get(jit_State *J, RecordFFData *rd) | ||
| 1211 | { | ||
| 1212 | TRef ud = recff_sbufx_check(J, rd, 0); | ||
| 1213 | TRef trr = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_R); | ||
| 1214 | TRef trw = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_W); | ||
| 1215 | TRef tr; | ||
| 1216 | ptrdiff_t arg; | ||
| 1217 | if (!J->base[1]) { J->base[1] = TREF_NIL; J->base[2] = 0; } | ||
| 1218 | for (arg = 0; (tr = J->base[arg+1]); arg++) { | ||
| 1219 | TRef len = recff_sbufx_len(J, trr, trw); | ||
| 1220 | if (tref_isnil(tr)) { | ||
| 1221 | J->base[arg] = emitir(IRT(IR_XSNEW, IRT_STR), trr, len); | ||
| 1222 | trr = trw; | ||
| 1223 | } else { | ||
| 1224 | TRef trn = recff_sbufx_checkint(J, rd, arg+1); | ||
| 1225 | TRef tru; | ||
| 1226 | len = emitir(IRTI(IR_MIN), len, trn); | ||
| 1227 | tru = emitir(IRT(IR_ADD, IRT_PTR), trr, len); | ||
| 1228 | J->base[arg] = emitir(IRT(IR_XSNEW, IRT_STR), trr, len); | ||
| 1229 | trr = tru; /* Doing the ADD before the SNEW generates better code. */ | ||
| 1230 | } | ||
| 1231 | recff_sbufx_set_ptr(J, ud, IRFL_SBUF_R, trr); | ||
| 1232 | } | ||
| 1233 | rd->nres = arg; | ||
| 1234 | } | ||
| 1235 | |||
| 1236 | static void LJ_FASTCALL recff_buffer_method___tostring(jit_State *J, RecordFFData *rd) | ||
| 1237 | { | ||
| 1238 | TRef ud = recff_sbufx_check(J, rd, 0); | ||
| 1239 | TRef trr = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_R); | ||
| 1240 | TRef trw = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_W); | ||
| 1241 | J->base[0] = emitir(IRT(IR_XSNEW, IRT_STR), trr, recff_sbufx_len(J, trr, trw)); | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | static void LJ_FASTCALL recff_buffer_method___len(jit_State *J, RecordFFData *rd) | ||
| 1245 | { | ||
| 1246 | TRef ud = recff_sbufx_check(J, rd, 0); | ||
| 1247 | TRef trr = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_R); | ||
| 1248 | TRef trw = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_W); | ||
| 1249 | J->base[0] = recff_sbufx_len(J, trr, trw); | ||
| 1250 | } | ||
| 1251 | |||
| 1252 | #if LJ_HASFFI | ||
| 1253 | static void LJ_FASTCALL recff_buffer_method_putcdata(jit_State *J, RecordFFData *rd) | ||
| 1254 | { | ||
| 1255 | TRef ud = recff_sbufx_check(J, rd, 0); | ||
| 1256 | TRef trbuf = recff_sbufx_write(J, ud); | ||
| 1257 | TRef tr = lj_crecord_topcvoid(J, J->base[1], &rd->argv[1]); | ||
| 1258 | TRef len = recff_sbufx_checkint(J, rd, 2); | ||
| 1259 | trbuf = lj_ir_call(J, IRCALL_lj_buf_putmem, trbuf, tr, len); | ||
| 1260 | emitir(IRT(IR_USE, IRT_NIL), trbuf, 0); | ||
| 1261 | } | ||
| 1262 | |||
| 1263 | static void LJ_FASTCALL recff_buffer_method_reserve(jit_State *J, RecordFFData *rd) | ||
| 1264 | { | ||
| 1265 | TRef ud = recff_sbufx_check(J, rd, 0); | ||
| 1266 | TRef trbuf = recff_sbufx_write(J, ud); | ||
| 1267 | TRef trsz = recff_sbufx_checkint(J, rd, 1); | ||
| 1268 | J->base[1] = lj_ir_call(J, IRCALL_lj_bufx_more, trbuf, trsz); | ||
| 1269 | J->base[0] = lj_crecord_topuint8(J, recff_sbufx_get_ptr(J, ud, IRFL_SBUF_W)); | ||
| 1270 | rd->nres = 2; | ||
| 1271 | } | ||
| 1272 | |||
| 1273 | static void LJ_FASTCALL recff_buffer_method_commit(jit_State *J, RecordFFData *rd) | ||
| 1274 | { | ||
| 1275 | TRef ud = recff_sbufx_check(J, rd, 0); | ||
| 1276 | TRef len = recff_sbufx_checkint(J, rd, 1); | ||
| 1277 | TRef trw = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_W); | ||
| 1278 | TRef tre = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_E); | ||
| 1279 | TRef left = emitir(IRT(IR_SUB, IRT_INTP), tre, trw); | ||
| 1280 | if (LJ_64) | ||
| 1281 | left = emitir(IRTI(IR_CONV), left, (IRT_INT<<5)|IRT_INTP|IRCONV_NONE); | ||
| 1282 | emitir(IRTGI(IR_ULE), len, left); | ||
| 1283 | trw = emitir(IRT(IR_ADD, IRT_PTR), trw, len); | ||
| 1284 | recff_sbufx_set_ptr(J, ud, IRFL_SBUF_W, trw); | ||
| 1285 | } | ||
| 1286 | |||
| 1287 | static void LJ_FASTCALL recff_buffer_method_ref(jit_State *J, RecordFFData *rd) | ||
| 1288 | { | ||
| 1289 | TRef ud = recff_sbufx_check(J, rd, 0); | ||
| 1290 | TRef trr = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_R); | ||
| 1291 | TRef trw = recff_sbufx_get_ptr(J, ud, IRFL_SBUF_W); | ||
| 1292 | J->base[0] = lj_crecord_topuint8(J, trr); | ||
| 1293 | J->base[1] = recff_sbufx_len(J, trr, trw); | ||
| 1294 | rd->nres = 2; | ||
| 1295 | } | ||
| 1296 | #endif | ||
| 1297 | |||
| 1298 | static void LJ_FASTCALL recff_buffer_method_encode(jit_State *J, RecordFFData *rd) | ||
| 1299 | { | ||
| 1300 | TRef ud = recff_sbufx_check(J, rd, 0); | ||
| 1301 | TRef trbuf = recff_sbufx_write(J, ud); | ||
| 1302 | TRef tmp, tr = J->base[1]; | ||
| 1303 | if (!LJ_DUALNUM && tref_isinteger(tr)) | ||
| 1304 | tr = emitir(IRTN(IR_CONV), tr, IRCONV_NUM_INT); | ||
| 1305 | tmp = emitir(IRT(IR_TMPREF, IRT_PGC), tr, IRTMPREF_IN1); | ||
| 1306 | lj_ir_call(J, IRCALL_lj_serialize_put, trbuf, tmp); | ||
| 1307 | /* No IR_USE needed, since the call is a store. */ | ||
| 1308 | } | ||
| 1309 | |||
| 1310 | static void LJ_FASTCALL recff_buffer_method_decode(jit_State *J, RecordFFData *rd) | ||
| 1311 | { | ||
| 1312 | TRef ud = recff_sbufx_check(J, rd, 0); | ||
| 1313 | TRef trbuf = recff_sbufx_write(J, ud); | ||
| 1314 | TRef trr, tmp; | ||
| 1315 | IRType t; | ||
| 1316 | tmp = emitir(IRT(IR_TMPREF, IRT_PGC), REF_NIL, IRTMPREF_OUT1); | ||
| 1317 | trr = lj_ir_call(J, IRCALL_lj_serialize_get, trbuf, tmp); | ||
| 1318 | /* No IR_USE needed, since the call is a store. */ | ||
| 1319 | t = (IRType)lj_serialize_peektype(bufV(&rd->argv[0])); | ||
| 1320 | J->base[0] = lj_record_vload(J, tmp, t); | ||
| 1321 | /* The sbx->r store must be after the VLOAD type check, in case it fails. */ | ||
| 1322 | recff_sbufx_set_ptr(J, ud, IRFL_SBUF_R, trr); | ||
| 1323 | } | ||
| 1324 | |||
| 1325 | static void LJ_FASTCALL recff_buffer_encode(jit_State *J, RecordFFData *rd) | ||
| 1326 | { | ||
| 1327 | TRef tmp, tr = J->base[0]; | ||
| 1328 | if (!LJ_DUALNUM && tref_isinteger(tr)) | ||
| 1329 | tr = emitir(IRTN(IR_CONV), tr, IRCONV_NUM_INT); | ||
| 1330 | tmp = emitir(IRT(IR_TMPREF, IRT_PGC), tr, IRTMPREF_IN1); | ||
| 1331 | J->base[0] = lj_ir_call(J, IRCALL_lj_serialize_encode, tmp); | ||
| 1332 | /* IR_USE needed for IR_CALLA, because the encoder may throw non-OOM. */ | ||
| 1333 | emitir(IRT(IR_USE, IRT_NIL), J->base[0], 0); | ||
| 1334 | UNUSED(rd); | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | static void LJ_FASTCALL recff_buffer_decode(jit_State *J, RecordFFData *rd) | ||
| 1338 | { | ||
| 1339 | if (tvisstr(&rd->argv[0])) { | ||
| 1340 | GCstr *str = strV(&rd->argv[0]); | ||
| 1341 | SBufExt sbx; | ||
| 1342 | TRef tr, tmp; | ||
| 1343 | IRType t; | ||
| 1344 | tmp = emitir(IRT(IR_TMPREF, IRT_PGC), REF_NIL, IRTMPREF_OUT1); | ||
| 1345 | tr = lj_ir_call(J, IRCALL_lj_serialize_decode, tmp, J->base[0]); | ||
| 1346 | /* IR_USE needed for IR_CALLA, because the decoder may throw non-OOM. | ||
| 1347 | ** That's why IRCALL_lj_serialize_decode needs a fake INT result. | ||
| 1348 | */ | ||
| 1349 | emitir(IRT(IR_USE, IRT_NIL), tr, 0); | ||
| 1350 | memset(&sbx, 0, sizeof(SBufExt)); | ||
| 1351 | lj_bufx_set_cow(J->L, &sbx, strdata(str), str->len); | ||
| 1352 | t = (IRType)lj_serialize_peektype(&sbx); | ||
| 1353 | J->base[0] = lj_record_vload(J, tmp, t); | ||
| 1354 | } /* else: Interpreter will throw. */ | ||
| 1355 | } | ||
| 1356 | |||
| 1357 | #endif | ||
| 1358 | |||
| 1034 | /* -- Table library fast functions ---------------------------------------- */ | 1359 | /* -- Table library fast functions ---------------------------------------- */ |
| 1035 | 1360 | ||
| 1036 | static void LJ_FASTCALL recff_table_insert(jit_State *J, RecordFFData *rd) | 1361 | static void LJ_FASTCALL recff_table_insert(jit_State *J, RecordFFData *rd) |
diff --git a/src/lj_ir.c b/src/lj_ir.c index 29d75d26..71bf8855 100644 --- a/src/lj_ir.c +++ b/src/lj_ir.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #endif | 30 | #endif |
| 31 | #include "lj_vm.h" | 31 | #include "lj_vm.h" |
| 32 | #include "lj_strscan.h" | 32 | #include "lj_strscan.h" |
| 33 | #include "lj_serialize.h" | ||
| 33 | #include "lj_strfmt.h" | 34 | #include "lj_strfmt.h" |
| 34 | #include "lj_prng.h" | 35 | #include "lj_prng.h" |
| 35 | 36 | ||
diff --git a/src/lj_ir.h b/src/lj_ir.h index fa10f4bc..b3faaea8 100644 --- a/src/lj_ir.h +++ b/src/lj_ir.h | |||
| @@ -205,10 +205,15 @@ IRFPMDEF(FPMENUM) | |||
| 205 | _(UDATA_META, offsetof(GCudata, metatable)) \ | 205 | _(UDATA_META, offsetof(GCudata, metatable)) \ |
| 206 | _(UDATA_UDTYPE, offsetof(GCudata, udtype)) \ | 206 | _(UDATA_UDTYPE, offsetof(GCudata, udtype)) \ |
| 207 | _(UDATA_FILE, sizeof(GCudata)) \ | 207 | _(UDATA_FILE, sizeof(GCudata)) \ |
| 208 | _(UDATA_BUF_R, sizeof(GCudata) + offsetof(SBufExt, r)) \ | 208 | _(SBUF_W, sizeof(GCudata) + offsetof(SBufExt, w)) \ |
| 209 | _(SBUF_E, sizeof(GCudata) + offsetof(SBufExt, e)) \ | ||
| 210 | _(SBUF_B, sizeof(GCudata) + offsetof(SBufExt, b)) \ | ||
| 211 | _(SBUF_L, sizeof(GCudata) + offsetof(SBufExt, L)) \ | ||
| 212 | _(SBUF_REF, sizeof(GCudata) + offsetof(SBufExt, cowref)) \ | ||
| 213 | _(SBUF_R, sizeof(GCudata) + offsetof(SBufExt, r)) \ | ||
| 209 | _(CDATA_CTYPEID, offsetof(GCcdata, ctypeid)) \ | 214 | _(CDATA_CTYPEID, offsetof(GCcdata, ctypeid)) \ |
| 210 | _(CDATA_PTR, sizeof(GCcdata)) \ | 215 | _(CDATA_PTR, sizeof(GCcdata)) \ |
| 211 | _(CDATA_INT, sizeof(GCcdata)) \ | 216 | _(CDATA_INT, sizeof(GCcdata)) \ |
| 212 | _(CDATA_INT64, sizeof(GCcdata)) \ | 217 | _(CDATA_INT64, sizeof(GCcdata)) \ |
| 213 | _(CDATA_INT64_4, sizeof(GCcdata) + 4) | 218 | _(CDATA_INT64_4, sizeof(GCcdata) + 4) |
| 214 | 219 | ||
diff --git a/src/lj_ircall.h b/src/lj_ircall.h index 13501ba1..c837b18d 100644 --- a/src/lj_ircall.h +++ b/src/lj_ircall.h | |||
| @@ -113,6 +113,18 @@ typedef struct CCallInfo { | |||
| 113 | #define IRCALLCOND_FFI32(x) NULL | 113 | #define IRCALLCOND_FFI32(x) NULL |
| 114 | #endif | 114 | #endif |
| 115 | 115 | ||
| 116 | #if LJ_HASBUFFER | ||
| 117 | #define IRCALLCOND_BUFFER(x) x | ||
| 118 | #else | ||
| 119 | #define IRCALLCOND_BUFFER(x) NULL | ||
| 120 | #endif | ||
| 121 | |||
| 122 | #if LJ_HASBUFFER && LJ_HASFFI | ||
| 123 | #define IRCALLCOND_BUFFFI(x) x | ||
| 124 | #else | ||
| 125 | #define IRCALLCOND_BUFFFI(x) NULL | ||
| 126 | #endif | ||
| 127 | |||
| 116 | #if LJ_SOFTFP | 128 | #if LJ_SOFTFP |
| 117 | #define XA_FP CCI_XA | 129 | #define XA_FP CCI_XA |
| 118 | #define XA2_FP (CCI_XA+CCI_XA) | 130 | #define XA2_FP (CCI_XA+CCI_XA) |
| @@ -163,6 +175,12 @@ typedef struct CCallInfo { | |||
| 163 | _(ANY, lj_buf_putstr_upper, 2, FL, PGC, CCI_T) \ | 175 | _(ANY, lj_buf_putstr_upper, 2, FL, PGC, CCI_T) \ |
| 164 | _(ANY, lj_buf_putstr_rep, 3, L, PGC, CCI_T) \ | 176 | _(ANY, lj_buf_putstr_rep, 3, L, PGC, CCI_T) \ |
| 165 | _(ANY, lj_buf_puttab, 5, L, PGC, CCI_T) \ | 177 | _(ANY, lj_buf_puttab, 5, L, PGC, CCI_T) \ |
| 178 | _(BUFFER, lj_bufx_set, 4, S, NIL, 0) \ | ||
| 179 | _(BUFFFI, lj_bufx_more, 2, FS, INT, CCI_T) \ | ||
| 180 | _(BUFFER, lj_serialize_put, 2, FS, PGC, CCI_T) \ | ||
| 181 | _(BUFFER, lj_serialize_get, 2, FS, PTR, CCI_T) \ | ||
| 182 | _(BUFFER, lj_serialize_encode, 2, FA, STR, CCI_L|CCI_T) \ | ||
| 183 | _(BUFFER, lj_serialize_decode, 3, A, INT, CCI_L|CCI_T) \ | ||
| 166 | _(ANY, lj_buf_tostr, 1, FL, STR, CCI_T) \ | 184 | _(ANY, lj_buf_tostr, 1, FL, STR, CCI_T) \ |
| 167 | _(ANY, lj_tab_new_ah, 3, A, TAB, CCI_L|CCI_T) \ | 185 | _(ANY, lj_tab_new_ah, 3, A, TAB, CCI_L|CCI_T) \ |
| 168 | _(ANY, lj_tab_new1, 2, FA, TAB, CCI_L|CCI_T) \ | 186 | _(ANY, lj_tab_new1, 2, FA, TAB, CCI_L|CCI_T) \ |
diff --git a/src/lj_iropt.h b/src/lj_iropt.h index 69835ee8..0541090d 100644 --- a/src/lj_iropt.h +++ b/src/lj_iropt.h | |||
| @@ -124,6 +124,7 @@ LJ_FUNC TRef LJ_FASTCALL lj_opt_fwd_alen(jit_State *J); | |||
| 124 | LJ_FUNC TRef LJ_FASTCALL lj_opt_fwd_hrefk(jit_State *J); | 124 | LJ_FUNC TRef LJ_FASTCALL lj_opt_fwd_hrefk(jit_State *J); |
| 125 | LJ_FUNC int LJ_FASTCALL lj_opt_fwd_href_nokey(jit_State *J); | 125 | LJ_FUNC int LJ_FASTCALL lj_opt_fwd_href_nokey(jit_State *J); |
| 126 | LJ_FUNC int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim); | 126 | LJ_FUNC int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim); |
| 127 | LJ_FUNC int LJ_FASTCALL lj_opt_fwd_sbuf(jit_State *J, IRRef lim); | ||
| 127 | LJ_FUNC int lj_opt_fwd_wasnonnil(jit_State *J, IROpT loadop, IRRef xref); | 128 | LJ_FUNC int lj_opt_fwd_wasnonnil(jit_State *J, IROpT loadop, IRRef xref); |
| 128 | 129 | ||
| 129 | /* Dead-store elimination. */ | 130 | /* Dead-store elimination. */ |
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c index 97dad4ff..41e0d1ca 100644 --- a/src/lj_opt_fold.c +++ b/src/lj_opt_fold.c | |||
| @@ -578,6 +578,9 @@ LJFOLDF(kfold_strcmp) | |||
| 578 | ** The compromise is to declare them as loads, emit them like stores and | 578 | ** The compromise is to declare them as loads, emit them like stores and |
| 579 | ** CSE whole chains manually when the BUFSTR is to be emitted. Any chain | 579 | ** CSE whole chains manually when the BUFSTR is to be emitted. Any chain |
| 580 | ** fragments left over from CSE are eliminated by DCE. | 580 | ** fragments left over from CSE are eliminated by DCE. |
| 581 | ** | ||
| 582 | ** The string buffer methods emit a USE instead of a BUFSTR to keep the | ||
| 583 | ** chain alive. | ||
| 581 | */ | 584 | */ |
| 582 | 585 | ||
| 583 | LJFOLD(BUFHDR any any) | 586 | LJFOLD(BUFHDR any any) |
| @@ -586,18 +589,38 @@ LJFOLDF(bufhdr_merge) | |||
| 586 | return fins->op2 == IRBUFHDR_WRITE ? CSEFOLD : EMITFOLD; | 589 | return fins->op2 == IRBUFHDR_WRITE ? CSEFOLD : EMITFOLD; |
| 587 | } | 590 | } |
| 588 | 591 | ||
| 589 | LJFOLD(BUFPUT BUFHDR BUFSTR) | 592 | LJFOLD(BUFPUT any BUFSTR) |
| 590 | LJFOLDF(bufput_append) | 593 | LJFOLDF(bufput_bufstr) |
| 591 | { | 594 | { |
| 592 | /* New buffer, no other buffer op inbetween and same buffer? */ | 595 | if ((J->flags & JIT_F_OPT_FWD)) { |
| 593 | if ((J->flags & JIT_F_OPT_FWD) && | 596 | IRRef hdr = fright->op2; |
| 594 | fleft->op2 == IRBUFHDR_RESET && | 597 | /* New buffer, no other buffer op inbetween and same buffer? */ |
| 595 | fleft->prev == fright->op2 && | 598 | if (fleft->o == IR_BUFHDR && fleft->op2 == IRBUFHDR_RESET && |
| 596 | fleft->op1 == IR(fright->op2)->op1) { | 599 | fleft->prev == hdr && |
| 597 | IRRef ref = fins->op1; | 600 | fleft->op1 == IR(hdr)->op1) { |
| 598 | IR(ref)->op2 = IRBUFHDR_APPEND; /* Modify BUFHDR. */ | 601 | IRRef ref = fins->op1; |
| 599 | IR(ref)->op1 = fright->op1; | 602 | IR(ref)->op2 = IRBUFHDR_APPEND; /* Modify BUFHDR. */ |
| 600 | return ref; | 603 | IR(ref)->op1 = fright->op1; |
| 604 | return ref; | ||
| 605 | } | ||
| 606 | /* Replay puts to global temporary buffer. */ | ||
| 607 | if (IR(hdr)->op2 == IRBUFHDR_RESET) { | ||
| 608 | IRIns *ir = IR(fright->op1); | ||
| 609 | /* For now only handle single string.reverse .lower .upper .rep. */ | ||
| 610 | if (ir->o == IR_CALLL && | ||
| 611 | ir->op2 >= IRCALL_lj_buf_putstr_reverse && | ||
| 612 | ir->op2 <= IRCALL_lj_buf_putstr_rep) { | ||
| 613 | IRIns *carg1 = IR(ir->op1); | ||
| 614 | if (ir->op2 == IRCALL_lj_buf_putstr_rep) { | ||
| 615 | IRIns *carg2 = IR(carg1->op1); | ||
| 616 | if (carg2->op1 == hdr) { | ||
| 617 | return lj_ir_call(J, ir->op2, fins->op1, carg2->op2, carg1->op2); | ||
| 618 | } | ||
| 619 | } else if (carg1->op1 == hdr) { | ||
| 620 | return lj_ir_call(J, ir->op2, fins->op1, carg1->op2); | ||
| 621 | } | ||
| 622 | } | ||
| 623 | } | ||
| 601 | } | 624 | } |
| 602 | return EMITFOLD; /* Always emit, CSE later. */ | 625 | return EMITFOLD; /* Always emit, CSE later. */ |
| 603 | } | 626 | } |
| @@ -2285,6 +2308,18 @@ LJFOLDF(fload_str_len_tostr) | |||
| 2285 | return NEXTFOLD; | 2308 | return NEXTFOLD; |
| 2286 | } | 2309 | } |
| 2287 | 2310 | ||
| 2311 | LJFOLD(FLOAD any IRFL_SBUF_W) | ||
| 2312 | LJFOLD(FLOAD any IRFL_SBUF_E) | ||
| 2313 | LJFOLD(FLOAD any IRFL_SBUF_B) | ||
| 2314 | LJFOLD(FLOAD any IRFL_SBUF_L) | ||
| 2315 | LJFOLD(FLOAD any IRFL_SBUF_REF) | ||
| 2316 | LJFOLD(FLOAD any IRFL_SBUF_R) | ||
| 2317 | LJFOLDF(fload_sbuf) | ||
| 2318 | { | ||
| 2319 | TRef tr = lj_opt_fwd_fload(J); | ||
| 2320 | return lj_opt_fwd_sbuf(J, tref_ref(tr)) ? tr : EMITFOLD; | ||
| 2321 | } | ||
| 2322 | |||
| 2288 | /* The C type ID of cdata objects is immutable. */ | 2323 | /* The C type ID of cdata objects is immutable. */ |
| 2289 | LJFOLD(FLOAD KGC IRFL_CDATA_CTYPEID) | 2324 | LJFOLD(FLOAD KGC IRFL_CDATA_CTYPEID) |
| 2290 | LJFOLDF(fload_cdata_typeid_kgc) | 2325 | LJFOLDF(fload_cdata_typeid_kgc) |
diff --git a/src/lj_opt_mem.c b/src/lj_opt_mem.c index f430fc37..81184f14 100644 --- a/src/lj_opt_mem.c +++ b/src/lj_opt_mem.c | |||
| @@ -620,8 +620,9 @@ TRef LJ_FASTCALL lj_opt_dse_fstore(jit_State *J) | |||
| 620 | goto doemit; | 620 | goto doemit; |
| 621 | break; /* Otherwise continue searching. */ | 621 | break; /* Otherwise continue searching. */ |
| 622 | case ALIAS_MUST: | 622 | case ALIAS_MUST: |
| 623 | if (store->op2 == val) /* Same value: drop the new store. */ | 623 | if (store->op2 == val && |
| 624 | return DROPFOLD; | 624 | !(xr->op2 >= IRFL_SBUF_W && xr->op2 <= IRFL_SBUF_R)) |
| 625 | return DROPFOLD; /* Same value: drop the new store. */ | ||
| 625 | /* Different value: try to eliminate the redundant store. */ | 626 | /* Different value: try to eliminate the redundant store. */ |
| 626 | if (ref > J->chain[IR_LOOP]) { /* Quick check to avoid crossing LOOP. */ | 627 | if (ref > J->chain[IR_LOOP]) { /* Quick check to avoid crossing LOOP. */ |
| 627 | IRIns *ir; | 628 | IRIns *ir; |
| @@ -642,6 +643,29 @@ doemit: | |||
| 642 | return EMITFOLD; /* Otherwise we have a conflict or simply no match. */ | 643 | return EMITFOLD; /* Otherwise we have a conflict or simply no match. */ |
| 643 | } | 644 | } |
| 644 | 645 | ||
| 646 | /* Check whether there's no aliasing buffer op between IRFL_SBUF_*. */ | ||
| 647 | int LJ_FASTCALL lj_opt_fwd_sbuf(jit_State *J, IRRef lim) | ||
| 648 | { | ||
| 649 | IRRef ref; | ||
| 650 | if (J->chain[IR_BUFPUT] > lim) | ||
| 651 | return 0; /* Conflict. */ | ||
| 652 | ref = J->chain[IR_CALLS]; | ||
| 653 | while (ref > lim) { | ||
| 654 | IRIns *ir = IR(ref); | ||
| 655 | if (ir->op2 >= IRCALL_lj_strfmt_putint && ir->op2 < IRCALL_lj_buf_tostr) | ||
| 656 | return 0; /* Conflict. */ | ||
| 657 | ref = ir->prev; | ||
| 658 | } | ||
| 659 | ref = J->chain[IR_CALLL]; | ||
| 660 | while (ref > lim) { | ||
| 661 | IRIns *ir = IR(ref); | ||
| 662 | if (ir->op2 >= IRCALL_lj_strfmt_putint && ir->op2 < IRCALL_lj_buf_tostr) | ||
| 663 | return 0; /* Conflict. */ | ||
| 664 | ref = ir->prev; | ||
| 665 | } | ||
| 666 | return 1; /* No conflict. Can safely FOLD/CSE. */ | ||
| 667 | } | ||
| 668 | |||
| 645 | /* -- XLOAD forwarding and XSTORE elimination ----------------------------- */ | 669 | /* -- XLOAD forwarding and XSTORE elimination ----------------------------- */ |
| 646 | 670 | ||
| 647 | /* Find cdata allocation for a reference (if any). */ | 671 | /* Find cdata allocation for a reference (if any). */ |
diff --git a/src/lj_record.c b/src/lj_record.c index c0aea106..ee62179b 100644 --- a/src/lj_record.c +++ b/src/lj_record.c | |||
| @@ -1445,6 +1445,16 @@ TRef lj_record_idx(jit_State *J, RecordIndex *ix) | |||
| 1445 | return 0; /* No result yet. */ | 1445 | return 0; /* No result yet. */ |
| 1446 | } | 1446 | } |
| 1447 | } | 1447 | } |
| 1448 | #if LJ_HASBUFFER | ||
| 1449 | /* The index table of buffer objects is treated as immutable. */ | ||
| 1450 | if (ix->mt == TREF_NIL && !ix->val && | ||
| 1451 | tref_isudata(ix->tab) && udataV(&ix->tabv)->udtype == UDTYPE_BUFFER && | ||
| 1452 | tref_istab(ix->mobj) && tref_isstr(ix->key) && tref_isk(ix->key)) { | ||
| 1453 | cTValue *val = lj_tab_getstr(tabV(&ix->mobjv), strV(&ix->keyv)); | ||
| 1454 | TRef tr = lj_record_constify(J, val); | ||
| 1455 | if (tr) return tr; /* Specialize to the value, i.e. a method. */ | ||
| 1456 | } | ||
| 1457 | #endif | ||
| 1448 | /* Otherwise retry lookup with metaobject. */ | 1458 | /* Otherwise retry lookup with metaobject. */ |
| 1449 | ix->tab = ix->mobj; | 1459 | ix->tab = ix->mobj; |
| 1450 | copyTV(J->L, &ix->tabv, &ix->mobjv); | 1460 | copyTV(J->L, &ix->tabv, &ix->mobjv); |
diff --git a/src/lj_serialize.c b/src/lj_serialize.c index d84ebcb8..70ff4796 100644 --- a/src/lj_serialize.c +++ b/src/lj_serialize.c | |||
| @@ -18,6 +18,9 @@ | |||
| 18 | #include "lj_ctype.h" | 18 | #include "lj_ctype.h" |
| 19 | #include "lj_cdata.h" | 19 | #include "lj_cdata.h" |
| 20 | #endif | 20 | #endif |
| 21 | #if LJ_HASJIT | ||
| 22 | #include "lj_ir.h" | ||
| 23 | #endif | ||
| 21 | #include "lj_serialize.h" | 24 | #include "lj_serialize.h" |
| 22 | 25 | ||
| 23 | /* Tags for internal serialization format. */ | 26 | /* Tags for internal serialization format. */ |
| @@ -400,6 +403,9 @@ eob: | |||
| 400 | return NULL; | 403 | return NULL; |
| 401 | } | 404 | } |
| 402 | 405 | ||
| 406 | /* -- External serialization API ------------------------------------------ */ | ||
| 407 | |||
| 408 | /* Encode to buffer. */ | ||
| 403 | SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o) | 409 | SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o) |
| 404 | { | 410 | { |
| 405 | sbx->depth = LJ_SERIALIZE_DEPTH; | 411 | sbx->depth = LJ_SERIALIZE_DEPTH; |
| @@ -407,10 +413,63 @@ SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o) | |||
| 407 | return sbx; | 413 | return sbx; |
| 408 | } | 414 | } |
| 409 | 415 | ||
| 410 | SBufExt * LJ_FASTCALL lj_serialize_get(SBufExt *sbx, TValue *o) | 416 | /* Decode from buffer. */ |
| 417 | char * LJ_FASTCALL lj_serialize_get(SBufExt *sbx, TValue *o) | ||
| 411 | { | 418 | { |
| 412 | sbx->r = serialize_get(sbx->r, sbx, o); | 419 | return serialize_get(sbx->r, sbx, o); |
| 413 | return sbx; | 420 | } |
| 421 | |||
| 422 | /* Stand-alone encoding, borrowing from global temporary buffer. */ | ||
| 423 | GCstr * LJ_FASTCALL lj_serialize_encode(lua_State *L, cTValue *o) | ||
| 424 | { | ||
| 425 | SBufExt sbx; | ||
| 426 | char *w; | ||
| 427 | memset(&sbx, 0, sizeof(SBufExt)); | ||
| 428 | lj_bufx_set_borrow(L, &sbx, &G(L)->tmpbuf); | ||
| 429 | sbx.depth = LJ_SERIALIZE_DEPTH; | ||
| 430 | w = serialize_put(sbx.w, &sbx, o); | ||
| 431 | return lj_str_new(L, sbx.b, (size_t)(w - sbx.b)); | ||
| 432 | } | ||
| 433 | |||
| 434 | /* Stand-alone decoding, copy-on-write from string. */ | ||
| 435 | void lj_serialize_decode(lua_State *L, TValue *o, GCstr *str) | ||
| 436 | { | ||
| 437 | SBufExt sbx; | ||
| 438 | char *r; | ||
| 439 | memset(&sbx, 0, sizeof(SBufExt)); | ||
| 440 | lj_bufx_set_cow(L, &sbx, strdata(str), str->len); | ||
| 441 | /* No need to set sbx.cowref here. */ | ||
| 442 | r = lj_serialize_get(&sbx, o); | ||
| 443 | if (r != sbx.w) lj_err_caller(L, LJ_ERR_BUFFER_LEFTOV); | ||
| 444 | } | ||
| 445 | |||
| 446 | #if LJ_HASJIT | ||
| 447 | /* Peek into buffer to find the result IRType for specialization purposes. */ | ||
| 448 | LJ_FUNC MSize LJ_FASTCALL lj_serialize_peektype(SBufExt *sbx) | ||
| 449 | { | ||
| 450 | uint32_t tp; | ||
| 451 | if (serialize_ru124(sbx->r, sbx->w, &tp)) { | ||
| 452 | /* This must match the handling of all tags in the decoder above. */ | ||
| 453 | switch (tp) { | ||
| 454 | case SER_TAG_NIL: return IRT_NIL; | ||
| 455 | case SER_TAG_FALSE: return IRT_FALSE; | ||
| 456 | case SER_TAG_TRUE: return IRT_TRUE; | ||
| 457 | case SER_TAG_NULL: case SER_TAG_LIGHTUD32: case SER_TAG_LIGHTUD64: | ||
| 458 | return IRT_LIGHTUD; | ||
| 459 | case SER_TAG_INT: return LJ_DUALNUM ? IRT_INT : IRT_NUM; | ||
| 460 | case SER_TAG_NUM: return IRT_NUM; | ||
| 461 | case SER_TAG_TAB: case SER_TAG_TAB+1: case SER_TAG_TAB+2: | ||
| 462 | case SER_TAG_TAB+3: case SER_TAG_TAB+4: case SER_TAG_TAB+5: | ||
| 463 | return IRT_TAB; | ||
| 464 | case SER_TAG_INT64: case SER_TAG_UINT64: case SER_TAG_COMPLEX: | ||
| 465 | return IRT_CDATA; | ||
| 466 | case SER_TAG_DICT: | ||
| 467 | default: | ||
| 468 | return IRT_STR; | ||
| 469 | } | ||
| 470 | } | ||
| 471 | return IRT_NIL; /* Will fail on actual decode. */ | ||
| 414 | } | 472 | } |
| 473 | #endif | ||
| 415 | 474 | ||
| 416 | #endif | 475 | #endif |
diff --git a/src/lj_serialize.h b/src/lj_serialize.h index ccf1d63d..9bd780ca 100644 --- a/src/lj_serialize.h +++ b/src/lj_serialize.h | |||
| @@ -15,7 +15,12 @@ | |||
| 15 | 15 | ||
| 16 | LJ_FUNC void LJ_FASTCALL lj_serialize_dict_prep(lua_State *L, GCtab *dict); | 16 | LJ_FUNC void LJ_FASTCALL lj_serialize_dict_prep(lua_State *L, GCtab *dict); |
| 17 | LJ_FUNC SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o); | 17 | LJ_FUNC SBufExt * LJ_FASTCALL lj_serialize_put(SBufExt *sbx, cTValue *o); |
| 18 | LJ_FUNC SBufExt * LJ_FASTCALL lj_serialize_get(SBufExt *sbx, TValue *o); | 18 | LJ_FUNC char * LJ_FASTCALL lj_serialize_get(SBufExt *sbx, TValue *o); |
| 19 | LJ_FUNC GCstr * LJ_FASTCALL lj_serialize_encode(lua_State *L, cTValue *o); | ||
| 20 | LJ_FUNC void lj_serialize_decode(lua_State *L, TValue *o, GCstr *str); | ||
| 21 | #if LJ_HASJIT | ||
| 22 | LJ_FUNC MSize LJ_FASTCALL lj_serialize_peektype(SBufExt *sbx); | ||
| 23 | #endif | ||
| 19 | 24 | ||
| 20 | #endif | 25 | #endif |
| 21 | 26 | ||
