diff --git a/doc/ext_ffi.html b/doc/ext_ffi.html index e8e2a62b..f496b51b 100644 --- a/doc/ext_ffi.html +++ b/doc/ext_ffi.html @@ -73,8 +73,8 @@ The FFI library is tightly integrated into LuaJIT (it's not available as a separate module). The code generated by the JIT-compiler for accesses to C data structures from Lua code is on par with the code a C compiler would generate. Calls to C functions can -be inlined in the JIT-compiled code, unlike calls to functions bound -via the classic Lua/C API. +be inlined in JIT-compiled code, unlike calls to functions bound via +the classic Lua/C API.

This page gives a short introduction to the usage of the FFI library. @@ -253,14 +253,17 @@ would consume 40 Megabytes in plain Lua (on x64). Next, performance: the pure Lua version runs in 9.57 seconds (52.9 seconds with the Lua interpreter) and the FFI version runs in 0.48 seconds on my machine (YMMV). That's a factor of 20x faster (110x -faster than with plain Lua). +faster than the Lua interpreter).

The avid reader may notice that converting the pure Lua version over to use array indexes for the colors ([1] instead of .red, [2] instead of .green etc.) ought to be more compact and faster. This is certainly true (by a factor of -~1.7x), but the resulting code would be less idiomatic and rather +~1.7x). Switching to a struct-of-arrays would help, too. +

+

+However the resulting code would be less idiomatic and rather error-prone. And it still doesn't get even close to the performance of the FFI version of the code. Also, high-level data structures cannot be easily passed to other C functions, especially I/O functions, diff --git a/doc/ext_ffi_api.html b/doc/ext_ffi_api.html index f985d965..f0c4de90 100644 --- a/doc/ext_ffi_api.html +++ b/doc/ext_ffi_api.html @@ -195,23 +195,10 @@ require the nelem argument. The second syntax uses a ctype as a constructor and is otherwise fully equivalent.

-The init arguments provide optional initializers. The created -cdata object is filled with zero bytes if no initializers are given. -Scalar types accept a single initializer. Aggregates can either be -initialized with a flat list of initializers or a single aggregate -initializer (see the C type -conversion rules). Excess initializers cause an error. -

-

-If a single initializer is given for an array, it's repeated for all -remaining elements. This doesn't happen if two or more initializers -are given — all uninitialized elements are filled with zero -bytes. The fields of a struct are initialized in the order of -their declaration. Uninitialized fields are filled with zero bytes. -Only the first field of union can be initialized with a flat -initializer. Elements or fields which are aggregates themselves are -initialized with a single init argument, but this -may be an aggregate initializer of course. +The cdata object is initialized according to the +rules for initializers, +using the optional init arguments. Excess initializers cause +an error.

Performance notice: if you want to create many objects of one kind, @@ -357,8 +344,8 @@ order of arguments!

status = ffi.abi(param)

Returns true if param (a Lua string) applies for the -target ABI (Application Binary Interface). Otherwise returns -false. The following parameters are currently defined: +target ABI (Application Binary Interface). Returns false +otherwise. The following parameters are currently defined:

diff --git a/doc/ext_ffi_semantics.html b/doc/ext_ffi_semantics.html index 598d44c9..4a1b6c11 100644 --- a/doc/ext_ffi_semantics.html +++ b/doc/ext_ffi_semantics.html @@ -70,6 +70,47 @@ TODO TODO

+

Initializers

+

+Creating a cdata object with ffi.new() +or the equivalent constructor syntax always initializes its contents, +too. Different rules apply, depending on the number of optional +initializers and the C types involved: +

+ +

C Library Namespaces

A C library namespace is a special kind of object which allows diff --git a/src/lj_cconv.c b/src/lj_cconv.c index ac6374ed..d4578f88 100644 --- a/src/lj_cconv.c +++ b/src/lj_cconv.c @@ -679,17 +679,12 @@ static void cconv_struct_init(CTState *cts, CType *d, CTSize sz, uint8_t *dp, ** This is true if an aggregate is to be initialized with a value. ** Valarrays are treated as values here so ct_tv handles (V|C, I|F). */ -int lj_cconv_multi_init(CTState *cts, CType *d, TValue *o) +int lj_cconv_multi_init(CType *d, TValue *o) { if (!(ctype_isrefarray(d->info) || ctype_isstruct(d->info))) return 0; /* Destination is not an aggregate. */ if (tvistab(o) || (tvisstr(o) && !ctype_isstruct(d->info))) return 0; /* Initializer is not a value. */ - if (tviscdata(o)) { - CTInfo info = lj_ctype_rawref(cts, cdataV(o)->typeid)->info; - if (ctype_isrefarray(info) || ctype_isstruct(info)) - return 0; /* Initializer is not a value. */ - } return 1; /* Otherwise the initializer is a value. */ } @@ -699,7 +694,7 @@ void lj_cconv_ct_init(CTState *cts, CType *d, CTSize sz, { if (len == 0) memset(dp, 0, sz); - else if (len == 1 && !lj_cconv_multi_init(cts, d, o)) + else if (len == 1 && !lj_cconv_multi_init(d, o)) lj_cconv_ct_tv(cts, d, dp, o, 0); else if (ctype_isarray(d->info)) /* Also handles valarray init with len>1. */ cconv_array_init(cts, d, sz, dp, o, len); diff --git a/src/lj_cconv.h b/src/lj_cconv.h index acc09af9..494f9d4e 100644 --- a/src/lj_cconv.h +++ b/src/lj_cconv.h @@ -58,7 +58,7 @@ LJ_FUNC int lj_cconv_tv_bf(CTState *cts, CType *s, TValue *o, uint8_t *sp); LJ_FUNC void lj_cconv_ct_tv(CTState *cts, CType *d, uint8_t *dp, TValue *o, CTInfo flags); LJ_FUNC void lj_cconv_bf_tv(CTState *cts, CType *d, uint8_t *dp, TValue *o); -LJ_FUNC int lj_cconv_multi_init(CTState *cts, CType *d, TValue *o); +LJ_FUNC int lj_cconv_multi_init(CType *d, TValue *o); LJ_FUNC void lj_cconv_ct_init(CTState *cts, CType *d, CTSize sz, uint8_t *dp, TValue *o, MSize len); diff --git a/src/lj_crecord.c b/src/lj_crecord.c index c6577975..681c5029 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c @@ -566,8 +566,7 @@ static void crec_alloc(jit_State *J, RecordFFData *rd, CTypeID id) CType *d = ctype_raw(cts, id); TRef trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, TREF_NIL); J->base[0] = trcd; - if (J->base[1] && !J->base[2] && - !lj_cconv_multi_init(cts, d, &rd->argv[1])) { + if (J->base[1] && !J->base[2] && !lj_cconv_multi_init(d, &rd->argv[1])) { goto single_init; } else if (ctype_isarray(d->info)) { CType *dc = ctype_rawchild(cts, d); /* Array element type. */