index.jsView |
---|
18 | 18 | return new ModuleRef(exports, id) |
19 | 19 | } |
20 | 20 | |
21 | 21 | function generateWrapper (funcRef, container) { |
| 22 | + |
| 23 | + if (funcRef.wrapper) { |
| 24 | + return funcRef.wrapper |
| 25 | + } |
22 | 26 | let wrapper = typeCheckWrapper(funcRef.params) |
23 | 27 | const wasm = json2wasm(wrapper) |
| 28 | + const fs = require('fs') |
| 29 | + fs.writeFileSync('./checker.wasm', wasm) |
24 | 30 | const mod = WebAssembly.Module(wasm) |
25 | 31 | const self = funcRef |
26 | 32 | wrapper = WebAssembly.Instance(mod, { |
27 | 33 | 'env': { |
32 | 38 | const type = annotations.LANGUAGE_TYPES_BIN[args.shift()] |
33 | 39 | let arg = args.shift() |
34 | 40 | if (!nativeTypes.has(type)) { |
35 | 41 | arg = container.refs.get(arg, type) |
| 42 | + checkedArgs.push(arg) |
| 43 | + } else if (type === 'i64') { |
| 44 | + checkedArgs.push(arg) |
| 45 | + checkedArgs.push(args.shift()) |
| 46 | + } else { |
| 47 | + checkedArgs.push(arg) |
36 | 48 | } |
37 | | - checkedArgs.push(arg) |
38 | 49 | } |
39 | 50 | const message = new Message({ |
40 | 51 | funcRef: self, |
41 | 52 | funcArguments: checkedArgs |
43 | 54 | container.actor.send(message) |
44 | 55 | } |
45 | 56 | } |
46 | 57 | }) |
| 58 | + |
| 59 | + funcRef.wrapper = wrapper |
47 | 60 | wrapper.exports.check.object = funcRef |
48 | 61 | return wrapper |
49 | 62 | } |
50 | 63 | |
88 | 101 | const self = this |
89 | 102 | return { |
90 | 103 | func: { |
91 | 104 | externalize: index => { |
92 | | - const func = this.instance.exports.table.get(index) |
| 105 | + const func = self.instance.exports.table.get(index) |
93 | 106 | const object = func.object |
94 | 107 | if (object) { |
95 | 108 | |
96 | 109 | return self.refs.add(object) |
106 | 119 | }, |
107 | 120 | internalize: (index, ref) => { |
108 | 121 | const funcRef = self.refs.get(ref, 'func') |
109 | 122 | const wrapper = generateWrapper(funcRef, self) |
110 | | - this.instance.exports.table.set(index, wrapper.exports.check) |
| 123 | + self.instance.exports.table.set(index, wrapper.exports.check) |
111 | 124 | }, |
112 | | - |
113 | | - |
114 | | - |
115 | | - |
116 | | - |
117 | 125 | get_gas_budget: (funcRef) => { |
118 | 126 | const func = self.refs.get(funcRef, 'func') |
119 | 127 | return func.gas |
120 | 128 | }, |
124 | 132 | } |
125 | 133 | }, |
126 | 134 | link: { |
127 | 135 | wrap: ref => { |
128 | | - const obj = this.refs.get(ref) |
| 136 | + const obj = self.refs.get(ref) |
129 | 137 | const link = {'/': obj} |
130 | | - return this.refs.add(link, 'link') |
| 138 | + return self.refs.add(link, 'link') |
131 | 139 | }, |
132 | 140 | unwrap: async (ref, cb) => { |
133 | | - const obj = this.refs.get(ref, 'link') |
134 | | - const promise = this.actor.tree.dataStore.get(obj) |
135 | | - await this._opsQueue.push(promise) |
| 141 | + const obj = self.refs.get(ref, 'link') |
| 142 | + const promise = self.actor.tree.dataStore.get(obj) |
| 143 | + await self._opsQueue.push(promise) |
136 | 144 | } |
137 | 145 | }, |
138 | 146 | module: { |
139 | 147 | new: dataRef => { |
140 | | - const mod = this.actor.createActor(dataRef) |
141 | | - return this.refs.add(mod, 'mod') |
| 148 | + const mod = self.actor.createActor(dataRef) |
| 149 | + return self.refs.add(mod, 'mod') |
142 | 150 | }, |
143 | 151 | export: (modRef, dataRef) => { |
144 | | - const mod = this.refs.get(modRef, 'mod') |
145 | | - let name = this.refs.get(dataRef, 'data') |
| 152 | + const mod = self.refs.get(modRef, 'mod') |
| 153 | + let name = self.refs.get(dataRef, 'data') |
146 | 154 | name = Buffer.from(name).toString() |
147 | 155 | const funcRef = mod.getFuncRef(name) |
148 | | - return this.refs.add(funcRef, 'func') |
| 156 | + return self.refs.add(funcRef, 'func') |
149 | 157 | }, |
150 | 158 | self: () => { |
151 | | - return this.refs.add(this.modSelf, 'mod') |
| 159 | + return self.refs.add(this.modSelf, 'mod') |
152 | 160 | } |
153 | 161 | }, |
154 | 162 | memory: { |
155 | 163 | externalize: (index, length) => { |
156 | 164 | const data = Buffer.from(this.get8Memory(index, length)) |
157 | | - return this.refs.add(data, 'data') |
| 165 | + return self.refs.add(data, 'data') |
158 | 166 | }, |
159 | 167 | internalize: (dataRef, srcOffset, sinkOffset, length) => { |
160 | | - let data = this.refs.get(dataRef, 'data') |
| 168 | + let data = self.refs.get(dataRef, 'data') |
161 | 169 | data = data.subarray(srcOffset, length) |
162 | | - const mem = this.get8Memory(sinkOffset, data.length) |
| 170 | + const mem = self.get8Memory(sinkOffset, data.length) |
163 | 171 | mem.set(data) |
164 | 172 | }, |
165 | 173 | length (dataRef) { |
166 | | - let data = this.refs.get(dataRef, 'data') |
| 174 | + let data = self.refs.get(dataRef, 'data') |
167 | 175 | return data.length |
168 | 176 | } |
169 | 177 | }, |
170 | | - table: { |
| 178 | + elem: { |
171 | 179 | externalize: (index, length) => { |
172 | 180 | const mem = Buffer.from(this.get8Memory(index, length * 4)) |
173 | 181 | const objects = [] |
174 | 182 | while (length--) { |
175 | 183 | const ref = mem.readUInt32LE(length * 4) |
176 | | - const obj = this.refs.get(ref) |
| 184 | + const obj = self.refs.get(ref) |
177 | 185 | objects.unshift(obj) |
178 | 186 | } |
179 | 187 | return this.refs.add(objects, 'elem') |
180 | 188 | }, |
181 | 189 | internalize: (elemRef, srcOffset, sinkOffset, length) => { |
182 | | - let table = this.refs.get(elemRef, 'elem') |
183 | | - const buf = table.slice(srcOffset, srcOffset + length).map(obj => this.refs.add(obj)) |
184 | | - const mem = this.get32Memory(sinkOffset, length) |
| 190 | + let table = self.refs.get(elemRef, 'elem') |
| 191 | + const buf = table.slice(srcOffset, srcOffset + length).map(obj => self.refs.add(obj)) |
| 192 | + const mem = self.get32Memory(sinkOffset, length) |
185 | 193 | mem.set(buf) |
186 | 194 | }, |
187 | 195 | length (elemRef) { |
188 | | - let elem = this.refs.get(elemRef, 'elem') |
| 196 | + let elem = self.refs.get(elemRef, 'elem') |
189 | 197 | return elem.length |
190 | 198 | } |
191 | 199 | }, |
192 | 200 | metering: { |
193 | 201 | usegas: amount => { |
194 | | - this.actor.incrementTicks(amount) |
| 202 | + self.actor.incrementTicks(amount) |
195 | 203 | funcRef.gas -= amount |
196 | | - if (funcRef.gas < 0) { |
197 | | - throw new Error('out of gas! :(') |
198 | | - } |
| 204 | + |
| 205 | + |
| 206 | + |
199 | 207 | } |
200 | 208 | } |
201 | 209 | } |
202 | 210 | } |
216 | 224 | } |
217 | 225 | } |
218 | 226 | } |
219 | 227 | |
220 | | - const args = message.funcArguments.map((arg, index) => { |
221 | | - const type = funcRef.params[index] |
| 228 | + let index = 0 |
| 229 | + const args = [] |
| 230 | + message.funcRef.params.forEach(type => { |
| 231 | + const arg = message.funcArguments[index] |
222 | 232 | if (nativeTypes.has(type)) { |
223 | | - return arg |
| 233 | + args.push(arg) |
| 234 | + if (type === 'i64') { |
| 235 | + args.push(message.funcArguments[++index]) |
| 236 | + } |
224 | 237 | } else { |
225 | | - return this.refs.add(arg, type) |
| 238 | + args.push(this.refs.add(arg, type)) |
226 | 239 | } |
| 240 | + index++ |
227 | 241 | }) |
228 | 242 | |
229 | 243 | |
230 | 244 | let numOfGlobals = this.json.persist.length |
237 | 251 | this.instance.exports.setter_globals(...refs) |
238 | 252 | } |
239 | 253 | |
240 | 254 | |
| 255 | + let wasmFunc |
241 | 256 | if (funcRef.identifier[0]) { |
242 | | - this.instance.exports.table.get(funcRef.identifier[1])(...args) |
| 257 | + wasmFunc = this.instance.exports.table.get(funcRef.identifier[1]) |
243 | 258 | } else { |
244 | | - this.instance.exports[funcRef.identifier[1]](...args) |
| 259 | + wasmFunc = this.instance.exports[funcRef.identifier[1]] |
245 | 260 | } |
| 261 | + |
| 262 | + const wrapper = generateWrapper(funcRef) |
| 263 | + wrapper.exports.table.set(0, wasmFunc) |
| 264 | + wrapper.exports.invoke(...args) |
246 | 265 | await this.onDone() |
247 | 266 | |
248 | 267 | |
249 | 268 | numOfGlobals = this.json.persist.length |