diff options
Diffstat (limited to 'src/lj_ffrecord.c')
-rw-r--r-- | src/lj_ffrecord.c | 345 |
1 files changed, 335 insertions, 10 deletions
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) |