Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 838 lines (727 sloc) 27.43 kB
8184302 @sorear Start draft of serialization/deserialization code
authored
1 using System;
d832c02 @sorear Second draft of serialization code
authored
2 using System.IO;
3 using System.Security.Cryptography;
b25256f @sorear Add Serialize.cs to build, fix build errors
authored
4 using System.Collections.Generic;
d832c02 @sorear Second draft of serialization code
authored
5 using System.Text;
9083142 @sorear Switch to single-AppDomain execution
authored
6 using Niecza.CLRBackend;
8184302 @sorear Start draft of serialization/deserialization code
authored
7
cdde7e0 @sorear Notes on four kinds of module scope
authored
8 // Here in Niecza we have four different kinds of unit scopes:
9 //
10 // * COMPILING::UNIT, aka RuntimeUnit: one of these exists for every
11 // call into the compiler, whether eval or module. The REPL will
12 // be considered as if it were eval.
13 //
14 // * Serialization scopes, which are created when compiling modules
15 // or when pre-compiling a main program. During execution there is
16 // no current serialization scope; evals inherit the serialization
17 // scope or lack thereof that was in effect.
18 //
19 // * Assembly scopes, which are an artifact of the CLR and almost align
20 // with precompilation scopes, except that they have to exist always
21 // because methods cannot be created free-floating in CLR 2.x.
22 //
23 // An assembly scope is created for all serialization scopes, and
24 // non-saved anonymous assemblies are created for eval-and-run of
25 // a file and non-BEGIN-time evals.
26 //
27 // * GLOBAL scope is very much like serialization scope except that there
28 // is a "true globals" scope that is used when not serializing.
29
8184302 @sorear Start draft of serialization/deserialization code
authored
30 // This implements "bounded serialization" for Niecza. Unfortunately
31 // the CLR's builtin serialization can't efficiently be made bounded,
32 // and anyway it would be nice if the serialization format could be
33 // transported across backends.
34
35 // TODO: implement a more Storable-like interface.
d832c02 @sorear Second draft of serialization code
authored
36
37 // Note, the serialization subsystem is *NOT* thread safe !
8184302 @sorear Start draft of serialization/deserialization code
authored
38 namespace Niecza.Serialization {
d832c02 @sorear Second draft of serialization code
authored
39 // Information kept on a serialization unit after loading or storing,
40 // but not before storing.
41 class SerUnit {
42 internal string name; // eg "File.Copy"
43 internal byte[] hash; // hash of entire file, filled at write time
8ed36ea @sorear Wire up serializer to run after pre-compiler
authored
44 internal object[] bynum = new object[8]; // objects in unit
d832c02 @sorear Second draft of serialization code
authored
45 internal object root; // the RuntimeUnit object
8ed36ea @sorear Wire up serializer to run after pre-compiler
authored
46 internal int nobj; // = 0
d832c02 @sorear Second draft of serialization code
authored
47 }
8184302 @sorear Start draft of serialization/deserialization code
authored
48
49 // The central feature of *bounded* serialization is that object
50 // registries are kept distinct from the (de)serializer, and can
51 // be shared between serialization runs.
52 class ObjectRegistry {
d832c02 @sorear Second draft of serialization code
authored
53 // TODO: investigate a more specialized representation,
54 // ideally not having to hash as many objects
55 struct ObjRef {
b25256f @sorear Add Serialize.cs to build, fix build errors
authored
56 public SerUnit unit;
57 public int id;
8184302 @sorear Start draft of serialization/deserialization code
authored
58 }
d832c02 @sorear Second draft of serialization code
authored
59 Dictionary<object,ObjRef> byref = new Dictionary<object,ObjRef>();
8184302 @sorear Start draft of serialization/deserialization code
authored
60
d832c02 @sorear Second draft of serialization code
authored
61 Dictionary<string,SerUnit> units =
62 new Dictionary<string,SerUnit>();
63
cdb4548 @sorear Checkpoint of global-variable inventory
authored
64 internal static HashAlgorithm NewHash() { return new SHA256Managed(); }
65
d832c02 @sorear Second draft of serialization code
authored
66 static readonly string signature = "Niecza-Serialized-Module";
67 static readonly int version = 1;
68
69 // Routines for use by serialization code
70 public bool CheckWriteObject(SerUnit into, object o,
71 out SerUnit lui, out int id) {
72 ObjRef or;
73 if (byref.TryGetValue(o, out or)) {
74 lui = or.unit;
75 id = or.id;
8184302 @sorear Start draft of serialization/deserialization code
authored
76 return true;
d832c02 @sorear Second draft of serialization code
authored
77 }
8184302 @sorear Start draft of serialization/deserialization code
authored
78
d832c02 @sorear Second draft of serialization code
authored
79 if (into.nobj == into.bynum.Length)
80 Array.Resize(ref into.bynum, into.nobj * 2);
8184302 @sorear Start draft of serialization/deserialization code
authored
81
b25256f @sorear Add Serialize.cs to build, fix build errors
authored
82 or.unit = lui = into;
d832c02 @sorear Second draft of serialization code
authored
83 id = or.id = into.nobj++;
84 into.bynum[id] = o;
85
86 byref[o] = or;
8184302 @sorear Start draft of serialization/deserialization code
authored
87
88 return false;
89 }
d832c02 @sorear Second draft of serialization code
authored
90
1c5bb04 @sorear Small refactor to AssemblyBuilder setup, start thaw coding
authored
91 public void RegisterThawed(SerUnit into, object o) {
92 ObjRef or;
93 if (into.nobj == into.bynum.Length)
94 Array.Resize(ref into.bynum, into.nobj * 2);
95
96 or.unit = into;
97 or.id = into.nobj++;
98 into.bynum[or.id] = o;
99
100 byref[o] = or;
101 }
102
d832c02 @sorear Second draft of serialization code
authored
103 // Routines for use by compilation manager
104
105 // Loads a single unit from the compiled-data directory.
106 // Will throw a ThawException if a stale reference is encountered
107 // or other data format error.
108 public SerUnit LoadUnit(string name) {
109 SerUnit su;
110
111 // is the unit already loaded?
112 if (units.TryGetValue(name, out su))
113 return su;
114
9083142 @sorear Switch to single-AppDomain execution
authored
115 string file = Path.Combine(Backend.obj_dir, Backend.prefix +
116 name.Replace("::",".") + ".ser");
d832c02 @sorear Second draft of serialization code
authored
117 byte[] bytes = File.ReadAllBytes(file);
118
119 su = new SerUnit();
120 su.name = name;
cdb4548 @sorear Checkpoint of global-variable inventory
authored
121 su.hash = NewHash().ComputeHash(bytes);
d832c02 @sorear Second draft of serialization code
authored
122
b25256f @sorear Add Serialize.cs to build, fix build errors
authored
123 ThawBuffer tb = new ThawBuffer(this, su, bytes);
d832c02 @sorear Second draft of serialization code
authored
124
8ed36ea @sorear Wire up serializer to run after pre-compiler
authored
125 units[name] = su;
d832c02 @sorear Second draft of serialization code
authored
126 bool success = false;
127 try {
128 string rsig = tb.String();
129 if (rsig != signature)
130 throw new ThawException("signature mismatch loading " + file);
131 int rver = tb.Int();
132 if (rver != version)
133 throw new ThawException("version mismatch loading " + file);
134
b25256f @sorear Add Serialize.cs to build, fix build errors
authored
135 su.root = tb.ObjRef();
c0af787 @sorear Fix fixup call order (oops!), serialization-compatible calling of pha…
authored
136 tb.RunFixups();
d832c02 @sorear Second draft of serialization code
authored
137 success = true;
138 } finally {
139 // don't leave half-read units in the map
140 if (!success)
141 UnloadUnit(name);
142 }
143
144 return su;
145 }
146
147 // removes a stale unit so a new version can be saved over it.
148 public void UnloadUnit(string name) {
8ed36ea @sorear Wire up serializer to run after pre-compiler
authored
149 if (!units.ContainsKey(name))
150 return;
d832c02 @sorear Second draft of serialization code
authored
151 SerUnit su = units[name];
152 units.Remove(name);
153
154 for (int i = 0; i < su.nobj; i++)
155 byref.Remove(su.bynum[i]);
156 }
157
158 public SerUnit SaveUnit(string name, IFreeze root) {
159 SerUnit su = new SerUnit();
160 su.name = name;
161 su.root = root;
162
163 if (units.ContainsKey(name))
b25256f @sorear Add Serialize.cs to build, fix build errors
authored
164 throw new InvalidOperationException("unit " +name+ " exists");
d832c02 @sorear Second draft of serialization code
authored
165
166 bool success = false;
9083142 @sorear Switch to single-AppDomain execution
authored
167 string file = Path.Combine(Backend.obj_dir, Backend.prefix +
168 name.Replace("::",".") + ".ser");
d832c02 @sorear Second draft of serialization code
authored
169
170 FreezeBuffer fb = new FreezeBuffer(this, su);
171
8ed36ea @sorear Wire up serializer to run after pre-compiler
authored
172 units[name] = su;
173
d832c02 @sorear Second draft of serialization code
authored
174 try {
175 fb.String(signature);
176 fb.Int(version);
177 fb.ObjRef(root);
178
179 byte[] data = fb.GetData();
cdb4548 @sorear Checkpoint of global-variable inventory
authored
180 su.hash = NewHash().ComputeHash(data);
d832c02 @sorear Second draft of serialization code
authored
181 File.WriteAllBytes(file, data);
182 success = true;
183 } finally {
184 if (!success)
185 UnloadUnit(name);
186 }
187
188 return su;
189 }
8184302 @sorear Start draft of serialization/deserialization code
authored
190 }
191
192 // One of these codes is written at the beginning of every object ref
1993029 @sorear Start implementing serialization for our objects
authored
193 enum SerializationCode : byte {
d832c02 @sorear Second draft of serialization code
authored
194 // special
195 Null,
196
8184302 @sorear Start draft of serialization/deserialization code
authored
197 // existing objects
198 ForeignRef,
199 SelfRef,
200 NewUnitRef,
1993029 @sorear Start implementing serialization for our objects
authored
201
202 // types of new object
203 RuntimeUnit,
204 SubInfo,
205 STable,
206 StashEnt,
d91ecdf @sorear Serialization for objects of type Rat, FatRat, Complex, BigInteger, I…
authored
207 Rat,
208 FatRat,
209 Complex,
210 BigInteger,
211 VarDeque,
212 VarHash,
dc6dd55 @sorear Implement serialization for Frame, finally kill off hashtable lexicals
authored
213 DispatchEnt,
214 RxFrame,
215 P6how,
3f80fca @sorear A procedure for serializing ContextHandler et al
authored
216 ReflectObj,
7ae298f @sorear Make CC, LIHint serializable
authored
217 CC,
218 AltInfo,
1993029 @sorear Start implementing serialization for our objects
authored
219
220 // types of P6any-reified object
d91ecdf @sorear Serialization for objects of type Rat, FatRat, Complex, BigInteger, I…
authored
221 P6opaque, // eventually let's specialize this
1993029 @sorear Start implementing serialization for our objects
authored
222 Frame,
223 Cursor,
224
1c5bb04 @sorear Small refactor to AssemblyBuilder setup, start thaw coding
authored
225 // miscellany - keep these in same order as FallbackFreeze
226 String,
227 ArrP6any,
228 ArrVariable,
7ae298f @sorear Make CC, LIHint serializable
authored
229 ArrString,
230 ArrCC,
fe6e595 @sorear Thaw for SimpleVariable, StashEnt
authored
231 Boolean,
1c5bb04 @sorear Small refactor to AssemblyBuilder setup, start thaw coding
authored
232 Int,
233 Double,
3f80fca @sorear A procedure for serializing ContextHandler et al
authored
234 Type,
d91ecdf @sorear Serialization for objects of type Rat, FatRat, Complex, BigInteger, I…
authored
235
ab35238 @sorear Tidy up STable fields a bit, add TiedVariable serialize
authored
236 // variables
1c5bb04 @sorear Small refactor to AssemblyBuilder setup, start thaw coding
authored
237 SimpleVariable, // allow 4 for flags
fe6e595 @sorear Thaw for SimpleVariable, StashEnt
authored
238 SimpleVariable_1,
239 SimpleVariable_2,
240 SimpleVariable_3,
241 SubstrLValue,
ab35238 @sorear Tidy up STable fields a bit, add TiedVariable serialize
authored
242 TiedVariable,
1993029 @sorear Start implementing serialization for our objects
authored
243
244 // vivification hooks
ab35238 @sorear Tidy up STable fields a bit, add TiedVariable serialize
authored
245 SubViviHook,
1993029 @sorear Start implementing serialization for our objects
authored
246 ArrayViviHook,
247 NewArrayViviHook,
248 HashViviHook,
249 NewHashViviHook,
b1088dc @sorear implement serialization for SubInfo, LAD, LexInfo
authored
250
251 // Longest-token automaton descriptors
252 LADNone, // no-args
253 LADNull,
254 LADDot,
255 LADDispatcher,
256 LADImp,
257 LADStr, // string
258 LADStrNoCase,
259 LADMethod,
260 LADParam,
261 LADOpt, // LAD
262 LADPlus,
263 LADStar,
264 LADSequence, // LAD[]
265 LADAny,
266 LADCC, // CC
8184302 @sorear Start draft of serialization/deserialization code
authored
267 }
268
269 // An instance of this class is used to serialize serialization units
1993029 @sorear Start implementing serialization for our objects
authored
270 public class FreezeBuffer {
8184302 @sorear Start draft of serialization/deserialization code
authored
271 byte[] data;
272 int wpointer;
273
d832c02 @sorear Second draft of serialization code
authored
274 Dictionary<SerUnit,int> unit_to_offset;
275 int usedunits;
8184302 @sorear Start draft of serialization/deserialization code
authored
276
277 ObjectRegistry reg;
d832c02 @sorear Second draft of serialization code
authored
278 SerUnit unit;
8184302 @sorear Start draft of serialization/deserialization code
authored
279
d832c02 @sorear Second draft of serialization code
authored
280 internal FreezeBuffer(ObjectRegistry reg, SerUnit unit) {
8ed36ea @sorear Wire up serializer to run after pre-compiler
authored
281 if (reg == null || unit == null)
282 throw new ArgumentNullException();
8184302 @sorear Start draft of serialization/deserialization code
authored
283 this.reg = reg;
d832c02 @sorear Second draft of serialization code
authored
284 this.unit = unit;
285 unit_to_offset = new Dictionary<SerUnit,int>();
8184302 @sorear Start draft of serialization/deserialization code
authored
286 data = new byte[256];
287 }
288
b25256f @sorear Add Serialize.cs to build, fix build errors
authored
289 internal byte[] GetData() {
290 byte[] ret = new byte[wpointer];
291 Array.Copy(data, ret, ret.Length);
292 return ret;
293 }
294
8184302 @sorear Start draft of serialization/deserialization code
authored
295 void Ensure(int ct) {
296 while (ct + wpointer > data.Length)
297 Array.Resize(ref data, data.Length * 2);
298 }
299
300 public void Byte(byte x) {
301 Ensure(1);
302 data[wpointer++] = x;
303 }
304
19ada5b @sorear Implement variable-length coding for serialization
authored
305 public void Long(long x) {
306 //Console.WriteLine("Saving {0} at {1}", x, wpointer);
307 Ensure(10);
308 while (true) {
309 if (x >= -64 && x <= 63) {
310 data[wpointer++] = (byte) (127 & (byte)x);
311 break;
312 } else {
313 data[wpointer++] = (byte) (128 | (byte)x);
314 x >>= 7;
315 }
316 }
8184302 @sorear Start draft of serialization/deserialization code
authored
317 }
318
19ada5b @sorear Implement variable-length coding for serialization
authored
319 public void ULong(ulong x) {
320 //Console.WriteLine("Saving {0} at {1}", x, wpointer);
321 Ensure(10);
322 while (true) {
323 if (x <= 127) {
324 data[wpointer++] = (byte) (127 & (byte)x);
325 break;
326 } else {
327 data[wpointer++] = (byte) (128 | (byte)x);
328 x >>= 7;
329 }
330 }
8184302 @sorear Start draft of serialization/deserialization code
authored
331 }
332
19ada5b @sorear Implement variable-length coding for serialization
authored
333 public void Short(short x) { Long(x); }
334 public void Int(int x) { Long(x); }
8184302 @sorear Start draft of serialization/deserialization code
authored
335
8035d26 @sorear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
336 public void Double(double x) {
337 Long(BitConverter.DoubleToInt64Bits(x));
338 }
339
8184302 @sorear Start draft of serialization/deserialization code
authored
340 public void String(string s) {
341 if (s == null) {
342 Int(-1);
343 } else {
344 Int(s.Length);
345 foreach (char ch in s)
19ada5b @sorear Implement variable-length coding for serialization
authored
346 ULong((ulong)ch);
8184302 @sorear Start draft of serialization/deserialization code
authored
347 }
348 }
349
3dc4789 @sorear Implement freezing for types
authored
350 public void Strings(string[] s) {
351 if (s == null) Int(-1);
352 else {
353 Int(s.Length);
354 foreach (string ch in s) String(ch);
355 }
356 }
357
b1088dc @sorear implement serialization for SubInfo, LAD, LexInfo
authored
358 public void Ints(int[] s) {
359 if (s == null) {
360 Int(-1);
361 } else {
362 Int(s.Length);
363 foreach (int ch in s)
364 Int(ch);
365 }
366 }
367
dc6dd55 @sorear Implement serialization for Frame, finally kill off hashtable lexicals
authored
368 public void Refs<T> (T[] x) {
d91ecdf @sorear Serialization for objects of type Rat, FatRat, Complex, BigInteger, I…
authored
369 if (x == null) {
370 Int(-1);
371 } else {
372 Int(x.Length);
373 foreach (T y in x)
374 ObjRef(y);
375 }
376 }
377
dc6dd55 @sorear Implement serialization for Frame, finally kill off hashtable lexicals
authored
378 public void Refs<T> (IList<T> x) {
3dc4789 @sorear Implement freezing for types
authored
379 if (x == null) {
380 Int(-1);
381 } else {
382 Int(x.Count);
383 foreach (T y in x)
384 ObjRef(y);
385 }
386 }
387
d832c02 @sorear Second draft of serialization code
authored
388 // This is the main routine you should call from your Freeze
389 // callbacks to freeze an object
d91ecdf @sorear Serialization for objects of type Rat, FatRat, Complex, BigInteger, I…
authored
390 public void ObjRef(object o) {
d832c02 @sorear Second draft of serialization code
authored
391 int id;
392 SerUnit altunit;
19ada5b @sorear Implement variable-length coding for serialization
authored
393 if (Config.SerTrace)
394 Console.WriteLine("Saving {0} at {1}...", o, wpointer);
d832c02 @sorear Second draft of serialization code
authored
395 if (o == null) { // null pointers are special
396 Byte((byte)SerializationCode.Null);
397 return;
398 }
399
400 if (reg.CheckWriteObject(unit, o, out altunit, out id)) {
8184302 @sorear Start draft of serialization/deserialization code
authored
401 if (altunit == unit) {
402 Byte((byte)SerializationCode.SelfRef);
403 } else {
d832c02 @sorear Second draft of serialization code
authored
404 int altcode;
405 if (!unit_to_offset.TryGetValue(altunit, out altcode)) {
8184302 @sorear Start draft of serialization/deserialization code
authored
406 Byte((byte)SerializationCode.NewUnitRef);
b25256f @sorear Add Serialize.cs to build, fix build errors
authored
407 String(altunit.name);
d832c02 @sorear Second draft of serialization code
authored
408 // save the hash too so stale refs can be caught
409 foreach (byte b in altunit.hash) Byte(b);
410
8184302 @sorear Start draft of serialization/deserialization code
authored
411 unit_to_offset[altunit] = usedunits++;
412 } else {
413 Byte((byte)SerializationCode.ForeignRef);
d832c02 @sorear Second draft of serialization code
authored
414 Int(altcode);
8184302 @sorear Start draft of serialization/deserialization code
authored
415 }
416 }
417 Int((int)id);
418 } else {
d832c02 @sorear Second draft of serialization code
authored
419 // must take responsibility for saving the tag
d91ecdf @sorear Serialization for objects of type Rat, FatRat, Complex, BigInteger, I…
authored
420 IFreeze f = o as IFreeze;
421 if (f != null) {
422 f.Freeze(this);
423 } else {
424 FallbackFreeze(o);
425 }
426 }
427 }
428
cdb4548 @sorear Checkpoint of global-variable inventory
authored
429 [Immutable]
be108f9 @sorear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, b…
authored
430 internal static Type[] boxTypes = new Type[] {
431 null, typeof(Rat), typeof(FatRat), typeof(Complex),
7ae298f @sorear Make CC, LIHint serializable
authored
432 typeof(double), typeof(int), typeof(string), typeof(VarHash),
be108f9 @sorear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, b…
authored
433 typeof(Variable[]), typeof(VarDeque), typeof(STable),
434 };
cdb4548 @sorear Checkpoint of global-variable inventory
authored
435 [Immutable]
be108f9 @sorear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, b…
authored
436 internal static Func<P6opaque>[] boxCreate = new Func<P6opaque>[] {
437 P6opaque.Create, BoxObject<Rat>.Create, BoxObject<FatRat>.Create,
438 BoxObject<Complex>.Create, BoxObject<double>.Create,
439 BoxObject<int>.Create, BoxObject<string>.Create,
19ada5b @sorear Implement variable-length coding for serialization
authored
440 BoxObject<VarHash>.Create, BoxObject<Variable[]>.Create,
441 BoxObject<VarDeque>.Create, BoxObject<STable>.Create,
be108f9 @sorear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, b…
authored
442 };
cdb4548 @sorear Checkpoint of global-variable inventory
authored
443 [Immutable]
d91ecdf @sorear Serialization for objects of type Rat, FatRat, Complex, BigInteger, I…
authored
444 static Type[] anyTypes = new Type[] {
445 typeof(string), typeof(P6any[]), typeof(Variable[]),
7ae298f @sorear Make CC, LIHint serializable
authored
446 typeof(string[]), typeof(CC[]),
3f80fca @sorear A procedure for serializing ContextHandler et al
authored
447 typeof(bool), typeof(int), typeof(double), typeof(Type),
d91ecdf @sorear Serialization for objects of type Rat, FatRat, Complex, BigInteger, I…
authored
448 };
449
450 void FallbackFreeze(object o) {
451 int ix = 0;
452 Type t = o.GetType();
fe6e595 @sorear Thaw for SimpleVariable, StashEnt
authored
453 while (ix != anyTypes.Length && anyTypes[ix] != t) ix++;
1c5bb04 @sorear Small refactor to AssemblyBuilder setup, start thaw coding
authored
454 Byte((byte)(((int)SerializationCode.String) + ix));
d91ecdf @sorear Serialization for objects of type Rat, FatRat, Complex, BigInteger, I…
authored
455
456 switch(ix) {
457 case 0:
458 String((string)o);
459 break;
460 case 1:
461 Refs((P6any[])o);
462 break;
463 case 2:
464 Refs((Variable[])o);
465 break;
466 case 3:
7ae298f @sorear Make CC, LIHint serializable
authored
467 Refs((string[])o);
d91ecdf @sorear Serialization for objects of type Rat, FatRat, Complex, BigInteger, I…
authored
468 break;
469 case 4:
7ae298f @sorear Make CC, LIHint serializable
authored
470 Refs((CC[])o);
fe6e595 @sorear Thaw for SimpleVariable, StashEnt
authored
471 break;
472 case 5:
7ae298f @sorear Make CC, LIHint serializable
authored
473 Byte((byte)((bool)o ? 1 : 0));
d91ecdf @sorear Serialization for objects of type Rat, FatRat, Complex, BigInteger, I…
authored
474 break;
3f80fca @sorear A procedure for serializing ContextHandler et al
authored
475 case 6:
7ae298f @sorear Make CC, LIHint serializable
authored
476 Int((int)o);
477 break;
478 case 7:
479 Double((double)o);
480 break;
481 case 8:
3f80fca @sorear A procedure for serializing ContextHandler et al
authored
482 String(((Type)o).AssemblyQualifiedName);
483 break;
d91ecdf @sorear Serialization for objects of type Rat, FatRat, Complex, BigInteger, I…
authored
484 default:
485 throw new NotImplementedException(t.FullName);
8184302 @sorear Start draft of serialization/deserialization code
authored
486 }
487 }
488 }
489
490 // Note that this interface only handles freezing - thaw is done using
491 // a switch statement.
1993029 @sorear Start implementing serialization for our objects
authored
492 public interface IFreeze {
8184302 @sorear Start draft of serialization/deserialization code
authored
493 void Freeze(FreezeBuffer fb);
494 }
fe6e595 @sorear Thaw for SimpleVariable, StashEnt
authored
495 // implement this if you need to copy in data from other objects, &c
496 interface IFixup {
497 void Fixup();
498 }
8184302 @sorear Start draft of serialization/deserialization code
authored
499
500 class ThawBuffer {
501 byte[] data;
502 int rpointer;
503 ObjectRegistry reg;
504
d832c02 @sorear Second draft of serialization code
authored
505 SerUnit[] unit_map = new SerUnit[8];
8184302 @sorear Start draft of serialization/deserialization code
authored
506 int refed_units;
d832c02 @sorear Second draft of serialization code
authored
507 SerUnit unit;
8184302 @sorear Start draft of serialization/deserialization code
authored
508
fe6e595 @sorear Thaw for SimpleVariable, StashEnt
authored
509 List<IFixup> fixups_needed = new List<IFixup>();
2ff6525 @sorear Thaw routines for types
authored
510 List<object> revalidate = new List<object>();
fe6e595 @sorear Thaw for SimpleVariable, StashEnt
authored
511
288db48 @sorear Use precompiled IL when using a precompiled module
authored
512 public Type type;
513
b25256f @sorear Add Serialize.cs to build, fix build errors
authored
514 internal ThawBuffer(ObjectRegistry reg, SerUnit unit, byte[] data) {
8184302 @sorear Start draft of serialization/deserialization code
authored
515 this.data = data;
516 this.reg = reg;
d832c02 @sorear Second draft of serialization code
authored
517 this.unit = unit;
8184302 @sorear Start draft of serialization/deserialization code
authored
518 }
519
fe6e595 @sorear Thaw for SimpleVariable, StashEnt
authored
520 internal void RunFixups() {
2ff6525 @sorear Thaw routines for types
authored
521 P6how.BulkRevalidate(revalidate);
fe6e595 @sorear Thaw for SimpleVariable, StashEnt
authored
522 foreach (IFixup f in fixups_needed)
523 f.Fixup();
524 fixups_needed.Clear();
525 }
526
527 internal void PushFixup(IFixup f) {
528 fixups_needed.Add(f);
529 }
530
2ff6525 @sorear Thaw routines for types
authored
531 internal void PushRevalidate(STable f) {
532 revalidate.Add(f);
533 }
534
b25256f @sorear Add Serialize.cs to build, fix build errors
authored
535 public byte Byte() { return data[rpointer++]; }
536
19ada5b @sorear Implement variable-length coding for serialization
authored
537 public long Long() {
538 int shift = 0;
539 long accum = 0;
540 while (true) {
541 byte b = Byte();
542 accum |= (((long)(b & 127)) << shift);
543 shift += 7;
544 if ((b & 128) == 0) {
545 if ((b & 64) != 0) {
546 accum |= ((-1L) << shift);
547 }
548 //Console.WriteLine("Read {0} end {1}", accum, rpointer);
549 return accum;
550 }
551 }
b25256f @sorear Add Serialize.cs to build, fix build errors
authored
552 }
553
19ada5b @sorear Implement variable-length coding for serialization
authored
554 public ulong ULong() {
555 int shift = 0;
556 ulong accum = 0;
557 while (true) {
558 byte b = Byte();
559 accum |= (((ulong)(b & 127)) << shift);
560 shift += 7;
561 if ((b & 128) == 0) {
562 //Console.WriteLine("Read {0} end {1}", accum, rpointer);
563 return accum;
564 }
565 }
b25256f @sorear Add Serialize.cs to build, fix build errors
authored
566 }
567
19ada5b @sorear Implement variable-length coding for serialization
authored
568 public short Short() {
569 return checked((short)Long());
570 }
571
572 public int Int() {
573 return checked((int)Long());
b25256f @sorear Add Serialize.cs to build, fix build errors
authored
574 }
575
8035d26 @sorear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
576 public double Double() {
577 return BitConverter.Int64BitsToDouble(Long());
578 }
579
b25256f @sorear Add Serialize.cs to build, fix build errors
authored
580 public string String() {
581 int l = Int();
582
583 if (l < 0) return null;
584 char[] cb = new char[l];
585
586 for (int i = 0; i < l; i++)
19ada5b @sorear Implement variable-length coding for serialization
authored
587 cb[i] = (char)ULong();
b25256f @sorear Add Serialize.cs to build, fix build errors
authored
588
589 return new string(cb);
590 }
591
592 public byte[] Bytes(int k) {
593 byte[] buf = new byte[k];
594
595 for (int i = 0; i < k; i++)
596 buf[i] = Byte();
597
598 return buf;
599 }
600
1c5bb04 @sorear Small refactor to AssemblyBuilder setup, start thaw coding
authored
601 public List<T> RefsL<T>() where T : class {
602 int ct = Int();
603 if (ct < 0) return null;
604 List<T> ret = new List<T>();
605 for (int i = 0; i < ct; i++)
606 ret.Add((T) ObjRef());
607 return ret;
608 }
609
2ff6525 @sorear Thaw routines for types
authored
610 public int[] Ints() {
611 int ct = Int();
612 if (ct < 0) return null;
613 int[] ret = new int[ct];
614 for (int i = 0; i < ct; i++) ret[i] = Int();
615 return ret;
616 }
617
618 public string[] Strings() {
619 int ct = Int();
620 if (ct < 0) return null;
621 string[] ret = new string[ct];
622 for (int i = 0; i < ct; i++) ret[i] = String();
623 return ret;
624 }
625
1c5bb04 @sorear Small refactor to AssemblyBuilder setup, start thaw coding
authored
626 public T[] RefsA<T>() where T : class {
627 int ct = Int();
628 if (ct < 0) return null;
629 T[] ret = new T[ct];
630 for (int i = 0; i < ct; i++)
631 ret[i] = (T) ObjRef();
632 return ret;
633 }
634
604037a @sorear Fix generic thawing of array objects
authored
635 // used from ObjRef only so guaranteed non-null
636 T[] RefsARegister<T>() where T : class {
637 int ct = Int();
638 T[] ret = new T[ct];
639 Register(ret);
640 for (int i = 0; i < ct; i++)
641 ret[i] = (T) ObjRef();
642 return ret;
643 }
644
b25256f @sorear Add Serialize.cs to build, fix build errors
authored
645 public object ObjRef() {
8184302 @sorear Start draft of serialization/deserialization code
authored
646 var tag = (SerializationCode)Byte();
19ada5b @sorear Implement variable-length coding for serialization
authored
647 if (Config.SerTrace)
648 Console.WriteLine("Reading {0} from {1}...", tag, rpointer-1);
8184302 @sorear Start draft of serialization/deserialization code
authored
649 int i, j;
650 switch(tag) {
d832c02 @sorear Second draft of serialization code
authored
651 case SerializationCode.Null:
652 return null;
8035d26 @sorear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
653
8184302 @sorear Start draft of serialization/deserialization code
authored
654 case SerializationCode.ForeignRef:
655 i = Int();
656 j = Int();
d832c02 @sorear Second draft of serialization code
authored
657 return unit_map[i].bynum[j];
8035d26 @sorear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
658 case SerializationCode.SelfRef:
659 i = Int();
660 return unit.bynum[i];
8184302 @sorear Start draft of serialization/deserialization code
authored
661 case SerializationCode.NewUnitRef:
d832c02 @sorear Second draft of serialization code
authored
662 return LoadNewUnit();
8035d26 @sorear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
663
1c5bb04 @sorear Small refactor to AssemblyBuilder setup, start thaw coding
authored
664 case SerializationCode.RuntimeUnit:
665 return RuntimeUnit.Thaw(this);
2671ab4 @sorear Add thaw routine for SubInfo
authored
666 case SerializationCode.SubInfo:
667 return SubInfo.Thaw(this);
2ff6525 @sorear Thaw routines for types
authored
668 case SerializationCode.STable:
669 return STable.Thaw(this);
fe6e595 @sorear Thaw for SimpleVariable, StashEnt
authored
670 case SerializationCode.StashEnt:
671 return StashEnt.Thaw(this);
8035d26 @sorear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
672 case SerializationCode.Rat:
673 return Rat.Thaw(this);
674 case SerializationCode.FatRat:
675 return FatRat.Thaw(this);
676 case SerializationCode.Complex:
677 return Complex.Thaw(this);
678 case SerializationCode.BigInteger:
679 return BigInteger.Thaw(this);
680 case SerializationCode.VarDeque:
681 return VarDeque.Thaw(this);
682 case SerializationCode.VarHash:
683 return VarHash.Thaw(this);
be108f9 @sorear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, b…
authored
684 case SerializationCode.DispatchEnt:
685 return DispatchEnt.Thaw(this);
8035d26 @sorear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
686 //case SerializationCode.RxFrame:
687 // return RxFrame.Thaw(this);
2ff6525 @sorear Thaw routines for types
authored
688 case SerializationCode.P6how:
689 return P6how.Thaw(this);
7ae298f @sorear Make CC, LIHint serializable
authored
690 case SerializationCode.CC:
691 return CC.Thaw(this);
e7d3f3f @sorear Reimplement regex_infix:<|> table generation
authored
692 case SerializationCode.AltInfo:
693 return AltInfo.Thaw(this);
8035d26 @sorear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
694
3f80fca @sorear A procedure for serializing ContextHandler et al
authored
695 case SerializationCode.ReflectObj:
696 return ReflectObj.Thaw(this);
be108f9 @sorear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, b…
authored
697 case SerializationCode.P6opaque:
698 return P6opaque.Thaw(this);
9b6504a @sorear Thaw routines for Frame
authored
699 case SerializationCode.Frame:
700 return Frame.Thaw(this);
8035d26 @sorear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
701 //Cursor,
702
be108f9 @sorear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, b…
authored
703 case SerializationCode.String:
704 return Register(String());
705 case SerializationCode.ArrP6any:
604037a @sorear Fix generic thawing of array objects
authored
706 return RefsARegister<P6any>();
be108f9 @sorear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, b…
authored
707 case SerializationCode.ArrVariable:
604037a @sorear Fix generic thawing of array objects
authored
708 return RefsARegister<Variable>();
7ae298f @sorear Make CC, LIHint serializable
authored
709 case SerializationCode.ArrString:
604037a @sorear Fix generic thawing of array objects
authored
710 return RefsARegister<string>();
7ae298f @sorear Make CC, LIHint serializable
authored
711 case SerializationCode.ArrCC:
604037a @sorear Fix generic thawing of array objects
authored
712 return RefsARegister<CC>();
be108f9 @sorear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, b…
authored
713 case SerializationCode.Boolean:
714 return Register(Byte() != 0);
715 case SerializationCode.Int:
716 return Register(Int());
717 case SerializationCode.Double:
718 return Register(Double());
719 case SerializationCode.Type:
720 return Register(Type.GetType(String(), true));
8035d26 @sorear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
721
fe6e595 @sorear Thaw for SimpleVariable, StashEnt
authored
722 case SerializationCode.SimpleVariable:
723 case SerializationCode.SimpleVariable_1:
724 case SerializationCode.SimpleVariable_2:
725 case SerializationCode.SimpleVariable_3:
726 return SimpleVariable.Thaw(this,
727 (int)tag - (int)SerializationCode.SimpleVariable);
054561b @sorear Thaw code for all LAD, Variable, ViviHook subclasses
authored
728 case SerializationCode.SubstrLValue:
729 return SubstrLValue.Thaw(this);
730 case SerializationCode.TiedVariable:
731 return TiedVariable.Thaw(this);
732
733 case SerializationCode.SubViviHook:
734 return SubViviHook.Thaw(this);
735 case SerializationCode.ArrayViviHook:
736 return ArrayViviHook.Thaw(this);
737 case SerializationCode.NewArrayViviHook:
738 return NewArrayViviHook.Thaw(this);
739 case SerializationCode.HashViviHook:
740 return HashViviHook.Thaw(this);
741 case SerializationCode.NewHashViviHook:
742 return NewHashViviHook.Thaw(this);
743
744 case SerializationCode.LADNone:
745 return Register(new LADNone());
746 case SerializationCode.LADNull:
747 return Register(new LADNull());
748 case SerializationCode.LADDot:
749 return Register(new LADDot());
750 case SerializationCode.LADDispatcher:
751 return Register(new LADDispatcher());
752 case SerializationCode.LADImp:
753 return Register(new LADImp());
754 case SerializationCode.LADStr:
755 return LADStr.Thaw(this);
756 case SerializationCode.LADStrNoCase:
757 return LADStrNoCase.Thaw(this);
758 case SerializationCode.LADMethod:
759 return LADMethod.Thaw(this);
760 case SerializationCode.LADParam:
761 return LADParam.Thaw(this);
762 case SerializationCode.LADOpt:
763 return LADOpt.Thaw(this);
764 case SerializationCode.LADPlus:
765 return LADPlus.Thaw(this);
766 case SerializationCode.LADStar:
767 return LADStar.Thaw(this);
768 case SerializationCode.LADSequence:
769 return LADSequence.Thaw(this);
770 case SerializationCode.LADAny:
771 return LADAny.Thaw(this);
772 case SerializationCode.LADCC:
773 return LADCC.Thaw(this);
8184302 @sorear Start draft of serialization/deserialization code
authored
774 default:
1c5bb04 @sorear Small refactor to AssemblyBuilder setup, start thaw coding
authored
775 throw new ThawException("unexpected object tag " + tag);
8184302 @sorear Start draft of serialization/deserialization code
authored
776 }
777 }
d832c02 @sorear Second draft of serialization code
authored
778
1c5bb04 @sorear Small refactor to AssemblyBuilder setup, start thaw coding
authored
779 // call this when thawing any new object
be108f9 @sorear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, b…
authored
780 internal object Register(object o) {
1c5bb04 @sorear Small refactor to AssemblyBuilder setup, start thaw coding
authored
781 reg.RegisterThawed(unit, o);
be108f9 @sorear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, b…
authored
782 return o;
1c5bb04 @sorear Small refactor to AssemblyBuilder setup, start thaw coding
authored
783 }
784
d832c02 @sorear Second draft of serialization code
authored
785 object LoadNewUnit() {
786 string name = String();
787 if (refed_units == unit_map.Length)
788 Array.Resize(ref unit_map, refed_units * 2);
789
790 SerUnit su = reg.LoadUnit(name);
791 unit_map[refed_units++] = su;
792
793 byte[] hash = Bytes(su.hash.Length);
794
795 for (int i = 0; i < hash.Length; i++)
796 if (hash[i] != su.hash[i])
797 goto badhash;
798
799 int ix = Int();
800 return su.bynum[ix];
801
802 badhash:
eee0cbb @sorear Add framework for detecting stale precompiled modules
authored
803 throw new ThawException(string.Format("Hash mismatch for " +
804 "unit {0} referenced from {1}, wanted {2}, got {3}",
805 su.name, unit.name, Utils.HashToStr(unit.hash),
806 Utils.HashToStr(su.hash)));
d832c02 @sorear Second draft of serialization code
authored
807 }
808 }
809
810 // Thrown to indicate data format problems in the serialized stream
811 // Not necessarily bugs; could also indicate stale files, including
812 // cases where the data format is changed and cases where a depended
813 // file was recreated
814 class ThawException : Exception {
815 public ThawException(string s) : base(s) { }
816 public ThawException() : base() { }
8184302 @sorear Start draft of serialization/deserialization code
authored
817 }
3f80fca @sorear A procedure for serializing ContextHandler et al
authored
818
819 public class ReflectObj : IFreeze {
820 protected virtual object[] GetData() { return new object[0]; }
821 protected virtual void SetData(object[] a) { }
822 void IFreeze.Freeze(FreezeBuffer fb) {
823 fb.Byte((byte)SerializationCode.ReflectObj);
824 fb.String(GetType().AssemblyQualifiedName);
825 fb.Refs(GetData());
826 }
827
828 internal static ReflectObj Thaw(ThawBuffer tb) {
829 Type nt = Type.GetType(tb.String());
830 ReflectObj n = (ReflectObj)
831 nt.GetConstructor(new Type[0]).Invoke(null, new object[0]);
832 tb.Register(n);
833 n.SetData(tb.RefsA<object>());
834 return n;
835 }
836 }
8184302 @sorear Start draft of serialization/deserialization code
authored
837 }
Something went wrong with that request. Please try again.