diff options
-rw-r--r-- | src/jit/dump.lua | 1 | ||||
-rw-r--r-- | src/lj_asm.c | 32 | ||||
-rw-r--r-- | src/lj_ffrecord.c | 3 | ||||
-rw-r--r-- | src/lj_ir.c | 3 | ||||
-rw-r--r-- | src/lj_ir.h | 7 | ||||
-rw-r--r-- | src/lj_ircall.h | 1 | ||||
-rw-r--r-- | src/lj_opt_fold.c | 8 | ||||
-rw-r--r-- | src/lj_record.c | 3 | ||||
-rw-r--r-- | src/lj_str.c | 8 | ||||
-rw-r--r-- | src/lj_str.h | 1 |
10 files changed, 47 insertions, 20 deletions
diff --git a/src/jit/dump.lua b/src/jit/dump.lua index c025a239..2a7d64e4 100644 --- a/src/jit/dump.lua +++ b/src/jit/dump.lua | |||
@@ -279,6 +279,7 @@ local litname = { | |||
279 | ["FREF "] = vmdef.irfield, | 279 | ["FREF "] = vmdef.irfield, |
280 | ["FPMATH"] = vmdef.irfpm, | 280 | ["FPMATH"] = vmdef.irfpm, |
281 | ["BUFHDR"] = { [0] = "RESET", "APPEND" }, | 281 | ["BUFHDR"] = { [0] = "RESET", "APPEND" }, |
282 | ["TOSTR "] = { [0] = "INT", "NUM", "CHAR" }, | ||
282 | } | 283 | } |
283 | 284 | ||
284 | local function ctlsub(c) | 285 | local function ctlsub(c) |
diff --git a/src/lj_asm.c b/src/lj_asm.c index e847b8c9..6ff32940 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c | |||
@@ -1070,23 +1070,26 @@ static void asm_bufput(ASMState *as, IRIns *ir) | |||
1070 | GCstr *s = ir_kstr(irs); | 1070 | GCstr *s = ir_kstr(irs); |
1071 | if (s->len == 1) { /* Optimize put of single-char string constant. */ | 1071 | if (s->len == 1) { /* Optimize put of single-char string constant. */ |
1072 | kchar = strdata(s)[0]; | 1072 | kchar = strdata(s)[0]; |
1073 | ci = &lj_ir_callinfo[IRCALL_lj_buf_putchar]; | ||
1074 | args[1] = ASMREF_TMP1; /* int, truncated to char */ | 1073 | args[1] = ASMREF_TMP1; /* int, truncated to char */ |
1074 | ci = &lj_ir_callinfo[IRCALL_lj_buf_putchar]; | ||
1075 | } | 1075 | } |
1076 | } else if (mayfuse(as, ir->op2) && ra_noreg(irs->r)) { | 1076 | } else if (mayfuse(as, ir->op2) && ra_noreg(irs->r)) { |
1077 | if (irs->o == IR_TOSTR) { /* Fuse number to string conversions. */ | 1077 | if (irs->o == IR_TOSTR) { /* Fuse number to string conversions. */ |
1078 | if (LJ_SOFTFP ? (irs+1)->o == IR_HIOP : irt_isnum(IR(irs->op1)->t)) { | 1078 | if (irs->op2 == IRTOSTR_NUM) { |
1079 | ci = &lj_ir_callinfo[IRCALL_lj_buf_putnum]; | ||
1080 | args[1] = ASMREF_TMP1; /* TValue * */ | 1079 | args[1] = ASMREF_TMP1; /* TValue * */ |
1080 | ci = &lj_ir_callinfo[IRCALL_lj_buf_putnum]; | ||
1081 | } else { | 1081 | } else { |
1082 | lua_assert(irt_isinteger(IR(irs->op1)->t)); | 1082 | lua_assert(irt_isinteger(IR(irs->op1)->t)); |
1083 | ci = &lj_ir_callinfo[IRCALL_lj_buf_putint]; | ||
1084 | args[1] = irs->op1; /* int */ | 1083 | args[1] = irs->op1; /* int */ |
1084 | if (irs->op2 == IRTOSTR_INT) | ||
1085 | ci = &lj_ir_callinfo[IRCALL_lj_buf_putint]; | ||
1086 | else | ||
1087 | ci = &lj_ir_callinfo[IRCALL_lj_buf_putchar]; | ||
1085 | } | 1088 | } |
1086 | } else if (irs->o == IR_SNEW) { /* Fuse string allocation. */ | 1089 | } else if (irs->o == IR_SNEW) { /* Fuse string allocation. */ |
1087 | ci = &lj_ir_callinfo[IRCALL_lj_buf_putmem]; | ||
1088 | args[1] = irs->op1; /* const void * */ | 1090 | args[1] = irs->op1; /* const void * */ |
1089 | args[2] = irs->op2; /* MSize */ | 1091 | args[2] = irs->op2; /* MSize */ |
1092 | ci = &lj_ir_callinfo[IRCALL_lj_buf_putmem]; | ||
1090 | } | 1093 | } |
1091 | } | 1094 | } |
1092 | asm_setupresult(as, ir, ci); /* SBuf * */ | 1095 | asm_setupresult(as, ir, ci); /* SBuf * */ |
@@ -1114,21 +1117,24 @@ static void asm_bufstr(ASMState *as, IRIns *ir) | |||
1114 | 1117 | ||
1115 | static void asm_tostr(ASMState *as, IRIns *ir) | 1118 | static void asm_tostr(ASMState *as, IRIns *ir) |
1116 | { | 1119 | { |
1120 | const CCallInfo *ci; | ||
1117 | IRRef args[2]; | 1121 | IRRef args[2]; |
1118 | args[0] = ASMREF_L; | 1122 | args[0] = ASMREF_L; |
1119 | as->gcsteps++; | 1123 | as->gcsteps++; |
1120 | if (irt_isnum(IR(ir->op1)->t) || (LJ_SOFTFP && (ir+1)->o == IR_HIOP)) { | 1124 | if (ir->op2 == IRTOSTR_NUM) { |
1121 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_fromnum]; | ||
1122 | args[1] = ASMREF_TMP1; /* const lua_Number * */ | 1125 | args[1] = ASMREF_TMP1; /* const lua_Number * */ |
1123 | asm_setupresult(as, ir, ci); /* GCstr * */ | 1126 | ci = &lj_ir_callinfo[IRCALL_lj_str_fromnum]; |
1124 | asm_gencall(as, ci, args); | ||
1125 | asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op1); | ||
1126 | } else { | 1127 | } else { |
1127 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_fromint]; | ||
1128 | args[1] = ir->op1; /* int32_t k */ | 1128 | args[1] = ir->op1; /* int32_t k */ |
1129 | asm_setupresult(as, ir, ci); /* GCstr * */ | 1129 | if (ir->op2 == IRTOSTR_INT) |
1130 | asm_gencall(as, ci, args); | 1130 | ci = &lj_ir_callinfo[IRCALL_lj_str_fromint]; |
1131 | else | ||
1132 | ci = &lj_ir_callinfo[IRCALL_lj_str_fromchar]; | ||
1131 | } | 1133 | } |
1134 | asm_setupresult(as, ir, ci); /* GCstr * */ | ||
1135 | asm_gencall(as, ci, args); | ||
1136 | if (ir->op2 == IRTOSTR_NUM) | ||
1137 | asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op1); | ||
1132 | } | 1138 | } |
1133 | 1139 | ||
1134 | #if LJ_32 && LJ_HASFFI && !LJ_SOFTFP && !LJ_TARGET_X86 | 1140 | #if LJ_32 && LJ_HASFFI && !LJ_SOFTFP && !LJ_TARGET_X86 |
diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c index 32346d22..929dbb55 100644 --- a/src/lj_ffrecord.c +++ b/src/lj_ffrecord.c | |||
@@ -335,7 +335,8 @@ static void LJ_FASTCALL recff_tostring(jit_State *J, RecordFFData *rd) | |||
335 | /* Pass on result in J->base[0]. */ | 335 | /* Pass on result in J->base[0]. */ |
336 | } else if (!recff_metacall(J, rd, MM_tostring)) { | 336 | } else if (!recff_metacall(J, rd, MM_tostring)) { |
337 | if (tref_isnumber(tr)) { | 337 | if (tref_isnumber(tr)) { |
338 | J->base[0] = emitir(IRT(IR_TOSTR, IRT_STR), tr, 0); | 338 | J->base[0] = emitir(IRT(IR_TOSTR, IRT_STR), tr, |
339 | tref_isnum(tr) ? IRTOSTR_NUM : IRTOSTR_INT); | ||
339 | } else if (tref_ispri(tr)) { | 340 | } else if (tref_ispri(tr)) { |
340 | J->base[0] = lj_ir_kstr(J, strV(&J->fn->c.upvalue[tref_type(tr)])); | 341 | J->base[0] = lj_ir_kstr(J, strV(&J->fn->c.upvalue[tref_type(tr)])); |
341 | } else { | 342 | } else { |
diff --git a/src/lj_ir.c b/src/lj_ir.c index f1e1959f..0ac9d0e6 100644 --- a/src/lj_ir.c +++ b/src/lj_ir.c | |||
@@ -444,7 +444,8 @@ TRef LJ_FASTCALL lj_ir_tostr(jit_State *J, TRef tr) | |||
444 | if (!tref_isstr(tr)) { | 444 | if (!tref_isstr(tr)) { |
445 | if (!tref_isnumber(tr)) | 445 | if (!tref_isnumber(tr)) |
446 | lj_trace_err(J, LJ_TRERR_BADTYPE); | 446 | lj_trace_err(J, LJ_TRERR_BADTYPE); |
447 | tr = emitir(IRT(IR_TOSTR, IRT_STR), tr, 0); | 447 | tr = emitir(IRT(IR_TOSTR, IRT_STR), tr, |
448 | tref_isnum(tr) ? IRTOSTR_NUM : IRTOSTR_INT); | ||
448 | } | 449 | } |
449 | return tr; | 450 | return tr; |
450 | } | 451 | } |
diff --git a/src/lj_ir.h b/src/lj_ir.h index 0cbd8b55..7ab8ab12 100644 --- a/src/lj_ir.h +++ b/src/lj_ir.h | |||
@@ -133,7 +133,7 @@ | |||
133 | /* Type conversions. */ \ | 133 | /* Type conversions. */ \ |
134 | _(CONV, NW, ref, lit) \ | 134 | _(CONV, NW, ref, lit) \ |
135 | _(TOBIT, N , ref, ref) \ | 135 | _(TOBIT, N , ref, ref) \ |
136 | _(TOSTR, N , ref, ___) \ | 136 | _(TOSTR, N , ref, lit) \ |
137 | _(STRTO, N , ref, ___) \ | 137 | _(STRTO, N , ref, ___) \ |
138 | \ | 138 | \ |
139 | /* Calls. */ \ | 139 | /* Calls. */ \ |
@@ -246,6 +246,11 @@ IRFLDEF(FLENUM) | |||
246 | #define IRCONV_INDEX (2<<IRCONV_CSH) /* Check + special backprop rules. */ | 246 | #define IRCONV_INDEX (2<<IRCONV_CSH) /* Check + special backprop rules. */ |
247 | #define IRCONV_CHECK (3<<IRCONV_CSH) /* Number checked for integerness. */ | 247 | #define IRCONV_CHECK (3<<IRCONV_CSH) /* Number checked for integerness. */ |
248 | 248 | ||
249 | /* TOSTR mode, stored in op2. */ | ||
250 | #define IRTOSTR_INT 0 /* Convert integer to string. */ | ||
251 | #define IRTOSTR_NUM 1 /* Convert number to string. */ | ||
252 | #define IRTOSTR_CHAR 2 /* Convert char value to string. */ | ||
253 | |||
249 | /* -- IR operands --------------------------------------------------------- */ | 254 | /* -- IR operands --------------------------------------------------------- */ |
250 | 255 | ||
251 | /* IR operand mode (2 bit). */ | 256 | /* IR operand mode (2 bit). */ |
diff --git a/src/lj_ircall.h b/src/lj_ircall.h index 46bb54fe..456f89ac 100644 --- a/src/lj_ircall.h +++ b/src/lj_ircall.h | |||
@@ -105,6 +105,7 @@ typedef struct CCallInfo { | |||
105 | _(ANY, lj_strscan_num, 2, FN, INT, 0) \ | 105 | _(ANY, lj_strscan_num, 2, FN, INT, 0) \ |
106 | _(ANY, lj_str_fromint, 2, FN, STR, CCI_L) \ | 106 | _(ANY, lj_str_fromint, 2, FN, STR, CCI_L) \ |
107 | _(ANY, lj_str_fromnum, 2, FN, STR, CCI_L) \ | 107 | _(ANY, lj_str_fromnum, 2, FN, STR, CCI_L) \ |
108 | _(ANY, lj_str_fromchar, 2, FN, STR, CCI_L) \ | ||
108 | _(ANY, lj_buf_putmem, 3, S, P32, 0) \ | 109 | _(ANY, lj_buf_putmem, 3, S, P32, 0) \ |
109 | _(ANY, lj_buf_putstr, 2, FS, P32, 0) \ | 110 | _(ANY, lj_buf_putstr, 2, FS, P32, 0) \ |
110 | _(ANY, lj_buf_putchar, 2, FS, P32, 0) \ | 111 | _(ANY, lj_buf_putchar, 2, FS, P32, 0) \ |
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c index e3194f76..06e0e783 100644 --- a/src/lj_opt_fold.c +++ b/src/lj_opt_fold.c | |||
@@ -759,16 +759,18 @@ LJFOLDF(kfold_conv_knum_u64_num) | |||
759 | return INT64FOLD(lj_num2u64(knumleft)); | 759 | return INT64FOLD(lj_num2u64(knumleft)); |
760 | } | 760 | } |
761 | 761 | ||
762 | LJFOLD(TOSTR KNUM) | 762 | LJFOLD(TOSTR KNUM any) |
763 | LJFOLDF(kfold_tostr_knum) | 763 | LJFOLDF(kfold_tostr_knum) |
764 | { | 764 | { |
765 | return lj_ir_kstr(J, lj_str_fromnum(J->L, &knumleft)); | 765 | return lj_ir_kstr(J, lj_str_fromnum(J->L, &knumleft)); |
766 | } | 766 | } |
767 | 767 | ||
768 | LJFOLD(TOSTR KINT) | 768 | LJFOLD(TOSTR KINT any) |
769 | LJFOLDF(kfold_tostr_kint) | 769 | LJFOLDF(kfold_tostr_kint) |
770 | { | 770 | { |
771 | return lj_ir_kstr(J, lj_str_fromint(J->L, fleft->i)); | 771 | return lj_ir_kstr(J, fins->op2 == IRTOSTR_INT ? |
772 | lj_str_fromint(J->L, fleft->i) : | ||
773 | lj_str_fromchar(J->L, fleft->i)); | ||
772 | } | 774 | } |
773 | 775 | ||
774 | LJFOLD(STRTO KGC) | 776 | LJFOLD(STRTO KGC) |
diff --git a/src/lj_record.c b/src/lj_record.c index bafb6ff7..1beaa75f 100644 --- a/src/lj_record.c +++ b/src/lj_record.c | |||
@@ -1611,7 +1611,8 @@ static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot) | |||
1611 | /* First convert numbers to strings. */ | 1611 | /* First convert numbers to strings. */ |
1612 | for (trp = top; trp >= base; trp--) { | 1612 | for (trp = top; trp >= base; trp--) { |
1613 | if (tref_isnumber(*trp)) | 1613 | if (tref_isnumber(*trp)) |
1614 | *trp = emitir(IRT(IR_TOSTR, IRT_STR), *trp, 0); | 1614 | *trp = emitir(IRT(IR_TOSTR, IRT_STR), *trp, |
1615 | tref_isnum(*trp) ? IRTOSTR_NUM : IRTOSTR_INT); | ||
1615 | else if (!tref_isstr(*trp)) | 1616 | else if (!tref_isstr(*trp)) |
1616 | break; | 1617 | break; |
1617 | } | 1618 | } |
diff --git a/src/lj_str.c b/src/lj_str.c index a0080e31..675213d7 100644 --- a/src/lj_str.c +++ b/src/lj_str.c | |||
@@ -274,6 +274,14 @@ GCstr * LJ_FASTCALL lj_str_fromnumber(lua_State *L, cTValue *o) | |||
274 | return tvisint(o) ? lj_str_fromint(L, intV(o)) : lj_str_fromnum(L, &o->n); | 274 | return tvisint(o) ? lj_str_fromint(L, intV(o)) : lj_str_fromnum(L, &o->n); |
275 | } | 275 | } |
276 | 276 | ||
277 | /* Convert char value to string. */ | ||
278 | GCstr * LJ_FASTCALL lj_str_fromchar(lua_State *L, int c) | ||
279 | { | ||
280 | char buf[1]; | ||
281 | buf[0] = c; | ||
282 | return lj_str_new(L, buf, 1); | ||
283 | } | ||
284 | |||
277 | /* -- String formatting --------------------------------------------------- */ | 285 | /* -- String formatting --------------------------------------------------- */ |
278 | 286 | ||
279 | /* Push formatted message as a string object to Lua stack. va_list variant. */ | 287 | /* Push formatted message as a string object to Lua stack. va_list variant. */ |
diff --git a/src/lj_str.h b/src/lj_str.h index 61666a2a..bf508d3b 100644 --- a/src/lj_str.h +++ b/src/lj_str.h | |||
@@ -27,6 +27,7 @@ LJ_FUNC const char *lj_str_buftv(char *buf, cTValue *o, MSize *lenp); | |||
27 | LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np); | 27 | LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np); |
28 | LJ_FUNC GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k); | 28 | LJ_FUNC GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k); |
29 | LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnumber(lua_State *L, cTValue *o); | 29 | LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnumber(lua_State *L, cTValue *o); |
30 | LJ_FUNC GCstr * LJ_FASTCALL lj_str_fromchar(lua_State *L, int c); | ||
30 | 31 | ||
31 | #define LJ_STR_INTBUF (1+10) | 32 | #define LJ_STR_INTBUF (1+10) |
32 | #define LJ_STR_NUMBUF LUAI_MAXNUMBER2STR | 33 | #define LJ_STR_NUMBUF LUAI_MAXNUMBER2STR |