From 14d1400fa7d6388302c3e313ba95526559d11d15 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Tue, 15 Oct 1996 00:10:59 +0000 Subject: 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. --- libguile/gc.c | 14 ++++----- libguile/struct.c | 86 +++++++++++++++++++++++++++++++++++++++++-------------- libguile/struct.h | 3 +- 3 files changed, 74 insertions(+), 29 deletions(-) diff --git a/libguile/gc.c b/libguile/gc.c index 069517023..c6d065d12 100644 --- a/libguile/gc.c +++ b/libguile/gc.c @@ -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; diff --git a/libguile/struct.c b/libguile/struct.c index 9ed0e0033..854bf8ae5 100644 --- a/libguile/struct.c +++ b/libguile/struct.c @@ -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; diff --git a/libguile/struct.h b/libguile/struct.h index 1b2b44924..e076a8aee 100644 --- a/libguile/struct.h +++ b/libguile/struct.h @@ -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. */ -- cgit v1.2.3