diff options
-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 | } |