Next: objects chars, Previous: objects vectors, Up: objects [Index]
A data structure is a variable–length block of memory referenced by machine words tagged as vectors; the first machine word of a structure is a reference to its structure type descriptor (STD), which is itself a data structure; the subsequent words, if any, are the fields of the structure. A block of memory is a data structure if and only if: a reference to it is tagged as vector and its first word is tagged as vector.
|----------------|----------| reference to structure heap pointer vector tag |----------------|----------| first word of structure heap pointer vector tag = reference to STD = reference to structure
The whole memory block layout of a struct with 5 fields is as follows:
|-----|------|------|------|------|------| STD field0 field1 field2 field3 field4
fields are indexed starting at zero.
The type descriptor of the type descriptors is the return value of
base-rtd
at the Scheme level and the structure referenced by the
field base_rtd
in the process control block (PCB). Such base
type descriptor is built at Vicare’s startup.
The graph of references for a structure and its type descriptor is as follows:
STD ref |-------|---------------| structure instance | ---<--- | | STD ref -->|-------|---------------| struct type descriptor | ---<--- | | STD ref +-->|-------|---------------| base struct type descriptor | | ---<---
the struct–type descriptor of the base struct–type descriptor is the base type descriptor itself.
About R6RS records and their types:
<rtd>
. The type <rtd>
is defined at the Scheme level.
<rcd>
. The type <rcd>
is defined at the Scheme
level.
The graph of references for a R6RS record and its type descriptor is as follows:
RTD ref |-------|---------------| R6RS record instance | ---<--- | | STD ref -->|-------|---------------| R6RS record-type descriptor | = struct instance of type <rtd> ---<--- | | STD ref +-->|-------|---------------| <rtd> struct-type descriptor | ---<--- | | STD ref +-->|-------|---------------| base struct-type descriptor | | ---<---
A struct–type descriptor (STD) is a fixed–length block of memory composed of 6 machine words interpreted as follows:
Type descriptors are best defined at the Scheme level using the
functions from the library (vicare system structs)
(see define-struct). To instantiate a structure at the
C language level we should write a C function accepting the type
descriptor as argument, and have the Scheme code hand the descriptor to
it. For example, at the Scheme level we do:
(define-struct timeval (tv_sec tv_usec)) (define (gettimeofday) (foreign-call "ikrt_posix_gettimeofday" (struct-type-descriptor timeval)))
and at the C level we do:
ikptr_t ikrt_posix_gettimeofday (ikptr_t s_rtd, ikpcb_t * pcb) { /* build and return an instance of "timeval" */ }
Data structure objects are allocated on the heap; to perform the allocation we compute the whole size of the structure:
ikpcb_t * pcb = ik_the_pcb(); ikuword_t num_of_fields = ...; ikuword_t block_size = \ disp_record_data + wordsize * num_of_fields; ikuword_t align_size = IK_ALIGN(block_size); ikptr_t s_stru = ik_safe_alloc(pcb, align_size) | record_tag;
ik_safe_alloc()
returns an ikptr_t
value representing the aligned
pointer, having the 3 least significant bits set to zero; we add
to it the record tag (an integer value fitting in 3 bits) which
allows to recognise records among all the other built in objects.
We have to explicitly store a reference to the STD in the first machine word of the structure, so a full allocation looks like this:
ikptr_t ika_struct_alloc_no_init (ikpcb_t * pcb, ikptr_t s_std) { ikptr_t s_num_of_fields = IK_STD_LENGTH(s_std); ikuword_t num_of_fields = IK_UNFIX(s_num_of_fields); ikuword_t align_size = \ IK_ALIGN(disp_record_data + num_of_fields * wordsize); ikptr_t s_stru; pcb->root9 = &s_std; { s_ stru = ik_safe_alloc(pcb, align_size) | record_tag; } pcb->root9 = NULL; IK_STRUCT_STD(s_stru) = s_std; return s_stru; }
notice that we do not need to call
ik_signal_dirt_in_page_of_pointer()
for s_stru because
s_std is an older object.
The allocation operation described above leaves the data area uninitialised: its content is undefined. This is bad if the garbage collector moves the newly built record before the elements are initialised to a correct Scheme value.
Structure fields are identified at the C level by a zero–based index; to store a value in field 2 of a structure we do:
ikptr_t s_stru = the_structure; ikptr_t s_field = the_field; IK_REF(s_stru, off_record_data + 2 * wordsize) = the_field; IK_SIGNAL_DIRT(pcb, \ IK_PTR(s_stru, off_record_data + 2 * wordsize));
or, shorter:
ikptr_t s_stru = the_structure; ikptr_t s_field = the_field; IK_FIELD(s_stru, 2) = the_field; IK_SIGNAL_DIRT(pcb, IK_FIELD_PTR(s_stru, 2));
and to retrieve a the value of field 2 we do:
ikptr_t s_stru = the_structure; ikptr_t s_field; s_field = IK_REF(s_stru, off_record_data + 2 * wordsize);
or, shorter:
ikptr_t s_stru = the_structure; ikptr_t s_field; s_field = IK_FIELD(s_stru, 2);
Integer values used to tag and recognise ikptr_t
references to
structures. record_mask
isolates the tag bits from an ikptr_t
and record_tag
represents the tag bits. These values are the
same used for vectors.
Displacement of the STD from the beginning of a structure block. The number of bytes to add to an untagged pointer to structure to get the pointer to the first byte in the word holding the STD.
Displacement of data area. The number of bytes to add to an untagged pointer to structure to get the pointer to the first byte of the first field in the data area.
An integer to add to a tagged ikptr_t
structure reference to retrieve
the pointer to the first byte of the STD.
An integer to add to a tagged ikptr_t
structure reference to retrieve
the pointer to the first byte of the first field of the structure.
Displacement of the base STD from the beginning of an STD block. The number of bytes to add to an untagged pointer to STD to get the pointer to the first byte of the reference to STD.
Displacements of the fields of an STD.
The total number of bytes in a memory block holding an STD.
Integer to add to a tagged ikptr_t
STD reference to retrieve the
pointer to the first byte of the fields.
Evaluate to true if obj is a reference to a structure; otherwise evaluate to false.
Evaluate to the location of the field in the struct–type descriptor std; std must be a tagged reference to a struct–type descriptor. A use of this macro can appear both as operand and as left–side of an assignment.
Evaluate to the location of the struct–type descriptor field for the structure stru; stru must be a tagged reference to a struct object. A use of this macro can appear both as operand and as left–side of an assignment.
ikptr_t s_stru = the_structure; ikptr_t s_std; s_std = IK_STRUCT_STD(s_stru); IK_STRUCT_STD(s_stru) = s_std;
Evaluate to a pointer to the struct–type descriptor field for the structure stru; stru must be a tagged reference to a struct object.
These macros are useful to build the second argument for a call to
ik_signal_dirt_in_page_of_pointer()
.
Evaluate to the location of the field at zero–based index idx for the structure stru. A use of this macro can appear both as operand and as left–side of an assignment.
ikptr_t s_stru = the_structure; ikptr_t s_field; s_field = IK_FIELD(s_stru, 2); IK_FIELD(s_stru, 2) = s_field; IK_SIGNAL_DIRT(pcb, IK_FIELD_PTR(s_stru, 2));
Evaluate to a pointer to the field at index idx for the structure stru; stru must be a tagged reference to a struct object.
This macro is useful to build the second argument for a call to
ik_signal_dirt_in_page_of_pointer()
.
Given a tagged pointer referencing a struct: return a pointer to the first machine word in the data area of the struct’s memory block; this is a pointer to the location of the first struct field.
Allocate, initialise and return a new structure instance of type std. The first word of the allocated block is initialised with std, the other words are left uninitialised.
NOTE This function makes use of the field root9
of
pcb.
Allocate, initialise and return a new structure instance of type std. The first word of the allocated block is initialised with std, the other words are initialised to the fixnum zero.
NOTE This function makes use of the field root9
of
pcb.
Return true if R is a reference to a structure; otherwise return false.
Next: objects chars, Previous: objects vectors, Up: objects [Index]