Skip to content

Commit

Permalink
fix: further cleanup based on reviews
Browse files Browse the repository at this point in the history
  • Loading branch information
FUDCo committed Oct 29, 2020
1 parent c101397 commit 848eda7
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 87 deletions.
2 changes: 0 additions & 2 deletions packages/SwingSet/src/kernel/liveSlots.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,6 @@ function build(syscall, forVatID, cacheSize, vatPowers, vatParameters) {
makeVirtualObjectRepresentative,
makeWeakStore,
makeKind,
flushCache,
} = makeVirtualObjectManager(
syscall,
allocateExportID,
Expand Down Expand Up @@ -569,7 +568,6 @@ function build(syscall, forVatID, cacheSize, vatPowers, vatParameters) {
const vatGlobals = harden({
makeWeakStore,
makeKind,
flushCache,
});

function setBuildRootObject(buildRootObject) {
Expand Down
57 changes: 33 additions & 24 deletions packages/SwingSet/src/kernel/virtualObjectManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,11 @@ import { parseVatSlot } from '../parseVatSlots';
export function makeCache(size, fetch, store) {
let lruHead;
let lruTail;
let count = 0;
const liveTable = new Map();

const cache = {
makeRoom() {
while (count > size && lruTail) {
while (liveTable.size > size && lruTail) {
liveTable.delete(lruTail.instanceKey);
store(lruTail.instanceKey, lruTail.rawData);
lruTail.rawData = null;
Expand All @@ -34,7 +33,6 @@ export function makeCache(size, fetch, store) {
lruHead = undefined;
}
lruTail = lruTail.prev;
count -= 1;
}
},
flush() {
Expand All @@ -47,9 +45,9 @@ export function makeCache(size, fetch, store) {
if (liveTable.has(innerObj.instanceKey)) {
return;
}
cache.makeRoom();
liveTable.set(innerObj.instanceKey, innerObj);
innerObj.prev = undefined;
cache.makeRoom();
innerObj.next = lruHead;
if (lruHead) {
lruHead.prev = innerObj;
Expand All @@ -58,7 +56,6 @@ export function makeCache(size, fetch, store) {
if (!lruTail) {
lruTail = innerObj;
}
count += 1;
},
refresh(innerObj) {
if (innerObj !== lruHead) {
Expand Down Expand Up @@ -280,60 +277,72 @@ export function makeVirtualObjectManager(
const kindID = `${allocateExportID()}`;
let nextInstanceID = 1;

function makeRepresentative(innerSelf) {
function makeRepresentative(innerSelf, initializing) {
function ensureState() {
if (!innerSelf.rawData) {
innerSelf = cache.lookup(innerSelf.instanceKey);
}
}

function wrapData() {
const activeData = {};
function wrapData(target) {
for (const prop of Object.getOwnPropertyNames(innerSelf.rawData)) {
Object.defineProperty(activeData, prop, {
Object.defineProperty(target, prop, {
get: () => {
ensureState();
ensureState(innerSelf);
return m.unserialize(innerSelf.rawData[prop]);
},
set: value => {
ensureState();
innerSelf.rawData[prop] = m.serialize(value);
const serializedValue = m.serialize(value);
ensureState(innerSelf);
innerSelf.rawData[prop] = serializedValue;
},
});
}
return harden(activeData);
innerSelf.wrapData = undefined;
harden(target);
}

const representative = instanceMaker(wrapData());
delete representative.initialize;
harden(representative);
let representative;
if (initializing) {
innerSelf.wrapData = wrapData;
representative = instanceMaker(innerSelf.rawData);
} else {
const activeData = {};
wrapData(activeData);
representative = instanceMaker(activeData);
delete representative.initialize;
harden(representative);
}
cache.remember(innerSelf);
valToSlotTable.set(representative, innerSelf.instanceKey);
return representative;
}

function reanimate(instanceKey) {
return makeRepresentative(cache.lookup(instanceKey));
return makeRepresentative(cache.lookup(instanceKey), false);
}
kindTable.set(kindID, reanimate);

function makeNewInstance(...args) {
const instanceKey = `o+${kindID}/${nextInstanceID}`;
nextInstanceID += 1;

const initializationData = {};
const tempInstance = instanceMaker(initializationData);
tempInstance.initialize(...args);
const initialData = {};
const innerSelf = { instanceKey, rawData: initialData };
const initialRepresentative = makeRepresentative(innerSelf, true);
initialRepresentative.initialize(...args);
const rawData = {};
for (const prop of Object.getOwnPropertyNames(initializationData)) {
for (const prop of Object.getOwnPropertyNames(initialData)) {
try {
rawData[prop] = m.serialize(initializationData[prop]);
rawData[prop] = m.serialize(initialData[prop]);
} catch (e) {
console.error(`state property ${prop} is not serializable`);
throw e;
}
}
const innerSelf = { instanceKey, rawData };
return makeRepresentative(innerSelf);
innerSelf.rawData = rawData;
innerSelf.wrapData(initialData);
return initialRepresentative;
}

return makeNewInstance;
Expand Down
133 changes: 79 additions & 54 deletions packages/SwingSet/test/test-virtualObjectManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ function capdata(body, slots = []) {
}
const s = JSON.stringify;

test('virtual objects', t => {
function makeAllTheStuff(cacheSize) {
const fakeStore = new Map();

function dumpStore() {
Expand Down Expand Up @@ -49,7 +49,7 @@ test('virtual objects', t => {
fakeAllocateExportID,
valToSlot,
fakeMarshal,
3,
cacheSize,
);

function fakeConvertValToSlot(val) {
Expand All @@ -66,60 +66,70 @@ test('virtual objects', t => {
return makeVirtualObjectRepresentative(slot);
}

function makeThingInstance(state) {
return {
initialize(label = 'thing', counter = 0) {
state.counter = counter;
state.label = label;
state.resetCounter = 0;
},
inc() {
state.counter += 1;
return state.counter;
},
reset(newStart) {
state.counter = newStart;
state.resetCounter += 1;
return state.resetCounter;
},
relabel(newLabel) {
state.label = newLabel;
},
get() {
return state.counter;
},
describe() {
return `${state.label} counter has been reset ${state.resetCounter} times and is now ${state.counter}`;
},
};
}
return {
makeWeakStore,
makeKind,
flushCache,
dumpStore,
};
}

const thingMaker = makeKind(makeThingInstance);
function makeThingInstance(state) {
return {
initialize(label = 'thing', counter = 0) {
state.counter = counter;
state.label = label;
state.resetCounter = 0;
},
inc() {
state.counter += 1;
return state.counter;
},
reset(newStart) {
state.counter = newStart;
state.resetCounter += 1;
return state.resetCounter;
},
relabel(newLabel) {
state.label = newLabel;
},
get() {
return state.counter;
},
describe() {
return `${state.label} counter has been reset ${state.resetCounter} times and is now ${state.counter}`;
},
};
}

function makeZotInstance(state) {
return {
initialize(arbitrary = 47, name = 'Bob', tag = 'say what?') {
state.arbitrary = arbitrary;
state.name = name;
state.tag = tag;
state.count = 0;
},
sayHello(msg) {
state.count += 1;
return `${msg} ${state.name}`;
},
rename(newName) {
state.name = newName;
state.count += 1;
return state.name;
},
getInfo() {
state.count += 1;
return `zot ${state.name} tag=${state.tag} count=${state.count} arbitrary=${state.arbitrary}`;
},
};
}
function makeZotInstance(state) {
return {
initialize(arbitrary = 47, name = 'Bob', tag = 'say what?') {
state.arbitrary = arbitrary;
state.name = name;
state.tag = tag;
state.count = 0;
},
sayHello(msg) {
state.count += 1;
return `${msg} ${state.name}`;
},
rename(newName) {
state.name = newName;
state.count += 1;
return state.name;
},
getInfo() {
state.count += 1;
return `zot ${state.name} tag=${state.tag} count=${state.count} arbitrary=${state.arbitrary}`;
},
};
}

test('virtual object operations', t => {
const { makeKind, flushCache, dumpStore } = makeAllTheStuff(3);

const thingMaker = makeKind(makeThingInstance);
const zotMaker = makeKind(makeZotInstance);

// phase 0: start
Expand All @@ -135,6 +145,7 @@ test('virtual objects', t => {
const zot2 = zotMaker(29, 'Bob', 'what are you saying?');
const zot3 = zotMaker(47, 'Carol', 'as if...');
const zot4 = zotMaker(66, 'Dave', 'you and what army?');

// prettier-ignore
t.deepEqual(dumpStore(), [
['o+1/1', s({counter:capdata('0'),label:capdata('"thing-1"'),resetCounter:capdata('0')})],
Expand Down Expand Up @@ -212,8 +223,22 @@ test('virtual objects', t => {
['o+2/3', s({arbitrary:capdata('47'),name:capdata('"Chester"'),tag:capdata('"as if..."'),count:capdata('3')})],
['o+2/4', s({arbitrary:capdata('66'),name:capdata('"Dave"'),tag:capdata('"you and what army?"'),count:capdata('2')})],
]);
});

test('weak store operations', t => {
const { makeWeakStore, makeKind } = makeAllTheStuff(3);

const thingMaker = makeKind(makeThingInstance);
const zotMaker = makeKind(makeZotInstance);

const thing1 = thingMaker('t1');
const thing2 = thingMaker('t2');

const zot1 = zotMaker(1, 'z1');
const zot2 = zotMaker(2, 'z2');
const zot3 = zotMaker(3, 'z3');
const zot4 = zotMaker(4, 'z4');

// phase 5: test weakStore
const ws1 = makeWeakStore();
const ws2 = makeWeakStore();
const nv1 = {};
Expand Down
7 changes: 1 addition & 6 deletions packages/swingset-runner/demo/vatStore1/vat-bob.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* global makeKind flushCache */
/* global makeKind */
const p = console.log;

function makeThingInstance(state) {
Expand Down Expand Up @@ -119,11 +119,6 @@ export function buildRootObject(_vatPowers) {
thing3.inc();
p(`${thing4.describe()}`);
break;
case 4:
p('phase 4: flush test');
thing1.inc();
flushCache();
break;
default:
// because otherwise eslint complains
break;
Expand Down
3 changes: 2 additions & 1 deletion packages/xs-vat-worker/src/vatWorker.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ function makeWorker(io, setImmediate) {
workerLog(`got start`);
sendUplink(['gotStart']);
} else if (type === 'setBundle') {
const [bundle, vatParameters] = margs;
const [bundle, vatParameters, virtualObjectCacheSize] = margs;
const endowments = {
console: makeConsole(`SwingSet:vatWorker`),
HandledPromise,
Expand Down Expand Up @@ -149,6 +149,7 @@ function makeWorker(io, setImmediate) {
vatID,
vatPowers,
vatParameters,
virtualObjectCacheSize,
);
workerLog(`got dispatch:`, Object.keys(dispatch).join(','));
sendUplink(['dispatchReady']);
Expand Down

0 comments on commit 848eda7

Please sign in to comment.