Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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