summaryrefslogtreecommitdiffstats
path: root/ffi.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-06-23 22:29:45 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-06-23 22:29:45 -0700
commit4cd1bf6f9fd47275e409d865c1f1c080f9e0c3ec (patch)
tree73ae9bcd5289deabd838caa0af3c2bfde4f37166 /ffi.c
parentaf052dcb0df9aeb5411ba8b60f1890dd46cc6c35 (diff)
downloadtxr-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.c41
1 files changed, 26 insertions, 15 deletions
diff --git a/ffi.c b/ffi.c
index 3e73f1fb..78eb00b0 100644
--- a/ffi.c
+++ b/ffi.c
@@ -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,