diff options
author | Andy Wingo <wingo@pobox.com> | 2013-06-28 20:01:35 +0200 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2013-06-28 20:01:35 +0200 |
commit | 98eaef1b50db626c672646da58645c62407d0c1a (patch) | |
tree | 814a737a115dff5f6c5230b3b27d51c140d6b7ac /libguile/fluids.c | |
parent | c32b7c4cef1c63a677a1c447a0386e90ab2ecd42 (diff) | |
download | guile-98eaef1b50db626c672646da58645c62407d0c1a.tar.gz |
Simplify dynstack API to only wind one fluid at a time
* libguile/dynstack.h (SCM_DYNSTACK_TYPE_WITH_FLUID): Rename from
with-fluids.
* libguile/dynstack.c (scm_dynstack_push_fluid):
(scm_dynstack_unwind_fluid): Change API to only wind/unwind one
fluid binding.
(WITH_FLUID_WORDS): New define, always 2 words (fluid and value box).
(WITH_FLUID_FLUID, WITH_FLUID_VALUE_BOX): New macros to get offsets of
fluid and value box.
(scm_dynstack_push_rewinder, scm_dynstack_push_unwinder): Use
WINDER_WORDS.
(scm_dynstack_push_dynwind): Use DYNWIND_WORDS.
(scm_dynstack_wind_1): Update for scm_swap_fluid API change.
* libguile/fluids.h:
* libguile/fluids.c (scm_prepare_fluids): Remove; no longer needed.
(scm_swap_fluid): Update to just swap one fluid binding.
(scm_c_with_fluids, scm_c_with_fluid): Update to use
scm_dynstack_push_fluid.
* libguile/memoize.c (do_push_fluid, do_pop_fluid): Adapt to API
change.
* libguile/vm-engine.c (rtl_vm_engine): Change wind-fluids / unwind-fluids
to push-fluid / pop-fluid, and actually enable. Woo!
* libguile/vm-i-system.c (push-fluid, pop-fluid): Update to new API.
Diffstat (limited to 'libguile/fluids.c')
-rw-r--r-- | libguile/fluids.c | 85 |
1 files changed, 18 insertions, 67 deletions
diff --git a/libguile/fluids.c b/libguile/fluids.c index 1199451b2..22d825beb 100644 --- a/libguile/fluids.c +++ b/libguile/fluids.c @@ -302,52 +302,17 @@ apply_thunk (void *thunk) return scm_call_0 (SCM_PACK (thunk)); } -size_t -scm_prepare_fluids (size_t n, SCM *fluids, SCM *values) -{ - size_t j; - - /* Ensure that there are no duplicates in the fluids set -- an N^2 operation, - but N will usually be small, so perhaps that's OK. */ - for (j = n; j--;) - { - size_t i; - - if (SCM_UNLIKELY (!IS_FLUID (fluids[j]))) - scm_wrong_type_arg ("with-fluids", 0, fluids[j]); - - for (i = j; i--;) - if (scm_is_eq (fluids[i], fluids[j])) - { - values[i] = values[j]; /* later bindings win */ - n--; - fluids[j] = fluids[n]; - values[j] = values[n]; - break; - } - } - - return n; -} - void -scm_swap_fluids (size_t n, SCM *fluids, SCM *values, SCM dynstate) +scm_swap_fluid (SCM fluid, SCM value_box, SCM dynstate) { - SCM fluid_vector; - size_t i, max = 0; + SCM fluid_vector, tmp; + size_t fluid_num; - fluid_vector = DYNAMIC_STATE_FLUIDS (dynstate); + fluid_num = FLUID_NUM (fluid); - /* We could cache the max in the with-fluids, but that would take more mem, - and we're touching all the fluids anyway, so this per-swap traversal should - be OK. */ - for (i = 0; i < n; i++) - { - size_t num = FLUID_NUM (fluids[i]); - max = (max > num) ? max : num; - } + fluid_vector = DYNAMIC_STATE_FLUIDS (dynstate); - if (SCM_UNLIKELY (max >= SCM_SIMPLE_VECTOR_LENGTH (fluid_vector))) + if (SCM_UNLIKELY (fluid_num >= SCM_SIMPLE_VECTOR_LENGTH (fluid_vector))) { /* Lazily grow the current thread's dynamic state. */ grow_dynamic_state (dynstate); @@ -355,17 +320,9 @@ scm_swap_fluids (size_t n, SCM *fluids, SCM *values, SCM dynstate) fluid_vector = DYNAMIC_STATE_FLUIDS (dynstate); } - /* Bind the fluids. Order doesn't matter, as all fluids are distinct. */ - for (i = 0; i < n; i++) - { - size_t fluid_num; - SCM x; - - fluid_num = FLUID_NUM (fluids[i]); - x = SCM_SIMPLE_VECTOR_REF (fluid_vector, fluid_num); - SCM_SIMPLE_VECTOR_SET (fluid_vector, fluid_num, values[i]); - values[i] = x; - } + tmp = SCM_SIMPLE_VECTOR_REF (fluid_vector, fluid_num); + SCM_SIMPLE_VECTOR_SET (fluid_vector, fluid_num, SCM_VARIABLE_REF (value_box)); + SCM_VARIABLE_SET (value_box, tmp); } SCM_DEFINE (scm_with_fluids, "with-fluids*", 3, 0, 0, @@ -387,7 +344,6 @@ scm_c_with_fluids (SCM fluids, SCM values, SCM (*cproc) (), void *cdata) { SCM ans; long flen, vlen, i; - SCM *fluidsv, *valuesv; scm_i_thread *thread = SCM_I_CURRENT_THREAD; SCM_VALIDATE_LIST_COPYLEN (1, fluids, flen); @@ -395,24 +351,19 @@ scm_c_with_fluids (SCM fluids, SCM values, SCM (*cproc) (), void *cdata) if (flen != vlen) scm_out_of_range (s_scm_with_fluids, values); - if (SCM_UNLIKELY (flen == 0)) - return cproc (cdata); - - fluidsv = alloca (sizeof(SCM)*flen); - valuesv = alloca (sizeof(SCM)*flen); - for (i = 0; i < flen; i++) { - fluidsv[i] = SCM_CAR (fluids); + scm_dynstack_push_fluid (&thread->dynstack, + SCM_CAR (fluids), SCM_CAR (values), + thread->dynamic_state); fluids = SCM_CDR (fluids); - valuesv[i] = SCM_CAR (values); values = SCM_CDR (values); } - scm_dynstack_push_fluids (&thread->dynstack, flen, fluidsv, valuesv, - thread->dynamic_state); ans = cproc (cdata); - scm_dynstack_unwind_fluids (&thread->dynstack, thread->dynamic_state); + + for (i = 0; i < flen; i++) + scm_dynstack_unwind_fluid (&thread->dynstack, thread->dynamic_state); return ans; } @@ -432,10 +383,10 @@ scm_c_with_fluid (SCM fluid, SCM value, SCM (*cproc) (), void *cdata) SCM ans; scm_i_thread *thread = SCM_I_CURRENT_THREAD; - scm_dynstack_push_fluids (&thread->dynstack, 1, &fluid, &value, - thread->dynamic_state); + scm_dynstack_push_fluid (&thread->dynstack, fluid, value, + thread->dynamic_state); ans = cproc (cdata); - scm_dynstack_unwind_fluids (&thread->dynstack, thread->dynamic_state); + scm_dynstack_unwind_fluid (&thread->dynstack, thread->dynamic_state); return ans; } |