Simplify recursive state handling (don't require get_state for set_state)

This commit is contained in:
Fabian 2020-12-31 19:14:32 -06:00
parent faadca9f35
commit cd3f48c0a3
7 changed files with 57 additions and 87 deletions

View file

@ -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,

View file

@ -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])
{

View file

@ -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];

View file

@ -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]);
};

View file

@ -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];

View file

@ -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);
};

View file

@ -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;
};