Skip to content

Instantly share code, notes, and snippets.

@jnthn
Created May 27, 2015 18:57
Show Gist options
  • Save jnthn/75c041af8f6a13bf5638 to your computer and use it in GitHub Desktop.
Save jnthn/75c041af8f6a13bf5638 to your computer and use it in GitHub Desktop.
diff --git a/src/6model/6model.h b/src/6model/6model.h
index 85b20fe..adc6dfc 100644
--- a/src/6model/6model.h
+++ b/src/6model/6model.h
@@ -131,7 +131,13 @@ typedef enum {
/* Note: if you're hunting for a flag, some day in the future when we
* have used them all, this one is easy enough to eliminate by having the
* tiny number of objects marked this way in a remembered set. */
- MVM_CF_NEVER_REPOSSESS = 1024
+ MVM_CF_NEVER_REPOSSESS = 1024,
+
+ /* Is the object still in the process of being deserialized? This flag is
+ * set if so. It prevents multi-threaded programs grabbing a partially
+ * deserialized object while another thread is in the middle of doing its
+ * deserialization. */
+ MVM_CF_DESERIALIZING = 2048
} MVMCollectableFlags;
#ifdef MVM_USE_OVERFLOW_SERIALIZATION_INDEX
diff --git a/src/6model/sc.c b/src/6model/sc.c
index 37864ad..076ee95 100644
--- a/src/6model/sc.c
+++ b/src/6model/sc.c
@@ -153,12 +153,17 @@ MVMSerializationContext * MVM_sc_get_sc(MVMThreadContext *tc, MVMCompUnit *cu, M
MVMObject * MVM_sc_get_object(MVMThreadContext *tc, MVMSerializationContext *sc, MVMint64 idx) {
MVMObject **roots = sc->body->root_objects;
MVMint64 count = sc->body->num_objects;
- if (idx >= 0 && idx < count)
- return roots[idx] ? roots[idx] : MVM_serialization_demand_object(tc, sc, idx);
- else
+ if (idx >= 0 && idx < count) {
+ MVMObject *result = roots[idx];
+ return result && !MVM_DESERIALIZING_TEST(tc, &(result->header))
+ ? result
+ : MVM_serialization_demand_object(tc, sc, idx);
+ }
+ else {
MVM_exception_throw_adhoc(tc,
"Probable version skew in pre-compiled '%s' (cause: no object at index %"PRId64")",
MVM_string_utf8_encode_C_string(tc, sc->body->description), idx);
+ }
}
MVMObject * MVM_sc_get_sc_object(MVMThreadContext *tc, MVMCompUnit *cu,
@@ -213,7 +218,9 @@ void MVM_sc_set_object(MVMThreadContext *tc, MVMSerializationContext *sc, MVMint
MVMSTable * MVM_sc_get_stable(MVMThreadContext *tc, MVMSerializationContext *sc, MVMint64 idx) {
if (idx >= 0 && idx < sc->body->num_stables) {
MVMSTable *got = sc->body->root_stables[idx];
- return got ? got : MVM_serialization_demand_stable(tc, sc, idx);
+ return got && !MVM_DESERIALIZING_TEST(tc, &(got->header))
+ ? got
+ : MVM_serialization_demand_stable(tc, sc, idx);
}
else {
MVM_exception_throw_adhoc(tc,
diff --git a/src/6model/sc.h b/src/6model/sc.h
index aafc82c..7970228 100644
--- a/src/6model/sc.h
+++ b/src/6model/sc.h
@@ -163,3 +163,14 @@ MVM_STATIC_INLINE void MVM_SC_WB_ST(MVMThreadContext *tc, MVMSTable *st) {
if (MVM_get_idx_of_sc(&st->header) > 0)
MVM_sc_wb_hit_st(tc, st);
}
+
+/* Set/clear/test the "currently being deserialized" flag on object/STable. */
+MVM_STATIC_INLINE void MVM_DESERIALIZING_SET(MVMThreadContext *tc, MVMCollectable *c) {
+ c->flags |= MVM_CF_DESERIALIZING;
+}
+MVM_STATIC_INLINE void MVM_DESERIALIZING_CLEAR(MVMThreadContext *tc, MVMCollectable *c) {
+ c->flags ^= MVM_CF_DESERIALIZING;
+}
+MVM_STATIC_INLINE MVMint64 MVM_DESERIALIZING_TEST(MVMThreadContext *tc, MVMCollectable *c) {
+ return c->flags & MVM_CF_DESERIALIZING;
+}
diff --git a/src/6model/serialization.c b/src/6model/serialization.c
index a7b9d95..1df54df 100644
--- a/src/6model/serialization.c
+++ b/src/6model/serialization.c
@@ -1929,6 +1929,7 @@ static void stub_stable(MVMThreadContext *tc, MVMSerializationReader *reader, MV
/* Allocate and store stub STable. */
st = MVM_gc_allocate_stable(tc, repr, NULL);
+ //MVM_DESERIALIZING_SET(tc, &(st->header));
MVM_sc_set_stable(tc, reader->root.sc, i, st);
}
@@ -2003,6 +2004,7 @@ static void stub_object(MVMThreadContext *tc, MVMSerializationReader *reader, MV
else
obj = MVM_gc_allocate_type_object(tc, st);
MVM_sc_set_object(tc, reader->root.sc, i, obj);
+ //MVM_DESERIALIZING_SET(tc, &(obj->header));
}
/* Set the object's SC. */
@@ -2312,6 +2314,9 @@ static void deserialize_stable(MVMThreadContext *tc, MVMSerializationReader *rea
if (st->REPR->deserialize_repr_data)
st->REPR->deserialize_repr_data(tc, st, reader);
+ /* Flag that we're done deserializing it. */
+ MVM_DESERIALIZING_CLEAR(tc, &(st->header));
+
/* Restore original read positions. */
reader->stables_data_offset = orig_stables_data_offset;
reader->cur_read_buffer = orig_read_buffer;
@@ -2346,6 +2351,9 @@ static void deserialize_object(MVMThreadContext *tc, MVMSerializationReader *rea
REPR(obj)->name);
reader->current_object = NULL;
}
+
+ /* Flag that we're done deserializing it. */
+ MVM_DESERIALIZING_CLEAR(tc, &(obj->header));
}
/* Worklist manipulation functions. */
@@ -2574,6 +2582,9 @@ static void repossess(MVMThreadContext *tc, MVMSerializationReader *reader, MVMi
});
}
+ /* Flag it as now being in the process of being deserialized. */
+ //MVM_DESERIALIZING_SET(tc, &(orig_obj->header));
+
/* Put it into objects root set at the apporpriate slot. */
slot = read_int32(table_row, 4);
MVM_sc_set_object(tc, reader->root.sc, slot, orig_obj);
@@ -2604,6 +2615,9 @@ static void repossess(MVMThreadContext *tc, MVMSerializationReader *reader, MVMi
"STable conflict detected during deserialization.\n"
"(Probable attempt to load two modules that cannot be loaded together).");
+ /* Flag it as now being in the process of being deserialized. */
+ //MVM_DESERIALIZING_SET(tc, &(orig_st->header));
+
/* Put it into STables root set at the apporpriate slot. */
slot = read_int32(table_row, 4);
MVM_sc_set_stable(tc, reader->root.sc, slot, orig_st);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment