1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-07-04 08:40:21 +02:00

Dynstack uses inline functions instead of macros

* libguile/control.c:
* libguile/dynstack.c:
* libguile/dynstack.h:
* libguile/vm.c: Move SCM_DYNSTACK_TAG etc to be inline functions.
Adapt all callers.
This commit is contained in:
Andy Wingo 2025-06-30 14:16:52 +02:00
parent 985c1d16f2
commit 2b3b843f82
4 changed files with 158 additions and 93 deletions

View file

@ -41,7 +41,7 @@
#define PROMPT_ESCAPE_P(p) \
(SCM_DYNSTACK_TAG_FLAGS (SCM_DYNSTACK_TAG (p)) \
(scm_dynstack_tag_flags (scm_dynstack_tag (p)) \
& SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY)

View file

@ -101,8 +101,8 @@ clear_scm_t_bits (scm_t_bits *items, size_t n)
static void
dynstack_ensure_space (scm_t_dynstack *dynstack, size_t n)
{
size_t capacity = SCM_DYNSTACK_CAPACITY (dynstack);
size_t height = SCM_DYNSTACK_HEIGHT (dynstack);
size_t capacity = scm_dynstack_capacity (dynstack);
size_t height = scm_dynstack_height (dynstack);
n += SCM_DYNSTACK_HEADER_LEN;
@ -142,18 +142,18 @@ scm_trace_dynstack (struct scm_dynstack *dynstack,
{
scm_t_bits *walk;
for (walk = SCM_DYNSTACK_PREV (dynstack->top); walk;
walk = SCM_DYNSTACK_PREV (walk))
for (walk = scm_dynstack_prev (dynstack->top); walk;
walk = scm_dynstack_prev (walk))
{
scm_t_bits tag = SCM_DYNSTACK_TAG (walk);
scm_t_bits tag = scm_dynstack_tag (walk);
switch (SCM_DYNSTACK_TAG_TYPE (tag))
switch (scm_dynstack_tag_type (tag))
{
case SCM_DYNSTACK_TYPE_FRAME:
break;
case SCM_DYNSTACK_TYPE_UNWINDER:
case SCM_DYNSTACK_TYPE_REWINDER:
if (SCM_DYNSTACK_TAG_FLAGS (tag) & SCM_F_DYNSTACK_WINDER_MANAGED)
if (scm_dynstack_tag_flags (tag) & SCM_F_DYNSTACK_WINDER_MANAGED)
trace (gc_edge (WINDER_DATA_LOC (walk)), heap, trace_data);
break;
case SCM_DYNSTACK_TYPE_WITH_FLUID:
@ -220,10 +220,10 @@ push_dynstack_entry_unchecked (scm_t_dynstack *dynstack,
{
scm_t_bits *ret = dynstack->top;
SCM_DYNSTACK_SET_TAG (dynstack->top, SCM_MAKE_DYNSTACK_TAG (type, flags, len));
scm_dynstack_set_tag (dynstack->top, scm_make_dynstack_tag (type, flags, len));
dynstack->top += SCM_DYNSTACK_HEADER_LEN + len;
SCM_DYNSTACK_SET_TAG (dynstack->top, 0);
SCM_DYNSTACK_SET_PREV_OFFSET (dynstack->top, SCM_DYNSTACK_HEADER_LEN + len);
scm_dynstack_set_tag (dynstack->top, 0);
scm_dynstack_set_prev_offset (dynstack->top, SCM_DYNSTACK_HEADER_LEN + len);
return ret;
}
@ -233,7 +233,7 @@ push_dynstack_entry (scm_t_dynstack *dynstack,
scm_t_dynstack_item_type type,
scm_t_bits flags, size_t len)
{
if (SCM_UNLIKELY (!SCM_DYNSTACK_HAS_SPACE (dynstack, len)))
if (SCM_UNLIKELY (!scm_dynstack_has_space (dynstack, len)))
dynstack_ensure_space (dynstack, len);
return push_dynstack_entry_unchecked (dynstack, type, flags, len);
}
@ -328,17 +328,17 @@ scm_dynstack_push_dynwind (scm_t_dynstack *dynstack, SCM enter, SCM leave)
static inline scm_t_bits
dynstack_pop (scm_t_dynstack *dynstack, scm_t_bits **words)
{
scm_t_bits *prev = SCM_DYNSTACK_PREV (dynstack->top);
scm_t_bits *prev = scm_dynstack_prev (dynstack->top);
scm_t_bits tag;
if (SCM_UNLIKELY (!prev))
abort ();
SCM_DYNSTACK_SET_PREV_OFFSET (dynstack->top, 0);
scm_dynstack_set_prev_offset (dynstack->top, 0);
dynstack->top = prev;
tag = SCM_DYNSTACK_TAG (dynstack->top);
SCM_DYNSTACK_SET_TAG (dynstack->top, 0);
tag = scm_dynstack_tag (dynstack->top);
scm_dynstack_set_tag (dynstack->top, 0);
*words = dynstack->top;
return tag;
@ -365,13 +365,13 @@ scm_dynstack_pop (scm_t_dynstack *dynstack)
{
scm_t_bits tag, *words;
tag = dynstack_pop (dynstack, &words);
clear_scm_t_bits (words, SCM_DYNSTACK_TAG_LEN (tag));
clear_scm_t_bits (words, scm_dynstack_tag_len (tag));
}
scm_t_dynstack *
scm_dynstack_capture_all (scm_t_dynstack *dynstack)
{
return scm_dynstack_capture (dynstack, SCM_DYNSTACK_FIRST (dynstack));
return scm_dynstack_capture (dynstack, scm_dynstack_first (dynstack));
}
scm_t_dynstack *
@ -380,7 +380,7 @@ scm_dynstack_capture (scm_t_dynstack *dynstack, scm_t_bits *item)
scm_t_dynstack *ret;
size_t len;
assert (item >= SCM_DYNSTACK_FIRST (dynstack));
assert (item >= scm_dynstack_first (dynstack));
assert (item <= dynstack->top);
len = dynstack->top - item + SCM_DYNSTACK_HEADER_LEN;
@ -392,7 +392,7 @@ scm_dynstack_capture (scm_t_dynstack *dynstack, scm_t_bits *item)
ret->top = ret->base + len;
copy_scm_t_bits (ret->base, item - SCM_DYNSTACK_HEADER_LEN, len);
SCM_DYNSTACK_SET_PREV_OFFSET (SCM_DYNSTACK_FIRST (ret), 0);
scm_dynstack_set_prev_offset (scm_dynstack_first (ret), 0);
return ret;
}
@ -403,11 +403,11 @@ scm_dynstack_relocate_prompts (scm_t_dynstack *dynstack, ptrdiff_t base)
scm_t_bits *walk;
/* Relocate prompts. */
for (walk = dynstack->top; walk; walk = SCM_DYNSTACK_PREV (walk))
for (walk = dynstack->top; walk; walk = scm_dynstack_prev (walk))
{
scm_t_bits tag = SCM_DYNSTACK_TAG (walk);
scm_t_bits tag = scm_dynstack_tag (walk);
if (SCM_DYNSTACK_TAG_TYPE (tag) == SCM_DYNSTACK_TYPE_PROMPT)
if (scm_dynstack_tag_type (tag) == SCM_DYNSTACK_TYPE_PROMPT)
{
SET_PROMPT_FP (walk, PROMPT_FP (walk) - base);
SET_PROMPT_SP (walk, PROMPT_SP (walk) - base);
@ -418,10 +418,10 @@ scm_dynstack_relocate_prompts (scm_t_dynstack *dynstack, ptrdiff_t base)
void
scm_dynstack_wind_1 (scm_t_dynstack *dynstack, scm_t_bits *item)
{
scm_t_bits tag = SCM_DYNSTACK_TAG (item);
scm_t_dynstack_item_type type = SCM_DYNSTACK_TAG_TYPE (tag);
scm_t_bits flags = SCM_DYNSTACK_TAG_FLAGS (tag);
size_t len = SCM_DYNSTACK_TAG_LEN (tag);
scm_t_bits tag = scm_dynstack_tag (item);
scm_t_dynstack_item_type type = scm_dynstack_tag_type (tag);
scm_t_bits flags = scm_dynstack_tag_flags (tag);
size_t len = scm_dynstack_tag_len (tag);
switch (type)
{
@ -480,7 +480,7 @@ scm_dynstack_unwind_1 (scm_t_dynstack *dynstack)
tag = dynstack_pop (dynstack, &words);
type = SCM_DYNSTACK_TAG_TYPE (tag);
type = scm_dynstack_tag_type (tag);
switch (type)
{
@ -534,7 +534,7 @@ scm_dynstack_unwind_1 (scm_t_dynstack *dynstack)
void
scm_dynstack_wind (scm_t_dynstack *dynstack, scm_t_bits *item)
{
for (; SCM_DYNSTACK_TAG (item); item = SCM_DYNSTACK_NEXT (item))
for (; scm_dynstack_tag (item); item = scm_dynstack_next (item))
scm_dynstack_wind_1 (dynstack, item);
}
@ -549,14 +549,14 @@ static int
same_entries (scm_t_bits *walk_a, scm_t_bits *next_a,
scm_t_bits *walk_b, scm_t_bits *next_b)
{
if (SCM_DYNSTACK_TAG (walk_a) != SCM_DYNSTACK_TAG (walk_b))
if (scm_dynstack_tag (walk_a) != scm_dynstack_tag (walk_b))
return 0;
if (next_a - walk_a != next_b - walk_b)
return 0;
assert (SCM_DYNSTACK_PREV_OFFSET (next_a) == next_a - walk_a);
assert (SCM_DYNSTACK_PREV_OFFSET (next_b) == next_b - walk_b);
assert (scm_dynstack_prev_offset (next_a) == next_a - walk_a);
assert (scm_dynstack_prev_offset (next_b) == next_b - walk_b);
while (walk_a != next_a)
if (*(walk_a++) != *(walk_b++))
@ -570,19 +570,19 @@ shared_prefix_length (scm_t_dynstack *a, scm_t_dynstack *b)
{
scm_t_bits *walk_a, *next_a, *walk_b, *next_b;
walk_a = SCM_DYNSTACK_FIRST (a);
walk_b = SCM_DYNSTACK_FIRST (b);
walk_a = scm_dynstack_first (a);
walk_b = scm_dynstack_first (b);
next_a = SCM_DYNSTACK_NEXT (walk_a);
next_b = SCM_DYNSTACK_NEXT (walk_b);
next_a = scm_dynstack_next (walk_a);
next_b = scm_dynstack_next (walk_b);
while (next_a && next_b && same_entries (walk_a, next_a, walk_b, next_b))
{
walk_a = next_a;
walk_b = next_b;
next_a = SCM_DYNSTACK_NEXT (walk_a);
next_b = SCM_DYNSTACK_NEXT (walk_b);
next_a = scm_dynstack_next (walk_a);
next_b = scm_dynstack_next (walk_b);
}
return walk_a - a->base;
@ -608,16 +608,16 @@ scm_dynstack_find_prompt (scm_t_dynstack *dynstack, SCM key,
{
scm_t_bits *walk;
for (walk = SCM_DYNSTACK_PREV (dynstack->top); walk;
walk = SCM_DYNSTACK_PREV (walk))
for (walk = scm_dynstack_prev (dynstack->top); walk;
walk = scm_dynstack_prev (walk))
{
scm_t_bits tag = SCM_DYNSTACK_TAG (walk);
scm_t_bits tag = scm_dynstack_tag (walk);
if (SCM_DYNSTACK_TAG_TYPE (tag) == SCM_DYNSTACK_TYPE_PROMPT
if (scm_dynstack_tag_type (tag) == SCM_DYNSTACK_TYPE_PROMPT
&& scm_is_eq (PROMPT_KEY (walk), key))
{
if (flags)
*flags = SCM_DYNSTACK_TAG_FLAGS (tag);
*flags = scm_dynstack_tag_flags (tag);
if (fp_offset)
*fp_offset = PROMPT_FP (walk);
if (sp_offset)
@ -641,12 +641,12 @@ scm_dynstack_find_old_fluid_value (scm_t_dynstack *dynstack, SCM fluid,
{
scm_t_bits *walk;
for (walk = SCM_DYNSTACK_PREV (dynstack->top); walk;
walk = SCM_DYNSTACK_PREV (walk))
for (walk = scm_dynstack_prev (dynstack->top); walk;
walk = scm_dynstack_prev (walk))
{
scm_t_bits tag = SCM_DYNSTACK_TAG (walk);
scm_t_bits tag = scm_dynstack_tag (walk);
switch (SCM_DYNSTACK_TAG_TYPE (tag))
switch (scm_dynstack_tag_type (tag))
{
case SCM_DYNSTACK_TYPE_WITH_FLUID:
{
@ -689,13 +689,13 @@ scm_dynstack_wind_prompt (scm_t_dynstack *dynstack, scm_t_bits *item,
ptrdiff_t base_fp_offset,
jmp_buf *registers)
{
scm_t_bits tag = SCM_DYNSTACK_TAG (item);
scm_t_bits tag = scm_dynstack_tag (item);
if (SCM_DYNSTACK_TAG_TYPE (tag) != SCM_DYNSTACK_TYPE_PROMPT)
if (scm_dynstack_tag_type (tag) != SCM_DYNSTACK_TYPE_PROMPT)
abort ();
scm_dynstack_push_prompt (dynstack,
SCM_DYNSTACK_TAG_FLAGS (tag),
scm_dynstack_tag_flags (tag),
PROMPT_KEY (item),
PROMPT_FP (item) + base_fp_offset,
PROMPT_SP (item) + base_fp_offset,
@ -714,7 +714,7 @@ scm_dynstack_unwind_frame (scm_t_dynstack *dynstack)
tag = dynstack_pop (dynstack, &words);
switch (SCM_DYNSTACK_TAG_TYPE (tag))
switch (scm_dynstack_tag_type (tag))
{
case SCM_DYNSTACK_TYPE_FRAME:
return;
@ -726,7 +726,7 @@ scm_dynstack_unwind_frame (scm_t_dynstack *dynstack)
scm_t_guard proc = WINDER_PROC (words);
void *data = WINDER_DATA (words);
clear_scm_t_bits (words, WINDER_WORDS);
if (SCM_DYNSTACK_TAG_FLAGS (tag) & SCM_F_DYNSTACK_WINDER_EXPLICIT)
if (scm_dynstack_tag_flags (tag) & SCM_F_DYNSTACK_WINDER_EXPLICIT)
proc (data);
continue;
}
@ -745,9 +745,9 @@ scm_dynstack_unwind_fluid (scm_t_dynstack *dynstack, scm_thread *thread)
size_t len;
tag = dynstack_pop (dynstack, &words);
len = SCM_DYNSTACK_TAG_LEN (tag);
len = scm_dynstack_tag_len (tag);
assert (SCM_DYNSTACK_TAG_TYPE (tag) == SCM_DYNSTACK_TYPE_WITH_FLUID);
assert (scm_dynstack_tag_type (tag) == SCM_DYNSTACK_TYPE_WITH_FLUID);
assert (len == WITH_FLUID_WORDS);
scm_swap_fluid (thread, WITH_FLUID_FLUID (words), WITH_FLUID_VALUE_BOX (words));
@ -762,9 +762,9 @@ scm_dynstack_unwind_dynamic_state (scm_t_dynstack *dynstack,
size_t len;
tag = dynstack_pop (dynstack, &words);
len = SCM_DYNSTACK_TAG_LEN (tag);
len = scm_dynstack_tag_len (tag);
assert (SCM_DYNSTACK_TAG_TYPE (tag) == SCM_DYNSTACK_TYPE_DYNAMIC_STATE);
assert (scm_dynstack_tag_type (tag) == SCM_DYNSTACK_TYPE_DYNAMIC_STATE);
assert (len == DYNAMIC_STATE_WORDS);
scm_variable_set_x (DYNAMIC_STATE_STATE_BOX (words),

View file

@ -69,18 +69,36 @@ typedef struct scm_dynstack
The tag is a combination of the type of the dynstack item, some flags
associated with the item, and the length of the item. See
SCM_MAKE_DYNSTACK_TAG below for the details.
scm_make_dynstack_tag below for the details.
This arrangement makes it possible to have variable-length dynstack
items, and yet be able to traverse them forwards or backwards. */
#define SCM_DYNSTACK_HEADER_LEN 2
#define SCM_DYNSTACK_PREV_OFFSET(top) ((top)[-2])
#define SCM_DYNSTACK_SET_PREV_OFFSET(top, offset) (top)[-2] = (offset)
static inline ptrdiff_t
scm_dynstack_prev_offset (scm_t_bits *top)
{
return top[-2];
}
#define SCM_DYNSTACK_TAG(top) ((top)[-1])
#define SCM_DYNSTACK_SET_TAG(top, tag) (top)[-1] = (tag)
static inline void
scm_dynstack_set_prev_offset (scm_t_bits *top, ptrdiff_t offset)
{
top[-2] = offset;
}
static inline scm_t_bits
scm_dynstack_tag (scm_t_bits *top)
{
return top[-1];
}
static inline void
scm_dynstack_set_tag (scm_t_bits *top, scm_t_bits tag)
{
top[-1] = tag;
}
typedef enum {
SCM_DYNSTACK_TYPE_NONE = 0,
@ -98,37 +116,84 @@ typedef enum {
#define SCM_DYNSTACK_TAG_FLAGS_SHIFT 4
#define SCM_DYNSTACK_TAG_LEN_SHIFT 8
#define SCM_MAKE_DYNSTACK_TAG(type, flags, len) \
((type) | (flags) | ((len) << SCM_DYNSTACK_TAG_LEN_SHIFT))
static inline scm_t_bits
scm_make_dynstack_tag (scm_t_dynstack_item_type type, scm_t_bits flags,
size_t len)
{
if (type & ~SCM_DYNSTACK_TAG_TYPE_MASK)
abort ();
if (flags & ~SCM_DYNSTACK_TAG_FLAGS_MASK)
abort ();
#define SCM_DYNSTACK_TAG_TYPE(tag) \
((tag) & SCM_DYNSTACK_TAG_TYPE_MASK)
#define SCM_DYNSTACK_TAG_FLAGS(tag) \
((tag) & SCM_DYNSTACK_TAG_FLAGS_MASK)
#define SCM_DYNSTACK_TAG_LEN(tag) \
((tag) >> SCM_DYNSTACK_TAG_LEN_SHIFT)
scm_t_bits ret = type;
ret |= flags;
ret |= (len << SCM_DYNSTACK_TAG_LEN_SHIFT);
return ret;
}
#define SCM_DYNSTACK_PREV(top) \
(SCM_DYNSTACK_PREV_OFFSET (top) \
? ((top) - SCM_DYNSTACK_PREV_OFFSET (top)) : NULL)
#define SCM_DYNSTACK_NEXT(top) \
(SCM_DYNSTACK_TAG (top) \
? ((top) + SCM_DYNSTACK_TAG_LEN (SCM_DYNSTACK_TAG (top)) \
+ SCM_DYNSTACK_HEADER_LEN) \
: NULL)
static inline scm_t_dynstack_item_type
scm_dynstack_tag_type (scm_t_bits tag)
{
return tag & SCM_DYNSTACK_TAG_TYPE_MASK;
}
#define SCM_DYNSTACK_FIRST(dynstack) \
((dynstack)->base + SCM_DYNSTACK_HEADER_LEN)
static inline scm_t_bits
scm_dynstack_tag_flags (scm_t_bits tag)
{
return tag & SCM_DYNSTACK_TAG_FLAGS_MASK;
}
#define SCM_DYNSTACK_CAPACITY(dynstack) \
((dynstack)->limit - (dynstack)->base)
#define SCM_DYNSTACK_SPACE(dynstack) \
((dynstack)->limit - (dynstack)->top)
#define SCM_DYNSTACK_HEIGHT(dynstack) \
((dynstack)->top - (dynstack)->base)
static inline size_t
scm_dynstack_tag_len (scm_t_bits tag)
{
return tag >> SCM_DYNSTACK_TAG_LEN_SHIFT;
}
#define SCM_DYNSTACK_HAS_SPACE(dynstack, n) \
(SCM_DYNSTACK_SPACE (dynstack) >= n + SCM_DYNSTACK_HEADER_LEN)
static inline scm_t_bits *
scm_dynstack_prev (scm_t_bits *top)
{
ptrdiff_t offset = scm_dynstack_prev_offset (top);
return offset ? top - offset : NULL;
}
static inline scm_t_bits *
scm_dynstack_next (scm_t_bits *top)
{
scm_t_bits tag = scm_dynstack_tag (top);
return tag
? top + scm_dynstack_tag_len (tag) + SCM_DYNSTACK_HEADER_LEN
: NULL;
}
static inline scm_t_bits *
scm_dynstack_first (struct scm_dynstack *dynstack)
{
return dynstack->base + SCM_DYNSTACK_HEADER_LEN;
}
static inline size_t
scm_dynstack_capacity (struct scm_dynstack *dynstack)
{
return dynstack->limit - dynstack->base;
}
static inline size_t
scm_dynstack_space (struct scm_dynstack *dynstack)
{
return dynstack->limit - dynstack->top;
}
static inline size_t
scm_dynstack_height (struct scm_dynstack *dynstack)
{
return dynstack->top - dynstack->base;
}
static inline int
scm_dynstack_has_space (struct scm_dynstack *dynstack, size_t n)
{
return scm_dynstack_space (dynstack) >= n + SCM_DYNSTACK_HEADER_LEN;
}
typedef enum {
SCM_F_DYNSTACK_FRAME_REWINDABLE = (1 << SCM_DYNSTACK_TAG_FLAGS_SHIFT)

View file

@ -1192,13 +1192,13 @@ compose_continuation (scm_thread *thread, SCM cont)
{
scm_t_bits *walk;
for (walk = SCM_DYNSTACK_FIRST (cp->dynstack);
SCM_DYNSTACK_TAG (walk);
walk = SCM_DYNSTACK_NEXT (walk))
for (walk = scm_dynstack_first (cp->dynstack);
scm_dynstack_tag (walk);
walk = scm_dynstack_next (walk))
{
scm_t_bits tag = SCM_DYNSTACK_TAG (walk);
scm_t_bits tag = scm_dynstack_tag (walk);
if (SCM_DYNSTACK_TAG_TYPE (tag) == SCM_DYNSTACK_TYPE_PROMPT)
if (scm_dynstack_tag_type (tag) == SCM_DYNSTACK_TYPE_PROMPT)
scm_dynstack_wind_prompt (&thread->dynstack, walk, old_fp_offset,
thread->vm.registers);
else
@ -1413,7 +1413,7 @@ abort_to_prompt (scm_thread *thread, uint8_t *saved_mra)
{
scm_t_dynstack *captured;
captured = scm_dynstack_capture (dynstack, SCM_DYNSTACK_NEXT (prompt));
captured = scm_dynstack_capture (dynstack, scm_dynstack_next (prompt));
cont = capture_delimited_continuation (thread, vp, fp, saved_mra,
registers, captured,
thread->vm.registers);