aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2014-04-01 00:30:22 +0200
committerMike Pall <mike>2014-04-01 00:30:22 +0200
commit19b69f21d409375ad8362c04186b246c1749fc8e (patch)
tree485af25c1188317a3c299afb7e703b05cafdc873 /src
parentc735293921724b3d660d2353c08f2ce15887b71d (diff)
downloadluajit-19b69f21d409375ad8362c04186b246c1749fc8e.tar.gz
luajit-19b69f21d409375ad8362c04186b246c1749fc8e.tar.bz2
luajit-19b69f21d409375ad8362c04186b246c1749fc8e.zip
FFI: Allow non-scalar cdata to be compared for equality by address.
Diffstat (limited to 'src')
-rw-r--r--src/lj_carith.c6
-rw-r--r--src/lj_crecord.c61
2 files changed, 38 insertions, 29 deletions
diff --git a/src/lj_carith.c b/src/lj_carith.c
index 9f94091d..92fe5597 100644
--- a/src/lj_carith.c
+++ b/src/lj_carith.c
@@ -73,7 +73,7 @@ static int carith_checkarg(lua_State *L, CTState *cts, CDArith *ca)
73 ok = 1; 73 ok = 1;
74 } else { 74 } else {
75 ca->ct[1-i] = ct; /* Use enum to improve error message. */ 75 ca->ct[1-i] = ct; /* Use enum to improve error message. */
76 ca->p[1-i] = NULL; 76 ca->p[1-i] = (void *)(intptr_t)1; /* To make it unequal. */
77 break; 77 break;
78 } 78 }
79 } 79 }
@@ -234,7 +234,9 @@ static int lj_carith_meta(lua_State *L, CTState *cts, CDArith *ca, MMS mm)
234 const char *repr[2]; 234 const char *repr[2];
235 int i, isenum = -1, isstr = -1; 235 int i, isenum = -1, isstr = -1;
236 if (mm == MM_eq) { /* Equality checks never raise an error. */ 236 if (mm == MM_eq) { /* Equality checks never raise an error. */
237 setboolV(L->top-1, 0); 237 int eq = ca->p[0] == ca->p[1];
238 setboolV(L->top-1, eq);
239 setboolV(&G(L)->tmptv2, eq); /* Remember for trace recorder. */
238 return 1; 240 return 1;
239 } 241 }
240 for (i = 0; i < 2; i++) { 242 for (i = 0; i < 2; i++) {
diff --git a/src/lj_crecord.c b/src/lj_crecord.c
index da9013f0..71f3d069 100644
--- a/src/lj_crecord.c
+++ b/src/lj_crecord.c
@@ -1317,7 +1317,8 @@ static TRef crec_arith_ptr(jit_State *J, TRef *sp, CType **s, MMS mm)
1317} 1317}
1318 1318
1319/* Record ctype arithmetic metamethods. */ 1319/* Record ctype arithmetic metamethods. */
1320static void crec_arith_meta(jit_State *J, CTState *cts, RecordFFData *rd) 1320static TRef crec_arith_meta(jit_State *J, TRef *sp, CTState *cts,
1321 RecordFFData *rd)
1321{ 1322{
1322 cTValue *tv = NULL; 1323 cTValue *tv = NULL;
1323 if (J->base[0]) { 1324 if (J->base[0]) {
@@ -1338,13 +1339,20 @@ static void crec_arith_meta(jit_State *J, CTState *cts, RecordFFData *rd)
1338 if (tvisfunc(tv)) { 1339 if (tvisfunc(tv)) {
1339 J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME; 1340 J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME;
1340 rd->nres = -1; /* Pending tailcall. */ 1341 rd->nres = -1; /* Pending tailcall. */
1341 return; 1342 return 0;
1342 } /* NYI: non-function metamethods. */ 1343 } /* NYI: non-function metamethods. */
1343 } else if ((MMS)rd->data == MM_eq) { 1344 } else if ((MMS)rd->data == MM_eq) { /* Fallback cdata pointer comparison. */
1344 J->base[0] = TREF_FALSE; 1345 if (sp[0] && sp[1]) {
1345 return; 1346 /* Assume true comparison. Fixup and emit pending guard later. */
1347 lj_ir_set(J, IRTG(IR_EQ, IRT_PTR), sp[0], sp[1]);
1348 J->postproc = LJ_POST_FIXGUARD;
1349 return TREF_TRUE;
1350 } else {
1351 return TREF_FALSE;
1352 }
1346 } 1353 }
1347 lj_trace_err(J, LJ_TRERR_BADTYPE); 1354 lj_trace_err(J, LJ_TRERR_BADTYPE);
1355 return 0;
1348} 1356}
1349 1357
1350void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd) 1358void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
@@ -1357,7 +1365,7 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
1357 TRef tr = J->base[i]; 1365 TRef tr = J->base[i];
1358 CType *ct = ctype_get(cts, CTID_DOUBLE); 1366 CType *ct = ctype_get(cts, CTID_DOUBLE);
1359 if (!tr) { 1367 if (!tr) {
1360 goto trymeta; 1368 lj_trace_err(J, LJ_TRERR_BADTYPE);
1361 } else if (tref_iscdata(tr)) { 1369 } else if (tref_iscdata(tr)) {
1362 CTypeID id = argv2cdata(J, tr, &rd->argv[i])->ctypeid; 1370 CTypeID id = argv2cdata(J, tr, &rd->argv[i])->ctypeid;
1363 IRType t; 1371 IRType t;
@@ -1387,11 +1395,12 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
1387 } 1395 }
1388 if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct); 1396 if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct);
1389 if (ctype_isnum(ct->info)) { 1397 if (ctype_isnum(ct->info)) {
1390 if (t == IRT_CDATA) goto trymeta; 1398 if (t == IRT_CDATA) {
1391 if (t == IRT_I64 || t == IRT_U64) lj_needsplit(J); 1399 tr = 0;
1392 tr = emitir(IRT(IR_XLOAD, t), tr, 0); 1400 } else {
1393 } else if (!(ctype_isptr(ct->info) || ctype_isrefarray(ct->info))) { 1401 if (t == IRT_I64 || t == IRT_U64) lj_needsplit(J);
1394 goto trymeta; 1402 tr = emitir(IRT(IR_XLOAD, t), tr, 0);
1403 }
1395 } 1404 }
1396 } else if (tref_isnil(tr)) { 1405 } else if (tref_isnil(tr)) {
1397 tr = lj_ir_kptr(J, NULL); 1406 tr = lj_ir_kptr(J, NULL);
@@ -1414,7 +1423,7 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
1414 } /* else: interpreter will throw. */ 1423 } /* else: interpreter will throw. */
1415 } /* else: interpreter will throw. */ 1424 } /* else: interpreter will throw. */
1416 } else if (!tref_isnum(tr)) { 1425 } else if (!tref_isnum(tr)) {
1417 goto trymeta; 1426 tr = 0;
1418 } 1427 }
1419 ok: 1428 ok:
1420 s[i] = ct; 1429 s[i] = ct;
@@ -1422,22 +1431,20 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
1422 } 1431 }
1423 { 1432 {
1424 TRef tr; 1433 TRef tr;
1425 if ((tr = crec_arith_int64(J, sp, s, (MMS)rd->data)) || 1434 if (!(tr = crec_arith_int64(J, sp, s, (MMS)rd->data)) &&
1426 (tr = crec_arith_ptr(J, sp, s, (MMS)rd->data))) { 1435 !(tr = crec_arith_ptr(J, sp, s, (MMS)rd->data)) &&
1427 J->base[0] = tr; 1436 !(tr = crec_arith_meta(J, sp, cts, rd)))
1428 /* Fixup cdata comparisons, too. Avoids some cdata escapes. */ 1437 return;
1429 if (J->postproc == LJ_POST_FIXGUARD && frame_iscont(J->L->base-1) && 1438 J->base[0] = tr;
1430 !irt_isguard(J->guardemit)) { 1439 /* Fixup cdata comparisons, too. Avoids some cdata escapes. */
1431 const BCIns *pc = frame_contpc(J->L->base-1) - 1; 1440 if (J->postproc == LJ_POST_FIXGUARD && frame_iscont(J->L->base-1) &&
1432 if (bc_op(*pc) <= BC_ISNEP) { 1441 !irt_isguard(J->guardemit)) {
1433 setframe_pc(&J2G(J)->tmptv, pc); 1442 const BCIns *pc = frame_contpc(J->L->base-1) - 1;
1434 J2G(J)->tmptv.u32.lo = ((tref_istrue(tr) ^ bc_op(*pc)) & 1); 1443 if (bc_op(*pc) <= BC_ISNEP) {
1435 J->postproc = LJ_POST_FIXCOMP; 1444 setframe_pc(&J2G(J)->tmptv, pc);
1436 } 1445 J2G(J)->tmptv.u32.lo = ((tref_istrue(tr) ^ bc_op(*pc)) & 1);
1446 J->postproc = LJ_POST_FIXCOMP;
1437 } 1447 }
1438 } else {
1439 trymeta:
1440 crec_arith_meta(J, cts, rd);
1441 } 1448 }
1442 } 1449 }
1443} 1450}