diff options
author | Mike Pall <mike> | 2014-04-01 00:30:22 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2014-04-01 00:30:22 +0200 |
commit | 19b69f21d409375ad8362c04186b246c1749fc8e (patch) | |
tree | 485af25c1188317a3c299afb7e703b05cafdc873 /src | |
parent | c735293921724b3d660d2353c08f2ce15887b71d (diff) | |
download | luajit-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.c | 6 | ||||
-rw-r--r-- | src/lj_crecord.c | 61 |
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. */ |
1320 | static void crec_arith_meta(jit_State *J, CTState *cts, RecordFFData *rd) | 1320 | static 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 | ||
1350 | void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd) | 1358 | void 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 | } |