diff options
| author | Mike Pall <mike> | 2011-01-09 16:48:23 +0100 |
|---|---|---|
| committer | Mike Pall <mike> | 2011-01-09 16:48:23 +0100 |
| commit | bfc638ca6c17319acad0f75dfd9b53f6d2ae1e6f (patch) | |
| tree | bd4a26e5b903fac51a6e8ccc6b1f420bd240a45c | |
| parent | aca1e5b3e69d8e7ed155de3d2db959bc49597bf1 (diff) | |
| download | luajit-bfc638ca6c17319acad0f75dfd9b53f6d2ae1e6f.tar.gz luajit-bfc638ca6c17319acad0f75dfd9b53f6d2ae1e6f.tar.bz2 luajit-bfc638ca6c17319acad0f75dfd9b53f6d2ae1e6f.zip | |
FFI: Add missing GC steps for C function calls.
| -rw-r--r-- | src/Makefile.dep | 2 | ||||
| -rw-r--r-- | src/lj_ccall.c | 34 |
2 files changed, 24 insertions, 12 deletions
diff --git a/src/Makefile.dep b/src/Makefile.dep index 9b790fb8..9982f7b0 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep | |||
| @@ -56,7 +56,7 @@ lj_asm.o: lj_asm.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | |||
| 56 | lj_bc.o: lj_bc.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_bc.h \ | 56 | lj_bc.o: lj_bc.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_bc.h \ |
| 57 | lj_bcdef.h | 57 | lj_bcdef.h |
| 58 | lj_ccall.o: lj_ccall.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 58 | lj_ccall.o: lj_ccall.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
| 59 | lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_gc.h lj_cconv.h lj_cdata.h \ | 59 | lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cconv.h lj_cdata.h \ |
| 60 | lj_ccall.h | 60 | lj_ccall.h |
| 61 | lj_cconv.o: lj_cconv.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 61 | lj_cconv.o: lj_cconv.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
| 62 | lj_err.h lj_errmsg.h lj_tab.h lj_ctype.h lj_gc.h lj_cdata.h lj_cconv.h | 62 | lj_err.h lj_errmsg.h lj_tab.h lj_ctype.h lj_gc.h lj_cdata.h lj_cconv.h |
diff --git a/src/lj_ccall.c b/src/lj_ccall.c index 5e91d962..688dfc89 100644 --- a/src/lj_ccall.c +++ b/src/lj_ccall.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | #if LJ_HASFFI | 8 | #if LJ_HASFFI |
| 9 | 9 | ||
| 10 | #include "lj_gc.h" | ||
| 10 | #include "lj_err.h" | 11 | #include "lj_err.h" |
| 11 | #include "lj_str.h" | 12 | #include "lj_str.h" |
| 12 | #include "lj_ctype.h" | 13 | #include "lj_ctype.h" |
| @@ -105,9 +106,10 @@ static CTypeID ccall_ctid_vararg(CTState *cts, cTValue *o) | |||
| 105 | } | 106 | } |
| 106 | 107 | ||
| 107 | /* Setup arguments for C call. */ | 108 | /* Setup arguments for C call. */ |
| 108 | static void ccall_set_args(lua_State *L, CTState *cts, CType *ct, | 109 | static int ccall_set_args(lua_State *L, CTState *cts, CType *ct, |
| 109 | CCallState *cc) | 110 | CCallState *cc) |
| 110 | { | 111 | { |
| 112 | int gcsteps = 0; | ||
| 111 | TValue *o, *top = L->top; | 113 | TValue *o, *top = L->top; |
| 112 | CTypeID fid; | 114 | CTypeID fid; |
| 113 | CType *ctr; | 115 | CType *ctr; |
| @@ -257,6 +259,7 @@ static void ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
| 257 | 259 | ||
| 258 | done: | 260 | done: |
| 259 | if (rp) { /* Pass by reference. */ | 261 | if (rp) { /* Pass by reference. */ |
| 262 | gcsteps++; | ||
| 260 | *(void **)dp = rp; | 263 | *(void **)dp = rp; |
| 261 | dp = rp; | 264 | dp = rp; |
| 262 | } | 265 | } |
| @@ -279,24 +282,30 @@ static void ccall_set_args(lua_State *L, CTState *cts, CType *ct, | |||
| 279 | cc->spadj = (CCALL_SPS_FREE + CCALL_SPS_EXTRA)*CTSIZE_PTR; | 282 | cc->spadj = (CCALL_SPS_FREE + CCALL_SPS_EXTRA)*CTSIZE_PTR; |
| 280 | if (nsp > CCALL_SPS_FREE) | 283 | if (nsp > CCALL_SPS_FREE) |
| 281 | cc->spadj += (((nsp-CCALL_SPS_FREE)*CTSIZE_PTR + 15u) & ~15u); | 284 | cc->spadj += (((nsp-CCALL_SPS_FREE)*CTSIZE_PTR + 15u) & ~15u); |
| 285 | return gcsteps; | ||
| 282 | } | 286 | } |
| 283 | 287 | ||
| 284 | /* Get results from C call. */ | 288 | /* Get results from C call. */ |
| 285 | static int ccall_get_results(lua_State *L, CTState *cts, CType *ct, | 289 | static int ccall_get_results(lua_State *L, CTState *cts, CType *ct, |
| 286 | CCallState *cc) | 290 | CCallState *cc, int *ret) |
| 287 | { | 291 | { |
| 288 | CType *ctr = ctype_rawchild(cts, ct); | 292 | CType *ctr = ctype_rawchild(cts, ct); |
| 289 | void *sp = &cc->gpr[0]; | 293 | void *sp = &cc->gpr[0]; |
| 290 | if (ctype_isvoid(ctr->info)) | 294 | if (ctype_isvoid(ctr->info)) { |
| 291 | return 0; /* Zero results. */ | 295 | *ret = 0; /* Zero results. */ |
| 296 | return 0; /* No additional GC step. */ | ||
| 297 | } | ||
| 298 | *ret = 1; /* One result. */ | ||
| 292 | if (ctype_isstruct(ctr->info)) { | 299 | if (ctype_isstruct(ctr->info)) { |
| 300 | /* Return cdata object which is already on top of stack. */ | ||
| 293 | if (!CCALL_STRUCT_RETREF && !cc->retref) { | 301 | if (!CCALL_STRUCT_RETREF && !cc->retref) { |
| 294 | void *dp = cdataptr(cdataV(L->top-1)); /* Use preallocated object. */ | 302 | void *dp = cdataptr(cdataV(L->top-1)); /* Use preallocated object. */ |
| 295 | memcpy(dp, sp, ctr->size); /* Copy struct return value from GPRs. */ | 303 | memcpy(dp, sp, ctr->size); /* Copy struct return value from GPRs. */ |
| 296 | } | 304 | } |
| 297 | return 1; /* Return cdata object which is already on top of stack. */ | 305 | return 1; /* One GC step. */ |
| 298 | } | 306 | } |
| 299 | if (ctype_iscomplex(ctr->info)) { | 307 | if (ctype_iscomplex(ctr->info)) { |
| 308 | /* Return cdata object which is already on top of stack. */ | ||
| 300 | #if !CCALL_COMPLEX_RETREF || !CCALL_COMPLEXF_RETREF | 309 | #if !CCALL_COMPLEX_RETREF || !CCALL_COMPLEXF_RETREF |
| 301 | void *dp = cdataptr(cdataV(L->top-1)); /* Use preallocated object. */ | 310 | void *dp = cdataptr(cdataV(L->top-1)); /* Use preallocated object. */ |
| 302 | #if CCALL_COMPLEX_RETREF && !CCALL_COMPLEXF_RETREF | 311 | #if CCALL_COMPLEX_RETREF && !CCALL_COMPLEXF_RETREF |
| @@ -315,7 +324,7 @@ static int ccall_get_results(lua_State *L, CTState *cts, CType *ct, | |||
| 315 | memcpy(dp, sp, ctr->size); /* Copy complex from GPRs. */ | 324 | memcpy(dp, sp, ctr->size); /* Copy complex from GPRs. */ |
| 316 | #endif | 325 | #endif |
| 317 | #endif | 326 | #endif |
| 318 | return 1; /* Return cdata object which is already on top of stack. */ | 327 | return 1; /* One GC step. */ |
| 319 | } | 328 | } |
| 320 | #if CCALL_NUM_FPR | 329 | #if CCALL_NUM_FPR |
| 321 | if (ctype_isfp(ctr->info) || ctype_isvector(ctr->info)) | 330 | if (ctype_isfp(ctr->info) || ctype_isvector(ctr->info)) |
| @@ -323,8 +332,7 @@ static int ccall_get_results(lua_State *L, CTState *cts, CType *ct, | |||
| 323 | #endif | 332 | #endif |
| 324 | /* No reference types end up here, so there's no need for the CTypeID. */ | 333 | /* No reference types end up here, so there's no need for the CTypeID. */ |
| 325 | lua_assert(!(ctype_isrefarray(ctr->info) || ctype_isstruct(ctr->info))); | 334 | lua_assert(!(ctype_isrefarray(ctr->info) || ctype_isstruct(ctr->info))); |
| 326 | lj_cconv_tv_ct(cts, ctr, 0, L->top-1, (uint8_t *)sp); | 335 | return lj_cconv_tv_ct(cts, ctr, 0, L->top-1, (uint8_t *)sp); |
| 327 | return 1; /* One result. */ | ||
| 328 | } | 336 | } |
| 329 | 337 | ||
| 330 | /* Call C function. */ | 338 | /* Call C function. */ |
| @@ -338,10 +346,14 @@ int lj_ccall_func(lua_State *L, GCcdata *cd) | |||
| 338 | ct = ctype_rawchild(cts, ct); | 346 | ct = ctype_rawchild(cts, ct); |
| 339 | if (ctype_isfunc(ct->info)) { | 347 | if (ctype_isfunc(ct->info)) { |
| 340 | CCallState cc; | 348 | CCallState cc; |
| 349 | int gcsteps, ret; | ||
| 341 | cc.func = (void (*)(void))cdata_getptr(p, sz); | 350 | cc.func = (void (*)(void))cdata_getptr(p, sz); |
| 342 | ccall_set_args(L, cts, ct, &cc); | 351 | gcsteps = ccall_set_args(L, cts, ct, &cc); |
| 343 | lj_vm_ffi_call(&cc); | 352 | lj_vm_ffi_call(&cc); |
| 344 | return ccall_get_results(L, cts, ct, &cc); | 353 | gcsteps += ccall_get_results(L, cts, ct, &cc, &ret); |
| 354 | while (gcsteps-- > 0) | ||
| 355 | lj_gc_check(L); | ||
| 356 | return ret; | ||
| 345 | } | 357 | } |
| 346 | return -1; /* Not a function. */ | 358 | return -1; /* Not a function. */ |
| 347 | } | 359 | } |
