mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-16 16:50:21 +02:00
Allocate data for structures on an eight-byte boundary, as
required by the tagging system. * struct.c (alloc_struct): New function. (scm_make_struct, scm_make_vtable_vtable): Call it. * struct.h (scm_struct_n_extra_words): Bump to 3. (scm_struct_i_ptr): New "field". * gc.c (scm_gc_sweep): When we need to free the data, use the information stored by alloc_struct to find the beginning of the block allocated to the structure, so we can free it.
This commit is contained in:
parent
2dfc85c018
commit
14d1400fa7
3 changed files with 74 additions and 29 deletions
|
@ -516,7 +516,9 @@ gc_mark_nimp:
|
|||
layout = vtable_data[scm_struct_i_layout];
|
||||
len = SCM_LENGTH (layout);
|
||||
fields_desc = SCM_CHARS (layout);
|
||||
mem = (SCM *)SCM_GCCDR (ptr); /* like struct_data but removes mark */
|
||||
/* We're using SCM_GCCDR here like STRUCT_DATA, except
|
||||
that it removes the mark */
|
||||
mem = (SCM *)SCM_GCCDR (ptr);
|
||||
|
||||
if (len)
|
||||
{
|
||||
|
@ -959,12 +961,10 @@ scm_gc_sweep ()
|
|||
|
||||
if ((SCM_CDR (vcell) == 0) || (SCM_CDR (vcell) == 1))
|
||||
{
|
||||
SCM * mem;
|
||||
SCM amt;
|
||||
mem = (SCM *)SCM_CDR (scmptr);
|
||||
amt = mem[- scm_struct_n_extra_words];
|
||||
free (mem - scm_struct_n_extra_words);
|
||||
m += amt * sizeof (SCM);
|
||||
SCM *p = (SCM *) SCM_GCCDR (scmptr);
|
||||
m += p[scm_struct_i_n_words] * sizeof (SCM);
|
||||
/* I feel like I'm programming in BCPL here... */
|
||||
free ((char *) p[scm_struct_i_ptr]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -276,6 +276,65 @@ scm_struct_vtable_p (x)
|
|||
: SCM_BOOL_F);
|
||||
}
|
||||
|
||||
|
||||
/* All struct data must be allocated at an address whose bottom three
|
||||
bits are zero. This is because the tag for a struct lives in the
|
||||
bottom three bits of the struct's car, and the upper bits point to
|
||||
the data of its vtable, which is a struct itself. Thus, if the
|
||||
address of that data doesn't end in three zeros, tagging it will
|
||||
destroy the pointer.
|
||||
|
||||
This function allocates a block of memory, and returns a pointer at
|
||||
least scm_struct_n_extra_words words into the block. Furthermore,
|
||||
it guarantees that that pointer's least three significant bits are
|
||||
all zero.
|
||||
|
||||
The argument n_words should be the number of words that should
|
||||
appear after the returned address. (That is, it shouldn't include
|
||||
scm_struct_n_extra_words.)
|
||||
|
||||
This function initializes the following fields of the struct:
|
||||
|
||||
scm_struct_i_ptr --- the actual stort of the block of memory; the
|
||||
address you should pass to 'free' to dispose of the block.
|
||||
This field allows us to both guarantee that the returned
|
||||
address is divisible by eight, and allow the GC to free the
|
||||
block.
|
||||
|
||||
scm_struct_i_n_words --- the number of words allocated to the
|
||||
block, including the extra fields. This is used by the GC.
|
||||
|
||||
scm_struct_i_tag --- a unique tag assigned to this struct,
|
||||
allocated according to struct_num.
|
||||
|
||||
Ugh. */
|
||||
|
||||
|
||||
static SCM *alloc_struct SCM_P ((int n_words, char *who));
|
||||
|
||||
static SCM *
|
||||
alloc_struct (n_words, who)
|
||||
int n_words;
|
||||
char *who;
|
||||
{
|
||||
int size = sizeof (SCM) * (n_words + scm_struct_n_extra_words) + 7;
|
||||
SCM *block = (SCM *) scm_must_malloc (size, who);
|
||||
|
||||
/* Adjust the pointer to hide the extra words. */
|
||||
SCM *p = block + scm_struct_n_extra_words;
|
||||
|
||||
/* Adjust it even further so it's aligned on an eight-byte boundary. */
|
||||
p = (SCM *) (((SCM) p + 7) & ~7);
|
||||
|
||||
/* Initialize a few fields as described above. */
|
||||
p[scm_struct_i_ptr] = (SCM) block;
|
||||
p[scm_struct_i_n_words] = (SCM) (scm_struct_n_extra_words + n_words);
|
||||
p[scm_struct_i_tag] = struct_num++;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
SCM_PROC (s_make_struct, "make-struct", 2, 0, 1, scm_make_struct);
|
||||
|
||||
SCM
|
||||
|
@ -292,22 +351,15 @@ scm_make_struct (vtable, tail_array_size, init)
|
|||
|
||||
SCM_ASSERT ((SCM_BOOL_F != scm_struct_vtable_p (vtable)),
|
||||
vtable, SCM_ARG1, s_make_struct);
|
||||
SCM_ASSERT (SCM_INUMP (tail_array_size), tail_array_size, SCM_ARG2, s_make_struct);
|
||||
SCM_ASSERT (SCM_INUMP (tail_array_size), tail_array_size, SCM_ARG2,
|
||||
s_make_struct);
|
||||
|
||||
layout = SCM_STRUCT_DATA (vtable)[scm_struct_i_layout];
|
||||
basic_size = SCM_LENGTH (layout) / 2;
|
||||
tail_elts = SCM_INUM (tail_array_size);
|
||||
SCM_NEWCELL (handle);
|
||||
SCM_DEFER_INTS;
|
||||
data = (SCM*)scm_must_malloc (sizeof (SCM) * (scm_struct_n_extra_words
|
||||
+ basic_size
|
||||
+ tail_elts),
|
||||
"structure");
|
||||
data += scm_struct_n_extra_words;
|
||||
data[scm_struct_i_n_words] = (SCM) (scm_struct_n_extra_words
|
||||
+ basic_size
|
||||
+ tail_elts);
|
||||
data[scm_struct_i_tag] = struct_num++;
|
||||
data = alloc_struct (basic_size + tail_elts, "make-struct");
|
||||
SCM_SETCDR (handle, data);
|
||||
SCM_SETCAR (handle, ((SCM)SCM_STRUCT_DATA (vtable)) + scm_tc3_cons_gloc);
|
||||
init_struct (handle, tail_elts, init);
|
||||
|
@ -334,8 +386,8 @@ scm_make_vtable_vtable (extra_fields, tail_array_size, init)
|
|||
|
||||
SCM_ASSERT (SCM_NIMP (extra_fields) && SCM_ROSTRINGP (extra_fields),
|
||||
extra_fields, SCM_ARG1, s_make_vtable_vtable);
|
||||
SCM_ASSERT (SCM_INUMP (tail_array_size), tail_array_size, SCM_ARG3, s_make_vtable_vtable);
|
||||
|
||||
SCM_ASSERT (SCM_INUMP (tail_array_size), tail_array_size, SCM_ARG2,
|
||||
s_make_vtable_vtable);
|
||||
|
||||
fields = scm_string_append (scm_listify (required_vtable_fields,
|
||||
extra_fields,
|
||||
|
@ -345,15 +397,7 @@ scm_make_vtable_vtable (extra_fields, tail_array_size, init)
|
|||
tail_elts = SCM_INUM (tail_array_size);
|
||||
SCM_NEWCELL (handle);
|
||||
SCM_DEFER_INTS;
|
||||
data = (SCM *) scm_must_malloc (sizeof (SCM) * (scm_struct_n_extra_words
|
||||
+ basic_size
|
||||
+ tail_elts),
|
||||
"structure");
|
||||
data += scm_struct_n_extra_words;
|
||||
data[scm_struct_i_n_words] = (SCM) (scm_struct_n_extra_words
|
||||
+ basic_size
|
||||
+ tail_elts);
|
||||
data[scm_struct_i_tag] = struct_num++;
|
||||
data = alloc_struct (basic_size + tail_elts, "make-vtable-vtable");
|
||||
SCM_SETCDR (handle, data);
|
||||
SCM_SETCAR (handle, ((SCM)data) + scm_tc3_cons_gloc);
|
||||
SCM_STRUCT_LAYOUT (handle) = layout;
|
||||
|
|
|
@ -49,9 +49,10 @@
|
|||
|
||||
|
||||
/* Number of words with negative index */
|
||||
#define scm_struct_n_extra_words 2
|
||||
#define scm_struct_n_extra_words 3
|
||||
|
||||
/* These are how the initial words of a vtable are allocated. */
|
||||
#define scm_struct_i_ptr -3 /* start of block (see alloc_struct) */
|
||||
#define scm_struct_i_n_words -2 /* How many words allocated to this struct? */
|
||||
#define scm_struct_i_tag -1 /* A unique tag for this type.. */
|
||||
#define scm_struct_i_layout 0 /* A symbol describing the physical arrangement of this type. */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue