aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/jit/dump.lua1
-rw-r--r--src/lj_asm.c32
-rw-r--r--src/lj_ffrecord.c3
-rw-r--r--src/lj_ir.c3
-rw-r--r--src/lj_ir.h7
-rw-r--r--src/lj_ircall.h1
-rw-r--r--src/lj_opt_fold.c8
-rw-r--r--src/lj_record.c3
-rw-r--r--src/lj_str.c8
-rw-r--r--src/lj_str.h1
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
284local function ctlsub(c) 285local 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
1115static void asm_tostr(ASMState *as, IRIns *ir) 1118static 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
762LJFOLD(TOSTR KNUM) 762LJFOLD(TOSTR KNUM any)
763LJFOLDF(kfold_tostr_knum) 763LJFOLDF(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
768LJFOLD(TOSTR KINT) 768LJFOLD(TOSTR KINT any)
769LJFOLDF(kfold_tostr_kint) 769LJFOLDF(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
774LJFOLD(STRTO KGC) 776LJFOLD(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. */
278GCstr * 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);
27LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np); 27LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np);
28LJ_FUNC GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k); 28LJ_FUNC GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k);
29LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnumber(lua_State *L, cTValue *o); 29LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnumber(lua_State *L, cTValue *o);
30LJ_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