mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 11:40:18 +02:00
Remove SCM_DEBUG_CELL_ACCESSES==1
Since the move to BDW-GC this option has not been useful. * libguile/__scm.h (SCM_DEBUG_CELL_ACCESSES): Remove default definition. * libguile/gc.h: Add comment about cells. (SCM_VALIDATE_CELL): Remove. I did a search on the internet and I found no external users. (SCM_CELL_WORD, SCM_CELL_OBJECT, SCM_SET_CELL_WORD) (SCM_SET_CELL_OBJECT, SCM_CELL_OBJECT_LOC): Remove SCM_VALIDATE_CELL uses. * libguile/gc.c (scm_debug_cell_accesses_p) (scm_expensive_debug_cell_accesses_p) (scm_debug_cells_gc_interval, scm_i_expensive_validation_check) (scm_assert_cell_valid): Remove bindings only available when SCM_DEBUG_CELL_ACCESSES was 1. * libguile/list.c (scm_list_n): Remove SCM_VALIDATE_CELL usage.
This commit is contained in:
parent
4985ef13e6
commit
705e3a83c8
4 changed files with 16 additions and 191 deletions
|
@ -248,15 +248,6 @@
|
||||||
#define SCM_DEBUG 0
|
#define SCM_DEBUG 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If SCM_DEBUG_CELL_ACCESSES is set to 1, cell accesses will perform
|
|
||||||
* exhaustive parameter checking: It will be verified that cell parameters
|
|
||||||
* actually point to a valid heap cell. Note: If this option is enabled,
|
|
||||||
* guile will run about ten times slower than normally.
|
|
||||||
*/
|
|
||||||
#ifndef SCM_DEBUG_CELL_ACCESSES
|
|
||||||
#define SCM_DEBUG_CELL_ACCESSES SCM_DEBUG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If SCM_DEBUG_PAIR_ACCESSES is set to 1, accesses to cons cells will be
|
/* If SCM_DEBUG_PAIR_ACCESSES is set to 1, accesses to cons cells will be
|
||||||
* exhaustively checked. Note: If this option is enabled, guile will run
|
* exhaustively checked. Note: If this option is enabled, guile will run
|
||||||
* slower than normally.
|
* slower than normally.
|
||||||
|
|
140
libguile/gc.c
140
libguile/gc.c
|
@ -89,108 +89,6 @@ int scm_debug_cells_gc_interval = 0;
|
||||||
static SCM scm_protects;
|
static SCM scm_protects;
|
||||||
|
|
||||||
|
|
||||||
#if (SCM_DEBUG_CELL_ACCESSES == 1)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
Assert that the given object is a valid reference to a valid cell. This
|
|
||||||
test involves to determine whether the object is a cell pointer, whether
|
|
||||||
this pointer actually points into a heap segment and whether the cell
|
|
||||||
pointed to is not a free cell. Further, additional garbage collections may
|
|
||||||
get executed after a user defined number of cell accesses. This helps to
|
|
||||||
find places in the C code where references are dropped for extremely short
|
|
||||||
periods.
|
|
||||||
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
scm_i_expensive_validation_check (SCM cell)
|
|
||||||
{
|
|
||||||
/* If desired, perform additional garbage collections after a user
|
|
||||||
* defined number of cell accesses.
|
|
||||||
*/
|
|
||||||
if (scm_debug_cells_gc_interval)
|
|
||||||
{
|
|
||||||
static unsigned int counter = 0;
|
|
||||||
|
|
||||||
if (counter != 0)
|
|
||||||
{
|
|
||||||
--counter;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
counter = scm_debug_cells_gc_interval;
|
|
||||||
scm_gc ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Whether cell validation is already running. */
|
|
||||||
static int scm_i_cell_validation_already_running = 0;
|
|
||||||
|
|
||||||
void
|
|
||||||
scm_assert_cell_valid (SCM cell)
|
|
||||||
{
|
|
||||||
if (!scm_i_cell_validation_already_running && scm_debug_cell_accesses_p)
|
|
||||||
{
|
|
||||||
scm_i_cell_validation_already_running = 1; /* set to avoid recursion */
|
|
||||||
|
|
||||||
/*
|
|
||||||
During GC, no user-code should be run, and the guile core
|
|
||||||
should use non-protected accessors.
|
|
||||||
*/
|
|
||||||
if (scm_gc_running_p)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Only scm_in_heap_p and rescanning the heap is wildly
|
|
||||||
expensive.
|
|
||||||
*/
|
|
||||||
if (scm_expensive_debug_cell_accesses_p)
|
|
||||||
scm_i_expensive_validation_check (cell);
|
|
||||||
|
|
||||||
scm_i_cell_validation_already_running = 0; /* re-enable */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SCM_DEFINE (scm_set_debug_cell_accesses_x, "set-debug-cell-accesses!", 1, 0, 0,
|
|
||||||
(SCM flag),
|
|
||||||
"If @var{flag} is @code{#f}, cell access checking is disabled.\n"
|
|
||||||
"If @var{flag} is @code{#t}, cheap cell access checking is enabled,\n"
|
|
||||||
"but no additional calls to garbage collection are issued.\n"
|
|
||||||
"If @var{flag} is a number, strict cell access checking is enabled,\n"
|
|
||||||
"with an additional garbage collection after the given\n"
|
|
||||||
"number of cell accesses.\n"
|
|
||||||
"This procedure only exists when the compile-time flag\n"
|
|
||||||
"@code{SCM_DEBUG_CELL_ACCESSES} was set to 1.")
|
|
||||||
#define FUNC_NAME s_scm_set_debug_cell_accesses_x
|
|
||||||
{
|
|
||||||
if (scm_is_false (flag))
|
|
||||||
{
|
|
||||||
scm_debug_cell_accesses_p = 0;
|
|
||||||
}
|
|
||||||
else if (scm_is_eq (flag, SCM_BOOL_T))
|
|
||||||
{
|
|
||||||
scm_debug_cells_gc_interval = 0;
|
|
||||||
scm_debug_cell_accesses_p = 1;
|
|
||||||
scm_expensive_debug_cell_accesses_p = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
scm_debug_cells_gc_interval = scm_to_signed_integer (flag, 0, INT_MAX);
|
|
||||||
scm_debug_cell_accesses_p = 1;
|
|
||||||
scm_expensive_debug_cell_accesses_p = 1;
|
|
||||||
}
|
|
||||||
return SCM_UNSPECIFIED;
|
|
||||||
}
|
|
||||||
#undef FUNC_NAME
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* SCM_DEBUG_CELL_ACCESSES == 1 */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int needs_gc_after_nonlocal_exit = 0;
|
static int needs_gc_after_nonlocal_exit = 0;
|
||||||
|
@ -679,42 +577,12 @@ queue_after_gc_hook (void * hook_data SCM_UNUSED,
|
||||||
void *fn_data SCM_UNUSED,
|
void *fn_data SCM_UNUSED,
|
||||||
void *data SCM_UNUSED)
|
void *data SCM_UNUSED)
|
||||||
{
|
{
|
||||||
/* If cell access debugging is enabled, the user may choose to perform
|
scm_i_thread *t = SCM_I_CURRENT_THREAD;
|
||||||
* additional garbage collections after an arbitrary number of cell
|
|
||||||
* accesses. We don't want the scheme level after-gc-hook to be performed
|
|
||||||
* for each of these garbage collections for the following reason: The
|
|
||||||
* execution of the after-gc-hook causes cell accesses itself. Thus, if the
|
|
||||||
* after-gc-hook was performed with every gc, and if the gc was performed
|
|
||||||
* after a very small number of cell accesses, then the number of cell
|
|
||||||
* accesses during the execution of the after-gc-hook will suffice to cause
|
|
||||||
* the execution of the next gc. Then, guile would keep executing the
|
|
||||||
* after-gc-hook over and over again, and would never come to do other
|
|
||||||
* things.
|
|
||||||
*
|
|
||||||
* To overcome this problem, if cell access debugging with additional
|
|
||||||
* garbage collections is enabled, the after-gc-hook is never run by the
|
|
||||||
* garbage collecter. When running guile with cell access debugging and the
|
|
||||||
* execution of the after-gc-hook is desired, then it is necessary to run
|
|
||||||
* the hook explicitly from the user code. This has the effect, that from
|
|
||||||
* the scheme level point of view it seems that garbage collection is
|
|
||||||
* performed with a much lower frequency than it actually is. Obviously,
|
|
||||||
* this will not work for code that depends on a fixed one to one
|
|
||||||
* relationship between the execution counts of the C level garbage
|
|
||||||
* collection hooks and the execution count of the scheme level
|
|
||||||
* after-gc-hook.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if (SCM_DEBUG_CELL_ACCESSES == 1)
|
if (scm_is_false (SCM_CDR (after_gc_async_cell)))
|
||||||
if (scm_debug_cells_gc_interval == 0)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
scm_i_thread *t = SCM_I_CURRENT_THREAD;
|
SCM_SETCDR (after_gc_async_cell, t->pending_asyncs);
|
||||||
|
t->pending_asyncs = after_gc_async_cell;
|
||||||
if (scm_is_false (SCM_CDR (after_gc_async_cell)))
|
|
||||||
{
|
|
||||||
SCM_SETCDR (after_gc_async_cell, t->pending_asyncs);
|
|
||||||
t->pending_asyncs = after_gc_async_cell;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -30,6 +30,13 @@
|
||||||
#include "libguile/threads.h"
|
#include "libguile/threads.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Before Guile 2.0, Guile had a custom garbage collector and memory
|
||||||
|
management system that largely worked in terms of "cells", two-word
|
||||||
|
heap-tagged objects. This is no longer the case, and the "cell"
|
||||||
|
concept is obsolete; the allocator can now make objects of any size.
|
||||||
|
Still, some old code uses "cell" to mean a two-word allocation, so
|
||||||
|
for that reason you'll see the word around Guile. */
|
||||||
|
|
||||||
typedef struct scm_t_cell
|
typedef struct scm_t_cell
|
||||||
{
|
{
|
||||||
SCM word_0;
|
SCM word_0;
|
||||||
|
@ -40,12 +47,6 @@ typedef struct scm_t_cell
|
||||||
#define PTR2SCM(x) (SCM_PACK_POINTER (x))
|
#define PTR2SCM(x) (SCM_PACK_POINTER (x))
|
||||||
#define SCM2PTR(x) ((scm_t_cell *) (SCM_UNPACK_POINTER (x)))
|
#define SCM2PTR(x) ((scm_t_cell *) (SCM_UNPACK_POINTER (x)))
|
||||||
|
|
||||||
/* Low level cell data accessing macros. These macros should only be used
|
|
||||||
* from within code related to garbage collection issues, since they will
|
|
||||||
* never check the cells they are applied to - not even if guile is compiled
|
|
||||||
* in debug mode. In particular these macros will even work for free cells,
|
|
||||||
* which should never be encountered by user code. */
|
|
||||||
|
|
||||||
#define SCM_GC_CELL_OBJECT(x, n) (((SCM *)SCM2PTR (x)) [n])
|
#define SCM_GC_CELL_OBJECT(x, n) (((SCM *)SCM2PTR (x)) [n])
|
||||||
#define SCM_GC_CELL_WORD(x, n) (SCM_UNPACK (SCM_GC_CELL_OBJECT ((x), (n))))
|
#define SCM_GC_CELL_WORD(x, n) (SCM_UNPACK (SCM_GC_CELL_OBJECT ((x), (n))))
|
||||||
|
|
||||||
|
@ -55,49 +56,31 @@ typedef struct scm_t_cell
|
||||||
|
|
||||||
#define SCM_GC_CELL_TYPE(x) (SCM_GC_CELL_OBJECT ((x), 0))
|
#define SCM_GC_CELL_TYPE(x) (SCM_GC_CELL_OBJECT ((x), 0))
|
||||||
|
|
||||||
|
#define SCM_CELL_WORD(x, n) SCM_GC_CELL_WORD ((x), (n))
|
||||||
/* Except for the garbage collector, no part of guile should ever run over a
|
|
||||||
* free cell. Thus, if guile is compiled in debug mode the SCM_CELL_* and
|
|
||||||
* SCM_SET_CELL_* macros below report an error if they are applied to a free
|
|
||||||
* cell. Some other plausibility checks are also performed. However, if
|
|
||||||
* guile is not compiled in debug mode, there won't be any time penalty at all
|
|
||||||
* when using these macros. */
|
|
||||||
|
|
||||||
#if (SCM_DEBUG_CELL_ACCESSES == 1)
|
|
||||||
# define SCM_VALIDATE_CELL(cell, expr) (scm_assert_cell_valid (cell), (expr))
|
|
||||||
#else
|
|
||||||
# define SCM_VALIDATE_CELL(cell, expr) (expr)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SCM_CELL_WORD(x, n) \
|
|
||||||
SCM_VALIDATE_CELL ((x), SCM_GC_CELL_WORD ((x), (n)))
|
|
||||||
#define SCM_CELL_WORD_0(x) SCM_CELL_WORD ((x), 0)
|
#define SCM_CELL_WORD_0(x) SCM_CELL_WORD ((x), 0)
|
||||||
#define SCM_CELL_WORD_1(x) SCM_CELL_WORD ((x), 1)
|
#define SCM_CELL_WORD_1(x) SCM_CELL_WORD ((x), 1)
|
||||||
#define SCM_CELL_WORD_2(x) SCM_CELL_WORD ((x), 2)
|
#define SCM_CELL_WORD_2(x) SCM_CELL_WORD ((x), 2)
|
||||||
#define SCM_CELL_WORD_3(x) SCM_CELL_WORD ((x), 3)
|
#define SCM_CELL_WORD_3(x) SCM_CELL_WORD ((x), 3)
|
||||||
|
|
||||||
#define SCM_CELL_OBJECT(x, n) \
|
#define SCM_CELL_OBJECT(x, n) SCM_GC_CELL_OBJECT ((x), (n))
|
||||||
SCM_VALIDATE_CELL ((x), SCM_GC_CELL_OBJECT ((x), (n)))
|
|
||||||
#define SCM_CELL_OBJECT_0(x) SCM_CELL_OBJECT ((x), 0)
|
#define SCM_CELL_OBJECT_0(x) SCM_CELL_OBJECT ((x), 0)
|
||||||
#define SCM_CELL_OBJECT_1(x) SCM_CELL_OBJECT ((x), 1)
|
#define SCM_CELL_OBJECT_1(x) SCM_CELL_OBJECT ((x), 1)
|
||||||
#define SCM_CELL_OBJECT_2(x) SCM_CELL_OBJECT ((x), 2)
|
#define SCM_CELL_OBJECT_2(x) SCM_CELL_OBJECT ((x), 2)
|
||||||
#define SCM_CELL_OBJECT_3(x) SCM_CELL_OBJECT ((x), 3)
|
#define SCM_CELL_OBJECT_3(x) SCM_CELL_OBJECT ((x), 3)
|
||||||
|
|
||||||
#define SCM_SET_CELL_WORD(x, n, v) \
|
#define SCM_SET_CELL_WORD(x, n, v) SCM_GC_SET_CELL_WORD ((x), (n), (v))
|
||||||
SCM_VALIDATE_CELL ((x), SCM_GC_SET_CELL_WORD ((x), (n), (v)))
|
|
||||||
#define SCM_SET_CELL_WORD_0(x, v) SCM_SET_CELL_WORD ((x), 0, (v))
|
#define SCM_SET_CELL_WORD_0(x, v) SCM_SET_CELL_WORD ((x), 0, (v))
|
||||||
#define SCM_SET_CELL_WORD_1(x, v) SCM_SET_CELL_WORD ((x), 1, (v))
|
#define SCM_SET_CELL_WORD_1(x, v) SCM_SET_CELL_WORD ((x), 1, (v))
|
||||||
#define SCM_SET_CELL_WORD_2(x, v) SCM_SET_CELL_WORD ((x), 2, (v))
|
#define SCM_SET_CELL_WORD_2(x, v) SCM_SET_CELL_WORD ((x), 2, (v))
|
||||||
#define SCM_SET_CELL_WORD_3(x, v) SCM_SET_CELL_WORD ((x), 3, (v))
|
#define SCM_SET_CELL_WORD_3(x, v) SCM_SET_CELL_WORD ((x), 3, (v))
|
||||||
|
|
||||||
#define SCM_SET_CELL_OBJECT(x, n, v) \
|
#define SCM_SET_CELL_OBJECT(x, n, v) SCM_GC_SET_CELL_OBJECT ((x), (n), (v))
|
||||||
SCM_VALIDATE_CELL ((x), SCM_GC_SET_CELL_OBJECT ((x), (n), (v)))
|
|
||||||
#define SCM_SET_CELL_OBJECT_0(x, v) SCM_SET_CELL_OBJECT ((x), 0, (v))
|
#define SCM_SET_CELL_OBJECT_0(x, v) SCM_SET_CELL_OBJECT ((x), 0, (v))
|
||||||
#define SCM_SET_CELL_OBJECT_1(x, v) SCM_SET_CELL_OBJECT ((x), 1, (v))
|
#define SCM_SET_CELL_OBJECT_1(x, v) SCM_SET_CELL_OBJECT ((x), 1, (v))
|
||||||
#define SCM_SET_CELL_OBJECT_2(x, v) SCM_SET_CELL_OBJECT ((x), 2, (v))
|
#define SCM_SET_CELL_OBJECT_2(x, v) SCM_SET_CELL_OBJECT ((x), 2, (v))
|
||||||
#define SCM_SET_CELL_OBJECT_3(x, v) SCM_SET_CELL_OBJECT ((x), 3, (v))
|
#define SCM_SET_CELL_OBJECT_3(x, v) SCM_SET_CELL_OBJECT ((x), 3, (v))
|
||||||
|
|
||||||
#define SCM_CELL_OBJECT_LOC(x, n) (SCM_VALIDATE_CELL((x), &SCM_GC_CELL_OBJECT ((x), (n))))
|
#define SCM_CELL_OBJECT_LOC(x, n) (&SCM_GC_CELL_OBJECT ((x), (n)))
|
||||||
#define SCM_CARLOC(x) (SCM_CELL_OBJECT_LOC ((x), 0))
|
#define SCM_CARLOC(x) (SCM_CELL_OBJECT_LOC ((x), 0))
|
||||||
#define SCM_CDRLOC(x) (SCM_CELL_OBJECT_LOC ((x), 1))
|
#define SCM_CDRLOC(x) (SCM_CELL_OBJECT_LOC ((x), 1))
|
||||||
|
|
||||||
|
@ -105,15 +88,6 @@ typedef struct scm_t_cell
|
||||||
#define SCM_SET_CELL_TYPE(x, t) SCM_SET_CELL_WORD_0 ((x), (t))
|
#define SCM_SET_CELL_TYPE(x, t) SCM_SET_CELL_WORD_0 ((x), (t))
|
||||||
|
|
||||||
|
|
||||||
#if (SCM_DEBUG_CELL_ACCESSES == 1)
|
|
||||||
/* Set this to != 0 if every cell that is accessed shall be checked:
|
|
||||||
*/
|
|
||||||
SCM_API int scm_debug_cell_accesses_p;
|
|
||||||
SCM_API int scm_expensive_debug_cell_accesses_p;
|
|
||||||
SCM_API int scm_debug_cells_gc_interval ;
|
|
||||||
SCM_API void scm_i_expensive_validation_check (SCM cell);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SCM_INTERNAL scm_i_pthread_mutex_t scm_i_gc_admin_mutex;
|
SCM_INTERNAL scm_i_pthread_mutex_t scm_i_gc_admin_mutex;
|
||||||
|
|
||||||
#define scm_gc_running_p 0
|
#define scm_gc_running_p 0
|
||||||
|
@ -138,10 +112,6 @@ SCM_API scm_t_c_hook scm_after_gc_c_hook;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if (SCM_DEBUG_CELL_ACCESSES == 1)
|
|
||||||
SCM_API void scm_assert_cell_valid (SCM);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SCM_API SCM scm_set_debug_cell_accesses_x (SCM flag);
|
SCM_API SCM scm_set_debug_cell_accesses_x (SCM flag);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -89,10 +89,6 @@ scm_list_n (SCM elt, ...)
|
||||||
va_start (foo, elt);
|
va_start (foo, elt);
|
||||||
while (! SCM_UNBNDP (elt))
|
while (! SCM_UNBNDP (elt))
|
||||||
{
|
{
|
||||||
#if (SCM_DEBUG_CELL_ACCESSES == 1)
|
|
||||||
if (SCM_HEAP_OBJECT_P (elt))
|
|
||||||
SCM_VALIDATE_CELL(elt, 0);
|
|
||||||
#endif
|
|
||||||
*pos = scm_cons (elt, SCM_EOL);
|
*pos = scm_cons (elt, SCM_EOL);
|
||||||
pos = SCM_CDRLOC (*pos);
|
pos = SCM_CDRLOC (*pos);
|
||||||
elt = va_arg (foo, SCM);
|
elt = va_arg (foo, SCM);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue