summaryrefslogtreecommitdiffstats
path: root/ffi.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-04-28 07:02:45 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-04-28 07:02:45 -0700
commit0f77a3213364452bcf63f0bb09a4049f9f5a4214 (patch)
treec8fb60138fa6184331a452dce253fff660206f6c /ffi.c
parentf4052f3a57893cab06a44dbae76f78dd7ea885d1 (diff)
downloadtxr-0f77a3213364452bcf63f0bb09a4049f9f5a4214.tar.gz
txr-0f77a3213364452bcf63f0bb09a4049f9f5a4214.tar.bz2
txr-0f77a3213364452bcf63f0bb09a4049f9f5a4214.zip
ffi: setup in functions at type compile time.
* ffi.c (ffi_str_put, ffi_ptr_in_put, ffi_ptr_out_put, ffi_ptr_in_out_put): Don't set up tft->in pointer at dynamic time; this is now being done at static time, in ffi_type_compile. (ff_struct_put, ffi_array_put): Similarly, don't calculate whether an in handler is needed or not based on the child type elements; this is determined statically. (make_ffi_type_pointer): Take an in function pointer argument, since all callers need to set this up. (make_ffi_type_struct): Set up an in handler for this type if any of the structure element types need one. (make_ffi_type_array): Set up an in handler for this type if the element type needs it. (ffi_type_compile): For the three ptr types, pass the appropriate in function to make_ffi_type_pointer. For the str type, set up the in pointer to ffi_freeing_in, after constructing as a builtin type.
Diffstat (limited to 'ffi.c')
-rw-r--r--ffi.c37
1 files changed, 19 insertions, 18 deletions
diff --git a/ffi.c b/ffi.c
index d10e3c34..b760bfb2 100644
--- a/ffi.c
+++ b/ffi.c
@@ -582,7 +582,6 @@ static void ffi_str_put(struct txr_ffi_type *tft,
char *u8s = utf8_dup_to(ws);
free(tft->buf);
tft->buf = coerce(mem_t *, u8s);
- tft->in = ffi_freeing_in;
*coerce(const char **, dst) = u8s;
}
@@ -647,7 +646,6 @@ static void ffi_ptr_in_put(struct txr_ffi_type *tft,
mem_t *buf = tgtft->alloc(tgtft, s, self);
tgtft->put(tgtft, s, buf, self);
tft->buf = buf;
- tft->in = ffi_ptr_in_in;
}
static void ffi_ptr_out_in(struct txr_ffi_type *tft, val obj, val self)
@@ -667,7 +665,6 @@ static void ffi_ptr_out_put(struct txr_ffi_type *tft,
struct txr_ffi_type *tgtft = ffi_type_struct(tgttype);
mem_t *buf = tgtft->alloc(tgtft, s, self);
tft->buf = buf;
- tft->in = ffi_ptr_out_in;
*coerce(mem_t **, dst) = buf;
}
@@ -687,7 +684,6 @@ static void ffi_ptr_in_out_put(struct txr_ffi_type *tft,
mem_t *buf = tgtft->alloc(tgtft, s, self);
tgtft->put(tgtft, s, buf, self);
tft->buf = buf;
- tft->in = ffi_ptr_out_in;
*coerce(mem_t **, dst) = buf;
}
@@ -709,7 +705,6 @@ static void ffi_struct_put(struct txr_ffi_type *tft,
val slots = tft->mnames;
val types = tft->mtypes;
ucnum offs = 0;
- int in_pass_needed = 0;
while (slots) {
val slsym = pop(&slots);
@@ -720,10 +715,7 @@ static void ffi_struct_put(struct txr_ffi_type *tft,
offs = (offs + almask) & ~almask;
mtft->put(mtft, slval, dst + offs, self);
offs += mtft->size;
- in_pass_needed = in_pass_needed || mtft->in != 0;
}
-
- tft->in = (in_pass_needed ? ffi_struct_in : 0);
}
static val ffi_struct_get(struct txr_ffi_type *tft, mem_t *src, val self)
@@ -788,7 +780,6 @@ static void ffi_array_put(struct txr_ffi_type *tft,
val eltypes = tft->mtypes;
cnum nelem = tft->nelem, i;
ucnum offs = 0;
- int in_pass_needed = 0;
for (i = 0; i < nelem; i++) {
val eltype = pop(&eltypes);
@@ -797,10 +788,7 @@ static void ffi_array_put(struct txr_ffi_type *tft,
val elval = ref(vec, num_fast(i));
etft->put(etft, elval, dst + offs, self);
offs += elsize;
- in_pass_needed = in_pass_needed || etft->in != 0;
}
-
- tft->in = (in_pass_needed ? ffi_array_in : 0);
}
static val ffi_array_get(struct txr_ffi_type *tft, mem_t *src, val self)
@@ -870,6 +858,8 @@ static val make_ffi_type_pointer(val syntax, val lisp_type,
val obj, mem_t *dst, val self),
val (*get)(struct txr_ffi_type *,
mem_t *src, val self),
+ void (*in)(struct txr_ffi_type *,
+ val obj, val self),
val tgtype)
{
struct txr_ffi_type *tft = coerce(struct txr_ffi_type *,
@@ -885,6 +875,7 @@ static val make_ffi_type_pointer(val syntax, val lisp_type,
tft->put = put;
tft->get = get;
tft->mtypes = tgtype;
+ tft->in = in;
tft->alloc = ffi_fixed_alloc;
tft->free = free;
@@ -905,6 +896,7 @@ static val make_ffi_type_struct(val syntax, val lisp_type,
val obj = cobj(coerce(mem_t *, tft), ffi_type_s, &ffi_type_struct_ops);
cnum total_size = 0;
cnum most_align = 0;
+ int in_handler_needed = 0;
ft->type = FFI_TYPE_STRUCT;
ft->size = 0;
@@ -932,10 +924,14 @@ static val make_ffi_type_struct(val syntax, val lisp_type,
most_align = align;
total_size = (total_size + align - 1) / align * align + size;
+ in_handler_needed = in_handler_needed || mtft->in != 0;
}
elements[i] = 0;
+ if (in_handler_needed)
+ tft->in = ffi_struct_in;
+
ft->elements = elements;
total_size = (total_size + most_align - 1) / most_align * most_align;
@@ -980,6 +976,8 @@ static val make_ffi_type_array(val syntax, val lisp_type,
tft->size = etft->size * nelem;
tft->align = etft->align;
}
+ if (i == 0 && etft->in != 0)
+ tft->in = ffi_array_in;
}
elements[i] = 0;
@@ -1044,7 +1042,7 @@ val ffi_type_compile(val syntax)
return make_ffi_type_pointer(syntax, cptr_s, sizeof (mem_t *),
&ffi_type_pointer,
ffi_ptr_in_put, ffi_void_get,
- target_type);
+ ffi_ptr_in_in, target_type);
} else if (sym == ptr_out_s) {
val target_type = ffi_type_compile(cadr(syntax));
struct txr_ffi_type *tft = ffi_type_struct(target_type);
@@ -1054,7 +1052,7 @@ val ffi_type_compile(val syntax)
return make_ffi_type_pointer(syntax, cptr_s, sizeof (mem_t *),
&ffi_type_pointer,
ffi_ptr_out_put, ffi_ptr_out_get,
- target_type);
+ ffi_ptr_out_in, target_type);
} else if (sym == ptr_in_out_s) {
val target_type = ffi_type_compile(cadr(syntax));
struct txr_ffi_type *tft = ffi_type_struct(target_type);
@@ -1064,7 +1062,7 @@ val ffi_type_compile(val syntax)
return make_ffi_type_pointer(syntax, cptr_s, sizeof (mem_t *),
&ffi_type_pointer,
ffi_ptr_in_out_put, ffi_ptr_out_get,
- target_type);
+ ffi_ptr_out_in, target_type);
} else if (sym == buf_s) {
cnum nelem = c_num(cadr(syntax));
val type = make_ffi_type_builtin(syntax, cptr_s, sizeof (mem_t *),
@@ -1171,9 +1169,12 @@ val ffi_type_compile(val syntax)
tft->free = ffi_noop_free;
return type;
} else if (syntax == str_s) {
- return make_ffi_type_builtin(syntax, cptr_s, sizeof (mem_t *),
- &ffi_type_pointer,
- ffi_str_put, ffi_str_get);
+ val type = make_ffi_type_builtin(syntax, cptr_s, sizeof (mem_t *),
+ &ffi_type_pointer,
+ ffi_str_put, ffi_str_get);
+ struct txr_ffi_type *tft = ffi_type_struct(type);
+ tft->in = ffi_freeing_in;
+ return type;
} else if (syntax == wstr_s) {
return make_ffi_type_builtin(syntax, cptr_s, sizeof (mem_t *),
&ffi_type_pointer,