mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-05 19:50:23 +02:00
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.
This commit is contained in:
parent
134c3be452
commit
2463a0741f
4 changed files with 80 additions and 56 deletions
|
@ -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*
|
struct gc_ephemeron*
|
||||||
scm_c_make_ephemeron (SCM key, SCM val)
|
scm_c_make_ephemeron (SCM key, SCM val)
|
||||||
{
|
{
|
||||||
|
@ -74,6 +76,20 @@ scm_as_ephemeron (SCM x)
|
||||||
return (struct gc_ephemeron*) SCM_UNPACK_POINTER (x);
|
return (struct gc_ephemeron*) SCM_UNPACK_POINTER (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
|
||||||
scm_c_ephemeron_key (struct gc_ephemeron *e)
|
scm_c_ephemeron_key (struct gc_ephemeron *e)
|
||||||
{
|
{
|
||||||
|
@ -109,9 +125,8 @@ scm_c_ephemeron_next (struct gc_ephemeron *e)
|
||||||
return gc_ephemeron_chain_next (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) \
|
#define SCM_VALIDATE_EPHEMERON(pos, x) \
|
||||||
SCM_MAKE_VALIDATE_MSG (pos, x, EPHEMERON_P, "ephemeron")
|
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);
|
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
|
struct scm_ephemeron_table
|
||||||
{
|
{
|
||||||
scm_t_bits tag;
|
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;
|
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_DEFINE_STATIC (scm_ephemeron_table_p, "ephemeron-table?", 1, 0, 0,
|
||||||
(SCM x),
|
(SCM x),
|
||||||
"Return @code{#t} if @var{x} is an ephemeron table, or "
|
"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);
|
} 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 void scm_c_ephemeron_mark_dead_x (struct gc_ephemeron *e);
|
||||||
SCM_INTERNAL int scm_i_print_ephemeron (SCM exp, SCM port,
|
SCM_INTERNAL int scm_i_print_ephemeron (SCM exp, SCM port,
|
||||||
scm_print_state *pstate SCM_UNUSED);
|
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 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);
|
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,
|
size_t idx,
|
||||||
struct gc_ephemeron * e,
|
struct gc_ephemeron * e,
|
||||||
struct gc_ephemeron *prev);
|
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_INTERNAL int scm_i_print_ephemeron_table (SCM exp, SCM port,
|
||||||
scm_print_state *pstate SCM_UNUSED);
|
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_INTERNAL SCM
|
||||||
scm_c_ephemeron_hash_table_refq (struct scm_ephemeron_table *et, SCM k,
|
scm_c_ephemeron_hash_table_refq (struct scm_ephemeron_table *et, SCM k,
|
||||||
SCM default_value);
|
SCM default_value);
|
||||||
SCM_INTERNAL void
|
SCM_INTERNAL void
|
||||||
scm_c_ephemeron_hash_table_setq_x (struct scm_ephemeron_table *et, SCM k, SCM v);
|
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);
|
SCM_INTERNAL void scm_register_ephemerons (void);
|
||||||
|
|
|
@ -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.
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of Guile.
|
This file is part of Guile.
|
||||||
|
@ -30,6 +30,7 @@
|
||||||
#include "cache-internal.h"
|
#include "cache-internal.h"
|
||||||
#include "deprecation.h"
|
#include "deprecation.h"
|
||||||
#include "dynwind.h"
|
#include "dynwind.h"
|
||||||
|
#include "ephemerons.h"
|
||||||
#include "eval.h"
|
#include "eval.h"
|
||||||
#include "gsubr.h"
|
#include "gsubr.h"
|
||||||
#include "hashtab.h"
|
#include "hashtab.h"
|
||||||
|
@ -132,7 +133,7 @@ restore_dynamic_state (SCM saved, scm_t_dynamic_state *state)
|
||||||
else
|
else
|
||||||
entry->key = entry->value = 0;
|
entry->key = entry->value = 0;
|
||||||
}
|
}
|
||||||
state->values = saved;
|
state->values = scm_to_ephemeron_table (saved);
|
||||||
state->has_aliased_values = 1;
|
state->has_aliased_values = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +141,7 @@ static inline SCM
|
||||||
save_dynamic_state (scm_t_dynamic_state *state)
|
save_dynamic_state (scm_t_dynamic_state *state)
|
||||||
{
|
{
|
||||||
int slot;
|
int slot;
|
||||||
SCM saved = state->values;
|
SCM saved = scm_from_ephemeron_table (state->values);
|
||||||
for (slot = 0; slot < SCM_CACHE_SIZE; slot++)
|
for (slot = 0; slot < SCM_CACHE_SIZE; slot++)
|
||||||
{
|
{
|
||||||
struct scm_cache_entry *entry = &state->cache.entries[slot];
|
struct scm_cache_entry *entry = &state->cache.entries[slot];
|
||||||
|
@ -157,14 +158,14 @@ save_dynamic_state (scm_t_dynamic_state *state)
|
||||||
cache. */
|
cache. */
|
||||||
scm_hashq_set_x (state->thread_local_values, key, value);
|
scm_hashq_set_x (state->thread_local_values, key, value);
|
||||||
}
|
}
|
||||||
else if (!scm_is_eq (scm_weak_table_refq (state->values, key,
|
else if (!scm_is_eq (scm_c_ephemeron_hash_table_refq (state->values, key,
|
||||||
SCM_UNDEFINED),
|
SCM_UNDEFINED),
|
||||||
value))
|
value))
|
||||||
{
|
{
|
||||||
if (state->has_aliased_values)
|
if (state->has_aliased_values)
|
||||||
saved = scm_acons (key, value, saved);
|
saved = scm_acons (key, value, saved);
|
||||||
else
|
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;
|
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))
|
if (scm_is_eq (SCM_CAAR (saved), fluid))
|
||||||
return SCM_CDAR (saved);
|
return SCM_CDAR (saved);
|
||||||
|
|
||||||
return scm_weak_table_refq (saved, fluid, dflt);
|
return scm_c_ephemeron_hash_table_refq (scm_to_ephemeron_table (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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -329,15 +317,17 @@ fluid_set_x (scm_t_dynamic_state *dynamic_state, SCM fluid, SCM value)
|
||||||
|
|
||||||
if (dynamic_state->has_aliased_values)
|
if (dynamic_state->has_aliased_values)
|
||||||
{
|
{
|
||||||
if (scm_is_eq (scm_weak_table_refq (dynamic_state->values,
|
SCM existing =
|
||||||
fluid, SCM_UNDEFINED),
|
scm_c_ephemeron_hash_table_refq (dynamic_state->values, fluid,
|
||||||
value))
|
SCM_UNDEFINED);
|
||||||
|
if (scm_is_eq (existing, value))
|
||||||
return;
|
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;
|
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,7 +346,7 @@ fluid_ref (scm_t_dynamic_state *dynamic_state, SCM fluid)
|
||||||
val = scm_hashq_ref (dynamic_state->thread_local_values, fluid,
|
val = scm_hashq_ref (dynamic_state->thread_local_values, fluid,
|
||||||
SCM_I_FLUID_DEFAULT (fluid));
|
SCM_I_FLUID_DEFAULT (fluid));
|
||||||
else
|
else
|
||||||
val = scm_weak_table_refq (dynamic_state->values, fluid,
|
val = scm_c_ephemeron_hash_table_refq (dynamic_state->values, fluid,
|
||||||
SCM_I_FLUID_DEFAULT (fluid));
|
SCM_I_FLUID_DEFAULT (fluid));
|
||||||
|
|
||||||
/* Cache this lookup. */
|
/* Cache this lookup. */
|
||||||
|
@ -420,7 +410,7 @@ SCM_DEFINE (scm_fluid_ref_star, "fluid-ref*", 2, 0, 0,
|
||||||
ret = scm_hashq_ref (dynamic_state->thread_local_values, fluid,
|
ret = scm_hashq_ref (dynamic_state->thread_local_values, fluid,
|
||||||
SCM_UNDEFINED);
|
SCM_UNDEFINED);
|
||||||
else
|
else
|
||||||
ret = scm_weak_table_refq (dynamic_state->values, fluid,
|
ret = scm_c_ephemeron_hash_table_refq (dynamic_state->values, fluid,
|
||||||
SCM_UNDEFINED);
|
SCM_UNDEFINED);
|
||||||
|
|
||||||
if (SCM_UNBNDP (ret))
|
if (SCM_UNBNDP (ret))
|
||||||
|
@ -581,8 +571,7 @@ SCM
|
||||||
scm_i_make_initial_dynamic_state (void)
|
scm_i_make_initial_dynamic_state (void)
|
||||||
{
|
{
|
||||||
return scm_cell (scm_tc7_dynamic_state,
|
return scm_cell (scm_tc7_dynamic_state,
|
||||||
SCM_UNPACK (scm_c_make_weak_table
|
(uintptr_t) scm_c_make_ephemeron_table (47));
|
||||||
(0, SCM_WEAK_TABLE_KIND_KEY)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SCM_DEFINE (scm_dynamic_state_p, "dynamic-state?", 1, 0, 0,
|
SCM_DEFINE (scm_dynamic_state_p, "dynamic-state?", 1, 0, 0,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef SCM_FLUIDS_H
|
#ifndef SCM_FLUIDS_H
|
||||||
#define 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.
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of Guile.
|
This file is part of Guile.
|
||||||
|
@ -44,10 +44,11 @@
|
||||||
#ifdef BUILDING_LIBGUILE
|
#ifdef BUILDING_LIBGUILE
|
||||||
# include <libguile/cache-internal.h>
|
# include <libguile/cache-internal.h>
|
||||||
|
|
||||||
|
struct scm_ephemeron_table;
|
||||||
struct scm_dynamic_state
|
struct scm_dynamic_state
|
||||||
{
|
{
|
||||||
SCM thread_local_values;
|
SCM thread_local_values;
|
||||||
SCM values;
|
struct scm_ephemeron_table *values;
|
||||||
uint8_t has_aliased_values;
|
uint8_t has_aliased_values;
|
||||||
struct scm_cache cache;
|
struct scm_cache cache;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue