2013-03-01 17:36:21 +01:00
|
|
|
|
/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2006,
|
2014-02-27 22:04:39 -05:00
|
|
|
|
* 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
|
2000-03-18 11:09:41 +00:00
|
|
|
|
*
|
2003-04-05 19:15:35 +00:00
|
|
|
|
* This library is free software; you can redistribute it and/or
|
2009-06-17 00:22:09 +01:00
|
|
|
|
* modify it under the terms of the GNU Lesser General Public License
|
|
|
|
|
|
* as published by the Free Software Foundation; either version 3 of
|
|
|
|
|
|
* the License, or (at your option) any later version.
|
2000-03-18 11:09:41 +00:00
|
|
|
|
*
|
2009-06-17 00:22:09 +01:00
|
|
|
|
* This library is distributed in the hope that it will be useful, but
|
|
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
2003-04-05 19:15:35 +00:00
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
|
* Lesser General Public License for more details.
|
2000-03-18 11:09:41 +00:00
|
|
|
|
*
|
2003-04-05 19:15:35 +00:00
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
|
* License along with this library; if not, write to the Free Software
|
2009-06-17 00:22:09 +01:00
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
|
|
|
|
* 02110-1301 USA
|
2003-04-05 19:15:35 +00:00
|
|
|
|
*/
|
1999-12-12 02:36:16 +00:00
|
|
|
|
|
2000-03-20 14:57:04 +00:00
|
|
|
|
/* #define DEBUGINFO */
|
|
|
|
|
|
|
2008-09-13 15:35:27 +02:00
|
|
|
|
#ifdef HAVE_CONFIG_H
|
2003-03-25 23:55:31 +00:00
|
|
|
|
# include <config.h>
|
|
|
|
|
|
#endif
|
2000-12-23 23:00:23 +00:00
|
|
|
|
|
2011-12-19 15:55:07 +01:00
|
|
|
|
#define SCM_BUILDING_DEPRECATED_CODE
|
|
|
|
|
|
|
2006-12-03 21:59:02 +00:00
|
|
|
|
#include "libguile/gen-scmconfig.h"
|
|
|
|
|
|
|
1996-07-25 22:56:11 +00:00
|
|
|
|
#include <stdio.h>
|
* _scm.h: Removed #include <errno.h>.
* error.c, net_db.c, putenv.c, stime.c: Removed declaration of
errno variable (can be a macro on some systems, for example when
using linux libc with threads).
* error.c, filesys.c, gc.c, ioext.c, iselect.c, net_db.c, ports.c,
posix.c, print.c, putenv.c, scmsigs.c, script.c, simpos.c, smob.c,
socket.c, srcprop.c, stime.c, strop.c, unif.c, vports.c: Added
#include <errno.h> in these 20 out of 100 files.
2001-03-10 16:56:09 +00:00
|
|
|
|
#include <errno.h>
|
2001-03-09 23:33:41 +00:00
|
|
|
|
#include <string.h>
|
2011-12-22 09:54:24 -05:00
|
|
|
|
#include <stdlib.h>
|
2011-11-29 00:48:56 +01:00
|
|
|
|
#include <math.h>
|
* _scm.h: Removed #include <errno.h>.
* error.c, net_db.c, putenv.c, stime.c: Removed declaration of
errno variable (can be a macro on some systems, for example when
using linux libc with threads).
* error.c, filesys.c, gc.c, ioext.c, iselect.c, net_db.c, ports.c,
posix.c, print.c, putenv.c, scmsigs.c, script.c, simpos.c, smob.c,
socket.c, srcprop.c, stime.c, strop.c, unif.c, vports.c: Added
#include <errno.h> in these 20 out of 100 files.
2001-03-10 16:56:09 +00:00
|
|
|
|
|
2006-12-12 16:23:36 +00:00
|
|
|
|
#ifdef __ia64__
|
|
|
|
|
|
#include <ucontext.h>
|
|
|
|
|
|
extern unsigned long * __libc_ia64_register_backing_store_base;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
2000-04-21 14:16:44 +00:00
|
|
|
|
#include "libguile/_scm.h"
|
2000-06-29 08:27:40 +00:00
|
|
|
|
#include "libguile/eval.h"
|
2000-04-21 14:16:44 +00:00
|
|
|
|
#include "libguile/stime.h"
|
|
|
|
|
|
#include "libguile/stackchk.h"
|
|
|
|
|
|
#include "libguile/struct.h"
|
|
|
|
|
|
#include "libguile/smob.h"
|
2009-07-17 01:08:35 +02:00
|
|
|
|
#include "libguile/arrays.h"
|
2000-04-21 14:16:44 +00:00
|
|
|
|
#include "libguile/async.h"
|
|
|
|
|
|
#include "libguile/ports.h"
|
|
|
|
|
|
#include "libguile/root.h"
|
|
|
|
|
|
#include "libguile/strings.h"
|
|
|
|
|
|
#include "libguile/vectors.h"
|
2000-04-21 23:11:29 +00:00
|
|
|
|
#include "libguile/weaks.h"
|
2000-05-21 20:49:20 +00:00
|
|
|
|
#include "libguile/hashtab.h"
|
2001-02-03 12:26:38 +00:00
|
|
|
|
#include "libguile/tags.h"
|
2000-04-21 14:16:44 +00:00
|
|
|
|
|
2002-08-04 00:17:18 +00:00
|
|
|
|
#include "libguile/private-gc.h"
|
2000-04-21 14:16:44 +00:00
|
|
|
|
#include "libguile/validate.h"
|
* validate.h
(SCM_NUM2{SIZE,PTRDIFF,SHORT,USHORT,BITS,UBITS,INT,UINT}[_DEF]):
new macros.
* unif.h: type renaming:
scm_array -> scm_array_t
scm_array_dim -> scm_array_dim_t
the old names are deprecated, all in-Guile uses changed.
* tags.h (scm_ubits_t): new typedef, representing unsigned
scm_bits_t.
* stacks.h: type renaming:
scm_info_frame -> scm_info_frame_t
scm_stack -> scm_stack_t
the old names are deprecated, all in-Guile uses changed.
* srcprop.h: type renaming:
scm_srcprops -> scm_srcprops_t
scm_srcprops_chunk -> scm_srcprops_chunk_t
the old names are deprecated, all in-Guile uses changed.
* gsubr.c, procs.c, print.c, ports.c, read.c, rdelim.c, ramap.c,
rw.c, smob.c, sort.c, srcprop.c, stacks.c, strings.c, strop.c,
strorder.c, strports.c, struct.c, symbols.c, unif.c, values.c,
vectors.c, vports.c, weaks.c:
various int/size_t -> size_t/scm_bits_t changes.
* random.h: type renaming:
scm_rstate -> scm_rstate_t
scm_rng -> scm_rng_t
scm_i_rstate -> scm_i_rstate_t
the old names are deprecated, all in-Guile uses changed.
* procs.h: type renaming:
scm_subr_entry -> scm_subr_entry_t
the old name is deprecated, all in-Guile uses changed.
* options.h (scm_option_t.val): unsigned long -> scm_bits_t.
type renaming:
scm_option -> scm_option_t
the old name is deprecated, all in-Guile uses changed.
* objects.c: various long -> scm_bits_t changes.
(scm_i_make_class_object): flags: unsigned long -> scm_ubits_t
* numbers.h (SCM_FIXNUM_BIT): deprecated, renamed to
SCM_I_FIXNUM_BIT.
* num2integral.i.c: new file, multiply included by numbers.c, used
to "templatize" the various integral <-> num conversion routines.
* numbers.c (scm_mkbig, scm_big2num, scm_adjbig, scm_normbig,
scm_copybig, scm_2ulong2big, scm_dbl2big, scm_big2dbl):
deprecated.
(scm_i_mkbig, scm_i_big2inum, scm_i_adjbig, scm_i_normbig,
scm_i_copybig, scm_i_short2big, scm_i_ushort2big, scm_i_int2big,
scm_i_uint2big, scm_i_long2big, scm_i_ulong2big, scm_i_bits2big,
scm_i_ubits2big, scm_i_size2big, scm_i_ptrdiff2big,
scm_i_long_long2big, scm_i_ulong_long2big, scm_i_dbl2big,
scm_i_big2dbl, scm_short2num, scm_ushort2num, scm_int2num,
scm_uint2num, scm_bits2num, scm_ubits2num, scm_size2num,
scm_ptrdiff2num, scm_num2short, scm_num2ushort, scm_num2int,
scm_num2uint, scm_num2bits, scm_num2ubits, scm_num2ptrdiff,
scm_num2size): new functions.
* modules.c (scm_module_reverse_lookup): i, n: int -> scm_bits_t.x
* load.c: change int -> size_t in various places (where the
variable is used to store a string length).
(search-path): call scm_done_free, not scm_done_malloc.
* list.c (scm_ilength): return a scm_bits_t, not long.
some other {int,long} -> scm_bits_t changes.
* hashtab.c: various [u]int -> scm_bits_t changes.
scm_ihashx_closure -> scm_ihashx_closure_t (and made a typedef).
(scm_ihashx): n: uint -> scm_bits_t
use scm_bits2num instead of scm_ulong2num.
* gsubr.c: various int -> scm_bits_t changes.
* gh_data.c (gh_scm2double): no loss of precision any more.
* gh.h (gh_str2scm): len: int -> size_t
(gh_{get,set}_substr): start: int -> scm_bits_t,
len: int -> size_t
(gh_<num>2scm): n: int -> scm_bits_t
(gh_*vector_length): return scm_[u]size_t, not unsigned long.
(gh_length): return scm_bits_t, not unsigned long.
* fports.h: type renaming:
scm_fport -> scm_fport_t
the old name is deprecated, all in-Guile uses changed.
* fports.c (fport_fill_input): count: int -> scm_bits_t
(fport_flush): init_size, remaining, count: int -> scm_bits_t
* debug.h (scm_lookup_cstr, scm_lookup_soft, scm_evstr): removed
those prototypes, as the functions they prototype don't exist.
* fports.c (default_buffer_size): int -> size_t
(scm_fport_buffer_add): read_size, write_size: int -> scm_bits_t
default_size: int -> size_t
(scm_setvbuf): csize: int -> scm_bits_t
* fluids.c (n_fluids): int -> scm_bits_t
(grow_fluids): old_length, i: int -> scm_bits_t
(next_fluid_num, scm_fluid_ref, scm_fluid_set_x): n: int ->
scm_bits_t
(scm_c_with_fluids): flen, vlen: int -> scm_bits_t
* filesys.c (s_scm_open_fdes): changed calls to SCM_NUM2LONG to
the new and shiny SCM_NUM2INT.
* extensions.c: extension -> extension_t (and made a typedef).
* eval.h (SCM_IFRAME): cast to scm_bits_t, not int. just so
there are no nasty surprises if/when the various deeply magic tag
bits move somewhere else.
* eval.c: changed the locals used to store results of SCM_IFRAME,
scm_ilength and such to be of type scm_bits_t (and not int/long).
(iqq): depth, edepth: int -> scm_bits_t
(scm_eval_stack): int -> scm_bits_t
(SCM_CEVAL): various vars are not scm_bits_t instead of int.
(check_map_args, scm_map, scm_for_each): len: long -> scm_bits_t
i: int -> scm_bits_t
* environments.c: changed the many calls to scm_ulong2num to
scm_ubits2num.
(import_environment_fold): proc_as_ul: ulong -> scm_ubits_t
* dynwind.c (scm_dowinds): delta: long -> scm_bits_t
* debug.h: type renaming:
scm_debug_info -> scm_debug_info_t
scm_debug_frame -> scm_debug_frame_t
the old names are deprecated, all in-Guile uses changed.
(scm_debug_eframe_size): int -> scm_bits_t
* debug.c (scm_init_debug): use scm_c_define instead of the
deprecated scm_define.
* continuations.h: type renaming:
scm_contregs -> scm_contregs_t
the old name is deprecated, all in-Guile uses changed.
(scm_contregs_t.num_stack_items): size_t -> scm_bits_t
(scm_contregs_t.num_stack_items): ulong -> scm_ubits_t
* continuations.c (scm_make_continuation): change the type of
stack_size form long to scm_bits_t.
* ports.h: type renaming:
scm_port_rw_active -> scm_port_rw_active_t (and made a typedef)
scm_port -> scm_port_t
scm_ptob_descriptor -> scm_ptob_descriptor_t
the old names are deprecated, all in-Guile uses changed.
(scm_port_t.entry): int -> scm_bits_t.
(scm_port_t.line_number): int -> long.
(scm_port_t.putback_buf_size): int -> size_t.
* __scm.h (long_long, ulong_long): deprecated (they pollute the
global namespace and have little value besides that).
(SCM_BITS_LENGTH): new, is the bit size of scm_bits_t (i.e. of an
SCM handle).
(ifdef spaghetti): include sys/types.h and sys/stdtypes.h, if they
exist (for size_t & ptrdiff_t)
(scm_sizet): deprecated.
* Makefile.am (noinst_HEADERS): add num2integral.i.c
2001-05-24 00:50:51 +00:00
|
|
|
|
#include "libguile/deprecation.h"
|
2000-04-21 14:16:44 +00:00
|
|
|
|
#include "libguile/gc.h"
|
2005-03-02 20:42:01 +00:00
|
|
|
|
#include "libguile/dynwind.h"
|
1996-09-10 19:06:45 +00:00
|
|
|
|
|
2009-09-13 15:59:31 +02:00
|
|
|
|
#include "libguile/bdw-gc.h"
|
2006-04-04 21:27:48 +00:00
|
|
|
|
|
2011-04-15 17:45:52 +02:00
|
|
|
|
/* For GC_set_start_callback. */
|
|
|
|
|
|
#include <gc/gc_mark.h>
|
|
|
|
|
|
|
2000-04-21 00:26:35 +00:00
|
|
|
|
#ifdef GUILE_DEBUG_MALLOC
|
2000-04-21 14:16:44 +00:00
|
|
|
|
#include "libguile/debug-malloc.h"
|
2000-04-21 00:26:35 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
1996-08-07 09:46:41 +00:00
|
|
|
|
#include <unistd.h>
|
1996-07-25 22:56:11 +00:00
|
|
|
|
|
2001-08-17 23:45:29 +00:00
|
|
|
|
/* Set this to != 0 if every cell that is accessed shall be checked:
|
2001-03-30 17:01:28 +00:00
|
|
|
|
*/
|
2002-08-08 19:47:31 +00:00
|
|
|
|
int scm_debug_cell_accesses_p = 0;
|
|
|
|
|
|
int scm_expensive_debug_cell_accesses_p = 0;
|
2000-07-13 15:00:58 +00:00
|
|
|
|
|
2001-06-07 21:12:19 +00:00
|
|
|
|
/* Set this to 0 if no additional gc's shall be performed, otherwise set it to
|
|
|
|
|
|
* the number of cell accesses after which a gc shall be called.
|
|
|
|
|
|
*/
|
2002-08-08 19:47:31 +00:00
|
|
|
|
int scm_debug_cells_gc_interval = 0;
|
2001-06-07 21:12:19 +00:00
|
|
|
|
|
2011-11-18 11:09:48 +01:00
|
|
|
|
#if SCM_ENABLE_DEPRECATED == 1
|
2010-02-13 19:33:51 +01:00
|
|
|
|
/* Hash table that keeps a reference to objects the user wants to protect from
|
|
|
|
|
|
garbage collection. It could arguably be private but applications have come
|
|
|
|
|
|
to rely on it (e.g., Lilypond 2.13.9). */
|
|
|
|
|
|
SCM scm_protects;
|
2011-11-18 11:09:48 +01:00
|
|
|
|
#else
|
|
|
|
|
|
static SCM scm_protects;
|
|
|
|
|
|
#endif
|
decruftify scm_sys_protects
* libguile/root.h
* libguile/root.c (scm_sys_protects): It used to be that for some reason
we'd define a special array of "protected" values. This was a little
silly, always, but with the BDW GC it's completely unnecessary. Also
many of these variables were unused, and none of them were good API.
So remove this array, and either eliminate, make static, or make
internal the various values.
* libguile/snarf.h: No need to generate calls to scm_permanent_object.
* guile-readline/readline.c (scm_init_readline): No need to call
scm_permanent_object.
* libguile/array-map.c (ramap, rafe): Remove the dubious nullvect
optimizations.
* libguile/async.c (scm_init_async): No need to init scm_asyncs, it is
no more.
* libguile/eval.c (scm_init_eval): No need to init scm_listofnull, it is
no more.
* libguile/gc.c: Make scm_protects a static var.
(scm_storage_prehistory): Change the sanity check to use the address
of protects.
(scm_init_gc_protect_object): No need to clear the scm_sys_protects,
as it is no more.
* libguile/keywords.c: Make the keyword obarray a static var.
* libguile/numbers.c: Make flo0 a static var.
* libguile/objprop.c: Make object_whash a static var.
* libguile/properties.c: Make properties_whash a static var.
* libguile/srcprop.h:
* libguile/srcprop.c: Make scm_source_whash a global with internal
linkage.
* libguile/strings.h:
* libguile/strings.c: Make scm_nullstr a global with internal linkage.
* libguile/vectors.c (scm_init_vectors): No need to init scm_nullvect,
it's unused.
2009-12-05 12:38:32 +01:00
|
|
|
|
|
2002-08-08 19:47:31 +00:00
|
|
|
|
#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.
|
|
|
|
|
|
|
|
|
|
|
|
*/
|
2000-07-13 15:00:58 +00:00
|
|
|
|
void
|
2002-08-08 19:47:31 +00:00
|
|
|
|
scm_i_expensive_validation_check (SCM cell)
|
2000-07-13 15:00:58 +00:00
|
|
|
|
{
|
2002-08-08 19:47:31 +00:00
|
|
|
|
/* 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;
|
2001-03-30 17:01:28 +00:00
|
|
|
|
|
2002-08-08 19:47:31 +00:00
|
|
|
|
if (counter != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
--counter;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
counter = scm_debug_cells_gc_interval;
|
2005-03-10 18:39:53 +00:00
|
|
|
|
scm_gc ();
|
2002-08-08 19:47:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2010-05-28 16:51:57 +02:00
|
|
|
|
/* Whether cell validation is already running. */
|
|
|
|
|
|
static int scm_i_cell_validation_already_running = 0;
|
|
|
|
|
|
|
2002-08-08 19:47:31 +00:00
|
|
|
|
void
|
|
|
|
|
|
scm_assert_cell_valid (SCM cell)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!scm_i_cell_validation_already_running && scm_debug_cell_accesses_p)
|
2000-07-13 15:00:58 +00:00
|
|
|
|
{
|
2002-08-08 19:47:31 +00:00
|
|
|
|
scm_i_cell_validation_already_running = 1; /* set to avoid recursion */
|
2000-07-13 15:00:58 +00:00
|
|
|
|
|
2002-08-04 00:17:18 +00:00
|
|
|
|
/*
|
2002-08-08 19:47:31 +00:00
|
|
|
|
During GC, no user-code should be run, and the guile core
|
|
|
|
|
|
should use non-protected accessors.
|
|
|
|
|
|
*/
|
2002-08-04 00:17:18 +00:00
|
|
|
|
if (scm_gc_running_p)
|
2002-08-08 19:47:31 +00:00
|
|
|
|
return;
|
2002-08-04 00:17:18 +00:00
|
|
|
|
|
|
|
|
|
|
/*
|
2002-08-08 19:47:31 +00:00
|
|
|
|
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);
|
2009-10-29 12:16:12 -04:00
|
|
|
|
|
2002-08-08 19:47:31 +00:00
|
|
|
|
scm_i_cell_validation_already_running = 0; /* re-enable */
|
2000-07-13 15:00:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2002-08-08 19:47:31 +00:00
|
|
|
|
|
2000-07-13 15:00:58 +00:00
|
|
|
|
SCM_DEFINE (scm_set_debug_cell_accesses_x, "set-debug-cell-accesses!", 1, 0, 0,
|
|
|
|
|
|
(SCM flag),
|
2001-04-03 13:19:05 +00:00
|
|
|
|
"If @var{flag} is @code{#f}, cell access checking is disabled.\n"
|
2002-08-08 19:47:31 +00:00
|
|
|
|
"If @var{flag} is @code{#t}, cheap cell access checking is enabled,\n"
|
2001-06-07 21:12:19 +00:00
|
|
|
|
"but no additional calls to garbage collection are issued.\n"
|
2002-08-08 19:47:31 +00:00
|
|
|
|
"If @var{flag} is a number, strict cell access checking is enabled,\n"
|
2001-06-07 21:12:19 +00:00
|
|
|
|
"with an additional garbage collection after the given\n"
|
|
|
|
|
|
"number of cell accesses.\n"
|
2001-04-03 13:19:05 +00:00
|
|
|
|
"This procedure only exists when the compile-time flag\n"
|
|
|
|
|
|
"@code{SCM_DEBUG_CELL_ACCESSES} was set to 1.")
|
2000-07-13 15:00:58 +00:00
|
|
|
|
#define FUNC_NAME s_scm_set_debug_cell_accesses_x
|
|
|
|
|
|
{
|
2004-07-06 10:59:25 +00:00
|
|
|
|
if (scm_is_false (flag))
|
2002-08-08 19:47:31 +00:00
|
|
|
|
{
|
|
|
|
|
|
scm_debug_cell_accesses_p = 0;
|
|
|
|
|
|
}
|
2004-07-27 15:41:49 +00:00
|
|
|
|
else if (scm_is_eq (flag, SCM_BOOL_T))
|
2002-08-08 19:47:31 +00:00
|
|
|
|
{
|
|
|
|
|
|
scm_debug_cells_gc_interval = 0;
|
|
|
|
|
|
scm_debug_cell_accesses_p = 1;
|
|
|
|
|
|
scm_expensive_debug_cell_accesses_p = 0;
|
|
|
|
|
|
}
|
2004-07-23 15:43:02 +00:00
|
|
|
|
else
|
2002-08-08 19:47:31 +00:00
|
|
|
|
{
|
2004-07-23 15:43:02 +00:00
|
|
|
|
scm_debug_cells_gc_interval = scm_to_signed_integer (flag, 0, INT_MAX);
|
2002-08-08 19:47:31 +00:00
|
|
|
|
scm_debug_cell_accesses_p = 1;
|
|
|
|
|
|
scm_expensive_debug_cell_accesses_p = 1;
|
|
|
|
|
|
}
|
2000-07-13 15:00:58 +00:00
|
|
|
|
return SCM_UNSPECIFIED;
|
|
|
|
|
|
}
|
|
|
|
|
|
#undef FUNC_NAME
|
1996-07-25 22:56:11 +00:00
|
|
|
|
|
2001-02-03 12:26:38 +00:00
|
|
|
|
|
2002-08-04 00:17:18 +00:00
|
|
|
|
#endif /* SCM_DEBUG_CELL_ACCESSES == 1 */
|
1996-07-25 22:56:11 +00:00
|
|
|
|
|
2011-11-28 19:58:53 +01:00
|
|
|
|
|
|
|
|
|
|
|
2011-11-29 00:48:56 +01:00
|
|
|
|
/* Compatibility. */
|
|
|
|
|
|
|
2011-11-28 19:58:53 +01:00
|
|
|
|
#ifndef HAVE_GC_GET_HEAP_USAGE_SAFE
|
|
|
|
|
|
static void
|
|
|
|
|
|
GC_get_heap_usage_safe (GC_word *pheap_size, GC_word *pfree_bytes,
|
|
|
|
|
|
GC_word *punmapped_bytes, GC_word *pbytes_since_gc,
|
|
|
|
|
|
GC_word *ptotal_bytes)
|
|
|
|
|
|
{
|
|
|
|
|
|
*pheap_size = GC_get_heap_size ();
|
|
|
|
|
|
*pfree_bytes = GC_get_free_bytes ();
|
2011-12-08 21:13:30 +01:00
|
|
|
|
#ifdef HAVE_GC_GET_UNMAPPED_BYTES
|
2011-11-28 19:58:53 +01:00
|
|
|
|
*punmapped_bytes = GC_get_unmapped_bytes ();
|
2011-12-08 21:13:30 +01:00
|
|
|
|
#else
|
|
|
|
|
|
*punmapped_bytes = 0;
|
|
|
|
|
|
#endif
|
2011-11-28 19:58:53 +01:00
|
|
|
|
*pbytes_since_gc = GC_get_bytes_since_gc ();
|
|
|
|
|
|
*ptotal_bytes = GC_get_total_bytes ();
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
2011-11-29 00:48:56 +01:00
|
|
|
|
#ifndef HAVE_GC_GET_FREE_SPACE_DIVISOR
|
|
|
|
|
|
static GC_word
|
|
|
|
|
|
GC_get_free_space_divisor (void)
|
|
|
|
|
|
{
|
|
|
|
|
|
return GC_free_space_divisor;
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
1996-07-25 22:56:11 +00:00
|
|
|
|
|
2006-03-21 22:16:33 +00:00
|
|
|
|
/* Hooks. */
|
|
|
|
|
|
scm_t_c_hook scm_before_gc_c_hook;
|
|
|
|
|
|
scm_t_c_hook scm_before_mark_c_hook;
|
|
|
|
|
|
scm_t_c_hook scm_before_sweep_c_hook;
|
|
|
|
|
|
scm_t_c_hook scm_after_sweep_c_hook;
|
|
|
|
|
|
scm_t_c_hook scm_after_gc_c_hook;
|
2000-03-14 09:02:51 +00:00
|
|
|
|
|
1996-07-25 22:56:11 +00:00
|
|
|
|
|
2011-04-15 16:41:34 +00:00
|
|
|
|
static void
|
|
|
|
|
|
run_before_gc_c_hook (void)
|
|
|
|
|
|
{
|
2012-01-30 16:42:09 +01:00
|
|
|
|
if (!SCM_I_CURRENT_THREAD)
|
|
|
|
|
|
/* GC while a thread is spinning up; punt. */
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2011-04-15 16:41:34 +00:00
|
|
|
|
scm_c_hook_run (&scm_before_gc_c_hook, NULL);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
1996-07-25 22:56:11 +00:00
|
|
|
|
/* GC Statistics Keeping
|
|
|
|
|
|
*/
|
Fixed warnings due to unused stuff.
* libguile/gc.c (scm_cells_allocated, scm_last_cells_allocated,
scm_gc_cells_collected, scm_gc_cells_collected_1,
scm_gc_malloc_collected, scm_gc_time_taken, t_before_gc,
scm_gc_mark_time_taken, scm_gc_times, scm_gc_cells_swept,
scm_gc_cells_marked_acc, scm_gc_cells_swept_acc,
scm_gc_cell_yield_percentage, scm_gc_malloc_yield_percentage):
Removed.
* libguile/gc.h: Updated accordingly.
* libguile/gdbint.c (port_mark_p, stream_mark_p, string_mark_p,
unmark_port, remark_port): Removed.
git-archimport-id: lcourtes@laas.fr--2006-libre/guile-core--boehm-gc--0--patch-4
2007-07-22 21:21:02 +00:00
|
|
|
|
unsigned long scm_gc_ports_collected = 0;
|
2011-05-04 18:48:02 +02:00
|
|
|
|
static long gc_time_taken = 0;
|
|
|
|
|
|
static long gc_start_time = 0;
|
|
|
|
|
|
|
2011-11-29 00:48:56 +01:00
|
|
|
|
static unsigned long free_space_divisor;
|
|
|
|
|
|
static unsigned long minimum_free_space_divisor;
|
|
|
|
|
|
static double target_free_space_divisor;
|
Fixed warnings due to unused stuff.
* libguile/gc.c (scm_cells_allocated, scm_last_cells_allocated,
scm_gc_cells_collected, scm_gc_cells_collected_1,
scm_gc_malloc_collected, scm_gc_time_taken, t_before_gc,
scm_gc_mark_time_taken, scm_gc_times, scm_gc_cells_swept,
scm_gc_cells_marked_acc, scm_gc_cells_swept_acc,
scm_gc_cell_yield_percentage, scm_gc_malloc_yield_percentage):
Removed.
* libguile/gc.h: Updated accordingly.
* libguile/gdbint.c (port_mark_p, stream_mark_p, string_mark_p,
unmark_port, remark_port): Removed.
git-archimport-id: lcourtes@laas.fr--2006-libre/guile-core--boehm-gc--0--patch-4
2007-07-22 21:21:02 +00:00
|
|
|
|
|
2006-07-02 20:26:29 +00:00
|
|
|
|
static unsigned long protected_obj_count = 0;
|
2002-08-04 14:09:14 +00:00
|
|
|
|
|
1996-07-25 22:56:11 +00:00
|
|
|
|
|
2011-03-17 11:43:06 +01:00
|
|
|
|
SCM_SYMBOL (sym_gc_time_taken, "gc-time-taken");
|
2006-07-02 20:26:29 +00:00
|
|
|
|
SCM_SYMBOL (sym_heap_size, "heap-size");
|
|
|
|
|
|
SCM_SYMBOL (sym_heap_free_size, "heap-free-size");
|
|
|
|
|
|
SCM_SYMBOL (sym_heap_total_allocated, "heap-total-allocated");
|
2011-03-17 11:43:06 +01:00
|
|
|
|
SCM_SYMBOL (sym_heap_allocated_since_gc, "heap-allocated-since-gc");
|
2004-01-21 00:06:11 +00:00
|
|
|
|
SCM_SYMBOL (sym_protected_objects, "protected-objects");
|
2011-03-17 11:43:06 +01:00
|
|
|
|
SCM_SYMBOL (sym_times, "gc-times");
|
1996-11-10 20:46:21 +00:00
|
|
|
|
|
2001-03-14 10:02:12 +00:00
|
|
|
|
|
1996-07-25 22:56:11 +00:00
|
|
|
|
/* {Scheme Interface to GC}
|
|
|
|
|
|
*/
|
2002-08-04 14:09:14 +00:00
|
|
|
|
extern int scm_gc_malloc_yield_percentage;
|
2000-03-18 11:09:41 +00:00
|
|
|
|
SCM_DEFINE (scm_gc_stats, "gc-stats", 0, 0, 0,
|
1999-12-12 02:36:16 +00:00
|
|
|
|
(),
|
2001-04-03 13:19:05 +00:00
|
|
|
|
"Return an association list of statistics about Guile's current\n"
|
2002-08-04 00:17:18 +00:00
|
|
|
|
"use of storage.\n")
|
1999-12-12 02:36:16 +00:00
|
|
|
|
#define FUNC_NAME s_scm_gc_stats
|
1996-07-25 22:56:11 +00:00
|
|
|
|
{
|
|
|
|
|
|
SCM answer;
|
2011-11-28 19:58:53 +01:00
|
|
|
|
GC_word heap_size, free_bytes, unmapped_bytes, bytes_since_gc, total_bytes;
|
2006-07-02 20:26:29 +00:00
|
|
|
|
size_t gc_times;
|
* gc.h, gc.c (scm_gc_sweep): Issue deprecation warning when
non-zero is returned from a port or smob free function.
(scm_malloc, scm_realloc, scm_strndup, scm_strdup,
scm_gc_register_collectable_memory,
scm_gc_unregister_collectable_memory, scm_gc_malloc,
scm_gc_realloc, scm_gc_free, scm_gc_strndup, scm_gc_strdup): New.
* backtrace.c, continuations.c, convert.i.c, coop-threads.c,
debug-malloc.c, dynl.c, environments.c, environments.h,
extensions.c, filesys.c, fports.c, gc.c, gc.h, gh_data.c, goops.c,
guardians.c, hooks.c, init.c, keywords.c, load.c, numbers.c,
ports.c, posix.c, procs.c, rdelim.c, regex-posix.c, root.c,
smob.c, stime.c, strings.c, struct.c, struct.h, symbols.c, unif.c,
vectors.c, weaks.c: Use scm_gc_malloc/scm_malloc and
scm_gc_free/free instead of scm_must_malloc and scm_must_free, as
appropriate. Return zero from smob and port free functions.
* debug-malloc.c (scm_malloc_reregister): Handle "old == NULL".
* fports.c (scm_setvbuf): Reset read buffer to saved values when
it is pointing to the putback buffer.
2002-02-11 18:06:50 +00:00
|
|
|
|
|
2011-11-28 19:58:53 +01:00
|
|
|
|
GC_get_heap_usage_safe (&heap_size, &free_bytes, &unmapped_bytes,
|
|
|
|
|
|
&bytes_since_gc, &total_bytes);
|
2013-03-01 17:36:21 +01:00
|
|
|
|
#ifdef HAVE_GC_GET_GC_NO
|
|
|
|
|
|
/* This function was added in 7.2alpha2 (June 2009). */
|
|
|
|
|
|
gc_times = GC_get_gc_no ();
|
|
|
|
|
|
#else
|
|
|
|
|
|
/* This symbol is deprecated as of 7.3. */
|
2011-11-28 19:58:53 +01:00
|
|
|
|
gc_times = GC_gc_no;
|
2013-03-01 17:36:21 +01:00
|
|
|
|
#endif
|
2006-04-02 21:05:04 +00:00
|
|
|
|
|
* numbers.h, numbers.c, discouraged.h, discouraged.c (scm_short2num,
scm_ushort2num, scm_int2num, scm_uint2num, scm_long2num,
scm_ulong2num, scm_size2num, scm_ptrdiff2num, scm_num2short,
scm_num2ushort, scm_num2int, scm_num2uint, scm_num2long,
scm_num2ulong, scm_num2size, scm_num2ptrdiff, scm_long_long2num,
scm_ulong_long2num, scm_num2long_long, scm_num2ulong_long):
Discouraged by moving to discouraged.h and discouraged.c and
reimplementing in terms of scm_from_* and scm_to_*. Changed all uses
to the new scm_from_* and scm_to_* functions.
2004-08-02 16:14:04 +00:00
|
|
|
|
answer =
|
2011-05-04 18:48:02 +02:00
|
|
|
|
scm_list_n (scm_cons (sym_gc_time_taken, scm_from_long (gc_time_taken)),
|
2006-07-02 20:26:29 +00:00
|
|
|
|
scm_cons (sym_heap_size, scm_from_size_t (heap_size)),
|
|
|
|
|
|
scm_cons (sym_heap_free_size, scm_from_size_t (free_bytes)),
|
|
|
|
|
|
scm_cons (sym_heap_total_allocated,
|
|
|
|
|
|
scm_from_size_t (total_bytes)),
|
2011-03-17 11:43:06 +01:00
|
|
|
|
scm_cons (sym_heap_allocated_since_gc,
|
|
|
|
|
|
scm_from_size_t (bytes_since_gc)),
|
2006-07-02 20:26:29 +00:00
|
|
|
|
scm_cons (sym_protected_objects,
|
|
|
|
|
|
scm_from_ulong (protected_obj_count)),
|
|
|
|
|
|
scm_cons (sym_times, scm_from_size_t (gc_times)),
|
* numbers.h, numbers.c, discouraged.h, discouraged.c (scm_short2num,
scm_ushort2num, scm_int2num, scm_uint2num, scm_long2num,
scm_ulong2num, scm_size2num, scm_ptrdiff2num, scm_num2short,
scm_num2ushort, scm_num2int, scm_num2uint, scm_num2long,
scm_num2ulong, scm_num2size, scm_num2ptrdiff, scm_long_long2num,
scm_ulong_long2num, scm_num2long_long, scm_num2ulong_long):
Discouraged by moving to discouraged.h and discouraged.c and
reimplementing in terms of scm_from_* and scm_to_*. Changed all uses
to the new scm_from_* and scm_to_* functions.
2004-08-02 16:14:04 +00:00
|
|
|
|
SCM_UNDEFINED);
|
2006-04-02 21:05:04 +00:00
|
|
|
|
|
2002-08-04 00:17:18 +00:00
|
|
|
|
return answer;
|
1996-07-25 22:56:11 +00:00
|
|
|
|
}
|
2002-08-04 00:17:18 +00:00
|
|
|
|
#undef FUNC_NAME
|
1996-07-25 22:56:11 +00:00
|
|
|
|
|
2002-02-14 15:32:12 +00:00
|
|
|
|
|
2008-10-23 17:46:08 +02:00
|
|
|
|
SCM_DEFINE (scm_gc_dump, "gc-dump", 0, 0, 0,
|
|
|
|
|
|
(void),
|
|
|
|
|
|
"Dump information about the garbage collector's internal data "
|
|
|
|
|
|
"structures and memory usage to the standard output.")
|
|
|
|
|
|
#define FUNC_NAME s_scm_gc_dump
|
|
|
|
|
|
{
|
|
|
|
|
|
GC_dump ();
|
|
|
|
|
|
|
|
|
|
|
|
return SCM_UNSPECIFIED;
|
|
|
|
|
|
}
|
|
|
|
|
|
#undef FUNC_NAME
|
|
|
|
|
|
|
2000-06-29 13:31:33 +00:00
|
|
|
|
|
2002-08-04 00:17:18 +00:00
|
|
|
|
SCM_DEFINE (scm_object_address, "object-address", 1, 0, 0,
|
|
|
|
|
|
(SCM obj),
|
|
|
|
|
|
"Return an integer that for the lifetime of @var{obj} is uniquely\n"
|
|
|
|
|
|
"returned by this function for @var{obj}")
|
|
|
|
|
|
#define FUNC_NAME s_scm_object_address
|
1997-10-02 14:45:09 +00:00
|
|
|
|
{
|
* numbers.h, numbers.c, discouraged.h, discouraged.c (scm_short2num,
scm_ushort2num, scm_int2num, scm_uint2num, scm_long2num,
scm_ulong2num, scm_size2num, scm_ptrdiff2num, scm_num2short,
scm_num2ushort, scm_num2int, scm_num2uint, scm_num2long,
scm_num2ulong, scm_num2size, scm_num2ptrdiff, scm_long_long2num,
scm_ulong_long2num, scm_num2long_long, scm_num2ulong_long):
Discouraged by moving to discouraged.h and discouraged.c and
reimplementing in terms of scm_from_* and scm_to_*. Changed all uses
to the new scm_from_* and scm_to_* functions.
2004-08-02 16:14:04 +00:00
|
|
|
|
return scm_from_ulong (SCM_UNPACK (obj));
|
1997-10-02 14:45:09 +00:00
|
|
|
|
}
|
2002-08-04 00:17:18 +00:00
|
|
|
|
#undef FUNC_NAME
|
1997-10-02 14:45:09 +00:00
|
|
|
|
|
* validate.h
(SCM_NUM2{SIZE,PTRDIFF,SHORT,USHORT,BITS,UBITS,INT,UINT}[_DEF]):
new macros.
* unif.h: type renaming:
scm_array -> scm_array_t
scm_array_dim -> scm_array_dim_t
the old names are deprecated, all in-Guile uses changed.
* tags.h (scm_ubits_t): new typedef, representing unsigned
scm_bits_t.
* stacks.h: type renaming:
scm_info_frame -> scm_info_frame_t
scm_stack -> scm_stack_t
the old names are deprecated, all in-Guile uses changed.
* srcprop.h: type renaming:
scm_srcprops -> scm_srcprops_t
scm_srcprops_chunk -> scm_srcprops_chunk_t
the old names are deprecated, all in-Guile uses changed.
* gsubr.c, procs.c, print.c, ports.c, read.c, rdelim.c, ramap.c,
rw.c, smob.c, sort.c, srcprop.c, stacks.c, strings.c, strop.c,
strorder.c, strports.c, struct.c, symbols.c, unif.c, values.c,
vectors.c, vports.c, weaks.c:
various int/size_t -> size_t/scm_bits_t changes.
* random.h: type renaming:
scm_rstate -> scm_rstate_t
scm_rng -> scm_rng_t
scm_i_rstate -> scm_i_rstate_t
the old names are deprecated, all in-Guile uses changed.
* procs.h: type renaming:
scm_subr_entry -> scm_subr_entry_t
the old name is deprecated, all in-Guile uses changed.
* options.h (scm_option_t.val): unsigned long -> scm_bits_t.
type renaming:
scm_option -> scm_option_t
the old name is deprecated, all in-Guile uses changed.
* objects.c: various long -> scm_bits_t changes.
(scm_i_make_class_object): flags: unsigned long -> scm_ubits_t
* numbers.h (SCM_FIXNUM_BIT): deprecated, renamed to
SCM_I_FIXNUM_BIT.
* num2integral.i.c: new file, multiply included by numbers.c, used
to "templatize" the various integral <-> num conversion routines.
* numbers.c (scm_mkbig, scm_big2num, scm_adjbig, scm_normbig,
scm_copybig, scm_2ulong2big, scm_dbl2big, scm_big2dbl):
deprecated.
(scm_i_mkbig, scm_i_big2inum, scm_i_adjbig, scm_i_normbig,
scm_i_copybig, scm_i_short2big, scm_i_ushort2big, scm_i_int2big,
scm_i_uint2big, scm_i_long2big, scm_i_ulong2big, scm_i_bits2big,
scm_i_ubits2big, scm_i_size2big, scm_i_ptrdiff2big,
scm_i_long_long2big, scm_i_ulong_long2big, scm_i_dbl2big,
scm_i_big2dbl, scm_short2num, scm_ushort2num, scm_int2num,
scm_uint2num, scm_bits2num, scm_ubits2num, scm_size2num,
scm_ptrdiff2num, scm_num2short, scm_num2ushort, scm_num2int,
scm_num2uint, scm_num2bits, scm_num2ubits, scm_num2ptrdiff,
scm_num2size): new functions.
* modules.c (scm_module_reverse_lookup): i, n: int -> scm_bits_t.x
* load.c: change int -> size_t in various places (where the
variable is used to store a string length).
(search-path): call scm_done_free, not scm_done_malloc.
* list.c (scm_ilength): return a scm_bits_t, not long.
some other {int,long} -> scm_bits_t changes.
* hashtab.c: various [u]int -> scm_bits_t changes.
scm_ihashx_closure -> scm_ihashx_closure_t (and made a typedef).
(scm_ihashx): n: uint -> scm_bits_t
use scm_bits2num instead of scm_ulong2num.
* gsubr.c: various int -> scm_bits_t changes.
* gh_data.c (gh_scm2double): no loss of precision any more.
* gh.h (gh_str2scm): len: int -> size_t
(gh_{get,set}_substr): start: int -> scm_bits_t,
len: int -> size_t
(gh_<num>2scm): n: int -> scm_bits_t
(gh_*vector_length): return scm_[u]size_t, not unsigned long.
(gh_length): return scm_bits_t, not unsigned long.
* fports.h: type renaming:
scm_fport -> scm_fport_t
the old name is deprecated, all in-Guile uses changed.
* fports.c (fport_fill_input): count: int -> scm_bits_t
(fport_flush): init_size, remaining, count: int -> scm_bits_t
* debug.h (scm_lookup_cstr, scm_lookup_soft, scm_evstr): removed
those prototypes, as the functions they prototype don't exist.
* fports.c (default_buffer_size): int -> size_t
(scm_fport_buffer_add): read_size, write_size: int -> scm_bits_t
default_size: int -> size_t
(scm_setvbuf): csize: int -> scm_bits_t
* fluids.c (n_fluids): int -> scm_bits_t
(grow_fluids): old_length, i: int -> scm_bits_t
(next_fluid_num, scm_fluid_ref, scm_fluid_set_x): n: int ->
scm_bits_t
(scm_c_with_fluids): flen, vlen: int -> scm_bits_t
* filesys.c (s_scm_open_fdes): changed calls to SCM_NUM2LONG to
the new and shiny SCM_NUM2INT.
* extensions.c: extension -> extension_t (and made a typedef).
* eval.h (SCM_IFRAME): cast to scm_bits_t, not int. just so
there are no nasty surprises if/when the various deeply magic tag
bits move somewhere else.
* eval.c: changed the locals used to store results of SCM_IFRAME,
scm_ilength and such to be of type scm_bits_t (and not int/long).
(iqq): depth, edepth: int -> scm_bits_t
(scm_eval_stack): int -> scm_bits_t
(SCM_CEVAL): various vars are not scm_bits_t instead of int.
(check_map_args, scm_map, scm_for_each): len: long -> scm_bits_t
i: int -> scm_bits_t
* environments.c: changed the many calls to scm_ulong2num to
scm_ubits2num.
(import_environment_fold): proc_as_ul: ulong -> scm_ubits_t
* dynwind.c (scm_dowinds): delta: long -> scm_bits_t
* debug.h: type renaming:
scm_debug_info -> scm_debug_info_t
scm_debug_frame -> scm_debug_frame_t
the old names are deprecated, all in-Guile uses changed.
(scm_debug_eframe_size): int -> scm_bits_t
* debug.c (scm_init_debug): use scm_c_define instead of the
deprecated scm_define.
* continuations.h: type renaming:
scm_contregs -> scm_contregs_t
the old name is deprecated, all in-Guile uses changed.
(scm_contregs_t.num_stack_items): size_t -> scm_bits_t
(scm_contregs_t.num_stack_items): ulong -> scm_ubits_t
* continuations.c (scm_make_continuation): change the type of
stack_size form long to scm_bits_t.
* ports.h: type renaming:
scm_port_rw_active -> scm_port_rw_active_t (and made a typedef)
scm_port -> scm_port_t
scm_ptob_descriptor -> scm_ptob_descriptor_t
the old names are deprecated, all in-Guile uses changed.
(scm_port_t.entry): int -> scm_bits_t.
(scm_port_t.line_number): int -> long.
(scm_port_t.putback_buf_size): int -> size_t.
* __scm.h (long_long, ulong_long): deprecated (they pollute the
global namespace and have little value besides that).
(SCM_BITS_LENGTH): new, is the bit size of scm_bits_t (i.e. of an
SCM handle).
(ifdef spaghetti): include sys/types.h and sys/stdtypes.h, if they
exist (for size_t & ptrdiff_t)
(scm_sizet): deprecated.
* Makefile.am (noinst_HEADERS): add num2integral.i.c
2001-05-24 00:50:51 +00:00
|
|
|
|
|
2006-07-02 20:26:29 +00:00
|
|
|
|
SCM_DEFINE (scm_gc_disable, "gc-disable", 0, 0, 0,
|
|
|
|
|
|
(),
|
|
|
|
|
|
"Disables the garbage collector. Nested calls are permitted. "
|
|
|
|
|
|
"GC is re-enabled once @code{gc-enable} has been called the "
|
|
|
|
|
|
"same number of times @code{gc-disable} was called.")
|
|
|
|
|
|
#define FUNC_NAME s_scm_gc_disable
|
|
|
|
|
|
{
|
|
|
|
|
|
GC_disable ();
|
|
|
|
|
|
return SCM_UNSPECIFIED;
|
|
|
|
|
|
}
|
|
|
|
|
|
#undef FUNC_NAME
|
|
|
|
|
|
|
|
|
|
|
|
SCM_DEFINE (scm_gc_enable, "gc-enable", 0, 0, 0,
|
|
|
|
|
|
(),
|
|
|
|
|
|
"Enables the garbage collector.")
|
|
|
|
|
|
#define FUNC_NAME s_scm_gc_enable
|
|
|
|
|
|
{
|
|
|
|
|
|
GC_enable ();
|
|
|
|
|
|
return SCM_UNSPECIFIED;
|
|
|
|
|
|
}
|
|
|
|
|
|
#undef FUNC_NAME
|
|
|
|
|
|
|
|
|
|
|
|
|
2002-08-04 00:17:18 +00:00
|
|
|
|
SCM_DEFINE (scm_gc, "gc", 0, 0, 0,
|
|
|
|
|
|
(),
|
|
|
|
|
|
"Scans all of SCM objects and reclaims for further use those that are\n"
|
|
|
|
|
|
"no longer accessible.")
|
|
|
|
|
|
#define FUNC_NAME s_scm_gc
|
|
|
|
|
|
{
|
2005-03-10 18:39:53 +00:00
|
|
|
|
scm_i_gc ("call");
|
2012-02-24 13:18:48 +01:00
|
|
|
|
/* If you're calling scm_gc(), you probably want synchronous
|
|
|
|
|
|
finalization. */
|
|
|
|
|
|
GC_invoke_finalizers ();
|
2002-08-04 00:17:18 +00:00
|
|
|
|
return SCM_UNSPECIFIED;
|
2000-07-15 13:44:04 +00:00
|
|
|
|
}
|
2002-08-04 00:17:18 +00:00
|
|
|
|
#undef FUNC_NAME
|
2000-07-15 13:44:04 +00:00
|
|
|
|
|
2002-08-04 00:17:18 +00:00
|
|
|
|
void
|
2005-03-10 18:39:53 +00:00
|
|
|
|
scm_i_gc (const char *what)
|
2002-08-04 00:17:18 +00:00
|
|
|
|
{
|
2011-04-15 18:31:06 +02:00
|
|
|
|
#ifndef HAVE_GC_SET_START_CALLBACK
|
|
|
|
|
|
run_before_gc_c_hook ();
|
|
|
|
|
|
#endif
|
2006-03-21 22:16:33 +00:00
|
|
|
|
GC_gcollect ();
|
2002-08-08 19:47:31 +00:00
|
|
|
|
}
|
1996-07-25 22:56:11 +00:00
|
|
|
|
|
2006-02-14 11:38:30 +00:00
|
|
|
|
|
1996-07-25 22:56:11 +00:00
|
|
|
|
|
|
|
|
|
|
/* {GC Protection Helper Functions}
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
2000-12-28 16:49:09 +00:00
|
|
|
|
/*
|
|
|
|
|
|
* If within a function you need to protect one or more scheme objects from
|
|
|
|
|
|
* garbage collection, pass them as parameters to one of the
|
|
|
|
|
|
* scm_remember_upto_here* functions below. These functions don't do
|
|
|
|
|
|
* anything, but since the compiler does not know that they are actually
|
|
|
|
|
|
* no-ops, it will generate code that calls these functions with the given
|
|
|
|
|
|
* parameters. Therefore, you can be sure that the compiler will keep those
|
|
|
|
|
|
* scheme values alive (on the stack or in a register) up to the point where
|
|
|
|
|
|
* scm_remember_upto_here* is called. In other words, place the call to
|
2001-06-30 19:50:10 +00:00
|
|
|
|
* scm_remember_upto_here* _behind_ the last code in your function, that
|
2000-12-28 16:49:09 +00:00
|
|
|
|
* depends on the scheme object to exist.
|
|
|
|
|
|
*
|
2001-08-31 14:42:31 +00:00
|
|
|
|
* Example: We want to make sure that the string object str does not get
|
|
|
|
|
|
* garbage collected during the execution of 'some_function' in the code
|
|
|
|
|
|
* below, because otherwise the characters belonging to str would be freed and
|
2000-12-28 16:49:09 +00:00
|
|
|
|
* 'some_function' might access freed memory. To make sure that the compiler
|
|
|
|
|
|
* keeps str alive on the stack or in a register such that it is visible to
|
|
|
|
|
|
* the conservative gc we add the call to scm_remember_upto_here_1 _after_ the
|
|
|
|
|
|
* call to 'some_function'. Note that this would not be necessary if str was
|
|
|
|
|
|
* used anyway after the call to 'some_function'.
|
2004-08-19 16:48:38 +00:00
|
|
|
|
* char *chars = scm_i_string_chars (str);
|
2000-12-28 16:49:09 +00:00
|
|
|
|
* some_function (chars);
|
|
|
|
|
|
* scm_remember_upto_here_1 (str); // str will be alive up to this point.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2003-08-12 21:09:10 +00:00
|
|
|
|
/* Remove any macro versions of these while defining the functions.
|
|
|
|
|
|
Functions are always included in the library, for upward binary
|
|
|
|
|
|
compatibility and in case combinations of GCC and non-GCC are used. */
|
|
|
|
|
|
#undef scm_remember_upto_here_1
|
|
|
|
|
|
#undef scm_remember_upto_here_2
|
|
|
|
|
|
|
2000-12-28 16:49:09 +00:00
|
|
|
|
void
|
2001-06-07 21:12:19 +00:00
|
|
|
|
scm_remember_upto_here_1 (SCM obj SCM_UNUSED)
|
2000-12-28 16:49:09 +00:00
|
|
|
|
{
|
|
|
|
|
|
/* Empty. Protects a single object from garbage collection. */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2001-06-07 21:12:19 +00:00
|
|
|
|
scm_remember_upto_here_2 (SCM obj1 SCM_UNUSED, SCM obj2 SCM_UNUSED)
|
2000-12-28 16:49:09 +00:00
|
|
|
|
{
|
|
|
|
|
|
/* Empty. Protects two objects from garbage collection. */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2001-06-07 21:12:19 +00:00
|
|
|
|
scm_remember_upto_here (SCM obj SCM_UNUSED, ...)
|
2000-12-28 16:49:09 +00:00
|
|
|
|
{
|
|
|
|
|
|
/* Empty. Protects any number of objects from garbage collection. */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2000-03-09 18:58:58 +00:00
|
|
|
|
/*
|
2000-03-09 21:48:25 +00:00
|
|
|
|
These crazy functions prevent garbage collection
|
|
|
|
|
|
of arguments after the first argument by
|
|
|
|
|
|
ensuring they remain live throughout the
|
|
|
|
|
|
function because they are used in the last
|
|
|
|
|
|
line of the code block.
|
|
|
|
|
|
It'd be better to have a nice compiler hint to
|
|
|
|
|
|
aid the conservative stack-scanning GC. --03/09/00 gjb */
|
1996-07-25 22:56:11 +00:00
|
|
|
|
SCM
|
|
|
|
|
|
scm_return_first (SCM elt, ...)
|
|
|
|
|
|
{
|
|
|
|
|
|
return elt;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2000-03-09 21:48:25 +00:00
|
|
|
|
int
|
|
|
|
|
|
scm_return_first_int (int i, ...)
|
|
|
|
|
|
{
|
|
|
|
|
|
return i;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
1996-07-25 22:56:11 +00:00
|
|
|
|
|
|
|
|
|
|
SCM
|
1999-12-12 20:35:02 +00:00
|
|
|
|
scm_permanent_object (SCM obj)
|
1996-07-25 22:56:11 +00:00
|
|
|
|
{
|
2006-11-27 00:16:27 +00:00
|
|
|
|
return (scm_gc_protect_object (obj));
|
1996-07-25 22:56:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2000-06-19 10:03:57 +00:00
|
|
|
|
/* Protect OBJ from the garbage collector. OBJ will not be freed, even if all
|
|
|
|
|
|
other references are dropped, until the object is unprotected by calling
|
2001-05-26 22:10:58 +00:00
|
|
|
|
scm_gc_unprotect_object (OBJ). Calls to scm_gc_protect/unprotect_object nest,
|
2000-06-19 10:03:57 +00:00
|
|
|
|
i. e. it is possible to protect the same object several times, but it is
|
|
|
|
|
|
necessary to unprotect the object the same number of times to actually get
|
|
|
|
|
|
the object unprotected. It is an error to unprotect an object more often
|
|
|
|
|
|
than it has been protected before. The function scm_protect_object returns
|
|
|
|
|
|
OBJ.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/* Implementation note: For every object X, there is a counter which
|
2008-08-21 23:16:20 -03:00
|
|
|
|
scm_gc_protect_object (X) increments and scm_gc_unprotect_object (X) decrements.
|
2000-06-19 10:03:57 +00:00
|
|
|
|
*/
|
2000-05-21 20:49:20 +00:00
|
|
|
|
|
2004-01-21 00:06:11 +00:00
|
|
|
|
|
|
|
|
|
|
|
1996-12-23 04:37:03 +00:00
|
|
|
|
SCM
|
2001-05-26 22:10:58 +00:00
|
|
|
|
scm_gc_protect_object (SCM obj)
|
1996-12-23 04:37:03 +00:00
|
|
|
|
{
|
2000-05-21 20:49:20 +00:00
|
|
|
|
SCM handle;
|
2000-07-15 13:44:04 +00:00
|
|
|
|
|
2000-05-21 20:49:20 +00:00
|
|
|
|
/* This critical section barrier will be replaced by a mutex. */
|
2005-03-30 22:11:07 +00:00
|
|
|
|
/* njrev: Indeed; if my comment above is correct, there is the same
|
|
|
|
|
|
critsec/mutex inconsistency here. */
|
2005-03-02 20:42:01 +00:00
|
|
|
|
SCM_CRITICAL_SECTION_START;
|
2000-07-15 13:44:04 +00:00
|
|
|
|
|
2010-02-13 19:33:51 +01:00
|
|
|
|
handle = scm_hashq_create_handle_x (scm_protects, obj, scm_from_int (0));
|
2004-07-23 15:43:02 +00:00
|
|
|
|
SCM_SETCDR (handle, scm_sum (SCM_CDR (handle), scm_from_int (1)));
|
2000-07-15 13:44:04 +00:00
|
|
|
|
|
2004-01-21 00:06:11 +00:00
|
|
|
|
protected_obj_count ++;
|
|
|
|
|
|
|
2005-03-02 20:42:01 +00:00
|
|
|
|
SCM_CRITICAL_SECTION_END;
|
2000-07-15 13:44:04 +00:00
|
|
|
|
|
1996-12-23 04:37:03 +00:00
|
|
|
|
return obj;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Remove any protection for OBJ established by a prior call to
|
1998-10-07 20:05:56 +00:00
|
|
|
|
scm_protect_object. This function returns OBJ.
|
1996-12-23 04:37:03 +00:00
|
|
|
|
|
1998-10-07 20:05:56 +00:00
|
|
|
|
See scm_protect_object for more information. */
|
1996-12-23 04:37:03 +00:00
|
|
|
|
SCM
|
2001-05-26 22:10:58 +00:00
|
|
|
|
scm_gc_unprotect_object (SCM obj)
|
1996-12-23 04:37:03 +00:00
|
|
|
|
{
|
2000-05-21 20:49:20 +00:00
|
|
|
|
SCM handle;
|
2000-07-15 13:44:04 +00:00
|
|
|
|
|
2000-05-21 20:49:20 +00:00
|
|
|
|
/* This critical section barrier will be replaced by a mutex. */
|
2005-03-30 22:11:07 +00:00
|
|
|
|
/* njrev: and again. */
|
2005-03-02 20:42:01 +00:00
|
|
|
|
SCM_CRITICAL_SECTION_START;
|
2000-07-15 13:44:04 +00:00
|
|
|
|
|
2004-09-24 09:23:44 +00:00
|
|
|
|
if (scm_gc_running_p)
|
|
|
|
|
|
{
|
|
|
|
|
|
fprintf (stderr, "scm_unprotect_object called during GC.\n");
|
|
|
|
|
|
abort ();
|
|
|
|
|
|
}
|
2005-03-10 18:39:53 +00:00
|
|
|
|
|
2010-02-13 19:33:51 +01:00
|
|
|
|
handle = scm_hashq_get_handle (scm_protects, obj);
|
2000-07-15 13:44:04 +00:00
|
|
|
|
|
2004-07-06 10:59:25 +00:00
|
|
|
|
if (scm_is_false (handle))
|
2000-05-21 20:49:20 +00:00
|
|
|
|
{
|
2000-06-14 15:00:52 +00:00
|
|
|
|
fprintf (stderr, "scm_unprotect_object called on unprotected object\n");
|
|
|
|
|
|
abort ();
|
2000-05-21 20:49:20 +00:00
|
|
|
|
}
|
2000-06-15 08:35:42 +00:00
|
|
|
|
else
|
|
|
|
|
|
{
|
2004-07-23 15:43:02 +00:00
|
|
|
|
SCM count = scm_difference (SCM_CDR (handle), scm_from_int (1));
|
2004-07-27 15:41:49 +00:00
|
|
|
|
if (scm_is_eq (count, scm_from_int (0)))
|
2010-02-13 19:33:51 +01:00
|
|
|
|
scm_hashq_remove_x (scm_protects, obj);
|
2000-06-15 08:35:42 +00:00
|
|
|
|
else
|
* validate.h
(SCM_NUM2{SIZE,PTRDIFF,SHORT,USHORT,BITS,UBITS,INT,UINT}[_DEF]):
new macros.
* unif.h: type renaming:
scm_array -> scm_array_t
scm_array_dim -> scm_array_dim_t
the old names are deprecated, all in-Guile uses changed.
* tags.h (scm_ubits_t): new typedef, representing unsigned
scm_bits_t.
* stacks.h: type renaming:
scm_info_frame -> scm_info_frame_t
scm_stack -> scm_stack_t
the old names are deprecated, all in-Guile uses changed.
* srcprop.h: type renaming:
scm_srcprops -> scm_srcprops_t
scm_srcprops_chunk -> scm_srcprops_chunk_t
the old names are deprecated, all in-Guile uses changed.
* gsubr.c, procs.c, print.c, ports.c, read.c, rdelim.c, ramap.c,
rw.c, smob.c, sort.c, srcprop.c, stacks.c, strings.c, strop.c,
strorder.c, strports.c, struct.c, symbols.c, unif.c, values.c,
vectors.c, vports.c, weaks.c:
various int/size_t -> size_t/scm_bits_t changes.
* random.h: type renaming:
scm_rstate -> scm_rstate_t
scm_rng -> scm_rng_t
scm_i_rstate -> scm_i_rstate_t
the old names are deprecated, all in-Guile uses changed.
* procs.h: type renaming:
scm_subr_entry -> scm_subr_entry_t
the old name is deprecated, all in-Guile uses changed.
* options.h (scm_option_t.val): unsigned long -> scm_bits_t.
type renaming:
scm_option -> scm_option_t
the old name is deprecated, all in-Guile uses changed.
* objects.c: various long -> scm_bits_t changes.
(scm_i_make_class_object): flags: unsigned long -> scm_ubits_t
* numbers.h (SCM_FIXNUM_BIT): deprecated, renamed to
SCM_I_FIXNUM_BIT.
* num2integral.i.c: new file, multiply included by numbers.c, used
to "templatize" the various integral <-> num conversion routines.
* numbers.c (scm_mkbig, scm_big2num, scm_adjbig, scm_normbig,
scm_copybig, scm_2ulong2big, scm_dbl2big, scm_big2dbl):
deprecated.
(scm_i_mkbig, scm_i_big2inum, scm_i_adjbig, scm_i_normbig,
scm_i_copybig, scm_i_short2big, scm_i_ushort2big, scm_i_int2big,
scm_i_uint2big, scm_i_long2big, scm_i_ulong2big, scm_i_bits2big,
scm_i_ubits2big, scm_i_size2big, scm_i_ptrdiff2big,
scm_i_long_long2big, scm_i_ulong_long2big, scm_i_dbl2big,
scm_i_big2dbl, scm_short2num, scm_ushort2num, scm_int2num,
scm_uint2num, scm_bits2num, scm_ubits2num, scm_size2num,
scm_ptrdiff2num, scm_num2short, scm_num2ushort, scm_num2int,
scm_num2uint, scm_num2bits, scm_num2ubits, scm_num2ptrdiff,
scm_num2size): new functions.
* modules.c (scm_module_reverse_lookup): i, n: int -> scm_bits_t.x
* load.c: change int -> size_t in various places (where the
variable is used to store a string length).
(search-path): call scm_done_free, not scm_done_malloc.
* list.c (scm_ilength): return a scm_bits_t, not long.
some other {int,long} -> scm_bits_t changes.
* hashtab.c: various [u]int -> scm_bits_t changes.
scm_ihashx_closure -> scm_ihashx_closure_t (and made a typedef).
(scm_ihashx): n: uint -> scm_bits_t
use scm_bits2num instead of scm_ulong2num.
* gsubr.c: various int -> scm_bits_t changes.
* gh_data.c (gh_scm2double): no loss of precision any more.
* gh.h (gh_str2scm): len: int -> size_t
(gh_{get,set}_substr): start: int -> scm_bits_t,
len: int -> size_t
(gh_<num>2scm): n: int -> scm_bits_t
(gh_*vector_length): return scm_[u]size_t, not unsigned long.
(gh_length): return scm_bits_t, not unsigned long.
* fports.h: type renaming:
scm_fport -> scm_fport_t
the old name is deprecated, all in-Guile uses changed.
* fports.c (fport_fill_input): count: int -> scm_bits_t
(fport_flush): init_size, remaining, count: int -> scm_bits_t
* debug.h (scm_lookup_cstr, scm_lookup_soft, scm_evstr): removed
those prototypes, as the functions they prototype don't exist.
* fports.c (default_buffer_size): int -> size_t
(scm_fport_buffer_add): read_size, write_size: int -> scm_bits_t
default_size: int -> size_t
(scm_setvbuf): csize: int -> scm_bits_t
* fluids.c (n_fluids): int -> scm_bits_t
(grow_fluids): old_length, i: int -> scm_bits_t
(next_fluid_num, scm_fluid_ref, scm_fluid_set_x): n: int ->
scm_bits_t
(scm_c_with_fluids): flen, vlen: int -> scm_bits_t
* filesys.c (s_scm_open_fdes): changed calls to SCM_NUM2LONG to
the new and shiny SCM_NUM2INT.
* extensions.c: extension -> extension_t (and made a typedef).
* eval.h (SCM_IFRAME): cast to scm_bits_t, not int. just so
there are no nasty surprises if/when the various deeply magic tag
bits move somewhere else.
* eval.c: changed the locals used to store results of SCM_IFRAME,
scm_ilength and such to be of type scm_bits_t (and not int/long).
(iqq): depth, edepth: int -> scm_bits_t
(scm_eval_stack): int -> scm_bits_t
(SCM_CEVAL): various vars are not scm_bits_t instead of int.
(check_map_args, scm_map, scm_for_each): len: long -> scm_bits_t
i: int -> scm_bits_t
* environments.c: changed the many calls to scm_ulong2num to
scm_ubits2num.
(import_environment_fold): proc_as_ul: ulong -> scm_ubits_t
* dynwind.c (scm_dowinds): delta: long -> scm_bits_t
* debug.h: type renaming:
scm_debug_info -> scm_debug_info_t
scm_debug_frame -> scm_debug_frame_t
the old names are deprecated, all in-Guile uses changed.
(scm_debug_eframe_size): int -> scm_bits_t
* debug.c (scm_init_debug): use scm_c_define instead of the
deprecated scm_define.
* continuations.h: type renaming:
scm_contregs -> scm_contregs_t
the old name is deprecated, all in-Guile uses changed.
(scm_contregs_t.num_stack_items): size_t -> scm_bits_t
(scm_contregs_t.num_stack_items): ulong -> scm_ubits_t
* continuations.c (scm_make_continuation): change the type of
stack_size form long to scm_bits_t.
* ports.h: type renaming:
scm_port_rw_active -> scm_port_rw_active_t (and made a typedef)
scm_port -> scm_port_t
scm_ptob_descriptor -> scm_ptob_descriptor_t
the old names are deprecated, all in-Guile uses changed.
(scm_port_t.entry): int -> scm_bits_t.
(scm_port_t.line_number): int -> long.
(scm_port_t.putback_buf_size): int -> size_t.
* __scm.h (long_long, ulong_long): deprecated (they pollute the
global namespace and have little value besides that).
(SCM_BITS_LENGTH): new, is the bit size of scm_bits_t (i.e. of an
SCM handle).
(ifdef spaghetti): include sys/types.h and sys/stdtypes.h, if they
exist (for size_t & ptrdiff_t)
(scm_sizet): deprecated.
* Makefile.am (noinst_HEADERS): add num2integral.i.c
2001-05-24 00:50:51 +00:00
|
|
|
|
SCM_SETCDR (handle, count);
|
2000-06-15 08:35:42 +00:00
|
|
|
|
}
|
2004-01-21 00:06:11 +00:00
|
|
|
|
protected_obj_count --;
|
2000-05-21 20:49:20 +00:00
|
|
|
|
|
2005-03-02 20:42:01 +00:00
|
|
|
|
SCM_CRITICAL_SECTION_END;
|
1996-12-23 04:37:03 +00:00
|
|
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2001-05-26 22:10:58 +00:00
|
|
|
|
void
|
|
|
|
|
|
scm_gc_register_root (SCM *p)
|
|
|
|
|
|
{
|
2006-11-27 00:16:27 +00:00
|
|
|
|
/* Nothing. */
|
2001-05-26 22:10:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
scm_gc_unregister_root (SCM *p)
|
|
|
|
|
|
{
|
2006-11-27 00:16:27 +00:00
|
|
|
|
/* Nothing. */
|
2001-05-26 22:10:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
scm_gc_register_roots (SCM *b, unsigned long n)
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM *p = b;
|
|
|
|
|
|
for (; p < b + n; ++p)
|
|
|
|
|
|
scm_gc_register_root (p);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
scm_gc_unregister_roots (SCM *b, unsigned long n)
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM *p = b;
|
|
|
|
|
|
for (; p < b + n; ++p)
|
|
|
|
|
|
scm_gc_unregister_root (p);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
* __scm.h eq.c, eval.c, gc.c, hc.h, gh_data, hash.c, numbers.c,
numbers.h, objects.c, ramap.c, random.c, unif.c, unif.h: Extensive
rewrite of handling of real and complex numbers.
(SCM_FLOATS, SCM_SINGLES): These #ifdef conditionals have been
removed along with the support for floats. (Float vectors are
still supported.)
* gc.c (scm_freelist2): multi-cell freelists.
(inner_map_free_list): map_free_list, parameterized on ncells.
"nn cells in segment mm" was misleading for ncells > 1; changed to
"objects". still print cells too, though.
(scm_map_free_list): rewritten using inner_map_free_list.
(scm_check_freelist): get freelist as parameter, since now we have
more than one.
(scm_debug_newcell2): multi-cell variants of
scm_debug_newcell.
(scm_gc_for_newcell): take ncells and freelist pointer as
parameters.
(scm_gc_mark): add case for tc7_pws (procedures with setters are
now double cells).
(scm_gc_sweep): don't free the float data, since it's not malloced
anymore.
(init_heap_seg): didn't understand what n_new_objects stood for,
so changed to n_new_cells.
(make_initial_segment): new function, makes an initial segment
according to given ncells.
(scm_init_storage): call make_initial_segment, for ncells={1,2,3}.
2000-03-14 06:40:09 +00:00
|
|
|
|
|
2000-03-18 11:09:41 +00:00
|
|
|
|
|
2000-03-17 08:09:14 +00:00
|
|
|
|
|
2002-08-04 00:17:18 +00:00
|
|
|
|
/*
|
|
|
|
|
|
MOVE THIS FUNCTION. IT DOES NOT HAVE ANYTHING TODO WITH GC.
|
|
|
|
|
|
*/
|
2000-12-11 14:48:23 +00:00
|
|
|
|
|
|
|
|
|
|
/* Get an integer from an environment variable. */
|
2002-08-04 00:17:18 +00:00
|
|
|
|
int
|
|
|
|
|
|
scm_getenv_int (const char *var, int def)
|
2000-12-11 14:48:23 +00:00
|
|
|
|
{
|
2002-08-04 00:17:18 +00:00
|
|
|
|
char *end = 0;
|
|
|
|
|
|
char *val = getenv (var);
|
|
|
|
|
|
long res = def;
|
2000-12-11 14:48:23 +00:00
|
|
|
|
if (!val)
|
|
|
|
|
|
return def;
|
|
|
|
|
|
res = strtol (val, &end, 10);
|
|
|
|
|
|
if (end == val)
|
|
|
|
|
|
return def;
|
|
|
|
|
|
return res;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-03-08 23:50:41 +01:00
|
|
|
|
#ifndef HAVE_GC_SET_FINALIZE_ON_DEMAND
|
|
|
|
|
|
static void
|
|
|
|
|
|
GC_set_finalize_on_demand (int foo)
|
|
|
|
|
|
{
|
|
|
|
|
|
GC_finalize_on_demand = foo;
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
* hooks.c (scm_c_hook_add): Fixed bug in append mode.
* environments.c (obarray_enter, obarray_retrieve, obarray_remove,
leaf_environment_fold, obarray_remove_all): Use hashtable
accessors.
* gc.c (scm_init_storage): Moved hook initialization to
scm_storage_prehistory.
(scm_storage_prehistory): New function.
(scm_igc): Added commentary about placement of
scm_after_sweep_c_hook.
* gc-mark.c (scm_mark_all): Use hashtable accessors.
(scm_gc_mark_dependencies): Use SCM_WVECT_WEAK_KEY_P and
SCM_WVECT_WEAK_VALUE_P.
* hashtab.c, hashtab.h (scm_hash_for_each, scm_hash_map): New
functions.
(scm_vector_to_hash_table, scm_c_make_resizing_hash_table):
Removed.
(scm_make_weak_key_hash_table, scm_make_weak_value_hash_table,
scm_make_doubly_weak_hash_table): Moved here from weaks.c.
* init.c (scm_init_guile_1): Removed call to scm_init_weaks; Added
calls to scm_storage_prehistory and scm_hashtab_prehistory.
* modules.c (module-reverse-lookup): Use hashtable accessors.
* symbols.c, symbols.h (scm_i_hash_symbol): New function.
* weaks.c, weaks.h (scm_make_weak_key_alist_vector,
scm_make_weak_value_alist_vector,
scm_make_doubly_weak_alist_vector): New functions.
* weaks.c (scm_init_weaks_builtins): New function.
* weaks.h (SCM_WVECTF_WEAK_KEY, SCM_WVECTF_WEAK_VALUE,
SCM_WVECTF_NOSCAN, SCM_WVECT_WEAK_KEY_P, SCM_WVECT_WEAK_VALUE_P,
SCM_WVECT_NOSCAN_P): New macros.
* weaks.c (scm_scan_weak_vectors): Use SCM_WVECT_WEAK_KEY_P
and SCM_WVECT_WEAK_VALUE_P.
* weaks.c, weaks.h (scm_i_allocate_weak_vector): Renamed from
allocate_weak_vector and exported.
* Makefile.am (ice9_sources): Added weak-vector.scm.
* weak-vector.scm: New file.
* boot-9.scm (module-clear!): Use hash-clear!.
(module-for-each): Use hash-for-each.
(module-map): Use hash-map.
2003-02-19 15:04:51 +00:00
|
|
|
|
void
|
|
|
|
|
|
scm_storage_prehistory ()
|
|
|
|
|
|
{
|
2013-03-01 17:36:21 +01:00
|
|
|
|
#ifdef HAVE_GC_SET_ALL_INTERIOR_POINTERS
|
|
|
|
|
|
/* This function was added in 7.2alpha2 (June 2009). */
|
|
|
|
|
|
GC_set_all_interior_pointers (0);
|
|
|
|
|
|
#else
|
|
|
|
|
|
/* This symbol is deprecated in 7.3. */
|
2006-11-27 00:14:23 +00:00
|
|
|
|
GC_all_interior_pointers = 0;
|
2013-03-01 17:36:21 +01:00
|
|
|
|
#endif
|
|
|
|
|
|
|
2011-11-29 00:48:56 +01:00
|
|
|
|
free_space_divisor = scm_getenv_int ("GC_FREE_SPACE_DIVISOR", 3);
|
|
|
|
|
|
minimum_free_space_divisor = free_space_divisor;
|
|
|
|
|
|
target_free_space_divisor = free_space_divisor;
|
|
|
|
|
|
GC_set_free_space_divisor (free_space_divisor);
|
2012-02-24 13:18:48 +01:00
|
|
|
|
GC_set_finalize_on_demand (1);
|
2006-11-27 00:14:23 +00:00
|
|
|
|
|
2006-04-04 21:27:48 +00:00
|
|
|
|
GC_INIT ();
|
2006-12-03 21:59:02 +00:00
|
|
|
|
|
2008-09-15 22:57:24 +02:00
|
|
|
|
#if (! ((defined GC_VERSION_MAJOR) && (GC_VERSION_MAJOR >= 7))) \
|
|
|
|
|
|
&& (defined SCM_I_GSC_USE_PTHREAD_THREADS)
|
2006-12-03 21:59:02 +00:00
|
|
|
|
/* When using GC 6.8, this call is required to initialize thread-local
|
|
|
|
|
|
freelists (shouldn't be necessary with GC 7.0). */
|
|
|
|
|
|
GC_init ();
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
2006-11-27 00:15:53 +00:00
|
|
|
|
GC_expand_hp (SCM_DEFAULT_INIT_HEAP_SIZE_2);
|
2006-07-02 20:26:29 +00:00
|
|
|
|
|
2006-11-27 00:14:23 +00:00
|
|
|
|
/* We only need to register a displacement for those types for which the
|
|
|
|
|
|
higher bits of the type tag are used to store a pointer (that is, a
|
|
|
|
|
|
pointer to an 8-octet aligned region). For `scm_tc3_struct', this is
|
|
|
|
|
|
handled in `scm_alloc_struct ()'. */
|
|
|
|
|
|
GC_REGISTER_DISPLACEMENT (scm_tc3_cons);
|
eval.c closures are now applicable smobs, not tc3s
* libguile/debug.c (scm_procedure_name): Remove a SCM_CLOSUREP case and
some dead code.
(scm_procedure_module): Remove. This was introduced a few months ago
for the hygienic expander, but now it is no longer needed, as the
expander keeps track of this information itself.
* libguile/debug.h: Remove scm_procedure_module.
* libguile/eval.c: Instead of using tc3 closures, define a "boot
closure" applicable smob type, and represent closures with that. The
advantage is that after eval.scm is compiled, boot closures take up no
address space (besides a smob number) in the runtime, and require no
special cases in procedure dispatch.
* libguile/eval.h: Remove the internal functions scm_i_call_closure_0
and scm_closure_apply, and the public function scm_closure.
* libguile/gc.c (scm_storage_prehistory): No tc3_closure displacement
registration.
(scm_i_tag_name): Remove closure case, and a dead cclo case.
* libguile/vm.c (apply_foreign):
* libguile/print.c (iprin1):
* libguile/procs.c (scm_procedure_p, scm_procedure_documentation);
* libguile/evalext.c (scm_self_evaluating_p):
* libguile/goops.c (scm_class_of): Remove tc3_closure/tcs_closure cases.
* libguile/hash.c (scm_hasher):
* libguile/hooks.c (scm_add_hook_x): Use new scm_i_procedure_arity.
* libguile/macros.c (macro_print): Print all macros using the same code.
(scm_macro_transformer): Return any procedure, not just programs.
* libguile/procprop.h:
* libguile/procprop.c (scm_i_procedure_arity): Instead of returning a
list that the caller has to parse, have the same prototype as
scm_i_program_arity. An incompatible change, but it's an internal
function anyway.
(scm_procedure_properties, scm_set_procedure_properties)
(scm_procedure_property, scm_set_procedure_property): Remove closure
cases, and use scm_i_program_arity for arity.
* libguile/procs.h (SCM_CLOSUREP, SCM_CLOSCAR, SCM_CODE)
(SCM_CLOSURE_NUM_REQUIRED_ARGS, SCM_CLOSURE_HAS_REST_ARGS)
(SCM_CLOSURE_BODY, SCM_PROCPROPS, SCM_SETPROCPROPS, SCM_ENV)
(SCM_TOP_LEVEL): Remove these macros that pertain to boot closures
only. Only eval.c should know abut boot closures.
* libguile/procs.c (scm_closure_p): Remove this function. There is a
simple stub in deprecated.scm now.
(scm_thunk_p): Use scm_i_program_arity.
* libguile/tags.h (scm_tc3_closure): Remove. Yay, another tc3 to play
with!
(scm_tcs_closures): Remove.
* libguile/validate.h (SCM_VALIDATE_CLOSURE): Remove.
* module/ice-9/deprecated.scm (closure?): Add stub.
* module/ice-9/documentation.scm (object-documentation)
* module/ice-9/session.scm (help-doc, arity)
* module/oop/goops.scm (compute-getters-n-setters)
* module/oop/goops/describe.scm (describe)
* module/system/repl/describe.scm (display-object, display-type):
Remove calls to closure?.
2009-12-04 19:20:11 +01:00
|
|
|
|
/* GC_REGISTER_DISPLACEMENT (scm_tc3_unused); */
|
2006-11-27 00:14:23 +00:00
|
|
|
|
|
2006-07-02 20:26:29 +00:00
|
|
|
|
/* Sanity check. */
|
2010-02-13 19:33:51 +01:00
|
|
|
|
if (!GC_is_visible (&scm_protects))
|
2006-07-02 20:26:29 +00:00
|
|
|
|
abort ();
|
2006-04-04 21:27:48 +00:00
|
|
|
|
|
* hooks.c (scm_c_hook_add): Fixed bug in append mode.
* environments.c (obarray_enter, obarray_retrieve, obarray_remove,
leaf_environment_fold, obarray_remove_all): Use hashtable
accessors.
* gc.c (scm_init_storage): Moved hook initialization to
scm_storage_prehistory.
(scm_storage_prehistory): New function.
(scm_igc): Added commentary about placement of
scm_after_sweep_c_hook.
* gc-mark.c (scm_mark_all): Use hashtable accessors.
(scm_gc_mark_dependencies): Use SCM_WVECT_WEAK_KEY_P and
SCM_WVECT_WEAK_VALUE_P.
* hashtab.c, hashtab.h (scm_hash_for_each, scm_hash_map): New
functions.
(scm_vector_to_hash_table, scm_c_make_resizing_hash_table):
Removed.
(scm_make_weak_key_hash_table, scm_make_weak_value_hash_table,
scm_make_doubly_weak_hash_table): Moved here from weaks.c.
* init.c (scm_init_guile_1): Removed call to scm_init_weaks; Added
calls to scm_storage_prehistory and scm_hashtab_prehistory.
* modules.c (module-reverse-lookup): Use hashtable accessors.
* symbols.c, symbols.h (scm_i_hash_symbol): New function.
* weaks.c, weaks.h (scm_make_weak_key_alist_vector,
scm_make_weak_value_alist_vector,
scm_make_doubly_weak_alist_vector): New functions.
* weaks.c (scm_init_weaks_builtins): New function.
* weaks.h (SCM_WVECTF_WEAK_KEY, SCM_WVECTF_WEAK_VALUE,
SCM_WVECTF_NOSCAN, SCM_WVECT_WEAK_KEY_P, SCM_WVECT_WEAK_VALUE_P,
SCM_WVECT_NOSCAN_P): New macros.
* weaks.c (scm_scan_weak_vectors): Use SCM_WVECT_WEAK_KEY_P
and SCM_WVECT_WEAK_VALUE_P.
* weaks.c, weaks.h (scm_i_allocate_weak_vector): Renamed from
allocate_weak_vector and exported.
* Makefile.am (ice9_sources): Added weak-vector.scm.
* weak-vector.scm: New file.
* boot-9.scm (module-clear!): Use hash-clear!.
(module-for-each): Use hash-for-each.
(module-map): Use hash-map.
2003-02-19 15:04:51 +00:00
|
|
|
|
scm_c_hook_init (&scm_before_gc_c_hook, 0, SCM_C_HOOK_NORMAL);
|
|
|
|
|
|
scm_c_hook_init (&scm_before_mark_c_hook, 0, SCM_C_HOOK_NORMAL);
|
|
|
|
|
|
scm_c_hook_init (&scm_before_sweep_c_hook, 0, SCM_C_HOOK_NORMAL);
|
|
|
|
|
|
scm_c_hook_init (&scm_after_sweep_c_hook, 0, SCM_C_HOOK_NORMAL);
|
|
|
|
|
|
scm_c_hook_init (&scm_after_gc_c_hook, 0, SCM_C_HOOK_NORMAL);
|
|
|
|
|
|
}
|
2000-12-11 14:48:23 +00:00
|
|
|
|
|
2005-03-02 20:42:01 +00:00
|
|
|
|
scm_i_pthread_mutex_t scm_i_gc_admin_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER;
|
2004-08-19 16:48:38 +00:00
|
|
|
|
|
2009-12-05 11:43:20 +01:00
|
|
|
|
void
|
|
|
|
|
|
scm_init_gc_protect_object ()
|
1996-07-25 22:56:11 +00:00
|
|
|
|
{
|
2010-02-13 19:33:51 +01:00
|
|
|
|
scm_protects = scm_c_make_hash_table (31);
|
2000-03-15 07:30:53 +00:00
|
|
|
|
|
2005-03-02 20:42:01 +00:00
|
|
|
|
#if 0
|
|
|
|
|
|
/* We can't have a cleanup handler since we have no thread to run it
|
|
|
|
|
|
in. */
|
|
|
|
|
|
|
1999-08-30 02:13:45 +00:00
|
|
|
|
#ifdef HAVE_ATEXIT
|
1999-06-09 12:18:40 +00:00
|
|
|
|
atexit (cleanup);
|
1999-09-02 14:51:51 +00:00
|
|
|
|
#else
|
|
|
|
|
|
#ifdef HAVE_ON_EXIT
|
|
|
|
|
|
on_exit (cleanup, 0);
|
|
|
|
|
|
#endif
|
2005-03-02 20:42:01 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
1999-08-30 02:13:45 +00:00
|
|
|
|
#endif
|
1996-07-25 22:56:11 +00:00
|
|
|
|
}
|
2000-06-28 10:26:52 +00:00
|
|
|
|
|
1996-07-25 22:56:11 +00:00
|
|
|
|
|
|
|
|
|
|
|
2000-06-28 10:26:52 +00:00
|
|
|
|
SCM scm_after_gc_hook;
|
|
|
|
|
|
|
2011-04-15 17:45:52 +02:00
|
|
|
|
static SCM after_gc_async_cell;
|
2000-06-28 10:26:52 +00:00
|
|
|
|
|
2011-04-15 17:45:52 +02:00
|
|
|
|
/* The function after_gc_async_thunk causes the execution of the
|
|
|
|
|
|
* after-gc-hook. It is run after the gc, as soon as the asynchronous
|
|
|
|
|
|
* events are handled by the evaluator.
|
2000-06-28 10:26:52 +00:00
|
|
|
|
*/
|
|
|
|
|
|
static SCM
|
2011-04-15 17:45:52 +02:00
|
|
|
|
after_gc_async_thunk (void)
|
2000-06-28 10:26:52 +00:00
|
|
|
|
{
|
2011-04-15 17:45:52 +02:00
|
|
|
|
/* Fun, no? Hook-run *and* run-hook? */
|
|
|
|
|
|
scm_c_hook_run (&scm_after_gc_c_hook, NULL);
|
2000-06-28 10:26:52 +00:00
|
|
|
|
scm_c_run_hook (scm_after_gc_hook, SCM_EOL);
|
|
|
|
|
|
return SCM_UNSPECIFIED;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-04-15 17:45:52 +02:00
|
|
|
|
/* The function queue_after_gc_hook is run by the scm_before_gc_c_hook
|
|
|
|
|
|
* at the end of the garbage collection. The only purpose of this
|
|
|
|
|
|
* function is to mark the after_gc_async (which will eventually lead to
|
|
|
|
|
|
* the execution of the after_gc_async_thunk).
|
2000-06-28 10:26:52 +00:00
|
|
|
|
*/
|
|
|
|
|
|
static void *
|
2011-04-15 17:45:52 +02:00
|
|
|
|
queue_after_gc_hook (void * hook_data SCM_UNUSED,
|
|
|
|
|
|
void *fn_data SCM_UNUSED,
|
|
|
|
|
|
void *data SCM_UNUSED)
|
2001-06-07 21:12:19 +00:00
|
|
|
|
{
|
|
|
|
|
|
/* If cell access debugging is enabled, the user may choose to perform
|
|
|
|
|
|
* 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.
|
2001-08-17 23:45:29 +00:00
|
|
|
|
*
|
2001-06-07 21:12:19 +00:00
|
|
|
|
* 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.
|
|
|
|
|
|
*/
|
2005-03-02 20:42:01 +00:00
|
|
|
|
|
2001-06-07 21:12:19 +00:00
|
|
|
|
#if (SCM_DEBUG_CELL_ACCESSES == 1)
|
2002-08-08 19:47:31 +00:00
|
|
|
|
if (scm_debug_cells_gc_interval == 0)
|
2001-06-07 21:12:19 +00:00
|
|
|
|
#endif
|
2011-04-15 17:45:52 +02:00
|
|
|
|
{
|
|
|
|
|
|
scm_i_thread *t = SCM_I_CURRENT_THREAD;
|
|
|
|
|
|
|
|
|
|
|
|
if (scm_is_false (SCM_CDR (after_gc_async_cell)))
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM_SETCDR (after_gc_async_cell, t->active_asyncs);
|
|
|
|
|
|
t->active_asyncs = after_gc_async_cell;
|
|
|
|
|
|
t->pending_asyncs = 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2001-06-07 21:12:19 +00:00
|
|
|
|
|
2000-06-28 10:26:52 +00:00
|
|
|
|
return NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2011-05-04 18:48:02 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void *
|
|
|
|
|
|
start_gc_timer (void * hook_data SCM_UNUSED,
|
|
|
|
|
|
void *fn_data SCM_UNUSED,
|
|
|
|
|
|
void *data SCM_UNUSED)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!gc_start_time)
|
|
|
|
|
|
gc_start_time = scm_c_get_internal_run_time ();
|
|
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void *
|
|
|
|
|
|
accumulate_gc_timer (void * hook_data SCM_UNUSED,
|
|
|
|
|
|
void *fn_data SCM_UNUSED,
|
|
|
|
|
|
void *data SCM_UNUSED)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (gc_start_time)
|
2011-11-29 00:48:56 +01:00
|
|
|
|
{
|
|
|
|
|
|
long now = scm_c_get_internal_run_time ();
|
2011-05-04 18:48:02 +02:00
|
|
|
|
gc_time_taken += now - gc_start_time;
|
|
|
|
|
|
gc_start_time = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2011-11-29 00:48:56 +01:00
|
|
|
|
/* Return some idea of the memory footprint of a process, in bytes.
|
|
|
|
|
|
Currently only works on Linux systems. */
|
|
|
|
|
|
static size_t
|
|
|
|
|
|
get_image_size (void)
|
|
|
|
|
|
{
|
|
|
|
|
|
unsigned long size, resident, share;
|
2011-11-29 13:43:52 +01:00
|
|
|
|
size_t ret = 0;
|
2011-11-29 00:48:56 +01:00
|
|
|
|
|
|
|
|
|
|
FILE *fp = fopen ("/proc/self/statm", "r");
|
|
|
|
|
|
|
|
|
|
|
|
if (fp && fscanf (fp, "%lu %lu %lu", &size, &resident, &share) == 3)
|
|
|
|
|
|
ret = resident * 4096;
|
|
|
|
|
|
|
|
|
|
|
|
if (fp)
|
|
|
|
|
|
fclose (fp);
|
|
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2011-11-29 21:36:31 +01:00
|
|
|
|
/* These are discussed later. */
|
|
|
|
|
|
static size_t bytes_until_gc;
|
|
|
|
|
|
static scm_i_pthread_mutex_t bytes_until_gc_lock = SCM_I_PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
|
|
|
2011-11-29 00:48:56 +01:00
|
|
|
|
/* Make GC run more frequently when the process image size is growing,
|
|
|
|
|
|
measured against the number of bytes allocated through the GC.
|
|
|
|
|
|
|
|
|
|
|
|
If Guile is allocating at a GC-managed heap size H, libgc will tend
|
|
|
|
|
|
to limit the process image size to H*N. But if at the same time the
|
|
|
|
|
|
user program is mallocating at a rate M bytes per GC-allocated byte,
|
|
|
|
|
|
then the process stabilizes at H*N*M -- assuming that collecting data
|
|
|
|
|
|
will result in malloc'd data being freed. It doesn't take a very
|
|
|
|
|
|
large M for this to be a bad situation. To limit the image size,
|
|
|
|
|
|
Guile should GC more often -- the bigger the M, the more often.
|
|
|
|
|
|
|
|
|
|
|
|
Numeric functions that produce bigger and bigger integers are
|
|
|
|
|
|
pessimal, because M is an increasing function of time. Here is an
|
|
|
|
|
|
example of such a function:
|
|
|
|
|
|
|
|
|
|
|
|
(define (factorial n)
|
|
|
|
|
|
(define (fac n acc)
|
|
|
|
|
|
(if (<= n 1)
|
|
|
|
|
|
acc
|
|
|
|
|
|
(fac (1- n) (* n acc))))
|
|
|
|
|
|
(fac n 1))
|
|
|
|
|
|
|
|
|
|
|
|
It is possible for a process to grow for reasons that will not be
|
|
|
|
|
|
solved by faster GC. In that case M will be estimated as
|
|
|
|
|
|
artificially high for a while, and so GC will happen more often on
|
|
|
|
|
|
the Guile side. But when it stabilizes, Guile can ease back the GC
|
|
|
|
|
|
frequency.
|
|
|
|
|
|
|
|
|
|
|
|
The key is to measure process image growth, not mallocation rate.
|
|
|
|
|
|
For maximum effectiveness, Guile reacts quickly to process growth,
|
|
|
|
|
|
and exponentially backs down when the process stops growing.
|
|
|
|
|
|
|
|
|
|
|
|
See http://thread.gmane.org/gmane.lisp.guile.devel/12552/focus=12936
|
|
|
|
|
|
for further discussion.
|
|
|
|
|
|
*/
|
|
|
|
|
|
static void *
|
|
|
|
|
|
adjust_gc_frequency (void * hook_data SCM_UNUSED,
|
|
|
|
|
|
void *fn_data SCM_UNUSED,
|
|
|
|
|
|
void *data SCM_UNUSED)
|
|
|
|
|
|
{
|
|
|
|
|
|
static size_t prev_image_size = 0;
|
|
|
|
|
|
static size_t prev_bytes_alloced = 0;
|
|
|
|
|
|
size_t image_size;
|
|
|
|
|
|
size_t bytes_alloced;
|
|
|
|
|
|
|
2011-11-29 21:36:31 +01:00
|
|
|
|
scm_i_pthread_mutex_lock (&bytes_until_gc_lock);
|
|
|
|
|
|
bytes_until_gc = GC_get_heap_size ();
|
|
|
|
|
|
scm_i_pthread_mutex_unlock (&bytes_until_gc_lock);
|
|
|
|
|
|
|
2011-11-29 00:48:56 +01:00
|
|
|
|
image_size = get_image_size ();
|
|
|
|
|
|
bytes_alloced = GC_get_total_bytes ();
|
|
|
|
|
|
|
2011-11-29 10:17:07 +01:00
|
|
|
|
#define HEURISTICS_DEBUG 0
|
2011-11-29 00:48:56 +01:00
|
|
|
|
|
|
|
|
|
|
#if HEURISTICS_DEBUG
|
|
|
|
|
|
fprintf (stderr, "prev image / alloced: %lu / %lu\n", prev_image_size, prev_bytes_alloced);
|
|
|
|
|
|
fprintf (stderr, " image / alloced: %lu / %lu\n", image_size, bytes_alloced);
|
|
|
|
|
|
fprintf (stderr, "divisor %lu / %f\n", free_space_divisor, target_free_space_divisor);
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
if (prev_image_size && bytes_alloced != prev_bytes_alloced)
|
|
|
|
|
|
{
|
|
|
|
|
|
double growth_rate, new_target_free_space_divisor;
|
|
|
|
|
|
double decay_factor = 0.5;
|
|
|
|
|
|
double hysteresis = 0.1;
|
|
|
|
|
|
|
|
|
|
|
|
growth_rate = ((double) image_size - prev_image_size)
|
|
|
|
|
|
/ ((double)bytes_alloced - prev_bytes_alloced);
|
|
|
|
|
|
|
|
|
|
|
|
#if HEURISTICS_DEBUG
|
|
|
|
|
|
fprintf (stderr, "growth rate %f\n", growth_rate);
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
new_target_free_space_divisor = minimum_free_space_divisor;
|
|
|
|
|
|
|
|
|
|
|
|
if (growth_rate > 0)
|
|
|
|
|
|
new_target_free_space_divisor *= 1.0 + growth_rate;
|
|
|
|
|
|
|
|
|
|
|
|
#if HEURISTICS_DEBUG
|
|
|
|
|
|
fprintf (stderr, "new divisor %f\n", new_target_free_space_divisor);
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
if (new_target_free_space_divisor < target_free_space_divisor)
|
|
|
|
|
|
/* Decay down. */
|
|
|
|
|
|
target_free_space_divisor =
|
|
|
|
|
|
(decay_factor * target_free_space_divisor
|
|
|
|
|
|
+ (1.0 - decay_factor) * new_target_free_space_divisor);
|
|
|
|
|
|
else
|
|
|
|
|
|
/* Jump up. */
|
|
|
|
|
|
target_free_space_divisor = new_target_free_space_divisor;
|
|
|
|
|
|
|
|
|
|
|
|
#if HEURISTICS_DEBUG
|
|
|
|
|
|
fprintf (stderr, "new target divisor %f\n", target_free_space_divisor);
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
if (free_space_divisor + 0.5 + hysteresis < target_free_space_divisor
|
|
|
|
|
|
|| free_space_divisor - 0.5 - hysteresis > target_free_space_divisor)
|
|
|
|
|
|
{
|
|
|
|
|
|
free_space_divisor = lround (target_free_space_divisor);
|
|
|
|
|
|
#if HEURISTICS_DEBUG
|
|
|
|
|
|
fprintf (stderr, "new divisor %lu\n", free_space_divisor);
|
|
|
|
|
|
#endif
|
|
|
|
|
|
GC_set_free_space_divisor (free_space_divisor);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
prev_image_size = image_size;
|
|
|
|
|
|
prev_bytes_alloced = bytes_alloced;
|
|
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2011-11-29 21:36:31 +01:00
|
|
|
|
/* The adjust_gc_frequency routine handles transients in the process
|
|
|
|
|
|
image size. It can't handle instense non-GC-managed steady-state
|
|
|
|
|
|
allocation though, as it decays the FSD at steady-state down to its
|
|
|
|
|
|
minimum value.
|
|
|
|
|
|
|
|
|
|
|
|
The only real way to handle continuous, high non-GC allocation is to
|
|
|
|
|
|
let the GC know about it. This routine can handle non-GC allocation
|
|
|
|
|
|
rates that are similar in size to the GC-managed heap size.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
scm_gc_register_allocation (size_t size)
|
|
|
|
|
|
{
|
|
|
|
|
|
scm_i_pthread_mutex_lock (&bytes_until_gc_lock);
|
|
|
|
|
|
if (bytes_until_gc - size > bytes_until_gc)
|
|
|
|
|
|
{
|
|
|
|
|
|
bytes_until_gc = GC_get_heap_size ();
|
|
|
|
|
|
scm_i_pthread_mutex_unlock (&bytes_until_gc_lock);
|
|
|
|
|
|
GC_gcollect ();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
bytes_until_gc -= size;
|
|
|
|
|
|
scm_i_pthread_mutex_unlock (&bytes_until_gc_lock);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2011-05-04 18:48:02 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-03-21 22:16:33 +00:00
|
|
|
|
char const *
|
|
|
|
|
|
scm_i_tag_name (scm_t_bits tag)
|
|
|
|
|
|
{
|
2011-07-28 17:47:31 +02:00
|
|
|
|
switch (tag & 0x7f) /* 7 bits */
|
2006-03-21 22:16:33 +00:00
|
|
|
|
{
|
|
|
|
|
|
case scm_tcs_struct:
|
|
|
|
|
|
return "struct";
|
|
|
|
|
|
case scm_tcs_cons_imcar:
|
|
|
|
|
|
return "cons (immediate car)";
|
|
|
|
|
|
case scm_tcs_cons_nimcar:
|
|
|
|
|
|
return "cons (non-immediate car)";
|
Use "pointer" instead of "foreign" when dealing with wrapped pointers.
* libguile/foreign.h (scm_t_foreign_finalizer): Rename to...
(scm_t_pointer_finalizer): ... this.
(SCM_FOREIGN_P): Rename to...
(SCM_POINTER_P): this.
(SCM_VALIDATE_FOREIGN): Rename to...
(SCM_VALIDATE_POINTER): ... this.
(SCM_FOREIGN_HAS_FINALIZER): Rename to...
(SCM_POINTER_HAS_FINALIZER): ... this.
(scm_take_foreign_pointer): Rename to...
(scm_from_pointer): ... this.
(scm_foreign_address): Rename to...
(scm_pointer_address): ... this.
(scm_foreign_to_bytevector): Rename to...
(scm_pointer_to_bytevector): ... this.
(scm_foreign_set_finalizer_x): Rename to...
(scm_set_pointer_finalizer_x): ... this.
(scm_bytevector_to_foreign): Rename to...
(scm_bytevector_to_pointer): ... this.
(scm_i_foreign_print): Rename to...
(scm_i_pointer_print): ... this.
* libguile/foreign.c: Update accordingly.
* libguile/tags.h (scm_tc7_foreign): Rename to...
(scm_tc7_pointer): ... this.
* libguile/foreign.c, libguile/deprecated.c, libguile/dynl.c,
libguile/evalext.c, libguile/gc.c, libguile/goops.c, libguile/gsubr.c,
libguile/gsubr.h, libguile/print.c, libguile/snarf.h,
libguile/vm-i-system.c, module/system/foreign.scm,
test-suite/standalone/test-ffi, test-suite/tests/foreign.test: Update
accordingly.
2010-07-27 14:54:53 +02:00
|
|
|
|
case scm_tc7_pointer:
|
2010-01-04 12:11:33 +01:00
|
|
|
|
return "foreign";
|
2009-12-05 10:07:07 +01:00
|
|
|
|
case scm_tc7_hashtable:
|
|
|
|
|
|
return "hashtable";
|
fluids are tc7 objects
If you're wondering what I'm doing, I'm trying to eventually reimplement
smobs in terms of structs, so that applicable smobs can just follow the
applicable struct dispatch path. But to do that I have to get structs
initialized before things that use smobs, which means transforming a
bunch of smobby things to tc7 things. But this transformation is good
for performance anyway, and we currently have a glut of unused tc7s,
so here we go...
* libguile/tags.h (scm_tc7_fluid, scm_tc7_dynamic_state): Fluids (and
dynamic states) now have tc7s.
* libguile/fluids.h: Remove scm_fluids_prehistory, and add internal
scm_i_fluid_print. Update a comment.
* libguile/fluids.c: Update for tc7 representation. Also remove the next
pointers while we're at it, as they aren't used in the new BDW GC.
* libguile/eq.c (scm_equal_p): Remove the hashtable case. Hashtables
could never be equal? before, I don't see why to add stubs doing the
same thing now.
* libguile/print.c (iprin1):
* libguile/gc.c (scm_i_tag_name):
* libguile/evalext.c (scm_self_evaluating_p): Add fluid and
dynamic_state cases.
* libguile/goops.h: Remove scm_class_hashtable; it will be static.
* libguile/goops.c: Make <hashtable> static, and add <fluid> and
<dynamic-state> classes.
* libguile/hashtab.h:
* libguile/hashtab.c: Remove scm_i_hashtable_equal_p.
* libguile/init.c (scm_i_init_guile): Remove call to fluids_prehistory.
2009-12-05 10:52:18 +01:00
|
|
|
|
case scm_tc7_fluid:
|
|
|
|
|
|
return "fluid";
|
|
|
|
|
|
case scm_tc7_dynamic_state:
|
|
|
|
|
|
return "dynamic state";
|
2010-01-05 19:45:56 +01:00
|
|
|
|
case scm_tc7_frame:
|
|
|
|
|
|
return "frame";
|
|
|
|
|
|
case scm_tc7_objcode:
|
|
|
|
|
|
return "objcode";
|
|
|
|
|
|
case scm_tc7_vm:
|
|
|
|
|
|
return "vm";
|
|
|
|
|
|
case scm_tc7_vm_cont:
|
|
|
|
|
|
return "vm continuation";
|
2006-03-21 22:16:33 +00:00
|
|
|
|
case scm_tc7_wvect:
|
|
|
|
|
|
return "weak vector";
|
|
|
|
|
|
case scm_tc7_vector:
|
|
|
|
|
|
return "vector";
|
|
|
|
|
|
case scm_tc7_number:
|
|
|
|
|
|
switch (tag)
|
|
|
|
|
|
{
|
|
|
|
|
|
case scm_tc16_real:
|
|
|
|
|
|
return "real";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case scm_tc16_big:
|
|
|
|
|
|
return "bignum";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case scm_tc16_complex:
|
|
|
|
|
|
return "complex number";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case scm_tc16_fraction:
|
|
|
|
|
|
return "fraction";
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case scm_tc7_string:
|
|
|
|
|
|
return "string";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case scm_tc7_stringbuf:
|
|
|
|
|
|
return "string buffer";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case scm_tc7_symbol:
|
|
|
|
|
|
return "symbol";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case scm_tc7_variable:
|
|
|
|
|
|
return "variable";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case scm_tc7_port:
|
|
|
|
|
|
return "port";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case scm_tc7_smob:
|
2011-07-28 17:47:31 +02:00
|
|
|
|
{
|
|
|
|
|
|
int k = 0xff & (tag >> 8);
|
|
|
|
|
|
return (scm_smobs[k].name);
|
|
|
|
|
|
}
|
2006-03-21 22:16:33 +00:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1996-07-25 22:56:11 +00:00
|
|
|
|
void
|
|
|
|
|
|
scm_init_gc ()
|
|
|
|
|
|
{
|
2006-04-04 21:27:48 +00:00
|
|
|
|
/* `GC_INIT ()' was invoked in `scm_storage_prehistory ()'. */
|
2001-11-25 15:00:31 +00:00
|
|
|
|
|
2009-12-05 11:30:09 +01:00
|
|
|
|
scm_after_gc_hook = scm_make_hook (SCM_INUM0);
|
2001-05-28 14:18:35 +00:00
|
|
|
|
scm_c_define ("after-gc-hook", scm_after_gc_hook);
|
2000-06-28 10:26:52 +00:00
|
|
|
|
|
2011-04-15 17:45:52 +02:00
|
|
|
|
/* When the async is to run, the cdr of the gc_async pair gets set to
|
|
|
|
|
|
the asyncs queue of the current thread. */
|
|
|
|
|
|
after_gc_async_cell = scm_cons (scm_c_make_gsubr ("%after-gc-thunk", 0, 0, 0,
|
|
|
|
|
|
after_gc_async_thunk),
|
|
|
|
|
|
SCM_BOOL_F);
|
2000-06-28 10:26:52 +00:00
|
|
|
|
|
2011-04-15 17:45:52 +02:00
|
|
|
|
scm_c_hook_add (&scm_before_gc_c_hook, queue_after_gc_hook, NULL, 0);
|
2011-05-04 18:48:02 +02:00
|
|
|
|
scm_c_hook_add (&scm_before_gc_c_hook, start_gc_timer, NULL, 0);
|
|
|
|
|
|
scm_c_hook_add (&scm_after_gc_c_hook, accumulate_gc_timer, NULL, 0);
|
2011-04-15 18:31:06 +02:00
|
|
|
|
|
2011-12-01 12:57:49 +01:00
|
|
|
|
#if HAVE_GC_GET_HEAP_USAGE_SAFE
|
|
|
|
|
|
/* GC_get_heap_usage does not take a lock, and so can run in the GC
|
|
|
|
|
|
start hook. */
|
|
|
|
|
|
scm_c_hook_add (&scm_before_gc_c_hook, adjust_gc_frequency, NULL, 0);
|
|
|
|
|
|
#else
|
|
|
|
|
|
/* GC_get_heap_usage might take a lock (and did from 7.2alpha1 to
|
|
|
|
|
|
7.2alpha7), so call it in the after_gc_hook. */
|
|
|
|
|
|
scm_c_hook_add (&scm_after_gc_c_hook, adjust_gc_frequency, NULL, 0);
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
2011-04-15 18:31:06 +02:00
|
|
|
|
#ifdef HAVE_GC_SET_START_CALLBACK
|
2011-04-15 17:45:52 +02:00
|
|
|
|
GC_set_start_callback (run_before_gc_c_hook);
|
2011-04-15 18:31:06 +02:00
|
|
|
|
#endif
|
2000-06-28 10:26:52 +00:00
|
|
|
|
|
2000-04-21 14:16:44 +00:00
|
|
|
|
#include "libguile/gc.x"
|
1996-07-25 22:56:11 +00:00
|
|
|
|
}
|
2000-03-19 19:01:16 +00:00
|
|
|
|
|
2002-08-04 00:17:18 +00:00
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
scm_gc_sweep (void)
|
|
|
|
|
|
#define FUNC_NAME "scm_gc_sweep"
|
|
|
|
|
|
{
|
2006-03-21 22:16:33 +00:00
|
|
|
|
/* FIXME */
|
2009-12-14 15:21:54 +01:00
|
|
|
|
fprintf (stderr, "%s: doing nothing\n", FUNC_NAME);
|
2002-08-04 00:17:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
#undef FUNC_NAME
|
|
|
|
|
|
|
2000-03-19 19:01:16 +00:00
|
|
|
|
/*
|
|
|
|
|
|
Local Variables:
|
|
|
|
|
|
c-file-style: "gnu"
|
|
|
|
|
|
End:
|
|
|
|
|
|
*/
|