summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2025-05-09 12:49:42 +0200
committerAndy Wingo <wingo@pobox.com>2025-05-12 13:45:21 +0200
commit2463a0741f45e42b1ed93e948d839c7bda98e317 (patch)
treed7e0f5c40170f5c826d6f77eddac0035e4b5d27a
parent134c3be4528de0ed178980d33c9bcbca18d72cf0 (diff)
downloadguile-2463a0741f45e42b1ed93e948d839c7bda98e317.tar.gz
Rework fluids to use ephemeron hash tables
* libguile/ephemerons.c (scm_from_ephemeron, scm_to_ephemeron): (scm_from_ephemeron_table, scm_to_ephemeron_table): New interfaces. (scm_c_ephemeron_table_copy): Rename from scm_c_ephemeron_hash_table_copy, as it's not specific to hash tables. * libguile/fluids.h: * libguile/fluids.c (restore_dynamic_state, save_dynamic_state) (saved_dynamic_state_ref, fluid_set_x, fluid_ref) (scm_fluid_ref_star, scm_i_make_initial_dynamic_state): Use ephemeron hash tables.
-rw-r--r--libguile/ephemerons.c70
-rw-r--r--libguile/ephemerons.h8
-rw-r--r--libguile/fluids.c53
-rw-r--r--libguile/fluids.h5
4 files changed, 80 insertions, 56 deletions
diff --git a/libguile/ephemerons.c b/libguile/ephemerons.c
index 25fc760b2..7a2f75076 100644
--- a/libguile/ephemerons.c
+++ b/libguile/ephemerons.c
@@ -57,6 +57,8 @@ static inline struct gc_ref scm_to_ref (SCM scm)
+#define SCM_EPHEMERON_P(X) (SCM_HAS_TYP7 (X, scm_tc7_ephemeron))
+
struct gc_ephemeron*
scm_c_make_ephemeron (SCM key, SCM val)
{
@@ -75,6 +77,20 @@ scm_as_ephemeron (SCM x)
}
SCM
+scm_from_ephemeron (struct gc_ephemeron *e)
+{
+ return PTR2SCM (e);
+}
+
+struct gc_ephemeron*
+scm_to_ephemeron (SCM e)
+{
+ if (!SCM_EPHEMERON_P (e))
+ abort ();
+ return scm_as_ephemeron (e);
+}
+
+SCM
scm_c_ephemeron_key (struct gc_ephemeron *e)
{
struct gc_ref ret = gc_ephemeron_key (e);
@@ -109,9 +125,8 @@ scm_c_ephemeron_next (struct gc_ephemeron *e)
return gc_ephemeron_chain_next (e);
}
-
-#define SCM_EPHEMERON_P(X) (SCM_HAS_TYP7 (X, scm_tc7_ephemeron))
+
#define SCM_VALIDATE_EPHEMERON(pos, x) \
SCM_MAKE_VALIDATE_MSG (pos, x, EPHEMERON_P, "ephemeron")
@@ -214,6 +229,20 @@ scm_as_ephemeron_table (SCM x)
return (struct scm_ephemeron_table*) SCM_UNPACK_POINTER (x);
}
+SCM
+scm_from_ephemeron_table (struct scm_ephemeron_table *et)
+{
+ return PTR2SCM (et);
+}
+
+struct scm_ephemeron_table*
+scm_to_ephemeron_table (SCM et)
+{
+ if (!SCM_EPHEMERON_TABLE_P (et))
+ abort ();
+ return scm_as_ephemeron_table (et);
+}
+
struct scm_ephemeron_table
{
scm_t_bits tag;
@@ -270,6 +299,25 @@ scm_c_ephemeron_table_try_push_x (struct scm_ephemeron_table *et, size_t idx,
return prev;
}
+struct scm_ephemeron_table*
+scm_c_ephemeron_table_copy (struct scm_ephemeron_table *et)
+{
+ struct scm_ephemeron_table *ret = scm_c_make_ephemeron_table (et->size);
+
+ for (size_t idx = 0; idx < ret->size; idx++)
+ for (struct gc_ephemeron *e = scm_c_ephemeron_table_ref (et, idx);
+ e;
+ e = scm_c_ephemeron_next (e))
+ {
+ SCM key = scm_c_ephemeron_key (e);
+ SCM value = scm_c_ephemeron_value (e);
+ struct gc_ephemeron *copy = scm_c_make_ephemeron (key, value);
+ scm_c_ephemeron_table_push_x (ret, idx, copy);
+ }
+
+ return ret;
+}
+
SCM_DEFINE_STATIC (scm_ephemeron_table_p, "ephemeron-table?", 1, 0, 0,
(SCM x),
"Return @code{#t} if @var{x} is an ephemeron table, or "
@@ -409,24 +457,6 @@ scm_c_ephemeron_hash_table_setq_x (struct scm_ephemeron_table *et, SCM key,
} while (prev != chain);
}
-struct scm_ephemeron_table*
-scm_c_ephemeron_hash_table_copy (struct scm_ephemeron_table *et)
-{
- struct scm_ephemeron_table *ret = scm_c_make_ephemeron_table (et->size);
-
- for (size_t idx = 0; idx < ret->size; idx++)
- for (struct gc_ephemeron *e = scm_c_ephemeron_table_ref (et, idx);
- e;
- e = scm_c_ephemeron_next (e))
- {
- SCM key = scm_c_ephemeron_key (e);
- SCM value = scm_c_ephemeron_value (e);
- struct gc_ephemeron *copy = scm_c_make_ephemeron (key, value);
- scm_c_ephemeron_table_push_x (ret, idx, copy);
- }
-
- return ret;
-}
diff --git a/libguile/ephemerons.h b/libguile/ephemerons.h
index d3f403a70..d1eb9e548 100644
--- a/libguile/ephemerons.h
+++ b/libguile/ephemerons.h
@@ -36,6 +36,8 @@ SCM_INTERNAL SCM scm_c_ephemeron_swap_x (struct gc_ephemeron *e, SCM new_val);
SCM_INTERNAL void scm_c_ephemeron_mark_dead_x (struct gc_ephemeron *e);
SCM_INTERNAL int scm_i_print_ephemeron (SCM exp, SCM port,
scm_print_state *pstate SCM_UNUSED);
+SCM_INTERNAL struct gc_ephemeron* scm_to_ephemeron (SCM e);
+SCM_INTERNAL SCM scm_from_ephemeron (struct gc_ephemeron *e);
SCM_INTERNAL struct scm_ephemeron_table* scm_c_make_ephemeron_table (size_t count);
SCM_INTERNAL size_t scm_c_ephemeron_table_length (struct scm_ephemeron_table *et);
@@ -49,16 +51,18 @@ scm_c_ephemeron_table_try_push_x (struct scm_ephemeron_table *et,
size_t idx,
struct gc_ephemeron * e,
struct gc_ephemeron *prev);
+SCM_INTERNAL struct scm_ephemeron_table*
+scm_c_ephemeron_table_copy (struct scm_ephemeron_table *et);
SCM_INTERNAL int scm_i_print_ephemeron_table (SCM exp, SCM port,
scm_print_state *pstate SCM_UNUSED);
+SCM_INTERNAL struct scm_ephemeron_table* scm_to_ephemeron_table (SCM e);
+SCM_INTERNAL SCM scm_from_ephemeron_table (struct scm_ephemeron_table *e);
SCM_INTERNAL SCM
scm_c_ephemeron_hash_table_refq (struct scm_ephemeron_table *et, SCM k,
SCM default_value);
SCM_INTERNAL void
scm_c_ephemeron_hash_table_setq_x (struct scm_ephemeron_table *et, SCM k, SCM v);
-SCM_INTERNAL struct scm_ephemeron_table*
-scm_c_ephemeron_hash_table_copy (struct scm_ephemeron_table *et);
SCM_INTERNAL void scm_register_ephemerons (void);
diff --git a/libguile/fluids.c b/libguile/fluids.c
index ebdb48fbc..a2fadbd8a 100644
--- a/libguile/fluids.c
+++ b/libguile/fluids.c
@@ -1,4 +1,4 @@
-/* Copyright 1996-1997,2000-2001,2004,2006-2013,2017-2018
+/* Copyright 1996-1997,2000-2001,2004,2006-2013,2017-2018,2025
Free Software Foundation, Inc.
This file is part of Guile.
@@ -30,6 +30,7 @@
#include "cache-internal.h"
#include "deprecation.h"
#include "dynwind.h"
+#include "ephemerons.h"
#include "eval.h"
#include "gsubr.h"
#include "hashtab.h"
@@ -132,7 +133,7 @@ restore_dynamic_state (SCM saved, scm_t_dynamic_state *state)
else
entry->key = entry->value = 0;
}
- state->values = saved;
+ state->values = scm_to_ephemeron_table (saved);
state->has_aliased_values = 1;
}
@@ -140,7 +141,7 @@ static inline SCM
save_dynamic_state (scm_t_dynamic_state *state)
{
int slot;
- SCM saved = state->values;
+ SCM saved = scm_from_ephemeron_table (state->values);
for (slot = 0; slot < SCM_CACHE_SIZE; slot++)
{
struct scm_cache_entry *entry = &state->cache.entries[slot];
@@ -157,14 +158,14 @@ save_dynamic_state (scm_t_dynamic_state *state)
cache. */
scm_hashq_set_x (state->thread_local_values, key, value);
}
- else if (!scm_is_eq (scm_weak_table_refq (state->values, key,
- SCM_UNDEFINED),
+ else if (!scm_is_eq (scm_c_ephemeron_hash_table_refq (state->values, key,
+ SCM_UNDEFINED),
value))
{
if (state->has_aliased_values)
saved = scm_acons (key, value, saved);
else
- scm_weak_table_putq_x (state->values, key, value);
+ scm_c_ephemeron_hash_table_setq_x (state->values, key, value);
}
}
state->has_aliased_values = 1;
@@ -178,21 +179,8 @@ saved_dynamic_state_ref (SCM saved, SCM fluid, SCM dflt)
if (scm_is_eq (SCM_CAAR (saved), fluid))
return SCM_CDAR (saved);
- return scm_weak_table_refq (saved, fluid, dflt);
-}
-
-static SCM
-add_entry (void *data, SCM k, SCM v, SCM result)
-{
- scm_weak_table_putq_x (result, k, v);
- return result;
-}
-
-static SCM
-copy_value_table (SCM tab)
-{
- SCM ret = scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY);
- return scm_c_weak_table_fold (add_entry, NULL, ret, tab);
+ return scm_c_ephemeron_hash_table_refq (scm_to_ephemeron_table (saved),
+ fluid, dflt);
}
@@ -329,15 +317,17 @@ fluid_set_x (scm_t_dynamic_state *dynamic_state, SCM fluid, SCM value)
if (dynamic_state->has_aliased_values)
{
- if (scm_is_eq (scm_weak_table_refq (dynamic_state->values,
- fluid, SCM_UNDEFINED),
- value))
+ SCM existing =
+ scm_c_ephemeron_hash_table_refq (dynamic_state->values, fluid,
+ SCM_UNDEFINED);
+ if (scm_is_eq (existing, value))
return;
- dynamic_state->values = copy_value_table (dynamic_state->values);
+ dynamic_state->values =
+ scm_c_ephemeron_table_copy (dynamic_state->values);
dynamic_state->has_aliased_values = 0;
}
- scm_weak_table_putq_x (dynamic_state->values, fluid, value);
+ scm_c_ephemeron_hash_table_setq_x (dynamic_state->values, fluid, value);
}
}
@@ -356,8 +346,8 @@ fluid_ref (scm_t_dynamic_state *dynamic_state, SCM fluid)
val = scm_hashq_ref (dynamic_state->thread_local_values, fluid,
SCM_I_FLUID_DEFAULT (fluid));
else
- val = scm_weak_table_refq (dynamic_state->values, fluid,
- SCM_I_FLUID_DEFAULT (fluid));
+ val = scm_c_ephemeron_hash_table_refq (dynamic_state->values, fluid,
+ SCM_I_FLUID_DEFAULT (fluid));
/* Cache this lookup. */
fluid_set_x (dynamic_state, fluid, val);
@@ -420,8 +410,8 @@ SCM_DEFINE (scm_fluid_ref_star, "fluid-ref*", 2, 0, 0,
ret = scm_hashq_ref (dynamic_state->thread_local_values, fluid,
SCM_UNDEFINED);
else
- ret = scm_weak_table_refq (dynamic_state->values, fluid,
- SCM_UNDEFINED);
+ ret = scm_c_ephemeron_hash_table_refq (dynamic_state->values, fluid,
+ SCM_UNDEFINED);
if (SCM_UNBNDP (ret))
ret = SCM_I_FLUID_DEFAULT (fluid);
@@ -581,8 +571,7 @@ SCM
scm_i_make_initial_dynamic_state (void)
{
return scm_cell (scm_tc7_dynamic_state,
- SCM_UNPACK (scm_c_make_weak_table
- (0, SCM_WEAK_TABLE_KIND_KEY)));
+ (uintptr_t) scm_c_make_ephemeron_table (47));
}
SCM_DEFINE (scm_dynamic_state_p, "dynamic-state?", 1, 0, 0,
diff --git a/libguile/fluids.h b/libguile/fluids.h
index ffcb48931..9153169d0 100644
--- a/libguile/fluids.h
+++ b/libguile/fluids.h
@@ -1,7 +1,7 @@
#ifndef SCM_FLUIDS_H
#define SCM_FLUIDS_H
-/* Copyright 1996,2000-2001,2006,2008-2013,2018
+/* Copyright 1996,2000-2001,2006,2008-2013,2018,2025
Free Software Foundation, Inc.
This file is part of Guile.
@@ -44,10 +44,11 @@
#ifdef BUILDING_LIBGUILE
# include <libguile/cache-internal.h>
+struct scm_ephemeron_table;
struct scm_dynamic_state
{
SCM thread_local_values;
- SCM values;
+ struct scm_ephemeron_table *values;
uint8_t has_aliased_values;
struct scm_cache cache;
};