diff options
| author | Mike Pall <mike> | 2011-02-28 16:48:13 +0100 |
|---|---|---|
| committer | Mike Pall <mike> | 2011-02-28 16:48:13 +0100 |
| commit | 83a37aeca74724ef76dee7c8246bdbb88132940d (patch) | |
| tree | 9dca0cd0aa13cf911ad26c3655533a72bb6790a9 /src/lib_ffi.c | |
| parent | cead25f928ac606fc1a13882b818913aab3635a9 (diff) | |
| download | luajit-83a37aeca74724ef76dee7c8246bdbb88132940d.tar.gz luajit-83a37aeca74724ef76dee7c8246bdbb88132940d.tar.bz2 luajit-83a37aeca74724ef76dee7c8246bdbb88132940d.zip | |
FFI: Add ffi.gc() function for finalization of cdata objects.
Diffstat (limited to 'src/lib_ffi.c')
| -rw-r--r-- | src/lib_ffi.c | 77 |
1 files changed, 58 insertions, 19 deletions
diff --git a/src/lib_ffi.c b/src/lib_ffi.c index e88b6f54..674bbf00 100644 --- a/src/lib_ffi.c +++ b/src/lib_ffi.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include "lj_gc.h" | 17 | #include "lj_gc.h" |
| 18 | #include "lj_err.h" | 18 | #include "lj_err.h" |
| 19 | #include "lj_str.h" | 19 | #include "lj_str.h" |
| 20 | #include "lj_tab.h" | ||
| 20 | #include "lj_ctype.h" | 21 | #include "lj_ctype.h" |
| 21 | #include "lj_cparse.h" | 22 | #include "lj_cparse.h" |
| 22 | #include "lj_cdata.h" | 23 | #include "lj_cdata.h" |
| @@ -353,6 +354,24 @@ LJLIB_CF(ffi_new) LJLIB_REC(.) | |||
| 353 | return 1; | 354 | return 1; |
| 354 | } | 355 | } |
| 355 | 356 | ||
| 357 | LJLIB_CF(ffi_cast) LJLIB_REC(ffi_new) | ||
| 358 | { | ||
| 359 | CTState *cts = ctype_cts(L); | ||
| 360 | CTypeID id = ffi_checkctype(L, cts); | ||
| 361 | CType *d = ctype_raw(cts, id); | ||
| 362 | TValue *o = lj_lib_checkany(L, 2); | ||
| 363 | L->top = o+1; /* Make sure this is the last item on the stack. */ | ||
| 364 | if (!(ctype_isnum(d->info) || ctype_isptr(d->info) || ctype_isenum(d->info))) | ||
| 365 | lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE); | ||
| 366 | if (!(tviscdata(o) && cdataV(o)->typeid == id)) { | ||
| 367 | GCcdata *cd = lj_cdata_new(cts, id, d->size); | ||
| 368 | lj_cconv_ct_tv(cts, d, cdataptr(cd), o, CCF_CAST); | ||
| 369 | setcdataV(L, o, cd); | ||
| 370 | lj_gc_check(L); | ||
| 371 | } | ||
| 372 | return 1; | ||
| 373 | } | ||
| 374 | |||
| 356 | LJLIB_CF(ffi_typeof) | 375 | LJLIB_CF(ffi_typeof) |
| 357 | { | 376 | { |
| 358 | CTState *cts = ctype_cts(L); | 377 | CTState *cts = ctype_cts(L); |
| @@ -419,24 +438,6 @@ LJLIB_CF(ffi_offsetof) | |||
| 419 | return 0; | 438 | return 0; |
| 420 | } | 439 | } |
| 421 | 440 | ||
| 422 | LJLIB_CF(ffi_cast) LJLIB_REC(ffi_new) | ||
| 423 | { | ||
| 424 | CTState *cts = ctype_cts(L); | ||
| 425 | CTypeID id = ffi_checkctype(L, cts); | ||
| 426 | CType *d = ctype_raw(cts, id); | ||
| 427 | TValue *o = lj_lib_checkany(L, 2); | ||
| 428 | L->top = o+1; /* Make sure this is the last item on the stack. */ | ||
| 429 | if (!(ctype_isnum(d->info) || ctype_isptr(d->info) || ctype_isenum(d->info))) | ||
| 430 | lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE); | ||
| 431 | if (!(tviscdata(o) && cdataV(o)->typeid == id)) { | ||
| 432 | GCcdata *cd = lj_cdata_new(cts, id, d->size); | ||
| 433 | lj_cconv_ct_tv(cts, d, cdataptr(cd), o, CCF_CAST); | ||
| 434 | setcdataV(L, o, cd); | ||
| 435 | lj_gc_check(L); | ||
| 436 | } | ||
| 437 | return 1; | ||
| 438 | } | ||
| 439 | |||
| 440 | LJLIB_CF(ffi_string) LJLIB_REC(.) | 441 | LJLIB_CF(ffi_string) LJLIB_REC(.) |
| 441 | { | 442 | { |
| 442 | CTState *cts = ctype_cts(L); | 443 | CTState *cts = ctype_cts(L); |
| @@ -520,6 +521,30 @@ LJLIB_CF(ffi_abi) LJLIB_REC(.) | |||
| 520 | 521 | ||
| 521 | #undef H_ | 522 | #undef H_ |
| 522 | 523 | ||
| 524 | LJLIB_PUSH(top-7) LJLIB_SET(!) /* Store reference to weak table. */ | ||
| 525 | |||
| 526 | LJLIB_CF(ffi_gc) | ||
| 527 | { | ||
| 528 | GCcdata *cd = ffi_checkcdata(L, 1); | ||
| 529 | TValue *fin = lj_lib_checkany(L, 2); | ||
| 530 | CTState *cts = ctype_cts(L); | ||
| 531 | GCtab *t = cts->finalizer; | ||
| 532 | CType *ct = ctype_raw(cts, cd->typeid); | ||
| 533 | if (!(ctype_isptr(ct->info) || ctype_isstruct(ct->info) || | ||
| 534 | ctype_isrefarray(ct->info))) | ||
| 535 | lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE); | ||
| 536 | if (gcref(t->metatable)) { /* Update finalizer table, if still enabled. */ | ||
| 537 | copyTV(L, lj_tab_set(L, t, L->base), fin); | ||
| 538 | lj_gc_anybarriert(L, t); | ||
| 539 | if (!tvisnil(fin)) | ||
| 540 | cd->marked |= LJ_GC_CDATA_FIN; | ||
| 541 | else | ||
| 542 | cd->marked &= ~LJ_GC_CDATA_FIN; | ||
| 543 | } | ||
| 544 | L->top = L->base+1; /* Pass through the cdata object. */ | ||
| 545 | return 1; | ||
| 546 | } | ||
| 547 | |||
| 523 | LJLIB_PUSH(top-5) LJLIB_SET(!) /* Store clib metatable in func environment. */ | 548 | LJLIB_PUSH(top-5) LJLIB_SET(!) /* Store clib metatable in func environment. */ |
| 524 | 549 | ||
| 525 | LJLIB_CF(ffi_load) | 550 | LJLIB_CF(ffi_load) |
| @@ -538,9 +563,23 @@ LJLIB_PUSH(top-2) LJLIB_SET(arch) | |||
| 538 | 563 | ||
| 539 | /* ------------------------------------------------------------------------ */ | 564 | /* ------------------------------------------------------------------------ */ |
| 540 | 565 | ||
| 566 | /* Create special weak-keyed finalizer table. */ | ||
| 567 | static GCtab *ffi_finalizer(lua_State *L) | ||
| 568 | { | ||
| 569 | /* NOBARRIER: The table is new (marked white). */ | ||
| 570 | GCtab *t = lj_tab_new(L, 0, 1); | ||
| 571 | settabV(L, L->top++, t); | ||
| 572 | setgcref(t->metatable, obj2gco(t)); | ||
| 573 | setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "__mode")), | ||
| 574 | lj_str_newlit(L, "K")); | ||
| 575 | t->nomm = (uint8_t)(~(1u<<MM_mode)); | ||
| 576 | return t; | ||
| 577 | } | ||
| 578 | |||
| 541 | LUALIB_API int luaopen_ffi(lua_State *L) | 579 | LUALIB_API int luaopen_ffi(lua_State *L) |
| 542 | { | 580 | { |
| 543 | lj_ctype_init(L); | 581 | CTState *cts = lj_ctype_init(L); |
| 582 | cts->finalizer = ffi_finalizer(L); | ||
| 544 | LJ_LIB_REG(L, NULL, ffi_meta); | 583 | LJ_LIB_REG(L, NULL, ffi_meta); |
| 545 | /* NOBARRIER: basemt is a GC root. */ | 584 | /* NOBARRIER: basemt is a GC root. */ |
| 546 | setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1))); | 585 | setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1))); |
