Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 755 lines (646 sloc) 23.973 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
63 static readonly HashAlgorithm hash = SHA256.Create();
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
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
133 tb.RunFixups();
b25256f Stefan O'Rear Add Serialize.cs to build, fix build errors
authored
134 su.root = tb.ObjRef();
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,
1993029 Stefan O'Rear Start implementing serialization for our objects
authored
215
216 // types of P6any-reified object
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
217 P6opaque, // eventually let's specialize this
1993029 Stefan O'Rear Start implementing serialization for our objects
authored
218 Frame,
219 Cursor,
220
1c5bb04 Stefan O'Rear Small refactor to AssemblyBuilder setup, start thaw coding
authored
221 // miscellany - keep these in same order as FallbackFreeze
222 String,
223 ArrP6any,
224 ArrVariable,
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
225 Boolean,
1c5bb04 Stefan O'Rear Small refactor to AssemblyBuilder setup, start thaw coding
authored
226 Int,
227 Double,
3f80fca Stefan O'Rear A procedure for serializing ContextHandler et al
authored
228 Type,
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
229
ab35238 Stefan O'Rear Tidy up STable fields a bit, add TiedVariable serialize
authored
230 // variables
1c5bb04 Stefan O'Rear Small refactor to AssemblyBuilder setup, start thaw coding
authored
231 SimpleVariable, // allow 4 for flags
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
232 SimpleVariable_1,
233 SimpleVariable_2,
234 SimpleVariable_3,
235 SubstrLValue,
ab35238 Stefan O'Rear Tidy up STable fields a bit, add TiedVariable serialize
authored
236 TiedVariable,
1993029 Stefan O'Rear Start implementing serialization for our objects
authored
237
238 // vivification hooks
ab35238 Stefan O'Rear Tidy up STable fields a bit, add TiedVariable serialize
authored
239 SubViviHook,
1993029 Stefan O'Rear Start implementing serialization for our objects
authored
240 ArrayViviHook,
241 NewArrayViviHook,
242 HashViviHook,
243 NewHashViviHook,
b1088dc Stefan O'Rear implement serialization for SubInfo, LAD, LexInfo
authored
244
245 // Longest-token automaton descriptors
246 LADNone, // no-args
247 LADNull,
248 LADDot,
249 LADDispatcher,
250 LADImp,
251 LADStr, // string
252 LADStrNoCase,
253 LADMethod,
254 LADParam,
255 LADOpt, // LAD
256 LADPlus,
257 LADStar,
258 LADSequence, // LAD[]
259 LADAny,
260 LADCC, // CC
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
261 }
262
263 // An instance of this class is used to serialize serialization units
1993029 Stefan O'Rear Start implementing serialization for our objects
authored
264 public class FreezeBuffer {
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
265 byte[] data;
266 int wpointer;
267
d832c02 Stefan O'Rear Second draft of serialization code
authored
268 Dictionary<SerUnit,int> unit_to_offset;
269 int usedunits;
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
270
271 ObjectRegistry reg;
d832c02 Stefan O'Rear Second draft of serialization code
authored
272 SerUnit unit;
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
273
d832c02 Stefan O'Rear Second draft of serialization code
authored
274 internal FreezeBuffer(ObjectRegistry reg, SerUnit unit) {
8ed36ea Stefan O'Rear Wire up serializer to run after pre-compiler
authored
275 if (reg == null || unit == null)
276 throw new ArgumentNullException();
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
277 this.reg = reg;
d832c02 Stefan O'Rear Second draft of serialization code
authored
278 this.unit = unit;
279 unit_to_offset = new Dictionary<SerUnit,int>();
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
280 data = new byte[256];
281 }
282
b25256f Stefan O'Rear Add Serialize.cs to build, fix build errors
authored
283 internal byte[] GetData() {
284 byte[] ret = new byte[wpointer];
285 Array.Copy(data, ret, ret.Length);
286 return ret;
287 }
288
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
289 void Ensure(int ct) {
290 while (ct + wpointer > data.Length)
291 Array.Resize(ref data, data.Length * 2);
292 }
293
294 public void Byte(byte x) {
295 Ensure(1);
296 data[wpointer++] = x;
297 }
298
299 public void Short(short x) {
300 Ensure(2);
301 data[wpointer++] = (byte)(x >> 8);
302 data[wpointer++] = (byte)(x );
303 }
304
305 public void Int(int x) {
306 Ensure(4);
307 data[wpointer++] = (byte)(x >> 24);
308 data[wpointer++] = (byte)(x >> 16);
309 data[wpointer++] = (byte)(x >> 8);
310 data[wpointer++] = (byte)(x );
311 }
312
313 public void Long(long x) {
314 Ensure(8);
315 data[wpointer++] = (byte)(x >> 56);
316 data[wpointer++] = (byte)(x >> 48);
317 data[wpointer++] = (byte)(x >> 40);
318 data[wpointer++] = (byte)(x >> 32);
319 data[wpointer++] = (byte)(x >> 24);
320 data[wpointer++] = (byte)(x >> 16);
321 data[wpointer++] = (byte)(x >> 8);
322 data[wpointer++] = (byte)(x );
323 }
324
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
325 public void Double(double x) {
326 Long(BitConverter.DoubleToInt64Bits(x));
327 }
328
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
329 public void String(string s) {
330 if (s == null) {
331 Int(-1);
332 } else {
333 Int(s.Length);
334 foreach (char ch in s)
335 Short((short)ch);
336 }
337 }
338
3dc4789 Stefan O'Rear Implement freezing for types
authored
339 public void Strings(string[] s) {
340 if (s == null) Int(-1);
341 else {
342 Int(s.Length);
343 foreach (string ch in s) String(ch);
344 }
345 }
346
b1088dc Stefan O'Rear implement serialization for SubInfo, LAD, LexInfo
authored
347 public void Ints(int[] s) {
348 if (s == null) {
349 Int(-1);
350 } else {
351 Int(s.Length);
352 foreach (int ch in s)
353 Int(ch);
354 }
355 }
356
dc6dd55 Stefan O'Rear Implement serialization for Frame, finally kill off hashtable lexicals
authored
357 public void Refs<T> (T[] x) {
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
358 if (x == null) {
359 Int(-1);
360 } else {
361 Int(x.Length);
362 foreach (T y in x)
363 ObjRef(y);
364 }
365 }
366
dc6dd55 Stefan O'Rear Implement serialization for Frame, finally kill off hashtable lexicals
authored
367 public void Refs<T> (IList<T> x) {
3dc4789 Stefan O'Rear Implement freezing for types
authored
368 if (x == null) {
369 Int(-1);
370 } else {
371 Int(x.Count);
372 foreach (T y in x)
373 ObjRef(y);
374 }
375 }
376
d832c02 Stefan O'Rear Second draft of serialization code
authored
377 // This is the main routine you should call from your Freeze
378 // callbacks to freeze an object
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
379 public void ObjRef(object o) {
d832c02 Stefan O'Rear Second draft of serialization code
authored
380 int id;
381 SerUnit altunit;
382 if (o == null) { // null pointers are special
383 Byte((byte)SerializationCode.Null);
384 return;
385 }
386
387 if (reg.CheckWriteObject(unit, o, out altunit, out id)) {
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
388 if (altunit == unit) {
389 Byte((byte)SerializationCode.SelfRef);
390 } else {
d832c02 Stefan O'Rear Second draft of serialization code
authored
391 int altcode;
392 if (!unit_to_offset.TryGetValue(altunit, out altcode)) {
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
393 Byte((byte)SerializationCode.NewUnitRef);
b25256f Stefan O'Rear Add Serialize.cs to build, fix build errors
authored
394 String(altunit.name);
d832c02 Stefan O'Rear Second draft of serialization code
authored
395 // save the hash too so stale refs can be caught
396 foreach (byte b in altunit.hash) Byte(b);
397
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
398 unit_to_offset[altunit] = usedunits++;
399 } else {
400 Byte((byte)SerializationCode.ForeignRef);
d832c02 Stefan O'Rear Second draft of serialization code
authored
401 Int(altcode);
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
402 }
403 }
404 Int((int)id);
405 } else {
d832c02 Stefan O'Rear Second draft of serialization code
authored
406 // must take responsibility for saving the tag
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
407 IFreeze f = o as IFreeze;
408 if (f != null) {
409 f.Freeze(this);
410 } else {
411 FallbackFreeze(o);
412 }
413 }
414 }
415
be108f9 Stefan O'Rear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, bool...
authored
416 internal static Type[] boxTypes = new Type[] {
417 null, typeof(Rat), typeof(FatRat), typeof(Complex),
418 typeof(double), typeof(int), typeof(string),
419 typeof(Variable[]), typeof(VarDeque), typeof(STable),
420 };
421 internal static Func<P6opaque>[] boxCreate = new Func<P6opaque>[] {
422 P6opaque.Create, BoxObject<Rat>.Create, BoxObject<FatRat>.Create,
423 BoxObject<Complex>.Create, BoxObject<double>.Create,
424 BoxObject<int>.Create, BoxObject<string>.Create,
425 BoxObject<Variable[]>.Create, BoxObject<VarDeque>.Create,
426 BoxObject<STable>.Create,
427 };
428
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
429 static Type[] anyTypes = new Type[] {
430 typeof(string), typeof(P6any[]), typeof(Variable[]),
3f80fca Stefan O'Rear A procedure for serializing ContextHandler et al
authored
431 typeof(bool), typeof(int), typeof(double), typeof(Type),
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
432 };
433
434 void FallbackFreeze(object o) {
435 int ix = 0;
436 Type t = o.GetType();
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
437 while (ix != anyTypes.Length && anyTypes[ix] != t) ix++;
1c5bb04 Stefan O'Rear Small refactor to AssemblyBuilder setup, start thaw coding
authored
438 Byte((byte)(((int)SerializationCode.String) + ix));
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
439
440 switch(ix) {
441 case 0:
442 String((string)o);
443 break;
444 case 1:
445 Refs((P6any[])o);
446 break;
447 case 2:
448 Refs((Variable[])o);
449 break;
450 case 3:
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
451 Byte((byte)((bool)o ? 1 : 0));
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
452 break;
453 case 4:
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
454 Int((int)o);
455 break;
456 case 5:
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
457 Double((double)o);
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
458 break;
3f80fca Stefan O'Rear A procedure for serializing ContextHandler et al
authored
459 case 6:
460 String(((Type)o).AssemblyQualifiedName);
461 break;
d91ecdf Stefan O'Rear Serialization for objects of type Rat, FatRat, Complex, BigInteger, Int3...
authored
462 default:
463 throw new NotImplementedException(t.FullName);
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
464 }
465 }
466 }
467
468 // Note that this interface only handles freezing - thaw is done using
469 // a switch statement.
1993029 Stefan O'Rear Start implementing serialization for our objects
authored
470 public interface IFreeze {
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
471 void Freeze(FreezeBuffer fb);
472 }
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
473 // implement this if you need to copy in data from other objects, &c
474 interface IFixup {
475 void Fixup();
476 }
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
477
478 class ThawBuffer {
479 byte[] data;
480 int rpointer;
481 ObjectRegistry reg;
482
d832c02 Stefan O'Rear Second draft of serialization code
authored
483 SerUnit[] unit_map = new SerUnit[8];
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
484 int refed_units;
d832c02 Stefan O'Rear Second draft of serialization code
authored
485 SerUnit unit;
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
486
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
487 List<IFixup> fixups_needed = new List<IFixup>();
2ff6525 Stefan O'Rear Thaw routines for types
authored
488 List<object> revalidate = new List<object>();
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
489
b25256f Stefan O'Rear Add Serialize.cs to build, fix build errors
authored
490 internal ThawBuffer(ObjectRegistry reg, SerUnit unit, byte[] data) {
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
491 this.data = data;
492 this.reg = reg;
d832c02 Stefan O'Rear Second draft of serialization code
authored
493 this.unit = unit;
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
494 }
495
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
496 internal void RunFixups() {
2ff6525 Stefan O'Rear Thaw routines for types
authored
497 P6how.BulkRevalidate(revalidate);
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
498 foreach (IFixup f in fixups_needed)
499 f.Fixup();
500 fixups_needed.Clear();
501 }
502
503 internal void PushFixup(IFixup f) {
504 fixups_needed.Add(f);
505 }
506
2ff6525 Stefan O'Rear Thaw routines for types
authored
507 internal void PushRevalidate(STable f) {
508 revalidate.Add(f);
509 }
510
b25256f Stefan O'Rear Add Serialize.cs to build, fix build errors
authored
511 public byte Byte() { return data[rpointer++]; }
512
513 public short Short() {
514 return (short)((((int)Byte()) << 8) | Byte());
515 }
516
517 public int Int() {
518 return (((int)Byte()) << 24) | (((int)Byte()) << 16) |
519 (((int)Byte()) << 8) | ((int)Byte());
520 }
521
522 public long Long() {
523 // try to do as much as possible in 32-bit precision,
524 // but suppress sign extension
525 return (((long)Int()) << 32) | (long)(uint)Int();
526 }
527
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
528 public double Double() {
529 return BitConverter.Int64BitsToDouble(Long());
530 }
531
b25256f Stefan O'Rear Add Serialize.cs to build, fix build errors
authored
532 public string String() {
533 int l = Int();
534
535 if (l < 0) return null;
536 char[] cb = new char[l];
537
538 for (int i = 0; i < l; i++)
539 cb[i] = (char)Short();
540
541 return new string(cb);
542 }
543
544 public byte[] Bytes(int k) {
545 byte[] buf = new byte[k];
546
547 for (int i = 0; i < k; i++)
548 buf[i] = Byte();
549
550 return buf;
551 }
552
1c5bb04 Stefan O'Rear Small refactor to AssemblyBuilder setup, start thaw coding
authored
553 public List<T> RefsL<T>() where T : class {
554 int ct = Int();
555 if (ct < 0) return null;
556 List<T> ret = new List<T>();
557 for (int i = 0; i < ct; i++)
558 ret.Add((T) ObjRef());
559 return ret;
560 }
561
2ff6525 Stefan O'Rear Thaw routines for types
authored
562 public int[] Ints() {
563 int ct = Int();
564 if (ct < 0) return null;
565 int[] ret = new int[ct];
566 for (int i = 0; i < ct; i++) ret[i] = Int();
567 return ret;
568 }
569
570 public string[] Strings() {
571 int ct = Int();
572 if (ct < 0) return null;
573 string[] ret = new string[ct];
574 for (int i = 0; i < ct; i++) ret[i] = String();
575 return ret;
576 }
577
1c5bb04 Stefan O'Rear Small refactor to AssemblyBuilder setup, start thaw coding
authored
578 public T[] RefsA<T>() where T : class {
579 int ct = Int();
580 if (ct < 0) return null;
581 T[] ret = new T[ct];
582 for (int i = 0; i < ct; i++)
583 ret[i] = (T) ObjRef();
584 return ret;
585 }
586
b25256f Stefan O'Rear Add Serialize.cs to build, fix build errors
authored
587 public object ObjRef() {
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
588 var tag = (SerializationCode)Byte();
589 int i, j;
590 switch(tag) {
d832c02 Stefan O'Rear Second draft of serialization code
authored
591 case SerializationCode.Null:
592 return null;
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
593
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
594 case SerializationCode.ForeignRef:
595 i = Int();
596 j = Int();
d832c02 Stefan O'Rear Second draft of serialization code
authored
597 return unit_map[i].bynum[j];
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
598 case SerializationCode.SelfRef:
599 i = Int();
600 return unit.bynum[i];
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
601 case SerializationCode.NewUnitRef:
d832c02 Stefan O'Rear Second draft of serialization code
authored
602 return LoadNewUnit();
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
603
1c5bb04 Stefan O'Rear Small refactor to AssemblyBuilder setup, start thaw coding
authored
604 case SerializationCode.RuntimeUnit:
605 return RuntimeUnit.Thaw(this);
2671ab4 Stefan O'Rear Add thaw routine for SubInfo
authored
606 case SerializationCode.SubInfo:
607 return SubInfo.Thaw(this);
2ff6525 Stefan O'Rear Thaw routines for types
authored
608 case SerializationCode.STable:
609 return STable.Thaw(this);
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
610 case SerializationCode.StashEnt:
611 return StashEnt.Thaw(this);
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
612 case SerializationCode.Rat:
613 return Rat.Thaw(this);
614 case SerializationCode.FatRat:
615 return FatRat.Thaw(this);
616 case SerializationCode.Complex:
617 return Complex.Thaw(this);
618 case SerializationCode.BigInteger:
619 return BigInteger.Thaw(this);
620 case SerializationCode.VarDeque:
621 return VarDeque.Thaw(this);
622 case SerializationCode.VarHash:
623 return VarHash.Thaw(this);
be108f9 Stefan O'Rear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, bool...
authored
624 case SerializationCode.DispatchEnt:
625 return DispatchEnt.Thaw(this);
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
626 //case SerializationCode.RxFrame:
627 // return RxFrame.Thaw(this);
2ff6525 Stefan O'Rear Thaw routines for types
authored
628 case SerializationCode.P6how:
629 return P6how.Thaw(this);
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
630
3f80fca Stefan O'Rear A procedure for serializing ContextHandler et al
authored
631 case SerializationCode.ReflectObj:
632 return ReflectObj.Thaw(this);
be108f9 Stefan O'Rear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, bool...
authored
633 case SerializationCode.P6opaque:
634 return P6opaque.Thaw(this);
9b6504a Stefan O'Rear Thaw routines for Frame
authored
635 case SerializationCode.Frame:
636 return Frame.Thaw(this);
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
637 //Cursor,
638
be108f9 Stefan O'Rear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, bool...
authored
639 case SerializationCode.String:
640 return Register(String());
641 case SerializationCode.ArrP6any:
642 return Register(RefsA<P6any>());
643 case SerializationCode.ArrVariable:
644 return Register(RefsA<Variable>());
645 case SerializationCode.Boolean:
646 return Register(Byte() != 0);
647 case SerializationCode.Int:
648 return Register(Int());
649 case SerializationCode.Double:
650 return Register(Double());
651 case SerializationCode.Type:
652 return Register(Type.GetType(String(), true));
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
653
fe6e595 Stefan O'Rear Thaw for SimpleVariable, StashEnt
authored
654 case SerializationCode.SimpleVariable:
655 case SerializationCode.SimpleVariable_1:
656 case SerializationCode.SimpleVariable_2:
657 case SerializationCode.SimpleVariable_3:
658 return SimpleVariable.Thaw(this,
659 (int)tag - (int)SerializationCode.SimpleVariable);
8035d26 Stefan O'Rear Thaw code for VarDeque, VarHash, BigInteger, Complex, Rat, FatRat
authored
660 //SubstrLValue,
661 //TiedVariable,
662 //SubViviHook,
663 //ArrayViviHook,
664 //NewArrayViviHook,
665 //HashViviHook,
666 //NewHashViviHook,
667 //LADNone, // no-args
668 //LADNull,
669 //LADDot,
670 //LADDispatcher,
671 //LADImp,
672 //LADStr, // string
673 //LADStrNoCase,
674 //LADMethod,
675 //LADParam,
676 //LADOpt, // LAD
677 //LADPlus,
678 //LADStar,
679 //LADSequence, // LAD[]
680 //LADAny,
681 //LADCC, // CC
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
682 default:
1c5bb04 Stefan O'Rear Small refactor to AssemblyBuilder setup, start thaw coding
authored
683 throw new ThawException("unexpected object tag " + tag);
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
684 }
685 }
d832c02 Stefan O'Rear Second draft of serialization code
authored
686
1c5bb04 Stefan O'Rear Small refactor to AssemblyBuilder setup, start thaw coding
authored
687 // call this when thawing any new object
be108f9 Stefan O'Rear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, bool...
authored
688 internal object Register(object o) {
1c5bb04 Stefan O'Rear Small refactor to AssemblyBuilder setup, start thaw coding
authored
689 reg.RegisterThawed(unit, o);
be108f9 Stefan O'Rear Thaw routines for P6opaque, DispatchEnt, double, int, Type, string, bool...
authored
690 return o;
1c5bb04 Stefan O'Rear Small refactor to AssemblyBuilder setup, start thaw coding
authored
691 }
692
d832c02 Stefan O'Rear Second draft of serialization code
authored
693 object LoadNewUnit() {
694 string name = String();
695 if (refed_units == unit_map.Length)
696 Array.Resize(ref unit_map, refed_units * 2);
697
698 SerUnit su = reg.LoadUnit(name);
699 unit_map[refed_units++] = su;
700
701 byte[] hash = Bytes(su.hash.Length);
702
703 for (int i = 0; i < hash.Length; i++)
704 if (hash[i] != su.hash[i])
705 goto badhash;
706
707 int ix = Int();
708 return su.bynum[ix];
709
710 badhash:
711 StringBuilder sb = new StringBuilder();
712 sb.AppendFormat("Hash mismatch for unit {0} referenced from {1}",
713 su.name, unit.name);
714
715 sb.Append(", wanted ");
716 foreach (byte b in hash)
717 sb.AppendFormat("{0:X2}", b);
718
719 sb.Append(", got ");
720 foreach (byte b in su.hash)
721 sb.AppendFormat("{0:X2}", b);
722
723 throw new ThawException(sb.ToString());
724 }
725 }
726
727 // Thrown to indicate data format problems in the serialized stream
728 // Not necessarily bugs; could also indicate stale files, including
729 // cases where the data format is changed and cases where a depended
730 // file was recreated
731 class ThawException : Exception {
732 public ThawException(string s) : base(s) { }
733 public ThawException() : base() { }
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
734 }
3f80fca Stefan O'Rear A procedure for serializing ContextHandler et al
authored
735
736 public class ReflectObj : IFreeze {
737 protected virtual object[] GetData() { return new object[0]; }
738 protected virtual void SetData(object[] a) { }
739 void IFreeze.Freeze(FreezeBuffer fb) {
740 fb.Byte((byte)SerializationCode.ReflectObj);
741 fb.String(GetType().AssemblyQualifiedName);
742 fb.Refs(GetData());
743 }
744
745 internal static ReflectObj Thaw(ThawBuffer tb) {
746 Type nt = Type.GetType(tb.String());
747 ReflectObj n = (ReflectObj)
748 nt.GetConstructor(new Type[0]).Invoke(null, new object[0]);
749 tb.Register(n);
750 n.SetData(tb.RefsA<object>());
751 return n;
752 }
753 }
8184302 Stefan O'Rear Start draft of serialization/deserialization code
authored
754 }
Something went wrong with that request. Please try again.