summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2011-01-23 14:23:21 +0100
committerMike Pall <mike>2011-01-23 14:23:21 +0100
commit72b3fff72f6bb9cf5796bbcd50e9a490d4e02b4b (patch)
tree5ee063bd3f5af95dddda47f30c67adfe5bc0e5ad
parentf529d22869429d458c5382cf6787f213d7bd5296 (diff)
downloadluajit-72b3fff72f6bb9cf5796bbcd50e9a490d4e02b4b.tar.gz
luajit-72b3fff72f6bb9cf5796bbcd50e9a490d4e02b4b.tar.bz2
luajit-72b3fff72f6bb9cf5796bbcd50e9a490d4e02b4b.zip
FFI: Simplify initializer rules. Clarify docs.
-rw-r--r--doc/ext_ffi.html11
-rw-r--r--doc/ext_ffi_api.html25
-rw-r--r--doc/ext_ffi_semantics.html41
-rw-r--r--src/lj_cconv.c9
-rw-r--r--src/lj_cconv.h2
-rw-r--r--src/lj_crecord.c3
6 files changed, 58 insertions, 33 deletions
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
73as a separate module). The code generated by the JIT-compiler for 73as a separate module). The code generated by the JIT-compiler for
74accesses to C&nbsp;data structures from Lua code is on par with the 74accesses to C&nbsp;data structures from Lua code is on par with the
75code a C&nbsp;compiler would generate. Calls to C&nbsp;functions can 75code a C&nbsp;compiler would generate. Calls to C&nbsp;functions can
76be inlined in the JIT-compiled code, unlike calls to functions bound 76be inlined in JIT-compiled code, unlike calls to functions bound via
77via the classic Lua/C API. 77the classic Lua/C API.
78</p> 78</p>
79<p> 79<p>
80This page gives a short introduction to the usage of the FFI library. 80This page gives a short introduction to the usage of the FFI library.
@@ -253,14 +253,17 @@ would consume 40&nbsp;Megabytes in plain Lua (on x64).
253Next, performance: the pure Lua version runs in 9.57 seconds (52.9 253Next, performance: the pure Lua version runs in 9.57 seconds (52.9
254seconds with the Lua interpreter) and the FFI version runs in 0.48 254seconds with the Lua interpreter) and the FFI version runs in 0.48
255seconds on my machine (YMMV). That's a factor of 20x faster (110x 255seconds on my machine (YMMV). That's a factor of 20x faster (110x
256faster than with plain Lua). 256faster than the Lua interpreter).
257</p> 257</p>
258<p style="font-size: 8pt;"> 258<p style="font-size: 8pt;">
259The avid reader may notice that converting the pure Lua version over 259The avid reader may notice that converting the pure Lua version over
260to use array indexes for the colors (<tt>[1]</tt> instead of 260to use array indexes for the colors (<tt>[1]</tt> instead of
261<tt>.red</tt>, <tt>[2]</tt> instead of <tt>.green</tt> etc.) ought to 261<tt>.red</tt>, <tt>[2]</tt> instead of <tt>.green</tt> etc.) ought to
262be more compact and faster. This is certainly true (by a factor of 262be more compact and faster. This is certainly true (by a factor of
263~1.7x), but the resulting code would be less idiomatic and rather 263~1.7x). Switching to a struct-of-arrays would help, too.
264</p>
265<p style="font-size: 8pt;">
266However the resulting code would be less idiomatic and rather
264error-prone. And it still doesn't get even close to the performance of 267error-prone. And it still doesn't get even close to the performance of
265the FFI version of the code. Also, high-level data structures cannot 268the FFI version of the code. Also, high-level data structures cannot
266be easily passed to other C&nbsp;functions, especially I/O functions, 269be easily passed to other C&nbsp;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 <tt>nelem</tt> argument. The second syntax uses a ctype as
195a constructor and is otherwise fully equivalent. 195a constructor and is otherwise fully equivalent.
196</p> 196</p>
197<p> 197<p>
198The <tt>init</tt> arguments provide optional initializers. The created 198The cdata object is initialized according to the
199cdata object is filled with zero bytes if no initializers are given. 199<a href="ext_ffi_semantics.html#init">rules for initializers</a>,
200Scalar types accept a single initializer. Aggregates can either be 200using the optional <tt>init</tt> arguments. Excess initializers cause
201initialized with a flat list of initializers or a single aggregate 201an error.
202initializer (see the <a href="ext_ffi_semantics.html#convert">C&nbsp;type
203conversion rules</a>). Excess initializers cause an error.
204</p>
205<p>
206If a single initializer is given for an array, it's repeated for all
207remaining elements. This doesn't happen if two or more initializers
208are given &mdash; all uninitialized elements are filled with zero
209bytes. The fields of a <tt>struct</tt> are initialized in the order of
210their declaration. Uninitialized fields are filled with zero bytes.
211Only the first field of <tt>union</tt> can be initialized with a flat
212initializer. Elements or fields which are aggregates themselves are
213initialized with a <em>single</em> <tt>init</tt> argument, but this
214may be an aggregate initializer of course.
215</p> 202</p>
216<p> 203<p>
217Performance notice: if you want to create many objects of one kind, 204Performance notice: if you want to create many objects of one kind,
@@ -357,8 +344,8 @@ order of arguments!
357<h3 id="ffi_abi"><tt>status = ffi.abi(param)</tt></h3> 344<h3 id="ffi_abi"><tt>status = ffi.abi(param)</tt></h3>
358<p> 345<p>
359Returns <tt>true</tt> if <tt>param</tt> (a Lua string) applies for the 346Returns <tt>true</tt> if <tt>param</tt> (a Lua string) applies for the
360target ABI (Application Binary Interface). Otherwise returns 347target ABI (Application Binary Interface). Returns <tt>false</tt>
361<tt>false</tt>. The following parameters are currently defined: 348otherwise. The following parameters are currently defined:
362</p> 349</p>
363<table class="abitable"> 350<table class="abitable">
364<tr class="abihead"> 351<tr class="abihead">
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
70TODO 70TODO
71</p> 71</p>
72 72
73<h2 id="init">Initializers</h2>
74<p>
75Creating a cdata object with <a href="ffi_ext_api.html#ffi_new">ffi.new()</a>
76or the equivalent constructor syntax always initializes its contents,
77too. Different rules apply, depending on the number of optional
78initializers and the C&nbsp;types involved:
79</p>
80<ul>
81<li>If no initializers are given, the object is filled with zero bytes.</li>
82
83<li>Scalar types (numbers and pointers) accept a single initializer.
84The standard <a href="#convert">C&nbsp;type conversion rules</a>
85apply.</li>
86
87<li>Valarrays (complex numbers and vectors) are treated like scalars
88when a single initializer is given. Otherwise they are treated like
89regular arrays.</li>
90
91<li>Aggregate types (arrays and structs) accept either a single
92compound initializer (Lua table or string) or a flat list of
93initializers.</li>
94
95<li>The elements of an array are initialized, starting at index zero.
96If a single initializer is given for an array, it's repeated for all
97remaining elements. This doesn't happen if two or more initializers
98are given: all remaining uninitialized elements are filled with zero
99bytes.</li>
100
101<li>The fields of a <tt>struct</tt> are initialized in the order of
102their declaration. Uninitialized fields are filled with zero
103bytes.</li>
104
105<li>Only the first field of a <tt>union</tt> can be initialized with a
106flat initializer.</li>
107
108<li>Elements or fields which are aggregates themselves are initialized
109with a <em>single</em> initializer, but this may be a compound
110initializer or a compatible aggregate, of course.</li>
111
112</ul>
113
73<h2 id="clib">C Library Namespaces</h2> 114<h2 id="clib">C Library Namespaces</h2>
74<p> 115<p>
75A C&nbsp;library namespace is a special kind of object which allows 116A C&nbsp;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,
679** This is true if an aggregate is to be initialized with a value. 679** This is true if an aggregate is to be initialized with a value.
680** Valarrays are treated as values here so ct_tv handles (V|C, I|F). 680** Valarrays are treated as values here so ct_tv handles (V|C, I|F).
681*/ 681*/
682int lj_cconv_multi_init(CTState *cts, CType *d, TValue *o) 682int lj_cconv_multi_init(CType *d, TValue *o)
683{ 683{
684 if (!(ctype_isrefarray(d->info) || ctype_isstruct(d->info))) 684 if (!(ctype_isrefarray(d->info) || ctype_isstruct(d->info)))
685 return 0; /* Destination is not an aggregate. */ 685 return 0; /* Destination is not an aggregate. */
686 if (tvistab(o) || (tvisstr(o) && !ctype_isstruct(d->info))) 686 if (tvistab(o) || (tvisstr(o) && !ctype_isstruct(d->info)))
687 return 0; /* Initializer is not a value. */ 687 return 0; /* Initializer is not a value. */
688 if (tviscdata(o)) {
689 CTInfo info = lj_ctype_rawref(cts, cdataV(o)->typeid)->info;
690 if (ctype_isrefarray(info) || ctype_isstruct(info))
691 return 0; /* Initializer is not a value. */
692 }
693 return 1; /* Otherwise the initializer is a value. */ 688 return 1; /* Otherwise the initializer is a value. */
694} 689}
695 690
@@ -699,7 +694,7 @@ void lj_cconv_ct_init(CTState *cts, CType *d, CTSize sz,
699{ 694{
700 if (len == 0) 695 if (len == 0)
701 memset(dp, 0, sz); 696 memset(dp, 0, sz);
702 else if (len == 1 && !lj_cconv_multi_init(cts, d, o)) 697 else if (len == 1 && !lj_cconv_multi_init(d, o))
703 lj_cconv_ct_tv(cts, d, dp, o, 0); 698 lj_cconv_ct_tv(cts, d, dp, o, 0);
704 else if (ctype_isarray(d->info)) /* Also handles valarray init with len>1. */ 699 else if (ctype_isarray(d->info)) /* Also handles valarray init with len>1. */
705 cconv_array_init(cts, d, sz, dp, o, len); 700 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);
58LJ_FUNC void lj_cconv_ct_tv(CTState *cts, CType *d, 58LJ_FUNC void lj_cconv_ct_tv(CTState *cts, CType *d,
59 uint8_t *dp, TValue *o, CTInfo flags); 59 uint8_t *dp, TValue *o, CTInfo flags);
60LJ_FUNC void lj_cconv_bf_tv(CTState *cts, CType *d, uint8_t *dp, TValue *o); 60LJ_FUNC void lj_cconv_bf_tv(CTState *cts, CType *d, uint8_t *dp, TValue *o);
61LJ_FUNC int lj_cconv_multi_init(CTState *cts, CType *d, TValue *o); 61LJ_FUNC int lj_cconv_multi_init(CType *d, TValue *o);
62LJ_FUNC void lj_cconv_ct_init(CTState *cts, CType *d, CTSize sz, 62LJ_FUNC void lj_cconv_ct_init(CTState *cts, CType *d, CTSize sz,
63 uint8_t *dp, TValue *o, MSize len); 63 uint8_t *dp, TValue *o, MSize len);
64 64
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)
566 CType *d = ctype_raw(cts, id); 566 CType *d = ctype_raw(cts, id);
567 TRef trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, TREF_NIL); 567 TRef trcd = emitir(IRTG(IR_CNEW, IRT_CDATA), trid, TREF_NIL);
568 J->base[0] = trcd; 568 J->base[0] = trcd;
569 if (J->base[1] && !J->base[2] && 569 if (J->base[1] && !J->base[2] && !lj_cconv_multi_init(d, &rd->argv[1])) {
570 !lj_cconv_multi_init(cts, d, &rd->argv[1])) {
571 goto single_init; 570 goto single_init;
572 } else if (ctype_isarray(d->info)) { 571 } else if (ctype_isarray(d->info)) {
573 CType *dc = ctype_rawchild(cts, d); /* Array element type. */ 572 CType *dc = ctype_rawchild(cts, d); /* Array element type. */