diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-06-24 07:01:45 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-06-24 07:01:45 -0700 |
commit | 7de278b7c2971aef308ba43b786571fc1739aa00 (patch) | |
tree | 21e7481da7439bd8315ea4fc0d5fc114d2ba1ff5 /ffi.c | |
parent | 4cd1bf6f9fd47275e409d865c1f1c080f9e0c3ec (diff) | |
download | txr-7de278b7c2971aef308ba43b786571fc1739aa00.tar.gz txr-7de278b7c2971aef308ba43b786571fc1739aa00.tar.bz2 txr-7de278b7c2971aef308ba43b786571fc1739aa00.zip |
ffi: elide useless by-value in calls.
We can avoid calling in methods in the by-value nuance
(copy == 0) on types known not to have by-value in semantics.
Basic types have no by-value in.
Pointers inherently have by-value in.
An aggregate has by-value in semantics if any of one
of its members does, otherwise not.
* ffi.c (struct txr_ffi_type): New bitfield member,
by_value_in.
(ffi_ptr_in_in, ffi_ptr_in_d_in): Elite in call if target
type's by_value_in flag is clear.
(ffi_struct_in): Short-circuit to a return if doing by-value,
and the FFI struct type has no by-value semantics.
(ffi_array_in_common): Likewise. In this code change, we
just have to replace the test whether the element type has
an in method with a test of its by_value_in flag.
(make_ffi_type_pointer): Set by_value_in flag to 1, since
pointers have by value in semantics. This is true also of
ptr-in, because a structure passed as an in parameter to a
function via ptr-in could itself contain ptr or ptr-out
elements.
(make_ffi_type_struct): Set the type's by_value_in if
any element type's by_value_in is true.
(make_ffi_type_array): Propagate the by_value_in flag from
the element type to the array type.
(ffi_call_wrap): Calculate the in_pass_needed local flag
from the by_value_in flags of the arguments, not from whether
or not they have an in function. Only call the in function
for arguments which have the flag set.
Diffstat (limited to 'ffi.c')
-rw-r--r-- | ffi.c | 27 |
1 files changed, 16 insertions, 11 deletions
@@ -170,6 +170,7 @@ struct txr_ffi_type { struct smemb *memb; val sym_num, num_sym; unsigned null_term : 1; + unsigned by_value_in : 1; unsigned char_conv : 1; unsigned wchar_conv : 1; unsigned bchar_conv : 1; @@ -1969,7 +1970,7 @@ static val ffi_ptr_in_in(struct txr_ffi_type *tft, int copy, mem_t *src, val tgttype = tft->eltype; struct txr_ffi_type *tgtft = ffi_type_struct(tgttype); mem_t **loc = coerce(mem_t **, src); - if (tgtft->in != 0) + if (tgtft->in != 0 && tgtft->by_value_in) tgtft->in(tgtft, 0, *loc, obj, self); tgtft->free(*loc); *loc = 0; @@ -1982,7 +1983,7 @@ static val ffi_ptr_in_d_in(struct txr_ffi_type *tft, int copy, mem_t *src, val tgttype = tft->eltype; struct txr_ffi_type *tgtft = ffi_type_struct(tgttype); mem_t **loc = coerce(mem_t **, src); - if (tgtft->in != 0) + if (tgtft->in != 0 && tgtft->by_value_in) tgtft->in(tgtft, 0, *loc, obj, self); return obj; } @@ -2107,13 +2108,12 @@ static val ffi_struct_in(struct txr_ffi_type *tft, int copy, mem_t *src, cnum i, nmemb = tft->nelem; struct smemb *memb = tft->memb; + if (!copy && (!tft->by_value_in || strct == nil)) + return strct; + if (strct == nil) { - if (!copy) { - return nil; - } else { - args_decl(args, 0); - strct = make_struct(tft->lt, nil, args); - } + args_decl(args, 0); + strct = make_struct(tft->lt, nil, args); } for (i = 0; i < nmemb; i++) { @@ -2320,7 +2320,7 @@ 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)) + if (!copy && (!tft->by_value_in || vec == nil)) return vec; if (vec == nil) @@ -2776,6 +2776,7 @@ static val make_ffi_type_pointer(val syntax, val lisp_type, tft->release = release; tft->alloc = ffi_fixed_alloc; tft->free = free; + tft->by_value_in = 1; return obj; } @@ -2902,6 +2903,9 @@ static val make_ffi_type_struct(val syntax, val lisp_type, } need_out_handler = need_out_handler || mtft->out != 0; + + if (mtft->by_value_in) + tft->by_value_in = 1; } if (bit_offs > 0) { @@ -3043,6 +3047,7 @@ static val make_ffi_type_array(val syntax, val lisp_type, tft->release = ffi_array_release; tft->alloc = ffi_fixed_alloc; tft->free = free; + tft->by_value_in = etft->by_value_in; for (i = 0; i < nelem; i++) { if (i == 0) { @@ -4038,7 +4043,7 @@ val ffi_call_wrap(val fptr, val ffi_call_desc, struct args *args) for (i = 0; i < n; i++) { struct txr_ffi_type *mtft = type[i] = ffi_type_struct(pop(&types)); values[i] = zalloca(mtft->size); - in_pass_needed = in_pass_needed || mtft->in != 0; + in_pass_needed = in_pass_needed || mtft->by_value_in; } uw_simple_catch_begin; @@ -4070,7 +4075,7 @@ val ffi_call_wrap(val fptr, val ffi_call_desc, struct args *args) if (in_pass_needed) { for (i = 0; i < n; i++) { struct txr_ffi_type *mtft = type[i]; - if (mtft->in != 0) + if (mtft->by_value_in) mtft->in(mtft, 0, convert(mem_t *, values[i]), args->arg[i], self); } } |