Simplify recursive state handling (don't require get_state for set_state)
This commit is contained in:
parent
faadca9f35
commit
cd3f48c0a3
|
@ -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,
|
||||
|
|
|
@ -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])
|
||||
{
|
||||
|
|
34
src/cpu.js
34
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];
|
||||
|
||||
|
|
|
@ -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]);
|
||||
};
|
||||
|
|
|
@ -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];
|
||||
|
|
85
src/state.js
85
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);
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue