diff options
Diffstat (limited to 'src/lib_ffi.c')
| -rw-r--r-- | src/lib_ffi.c | 109 |
1 files changed, 59 insertions, 50 deletions
diff --git a/src/lib_ffi.c b/src/lib_ffi.c index 8c5c03fb..7b83ef25 100644 --- a/src/lib_ffi.c +++ b/src/lib_ffi.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include "lj_ccall.h" | 29 | #include "lj_ccall.h" |
| 30 | #include "lj_ccallback.h" | 30 | #include "lj_ccallback.h" |
| 31 | #include "lj_clib.h" | 31 | #include "lj_clib.h" |
| 32 | #include "lj_strfmt.h" | ||
| 32 | #include "lj_ff.h" | 33 | #include "lj_ff.h" |
| 33 | #include "lj_lib.h" | 34 | #include "lj_lib.h" |
| 34 | 35 | ||
| @@ -137,7 +138,7 @@ static int ffi_index_meta(lua_State *L, CTState *cts, CType *ct, MMS mm) | |||
| 137 | } | 138 | } |
| 138 | } | 139 | } |
| 139 | copyTV(L, base, L->top); | 140 | copyTV(L, base, L->top); |
| 140 | tv = L->top-1; | 141 | tv = L->top-1-LJ_FR2; |
| 141 | } | 142 | } |
| 142 | return lj_meta_tailcall(L, tv); | 143 | return lj_meta_tailcall(L, tv); |
| 143 | } | 144 | } |
| @@ -318,7 +319,7 @@ LJLIB_CF(ffi_meta___tostring) | |||
| 318 | } | 319 | } |
| 319 | } | 320 | } |
| 320 | } | 321 | } |
| 321 | lj_str_pushf(L, msg, strdata(lj_ctype_repr(L, id, NULL)), p); | 322 | lj_strfmt_pushf(L, msg, strdata(lj_ctype_repr(L, id, NULL)), p); |
| 322 | checkgc: | 323 | checkgc: |
| 323 | lj_gc_check(L); | 324 | lj_gc_check(L); |
| 324 | return 1; | 325 | return 1; |
| @@ -504,10 +505,7 @@ LJLIB_CF(ffi_new) LJLIB_REC(.) | |||
| 504 | } | 505 | } |
| 505 | if (sz == CTSIZE_INVALID) | 506 | if (sz == CTSIZE_INVALID) |
| 506 | lj_err_arg(L, 1, LJ_ERR_FFI_INVSIZE); | 507 | lj_err_arg(L, 1, LJ_ERR_FFI_INVSIZE); |
| 507 | if (!(info & CTF_VLA) && ctype_align(info) <= CT_MEMALIGN) | 508 | cd = lj_cdata_newx(cts, id, sz, info); |
| 508 | cd = lj_cdata_new(cts, id, sz); | ||
| 509 | else | ||
| 510 | cd = lj_cdata_newv(cts, id, sz, ctype_align(info)); | ||
| 511 | setcdataV(L, o-1, cd); /* Anchor the uninitialized cdata. */ | 509 | setcdataV(L, o-1, cd); /* Anchor the uninitialized cdata. */ |
| 512 | lj_cconv_ct_init(cts, ct, sz, cdataptr(cd), | 510 | lj_cconv_ct_init(cts, ct, sz, cdataptr(cd), |
| 513 | o, (MSize)(L->top - o)); /* Initialize cdata. */ | 511 | o, (MSize)(L->top - o)); /* Initialize cdata. */ |
| @@ -515,7 +513,7 @@ LJLIB_CF(ffi_new) LJLIB_REC(.) | |||
| 515 | /* Handle ctype __gc metamethod. Use the fast lookup here. */ | 513 | /* Handle ctype __gc metamethod. Use the fast lookup here. */ |
| 516 | cTValue *tv = lj_tab_getinth(cts->miscmap, -(int32_t)id); | 514 | cTValue *tv = lj_tab_getinth(cts->miscmap, -(int32_t)id); |
| 517 | if (tv && tvistab(tv) && (tv = lj_meta_fast(L, tabV(tv), MM_gc))) { | 515 | if (tv && tvistab(tv) && (tv = lj_meta_fast(L, tabV(tv), MM_gc))) { |
| 518 | GCtab *t = cts->finalizer; | 516 | GCtab *t = tabref(G(L)->gcroot[GCROOT_FFI_FIN]); |
| 519 | if (gcref(t->metatable)) { | 517 | if (gcref(t->metatable)) { |
| 520 | /* Add to finalizer table, if still enabled. */ | 518 | /* Add to finalizer table, if still enabled. */ |
| 521 | copyTV(L, lj_tab_set(L, t, o-1), tv); | 519 | copyTV(L, lj_tab_set(L, t, o-1), tv); |
| @@ -558,6 +556,32 @@ LJLIB_CF(ffi_typeof) LJLIB_REC(.) | |||
| 558 | return 1; | 556 | return 1; |
| 559 | } | 557 | } |
| 560 | 558 | ||
| 559 | /* Internal and unsupported API. */ | ||
| 560 | LJLIB_CF(ffi_typeinfo) | ||
| 561 | { | ||
| 562 | CTState *cts = ctype_cts(L); | ||
| 563 | CTypeID id = (CTypeID)ffi_checkint(L, 1); | ||
| 564 | if (id > 0 && id < cts->top) { | ||
| 565 | CType *ct = ctype_get(cts, id); | ||
| 566 | GCtab *t; | ||
| 567 | lua_createtable(L, 0, 4); /* Increment hash size if fields are added. */ | ||
| 568 | t = tabV(L->top-1); | ||
| 569 | setintV(lj_tab_setstr(L, t, lj_str_newlit(L, "info")), (int32_t)ct->info); | ||
| 570 | if (ct->size != CTSIZE_INVALID) | ||
| 571 | setintV(lj_tab_setstr(L, t, lj_str_newlit(L, "size")), (int32_t)ct->size); | ||
| 572 | if (ct->sib) | ||
| 573 | setintV(lj_tab_setstr(L, t, lj_str_newlit(L, "sib")), (int32_t)ct->sib); | ||
| 574 | if (gcref(ct->name)) { | ||
| 575 | GCstr *s = gco2str(gcref(ct->name)); | ||
| 576 | if (isdead(G(L), obj2gco(s))) flipwhite(obj2gco(s)); | ||
| 577 | setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "name")), s); | ||
| 578 | } | ||
| 579 | lj_gc_check(L); | ||
| 580 | return 1; | ||
| 581 | } | ||
| 582 | return 0; | ||
| 583 | } | ||
| 584 | |||
| 561 | LJLIB_CF(ffi_istype) LJLIB_REC(.) | 585 | LJLIB_CF(ffi_istype) LJLIB_REC(.) |
| 562 | { | 586 | { |
| 563 | CTState *cts = ctype_cts(L); | 587 | CTState *cts = ctype_cts(L); |
| @@ -697,45 +721,54 @@ LJLIB_CF(ffi_fill) LJLIB_REC(.) | |||
| 697 | return 0; | 721 | return 0; |
| 698 | } | 722 | } |
| 699 | 723 | ||
| 700 | #define H_(le, be) LJ_ENDIAN_SELECT(0x##le, 0x##be) | ||
| 701 | |||
| 702 | /* Test ABI string. */ | 724 | /* Test ABI string. */ |
| 703 | LJLIB_CF(ffi_abi) LJLIB_REC(.) | 725 | LJLIB_CF(ffi_abi) LJLIB_REC(.) |
| 704 | { | 726 | { |
| 705 | GCstr *s = lj_lib_checkstr(L, 1); | 727 | GCstr *s = lj_lib_checkstr(L, 1); |
| 706 | int b = 0; | 728 | int b = lj_cparse_case(s, |
| 707 | switch (s->hash) { | ||
| 708 | #if LJ_64 | 729 | #if LJ_64 |
| 709 | case H_(849858eb,ad35fd06): b = 1; break; /* 64bit */ | 730 | "\00564bit" |
| 710 | #else | 731 | #else |
| 711 | case H_(662d3c79,d0e22477): b = 1; break; /* 32bit */ | 732 | "\00532bit" |
| 712 | #endif | 733 | #endif |
| 713 | #if LJ_ARCH_HASFPU | 734 | #if LJ_ARCH_HASFPU |
| 714 | case H_(e33ee463,e33ee463): b = 1; break; /* fpu */ | 735 | "\003fpu" |
| 715 | #endif | 736 | #endif |
| 716 | #if LJ_ABI_SOFTFP | 737 | #if LJ_ABI_SOFTFP |
| 717 | case H_(61211a23,c2e8c81c): b = 1; break; /* softfp */ | 738 | "\006softfp" |
| 718 | #else | 739 | #else |
| 719 | case H_(539417a8,8ce0812f): b = 1; break; /* hardfp */ | 740 | "\006hardfp" |
| 720 | #endif | 741 | #endif |
| 721 | #if LJ_ABI_EABI | 742 | #if LJ_ABI_EABI |
| 722 | case H_(2182df8f,f2ed1152): b = 1; break; /* eabi */ | 743 | "\004eabi" |
| 723 | #endif | 744 | #endif |
| 724 | #if LJ_ABI_WIN | 745 | #if LJ_ABI_WIN |
| 725 | case H_(4ab624a8,4ab624a8): b = 1; break; /* win */ | 746 | "\003win" |
| 726 | #endif | 747 | #endif |
| 727 | case H_(3af93066,1f001464): b = 1; break; /* le/be */ | 748 | #if LJ_ABI_PAUTH |
| 728 | default: | 749 | "\005pauth" |
| 729 | break; | 750 | #endif |
| 730 | } | 751 | #if LJ_TARGET_UWP |
| 752 | "\003uwp" | ||
| 753 | #endif | ||
| 754 | #if LJ_LE | ||
| 755 | "\002le" | ||
| 756 | #else | ||
| 757 | "\002be" | ||
| 758 | #endif | ||
| 759 | #if LJ_GC64 | ||
| 760 | "\004gc64" | ||
| 761 | #endif | ||
| 762 | #if LJ_DUALNUM | ||
| 763 | "\007dualnum" | ||
| 764 | #endif | ||
| 765 | ) >= 0; | ||
| 731 | setboolV(L->top-1, b); | 766 | setboolV(L->top-1, b); |
| 732 | setboolV(&G(L)->tmptv2, b); /* Remember for trace recorder. */ | 767 | setboolV(&G(L)->tmptv2, b); /* Remember for trace recorder. */ |
| 733 | return 1; | 768 | return 1; |
| 734 | } | 769 | } |
| 735 | 770 | ||
| 736 | #undef H_ | 771 | LJLIB_PUSH(top-7) LJLIB_SET(!) /* Store reference to miscmap table. */ |
| 737 | |||
| 738 | LJLIB_PUSH(top-8) LJLIB_SET(!) /* Store reference to miscmap table. */ | ||
| 739 | 772 | ||
| 740 | LJLIB_CF(ffi_metatype) | 773 | LJLIB_CF(ffi_metatype) |
| 741 | { | 774 | { |
| @@ -761,26 +794,16 @@ LJLIB_CF(ffi_metatype) | |||
| 761 | return 1; | 794 | return 1; |
| 762 | } | 795 | } |
| 763 | 796 | ||
| 764 | LJLIB_PUSH(top-7) LJLIB_SET(!) /* Store reference to finalizer table. */ | ||
| 765 | |||
| 766 | LJLIB_CF(ffi_gc) LJLIB_REC(.) | 797 | LJLIB_CF(ffi_gc) LJLIB_REC(.) |
| 767 | { | 798 | { |
| 768 | GCcdata *cd = ffi_checkcdata(L, 1); | 799 | GCcdata *cd = ffi_checkcdata(L, 1); |
| 769 | TValue *fin = lj_lib_checkany(L, 2); | 800 | TValue *fin = lj_lib_checkany(L, 2); |
| 770 | CTState *cts = ctype_cts(L); | 801 | CTState *cts = ctype_cts(L); |
| 771 | GCtab *t = cts->finalizer; | ||
| 772 | CType *ct = ctype_raw(cts, cd->ctypeid); | 802 | CType *ct = ctype_raw(cts, cd->ctypeid); |
| 773 | if (!(ctype_isptr(ct->info) || ctype_isstruct(ct->info) || | 803 | if (!(ctype_isptr(ct->info) || ctype_isstruct(ct->info) || |
| 774 | ctype_isrefarray(ct->info))) | 804 | ctype_isrefarray(ct->info))) |
| 775 | lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE); | 805 | lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE); |
| 776 | if (gcref(t->metatable)) { /* Update finalizer table, if still enabled. */ | 806 | lj_cdata_setfin(L, cd, gcval(fin), itype(fin)); |
| 777 | copyTV(L, lj_tab_set(L, t, L->base), fin); | ||
| 778 | lj_gc_anybarriert(L, t); | ||
| 779 | if (!tvisnil(fin)) | ||
| 780 | cd->marked |= LJ_GC_CDATA_FIN; | ||
| 781 | else | ||
| 782 | cd->marked &= ~LJ_GC_CDATA_FIN; | ||
| 783 | } | ||
| 784 | L->top = L->base+1; /* Pass through the cdata object. */ | 807 | L->top = L->base+1; /* Pass through the cdata object. */ |
| 785 | return 1; | 808 | return 1; |
| 786 | } | 809 | } |
| @@ -803,19 +826,6 @@ LJLIB_PUSH(top-2) LJLIB_SET(arch) | |||
| 803 | 826 | ||
| 804 | /* ------------------------------------------------------------------------ */ | 827 | /* ------------------------------------------------------------------------ */ |
| 805 | 828 | ||
| 806 | /* Create special weak-keyed finalizer table. */ | ||
| 807 | static GCtab *ffi_finalizer(lua_State *L) | ||
| 808 | { | ||
| 809 | /* NOBARRIER: The table is new (marked white). */ | ||
| 810 | GCtab *t = lj_tab_new(L, 0, 1); | ||
| 811 | settabV(L, L->top++, t); | ||
| 812 | setgcref(t->metatable, obj2gco(t)); | ||
| 813 | setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "__mode")), | ||
| 814 | lj_str_newlit(L, "k")); | ||
| 815 | t->nomm = (uint8_t)(~(1u<<MM_mode)); | ||
| 816 | return t; | ||
| 817 | } | ||
| 818 | |||
| 819 | /* Register FFI module as loaded. */ | 829 | /* Register FFI module as loaded. */ |
| 820 | static void ffi_register_module(lua_State *L) | 830 | static void ffi_register_module(lua_State *L) |
| 821 | { | 831 | { |
| @@ -831,7 +841,6 @@ LUALIB_API int luaopen_ffi(lua_State *L) | |||
| 831 | { | 841 | { |
| 832 | CTState *cts = lj_ctype_init(L); | 842 | CTState *cts = lj_ctype_init(L); |
| 833 | settabV(L, L->top++, (cts->miscmap = lj_tab_new(L, 0, 1))); | 843 | settabV(L, L->top++, (cts->miscmap = lj_tab_new(L, 0, 1))); |
| 834 | cts->finalizer = ffi_finalizer(L); | ||
| 835 | LJ_LIB_REG(L, NULL, ffi_meta); | 844 | LJ_LIB_REG(L, NULL, ffi_meta); |
| 836 | /* NOBARRIER: basemt is a GC root. */ | 845 | /* NOBARRIER: basemt is a GC root. */ |
| 837 | setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1))); | 846 | setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1))); |
