diff --git a/lib/9p.js b/lib/9p.js index a035bad7..e9a08343 100644 --- a/lib/9p.js +++ b/lib/9p.js @@ -190,7 +190,7 @@ Virtio9p.prototype.set_state = function(state) { this.configspace_tagname = state[0]; this.configspace_taglen = state[1]; - this.virtio = state[2]; + this.virtio.set_state(state[2]); this.virtqueue = this.virtio.queues[0]; this.VERSION = state[3]; this.BLOCKSIZE = state[4]; @@ -201,7 +201,7 @@ Virtio9p.prototype.set_state = function(state) { return { inodeid: f[0], type: f[1], uid: f[2], dbg_name: f[3] }; }); - this.fs = state[9]; + this.fs.set_state(state[9]); }; // Note: dbg_name is only used for debugging messages and may not be the same as the filename, diff --git a/lib/filesystem.js b/lib/filesystem.js index f6a1c8af..9c47b26a 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -424,7 +424,11 @@ Inode.prototype.get_state = function() Inode.prototype.set_state = function(state) { this.updatedir = state[0]; - this.direntries = new Map(state[1]); + this.direntries = new Map(); + for(const [name, entry] of state[1]) + { + this.direntries.set(name, entry); + } this.locks = []; for(const lock_state of state[2]) { diff --git a/src/cpu.js b/src/cpu.js index 634eebf8..66fd9475 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -450,26 +450,26 @@ CPU.prototype.set_state = function(state) this.set_tsc(state[43][0], state[43][1]); - this.devices.virtio_9p = state[45]; - this.devices.apic = state[46]; - this.devices.rtc = state[47]; - this.devices.pci = state[48]; - this.devices.dma = state[49]; - this.devices.acpi = state[50]; - this.devices.hpet = state[51]; - this.devices.vga = state[52]; - this.devices.ps2 = state[53]; - this.devices.uart = state[54]; - this.devices.fdc = state[55]; - this.devices.cdrom = state[56]; - this.devices.hda = state[57]; - this.devices.pit = state[58]; - this.devices.net = state[59]; - this.devices.pic = state[60]; + this.devices.virtio_9p && this.devices.virtio_9p.set_state(state[45]); + this.devices.apic && this.devices.apic.set_state(state[46]); + this.devices.rtc && this.devices.rtc.set_state(state[47]); + this.devices.pci && this.devices.pci.set_state(state[48]); + this.devices.dma && this.devices.dma.set_state(state[49]); + this.devices.acpi && this.devices.acpi.set_state(state[50]); + this.devices.hpet && this.devices.hpet.set_state(state[51]); + this.devices.vga && this.devices.vga.set_state(state[52]); + this.devices.ps2 && this.devices.ps2.set_state(state[53]); + this.devices.uart && this.devices.uart.set_state(state[54]); + this.devices.fdc && this.devices.fdc.set_state(state[55]); + this.devices.cdrom && this.devices.cdrom.set_state(state[56]); + this.devices.hda && this.devices.hda.set_state(state[57]); + this.devices.pit && this.devices.pit.set_state(state[58]); + this.devices.net && this.devices.net.set_state(state[59]); + this.devices.pic && this.devices.pic.set_state(state[60]); this.fw_value = state[62]; - this.devices.ioapic = state[63]; + this.devices.ioapic && this.devices.ioapic.set_state(state[63]); this.tss_size_32[0] = state[64]; diff --git a/src/ide.js b/src/ide.js index 118cb863..4aa19e37 100644 --- a/src/ide.js +++ b/src/ide.js @@ -433,8 +433,8 @@ IDEDevice.prototype.get_state = function() IDEDevice.prototype.set_state = function(state) { - this.master = state[0]; - this.slave = state[1]; + this.master.set_state(state[0]); + this.slave.set_state(state[1]); this.ata_port = state[2]; this.irq = state[3]; this.pci_id = state[4]; @@ -2079,5 +2079,5 @@ IDEInterface.prototype.set_state = function(state) this.data16 = new Uint16Array(this.data.buffer); this.data32 = new Int32Array(this.data.buffer); - this.buffer = state[28]; + this.buffer && this.buffer.set_state(state[28]); }; diff --git a/src/pic.js b/src/pic.js index e85e4fcd..422f7cc7 100644 --- a/src/pic.js +++ b/src/pic.js @@ -413,7 +413,7 @@ PIC.prototype.set_state = function(state) this.isr = state[2]; this.irr = state[3]; this.is_master = state[4]; - this.slave = state[5]; + this.slave && this.slave.set_state(state[5]); this.expect_icw4 = state[6]; this.state = state[7]; this.read_isr = state[8]; diff --git a/src/state.js b/src/state.js index b4ee2978..6d7e15a4 100644 --- a/src/state.js +++ b/src/state.js @@ -90,82 +90,42 @@ function save_object(obj, saved_buffers) return result; } -const NO_BASE = Object.freeze({}); - -function restore_object(base, obj, buffers) +function restore_buffers(obj, buffers) { - // recursively restore obj into base - if(typeof obj !== "object" || obj === null) { dbg_assert(typeof obj !== "function"); return obj; } - if((base instanceof Array || base === NO_BASE) && obj instanceof Array) + if(obj instanceof Array) { - return obj.map(x => restore_object(NO_BASE, x, buffers)); + for(let i = 0; i < obj.length; i++) + { + obj[i] = restore_buffers(obj[i], buffers); + } + + return obj; } - var type = obj["__state_type__"]; + const type = obj["__state_type__"]; + dbg_assert(type !== undefined); - if(type === undefined) + const constructor = CONSTRUCTOR_TABLE[type]; + dbg_assert(constructor, "Unkown type: " + type); + + const info = buffers.infos[obj["buffer_id"]]; + + // restore large buffers by just returning a view on the state blob + // get_state is responsible for copying the data + if(info.length >= 1024 * 1024 && constructor === Uint8Array) { - if(DEBUG && base === undefined) - { - console.log("Cannot restore (base doesn't exist)", obj); - dbg_assert(false); - } - - if(DEBUG && !base.get_state) - { - console.log("No get_state:", base); - } - - var current = base.get_state(); - - dbg_assert(current.length === obj.length, "Cannot restore: Different number of properties"); - - for(var i = 0; i < obj.length; i++) - { - obj[i] = restore_object(current[i], obj[i], buffers); - } - - base.set_state(obj); - - return base; + return new Uint8Array(buffers.full, info.offset, info.length); } else { - var constructor = CONSTRUCTOR_TABLE[type]; - dbg_assert(constructor, "Unkown type: " + type); - - var info = buffers.infos[obj["buffer_id"]]; - - // restore large buffers by just returning a view on the state blob - if(info.length >= 1024 * 1024 && constructor === Uint8Array) - { - return new Uint8Array(buffers.full, info.offset, info.length); - } - // XXX: Disabled, unpredictable since it updates in-place, breaks pci - // and possibly also breaks restore -> save -> restore again - // avoid a new allocation if possible - //else if(base && - // base.constructor === constructor && - // base.byteOffset === 0 && - // base.byteLength === info.length) - //{ - // new Uint8Array(base.buffer).set( - // new Uint8Array(buffers.full, info.offset, info.length), - // base.byteOffset - // ); - // return base; - //} - else - { - var buf = buffers.full.slice(info.offset, info.offset + info.length); - return new constructor(buf); - } + var buf = buffers.full.slice(info.offset, info.offset + info.length); + return new constructor(buf); } } @@ -315,5 +275,6 @@ CPU.prototype.restore_state = function(state) infos: buffer_infos, }; - restore_object(this, state_object, buffers); + state_object = restore_buffers(state_object, buffers); + this.set_state(state_object); }; diff --git a/src/virtio.js b/src/virtio.js index 54c855d7..3cd849f9 100644 --- a/src/virtio.js +++ b/src/virtio.js @@ -923,7 +923,12 @@ VirtIO.prototype.set_state = function(state) this.config_generation = state[7]; this.isr_status = state[8]; this.queue_select = state[9]; - this.queues = state.slice(10); + let i = 0; + for(let queue of state.slice(10)) + { + this.queues[i].set_state(queue); + i++; + } this.queue_selected = this.queues[this.queue_select] || null; };