diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-06-23 22:29:45 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-06-23 22:29:45 -0700 |
commit | 4cd1bf6f9fd47275e409d865c1f1c080f9e0c3ec (patch) | |
tree | 73ae9bcd5289deabd838caa0af3c2bfde4f37166 /ffi.c | |
parent | af052dcb0df9aeb5411ba8b60f1890dd46cc6c35 (diff) | |
download | txr-4cd1bf6f9fd47275e409d865c1f1c080f9e0c3ec.tar.gz txr-4cd1bf6f9fd47275e409d865c1f1c080f9e0c3ec.tar.bz2 txr-4cd1bf6f9fd47275e409d865c1f1c080f9e0c3ec.zip |
ffi: short-circuit useless by-value in semantics.
The theme here is that if a struct or array is
being subject to a by-value in operation, there
is nothing to do for that aggregate itself. So
if there is no corresponding Lisp object, we
should not create one. The caller isn't expecting
it and will throw it away. If it is known that no
element of an aggregate supports by-value semantics,
then the operation should short-circuit, and not
perform a useless loop.
* ffi.c (ffi_struct_in): If the strct parameter is nil,
don't unconditionally make a new structure; do so only
when the copy flag is asserted (by reference semantics).
If there is no Lisp struct object and by value semantics is
in effect, there is no point in doing anything; just
short-circuit to a nil return.
(ffi_array_in_common): If doing by value semantics, and
there is no vector object or the structure element type
has no by value in semantics (such as a basic type),
then short circuit to an early return.
(ffi_array_in): Only do the special string decoding when
reference semantics is in effect; there is no point
in extracting strings back from a by-value struct.
If by-value semantics is in effect, we fall through to
the ffi_array_in_common call even for character types;
but since those types have no by-value in semantics,
that function will just short-circuit, which is what we want.
(ffi_varray_in): If there is no vec, bail out with nil,
regardless of whether this is by value or not.
Just return vec if by-value semantics is in effect; don't
try to update it.
Diffstat (limited to 'ffi.c')
-rw-r--r-- | ffi.c | 41 |
1 files changed, 26 insertions, 15 deletions
@@ -2108,8 +2108,12 @@ static val ffi_struct_in(struct txr_ffi_type *tft, int copy, mem_t *src, struct smemb *memb = tft->memb; if (strct == nil) { - args_decl(args, 0); - strct = make_struct(tft->lt, nil, args); + if (!copy) { + return nil; + } else { + args_decl(args, 0); + strct = make_struct(tft->lt, nil, args); + } } for (i = 0; i < nmemb; i++) { @@ -2316,6 +2320,9 @@ static val ffi_array_in_common(struct txr_ffi_type *tft, int copy, cnum znelem = if3(tft->null_term && nelem > 0 && vec && length(vec) < num_fast(nelem), nelem - 1, nelem); + if (!copy && (etft->in == 0 || vec == nil)) + return vec; + if (vec == nil) vec = vector(num_fast(znelem), nil); @@ -2336,18 +2343,19 @@ static val ffi_array_in_common(struct txr_ffi_type *tft, int copy, static val ffi_array_in(struct txr_ffi_type *tft, int copy, mem_t *src, val vec, val self) { - if (tft->char_conv) { - val str = ffi_char_array_get(tft, src, tft->nelem); - return if3(vec, replace(vec, str, zero, t), str); - } else if (tft->wchar_conv) { - val str = ffi_wchar_array_get(tft, src, tft->nelem); - return if3(vec, replace(vec, str, zero, t), str); - } else if (tft->bchar_conv) { - val str = ffi_bchar_array_get(tft, src, tft->nelem); - return if3(vec, replace(vec, str, zero, t), str); - } else { - return ffi_array_in_common(tft, copy, src, vec, self, tft->nelem); + if (copy) { + if (tft->char_conv) { + val str = ffi_char_array_get(tft, src, tft->nelem); + return if3(vec, replace(vec, str, zero, t), str); + } else if (tft->wchar_conv) { + val str = ffi_wchar_array_get(tft, src, tft->nelem); + return if3(vec, replace(vec, str, zero, t), str); + } else if (tft->bchar_conv) { + val str = ffi_bchar_array_get(tft, src, tft->nelem); + return if3(vec, replace(vec, str, zero, t), str); + } } + return ffi_array_in_common(tft, copy, src, vec, self, tft->nelem); } static void ffi_array_put_common(struct txr_ffi_type *tft, val vec, mem_t *dst, @@ -2498,8 +2506,11 @@ static void ffi_varray_put(struct txr_ffi_type *tft, val vec, mem_t *dst, static val ffi_varray_in(struct txr_ffi_type *tft, int copy, mem_t *src, val vec, val self) { - cnum nelem = c_num(length(vec)) + tft->null_term; - return ffi_array_in_common(tft, copy, src, vec, self, nelem); + if (copy && vec) { + cnum nelem = c_num(length(vec)) + tft->null_term; + return ffi_array_in_common(tft, copy, src, vec, self, nelem); + } + return vec; } static val ffi_varray_null_term_in(struct txr_ffi_type *tft, int copy, mem_t *src, |