git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 6f92591fea03c67a9e18c1daab07a4ed7d693b21

Files: 6f92591fea03c67a9e18c1daab07a4ed7d693b21 / wasmContainer.js

5876 bytesRaw
1const {wasm2json, json2wasm} = require('wasm-json-toolkit')
2const wasmMetering = require('wasm-metering')
3const customTypes = require('./customTypes.js')
4const typeCheckWrapper = require('./typeCheckWrapper.js')
5const ReferanceMap = require('reference-map')
6
7const nativeTypes = new Set(['i32', 'i64', 'f32', 'f64'])
8const LANGUAGE_TYPES = {
9 'actor': 0x0,
10 'buf': 0x1,
11 'i32': 0x7f,
12 'i64': 0x7e,
13 'f32': 0x7d,
14 'f64': 0x7c,
15 'anyFunc': 0x70,
16 'func': 0x60,
17 'block_type': 0x40,
18
19 0x0: 'actor',
20 0x1: 'buf',
21 0x7f: 'i32',
22 0x7e: 'i64',
23 0x7d: 'f32',
24 0x7c: 'f64',
25 0x70: 'anyFunc',
26 0x60: 'func',
27 0x40: 'block_type'
28}
29
30class Ref {
31 serialize () {}
32}
33
34class FunctionRef {
35 constructor (json, name) {
36 this.name = name
37 this.args = []
38 const typeIndex = json.typeMap[name]
39 const type = json.type[typeIndex]
40 const wrapper = typeCheckWrapper(type)
41 const wasm = json2wasm(wrapper)
42 this.mod = WebAssembly.Module(wasm)
43 const self = this
44 const instance = WebAssembly.Instance(this.mod, {
45 'env': {
46 'checkTypes': function () {
47 const args = [...arguments]
48 while (args.length) {
49 const type = LANGUAGE_TYPES[args.shift()]
50 let arg = args.shift()
51 if (!nativeTypes.has(type)) {
52 arg = self._container.refs.get(arg)
53 if (arg.type !== type) {
54 throw new Error('invalid type')
55 }
56 }
57 self.args.push({
58 arg,
59 type
60 })
61 }
62 self._container.sendMessage(instance)
63 }
64 }
65 })
66 this.wrapper = instance
67 }
68 set container (container) {
69 this._container = container
70 }
71}
72
73module.exports = class WasmContainer {
74 constructor () {
75 this.refs = new ReferanceMap()
76 }
77 onCreation (wasm, id, cachedb) {
78 let moduleJSON = wasm2json(wasm)
79 this.json = mergeTypeSections(moduleJSON)
80 moduleJSON = wasmMetering.meterJSON(moduleJSON, {
81 meterType: 'i32'
82 })
83 this.wasm = json2wasm(moduleJSON)
84 this.mod = WebAssembly.Module(this.wasm)
85 }
86
87 sendMessage () {
88 console.log('send')
89 }
90
91 onMessage (funcRef) {
92 const self = this
93 const instance = WebAssembly.Instance(this.mod, {
94 func: {
95 externalize: () => {},
96 internalize: (ref, index) => {
97 const {type, arg} = self.refs.get(ref)
98 if (type !== 'funcRef') {
99 throw new Error('invalid type')
100 }
101 arg.container = self
102 instance.exports.table.set(index, arg.wrapper.exports.check)
103 },
104 catch: (ref, catchRef) => {
105 const {funcRef} = self.refs.get(ref, FunctionRef)
106 const {funcRef: catchFunc} = self.refs.get(ref, FunctionRef)
107 funcRef.catch = catchFunc
108 },
109 getGasAmount: () => {},
110 setGasAmount: () => {}
111 },
112 storage: {
113 load: () => {},
114 store: () => {},
115 delete: () => {}
116 },
117 link: {
118 wrap: (ref) => {
119 const obj = this.refs.get(ref)
120 obj.seriarlize()
121 },
122 unwrap: () => {}
123 },
124 databuf: {
125 create: () => {},
126 load8: () => {},
127 load16: () => {},
128 load32: () => {},
129 load64: () => {},
130 store8: () => {},
131 store16: () => {},
132 store32: () => {},
133 store64: () => {},
134 copy: () => {}
135 },
136 elembuf: {
137 create: () => {},
138 load: () => {},
139 store: () => {},
140 delete: () => {}
141 },
142 test: {
143 check: (a, b) => {
144 console.log('$$$$', a, b)
145 }
146 },
147 metering: {
148 usegas: (amount) => {
149 funcRef.gas -= amount
150 if (funcRef.gas < 0) {
151 throw new Error('out of gas! :(')
152 }
153 }
154 }
155 })
156 const args = funcRef.args.map(arg => {
157 if (nativeTypes.has(arg.type)) {
158 return arg.arg
159 } else {
160 return this.refs.add(arg)
161 }
162 })
163 instance.exports[funcRef.name](...args)
164 }
165
166 getFuncRef (name, send) {
167 const funcRef = new FunctionRef(this.json, name, send)
168 return funcRef
169 }
170}
171
172function mergeTypeSections (json) {
173 const typeInfo = {}
174 let typeSection = {
175 'entries': []
176 }
177 let importSection = {
178 'entries': []
179 }
180 let functionSection = {
181 'entries': []
182 }
183 let exportSection = {
184 'entries': []
185 }
186 json.forEach(section => {
187 switch (section.name) {
188 case 'type':
189 typeSection = section
190 break
191 case 'export':
192 exportSection = section
193 break
194 case 'import':
195 importSection = section
196 break
197 case 'function':
198 functionSection = section
199 break
200 case 'custom':
201 switch (section.sectionName) {
202 case 'type':
203 typeInfo.type = customTypes.decodeType(section.payload)
204 break
205 case 'typeMap':
206 typeInfo.typeMap = customTypes.decodeTypeMap(section.payload)
207 break
208 }
209 break
210 }
211 })
212
213 const foundTypes = new Map()
214 const mappedFuncs = new Map()
215 const newTypeMap = {}
216 typeInfo.typeMap.forEach(map => mappedFuncs.set(map.func, map.type))
217 for (let exprt of exportSection.entries) {
218 if (exprt.kind === 'function') {
219 if (!mappedFuncs.has(exprt.index)) {
220 const typeIndex = functionSection.entries[exprt.index - importSection.entries.length]
221 if (!foundTypes.has(typeIndex)) {
222 const customIndex = typeInfo.type.push(typeSection.entries[typeIndex]) - 1
223 foundTypes.set(typeIndex, customIndex)
224 }
225 const customIndex = foundTypes.get(typeIndex)
226 newTypeMap[exprt.field_str] = customIndex
227 } else {
228 newTypeMap[exprt.field_str] = mappedFuncs.get(exprt.index)
229 }
230 }
231 }
232
233 typeInfo.typeMap = newTypeMap
234 return typeInfo
235}
236

Built with git-ssb-web