summaryrefslogtreecommitdiff
path: root/src/lj_crecord.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_crecord.c')
-rw-r--r--src/lj_crecord.c153
1 files changed, 121 insertions, 32 deletions
diff --git a/src/lj_crecord.c b/src/lj_crecord.c
index 0c4f5ca4..04c962d5 100644
--- a/src/lj_crecord.c
+++ b/src/lj_crecord.c
@@ -22,6 +22,7 @@
22#include "lj_jit.h" 22#include "lj_jit.h"
23#include "lj_iropt.h" 23#include "lj_iropt.h"
24#include "lj_trace.h" 24#include "lj_trace.h"
25#include "lj_record.h"
25#include "lj_ffrecord.h" 26#include "lj_ffrecord.h"
26#include "lj_crecord.h" 27#include "lj_crecord.h"
27#include "lj_dispatch.h" 28#include "lj_dispatch.h"
@@ -459,6 +460,41 @@ static TRef crec_reassoc_ofs(jit_State *J, TRef tr, ptrdiff_t *ofsp, MSize sz)
459 return tr; 460 return tr;
460} 461}
461 462
463/* Record ctype __index/__newindex metamethods. */
464static void crec_index_meta(jit_State *J, CTState *cts, CType *ct,
465 RecordFFData *rd)
466{
467 CTypeID id = ctype_typeid(cts, ct);
468 cTValue *tv = lj_ctype_meta(cts, id, rd->data ? MM_newindex : MM_index);
469 if (!tv)
470 lj_trace_err(J, LJ_TRERR_BADTYPE);
471 if (tvisfunc(tv)) {
472 J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME;
473 rd->nres = -1; /* Pending tailcall. */
474 } else if (rd->data == 0 && tvistab(tv) && tref_isstr(J->base[1])) {
475 /* Specialize to result of __index lookup. */
476 cTValue *o = lj_tab_get(J->L, tabV(tv), &rd->argv[1]);
477 IRType t = itype2irt(o);
478 if (tvisgcv(o))
479 J->base[0] = lj_ir_kgc(J, gcV(o), t);
480 else if (tvisint(o))
481 J->base[0] = lj_ir_kint(J, intV(o));
482 else if (tvisnum(o))
483 J->base[0] = lj_ir_knumint(J, numV(o));
484 else if (tvisbool(o))
485 J->base[0] = TREF_PRI(t);
486 else
487 lj_trace_err(J, LJ_TRERR_BADTYPE);
488 /* Always specialize to the key. */
489 emitir(IRTG(IR_EQ, IRT_STR), J->base[1], lj_ir_kstr(J, strV(&rd->argv[1])));
490 } else {
491 /* NYI: resolving of non-function metamethods. */
492 /* NYI: non-string keys for __index table. */
493 /* NYI: stores to __newindex table. */
494 lj_trace_err(J, LJ_TRERR_BADTYPE);
495 }
496}
497
462void LJ_FASTCALL recff_cdata_index(jit_State *J, RecordFFData *rd) 498void LJ_FASTCALL recff_cdata_index(jit_State *J, RecordFFData *rd)
463{ 499{
464 TRef idx, ptr = J->base[0]; 500 TRef idx, ptr = J->base[0];
@@ -477,12 +513,13 @@ void LJ_FASTCALL recff_cdata_index(jit_State *J, RecordFFData *rd)
477 ptr = crec_reassoc_ofs(J, ptr, &ofs, 1); 513 ptr = crec_reassoc_ofs(J, ptr, &ofs, 1);
478 } 514 }
479 515
516again:
480 idx = J->base[1]; 517 idx = J->base[1];
481 if (tref_isnumber(idx)) { 518 if (tref_isnumber(idx)) {
482 idx = lj_opt_narrow_cindex(J, idx); 519 idx = lj_opt_narrow_cindex(J, idx);
483 integer_key:
484 if (ctype_ispointer(ct->info)) { 520 if (ctype_ispointer(ct->info)) {
485 CTSize sz; 521 CTSize sz;
522 integer_key:
486 if ((ct->info & CTF_COMPLEX)) 523 if ((ct->info & CTF_COMPLEX))
487 idx = emitir(IRT(IR_BAND, IRT_INTP), idx, lj_ir_kintp(J, 1)); 524 idx = emitir(IRT(IR_BAND, IRT_INTP), idx, lj_ir_kintp(J, 1));
488 sz = lj_ctype_size(cts, (sid = ctype_cid(ct->info))); 525 sz = lj_ctype_size(cts, (sid = ctype_cid(ct->info)));
@@ -495,7 +532,8 @@ void LJ_FASTCALL recff_cdata_index(jit_State *J, RecordFFData *rd)
495 CType *ctk = ctype_raw(cts, cdk->typeid); 532 CType *ctk = ctype_raw(cts, cdk->typeid);
496 IRType t; 533 IRType t;
497 if (ctype_isenum(ctk->info)) ctk = ctype_child(cts, ctk); 534 if (ctype_isenum(ctk->info)) ctk = ctype_child(cts, ctk);
498 if (ctype_isinteger(ctk->info) && (t = crec_ct2irt(ctk)) != IRT_CDATA) { 535 if (ctype_ispointer(ct->info) &&
536 ctype_isinteger(ctk->info) && (t = crec_ct2irt(ctk)) != IRT_CDATA) {
499 if (ctk->size == 8) { 537 if (ctk->size == 8) {
500 idx = emitir(IRT(IR_FLOAD, t), idx, IRFL_CDATA_INT64); 538 idx = emitir(IRT(IR_FLOAD, t), idx, IRFL_CDATA_INT64);
501 } else { 539 } else {
@@ -513,22 +551,15 @@ void LJ_FASTCALL recff_cdata_index(jit_State *J, RecordFFData *rd)
513 } 551 }
514 } else if (tref_isstr(idx)) { 552 } else if (tref_isstr(idx)) {
515 GCstr *name = strV(&rd->argv[1]); 553 GCstr *name = strV(&rd->argv[1]);
516 /* Always specialize to the field name. */
517 emitir(IRTG(IR_EQ, IRT_STR), idx, lj_ir_kstr(J, name));
518 if (cd->typeid == CTID_CTYPEID) 554 if (cd->typeid == CTID_CTYPEID)
519 ct = ctype_raw(cts, crec_constructor(J, cd, ptr)); 555 ct = ctype_raw(cts, crec_constructor(J, cd, ptr));
520 if (ctype_isptr(ct->info)) { /* Automatically perform '->'. */ 556 if (ctype_isstruct(ct->info)) {
521 CType *cct = ctype_rawchild(cts, ct);
522 if (ctype_isstruct(cct->info)) {
523 ct = cct;
524 goto index_struct;
525 }
526 } else if (ctype_isstruct(ct->info)) {
527 CTSize fofs; 557 CTSize fofs;
528 CType *fct; 558 CType *fct;
529index_struct:
530 fct = lj_ctype_getfield(cts, ct, name, &fofs); 559 fct = lj_ctype_getfield(cts, ct, name, &fofs);
531 if (fct) { 560 if (fct) {
561 /* Always specialize to the field name. */
562 emitir(IRTG(IR_EQ, IRT_STR), idx, lj_ir_kstr(J, name));
532 if (ctype_isconstval(fct->info)) { 563 if (ctype_isconstval(fct->info)) {
533 if (fct->size >= 0x80000000u && 564 if (fct->size >= 0x80000000u &&
534 (ctype_child(cts, fct)->info & CTF_UNSIGNED)) { 565 (ctype_child(cts, fct)->info & CTF_UNSIGNED)) {
@@ -546,11 +577,26 @@ index_struct:
546 ofs += (ptrdiff_t)fofs; 577 ofs += (ptrdiff_t)fofs;
547 } 578 }
548 } else if (ctype_iscomplex(ct->info)) { 579 } else if (ctype_iscomplex(ct->info)) {
549 if (strdata(name)[0] == 'i') ofs += (ct->size >> 1); 580 if (name->len == 2 &&
550 sid = ctype_cid(ct->info); 581 ((strdata(name)[0] == 'r' && strdata(name)[1] == 'e') ||
582 (strdata(name)[0] == 'i' && strdata(name)[1] == 'm'))) {
583 /* Always specialize to the field name. */
584 emitir(IRTG(IR_EQ, IRT_STR), idx, lj_ir_kstr(J, name));
585 if (strdata(name)[0] == 'i') ofs += (ct->size >> 1);
586 sid = ctype_cid(ct->info);
587 }
551 } 588 }
552 } 589 }
553 if (!sid) lj_trace_err(J, LJ_TRERR_BADTYPE); 590 if (!sid) {
591 if (ctype_isptr(ct->info)) { /* Automatically perform '->'. */
592 CType *cct = ctype_rawchild(cts, ct);
593 if (ctype_isstruct(cct->info)) {
594 ct = cct;
595 if (tref_isstr(idx)) goto again;
596 }
597 }
598 return crec_index_meta(J, cts, ct, rd);
599 }
554 600
555 if (ofs) 601 if (ofs)
556 ptr = emitir(IRT(IR_ADD, IRT_PTR), ptr, lj_ir_kintp(J, ofs)); 602 ptr = emitir(IRT(IR_ADD, IRT_PTR), ptr, lj_ir_kintp(J, ofs));
@@ -592,6 +638,7 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
592 J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, sp); 638 J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), trid, sp);
593 } else { 639 } else {
594 TRef trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, TREF_NIL); 640 TRef trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, TREF_NIL);
641 cTValue *fin;
595 J->base[0] = trcd; 642 J->base[0] = trcd;
596 if (J->base[1] && !J->base[2] && !lj_cconv_multi_init(d, &rd->argv[1])) { 643 if (J->base[1] && !J->base[2] && !lj_cconv_multi_init(d, &rd->argv[1])) {
597 goto single_init; 644 goto single_init;
@@ -660,6 +707,24 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id)
660 crec_ct_tv(J, d, dp, lj_ir_kint(J, 0), &tv); 707 crec_ct_tv(J, d, dp, lj_ir_kint(J, 0), &tv);
661 } 708 }
662 } 709 }
710 /* Handle __gc metamethod. */
711 fin = lj_ctype_meta(cts, id, MM_gc);
712 if (fin) {
713 RecordIndex ix;
714 ix.idxchain = 0;
715 settabV(J->L, &ix.tabv, cts->finalizer);
716 ix.tab = lj_ir_ktab(J, cts->finalizer);
717 setboolV(&ix.keyv, 0); /* The key is new. Dummy value is ok here. */
718 ix.key = trcd;
719 copyTV(J->L, &ix.valv, fin);
720 if (tvisfunc(fin))
721 ix.val = lj_ir_kfunc(J, funcV(fin));
722 else if (tviscdata(fin))
723 ix.val = lj_ir_kgc(J, obj2gco(cdataV(fin)), IRT_CDATA);
724 else
725 lj_trace_err(J, LJ_TRERR_BADTYPE);
726 lj_record_idx(J, &ix);
727 }
663 } 728 }
664} 729}
665 730
@@ -849,6 +914,27 @@ static TRef crec_arith_ptr(jit_State *J, TRef *sp, CType **s, MMS mm)
849 } 914 }
850} 915}
851 916
917/* Record ctype arithmetic metamethods. */
918static void crec_arith_meta(jit_State *J, CTState *cts, RecordFFData *rd)
919{
920 cTValue *tv = NULL;
921 if (J->base[0]) {
922 if (tviscdata(&rd->argv[0]))
923 tv = lj_ctype_meta(cts, argv2cdata(J, J->base[0], &rd->argv[0])->typeid,
924 (MMS)rd->data);
925 if (!tv && J->base[1] && tviscdata(&rd->argv[1]))
926 tv = lj_ctype_meta(cts, argv2cdata(J, J->base[1], &rd->argv[1])->typeid,
927 (MMS)rd->data);
928 }
929 if (tv && tvisfunc(tv)) {
930 J->base[-1] = lj_ir_kfunc(J, funcV(tv)) | TREF_FRAME;
931 rd->nres = -1; /* Pending tailcall. */
932 } else {
933 /* NYI: non-function metamethods. */
934 lj_trace_err(J, LJ_TRERR_BADTYPE);
935 }
936}
937
852void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd) 938void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
853{ 939{
854 CTState *cts = ctype_ctsG(J2G(J)); 940 CTState *cts = ctype_ctsG(J2G(J));
@@ -858,7 +944,9 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
858 for (i = 0; i < 2; i++) { 944 for (i = 0; i < 2; i++) {
859 TRef tr = J->base[i]; 945 TRef tr = J->base[i];
860 CType *ct = ctype_get(cts, CTID_DOUBLE); 946 CType *ct = ctype_get(cts, CTID_DOUBLE);
861 if (tref_iscdata(tr)) { 947 if (!tr) {
948 goto trymeta;
949 } else if (tref_iscdata(tr)) {
862 CTypeID id = argv2cdata(J, tr, &rd->argv[i])->typeid; 950 CTypeID id = argv2cdata(J, tr, &rd->argv[i])->typeid;
863 ct = ctype_raw(cts, id); 951 ct = ctype_raw(cts, id);
864 if (ctype_isptr(ct->info)) { /* Resolve pointer or reference. */ 952 if (ctype_isptr(ct->info)) { /* Resolve pointer or reference. */
@@ -876,11 +964,11 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
876 if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct); 964 if (ctype_isenum(ct->info)) ct = ctype_child(cts, ct);
877 if (ctype_isnum(ct->info)) { 965 if (ctype_isnum(ct->info)) {
878 IRType t = crec_ct2irt(ct); 966 IRType t = crec_ct2irt(ct);
879 if (t == IRT_CDATA) goto err_type; 967 if (t == IRT_CDATA) goto trymeta;
880 if (t == IRT_I64 || t == IRT_U64) lj_needsplit(J); 968 if (t == IRT_I64 || t == IRT_U64) lj_needsplit(J);
881 tr = emitir(IRT(IR_XLOAD, t), tr, 0); 969 tr = emitir(IRT(IR_XLOAD, t), tr, 0);
882 } else if (!(ctype_isptr(ct->info) || ctype_isrefarray(ct->info))) { 970 } else if (!(ctype_isptr(ct->info) || ctype_isrefarray(ct->info))) {
883 goto err_type; 971 goto trymeta;
884 } 972 }
885 } else if (tref_isnil(tr)) { 973 } else if (tref_isnil(tr)) {
886 tr = lj_ir_kptr(J, NULL); 974 tr = lj_ir_kptr(J, NULL);
@@ -888,7 +976,7 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
888 } else if (tref_isinteger(tr)) { 976 } else if (tref_isinteger(tr)) {
889 ct = ctype_get(cts, CTID_INT32); 977 ct = ctype_get(cts, CTID_INT32);
890 } else if (!tref_isnum(tr)) { 978 } else if (!tref_isnum(tr)) {
891 goto err_type; 979 goto trymeta;
892 } 980 }
893 ok: 981 ok:
894 s[i] = ct; 982 s[i] = ct;
@@ -896,21 +984,22 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
896 } 984 }
897 { 985 {
898 TRef tr; 986 TRef tr;
899 if (!(tr = crec_arith_int64(J, sp, s, (MMS)rd->data)) && 987 if ((tr = crec_arith_int64(J, sp, s, (MMS)rd->data)) ||
900 !(tr = crec_arith_ptr(J, sp, s, (MMS)rd->data))) { 988 (tr = crec_arith_ptr(J, sp, s, (MMS)rd->data))) {
901 err_type: 989 J->base[0] = tr;
902 lj_trace_err(J, LJ_TRERR_BADTYPE); 990 /* Fixup cdata comparisons, too. Avoids some cdata escapes. */
903 } 991 if (J->postproc == LJ_POST_FIXGUARD && frame_iscont(J->L->base-1)) {
904 /* Fixup cdata comparisons, too. Avoids some cdata escapes. */ 992 const BCIns *pc = frame_contpc(J->L->base-1) - 1;
905 if (J->postproc == LJ_POST_FIXGUARD && frame_iscont(J->L->base-1)) { 993 if (bc_op(*pc) <= BC_ISNEP) {
906 const BCIns *pc = frame_contpc(J->L->base-1) - 1; 994 setframe_pc(&J2G(J)->tmptv, pc);
907 if (bc_op(*pc) <= BC_ISNEP) { 995 J2G(J)->tmptv.u32.lo = ((tref_istrue(tr) ^ bc_op(*pc)) & 1);
908 setframe_pc(&J2G(J)->tmptv, pc); 996 J->postproc = LJ_POST_FIXCOMP;
909 J2G(J)->tmptv.u32.lo = ((tref_istrue(tr) ^ bc_op(*pc)) & 1); 997 }
910 J->postproc = LJ_POST_FIXCOMP;
911 } 998 }
999 } else {
1000 trymeta:
1001 crec_arith_meta(J, cts, rd);
912 } 1002 }
913 J->base[0] = tr;
914 } 1003 }
915} 1004}
916 1005