mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 03:40:34 +02:00
Struct vtables store bitmask of unboxed fields
* libguile/struct.h (scm_vtable_index_unboxed_fields): Allocate slot for bitmask of which fields are unboxed. (SCM_VTABLE_FLAG_SIMPLE, SCM_VTABLE_FLAG_SIMPLE_RW): Remove flags. Renumber other flags. (SCM_VTABLE_SIZE, SCM_STRUCT_SIZE): New helpers; long overdue. (SCM_VTABLE_UNBOXED_FIELDS, SCM_VTABLE_FIELD_IS_UNBOXED): (SCM_STRUCT_FIELD_IS_UNBOXED): New macros. * libguile/struct.c (set_vtable_access_fields): Rename from set_vtable_layout_flags, and initialize the unboxed flags bitmask instead of computing vtable flags. (scm_struct_init, scm_c_make_structv, scm_allocate_struct): Simplify. (scm_i_make_vtable_vtable): Adapt. (scm_i_struct_equalp, scm_struct_ref, scm_struct_set_x) (scm_struct_ref_unboxed, scm_struct_set_x_unboxed): Simplify. * libguile/vm-engine.c (VM_VALIDATE_BOXED_STRUCT_FIELD): (VM_VALIDATE_UNBOXED_STRUCT_FIELD): Adapt definitions. (struct-ref, struct-set!, struct-ref/immediate) (struct-set!/immediate): Simplify definitions. * libguile/hash.c (scm_i_struct_hash): Simplify. * libguile/goops.c (scm_sys_clear_fields_x): Simplify. * libguile/foreign-object.c (scm_make_foreign_object_n): (scm_foreign_object_unsigned_ref, scm_foreign_object_unsigned_set_x): Simplify.
This commit is contained in:
parent
f32500acca
commit
214e887dbd
6 changed files with 112 additions and 226 deletions
|
@ -120,50 +120,35 @@ SCM_DEFINE (scm_make_struct_layout, "make-struct-layout", 1, 0, 0,
|
|||
#undef FUNC_NAME
|
||||
|
||||
|
||||
/* Check whether VTABLE instances have a simple layout (i.e., either
|
||||
only "pr" or only "pw" fields) and update its flags accordingly. */
|
||||
static void
|
||||
set_vtable_layout_flags (SCM vtable)
|
||||
set_vtable_access_fields (SCM vtable)
|
||||
{
|
||||
size_t len, field;
|
||||
size_t len, nfields, bitmask_size, field;
|
||||
SCM layout;
|
||||
const char *c_layout;
|
||||
scm_t_bits flags = SCM_VTABLE_FLAG_SIMPLE;
|
||||
scm_t_uint32 *unboxed_fields;
|
||||
|
||||
layout = SCM_VTABLE_LAYOUT (vtable);
|
||||
c_layout = scm_i_symbol_chars (layout);
|
||||
len = scm_i_symbol_length (layout);
|
||||
|
||||
assert (len % 2 == 0);
|
||||
nfields = len / 2;
|
||||
|
||||
bitmask_size = (nfields + 31U) / 32U;
|
||||
unboxed_fields = scm_gc_malloc_pointerless (bitmask_size, "unboxed fields");
|
||||
memset (unboxed_fields, 0, bitmask_size * sizeof(*unboxed_fields));
|
||||
|
||||
/* Update FLAGS according to LAYOUT. */
|
||||
for (field = 0;
|
||||
field < len && flags & SCM_VTABLE_FLAG_SIMPLE;
|
||||
field += 2)
|
||||
{
|
||||
if (c_layout[field] != 'p')
|
||||
flags = 0;
|
||||
else
|
||||
switch (c_layout[field + 1])
|
||||
{
|
||||
case 'w':
|
||||
case 'h':
|
||||
if (field == 0)
|
||||
flags |= SCM_VTABLE_FLAG_SIMPLE_RW;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
flags &= ~SCM_VTABLE_FLAG_SIMPLE_RW;
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
for (field = 0; field < nfields; field++)
|
||||
if (c_layout[field*2] == 'u')
|
||||
unboxed_fields[field/32U] |= 1U << (field%32U);
|
||||
|
||||
/* Record computed size of vtable's instances. */
|
||||
SCM_SET_VTABLE_FLAGS (vtable, flags);
|
||||
SCM_SET_VTABLE_FLAGS (vtable, 0);
|
||||
SCM_STRUCT_DATA_SET (vtable, scm_vtable_index_size, len / 2);
|
||||
SCM_STRUCT_DATA_SET (vtable, scm_vtable_index_unboxed_fields,
|
||||
(scm_t_uintptr) unboxed_fields);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -224,7 +209,7 @@ scm_i_struct_inherit_vtable_magic (SCM vtable, SCM obj)
|
|||
SCM_MISC_ERROR ("invalid layout for new vtable: ~a",
|
||||
scm_list_1 (SCM_VTABLE_LAYOUT (obj)));
|
||||
|
||||
set_vtable_layout_flags (obj);
|
||||
set_vtable_access_fields (obj);
|
||||
|
||||
/* If OBJ's vtable is compatible with the required vtable (class) layout, it
|
||||
is a metaclass. */
|
||||
|
@ -271,56 +256,27 @@ scm_i_struct_inherit_vtable_magic (SCM vtable, SCM obj)
|
|||
static void
|
||||
scm_struct_init (SCM handle, SCM layout, size_t n_inits, scm_t_bits *inits)
|
||||
{
|
||||
SCM vtable;
|
||||
scm_t_bits *mem;
|
||||
size_t n_fields;
|
||||
size_t n, n_fields, inits_idx = 0;
|
||||
|
||||
vtable = SCM_STRUCT_VTABLE (handle);
|
||||
n_fields = SCM_STRUCT_DATA_REF (vtable, scm_vtable_index_size);
|
||||
mem = SCM_STRUCT_DATA (handle);
|
||||
n_fields = SCM_STRUCT_SIZE (handle);
|
||||
|
||||
if (SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_SIMPLE)
|
||||
&& n_inits == n_fields)
|
||||
/* The fast path: HANDLE has N_INITS "p" fields. */
|
||||
memcpy (mem, inits, n_inits * sizeof (SCM));
|
||||
else
|
||||
for (n = 0; n < n_fields; n++)
|
||||
{
|
||||
scm_t_wchar prot = 0;
|
||||
int i;
|
||||
size_t inits_idx = 0;
|
||||
|
||||
i = -2;
|
||||
while (n_fields)
|
||||
{
|
||||
i += 2;
|
||||
prot = scm_i_symbol_ref (layout, i+1);
|
||||
switch (scm_i_symbol_ref (layout, i))
|
||||
{
|
||||
case 'u':
|
||||
if (prot == 'h' || inits_idx == n_inits)
|
||||
*mem = 0;
|
||||
else
|
||||
{
|
||||
*mem = scm_to_ulong (SCM_PACK (inits[inits_idx]));
|
||||
inits_idx++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (prot == 'h' || inits_idx == n_inits)
|
||||
*mem = SCM_UNPACK (SCM_BOOL_F);
|
||||
else
|
||||
{
|
||||
*mem = inits[inits_idx];
|
||||
inits_idx++;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
n_fields--;
|
||||
mem++;
|
||||
}
|
||||
if (inits_idx == n_inits || scm_i_symbol_ref (layout, n*2+1) == 'h')
|
||||
{
|
||||
if (SCM_STRUCT_FIELD_IS_UNBOXED (handle, n))
|
||||
SCM_STRUCT_DATA_SET (handle, n, 0);
|
||||
else
|
||||
SCM_STRUCT_SLOT_SET (handle, n, SCM_BOOL_F);
|
||||
}
|
||||
else
|
||||
{
|
||||
SCM_STRUCT_DATA_SET (handle, n,
|
||||
SCM_STRUCT_FIELD_IS_UNBOXED (handle, n)
|
||||
? scm_to_uintptr_t (SCM_PACK (inits[inits_idx]))
|
||||
: inits[inits_idx]);
|
||||
inits_idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -384,19 +340,17 @@ SCM
|
|||
scm_c_make_structv (SCM vtable, size_t n_tail, size_t n_init, scm_t_bits *init)
|
||||
#define FUNC_NAME "make-struct"
|
||||
{
|
||||
SCM layout;
|
||||
size_t basic_size;
|
||||
SCM obj;
|
||||
|
||||
SCM_VALIDATE_VTABLE (1, vtable);
|
||||
|
||||
layout = SCM_VTABLE_LAYOUT (vtable);
|
||||
basic_size = scm_i_symbol_length (layout) / 2;
|
||||
basic_size = SCM_VTABLE_SIZE (vtable);
|
||||
|
||||
SCM_ASSERT (n_tail == 0, scm_from_size_t (n_tail), 2, FUNC_NAME);
|
||||
|
||||
obj = scm_i_alloc_struct (SCM_UNPACK (vtable), basic_size);
|
||||
scm_struct_init (obj, layout, n_init, init);
|
||||
scm_struct_init (obj, SCM_VTABLE_LAYOUT (vtable), n_init, init);
|
||||
|
||||
/* If we're making a vtable, validate its layout and inherit
|
||||
flags. However we allow for separation of allocation and
|
||||
|
@ -450,19 +404,10 @@ SCM_DEFINE (scm_allocate_struct, "allocate-struct", 2, 0, 0,
|
|||
SCM_VALIDATE_VTABLE (1, vtable);
|
||||
c_nfields = scm_to_size_t (nfields);
|
||||
|
||||
SCM_ASSERT (SCM_STRUCT_DATA_REF (vtable, scm_vtable_index_size) == c_nfields,
|
||||
nfields, 2, FUNC_NAME);
|
||||
SCM_ASSERT (SCM_VTABLE_SIZE (vtable) == c_nfields, nfields, 2, FUNC_NAME);
|
||||
|
||||
ret = scm_i_alloc_struct (SCM_UNPACK (vtable), c_nfields);
|
||||
|
||||
if (SCM_LIKELY (SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_SIMPLE)))
|
||||
{
|
||||
size_t n;
|
||||
for (n = 0; n < c_nfields; n++)
|
||||
SCM_STRUCT_DATA_SET (ret, n, SCM_UNPACK (SCM_BOOL_F));
|
||||
}
|
||||
else
|
||||
scm_struct_init (ret, SCM_VTABLE_LAYOUT (vtable), 0, NULL);
|
||||
scm_struct_init (ret, SCM_VTABLE_LAYOUT (vtable), 0, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -526,19 +471,18 @@ scm_i_make_vtable_vtable (SCM fields)
|
|||
SCM_SET_CELL_WORD_0 (obj, SCM_UNPACK (obj) | scm_tc3_struct);
|
||||
/* Manually initialize fields. */
|
||||
SCM_STRUCT_SLOT_SET (obj, scm_vtable_index_layout, layout);
|
||||
SCM_STRUCT_DATA_SET (obj, scm_vtable_index_flags,
|
||||
SCM_VTABLE_FLAG_VTABLE | SCM_VTABLE_FLAG_VALIDATED);
|
||||
set_vtable_access_fields (obj);
|
||||
SCM_SET_VTABLE_FLAGS (obj, SCM_VTABLE_FLAG_VTABLE | SCM_VTABLE_FLAG_VALIDATED);
|
||||
SCM_STRUCT_DATA_SET (obj, scm_vtable_index_instance_finalize, 0);
|
||||
SCM_STRUCT_SLOT_SET (obj, scm_vtable_index_instance_printer, SCM_BOOL_F);
|
||||
SCM_STRUCT_SLOT_SET (obj, scm_vtable_index_name, SCM_BOOL_F);
|
||||
SCM_STRUCT_DATA_SET (obj, scm_vtable_index_size, nfields);
|
||||
SCM_STRUCT_DATA_SET (obj, scm_vtable_index_reserved_7, 0);
|
||||
|
||||
for (n = scm_vtable_offset_user; n < nfields; n++)
|
||||
if (scm_i_symbol_ref (layout, n*2) == 'p')
|
||||
SCM_STRUCT_SLOT_SET (obj, n, SCM_BOOL_F);
|
||||
else
|
||||
if (SCM_STRUCT_FIELD_IS_UNBOXED (obj, n))
|
||||
SCM_STRUCT_DATA_SET (obj, n, 0);
|
||||
else
|
||||
SCM_STRUCT_SLOT_SET (obj, n, SCM_BOOL_F);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
@ -570,20 +514,15 @@ SCM
|
|||
scm_i_struct_equalp (SCM s1, SCM s2)
|
||||
#define FUNC_NAME "scm_i_struct_equalp"
|
||||
{
|
||||
SCM vtable1, vtable2, layout;
|
||||
size_t struct_size, field_num;
|
||||
|
||||
SCM_VALIDATE_STRUCT (1, s1);
|
||||
SCM_VALIDATE_STRUCT (2, s2);
|
||||
|
||||
vtable1 = SCM_STRUCT_VTABLE (s1);
|
||||
vtable2 = SCM_STRUCT_VTABLE (s2);
|
||||
|
||||
if (!scm_is_eq (vtable1, vtable2))
|
||||
if (!scm_is_eq (SCM_STRUCT_VTABLE (s1), SCM_STRUCT_VTABLE (s2)))
|
||||
return SCM_BOOL_F;
|
||||
|
||||
layout = SCM_STRUCT_LAYOUT (s1);
|
||||
struct_size = scm_i_symbol_length (layout) / 2;
|
||||
struct_size = SCM_STRUCT_SIZE (s1);
|
||||
|
||||
for (field_num = 0; field_num < struct_size; field_num++)
|
||||
{
|
||||
|
@ -593,7 +532,7 @@ scm_i_struct_equalp (SCM s1, SCM s2)
|
|||
field2 = SCM_STRUCT_DATA_REF (s2, field_num);
|
||||
|
||||
if (field1 != field2) {
|
||||
if (scm_i_symbol_ref (layout, field_num * 2) == 'u')
|
||||
if (SCM_STRUCT_FIELD_IS_UNBOXED (s1, field_num))
|
||||
return SCM_BOOL_F;
|
||||
|
||||
/* Having a normal field point to the object itself is a bit
|
||||
|
@ -629,20 +568,16 @@ SCM_DEFINE (scm_struct_ref, "struct-ref", 2, 0, 0,
|
|||
"word.")
|
||||
#define FUNC_NAME s_scm_struct_ref
|
||||
{
|
||||
SCM vtable, layout;
|
||||
size_t nfields, p;
|
||||
|
||||
SCM_VALIDATE_STRUCT (1, handle);
|
||||
|
||||
vtable = SCM_STRUCT_VTABLE (handle);
|
||||
layout = SCM_VTABLE_LAYOUT (vtable);
|
||||
nfields = SCM_STRUCT_DATA_REF (vtable, scm_vtable_index_size);
|
||||
nfields = SCM_STRUCT_SIZE (handle);
|
||||
p = scm_to_size_t (pos);
|
||||
|
||||
SCM_ASSERT_RANGE (2, pos, p < nfields);
|
||||
|
||||
/* Only 'p' fields. */
|
||||
SCM_ASSERT (scm_i_symbol_ref (layout, p * 2) == 'p', layout, 0, FUNC_NAME);
|
||||
SCM_ASSERT (!SCM_STRUCT_FIELD_IS_UNBOXED (handle, p), pos, 2, FUNC_NAME);
|
||||
|
||||
return SCM_STRUCT_SLOT_REF (handle, p);
|
||||
}
|
||||
|
@ -656,20 +591,16 @@ SCM_DEFINE (scm_struct_set_x, "struct-set!", 3, 0, 0,
|
|||
"to.")
|
||||
#define FUNC_NAME s_scm_struct_set_x
|
||||
{
|
||||
SCM vtable, layout;
|
||||
size_t nfields, p;
|
||||
|
||||
SCM_VALIDATE_STRUCT (1, handle);
|
||||
|
||||
vtable = SCM_STRUCT_VTABLE (handle);
|
||||
layout = SCM_VTABLE_LAYOUT (vtable);
|
||||
nfields = SCM_STRUCT_DATA_REF (vtable, scm_vtable_index_size);
|
||||
nfields = SCM_STRUCT_SIZE (handle);
|
||||
p = scm_to_size_t (pos);
|
||||
|
||||
SCM_ASSERT_RANGE (2, pos, p < nfields);
|
||||
|
||||
/* Only 'p' fields. */
|
||||
SCM_ASSERT (scm_i_symbol_ref (layout, p * 2) == 'p', layout, 0, FUNC_NAME);
|
||||
SCM_ASSERT (!SCM_STRUCT_FIELD_IS_UNBOXED (handle, p), pos, 2, FUNC_NAME);
|
||||
|
||||
SCM_STRUCT_SLOT_SET (handle, p, val);
|
||||
|
||||
|
@ -684,20 +615,16 @@ SCM_DEFINE (scm_struct_ref_unboxed, "struct-ref/unboxed", 2, 0, 0,
|
|||
"@var{handle}. The field must be of type 'u'.")
|
||||
#define FUNC_NAME s_scm_struct_ref_unboxed
|
||||
{
|
||||
SCM vtable, layout;
|
||||
size_t nfields, p;
|
||||
|
||||
SCM_VALIDATE_STRUCT (1, handle);
|
||||
|
||||
vtable = SCM_STRUCT_VTABLE (handle);
|
||||
layout = SCM_VTABLE_LAYOUT (vtable);
|
||||
nfields = SCM_STRUCT_DATA_REF (vtable, scm_vtable_index_size);
|
||||
nfields = SCM_STRUCT_SIZE (handle);
|
||||
p = scm_to_size_t (pos);
|
||||
|
||||
SCM_ASSERT_RANGE (2, pos, p < nfields);
|
||||
|
||||
/* Only 'u' fields. */
|
||||
SCM_ASSERT (scm_i_symbol_ref (layout, p * 2) == 'u', layout, 0, FUNC_NAME);
|
||||
SCM_ASSERT (SCM_STRUCT_FIELD_IS_UNBOXED (handle, p), pos, 2, FUNC_NAME);
|
||||
|
||||
return scm_from_uintptr_t (SCM_STRUCT_DATA_REF (handle, p));
|
||||
}
|
||||
|
@ -711,20 +638,16 @@ SCM_DEFINE (scm_struct_set_x_unboxed, "struct-set!/unboxed", 3, 0, 0,
|
|||
"to.")
|
||||
#define FUNC_NAME s_scm_struct_set_x_unboxed
|
||||
{
|
||||
SCM vtable, layout;
|
||||
size_t nfields, p;
|
||||
|
||||
SCM_VALIDATE_STRUCT (1, handle);
|
||||
|
||||
vtable = SCM_STRUCT_VTABLE (handle);
|
||||
layout = SCM_VTABLE_LAYOUT (vtable);
|
||||
nfields = SCM_STRUCT_DATA_REF (vtable, scm_vtable_index_size);
|
||||
nfields = SCM_STRUCT_SIZE (handle);
|
||||
p = scm_to_size_t (pos);
|
||||
|
||||
SCM_ASSERT_RANGE (2, pos, p < nfields);
|
||||
|
||||
/* Only 'u' fields. */
|
||||
SCM_ASSERT (scm_i_symbol_ref (layout, p * 2) == 'u', layout, 0, FUNC_NAME);
|
||||
SCM_ASSERT (SCM_STRUCT_FIELD_IS_UNBOXED (handle, p), pos, 2, FUNC_NAME);
|
||||
|
||||
SCM_STRUCT_DATA_SET (handle, p, scm_to_uintptr_t (val));
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue