aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib_base.c2
-rw-r--r--src/lj_record.c42
2 files changed, 43 insertions, 1 deletions
diff --git a/src/lib_base.c b/src/lib_base.c
index e5f71d9c..0717ea86 100644
--- a/src/lib_base.c
+++ b/src/lib_base.c
@@ -163,7 +163,7 @@ LJLIB_CF(unpack)
163 return n; 163 return n;
164} 164}
165 165
166LJLIB_CF(select) 166LJLIB_CF(select) LJLIB_REC(.)
167{ 167{
168 int32_t n = (int32_t)(L->top - L->base); 168 int32_t n = (int32_t)(L->top - L->base);
169 if (n >= 1 && tvisstr(L->base) && *strVdata(L->base) == '#') { 169 if (n >= 1 && tvisstr(L->base) && *strVdata(L->base) == '#') {
diff --git a/src/lj_record.c b/src/lj_record.c
index 739279ad..5c998adf 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -1293,6 +1293,48 @@ static void LJ_FASTCALL recff_rawequal(jit_State *J, RecordFFData *rd)
1293 } /* else: Interpreter will throw. */ 1293 } /* else: Interpreter will throw. */
1294} 1294}
1295 1295
1296/* Determine mode of select() call. */
1297static int32_t select_mode(jit_State *J, TRef tr, TValue *tv)
1298{
1299 if (tref_isstr(tr) && *strVdata(tv) == '#') { /* select('#', ...) */
1300 if (strV(tv)->len == 1) {
1301 emitir(IRT(IR_EQ, IRT_STR), tr, lj_ir_kstr(J, strV(tv)));
1302 } else {
1303 TRef trptr = emitir(IRT(IR_STRREF, IRT_PTR), tr, 0);
1304 TRef trchar = emitir(IRT(IR_XLOAD, IRT_U8), trptr, IRXLOAD_READONLY);
1305 emitir(IRT(IR_EQ, IRT_INT), trchar, lj_ir_kint(J, '#'));
1306 }
1307 return 0;
1308 } else { /* select(n, ...) */
1309 int32_t start = argv2int(J, tv);
1310 if (start == 0) lj_trace_err(J, LJ_TRERR_BADTYPE); /* A bit misleading. */
1311 return start;
1312 }
1313}
1314
1315static void LJ_FASTCALL recff_select(jit_State *J, RecordFFData *rd)
1316{
1317 TRef tr = J->base[0];
1318 if (tr) {
1319 ptrdiff_t start = select_mode(J, tr, &rd->argv[0]);
1320 if (start == 0) { /* select('#', ...) */
1321 J->base[0] = lj_ir_kint(J, J->maxslot - 1);
1322 } else if (tref_isk(tr)) { /* select(k, ...) */
1323 ptrdiff_t n = (ptrdiff_t)J->maxslot;
1324 if (start < 0) start += n;
1325 else if (start > n) start = n;
1326 rd->nres = n - start;
1327 if (start >= 1) {
1328 ptrdiff_t i;
1329 for (i = 0; i < n - start; i++)
1330 J->base[i] = J->base[start+i];
1331 } /* else: Interpreter will throw. */
1332 } else {
1333 recff_nyiu(J);
1334 }
1335 } /* else: Interpreter will throw. */
1336}
1337
1296static void LJ_FASTCALL recff_tonumber(jit_State *J, RecordFFData *rd) 1338static void LJ_FASTCALL recff_tonumber(jit_State *J, RecordFFData *rd)
1297{ 1339{
1298 TRef tr = J->base[0]; 1340 TRef tr = J->base[0];