FFI: Add callback support (for x86/x64).

This commit is contained in:
Mike Pall
2011-11-14 14:15:57 +01:00
parent e9eb4fdb4a
commit 71d00a56db
27 changed files with 5469 additions and 4472 deletions

View File

@@ -27,6 +27,7 @@
#include "lj_cconv.h"
#include "lj_carith.h"
#include "lj_ccall.h"
#include "lj_ccallback.h"
#include "lj_clib.h"
#include "lj_ff.h"
#include "lj_lib.h"
@@ -384,6 +385,50 @@ LJLIB_CF(ffi_clib___gc)
#include "lj_libdef.h"
/* -- Callback function metamethods --------------------------------------- */
#define LJLIB_MODULE_ffi_callback
static int ffi_callback_set(lua_State *L, GCfunc *fn)
{
GCcdata *cd = ffi_checkcdata(L, 1);
CTState *cts = ctype_cts(L);
CType *ct = ctype_raw(cts, cd->typeid);
if (ctype_isptr(ct->info) && (LJ_32 || ct->size == 8)) {
MSize slot = lj_ccallback_ptr2slot(cts, *(void **)cdataptr(cd));
if (slot < cts->cb.sizeid && cts->cb.cbid[slot] != 0) {
GCtab *t = cts->miscmap;
TValue *tv = lj_tab_setint(L, t, (int32_t)slot);
if (fn) {
setfuncV(L, tv, fn);
lj_gc_anybarriert(L, t);
} else {
setnilV(tv);
cts->cb.cbid[slot] = 0;
cts->cb.topid = slot < cts->cb.topid ? slot : cts->cb.topid;
}
return 0;
}
}
lj_err_caller(L, LJ_ERR_FFI_BADCBACK);
return 0;
}
LJLIB_CF(ffi_callback_free)
{
return ffi_callback_set(L, NULL);
}
LJLIB_CF(ffi_callback_set)
{
GCfunc *fn = lj_lib_checkfunc(L, 2);
return ffi_callback_set(L, fn);
}
LJLIB_PUSH(top-1) LJLIB_SET(__index)
#include "lj_libdef.h"
/* -- FFI library functions ----------------------------------------------- */
#define LJLIB_MODULE_ffi
@@ -428,7 +473,7 @@ LJLIB_CF(ffi_new) LJLIB_REC(.)
o, (MSize)(L->top - o)); /* Initialize cdata. */
if (ctype_isstruct(ct->info)) {
/* Handle ctype __gc metamethod. Use the fast lookup here. */
cTValue *tv = lj_tab_getint(cts->metatype, (int32_t)id);
cTValue *tv = lj_tab_getinth(cts->miscmap, -(int32_t)id);
if (tv && tvistab(tv) && (tv = lj_meta_fast(L, tabV(tv), MM_gc))) {
GCtab *t = cts->finalizer;
if (gcref(t->metatable)) {
@@ -650,21 +695,21 @@ LJLIB_CF(ffi_abi) LJLIB_REC(.)
#undef H_
LJLIB_PUSH(top-8) LJLIB_SET(!) /* Store reference to metatype table. */
LJLIB_PUSH(top-8) LJLIB_SET(!) /* Store reference to miscmap table. */
LJLIB_CF(ffi_metatype)
{
CTState *cts = ctype_cts(L);
CTypeID id = ffi_checkctype(L, cts);
GCtab *mt = lj_lib_checktab(L, 2);
GCtab *t = cts->metatype;
GCtab *t = cts->miscmap;
CType *ct = ctype_get(cts, id); /* Only allow raw types. */
TValue *tv;
GCcdata *cd;
if (!(ctype_isstruct(ct->info) || ctype_iscomplex(ct->info) ||
ctype_isvector(ct->info)))
lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE);
tv = lj_tab_setint(L, t, (int32_t)id);
tv = lj_tab_setinth(L, t, -(int32_t)id);
if (!tvisnil(tv))
lj_err_caller(L, LJ_ERR_PROTMT);
settabV(L, tv, mt);
@@ -745,12 +790,16 @@ static void ffi_register_module(lua_State *L)
LUALIB_API int luaopen_ffi(lua_State *L)
{
CTState *cts = lj_ctype_init(L);
settabV(L, L->top++, (cts->metatype = lj_tab_new(L, 0, 0)));
settabV(L, L->top++, (cts->miscmap = lj_tab_new(L, 0, 1)));
cts->finalizer = ffi_finalizer(L);
LJ_LIB_REG(L, NULL, ffi_meta);
/* NOBARRIER: basemt is a GC root. */
setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1)));
LJ_LIB_REG(L, NULL, ffi_clib);
LJ_LIB_REG(L, NULL, ffi_callback);
/* NOBARRIER: the key is new and lj_tab_newkey() handles the barrier. */
settabV(L, lj_tab_setstr(L, cts->miscmap, &cts->g->strempty), tabV(L->top-1));
L->top--;
lj_clib_default(L, tabV(L->top-1)); /* Create ffi.C default namespace. */
lua_pushliteral(L, LJ_OS_NAME);
lua_pushliteral(L, LJ_ARCH_NAME);