git ssb

0+

wanderer🌟 / wasm-persist



Tree: ef2bd6aff34a889b871ba0df64660c209670a621

Files: ef2bd6aff34a889b871ba0df64660c209670a621 / index.js

3686 bytesRaw
1const inject = require('./injectGettersSetters.js')
2
3/**
4 * Prepares a binary by injecting getter and setter function for memory, globals and tables.
5 * @param {ArrayBuffer} binary - a wasm binary
6 * @param {Object} include
7 * @param {Boolean} [include.memory=true] - whether or not to included memory
8 * @param {Boolean} [include.table=true] - whether or not to included the function table
9 * @param {Array.<Boolean>} [include.globals=Array.<true>] - whether or not to
10 * included a given global. Each index in the array stands for a global index.
11 * Indexes that are set to false or left undefined will not be persisted. By
12 * default all globals are persisted.
13 * @param {String} [symbol = '_'] - a sting used to prefix the injected setter and getter functions
14 * @return {ArrayBuffer} the resulting wasm binary
15 */
16function prepare (binary, include = {memory: true, table: true}, symbol = '_') {
17 return inject(binary, include, symbol)
18}
19
20/**
21 * Given a wasm Instance this will produce an Object containing the current state of
22 * the instance
23 * @param {Webassembly.Instance} instance
24 * @param {String} symbol - the symbol that will be used to find the injected functions
25 * @returns {Object} the state of the wasm instance
26 */
27function hibernate (instance, symbol = '_') {
28 const json = {
29 globals: [],
30 table: [],
31 symbol
32 }
33 for (const key in instance.exports) {
34 const val = instance.exports[key]
35 if (key.startsWith(symbol)) {
36 const keyElems = key.slice(symbol.length).split('_')
37 // save the memory
38 if (val instanceof WebAssembly.Memory) {
39 json.memory = new Uint32Array(val.buffer)
40 } else if (val instanceof WebAssembly.Table) {
41 // mark the tables, (do something for external function?)
42 // the external functions should have a callback
43 for (let i = 0; i < val.length; i++) {
44 const func = val.get(i)
45 if (func === instance.exports[`${symbol}func_${func.name}`]) {
46 json.table.push(func.name)
47 }
48 }
49 } else if (keyElems[0] === 'global' && keyElems[1] === 'getter') {
50 // save the globals
51 const last = keyElems.pop()
52 if (last === 'high') {
53 json.globals.push([instance.exports[key]()])
54 } else if (last === 'low') {
55 json.globals[json.globals.length - 1].push(instance.exports[key]())
56 } else {
57 json.globals.push(instance.exports[key]())
58 }
59 }
60 }
61 }
62 instance.__hibrenated = true
63 return json
64}
65
66/**
67 * resumes a prevously hibranted webassembly instance
68 * @param {WebAssemby.Instance} instance
69 * @param {Object} state - the pervous state of the wasm instance
70 * @retrun {WebAssembly.Instance}
71 */
72function resume (instance, state) {
73 if (instance.__hibrenated) {
74 instance.__hibrenated = false
75 } else {
76 // initailize memory
77 const mem = instance.exports[`${state.symbol}memory`]
78 if (mem) {
79 // console.log(mem.length)
80 (new Uint32Array(mem.buffer)).set(state.memory, 0)
81 }
82
83 // initailize table
84 if (instance.exports._table) {
85 for (const index in state.table) {
86 const funcIndex = state.table[index]
87 instance.exports._table.set(index, instance.exports[`${state.symbol}func_${funcIndex}`])
88 }
89 }
90
91 // intialize globals
92 for (const index in state.globals) {
93 const val = state.globals[index]
94 if (Array.isArray(val)) {
95 instance.exports[`${state.symbol}global_setter_i64_${index}`](val[1], val[0])
96 } else {
97 instance.exports[`${state.symbol}global_setter_i32_${index}`](val)
98 }
99 }
100 }
101 return instance
102}
103
104module.exports = {
105 prepare,
106 hibernate,
107 resume
108}
109

Built with git-ssb-web