Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 838 lines (727 sloc) 27.43 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;
9083142 Stefan O'Rear Switch to single-AppDomain execution
authored
6 using Niecza.CLRBackend;
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
7
cdde7e0 Stefan O'Rear 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 Stefan O'Rear 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 Stefan O'Rear Second draft of serialization code
authored
36
37 // Note, the serialization subsystem is *NOT* thread safe !
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
38 namespace Niecza.Serialization {
d832c02 Stefan O'Rear 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 Stefan O'Rear Wire up serializer to run after pre-compiler
authored
44 internal object[] bynum = new object[8]; // objects in unit
d832c02 Stefan O'Rear Second draft of serialization code
authored
45 internal object root; // the RuntimeUnit object
8ed36ea Stefan O'Rear Wire up serializer to run after pre-compiler
authored
46 internal int nobj; // = 0
d832c02 Stefan O'Rear Second draft of serialization code
authored
47 }
8184302 Stefan O'Rear 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 Stefan O'Rear 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 Stefan O'Rear Add Serialize.cs to build, fix build errors
authored
56 public SerUnit unit;
57 public int id;
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
58 }
d832c02 Stefan O'Rear Second draft of serialization code
authored
59 Dictionary<object,ObjRef> byref = new Dictionary<object,ObjRef>();
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
60
d832c02 Stefan O'Rear Second draft of serialization code
authored
61 Dictionary<string,SerUnit> units =
62 new Dictionary<string,SerUnit>();
63
cdb4548 Stefan O'Rear Checkpoint of global-variable inventory
authored
64 internal static HashAlgorithm NewHash() { return new SHA256Managed(); }
65
d832c02 Stefan O'Rear 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 Stefan O'Rear Start draft of serialization/deserialization code
authored
76 return true;
d832c02 Stefan O'Rear Second draft of serialization code
authored
77 }
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
78
d832c02 Stefan O'Rear Second draft of serialization code
authored
79 if (into.nobj == into.bynum.Length)
80 Array.Resize(ref into.bynum, into.nobj * 2);
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
81
b25256f Stefan O'Rear Add Serialize.cs to build, fix build errors
authored
82 or.unit = lui = into;
d832c02 Stefan O'Rear Second draft of serialization code
authored
83 id = or.id = into.nobj++;
84 into.bynum[id] = o;
85
86 byref[o] = or;
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
87
88 return false;
89 }
d832c02 Stefan O'Rear Second draft of serialization code
authored
90
1c5bb04 Stefan O'Rear 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 Stefan O'Rear 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 Stefan O'Rear Switch to single-AppDomain execution
authored
115 string file = Path.Combine(Backend.obj_dir, Backend.prefix +
116 name.Replace("::",".") + ".ser");
d832c02 Stefan O'Rear Second draft of serialization code
authored
117 byte[] bytes = File.ReadAllBytes(file);
118
119 su = new SerUnit();
120 su.name = name;
cdb4548 Stefan O'Rear Checkpoint of global-variable inventory
authored
121 su.hash = NewHash().ComputeHash(bytes);
d832c02 Stefan O'Rear Second draft of serialization code
authored
122
b25256f Stefan O'Rear Add Serialize.cs to build, fix build errors
authored
123 ThawBuffer tb = new ThawBuffer(this, su, bytes);
d832c02 Stefan O'Rear Second draft of serialization code
authored
124
8ed36ea Stefan O'Rear Wire up serializer to run after pre-compiler
authored
125 units[name] = su;
d832c02 Stefan O'Rear 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 Stefan O'Rear Add Serialize.cs to build, fix build errors
authored
135 su.root = tb.ObjRef();
c0af787 Stefan O'Rear Fix fixup call order (oops!), serialization-compatible calling of phaser...
authored
136 tb.RunFixups();
d832c02 Stefan O'Rear 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 Stefan O'Rear Wire up serializer to run after pre-compiler
authored
149 if (!units.ContainsKey(name))
150 return;
d832c02 Stefan O'Rear 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 Stefan O'Rear Add Serialize.cs to build, fix build errors
authored
164 throw new InvalidOperationException("unit " +name+ " exists");
d832c02 Stefan O'Rear Second draft of serialization code
authored
165
166 bool success = false;
9083142 Stefan O'Rear Switch to single-AppDomain execution
authored
167 string file = Path.Combine(Backend.obj_dir, Backend.prefix +
168 name.Replace("::",".") + ".ser");
d832c02 Stefan O'Rear Second draft of serialization code
authored
169
170 FreezeBuffer fb = new FreezeBuffer(this, su);
171
8ed36ea Stefan O'Rear Wire up serializer to run after pre-compiler
authored
172 units[name] = su;
173
d832c02 Stefan O'Rear 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 Stefan O'Rear Checkpoint of global-variable inventory
authored
180 su.hash = NewHash().ComputeHash(data);
d832c02 Stefan O'Rear 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 Stefan O'Rear Start draft of serialization/deserialization code
authored
190 }
191
192 // One of these codes is written at the beginning of every object ref
1993029 Stefan O'Rear Start implementing serialization for our objects
authored
193 enum SerializationCode : byte {
d832c02 Stefan O'Rear Second draft of serialization code
authored
194 // special
195 Null,
196
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
197 // existing objects
198 ForeignRef,
199 SelfRef,
200 NewUnitRef,
1993029 Stefan O'Rear Start implementing serialization for our objects
authored
201
202 // types of new object
203 RuntimeUnit,
204 SubInfo,
205 STable,
206 StashEnt,
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
207 Rat,
208 FatRat,
209 Complex,
210 BigInteger,
211 VarDeque,
212 VarHash,
dc6dd55 Stefan O'Rear Implement serialization for Frame, finally kill off hashtable lexicals
authored
213 DispatchEnt,
214 RxFrame,
215 P6how,
3f80fca Stefan O'Rear A procedure for serializing ContextHandler et al
authored
216 ReflectObj,
7ae298f Stefan O'Rear Make CC, LIHint serializable
authored
217 CC,
218 AltInfo,
1993029 Stefan O'Rear Start implementing serialization for our objects
authored
219
220 // types of P6any-reified object
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
221 P6opaque, // eventually let's specialize this
1993029 Stefan O'Rear Start implementing serialization for our objects
authored
222 Frame,
223 Cursor,
224
1c5bb04 Stefan O'Rear 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 Stefan O'Rear Make CC, LIHint serializable
authored
229 ArrString,
230 ArrCC,
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
231 Boolean,
1c5bb04 Stefan O'Rear Small refactor to AssemblyBuilder setup, start thaw coding
authored
232 Int,
233 Double,
3f80fca Stefan O'Rear A procedure for serializing ContextHandler et al
authored
234 Type,
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
235
ab35238 Stefan O'Rear Tidy up STable fields a bit, add TiedVariable serialize
authored
236 // variables
1c5bb04 Stefan O'Rear Small refactor to AssemblyBuilder setup, start thaw coding
authored
237 SimpleVariable, // allow 4 for flags
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
238 SimpleVariable_1,
239 SimpleVariable_2,
240 SimpleVariable_3,
241 SubstrLValue,
ab35238 Stefan O'Rear Tidy up STable fields a bit, add TiedVariable serialize
authored
242 TiedVariable,
1993029 Stefan O'Rear Start implementing serialization for our objects
authored
243
244 // vivification hooks
ab35238 Stefan O'Rear Tidy up STable fields a bit, add TiedVariable serialize
authored
245 SubViviHook,
1993029 Stefan O'Rear Start implementing serialization for our objects
authored
246 ArrayViviHook,
247 NewArrayViviHook,
248 HashViviHook,
249 NewHashViviHook,
b1088dc Stefan O'Rear 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 Stefan O'Rear Start draft of serialization/deserialization code
authored
267 }
268
269 // An instance of this class is used to serialize serialization units
1993029 Stefan O'Rear Start implementing serialization for our objects
authored
270 public class FreezeBuffer {
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
271 byte[] data;
272 int wpointer;
273
d832c02 Stefan O'Rear Second draft of serialization code
authored
274 Dictionary<SerUnit,int> unit_to_offset;
275 int usedunits;
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
276
277 ObjectRegistry reg;
d832c02 Stefan O'Rear Second draft of serialization code
authored
278 SerUnit unit;
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
279
d832c02 Stefan O'Rear Second draft of serialization code
authored
280 internal FreezeBuffer(ObjectRegistry reg, SerUnit unit) {
8ed36ea Stefan O'Rear Wire up serializer to run after pre-compiler
authored
281 if (reg == null || unit == null)
282 throw new ArgumentNullException();
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
283 this.reg = reg;
d832c02 Stefan O'Rear Second draft of serialization code
authored
284 this.unit = unit;
285 unit_to_offset = new Dictionary<SerUnit,int>();
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
286 data = new byte[256];
287 }
288
b25256f Stefan O'Rear 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 Stefan O'Rear 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 Stefan O'Rear 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 Stefan O'Rear Start draft of serialization/deserialization code
authored
317 }
318
19ada5b Stefan O'Rear 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 Stefan O'Rear Start draft of serialization/deserialization code
authored
331 }
332
19ada5b Stefan O'Rear Implement variable-length coding for serialization
authored
333 public void Short(short x) { Long(x); }
334 public void Int(int x) { Long(x); }
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
335
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
336 public void Double(double x) {
337 Long(BitConverter.DoubleToInt64Bits(x));
338 }
339
8184302 Stefan O'Rear 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 Stefan O'Rear Implement variable-length coding for serialization
authored
346 ULong((ulong)ch);
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
347 }
348 }
349
3dc4789 Stefan O'Rear 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 Stefan O'Rear 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 Stefan O'Rear Implement serialization for Frame, finally kill off hashtable lexicals
authored
368 public void Refs<T> (T[] x) {
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
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 Stefan O'Rear Implement serialization for Frame, finally kill off hashtable lexicals
authored
378 public void Refs<T> (IList<T> x) {
3dc4789 Stefan O'Rear 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 Stefan O'Rear 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 Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
390 public void ObjRef(object o) {
d832c02 Stefan O'Rear Second draft of serialization code
authored
391 int id;
392 SerUnit altunit;
19ada5b Stefan O'Rear Implement variable-length coding for serialization
authored
393 if (Config.SerTrace)
394 Console.WriteLine("Saving {0} at {1}...", o, wpointer);
d832c02 Stefan O'Rear 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 Stefan O'Rear Start draft of serialization/deserialization code
authored
401 if (altunit == unit) {
402 Byte((byte)SerializationCode.SelfRef);
403 } else {
d832c02 Stefan O'Rear Second draft of serialization code
authored
404 int altcode;
405 if (!unit_to_offset.TryGetValue(altunit, out altcode)) {
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
406 Byte((byte)SerializationCode.NewUnitRef);
b25256f Stefan O'Rear Add Serialize.cs to build, fix build errors
authored
407 String(altunit.name);
d832c02 Stefan O'Rear 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 Stefan O'Rear Start draft of serialization/deserialization code
authored
411 unit_to_offset[altunit] = usedunits++;
412 } else {
413 Byte((byte)SerializationCode.ForeignRef);
d832c02 Stefan O'Rear Second draft of serialization code
authored
414 Int(altcode);
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
415 }
416 }
417 Int((int)id);
418 } else {
d832c02 Stefan O'Rear Second draft of serialization code
authored
419 // must take responsibility for saving the tag
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
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 Stefan O'Rear Checkpoint of global-variable inventory
authored
429 [Immutable]
be108f9 Stefan O'Rear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, bool...
authored
430 internal static Type[] boxTypes = new Type[] {
431 null, typeof(Rat), typeof(FatRat), typeof(Complex),
7ae298f Stefan O'Rear Make CC, LIHint serializable
authored
432 typeof(double), typeof(int), typeof(string), typeof(VarHash),
be108f9 Stefan O'Rear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, bool...
authored
433 typeof(Variable[]), typeof(VarDeque), typeof(STable),
434 };
cdb4548 Stefan O'Rear Checkpoint of global-variable inventory
authored
435 [Immutable]
be108f9 Stefan O'Rear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, bool...
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 Stefan O'Rear Implement variable-length coding for serialization
authored
440 BoxObject<VarHash>.Create, BoxObject<Variable[]>.Create,
441 BoxObject<VarDeque>.Create, BoxObject<STable>.Create,
be108f9 Stefan O'Rear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, bool...
authored
442 };
cdb4548 Stefan O'Rear Checkpoint of global-variable inventory
authored
443 [Immutable]
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
444 static Type[] anyTypes = new Type[] {
445 typeof(string), typeof(P6any[]), typeof(Variable[]),
7ae298f Stefan O'Rear Make CC, LIHint serializable
authored
446 typeof(string[]), typeof(CC[]),
3f80fca Stefan O'Rear A procedure for serializing ContextHandler et al
authored
447 typeof(bool), typeof(int), typeof(double), typeof(Type),
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
448 };
449
450 void FallbackFreeze(object o) {
451 int ix = 0;
452 Type t = o.GetType();
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
453 while (ix != anyTypes.Length && anyTypes[ix] != t) ix++;
1c5bb04 Stefan O'Rear Small refactor to AssemblyBuilder setup, start thaw coding
authored
454 Byte((byte)(((int)SerializationCode.String) + ix));
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
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 Stefan O'Rear Make CC, LIHint serializable
authored
467 Refs((string[])o);
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
468 break;
469 case 4:
7ae298f Stefan O'Rear Make CC, LIHint serializable
authored
470 Refs((CC[])o);
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
471 break;
472 case 5:
7ae298f Stefan O'Rear Make CC, LIHint serializable
authored
473 Byte((byte)((bool)o ? 1 : 0));
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
474 break;
3f80fca Stefan O'Rear A procedure for serializing ContextHandler et al
authored
475 case 6:
7ae298f Stefan O'Rear Make CC, LIHint serializable
authored
476 Int((int)o);
477 break;
478 case 7:
479 Double((double)o);
480 break;
481 case 8:
3f80fca Stefan O'Rear A procedure for serializing ContextHandler et al
authored
482 String(((Type)o).AssemblyQualifiedName);
483 break;
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
484 default:
485 throw new NotImplementedException(t.FullName);
8184302 Stefan O'Rear 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 Stefan O'Rear Start implementing serialization for our objects
authored
492 public interface IFreeze {
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
493 void Freeze(FreezeBuffer fb);
494 }
fe6e595 Stefan O'Rear 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 Stefan O'Rear Start draft of serialization/deserialization code
authored
499
500 class ThawBuffer {
501 byte[] data;
502 int rpointer;
503 ObjectRegistry reg;
504
d832c02 Stefan O'Rear Second draft of serialization code
authored
505 SerUnit[] unit_map = new SerUnit[8];
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
506 int refed_units;
d832c02 Stefan O'Rear Second draft of serialization code
authored
507 SerUnit unit;
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
508
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
509 List<IFixup> fixups_needed = new List<IFixup>();
2ff6525 Stefan O'Rear Thaw routines for types
authored
510 List<object> revalidate = new List<object>();
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
511
288db48 Stefan O'Rear Use precompiled IL when using a precompiled module
authored
512 public Type type;
513
b25256f Stefan O'Rear Add Serialize.cs to build, fix build errors
authored
514 internal ThawBuffer(ObjectRegistry reg, SerUnit unit, byte[] data) {
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
515 this.data = data;
516 this.reg = reg;
d832c02 Stefan O'Rear Second draft of serialization code
authored
517 this.unit = unit;
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
518 }
519
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
520 internal void RunFixups() {
2ff6525 Stefan O'Rear Thaw routines for types
authored
521 P6how.BulkRevalidate(revalidate);
fe6e595 Stefan O'Rear 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 Stefan O'Rear Thaw routines for types
authored
531 internal void PushRevalidate(STable f) {
532 revalidate.Add(f);
533 }
534
b25256f Stefan O'Rear Add Serialize.cs to build, fix build errors
authored
535 public byte Byte() { return data[rpointer++]; }
536
19ada5b Stefan O'Rear 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 Stefan O'Rear Add Serialize.cs to build, fix build errors
authored
552 }
553
19ada5b Stefan O'Rear 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 Stefan O'Rear Add Serialize.cs to build, fix build errors
authored
566 }
567
19ada5b Stefan O'Rear 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 Stefan O'Rear Add Serialize.cs to build, fix build errors
authored
574 }
575
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
576 public double Double() {
577 return BitConverter.Int64BitsToDouble(Long());
578 }
579
b25256f Stefan O'Rear 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 Stefan O'Rear Implement variable-length coding for serialization
authored
587 cb[i] = (char)ULong();
b25256f Stefan O'Rear 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 Stefan O'Rear 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 Stefan O'Rear 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 Stefan O'Rear 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 Stefan O'Rear 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 Stefan O'Rear Add Serialize.cs to build, fix build errors
authored
645 public object ObjRef() {
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
646 var tag = (SerializationCode)Byte();
19ada5b Stefan O'Rear Implement variable-length coding for serialization
authored
647 if (Config.SerTrace)
648 Console.WriteLine("Reading {0} from {1}...", tag, rpointer-1);
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
649 int i, j;
650 switch(tag) {
d832c02 Stefan O'Rear Second draft of serialization code
authored
651 case SerializationCode.Null:
652 return null;
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
653
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
654 case SerializationCode.ForeignRef:
655 i = Int();
656 j = Int();
d832c02 Stefan O'Rear Second draft of serialization code
authored
657 return unit_map[i].bynum[j];
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
658 case SerializationCode.SelfRef:
659 i = Int();
660 return unit.bynum[i];
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
661 case SerializationCode.NewUnitRef:
d832c02 Stefan O'Rear Second draft of serialization code
authored
662 return LoadNewUnit();
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
663
1c5bb04 Stefan O'Rear Small refactor to AssemblyBuilder setup, start thaw coding
authored
664 case SerializationCode.RuntimeUnit:
665 return RuntimeUnit.Thaw(this);
2671ab4 Stefan O'Rear Add thaw routine for SubInfo
authored
666 case SerializationCode.SubInfo:
667 return SubInfo.Thaw(this);
2ff6525 Stefan O'Rear Thaw routines for types
authored
668 case SerializationCode.STable:
669 return STable.Thaw(this);
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
670 case SerializationCode.StashEnt:
671 return StashEnt.Thaw(this);
8035d26 Stefan O'Rear 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 Stefan O'Rear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, bool...
authored
684 case SerializationCode.DispatchEnt:
685 return DispatchEnt.Thaw(this);
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
686 //case SerializationCode.RxFrame:
687 // return RxFrame.Thaw(this);
2ff6525 Stefan O'Rear Thaw routines for types
authored
688 case SerializationCode.P6how:
689 return P6how.Thaw(this);
7ae298f Stefan O'Rear Make CC, LIHint serializable
authored
690 case SerializationCode.CC:
691 return CC.Thaw(this);
e7d3f3f Stefan O'Rear Reimplement regex_infix:<|> table generation
authored
692 case SerializationCode.AltInfo:
693 return AltInfo.Thaw(this);
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
694
3f80fca Stefan O'Rear A procedure for serializing ContextHandler et al
authored
695 case SerializationCode.ReflectObj:
696 return ReflectObj.Thaw(this);
be108f9 Stefan O'Rear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, bool...
authored
697 case SerializationCode.P6opaque:
698 return P6opaque.Thaw(this);
9b6504a Stefan O'Rear Thaw routines for Frame
authored
699 case SerializationCode.Frame:
700 return Frame.Thaw(this);
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
701 //Cursor,
702
be108f9 Stefan O'Rear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, bool...
authored
703 case SerializationCode.String:
704 return Register(String());
705 case SerializationCode.ArrP6any:
604037a Stefan O'Rear Fix generic thawing of array objects
authored
706 return RefsARegister<P6any>();
be108f9 Stefan O'Rear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, bool...
authored
707 case SerializationCode.ArrVariable:
604037a Stefan O'Rear Fix generic thawing of array objects
authored
708 return RefsARegister<Variable>();
7ae298f Stefan O'Rear Make CC, LIHint serializable
authored
709 case SerializationCode.ArrString:
604037a Stefan O'Rear Fix generic thawing of array objects
authored
710 return RefsARegister<string>();
7ae298f Stefan O'Rear Make CC, LIHint serializable
authored
711 case SerializationCode.ArrCC:
604037a Stefan O'Rear Fix generic thawing of array objects
authored
712 return RefsARegister<CC>();
be108f9 Stefan O'Rear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, bool...
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 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
721
fe6e595 Stefan O'Rear 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 Stefan O'Rear 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 Stefan O'Rear Start draft of serialization/deserialization code
authored
774 default:
1c5bb04 Stefan O'Rear Small refactor to AssemblyBuilder setup, start thaw coding
authored
775 throw new ThawException("unexpected object tag " + tag);
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
776 }
777 }
d832c02 Stefan O'Rear Second draft of serialization code
authored
778
1c5bb04 Stefan O'Rear Small refactor to AssemblyBuilder setup, start thaw coding
authored
779 // call this when thawing any new object
be108f9 Stefan O'Rear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, bool...
authored
780 internal object Register(object o) {
1c5bb04 Stefan O'Rear Small refactor to AssemblyBuilder setup, start thaw coding
authored
781 reg.RegisterThawed(unit, o);
be108f9 Stefan O'Rear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, bool...
authored
782 return o;
1c5bb04 Stefan O'Rear Small refactor to AssemblyBuilder setup, start thaw coding
authored
783 }
784
d832c02 Stefan O'Rear 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 Stefan O'Rear 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 Stefan O'Rear 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 Stefan O'Rear Start draft of serialization/deserialization code
authored
817 }
3f80fca Stefan O'Rear 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 Stefan O'Rear Start draft of serialization/deserialization code
authored
837 }
Something went wrong with that request. Please try again.