UNPKG

microvium

Version:

A compact, embeddable scripting engine for microcontrollers for executing small scripts written in a subset of JavaScript.

202 lines (198 loc) 10.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const lib_1 = require("../lib"); const chai_1 = require("chai"); suite('minimal-size', function () { const corePointerCount = 6; const coreLongPointerCount = 1; const coreOptionalInt32Count = 1; const coreWordCount = 4; // includes 2 single-byte fields const coreOptionalPointerCount = 2; // In the following, "optional features" refers to debug capability and gas counter // The expected size on a 64-bit machine with optional features enabled const coreSize64BitMax = roundUpTo8Bytes((corePointerCount + coreLongPointerCount + coreOptionalPointerCount) * 8 + coreOptionalInt32Count * 4 + coreWordCount * 2); // The core size on a 32-bit embedded device, with optional features const coreSize32BitMax = (corePointerCount + coreLongPointerCount + coreOptionalPointerCount) * 4 + coreOptionalInt32Count * 4 + coreWordCount * 2; // The core size on a 32-bit embedded device, without optional features const coreSize32BitMin = (corePointerCount + coreLongPointerCount) * 4 + coreWordCount * 2; // The core size on a 16-bit embedded device, without optional features const coreSize16BitMin = corePointerCount * 2 + coreLongPointerCount * 4 + coreWordCount * 2; test('no-lib', () => { /* This tests the smallest theoretical size for Microvium (see the assertions at the end of this function): - No builtins - No debugger support - 32-bit or 16-bit device The tests are run on this machine, which is a 64-bit machine (please run these tests with the 64-bit version of node.js, so these results are consistent). This is inferring the 16-bit and 32-bit by calculating the expected size on a 16-, 32-, and 64-bit platforms and then asserting the 64-bit size and assuming then that the 16-bit and 32-bit sizes are also correct. */ const vm = lib_1.Microvium.create({}, { noLib: true }); vm.evaluateModule({ sourceText: '' }); const snapshot = vm.createSnapshot(); chai_1.assert.equal(snapshot.data.length, 46); // Note: because we're not running this on an emulator, this is the size as // running on a 64-bit machine. Also, debug mode is enabled const vm2 = lib_1.Microvium.restore(snapshot, {}); const stats = vm2.getMemoryStats(); chai_1.assert.equal(stats.totalSize, coreSize64BitMax); chai_1.assert.equal(stats.coreSize, coreSize64BitMax); chai_1.assert.equal(stats.fragmentCount, 1); chai_1.assert.equal(stats.virtualHeapAllocatedCapacity, 0); chai_1.assert.equal(stats.virtualHeapUsed, 0); chai_1.assert.equal(stats.virtualHeapHighWaterMark, 0); chai_1.assert.equal(stats.stackHighWaterMark, 0); chai_1.assert.equal(stats.stackHeight, 0); chai_1.assert.equal(stats.stackAllocatedCapacity, 0); chai_1.assert.equal(stats.registersSize, 0); chai_1.assert.equal(stats.importTableSize, 0); chai_1.assert.equal(stats.globalVariablesSize, 0); chai_1.assert.equal(coreSize64BitMax, 88); chai_1.assert.equal(coreSize32BitMax, 48); // Smallest theoretical size: chai_1.assert.equal(coreSize32BitMin, 36); chai_1.assert.equal(coreSize16BitMin, 24); }); test('empty-size', () => { const vm = lib_1.Microvium.create({}, {}); vm.evaluateModule({ sourceText: '' }); const snapshot = vm.createSnapshot(); chai_1.assert.equal(snapshot.data.length, 46); const vm2 = lib_1.Microvium.restore(snapshot, {}); const stats = vm2.getMemoryStats(); chai_1.assert.equal(stats.totalSize, 88); chai_1.assert.equal(stats.coreSize, 88); chai_1.assert.equal(stats.fragmentCount, 1); chai_1.assert.equal(stats.virtualHeapAllocatedCapacity, 0); chai_1.assert.equal(stats.virtualHeapUsed, 0); chai_1.assert.equal(stats.virtualHeapHighWaterMark, 0); chai_1.assert.equal(stats.stackHighWaterMark, 0); chai_1.assert.equal(stats.stackHeight, 0); chai_1.assert.equal(stats.stackAllocatedCapacity, 0); chai_1.assert.equal(stats.registersSize, 0); chai_1.assert.equal(stats.importTableSize, 0); chai_1.assert.equal(stats.globalVariablesSize, 0); }); test('running-size', () => { const vm = lib_1.Microvium.create({}, {}); /* This tests the size of the VM when actually running. Like with the no-lib test, I calculate what the size should be on different platforms and then assert the size for this platform to test the assumptions. This one is not compiled with noLib. The idea here is that this a "typical" usage of the engine rather than completely minimal. This amount of space is what you'd reasonably expect for a roughly-empty program. */ const pointerRegisterCount = 4; const longPointerRegisterCount = 1; const wordRegisterCount = 4; const optionalWordRegisterCount = 1; // Includes single-byte `usingCachedRegisters` const registersSize64BitMax = padTo64Bit(pointerRegisterCount * 8 + longPointerRegisterCount * 8 + wordRegisterCount * 2 + optionalWordRegisterCount * 2); const registersSize32BitMax = padTo32Bit(pointerRegisterCount * 4 + longPointerRegisterCount * 4 + wordRegisterCount * 2 + optionalWordRegisterCount * 2); const registersSize32BitMin = padTo32Bit(pointerRegisterCount * 4 + longPointerRegisterCount * 4 + wordRegisterCount * 2); const registersSize16BitMin = pointerRegisterCount * 2 + longPointerRegisterCount * 4 + wordRegisterCount * 2; const importTableCount = 1; // This example imports one function const importTableSize64Bit = importTableCount * 8; const importTableSize32Bit = importTableCount * 4; const importTableSize16Bit = importTableCount * 4; // Using 4 bytes here because flash pointer const globalVariablesSize = 2; // 1 global variable at 2 bytes each const virtualHeapSize = 0; // Now that builtins are GC'd, the virtual heap can be empty const defaultStackCapacity = 256; const heapOverheadSize64Bit = 4 * 8; const heapOverheadSize32Bit = 4 * 4; const heapOverheadSize16Bit = 4 * 2; const totalSize64BitMax = coreSize64BitMax + importTableSize64Bit + globalVariablesSize + registersSize64BitMax + defaultStackCapacity + virtualHeapSize + (virtualHeapSize ? heapOverheadSize64Bit : 0); const totalSize32BitMin = coreSize32BitMin + importTableSize32Bit + globalVariablesSize + registersSize32BitMin + defaultStackCapacity + virtualHeapSize + (virtualHeapSize ? heapOverheadSize32Bit : 0); const totalSize32BitMax = coreSize32BitMax + importTableSize32Bit + globalVariablesSize + registersSize32BitMax + defaultStackCapacity + virtualHeapSize + (virtualHeapSize ? heapOverheadSize32Bit : 0); const totalSize16BitMin = coreSize16BitMin + importTableSize16Bit + globalVariablesSize + registersSize16BitMin + defaultStackCapacity + virtualHeapSize + (virtualHeapSize ? heapOverheadSize16Bit : 0); vm.globalThis.vmImport = vm.vmImport; vm.globalThis.vmExport = vm.vmExport; vm.evaluateModule({ sourceText: ` const checkSize = vmImport(0); vmExport(0, () => checkSize()); ` }); const snapshot = vm.createSnapshot(); chai_1.assert.equal(snapshot.data.length, 70); const vm2 = lib_1.Microvium.restore(snapshot, { 0: checkSize }); let stats = undefined; const run = vm2.resolveExport(0); run(); function checkSize() { stats = vm2.getMemoryStats(); } chai_1.assert.equal(stats.totalSize, totalSize64BitMax); chai_1.assert.equal(stats.coreSize, coreSize64BitMax); chai_1.assert.equal(stats.fragmentCount, 2); chai_1.assert.equal(stats.virtualHeapAllocatedCapacity, virtualHeapSize); chai_1.assert.equal(stats.virtualHeapUsed, virtualHeapSize); chai_1.assert.equal(stats.virtualHeapHighWaterMark, virtualHeapSize); chai_1.assert.equal(stats.stackHighWaterMark, 26); chai_1.assert.equal(stats.stackHeight, 18); chai_1.assert.equal(stats.stackAllocatedCapacity, defaultStackCapacity); chai_1.assert.equal(stats.registersSize, registersSize64BitMax); chai_1.assert.equal(stats.importTableSize, importTableSize64Bit); chai_1.assert.equal(stats.globalVariablesSize, 2); // The following is the final figures. Just update them manually when they change chai_1.assert.equal(registersSize64BitMax, 56); chai_1.assert.equal(registersSize32BitMax, 32); chai_1.assert.equal(registersSize32BitMin, 28); chai_1.assert.equal(registersSize16BitMin, 20); chai_1.assert.equal(totalSize64BitMax, 410); chai_1.assert.equal(totalSize32BitMax, 342); chai_1.assert.equal(totalSize32BitMin, 326); chai_1.assert.equal(totalSize16BitMin, 306); }); }); function padTo64Bit(n) { return Math.ceil(n / 8) * 8; } function padTo32Bit(n) { return Math.ceil(n / 4) * 4; } function roundUpTo8Bytes(n) { return Math.ceil(n / 8) * 8; } //# sourceMappingURL=minimal-size.test.js.map