aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.dep10
-rw-r--r--src/lib_ffi.c77
-rw-r--r--src/lj_cdata.c13
-rw-r--r--src/lj_ctype.c3
-rw-r--r--src/lj_ctype.h3
-rw-r--r--src/lj_gc.c103
-rw-r--r--src/lj_gc.h8
-rw-r--r--src/lj_state.c3
8 files changed, 163 insertions, 57 deletions
diff --git a/src/Makefile.dep b/src/Makefile.dep
index 7f87155e..1684ebd7 100644
--- a/src/Makefile.dep
+++ b/src/Makefile.dep
@@ -21,9 +21,9 @@ lib_bit.o: lib_bit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
21lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ 21lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
22 lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_lib.h lj_libdef.h 22 lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_lib.h lj_libdef.h
23lib_ffi.o: lib_ffi.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ 23lib_ffi.o: lib_ffi.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
24 lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cparse.h \ 24 lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_ctype.h \
25 lj_cdata.h lj_cconv.h lj_carith.h lj_ccall.h lj_clib.h lj_ff.h \ 25 lj_cparse.h lj_cdata.h lj_cconv.h lj_carith.h lj_ccall.h lj_clib.h \
26 lj_ffdef.h lj_lib.h lj_libdef.h 26 lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h
27lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h 27lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h
28lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ 28lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
29 lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ff.h lj_ffdef.h \ 29 lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ff.h lj_ffdef.h \
@@ -96,7 +96,7 @@ lj_func.o: lj_func.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
96 lj_traceerr.h lj_vm.h 96 lj_traceerr.h lj_vm.h
97lj_gc.o: lj_gc.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 97lj_gc.o: lj_gc.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
98 lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h lj_udata.h lj_meta.h \ 98 lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h lj_udata.h lj_meta.h \
99 lj_state.h lj_frame.h lj_bc.h lj_cdata.h lj_ctype.h lj_trace.h lj_jit.h \ 99 lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cdata.h lj_trace.h lj_jit.h \
100 lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h 100 lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h
101lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 101lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
102 lj_gc.h lj_err.h lj_errmsg.h lj_frame.h lj_bc.h lj_jit.h lj_ir.h \ 102 lj_gc.h lj_err.h lj_errmsg.h lj_frame.h lj_bc.h lj_jit.h lj_ir.h \
@@ -161,7 +161,7 @@ lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
161 lj_vm.h lj_vmevent.h 161 lj_vm.h lj_vmevent.h
162ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_gc.c lj_obj.h lj_def.h \ 162ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_gc.c lj_obj.h lj_def.h \
163 lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h \ 163 lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h \
164 lj_udata.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_cdata.h lj_ctype.h \ 164 lj_udata.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cdata.h \
165 lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_err.c \ 165 lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_err.c \
166 lj_ff.h lj_ffdef.h lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c \ 166 lj_ff.h lj_ffdef.h lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c \
167 lj_str.c lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_state.c lj_lex.h \ 167 lj_str.c lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_state.c lj_lex.h \
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
357LJLIB_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
356LJLIB_CF(ffi_typeof) 375LJLIB_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
422LJLIB_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
440LJLIB_CF(ffi_string) LJLIB_REC(.) 441LJLIB_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
524LJLIB_PUSH(top-7) LJLIB_SET(!) /* Store reference to weak table. */
525
526LJLIB_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
523LJLIB_PUSH(top-5) LJLIB_SET(!) /* Store clib metatable in func environment. */ 548LJLIB_PUSH(top-5) LJLIB_SET(!) /* Store clib metatable in func environment. */
524 549
525LJLIB_CF(ffi_load) 550LJLIB_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. */
567static 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
541LUALIB_API int luaopen_ffi(lua_State *L) 579LUALIB_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)));
diff --git a/src/lj_cdata.c b/src/lj_cdata.c
index ae66b4b5..11c84d8e 100644
--- a/src/lj_cdata.c
+++ b/src/lj_cdata.c
@@ -52,7 +52,18 @@ GCcdata *lj_cdata_newv(CTState *cts, CTypeID id, CTSize sz, CTSize align)
52/* Free a C data object. */ 52/* Free a C data object. */
53void LJ_FASTCALL lj_cdata_free(global_State *g, GCcdata *cd) 53void LJ_FASTCALL lj_cdata_free(global_State *g, GCcdata *cd)
54{ 54{
55 if (LJ_LIKELY(!cdataisv(cd))) { 55 if (LJ_UNLIKELY(cd->marked & LJ_GC_CDATA_FIN)) {
56 GCobj *root;
57 cd->marked = curwhite(g) | LJ_GC_FINALIZED;
58 if ((root = gcref(g->gc.mmudata)) != NULL) {
59 setgcrefr(cd->nextgc, root->gch.nextgc);
60 setgcref(root->gch.nextgc, obj2gco(cd));
61 setgcref(g->gc.mmudata, obj2gco(cd));
62 } else {
63 setgcref(cd->nextgc, obj2gco(cd));
64 setgcref(g->gc.mmudata, obj2gco(cd));
65 }
66 } else if (LJ_LIKELY(!cdataisv(cd))) {
56 CType *ct = ctype_raw(ctype_ctsG(g), cd->typeid); 67 CType *ct = ctype_raw(ctype_ctsG(g), cd->typeid);
57 CTSize sz = ctype_hassize(ct->info) ? ct->size : CTSIZE_PTR; 68 CTSize sz = ctype_hassize(ct->info) ? ct->size : CTSIZE_PTR;
58 lua_assert(ctype_hassize(ct->info) || ctype_isfunc(ct->info) || 69 lua_assert(ctype_hassize(ct->info) || ctype_isfunc(ct->info) ||
diff --git a/src/lj_ctype.c b/src/lj_ctype.c
index 956f0a09..ae360b54 100644
--- a/src/lj_ctype.c
+++ b/src/lj_ctype.c
@@ -540,7 +540,7 @@ GCstr *lj_ctype_repr_complex(lua_State *L, void *sp, CTSize size)
540/* -- C type state -------------------------------------------------------- */ 540/* -- C type state -------------------------------------------------------- */
541 541
542/* Initialize C type table and state. */ 542/* Initialize C type table and state. */
543void lj_ctype_init(lua_State *L) 543CTState *lj_ctype_init(lua_State *L)
544{ 544{
545 CTState *cts = lj_mem_newt(L, sizeof(CTState), CTState); 545 CTState *cts = lj_mem_newt(L, sizeof(CTState), CTState);
546 CType *ct = lj_mem_newvec(L, CTTYPETAB_MIN, CType); 546 CType *ct = lj_mem_newvec(L, CTTYPETAB_MIN, CType);
@@ -568,6 +568,7 @@ void lj_ctype_init(lua_State *L)
568 } 568 }
569 } 569 }
570 setmref(G(L)->ctype_state, cts); 570 setmref(G(L)->ctype_state, cts);
571 return cts;
571} 572}
572 573
573/* Free C type table and state. */ 574/* Free C type table and state. */
diff --git a/src/lj_ctype.h b/src/lj_ctype.h
index 555393db..a45767c2 100644
--- a/src/lj_ctype.h
+++ b/src/lj_ctype.h
@@ -158,6 +158,7 @@ typedef struct CTState {
158 MSize sizetab; /* Size of C type table. */ 158 MSize sizetab; /* Size of C type table. */
159 lua_State *L; /* Lua state (needed for errors and allocations). */ 159 lua_State *L; /* Lua state (needed for errors and allocations). */
160 global_State *g; /* Global state. */ 160 global_State *g; /* Global state. */
161 GCtab *finalizer; /* Map of cdata to finalizer. */
161 CTypeID1 hash[CTHASH_SIZE]; /* Hash anchors for C type table. */ 162 CTypeID1 hash[CTHASH_SIZE]; /* Hash anchors for C type table. */
162} CTState; 163} CTState;
163 164
@@ -428,7 +429,7 @@ LJ_FUNC CTInfo lj_ctype_info(CTState *cts, CTypeID id, CTSize *szp);
428LJ_FUNC GCstr *lj_ctype_repr(lua_State *L, CTypeID id, GCstr *name); 429LJ_FUNC GCstr *lj_ctype_repr(lua_State *L, CTypeID id, GCstr *name);
429LJ_FUNC GCstr *lj_ctype_repr_int64(lua_State *L, uint64_t n, int isunsigned); 430LJ_FUNC GCstr *lj_ctype_repr_int64(lua_State *L, uint64_t n, int isunsigned);
430LJ_FUNC GCstr *lj_ctype_repr_complex(lua_State *L, void *sp, CTSize size); 431LJ_FUNC GCstr *lj_ctype_repr_complex(lua_State *L, void *sp, CTSize size);
431LJ_FUNC void lj_ctype_init(lua_State *L); 432LJ_FUNC CTState *lj_ctype_init(lua_State *L);
432LJ_FUNC void lj_ctype_freestate(global_State *g); 433LJ_FUNC void lj_ctype_freestate(global_State *g);
433 434
434#endif 435#endif
diff --git a/src/lj_gc.c b/src/lj_gc.c
index 793d8dac..f231b1ce 100644
--- a/src/lj_gc.c
+++ b/src/lj_gc.c
@@ -20,6 +20,7 @@
20#include "lj_state.h" 20#include "lj_state.h"
21#include "lj_frame.h" 21#include "lj_frame.h"
22#if LJ_HASFFI 22#if LJ_HASFFI
23#include "lj_ctype.h"
23#include "lj_cdata.h" 24#include "lj_cdata.h"
24#endif 25#endif
25#include "lj_trace.h" 26#include "lj_trace.h"
@@ -170,8 +171,9 @@ static int gc_traverse_tab(global_State *g, GCtab *t)
170 while ((c = *modestr++)) { 171 while ((c = *modestr++)) {
171 if (c == 'k') weak |= LJ_GC_WEAKKEY; 172 if (c == 'k') weak |= LJ_GC_WEAKKEY;
172 else if (c == 'v') weak |= LJ_GC_WEAKVAL; 173 else if (c == 'v') weak |= LJ_GC_WEAKVAL;
174 else if (c == 'K') weak = (int)(~0u & ~LJ_GC_WEAKVAL);
173 } 175 }
174 if (weak) { /* Weak tables are cleared in the atomic phase. */ 176 if (weak > 0) { /* Weak tables are cleared in the atomic phase. */
175 t->marked = cast_byte((t->marked & ~LJ_GC_WEAK) | weak); 177 t->marked = cast_byte((t->marked & ~LJ_GC_WEAK) | weak);
176 setgcrefr(t->gclist, g->gc.weak); 178 setgcrefr(t->gclist, g->gc.weak);
177 setgcref(g->gc.weak, obj2gco(t)); 179 setgcref(g->gc.weak, obj2gco(t));
@@ -458,53 +460,98 @@ static void gc_clearweak(GCobj *o)
458 } 460 }
459} 461}
460 462
461/* Finalize one userdata object from mmudata list. */ 463/* Call a userdata or cdata finalizer. */
464static void gc_call_finalizer(global_State *g, lua_State *L,
465 cTValue *mo, GCobj *o)
466{
467 /* Save and restore lots of state around the __gc callback. */
468 uint8_t oldh = hook_save(g);
469 MSize oldt = g->gc.threshold;
470 int errcode;
471 TValue *top;
472 lj_trace_abort(g);
473 top = L->top;
474 L->top = top+2;
475 hook_entergc(g); /* Disable hooks and new traces during __gc. */
476 g->gc.threshold = LJ_MAX_MEM; /* Prevent GC steps. */
477 copyTV(L, top, mo);
478 setgcV(L, top+1, o, ~o->gch.gct);
479 errcode = lj_vm_pcall(L, top+1, 1+0, -1); /* Stack: |mo|o| -> | */
480 hook_restore(g, oldh);
481 g->gc.threshold = oldt; /* Restore GC threshold. */
482 if (errcode)
483 lj_err_throw(L, errcode); /* Propagate errors. */
484}
485
486/* Finalize one userdata or cdata object from the mmudata list. */
462static void gc_finalize(lua_State *L) 487static void gc_finalize(lua_State *L)
463{ 488{
464 global_State *g = G(L); 489 global_State *g = G(L);
465 GCobj *o = gcnext(gcref(g->gc.mmudata)); 490 GCobj *o = gcnext(gcref(g->gc.mmudata));
466 GCudata *ud = gco2ud(o);
467 cTValue *mo; 491 cTValue *mo;
468 lua_assert(gcref(g->jit_L) == NULL); /* Must not be called on trace. */ 492 lua_assert(gcref(g->jit_L) == NULL); /* Must not be called on trace. */
469 /* Unchain from list of userdata to be finalized. */ 493 /* Unchain from list of userdata to be finalized. */
470 if (o == gcref(g->gc.mmudata)) 494 if (o == gcref(g->gc.mmudata))
471 setgcrefnull(g->gc.mmudata); 495 setgcrefnull(g->gc.mmudata);
472 else 496 else
473 setgcrefr(gcref(g->gc.mmudata)->gch.nextgc, ud->nextgc); 497 setgcrefr(gcref(g->gc.mmudata)->gch.nextgc, o->gch.nextgc);
474 /* Add it back to the main userdata list and make it white. */
475 setgcrefr(ud->nextgc, mainthread(g)->nextgc);
476 setgcref(mainthread(g)->nextgc, o);
477 makewhite(g, o); 498 makewhite(g, o);
478 /* Resolve the __gc metamethod. */ 499#if LJ_HASFFI
479 mo = lj_meta_fastg(g, tabref(ud->metatable), MM_gc); 500 if (o->gch.gct == ~LJ_TCDATA) {
480 if (mo) { 501 TValue tmp, *tv;
481 /* Save and restore lots of state around the __gc callback. */ 502 setgcrefr(o->gch.nextgc, g->gc.root); /* Add cdata back to the gc list. */
482 uint8_t oldh = hook_save(g); 503 setgcref(g->gc.root, o);
483 MSize oldt = g->gc.threshold; 504 /* Resolve finalizer. */
484 int errcode; 505 setcdataV(L, &tmp, gco2cd(o));
485 TValue *top; 506 tv = lj_tab_set(L, ctype_ctsG(g)->finalizer, &tmp);
486 lj_trace_abort(g); 507 if (!tvisnil(tv)) {
487 top = L->top; 508 copyTV(L, &tmp, tv);
488 L->top = top+2; 509 setnilV(tv); /* Clear entry in finalizer table. */
489 hook_entergc(g); /* Disable hooks and new traces during __gc. */ 510 gc_call_finalizer(g, L, &tmp, o);
490 g->gc.threshold = LJ_MAX_MEM; /* Prevent GC steps. */ 511 }
491 copyTV(L, top, mo); 512 return;
492 setudataV(L, top+1, ud);
493 errcode = lj_vm_pcall(L, top+1, 1+0, -1); /* Stack: |mo|ud| -> | */
494 hook_restore(g, oldh);
495 g->gc.threshold = oldt; /* Restore GC threshold. */
496 if (errcode)
497 lj_err_throw(L, errcode); /* Propagate errors. */
498 } 513 }
514#endif
515 /* Add userdata back to the main userdata list. */
516 setgcrefr(o->gch.nextgc, mainthread(g)->nextgc);
517 setgcref(mainthread(g)->nextgc, o);
518 /* Resolve the __gc metamethod. */
519 mo = lj_meta_fastg(g, tabref(gco2ud(o)->metatable), MM_gc);
520 if (mo)
521 gc_call_finalizer(g, L, mo, o);
499} 522}
500 523
501/* Finalize all userdata objects from mmudata list. */ 524/* Finalize all userdata objects from mmudata list. */
502void lj_gc_finalizeudata(lua_State *L) 525void lj_gc_finalize_udata(lua_State *L)
503{ 526{
504 while (gcref(G(L)->gc.mmudata) != NULL) 527 while (gcref(G(L)->gc.mmudata) != NULL)
505 gc_finalize(L); 528 gc_finalize(L);
506} 529}
507 530
531#if LJ_HASFFI
532/* Finalize all cdata objects from finalizer table. */
533void lj_gc_finalize_cdata(lua_State *L)
534{
535 global_State *g = G(L);
536 CTState *cts = ctype_ctsG(g);
537 if (cts) {
538 GCtab *t = cts->finalizer;
539 Node *node = noderef(t->node);
540 ptrdiff_t i;
541 setgcrefnull(t->metatable); /* Mark finalizer table as disabled. */
542 for (i = (ptrdiff_t)t->hmask; i >= 0; i--)
543 if (!tvisnil(&node[i].val) && tviscdata(&node[i].key)) {
544 GCobj *o = gcV(&node[i].key);
545 TValue tmp;
546 o->gch.marked &= ~LJ_GC_CDATA_FIN;
547 copyTV(L, &tmp, &node[i].val);
548 setnilV(&node[i].val);
549 gc_call_finalizer(g, L, &tmp, o);
550 }
551 }
552}
553#endif
554
508/* Free all remaining GC objects. */ 555/* Free all remaining GC objects. */
509void lj_gc_freeall(global_State *g) 556void lj_gc_freeall(global_State *g)
510{ 557{
diff --git a/src/lj_gc.h b/src/lj_gc.h
index 75b38db8..e3973d8e 100644
--- a/src/lj_gc.h
+++ b/src/lj_gc.h
@@ -20,6 +20,7 @@ enum {
20#define LJ_GC_FINALIZED 0x08 20#define LJ_GC_FINALIZED 0x08
21#define LJ_GC_WEAKKEY 0x08 21#define LJ_GC_WEAKKEY 0x08
22#define LJ_GC_WEAKVAL 0x10 22#define LJ_GC_WEAKVAL 0x10
23#define LJ_GC_CDATA_FIN 0x10
23#define LJ_GC_FIXED 0x20 24#define LJ_GC_FIXED 0x20
24#define LJ_GC_SFIXED 0x40 25#define LJ_GC_SFIXED 0x40
25 26
@@ -42,7 +43,12 @@ enum {
42 43
43/* Collector. */ 44/* Collector. */
44LJ_FUNC size_t lj_gc_separateudata(global_State *g, int all); 45LJ_FUNC size_t lj_gc_separateudata(global_State *g, int all);
45LJ_FUNC void lj_gc_finalizeudata(lua_State *L); 46LJ_FUNC void lj_gc_finalize_udata(lua_State *L);
47#if LJ_HASFFI
48LJ_FUNC void lj_gc_finalize_cdata(lua_State *L);
49#else
50#define lj_gc_finalize_cdata(L) UNUSED(L)
51#endif
46LJ_FUNC void lj_gc_freeall(global_State *g); 52LJ_FUNC void lj_gc_freeall(global_State *g);
47LJ_FUNCA int LJ_FASTCALL lj_gc_step(lua_State *L); 53LJ_FUNCA int LJ_FASTCALL lj_gc_step(lua_State *L);
48LJ_FUNCA void LJ_FASTCALL lj_gc_step_fixtop(lua_State *L); 54LJ_FUNCA void LJ_FASTCALL lj_gc_step_fixtop(lua_State *L);
diff --git a/src/lj_state.c b/src/lj_state.c
index 85348aa7..11b820b2 100644
--- a/src/lj_state.c
+++ b/src/lj_state.c
@@ -225,7 +225,8 @@ static TValue *cpfinalize(lua_State *L, lua_CFunction dummy, void *ud)
225{ 225{
226 UNUSED(dummy); 226 UNUSED(dummy);
227 UNUSED(ud); 227 UNUSED(ud);
228 lj_gc_finalizeudata(L); 228 lj_gc_finalize_udata(L);
229 lj_gc_finalize_cdata(L);
229 /* Frame pop omitted. */ 230 /* Frame pop omitted. */
230 return NULL; 231 return NULL;
231} 232}