summaryrefslogtreecommitdiff
path: root/src/lj_record.c
diff options
context:
space:
mode:
authorMike Pall <mike>2010-11-18 00:23:24 +0100
committerMike Pall <mike>2010-11-18 00:23:24 +0100
commitba602c9578e01b1d692beddf7e974fa70b6eecf2 (patch)
tree3ec1beecf5205801d9c1048aca92c97b5bafe859 /src/lj_record.c
parent3754a8fe7a820bcfc5e2633d15c648a194dd4144 (diff)
downloadluajit-ba602c9578e01b1d692beddf7e974fa70b6eecf2.tar.gz
luajit-ba602c9578e01b1d692beddf7e974fa70b6eecf2.tar.bz2
luajit-ba602c9578e01b1d692beddf7e974fa70b6eecf2.zip
Add support for __pairs and __ipairs metamethods (from Lua 5.2).
Diffstat (limited to 'src/lj_record.c')
-rw-r--r--src/lj_record.c63
1 files changed, 36 insertions, 27 deletions
diff --git a/src/lj_record.c b/src/lj_record.c
index 734adcf5..4ff208f8 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -1358,7 +1358,7 @@ static void LJ_FASTCALL recff_tonumber(jit_State *J, RecordFFData *rd)
1358 UNUSED(rd); 1358 UNUSED(rd);
1359} 1359}
1360 1360
1361static TValue *recff_tostring_cp(lua_State *L, lua_CFunction dummy, void *ud) 1361static TValue *recff_metacall_cp(lua_State *L, lua_CFunction dummy, void *ud)
1362{ 1362{
1363 jit_State *J = (jit_State *)ud; 1363 jit_State *J = (jit_State *)ud;
1364 rec_tailcall(J, 0, 1); 1364 rec_tailcall(J, 0, 1);
@@ -1366,31 +1366,38 @@ static TValue *recff_tostring_cp(lua_State *L, lua_CFunction dummy, void *ud)
1366 return NULL; 1366 return NULL;
1367} 1367}
1368 1368
1369static int recff_metacall(jit_State *J, RecordFFData *rd, MMS mm)
1370{
1371 RecordIndex ix;
1372 ix.tab = J->base[0];
1373 copyTV(J->L, &ix.tabv, &rd->argv[0]);
1374 if (rec_mm_lookup(J, &ix, mm)) { /* Has metamethod? */
1375 int errcode;
1376 /* Temporarily insert metamethod below object. */
1377 J->base[1] = J->base[0];
1378 J->base[0] = ix.mobj;
1379 copyTV(J->L, &rd->argv[1], &rd->argv[0]);
1380 copyTV(J->L, &rd->argv[0], &ix.mobjv);
1381 /* Need to protect rec_tailcall because it may throw. */
1382 errcode = lj_vm_cpcall(J->L, NULL, J, recff_metacall_cp);
1383 /* Always undo Lua stack changes to avoid confusing the interpreter. */
1384 copyTV(J->L, &rd->argv[0], &rd->argv[1]);
1385 if (errcode)
1386 lj_err_throw(J->L, errcode); /* Propagate errors. */
1387 rd->nres = -1; /* Pending call. */
1388 return 1; /* Tailcalled to metamethod. */
1389 }
1390 return 0;
1391}
1392
1369static void LJ_FASTCALL recff_tostring(jit_State *J, RecordFFData *rd) 1393static void LJ_FASTCALL recff_tostring(jit_State *J, RecordFFData *rd)
1370{ 1394{
1371 TRef tr = J->base[0]; 1395 TRef tr = J->base[0];
1372 if (tref_isstr(tr)) { 1396 if (tref_isstr(tr)) {
1373 /* Ignore __tostring in the string base metatable. */ 1397 /* Ignore __tostring in the string base metatable. */
1374 /* Pass on result in J->base[0]. */ 1398 /* Pass on result in J->base[0]. */
1375 } else { 1399 } else if (!recff_metacall(J, rd, MM_tostring)) {
1376 RecordIndex ix; 1400 if (tref_isnumber(tr)) {
1377 ix.tab = tr;
1378 copyTV(J->L, &ix.tabv, &rd->argv[0]);
1379 if (rec_mm_lookup(J, &ix, MM_tostring)) { /* Has __tostring metamethod? */
1380 int errcode;
1381 /* Temporarily insert metamethod below object. */
1382 J->base[1] = tr;
1383 J->base[0] = ix.mobj;
1384 copyTV(J->L, &rd->argv[1], &rd->argv[0]);
1385 copyTV(J->L, &rd->argv[0], &ix.mobjv);
1386 /* Need to protect rec_tailcall because it may throw. */
1387 errcode = lj_vm_cpcall(J->L, NULL, J, recff_tostring_cp);
1388 /* Always undo Lua stack changes to avoid confusing the interpreter. */
1389 copyTV(J->L, &rd->argv[0], &rd->argv[1]);
1390 if (errcode)
1391 lj_err_throw(J->L, errcode); /* Propagate errors. */
1392 rd->nres = -1; /* Pending call. */
1393 } else if (tref_isnumber(tr)) {
1394 J->base[0] = emitir(IRT(IR_TOSTR, IRT_STR), tr, 0); 1401 J->base[0] = emitir(IRT(IR_TOSTR, IRT_STR), tr, 0);
1395 } else if (tref_ispri(tr)) { 1402 } else if (tref_ispri(tr)) {
1396 J->base[0] = lj_ir_kstr(J, strV(&J->fn->c.upvalue[tref_type(tr)])); 1403 J->base[0] = lj_ir_kstr(J, strV(&J->fn->c.upvalue[tref_type(tr)]));
@@ -1419,13 +1426,15 @@ static void LJ_FASTCALL recff_ipairs_aux(jit_State *J, RecordFFData *rd)
1419 1426
1420static void LJ_FASTCALL recff_ipairs(jit_State *J, RecordFFData *rd) 1427static void LJ_FASTCALL recff_ipairs(jit_State *J, RecordFFData *rd)
1421{ 1428{
1422 TRef tab = J->base[0]; 1429 if (!recff_metacall(J, rd, MM_ipairs)) {
1423 if (tref_istab(tab)) { 1430 TRef tab = J->base[0];
1424 J->base[0] = lj_ir_kfunc(J, funcV(&J->fn->c.upvalue[0])); 1431 if (tref_istab(tab)) {
1425 J->base[1] = tab; 1432 J->base[0] = lj_ir_kfunc(J, funcV(&J->fn->c.upvalue[0]));
1426 J->base[2] = lj_ir_kint(J, 0); 1433 J->base[1] = tab;
1427 rd->nres = 3; 1434 J->base[2] = lj_ir_kint(J, 0);
1428 } /* else: Interpreter will throw. */ 1435 rd->nres = 3;
1436 } /* else: Interpreter will throw. */
1437 }
1429} 1438}
1430 1439
1431static void LJ_FASTCALL recff_pcall(jit_State *J, RecordFFData *rd) 1440static void LJ_FASTCALL recff_pcall(jit_State *J, RecordFFData *rd)