@@ -5,7 +5,7 @@ var NQPInt = require('./nqp-int.js');
5
5
var op = { } ;
6
6
exports . op = op ;
7
7
8
- var CURRENT_VERSION = 15 ;
8
+ var CURRENT_VERSION = 16 ;
9
9
var OBJECTS_TABLE_ENTRY_SC_MASK = 0x7FF ;
10
10
var OBJECTS_TABLE_ENTRY_SC_IDX_MASK = 0x000FFFFF ;
11
11
var OBJECTS_TABLE_ENTRY_SC_IDX_MAX = 0x000FFFFF ;
@@ -14,6 +14,12 @@ var OBJECTS_TABLE_ENTRY_SC_SHIFT = 20;
14
14
var OBJECTS_TABLE_ENTRY_SC_OVERFLOW = 0x7FF ;
15
15
var OBJECTS_TABLE_ENTRY_IS_CONCRETE = 0x80000000 ;
16
16
17
+ var STRING_HEAP_LOC_MAX = 0x7FFFFFFF ;
18
+ var STRING_HEAP_LOC_PACKED_MAX = 0x00007FFF ;
19
+ var STRING_HEAP_LOC_PACKED_OVERFLOW = 0x00008000 ;
20
+ var STRING_HEAP_LOC_PACKED_LOW_MASK = 0x0000FFFF ;
21
+ var STRING_HEAP_LOC_PACKED_SHIFT = 16
22
+
17
23
/* Possible reference types we can serialize. */
18
24
var REFVAR_NULL = 1 ;
19
25
var REFVAR_OBJECT = 2 ;
@@ -47,6 +53,23 @@ BinaryWriteCursor.prototype.str = function(str) {
47
53
console . trace ( 'undefined string' ) ;
48
54
str = '?' ;
49
55
}
56
+
57
+ var heap_loc = this . writer . stringIndex ( str ) ;
58
+
59
+ if ( ! ( heap_loc >= 0 && heap_loc <= STRING_HEAP_LOC_MAX ) ) {
60
+ throw "Serialization error: string offset " + heap_loc + "can't be serialized" ;
61
+ }
62
+
63
+ if ( heap_loc <= STRING_HEAP_LOC_PACKED_MAX ) {
64
+ this . U16 ( heap_loc ) ;
65
+ } else {
66
+ this . U16 ( ( heap_loc >> STRING_HEAP_LOC_PACKED_SHIFT )
67
+ | STRING_HEAP_LOC_PACKED_OVERFLOW ) ;
68
+ this . U16 ( heap_loc & STRING_HEAP_LOC_PACKED_LOW_MASK ) ;
69
+ }
70
+ } ;
71
+
72
+ BinaryWriteCursor . prototype . str32 = function ( str ) {
50
73
this . I32 ( this . writer . stringIndex ( str ) ) ;
51
74
} ;
52
75
@@ -124,6 +147,12 @@ BinaryWriteCursor.prototype.U8 = function(value) {
124
147
this . offset += 1 ;
125
148
} ;
126
149
150
+ BinaryWriteCursor . prototype . U16 = function ( value ) {
151
+ this . growToHold ( 2 ) ;
152
+ this . buffer . writeUInt16LE ( value , this . offset ) ;
153
+ this . offset += 2 ;
154
+ } ;
155
+
127
156
128
157
BinaryWriteCursor . prototype . I32 = function ( value ) {
129
158
this . growToHold ( 4 ) ;
@@ -340,7 +369,7 @@ BinaryWriteCursor.prototype.ref = function(ref) {
340
369
// case REFVAR_VM_ARR_STR:
341
370
// ref.st.REPR.serialize(tc, this, ref);
342
371
case REFVAR_VM_ARR_VAR :
343
- this . I32 ( ref . length ) ;
372
+ this . varint ( ref . length ) ;
344
373
for ( var i = 0 ; i < ref . length ; i ++ ) {
345
374
this . ref ( ref [ i ] ) ;
346
375
}
@@ -370,7 +399,7 @@ BinaryWriteCursor.prototype.ref = function(ref) {
370
399
SerializationWriter . prototype . serializeSTable = function ( st ) {
371
400
372
401
/* Make STables table entry. */
373
- this . stables . str ( st . REPR . constructor . name ) ;
402
+ this . stables . str32 ( st . REPR . constructor . name ) ;
374
403
this . stables . I32 ( this . stables_data . offset ) ;
375
404
376
405
/* Write HOW, WHAT and WHO. */
@@ -397,35 +426,67 @@ SerializationWriter.prototype.serializeSTable = function(st) {
397
426
398
427
/* Type check cache. */
399
428
var tcl = ! st . type_check_cache ? 0 : st . type_check_cache . length ;
400
- this . stables_data . I64 ( tcl ) ;
429
+ this . stables_data . varint ( tcl ) ;
401
430
for ( var i = 0 ; i < tcl ; i ++ ) {
402
431
this . stables_data . ref ( st . type_check_cache [ i ] ) ;
403
432
}
404
433
405
- /* Mode flags. */
406
- // writeInt(st.ModeFlags);
407
- this . stables_data . I64 ( 0 ) ;
434
+
435
+ /* Mode flags.
436
+ These are stored as MVMuint16, but currently only the bottom 6 bits are
437
+ used. Whilst we could store these as 2 bytes, we don't actually gain any
438
+ future-proofing from that, because if we start assigning meaning to
439
+ currently unused bits, then we have to bump the serialisation version
440
+ *anyway*. If we didn't, older readers would encounter files with the
441
+ newly used bits, but ignore whatever semantics those bits were meant to
442
+ convey, and hence show buggy behaviour. And if we're bumping the
443
+ serialisation version, then we can increase the storage size. */
444
+
445
+ /* TODO */
446
+ this . stables_data . U8 ( 0 ) ;
408
447
409
448
/* Boolification spec. */
410
- this . stables_data . I64 ( 0 ) ;
449
+ /* As this only needs 4 bits, also use the same byte to store various
450
+ NULL/not-NULL flag bits. */
451
+
452
+ /*TODO serialize boolifcation spec*/
453
+ var flags ;
454
+
455
+ if ( false ) {
456
+ //if (st->boolification_spec->mode >= 0xF) {
457
+ // MVM_exception_throw_adhoc(tc,
458
+ // "Serialization error: boolification spec mode %u out of range and can't be serialized",
459
+ // st->boolification_spec->mode);
460
+ //}
461
+ //flags = st->boolification_spec->mode;
462
+ } else {
463
+ flags = 0xF ;
464
+ }
465
+ /*
466
+ if (st->container_spec != NULL)
467
+ flags |= STABLE_HAS_CONTAINER_SPEC;
468
+ if (st->invocation_spec != NULL)
469
+ flags |= STABLE_HAS_INVOCATION_SPEC;
470
+ if (st->hll_owner != NULL)
471
+ flags |= STABLE_HAS_HLL_OWNER;
472
+ */
473
+
474
+ /* Boolification spec. */
475
+ this . stables_data . U8 ( flags ) ;
411
476
412
477
/*writeInt(st.BoolificationSpec == null ? 0 : 1);
413
478
if (st.BoolificationSpec != null) {
414
479
writeInt(st.BoolificationSpec.Mode);
415
480
writeRef(st.BoolificationSpec.Method);
416
481
}*/
417
482
418
- /* Container spec. */
419
- this . stables_data . I64 ( 0 ) ;
420
-
421
483
/*this.stables_data.writeInt(st.ContainerSpec == null ? 0 : 1);
422
484
if (st.ContainerSpec != null) {
423
485
writeStr(st.ContainerSpec.name());
424
486
st.ContainerSpec.serialize(tc, st, this);
425
487
}*/
426
488
427
489
/* Invocation spec. */
428
- this . stables_data . I64 ( 0 ) ;
429
490
430
491
/*writeInt(st.InvocationSpec == null ? 0 : 1);
431
492
if (st.InvocationSpec != null) {
@@ -444,7 +505,8 @@ SerializationWriter.prototype.serializeSTable = function(st) {
444
505
445
506
/* TODO - HLL owner */
446
507
447
- this . stables_data . str ( null ) ;
508
+ //this.stables_data.str(null);
509
+
448
510
/* Location of REPR data. */
449
511
this . stables . I32 ( this . stables_data . offset ) ;
450
512
@@ -555,8 +617,8 @@ SerializationWriter.prototype.getSCId = function(sc) {
555
617
/* Otherwise, need to add it to our dependencies list. */
556
618
this . dependentSCs . push ( sc ) ;
557
619
558
- this . deps . str ( sc . handle ) ;
559
- this . deps . str ( sc . description ) ;
620
+ this . deps . str32 ( sc . handle ) ;
621
+ this . deps . str32 ( sc . description ) ;
560
622
561
623
return this . dependentSCs . length ; /* Deliberately index + 1. */
562
624
} ;
0 commit comments