1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-30 03:40:34 +02:00

Remove support for tail arrays and self slots

* libguile/struct.c (scm_make_struct): Remove support for tail arrays
  and self slots.
  (set_vtable_layout_flags): Always initialize the nfields member.
  (scm_is_valid_vtable_layout): Remove support for tail arrays and self
  slots.
  (scm_i_struct_inherit_vtable_magic): No need to issue deprecation
  warning for self slots, as they are no longer supported.
  (scm_struct_init): Remove support for tail arrays and self slots.
  (scm_c_make_structv): Throw an exception if n_tail is not 0.
  (scm_allocate_struct): Adapt to scm_struct_init change.
  (scm_i_make_vtable_vtable): Initialize slots manually, to avoid
  relying on an already-initialized nfields member.
  (scm_struct_ref, scm_struct_set_x): Simplify.
* module/oop/goops.scm: As we now rely on nfields being valid, when
  recalculating slots during boot we need to avoid resetting nfields of
  <class>, even temporarily, as that would prevent any further access to
  <class>!
This commit is contained in:
Andy Wingo 2017-09-22 15:04:36 +02:00
parent 2f9ad7d9bc
commit d354962b68
2 changed files with 82 additions and 204 deletions

View file

@ -51,9 +51,6 @@
/* A needlessly obscure test. */
#define SCM_LAYOUT_TAILP(X) (((X) & 32) == 0) /* R, W or O */
static SCM required_vtable_fields = SCM_BOOL_F;
static SCM required_applicable_fields = SCM_BOOL_F;
static SCM required_applicable_with_setter_fields = SCM_BOOL_F;
@ -99,7 +96,6 @@ SCM_DEFINE (scm_make_struct_layout, "make-struct-layout", 1, 0, 0,
{
case 'u':
case 'p':
case 's':
break;
default:
SCM_MISC_ERROR ("unrecognized field type: ~S",
@ -110,21 +106,9 @@ SCM_DEFINE (scm_make_struct_layout, "make-struct-layout", 1, 0, 0,
{
case 'w':
case 'h':
if (scm_i_string_ref (fields, x) == 's')
SCM_MISC_ERROR ("self fields not writable", SCM_EOL);
case 'r':
case 'o':
break;
case 'R':
case 'W':
case 'O':
if (scm_i_string_ref (fields, x) == 's')
SCM_MISC_ERROR ("self fields not allowed in tail array",
SCM_EOL);
if (x != len - 2)
SCM_MISC_ERROR ("tail array field must be last field in layout",
SCM_EOL);
break;
default:
SCM_MISC_ERROR ("unrecognized ref specification: ~S",
scm_list_1 (SCM_MAKE_CHAR (c)));
@ -139,8 +123,7 @@ SCM_DEFINE (scm_make_struct_layout, "make-struct-layout", 1, 0, 0,
/* Check whether VTABLE instances have a simple layout (i.e., either
only "pr" or only "pw" fields and no tail array) and update its flags
accordingly. */
only "pr" or only "pw" fields) and update its flags accordingly. */
static void
set_vtable_layout_flags (SCM vtable)
{
@ -179,13 +162,9 @@ set_vtable_layout_flags (SCM vtable)
}
}
if (flags & SCM_VTABLE_FLAG_SIMPLE)
{
/* VTABLE is simple so update its flags and record the size of its
instances. */
SCM_SET_VTABLE_FLAGS (vtable, flags);
SCM_STRUCT_DATA_SET (vtable, scm_vtable_index_size, len / 2);
}
/* Record computed size of vtable's instances. */
SCM_SET_VTABLE_FLAGS (vtable, flags);
SCM_STRUCT_DATA_SET (vtable, scm_vtable_index_size, len / 2);
}
static int
@ -205,14 +184,8 @@ scm_is_valid_vtable_layout (SCM layout)
{
case 'u':
case 'p':
case 's':
switch (c_layout[n+1])
{
case 'W':
case 'R':
case 'O':
if (n + 2 != len)
return 0;
case 'w':
case 'h':
case 'r':
@ -228,23 +201,6 @@ scm_is_valid_vtable_layout (SCM layout)
return 1;
}
static void
issue_deprecation_warning_for_self_slots (SCM vtable)
{
SCM olayout;
size_t idx, first_user_slot = 0;
olayout = scm_symbol_to_string (SCM_VTABLE_LAYOUT (vtable));
if (SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_VTABLE))
first_user_slot = scm_vtable_offset_user;
for (idx = first_user_slot * 2; idx < scm_c_string_length (olayout); idx += 2)
if (scm_is_eq (scm_c_string_ref (olayout, idx), SCM_MAKE_CHAR ('s')))
scm_c_issue_deprecation_warning
("Vtables with \"self\" slots are deprecated. Initialize these "
"fields manually.");
}
/* Have OBJ, a newly created vtable, inherit flags from VTABLE. VTABLE is a
vtable-vtable and OBJ is an instance of VTABLE. */
void
@ -304,54 +260,37 @@ scm_i_struct_inherit_vtable_magic (SCM vtable, SCM obj)
SCM_SET_VTABLE_FLAGS (obj, SCM_VTABLE_FLAG_APPLICABLE);
}
issue_deprecation_warning_for_self_slots (obj);
SCM_SET_VTABLE_FLAGS (obj, SCM_VTABLE_FLAG_VALIDATED);
}
#undef FUNC_NAME
static void
scm_struct_init (SCM handle, SCM layout, size_t n_tail,
size_t n_inits, scm_t_bits *inits)
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;
vtable = SCM_STRUCT_VTABLE (handle);
n_fields = SCM_STRUCT_DATA_REF (vtable, scm_vtable_index_size);
mem = SCM_STRUCT_DATA (handle);
if (SCM_UNPACK (vtable) != 0
&& SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_SIMPLE)
&& n_tail == 0
&& n_inits == SCM_STRUCT_DATA_REF (vtable, scm_vtable_index_size))
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
{
scm_t_wchar prot = 0;
int n_fields = scm_i_symbol_length (layout) / 2;
int tailp = 0;
int i;
size_t inits_idx = 0;
i = -2;
while (n_fields)
{
if (!tailp)
{
i += 2;
prot = scm_i_symbol_ref (layout, i+1);
if (SCM_LAYOUT_TAILP (prot))
{
tailp = 1;
prot = prot == 'R' ? 'r' : prot == 'W' ? 'w' : 'o';
*mem++ = (scm_t_bits)n_tail;
n_fields += n_tail - 1;
if (n_fields == 0)
break;
}
}
i += 2;
prot = scm_i_symbol_ref (layout, i+1);
switch (scm_i_symbol_ref (layout, i))
{
case 'u':
@ -374,10 +313,6 @@ scm_struct_init (SCM handle, SCM layout, size_t n_tail,
}
break;
case 's':
*mem = SCM_UNPACK (handle);
break;
}
n_fields--;
@ -455,26 +390,10 @@ scm_c_make_structv (SCM vtable, size_t n_tail, size_t n_init, scm_t_bits *init)
layout = SCM_VTABLE_LAYOUT (vtable);
basic_size = scm_i_symbol_length (layout) / 2;
if (n_tail != 0)
{
SCM layout_str, last_char;
if (basic_size == 0)
{
bad_tail:
SCM_MISC_ERROR ("tail array not allowed unless layout ends R, W, or O", SCM_EOL);
}
SCM_ASSERT (n_tail == 0, scm_from_size_t (n_tail), 2, FUNC_NAME);
layout_str = scm_symbol_to_string (layout);
last_char = scm_string_ref (layout_str,
scm_from_size_t (2 * basic_size - 1));
if (! SCM_LAYOUT_TAILP (SCM_CHAR (last_char)))
goto bad_tail;
}
obj = scm_i_alloc_struct (SCM_UNPACK (vtable), basic_size + n_tail);
scm_struct_init (obj, layout, n_tail, n_init, init);
obj = scm_i_alloc_struct (SCM_UNPACK (vtable), basic_size);
scm_struct_init (obj, layout, n_init, init);
/* If we're making a vtable, validate its layout and inherit
flags. However we allow for separation of allocation and
@ -495,6 +414,8 @@ scm_c_make_struct (SCM vtable, size_t n_tail, size_t n_init, scm_t_bits init, ..
scm_t_bits *v;
size_t i;
SCM_ASSERT (n_tail == 0, scm_from_size_t (n_tail), 2, "scm_c_make_struct");
v = alloca (sizeof (scm_t_bits) * n_init);
va_start (foo, init);
@ -505,7 +426,7 @@ scm_c_make_struct (SCM vtable, size_t n_tail, size_t n_init, scm_t_bits init, ..
}
va_end (foo);
return scm_c_make_structv (vtable, n_tail, n_init, v);
return scm_c_make_structv (vtable, 0, n_init, v);
}
SCM_DEFINE (scm_allocate_struct, "allocate-struct", 2, 0, 0,
@ -538,7 +459,7 @@ SCM_DEFINE (scm_allocate_struct, "allocate-struct", 2, 0, 0,
SCM_STRUCT_DATA_SET (ret, n, SCM_UNPACK (SCM_BOOL_F));
}
else
scm_struct_init (ret, SCM_VTABLE_LAYOUT (vtable), 0, 0, NULL);
scm_struct_init (ret, SCM_VTABLE_LAYOUT (vtable), 0, NULL);
return ret;
}
@ -588,8 +509,7 @@ scm_i_make_vtable_vtable (SCM fields)
#define FUNC_NAME "make-vtable-vtable"
{
SCM layout, obj;
size_t basic_size;
scm_t_bits v;
size_t n, nfields;
SCM_VALIDATE_STRING (1, fields);
@ -597,16 +517,26 @@ scm_i_make_vtable_vtable (SCM fields)
if (!scm_is_valid_vtable_layout (layout))
SCM_MISC_ERROR ("invalid user fields", scm_list_1 (fields));
basic_size = scm_i_symbol_length (layout) / 2;
nfields = scm_i_symbol_length (layout) / 2;
obj = scm_i_alloc_struct (0, basic_size);
obj = scm_i_alloc_struct (0, nfields);
/* Make it so that the vtable of OBJ is itself. */
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);
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);
v = SCM_UNPACK (layout);
scm_struct_init (obj, layout, 0, 1, &v);
SCM_SET_VTABLE_FLAGS (obj,
SCM_VTABLE_FLAG_VTABLE | SCM_VTABLE_FLAG_VALIDATED);
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
SCM_STRUCT_DATA_SET (obj, n, 0);
return obj;
}
@ -672,8 +602,6 @@ scm_i_struct_equalp (SCM s1, SCM s2)
return SCM_BOOL_F;
}
/* FIXME: Tail elements should be tested for equality. */
return SCM_BOOL_T;
}
#undef FUNC_NAME
@ -695,72 +623,38 @@ SCM_DEFINE (scm_struct_ref, "struct-ref", 2, 0, 0,
"word.")
#define FUNC_NAME s_scm_struct_ref
{
SCM vtable, answer = SCM_UNDEFINED;
scm_t_bits *data;
size_t p;
SCM vtable;
scm_t_bits data;
size_t nfields, p;
SCM_VALIDATE_STRUCT (1, handle);
vtable = SCM_STRUCT_VTABLE (handle);
data = SCM_STRUCT_DATA (handle);
nfields = SCM_STRUCT_DATA_REF (vtable, scm_vtable_index_size);
p = scm_to_size_t (pos);
if (SCM_LIKELY (SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_SIMPLE)
&& p < SCM_STRUCT_DATA_REF (vtable, scm_vtable_index_size)))
/* The fast path: HANDLE is a struct with only "p" fields. */
answer = SCM_PACK (data[p]);
SCM_ASSERT_RANGE (2, pos, p < nfields);
data = SCM_STRUCT_DATA_REF (handle, p);
if (SCM_LIKELY (SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_SIMPLE)))
/* The fast path: HANDLE is a struct with only readable "p"
fields. */
return SCM_PACK (data);
else
{
SCM layout;
size_t layout_len, n_fields;
scm_t_wchar field_type = 0;
scm_t_wchar field_type, protection;
layout = SCM_STRUCT_LAYOUT (handle);
layout_len = scm_i_symbol_length (layout);
n_fields = layout_len / 2;
field_type = scm_i_symbol_ref (layout, p * 2);
protection = scm_i_symbol_ref (layout, p * 2 + 1);
if (SCM_LAYOUT_TAILP (scm_i_symbol_ref (layout, layout_len - 1)))
n_fields += data[n_fields - 1];
if (protection == 'o')
SCM_MISC_ERROR ("ref denied for field ~A", scm_list_1 (pos));
SCM_ASSERT_RANGE (1, pos, p < n_fields);
if (p * 2 < layout_len)
{
scm_t_wchar ref;
field_type = scm_i_symbol_ref (layout, p * 2);
ref = scm_i_symbol_ref (layout, p * 2 + 1);
if ((ref != 'r') && (ref != 'w') && (ref != 'h'))
{
if ((ref == 'R') || (ref == 'W'))
field_type = 'u';
else
SCM_MISC_ERROR ("ref denied for field ~A", scm_list_1 (pos));
}
}
else if (scm_i_symbol_ref (layout, layout_len - 1) != 'O')
field_type = scm_i_symbol_ref(layout, layout_len - 2);
else
SCM_MISC_ERROR ("ref denied for field ~A", scm_list_1 (pos));
switch (field_type)
{
case 'u':
answer = scm_from_ulong (data[p]);
break;
case 's':
case 'p':
answer = SCM_PACK (data[p]);
break;
default:
SCM_MISC_ERROR ("unrecognized field type: ~S",
scm_list_1 (SCM_MAKE_CHAR (field_type)));
}
return (field_type == 'p') ? SCM_PACK (data) : scm_from_uintptr_t (data);
}
return answer;
}
#undef FUNC_NAME
@ -773,65 +667,35 @@ SCM_DEFINE (scm_struct_set_x, "struct-set!", 3, 0, 0,
#define FUNC_NAME s_scm_struct_set_x
{
SCM vtable;
scm_t_bits *data;
size_t p;
size_t nfields, p;
SCM_VALIDATE_STRUCT (1, handle);
vtable = SCM_STRUCT_VTABLE (handle);
data = SCM_STRUCT_DATA (handle);
nfields = SCM_STRUCT_DATA_REF (vtable, scm_vtable_index_size);
p = scm_to_size_t (pos);
if (SCM_LIKELY (SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_SIMPLE)
&& SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_SIMPLE_RW)
&& p < SCM_STRUCT_DATA_REF (vtable, scm_vtable_index_size)))
/* The fast path: HANDLE is a struct with only "pw" fields. */
data[p] = SCM_UNPACK (val);
SCM_ASSERT_RANGE (2, pos, p < nfields);
if (SCM_LIKELY (SCM_VTABLE_FLAG_IS_SET (vtable, SCM_VTABLE_FLAG_SIMPLE_RW)))
/* The fast path: HANDLE is a struct with only "p" fields. */
SCM_STRUCT_SLOT_SET (handle, p, val);
else
{
SCM layout;
size_t layout_len, n_fields;
scm_t_wchar field_type = 0;
scm_t_wchar field_type, protection;
layout = SCM_STRUCT_LAYOUT (handle);
layout_len = scm_i_symbol_length (layout);
n_fields = layout_len / 2;
field_type = scm_i_symbol_ref (layout, p * 2);
protection = scm_i_symbol_ref (layout, p * 2 + 1);
if (SCM_LAYOUT_TAILP (scm_i_symbol_ref (layout, layout_len - 1)))
n_fields += data[n_fields - 1];
if (protection == 'o' || protection == 'r')
SCM_MISC_ERROR ("set! denied for field ~A", scm_list_1 (pos));
SCM_ASSERT_RANGE (1, pos, p < n_fields);
if (p * 2 < layout_len)
{
char set_x;
field_type = scm_i_symbol_ref (layout, p * 2);
set_x = scm_i_symbol_ref (layout, p * 2 + 1);
if (set_x != 'w' && set_x != 'h')
SCM_MISC_ERROR ("set! denied for field ~A", scm_list_1 (pos));
}
else if (scm_i_symbol_ref (layout, layout_len - 1) == 'W')
field_type = scm_i_symbol_ref (layout, layout_len - 2);
if (field_type == 'p')
SCM_STRUCT_SLOT_SET (handle, p, val);
else
SCM_MISC_ERROR ("set! denied for field ~A", scm_list_1 (pos));
switch (field_type)
{
case 'u':
data[p] = SCM_NUM2ULONG (3, val);
break;
case 'p':
data[p] = SCM_UNPACK (val);
break;
case 's':
SCM_MISC_ERROR ("self fields immutable", SCM_EOL);
default:
SCM_MISC_ERROR ("unrecognized field type: ~S",
scm_list_1 (SCM_MAKE_CHAR (field_type)));
}
SCM_STRUCT_DATA_SET (handle, p, scm_to_uintptr_t (val));
}
return val;