diff options
author | Jim Blandy <jimb@red-bean.com> | 1996-10-15 00:10:59 +0000 |
---|---|---|
committer | Jim Blandy <jimb@red-bean.com> | 1996-10-15 00:10:59 +0000 |
commit | 14d1400fa7d6388302c3e313ba95526559d11d15 (patch) | |
tree | c38d2f58708938521665c1d63c5ba26ed623334e /libguile/struct.c | |
parent | 2dfc85c018817322c19faa36457ad23fa98fcc89 (diff) | |
download | guile-14d1400fa7d6388302c3e313ba95526559d11d15.tar.gz |
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.
Diffstat (limited to 'libguile/struct.c')
-rw-r--r-- | libguile/struct.c | 86 |
1 files changed, 65 insertions, 21 deletions
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; |