Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
A scheme for serializing CLR wrappers (fixes #117)
Based on the generic reference serialization scheme.  Not foolproof;
attempting to serialize a reference to a method will still blow up.
  • Loading branch information
sorear committed May 26, 2012
1 parent ad2d70a commit 69f2cee
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 6 deletions.
7 changes: 7 additions & 0 deletions lib/NieczaCLR.cs
Expand Up @@ -515,6 +515,10 @@ public class CLRWrapperProvider {
}
}

internal static void LoadWrapper(string tn) {
GetWrapper(Type.GetType(tn));
}

public static STable GetNamedWrapper(string nm) {
lock (wrapper_cache_lock) {
if (named_wrapper_cache == null)
Expand Down Expand Up @@ -765,6 +769,9 @@ public class CLRWrapperProvider {
foreach (var o in m.mo.type_list)
Console.WriteLine("type {0}", o.name);
}

RuntimeUnit.reg.InstallFakeUnit("CLR," + t.AssemblyQualifiedName,
m, m.who, m.how, m.mo, m.typeObject, m.typeVar);
return m;
}

Expand Down
41 changes: 35 additions & 6 deletions lib/Serialize.cs
Expand Up @@ -45,6 +45,8 @@ class SerUnit {
internal object[] bynum = new object[8]; // objects in unit
internal object root; // the RuntimeUnit object
internal int nobj; // = 0

internal bool fake; // true for CLR reference units
}

// The central feature of *bounded* serialization is that object
Expand All @@ -68,7 +70,7 @@ struct ObjRef {
new Dictionary<string,Dictionary<string,MethodInfo>>();

static readonly string signature = "Niecza-Serialized-Module";
static readonly int version = 25;
static readonly int version = 26;

// Routines for use by serialization code
public bool CheckWriteObject(SerUnit into, object o,
Expand Down Expand Up @@ -111,17 +113,39 @@ struct ObjRef {
}

// Routines for use by compilation manager
public void InstallFakeUnit(string name, params object[] items) {
SerUnit su = new SerUnit();
su.fake = true;
su.name = name;
su.bynum = items;
su.hash = new byte[0];
units[name] = su;

ObjRef or;
or.unit = su;
for (or.id = 0; or.id < items.Length; or.id++)
byref[items[or.id]] = or;
}

// Loads a single unit from the compiled-data directory.
// Will throw a ThawException if a stale reference is encountered
// or other data format error.
public SerUnit LoadUnit(string name) {
public SerUnit LoadUnit(string name, bool fake = false) {
SerUnit su;

// is the unit already loaded?
if (units.TryGetValue(name, out su))
return su;

if (fake) {
if (name.StartsWith("CLR,"))
CLRWrapperProvider.LoadWrapper(name.Substring(4));
else
throw new ThawException("No handler for fake unit name " + name);

return units[name];
}

string file = Path.Combine(Backend.obj_dir, Backend.prefix +
name.Replace("::",".") + ".ser");
byte[] bytes = File.ReadAllBytes(file);
Expand Down Expand Up @@ -208,6 +232,7 @@ enum SerializationCode : byte {
ForeignRef,
SelfRef,
NewUnitRef,
FakeUnitRef,

// types of new object
RuntimeUnit,
Expand Down Expand Up @@ -419,7 +444,9 @@ public class FreezeBuffer {
} else {
int altcode;
if (!unit_to_offset.TryGetValue(altunit, out altcode)) {
Byte((byte)SerializationCode.NewUnitRef);
Byte(altunit.fake ?
(byte)SerializationCode.FakeUnitRef :
(byte)SerializationCode.NewUnitRef);
String(altunit.name);
// save the hash too so stale refs can be caught
foreach (byte b in altunit.hash) Byte(b);
Expand Down Expand Up @@ -677,7 +704,9 @@ class ThawBuffer {
i = Int();
return unit.bynum[i];
case SerializationCode.NewUnitRef:
return LoadNewUnit();
return LoadNewUnit(false);
case SerializationCode.FakeUnitRef:
return LoadNewUnit(true);

case SerializationCode.RuntimeUnit:
return RuntimeUnit.Thaw(this);
Expand Down Expand Up @@ -802,12 +831,12 @@ class ThawBuffer {
return o;
}

object LoadNewUnit() {
object LoadNewUnit(bool fake) {
string name = String();
if (refed_units == unit_map.Length)
Array.Resize(ref unit_map, refed_units * 2);

SerUnit su = reg.LoadUnit(name);
SerUnit su = reg.LoadUnit(name, fake);
unit_map[refed_units++] = su;

byte[] hash = Bytes(su.hash.Length);
Expand Down

0 comments on commit 69f2cee

Please sign in to comment.