Skip to content

Commit ecb463b

Browse files
committed
Implement serialization of references to other objects, which makes a cross-reference to another SC if needed, or if the object is in no SC adds it to ours and puts it onto the serialization worklist. Test for circular reference serialization now passes.
1 parent f29733c commit ecb463b

File tree

3 files changed

+115
-14
lines changed

3 files changed

+115
-14
lines changed

src/6model/serialization.c

Lines changed: 104 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,18 @@
2525
/* Possible reference types we can serialize. */
2626
#define REFVAR_NULL 1
2727
#define REFVAR_OBJECT 2
28-
#define REFVAR_VM_INT 3
29-
#define REFVAR_VM_NUM 4
30-
#define REFVAR_VM_STR 5
31-
#define REFVAR_VM_ARR_VAR 6
32-
#define REFVAR_VM_ARR_STR 7
33-
#define REFVAR_VM_ARR_INT 8
34-
#define REFVAR_VM_HASH_STR_VAR 9
35-
#define REFVAR_STATIC_CODEREF 10
28+
#define REFVAR_VM_NULL 3
29+
#define REFVAR_VM_INT 4
30+
#define REFVAR_VM_NUM 5
31+
#define REFVAR_VM_STR 6
32+
#define REFVAR_VM_ARR_VAR 7
33+
#define REFVAR_VM_ARR_STR 8
34+
#define REFVAR_VM_ARR_INT 9
35+
#define REFVAR_VM_HASH_STR_VAR 10
36+
#define REFVAR_STATIC_CODEREF 11
37+
38+
/* Cached type IDs. */
39+
static INTVAL smo_id = 0;
3640

3741
/* ***************************************************************************
3842
* Serialization (writing related)
@@ -179,11 +183,51 @@ void write_str_func(PARROT_INTERP, SerializationWriter *writer, STRING *value) {
179183
}
180184
}
181185

186+
/* Writes an object reference. */
187+
void write_obj_ref(PARROT_INTERP, SerializationWriter *writer, PMC *ref) {
188+
Parrot_Int4 sc_id, idx;
189+
190+
if (PMC_IS_NULL(SC_PMC(ref))) {
191+
/* This object doesn't belong to an SC yet, so it must be serialized as part of
192+
* this compilation unit. Add it to the work list. */
193+
SC_PMC(ref) = writer->root.sc;
194+
VTABLE_push_pmc(interp, writer->objects_list, ref);
195+
}
196+
sc_id = get_sc_id(interp, writer, SC_PMC(ref));
197+
idx = (Parrot_Int4)SC_find_object_idx(interp, SC_PMC(ref), ref);
198+
199+
expand_storage_if_needed(interp, writer, 8);
200+
if (writer->writing_object) {
201+
write_int32(writer->root.objects_data, writer->objects_data_offset, sc_id);
202+
writer->objects_data_offset += 4;
203+
write_int32(writer->root.objects_data, writer->objects_data_offset, idx);
204+
writer->objects_data_offset += 4;
205+
}
206+
else {
207+
write_int32(writer->root.stables_data, writer->stables_data_offset, sc_id);
208+
writer->stables_data_offset += 4;
209+
write_int32(writer->root.stables_data, writer->stables_data_offset, idx);
210+
writer->stables_data_offset += 4;
211+
}
212+
}
213+
182214
/* Writing function for references to things. */
183215
void write_ref_func(PARROT_INTERP, SerializationWriter *writer, PMC *ref) {
184216
/* Work out what kind of thing we have and determine the discriminator. */
185217
Parrot_Int2 discrim = 0;
186-
/* XXX */
218+
if (ref == NULL) {
219+
discrim = REFVAR_NULL;
220+
}
221+
else if (PMC_IS_NULL(ref)) {
222+
discrim = REFVAR_VM_NULL;
223+
}
224+
else if (ref->vtable->base_type == smo_id) {
225+
discrim = REFVAR_OBJECT;
226+
}
227+
else {
228+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
229+
"Serialization Error: Unimplemented object type passed to write_ref");
230+
}
187231

188232
/* Write the discriminator. */
189233
expand_storage_if_needed(interp, writer, 2);
@@ -197,8 +241,18 @@ void write_ref_func(PARROT_INTERP, SerializationWriter *writer, PMC *ref) {
197241
}
198242

199243
/* Now take appropriate action. */
200-
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
201-
"write_ref not yet implemented");
244+
switch (discrim) {
245+
case REFVAR_NULL:
246+
case REFVAR_VM_NULL:
247+
/* Nothing to do for these. */
248+
break;
249+
case REFVAR_OBJECT:
250+
write_obj_ref(interp, writer, ref);
251+
break;
252+
default:
253+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
254+
"Serialization Error: Unimplemented object type passed to write_ref");
255+
}
202256
}
203257

