1
+ var Hash = require ( './hash.js' ) ;
2
+ var CodeRef = require ( './code-ref.js' ) ;
1
3
2
4
var op = { } ;
3
5
exports . op = op ;
@@ -11,6 +13,20 @@ var OBJECTS_TABLE_ENTRY_SC_SHIFT = 20;
11
13
var OBJECTS_TABLE_ENTRY_SC_OVERFLOW = 0x7FF ;
12
14
var OBJECTS_TABLE_ENTRY_IS_CONCRETE = 0x80000000 ;
13
15
16
+ /* Possible reference types we can serialize. */
17
+ var REFVAR_NULL = 1 ;
18
+ var REFVAR_OBJECT = 2 ;
19
+ var REFVAR_VM_NULL = 3 ;
20
+ var REFVAR_VM_INT = 4 ;
21
+ var REFVAR_VM_NUM = 5 ;
22
+ var REFVAR_VM_STR = 6 ;
23
+ var REFVAR_VM_ARR_VAR = 7 ;
24
+ var REFVAR_VM_ARR_STR = 8 ;
25
+ var REFVAR_VM_ARR_INT = 9 ;
26
+ var REFVAR_VM_HASH_STR_VAR = 10 ;
27
+ var REFVAR_STATIC_CODEREF = 11 ;
28
+ var REFVAR_CLONED_CODEREF = 12 ;
29
+
14
30
function BinaryWriteCursor ( writer ) {
15
31
this . buffer = new Buffer ( 1024 ) ;
16
32
this . writer = writer ;
@@ -78,7 +94,7 @@ BinaryWriteCursor.prototype.varint = function(value) {
78
94
|| ( nybble >> 3 ) == ~ 0 ) ;
79
95
80
96
this . I8 ( ( rest << 4 ) | ( nybble & 0xF ) ) ;
81
- console . log ( "TODO - writing varints that take 2-8 bytes" ) ;
97
+ console . log ( "TODO - writing varints that take 2-8 bytes" , value , storage_needed ) ;
82
98
//memcpy(buffer + offset, &value, rest);
83
99
}
84
100
} ;
@@ -175,6 +191,182 @@ SerializationWriter.prototype.serializeObject = function(obj) {
175
191
this.objects.I32(obj._type_object ? 0 : 1);*/
176
192
} ;
177
193
194
+ var PACKED_SC_IDX_MASK = 0x000FFFFF ;
195
+ var PACKED_SC_MAX = 0xFFE ;
196
+ var PACKED_SC_IDX_MAX = 0x000FFFFF ;
197
+ var PACKED_SC_SHIFT = 20 ;
198
+ var PACKED_SC_OVERFLOW = 0xFFF ;
199
+
200
+ /* Writes the ID, index pair that identifies an entry in a Serialization
201
+ context. */
202
+ BinaryWriteCursor . prototype . idIdx = function ( sc_id , idx ) {
203
+ //static void write_sc_id_idx(MVMThreadContext *tc, MVMSerializationWriter *writer, MVMint32 sc_id, MVMint32 idx) {
204
+ if ( sc_id <= PACKED_SC_MAX && idx <= PACKED_SC_IDX_MAX ) {
205
+ var packed = ( sc_id << PACKED_SC_SHIFT ) | ( idx & PACKED_SC_IDX_MASK ) ;
206
+ this . I32 ( packed ) ;
207
+ } else {
208
+ var packed = PACKED_SC_OVERFLOW << PACKED_SC_SHIFT ;
209
+
210
+ this . I32 ( packed ) ;
211
+ this . I32 ( sc_id ) ;
212
+ this . I32 ( idx ) ;
213
+ /*write_int32(*(writer->cur_write_buffer), *(writer->cur_write_offset), packed);
214
+ write_int32(*(writer->cur_write_buffer), *(writer->cur_write_offset), sc_id);
215
+ write_int32(*(writer->cur_write_buffer), *(writer->cur_write_offset), idx);*/
216
+ }
217
+ }
218
+
219
+ BinaryWriteCursor . prototype . objRef = function ( ref ) {
220
+ var writer_sc = this . writer . sc ;
221
+ if ( ! ref . _STable ) {
222
+ console . log ( ref ) ;
223
+ console . trace ( "can't serialize this for sure" ) ;
224
+ console . log ( typeof ref ) ;
225
+ console . log ( ref . code_ref ) ;
226
+ process . exit ( ) ;
227
+ }
228
+ if ( ! ref . _SC ) {
229
+ /* This object doesn't belong to an SC yet, so it must be serialized
230
+ * as part of this compilation unit. Add it to the work list. */
231
+ ref . _SC = 123 ;
232
+ ref . _SC = writer_sc ;
233
+
234
+ this . writer . sc . root_objects . push ( ref ) ;
235
+ }
236
+
237
+ var sc = ref . _SC ;
238
+ if ( ! sc ) {
239
+ console . log ( '!sc' , ! ref . _SC , ref . _SC ) ;
240
+ console . trace ( '!sc' ) ;
241
+ //process.exit();
242
+ }
243
+ /* Write SC index, then object index. */
244
+ this . idIdx ( this . writer . getSCId ( sc ) , sc . root_objects . indexOf ( ref ) ) ;
245
+ } ;
246
+
247
+ BinaryWriteCursor . prototype . ref = function ( ref ) {
248
+ /* Work out what kind of thing we have and determine the discriminator. */
249
+ // cnsole.log('got to ref',value);
250
+ var discrim = 0 ;
251
+
252
+ if ( ref == null ) {
253
+ discrim = REFVAR_VM_NULL ;
254
+ }
255
+ // else if (ref.st.REPR instanceof IOHandle) {
256
+ // /* Can't serialize handles. */
257
+ // discrim = REFVAR_VM_NULL;
258
+ // }
259
+ // else if (ref.st.REPR instanceof CallCapture) {
260
+ // /* This is a hack for Rakudo's sake; it keeps a CallCapture around in
261
+ // * the lexpad, for no really good reason. */
262
+ // discrim = REFVAR_VM_NULL;
263
+ // }
264
+ // else if (ref.st.REPR instanceof MultiCache) {
265
+ // /* These are re-computed each time. */
266
+ // discrim = REFVAR_VM_NULL;
267
+ // }
268
+ // else if (ref.st.WHAT == tc.gc.BOOTInt) {
269
+ // discrim = REFVAR_VM_INT;
270
+ // }
271
+ else if ( typeof ref == 'number' ) {
272
+ discrim = REFVAR_VM_NUM ;
273
+ }
274
+ else if ( typeof ref == 'string' ) {
275
+ discrim = REFVAR_VM_STR ;
276
+ }
277
+ else if ( ref instanceof Array ) {
278
+ discrim = REFVAR_VM_ARR_VAR ;
279
+ }
280
+ // else if (ref.st.WHAT == tc.gc.BOOTIntArray) {
281
+ // discrim = REFVAR_VM_ARR_INT;
282
+ // }
283
+ // else if (ref.st.WHAT == tc.gc.BOOTStrArray) {
284
+ // discrim = REFVAR_VM_ARR_STR;
285
+ // }
286
+ else if ( ref instanceof Hash ) {
287
+ discrim = REFVAR_VM_HASH_STR_VAR ;
288
+ }
289
+ else if ( ref instanceof CodeRef || typeof ref == 'function' ) {
290
+ // console.log("serializing code ref");
291
+ discrim = REFVAR_VM_NULL ;
292
+ if ( ref . _SC && ref . isStaticCodeRef ) {
293
+ /* Static code reference. */
294
+ discrim = REFVAR_STATIC_CODEREF ;
295
+ }
296
+ else if ( ref . _SC ) {
297
+ /* Closure, but already seen and serialization already handled. */
298
+ discrim = REFVAR_CLONED_CODEREF ;
299
+ }
300
+ else {
301
+ /* Closure but didn't see it yet. Take care of it serialization, which
302
+ * gets it marked with this SC. Then it's just a normal code ref that
303
+ * needs serializing. */
304
+ this . writer . serializeClosure ( ref ) ;
305
+ discrim = REFVAR_CLONED_CODEREF ;
306
+ }
307
+ }
308
+ else {
309
+ /* Just a normal object, with no special serialization needs. */
310
+ discrim = REFVAR_OBJECT ;
311
+ }
312
+
313
+
314
+ this . I8 ( discrim ) ;
315
+
316
+ /* Now take appropriate action. */
317
+ switch ( discrim ) {
318
+ case REFVAR_NULL :
319
+ case REFVAR_VM_NULL :
320
+ /* Nothing to do for these. */
321
+ break ;
322
+ case REFVAR_OBJECT :
323
+ this . objRef ( ref ) ;
324
+ break ;
325
+ case REFVAR_VM_INT :
326
+ this . I64 ( ref ) ;
327
+ break ;
328
+ case REFVAR_VM_NUM :
329
+ this . double ( ref ) ;
330
+ // writeNum(ref.get_num(tc));
331
+ break ;
332
+ case REFVAR_VM_STR :
333
+ this . str ( ref ) ;
334
+ break ;
335
+ // case REFVAR_VM_ARR_INT:
336
+ // case REFVAR_VM_ARR_STR:
337
+ // ref.st.REPR.serialize(tc, this, ref);
338
+ case REFVAR_VM_ARR_VAR :
339
+ this . I32 ( ref . length ) ;
340
+ for ( var i = 0 ; i < ref . length ; i ++ ) {
341
+ this . ref ( ref [ i ] ) ;
342
+ }
343
+ break ;
344
+ case REFVAR_VM_HASH_STR_VAR :
345
+ var count = 0 ;
346
+ for ( var key in ref ) {
347
+ count ++ ;
348
+ }
349
+ this . I32 ( count ) ;
350
+ for ( var key in ref ) {
351
+ if ( key === undefined ) {
352
+ console . log ( ref ) ;
353
+ }
354
+ this . string ( key ) ;
355
+ this . ref ( ref [ key ] ) ;
356
+ }
357
+ break ;
358
+ case REFVAR_STATIC_CODEREF :
359
+ case REFVAR_CLONED_CODEREF :
360
+ var scId = this . writer . getSCId ( ref . _SC ) ;
361
+ var idx = ref . _SC . root_codes . indexOf ( ref ) ;
362
+ this . I32 ( scId ) ;
363
+ this . I32 ( idx ) ;
364
+ break ;
365
+ default :
366
+ throw 'Serialization Error: Unimplemented object type: ' + discrim ;
367
+ }
368
+ } ;
369
+
178
370
/* This is the overall serialization loop. It keeps an index into the list of
179
371
* STables and objects in the SC. As we discover new ones, they get added. We
180
372
* finished when we've serialized everything. */
0 commit comments