Skip to content

Commit c2d1459

Browse files
committed
[js] Update serialization to format version 16.
1 parent 568f06a commit c2d1459

File tree

1 file changed

+77
-15
lines changed

1 file changed

+77
-15
lines changed

src/vm/js/nqp-runtime/serialization.js

Lines changed: 77 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ var NQPInt = require('./nqp-int.js');
55
var op = {};
66
exports.op = op;
77

8-
var CURRENT_VERSION = 15;
8+
var CURRENT_VERSION = 16;
99
var OBJECTS_TABLE_ENTRY_SC_MASK = 0x7FF;
1010
var OBJECTS_TABLE_ENTRY_SC_IDX_MASK = 0x000FFFFF;
1111
var OBJECTS_TABLE_ENTRY_SC_IDX_MAX = 0x000FFFFF;
@@ -14,6 +14,12 @@ var OBJECTS_TABLE_ENTRY_SC_SHIFT = 20;
1414
var OBJECTS_TABLE_ENTRY_SC_OVERFLOW = 0x7FF;
1515
var OBJECTS_TABLE_ENTRY_IS_CONCRETE = 0x80000000;
1616

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+
1723
/* Possible reference types we can serialize. */
1824
var REFVAR_NULL = 1;
1925
var REFVAR_OBJECT = 2;
@@ -47,6 +53,23 @@ BinaryWriteCursor.prototype.str = function(str) {
4753
console.trace('undefined string');
4854
str = '?';
4955
}
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) {
5073
this.I32(this.writer.stringIndex(str));
5174
};
5275

@@ -124,6 +147,12 @@ BinaryWriteCursor.prototype.U8 = function(value) {
124147
this.offset += 1;
125148
};
126149

150+
BinaryWriteCursor.prototype.U16 = function(value) {
151+
this.growToHold(2);
152+
this.buffer.writeUInt16LE(value, this.offset);
153+
this.offset += 2;
154+
};
155+
127156

128157
BinaryWriteCursor.prototype.I32 = function(value) {
129158
this.growToHold(4);
@@ -340,7 +369,7 @@ BinaryWriteCursor.prototype.ref = function(ref) {
340369
// case REFVAR_VM_ARR_STR:
341370
// ref.st.REPR.serialize(tc, this, ref);
342371
case REFVAR_VM_ARR_VAR:
343-
this.I32(ref.length);
372+
this.varint(ref.length);
344373
for (var i = 0; i < ref.length; i++) {
345374
this.ref(ref[i]);
346375
}
@@ -370,7 +399,7 @@ BinaryWriteCursor.prototype.ref = function(ref) {
370399
SerializationWriter.prototype.serializeSTable = function(st) {
371400

372401
/* Make STables table entry. */
373-
this.stables.str(st.REPR.constructor.name);
402+
this.stables.str32(st.REPR.constructor.name);
374403
this.stables.I32(this.stables_data.offset);
375404

376405
/* Write HOW, WHAT and WHO. */
@@ -397,35 +426,67 @@ SerializationWriter.prototype.serializeSTable = function(st) {
397426

398427
/* Type check cache. */
399428
var tcl = !st.type_check_cache ? 0 : st.type_check_cache.length;
400-
this.stables_data.I64(tcl);
429+
this.stables_data.varint(tcl);
401430
for (var i = 0; i < tcl; i++) {
402431
this.stables_data.ref(st.type_check_cache[i]);
403432
}
404433

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);
408447

409448
/* 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);
411476

412477
/*writeInt(st.BoolificationSpec == null ? 0 : 1);
413478
if (st.BoolificationSpec != null) {
414479
writeInt(st.BoolificationSpec.Mode);
415480
writeRef(st.BoolificationSpec.Method);
416481
}*/
417482

418-
/* Container spec. */
419-
this.stables_data.I64(0);
420-
421483
/*this.stables_data.writeInt(st.ContainerSpec == null ? 0 : 1);
422484
if (st.ContainerSpec != null) {
423485
writeStr(st.ContainerSpec.name());
424486
st.ContainerSpec.serialize(tc, st, this);
425487
}*/
426488

427489
/* Invocation spec. */
428-
this.stables_data.I64(0);
429490

430491
/*writeInt(st.InvocationSpec == null ? 0 : 1);
431492
if (st.InvocationSpec != null) {
@@ -444,7 +505,8 @@ SerializationWriter.prototype.serializeSTable = function(st) {
444505

445506
/* TODO - HLL owner */
446507

447-
this.stables_data.str(null);
508+
//this.stables_data.str(null);
509+
448510
/* Location of REPR data. */
449511
this.stables.I32(this.stables_data.offset);
450512

@@ -555,8 +617,8 @@ SerializationWriter.prototype.getSCId = function(sc) {
555617
/* Otherwise, need to add it to our dependencies list. */
556618
this.dependentSCs.push(sc);
557619

558-
this.deps.str(sc.handle);
559-
this.deps.str(sc.description);
620+
this.deps.str32(sc.handle);
621+
this.deps.str32(sc.description);
560622

561623
return this.dependentSCs.length; /* Deliberately index + 1. */
562624
};

0 commit comments

Comments
 (0)