204258
/* Concatenates the various output segments into a single binary string. */
@@ -380,6 +434,9 @@ STRING * Serialization_serialize(PARROT_INTERP, PMC *sc, PMC *empty_string_heap)
380434
writer->write_num = write_num_func;
381435
writer->write_str = write_str_func;
382436
writer->write_ref = write_ref_func;
437+
438+
/* Other init. */
439+
smo_id = Parrot_pmc_get_type_str(interp, Parrot_str_new(interp, "SixModelObject", 0));
383440

384441
/* Start serializing. */
385442
serialize(interp, writer);
@@ -524,7 +581,28 @@ STRING * read_str_func(PARROT_INTERP, SerializationReader *reader) {
524581
}
525582
}
526583

527-
/* Reading function for native strings. */
584+
/* Reads in and resolves an object references. */
585+
PMC * read_obj_ref(PARROT_INTERP, SerializationReader *reader) {
586+
Parrot_Int4 sc_id, idx;
587+
588+
assert_can_read(interp, reader, 8);
589+
if (reader->reading_object) {
590+
sc_id = read_int32(reader->root.objects_data, reader->objects_data_offset);
591+
reader->objects_data_offset += 4;
592+
idx = read_int32(reader->root.objects_data, reader->objects_data_offset);
593+
reader->objects_data_offset += 4;
594+
}
595+
else {
596+
sc_id = read_int32(reader->root.stables_data, reader->stables_data_offset);
597+
reader->stables_data_offset += 4;
598+
idx = read_int32(reader->root.stables_data, reader->stables_data_offset);
599+
reader->stables_data_offset += 4;
600+
}
601+
602+
return SC_get_object(interp, locate_sc(interp, reader, sc_id), idx);
603+
}
604+
605+
/* Reading function for references. */
528606
PMC * read_ref_func(PARROT_INTERP, SerializationReader *reader) {
529607
/* Read the discriminator. */
530608
Parrot_Int2 discrim;
@@ -539,8 +617,17 @@ PMC * read_ref_func(PARROT_INTERP, SerializationReader *reader) {
539617
}
540618

541619
/* Decide what to do based on it. */
542-
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
543-
"read_ref not yet implemented");
620+
switch (discrim) {
621+
case REFVAR_NULL:
622+
return NULL;
623+
case REFVAR_OBJECT:
624+
return read_obj_ref(interp, reader);
625+
case REFVAR_VM_NULL:
626+
return PMCNULL;
627+
default:
628+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
629+
"Serialization Error: Unimplemented case of read_ref");
630+
}
544631
}
545632

546633
/* Checks the header looks sane and all of the places it points to make sense.
@@ -703,6 +790,9 @@ void Serialization_deserialize(PARROT_INTERP, PMC *sc, PMC *string_heap, STRING
703790
reader->read_str = read_str_func;
704791
reader->read_ref = read_ref_func;
705792

793+
/* Other init. */
794+
smo_id = Parrot_pmc_get_type_str(interp, Parrot_str_new(interp, "SixModelObject", 0));
795+
706796
/* Read header and disect the data into its parts. */
707797
check_and_disect_input(interp, reader, data);
708798

src/6model/serialization_context.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,13 @@ PMC * SC_get_stable(PARROT_INTERP, PMC *sc, INTVAL idx) {
8181
"No STable at index %d", idx);
8282
return VTABLE_get_pmc_keyed_int(interp, stables, idx);
8383
}
84+
85+
/* Given an SC and an index, fetch the object stored there. */
86+
PMC * SC_get_object(PARROT_INTERP, PMC *sc, INTVAL idx) {
87+
PMC *objects;
88+
GETATTR_SerializationContext_root_objects(interp, sc, objects);
89+
if (idx >= VTABLE_elements(interp, objects))
90+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
91+
"No object at index %d", idx);
92+
return VTABLE_get_pmc_keyed_int(interp, objects, idx);
93+
}

src/6model/serialization_context.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ INTVAL SC_find_object_idx(PARROT_INTERP, PMC *sc, PMC *st);
88
STRING * SC_get_handle(PARROT_INTERP, PMC *sc);
99
STRING * SC_get_description(PARROT_INTERP, PMC *sc);
1010
PMC * SC_get_stable(PARROT_INTERP, PMC *sc, INTVAL idx);
11+
PMC * SC_get_object(PARROT_INTERP, PMC *sc, INTVAL idx);
1112
#endif

0 commit comments

Comments
 (0)