git ssb

0+

wanderer🌟 / js-primea-hypervisor



Commit c1baf026f5fba05cb5619603b350445d6e40a0d5

fix merge sections

wanderer committed on 2/14/2018, 9:31:02 PM
Parent: 69542e9b41cc18d3434269b364a714712a5a5631

Files changed

customTypes.jschanged
tests/wasm/caller.wasmchanged
tests/wasm/elem.wasmadded
tests/wasm/funcRef_caller.wasmadded
tests/wasm/funcRef_reciever.wasmadded
tests/wasmContainer.jschanged
tests/wast/elem.wastadded
tests/wast/funcRef_caller.jsonadded
tests/wast/funcRef_caller.wastadded
tests/wast/funcRef_reciever.jsonadded
tests/wast/funcRef_reciever.wastadded
tests/wast2wasm.jschanged
wasmContainer.jschanged
customTypes.jsView
@@ -131,13 +131,81 @@
131131 const buf = encodeJSON(json)
132132 return injectCustomSection(buf, wasm)
133133 }
134134
135+function mergeTypeSections (json) {
136+ const result = {
137+ types: [],
138+ indexes: {},
139+ exports: {}
140+ }
141+ const iterator = findSections(json)
142+ const mappedFuncs = new Map()
143+ const mappedTypes = new Map()
144+ iterator.next()
145+ const {value: customType} = iterator.next('custom')
146+ if (customType) {
147+ const type = decodeType(customType.payload)
148+ result.types = type
149+ }
150+ let {value: typeMap} = iterator.next('custom')
151+ if (typeMap) {
152+ decodeTypeMap(typeMap.payload).forEach(map => mappedFuncs.set(map.func, map.type))
153+ }
154+
155+ const {value: type} = iterator.next('type')
156+ const {value: imports = {entries: []}} = iterator.next('import')
157+ const {value: functions} = iterator.next('function')
158+ functions.entries.forEach((typeIndex, funcIndex) => {
159+ let customIndex = mappedFuncs.get(funcIndex)
160+ if (customIndex === undefined) {
161+ customIndex = mappedTypes.get(typeIndex)
162+ }
163+ if (customIndex === undefined) {
164+ customIndex = result.types.push(type.entries[typeIndex]) - 1
165+ mappedTypes.set(typeIndex, customIndex)
166+ }
167+ result.indexes[funcIndex + imports.entries.length] = customIndex
168+ })
169+
170+ const {value: exports = {entries: []}} = iterator.next('export')
171+ exports.entries.forEach(entry => {
172+ if (entry.kind === 'function') {
173+ result.exports[entry.field_str] = entry.index
174+ }
175+ })
176+ return result
177+}
178+
179+const wantedSections = new Set(['custom', 'type', 'function', 'export', 'import'])
180+
181+function * findSections (array) {
182+ let section = array[0]
183+ let index = 0
184+ let nextSection = yield null
185+
186+ while (section) {
187+ if (!wantedSections.has(section.name)) {
188+ index++
189+ section = array[index]
190+ } else {
191+ if (section.name === nextSection) {
192+ nextSection = yield section
193+ index++
194+ section = array[index]
195+ } else {
196+ nextSection = yield null
197+ }
198+ }
199+ }
200+}
201+
135202 module.exports = {
136203 injectCustomSection,
137204 inject,
138205 decodeType,
139206 decodeTypeMap,
140207 encodeType,
141208 encodeTypeMap,
142- encodeJSON
209+ encodeJSON,
210+ mergeTypeSections
143211 }
tests/wasm/caller.wasmView
@@ -1,3 +1,4 @@
1-asm
1+asm
2+type`` typeMap
23 ``func internalizeptablecall
34 A AA
tests/wasm/elem.wasmView
@@ -1,0 +1,3 @@
1+asm
2+``func internalizeptablereceive A 
3+A AA
tests/wasm/funcRef_caller.wasmView
@@ -1,0 +1,3 @@
1+asm
2+type`` typeMap````@func internalizetestcheckmoduleselfmoduleexportsp$memorytablecallcallback
3+ AAA A  A A callback
tests/wasm/funcRef_reciever.wasmView
@@ -1,0 +1,4 @@
1+asm
2+type`` typeMap
3+``func internalizeptablereceive
4+ AAA
tests/wasmContainer.jsView
@@ -34,9 +34,9 @@
3434 return this.refs.add(obj)
3535 }
3636 }
3737
38-tape.only('basic', async t => {
38+tape('basic', async t => {
3939 t.plan(2)
4040 tester = t
4141 const expectedState = {
4242 '/': Buffer.from('4494963fb0e02312510e675fbca8b60b6e03bd00', 'hex')
@@ -76,14 +76,13 @@
7676
7777 const hypervisor = new Hypervisor(tree)
7878 hypervisor.registerContainer(TestWasmContainer)
7979
80- const {exports: receiverExports} = await hypervisor.createActor(TestWasmContainer.typeId, recieverWasm)
81- const {exports: callerExports} = await hypervisor.createActor(TestWasmContainer.typeId, callerWasm)
82-
80+ const {module: receiverMod} = await hypervisor.createActor(TestWasmContainer.typeId, recieverWasm)
81+ const {module: callerMod} = await hypervisor.createActor(TestWasmContainer.typeId, callerWasm)
8382 const message = new Message({
84- funcRef: callerExports.call,
85- funcArguments: [receiverExports.receive]
83+ funcRef: callerMod.getFuncRef('call'),
84+ funcArguments: [receiverMod.getFuncRef('receive')]
8685 })
8786
8887 hypervisor.send(message)
8988 const stateRoot = await hypervisor.createStateRoot()
@@ -93,9 +92,9 @@
9392 tape('two communicating actors with callback', async t => {
9493 // t.plan(2)
9594 tester = t
9695 const expectedState = {
97- '/': Buffer.from('f3cc5ba63d6b1737bea2c33bd1942e5488787b82', 'hex')
96+ '/': Buffer.from('51ded6c294314defc886b70f7f593434c8d53c95', 'hex')
9897 }
9998
10099 const tree = new RadixTree({
101100 db
@@ -106,19 +105,19 @@
106105
107106 const hypervisor = new Hypervisor(tree)
108107 hypervisor.registerContainer(TestWasmContainer)
109108
110- const {exports: receiverExports} = await hypervisor.createActor(TestWasmContainer.typeId, recieverWasm)
111- const {exports: callerExports} = await hypervisor.createActor(TestWasmContainer.typeId, callerWasm)
109+ const {module: receiverMod} = await hypervisor.createActor(TestWasmContainer.typeId, recieverWasm)
110+ const {module: callerMod} = await hypervisor.createActor(TestWasmContainer.typeId, callerWasm)
112111
113112 const message = new Message({
114- funcRef: callerExports.call,
115- funcArguments: [receiverExports.receive]
113+ funcRef: callerMod.getFuncRef('call'),
114+ funcArguments: [receiverMod.getFuncRef('receive')]
116115 })
117116
118117 hypervisor.send(message)
119118 const stateRoot = await hypervisor.createStateRoot()
120- // t.deepEquals(stateRoot, expectedState, 'expected root!')
119+ t.deepEquals(stateRoot, expectedState, 'expected root!')
121120 t.end()
122121 })
123122
124123 // Increment a counter.
@@ -131,12 +130,12 @@
131130
132131 const hypervisor = new Hypervisor(tree)
133132 hypervisor.registerContainer(TestWasmContainer)
134133
135- const {exports} = await hypervisor.createActor(TestWasmContainer.typeId, wasm)
134+ const {module} = await hypervisor.createActor(TestWasmContainer.typeId, wasm)
136135
137136 const message = new Message({
138- funcRef: exports.increment,
137+ funcRef: module.increment,
139138 funcArguments: []
140139 })
141140 hypervisor.send(message)
142141
tests/wast/elem.wastView
@@ -1,0 +1,13 @@
1+(module
2+ (import "func" "internalize" (func $internalize (param i32 i32)))
3+ (table (export "table") 1 1 anyfunc)
4+ (elem (i32.const 0) $receive)
5+ (func $receive (param i32)
6+ i32.const 5
7+ get_local 0
8+ i32.const 0
9+ call $internalize
10+ i32.const 0
11+ call_indirect (param i32)
12+ )
13+ (export "receive" (func $receive)))
tests/wast/funcRef_caller.jsonView
@@ -1,0 +1,12 @@
1+{
2+ "type": [{
3+ "form": "func",
4+ "params": [
5+ "func"
6+ ]
7+ }],
8+ "typeMap": [{
9+ "func": 0,
10+ "type": 0
11+ }]
12+}
tests/wast/funcRef_caller.wastView
@@ -1,0 +1,26 @@
1+(module
2+ (import "func" "internalize" (func $internalize (param i32 i32)))
3+ (import "test" "check" (func $check (param i32 i32)))
4+ (import "module" "self" (func $self (result i32)))
5+ (import "module" "exports" (func $exports (param i32 i32 i32) (result i32)))
6+ (memory (export "memory") 1)
7+ (data (i32.const 0) "callback")
8+ (table (export "table") 1 1 anyfunc)
9+ (func $call (param i32)
10+ call $self
11+ i32.const 0
12+ i32.const 8
13+ call $exports
14+ i32.const 0
15+ get_local 0
16+ call $internalize
17+ i32.const 0
18+ call_indirect (param i32)
19+ )
20+ (func $callback (param i32)
21+ get_local 0
22+ i32.const 5
23+ call $check
24+ )
25+ (export "call" (func $call))
26+ (export "callback" (func $callback)))
tests/wast/funcRef_reciever.jsonView
@@ -1,0 +1,12 @@
1+{
2+ "type": [{
3+ "form": "func",
4+ "params": [
5+ "func"
6+ ]
7+ }],
8+ "typeMap": [{
9+ "func": 0,
10+ "type": 0
11+ }]
12+}
tests/wast/funcRef_reciever.wastView
@@ -1,0 +1,12 @@
1+(module
2+ (import "func" "internalize" (func $internalize (param i32 i32)))
3+ (table (export "table") 1 1 anyfunc)
4+ (func $receive (param i32)
5+ get_local 0
6+ i32.const 0
7+ call $internalize
8+ i32.const 5
9+ i32.const 0
10+ call_indirect (param i32)
11+ )
12+ (export "receive" (func $receive)))
tests/wast2wasm.jsView
@@ -20,11 +20,10 @@
2020 const mod = wabt.parseWat('module.wast', wat)
2121 const r = mod.toBinary({log: true})
2222 let binary = Buffer.from(r.buffer)
2323 if (json) {
24- console.log(json)
2524 const buf = types.encodeJSON(json)
26- // binary = types.injectCustomSection(buf, binary)
25+ binary = types.injectCustomSection(buf, binary)
2726 }
2827 fs.writeFileSync(`${__dirname}/wasm/${file}.wasm`, binary)
2928 }
3029 }
wasmContainer.jsView
@@ -29,10 +29,12 @@
2929 0x60: 'func',
3030 0x40: 'block_type'
3131 }
3232
33-
3433 class ElementBuffer {
34+ static get type () {
35+ return 'elem'
36+ }
3537 constructor (size) {
3638 this._array = new Array(size)
3739 }
3840
@@ -44,8 +46,11 @@
4446 static deserialize (serialized) {}
4547 }
4648
4749 class DataBuffer {
50+ static get type () {
51+ return 'data'
52+ }
4853 constructor (memory, offset, length) {
4954 this._data = new Uint8Array(this.instance.exports.memory.buffer, offset, length)
5055 }
5156 serialize () {
@@ -54,30 +59,41 @@
5459 static deserialize (serialized) {}
5560 }
5661
5762 class LinkRef {
63+ static get type () {
64+ return 'link'
65+ }
5866 serialize () {
5967 return Buffer.concat(Buffer.from([LANGUAGE_TYPES['link'], this]))
6068 }
6169 static deserialize (serialized) {}
6270 }
6371
6472 class FunctionRef {
6573 static get type () {
66- return 'funcRef'
74+ return 'func'
6775 }
6876
69- constructor (name, json, id) {
70- this.name = name
77+ constructor (type, identifier, json, id) {
78+ this.type = type
7179 this.destId = id
72- this.args = []
73- const typeIndex = json.typeMap[name]
74- const type = json.type[typeIndex]
75- const wrapper = typeCheckWrapper(type)
80+ let funcIndex
81+ if (type === 'export') {
82+ this.indentifier = identifier
83+ funcIndex = json.exports[identifier]
84+ } else {
85+ this.indentifier = identifier.tableIndex
86+ funcIndex = Number(identifier.name) - 1
87+ }
88+ const typeIndex = json.indexes[funcIndex]
89+ const funcType = json.types[typeIndex]
90+
91+ const wrapper = typeCheckWrapper(funcType)
7692 const wasm = json2wasm(wrapper)
77- this.mod = WebAssembly.Module(wasm)
93+ const mod = WebAssembly.Module(wasm)
7894 const self = this
79- const instance = WebAssembly.Instance(this.mod, {
95+ this.wrapper = WebAssembly.Instance(mod, {
8096 'env': {
8197 'checkTypes': function () {
8298 const args = [...arguments]
8399 const checkedArgs = []
@@ -96,23 +112,27 @@
96112 self._container.actor.send(message)
97113 }
98114 }
99115 })
100- this.wrapper = instance
116+ this.wrapper.exports.check.object = this
101117 }
102118 set container (container) {
103119 this._container = container
104120 }
105121 }
106122
107123 class ModuleRef {
124+ static get type () {
125+ return 'mod'
126+ }
127+
108128 constructor (json, id) {
109129 this._json = json
110130 this.id = id
111131 }
112132
113133 getFuncRef (name) {
114- return new FunctionRef(name, this._json, this.id)
134+ return new FunctionRef('export', name, this._json, this.id)
115135 }
116136
117137 serialize () {
118138 return this._json
@@ -131,9 +151,9 @@
131151 if (!WebAssembly.validate(wasm)) {
132152 throw new Error('invalid wasm binary')
133153 }
134154 let moduleJSON = wasm2json(wasm)
135- const json = mergeTypeSections(moduleJSON)
155+ const json = customTypes.mergeTypeSections(moduleJSON)
136156 moduleJSON = wasmMetering.meterJSON(moduleJSON, {
137157 meterType: 'i32'
138158 })
139159 wasm = json2wasm(moduleJSON)
@@ -151,11 +171,20 @@
151171 getInterface (funcRef) {
152172 const self = this
153173 return {
154174 func: {
155- externalize: () => {},
175+ externalize: (index) => {
176+ const func = this.instance.exports.table.get(index)
177+ const object = func.object
178+ if (object) {
179+ return self.refs.add(object)
180+ } else {
181+ const ref = new FunctionRef(false, object.tableIndex, self.json, self.actor.id)
182+ return self.refs.add(ref)
183+ }
184+ },
156185 internalize: (ref, index) => {
157- const funcRef = self.refs.get(ref, 'funcRef')
186+ const funcRef = self.refs.get(ref)
158187 funcRef.container = self
159188 this.instance.exports.table.set(index, funcRef.wrapper.exports.check)
160189 },
161190 catch: (ref, catchRef) => {
@@ -184,13 +213,13 @@
184213 exports: (modRef, offset, length) => {
185214 const mod = this.refs.get(modRef, 'mod')
186215 let name = this.getMemory(offset, length)
187216 name = Buffer.from(name).toString()
188- const funcRef = new FunctionRef(name, mod, this.actor.id)
189- return this.refs.add(funcRef)
217+ const funcRef = mod.getFuncRef(name)
218+ return this.refs.add(funcRef, 'func')
190219 },
191220 self: () => {
192- return this.refs.add(this.json, 'mod')
221+ return this.refs.add(this.moduleObj, 'mod')
193222 }
194223 },
195224 memory: {
196225 externalize: (index, length) => {
@@ -216,12 +245,12 @@
216245 throw new Error('invalid ref')
217246 }
218247 }
219248 const eleBuf = new ElementBuffer(objects)
220- return this.refs.add(eleBuf, 'ele')
249+ return this.refs.add(eleBuf, 'elem')
221250 },
222251 internalize: (dataRef, writeOffset, readOffset, length) => {
223- let buf = this.refs.get(dataRef, 'ele')
252+ let buf = this.refs.get(dataRef, 'elem')
224253 buf = buf.subarray(readOffset, length)
225254 const mem = this.getMemory(writeOffset, buf.length)
226255 mem.set(buf)
227256 }
@@ -240,19 +269,30 @@
240269 async onMessage (message) {
241270 const funcRef = message.funcRef
242271 const intef = this.getInterface(funcRef)
243272 this.instance = WebAssembly.Instance(this.mod, intef)
244- if (this.instance.exports.table) {
245- this._orginalTable = this.instance.exports.table
273+ const table = this.instance.exports.table
274+ if (table) {
275+ let length = table.length
276+ while (length--) {
277+ const func = table.get(length)
278+ if (func) {
279+ func.tableIndex = length
280+ }
281+ }
246282 }
247283 const args = message.funcArguments.map(arg => {
248284 if (typeof arg === 'number') {
249285 return arg
250286 } else {
251287 return this.refs.add(arg, arg.constructor.type)
252288 }
253289 })
254- this.instance.exports[funcRef.name](...args)
290+ if (funcRef.type === 'export') {
291+ this.instance.exports[funcRef.indentifier](...args)
292+ } else {
293+ this.instance.exports.table.get(funcRef.indentifier)(...args)
294+ }
255295 await this.onDone()
256296 this.refs.clear()
257297 }
258298
@@ -307,8 +347,9 @@
307347 wasm = Buffer.from(wasm, 'hex')
308348 json = JSON.parse(json)
309349 this.mod = WebAssembly.Module(wasm)
310350 this.json = json
351+ this.moduleObj = new ModuleRef(json, this.actor.id)
311352 }
312353
313354 getMemory (offset, length) {
314355 return new Uint8Array(this.instance.exports.memory.buffer, offset, length)
@@ -317,72 +358,4 @@
317358 static get typeId () {
318359 return 9
319360 }
320361 }
321-
322-function mergeTypeSections (json) {
323- const typeInfo = {
324- typeMap: [],
325- type: []
326- }
327- let typeSection = {
328- 'entries': []
329- }
330- let importSection = {
331- 'entries': []
332- }
333- let functionSection = {
334- 'entries': []
335- }
336- let exportSection = {
337- 'entries': []
338- }
339- json.forEach(section => {
340- switch (section.name) {
341- case 'type':
342- typeSection = section
343- break
344- case 'export':
345- exportSection = section
346- break
347- case 'import':
348- importSection = section
349- break
350- case 'function':
351- functionSection = section
352- break
353- case 'custom':
354- switch (section.sectionName) {
355- case 'type':
356- typeInfo.type = customTypes.decodeType(section.payload)
357- break
358- case 'typeMap':
359- typeInfo.typeMap = customTypes.decodeTypeMap(section.payload)
360- break
361- }
362- break
363- }
364- })
365-
366- const foundTypes = new Map()
367- const mappedFuncs = new Map()
368- const newTypeMap = {}
369- typeInfo.typeMap.forEach(map => mappedFuncs.set(map.func, map.type))
370- for (let exprt of exportSection.entries) {
371- if (exprt.kind === 'function') {
372- if (!mappedFuncs.has(exprt.index)) {
373- const typeIndex = functionSection.entries[exprt.index - importSection.entries.length]
374- if (!foundTypes.has(typeIndex)) {
375- const customIndex = typeInfo.type.push(typeSection.entries[typeIndex]) - 1
376- foundTypes.set(typeIndex, customIndex)
377- }
378- const customIndex = foundTypes.get(typeIndex)
379- newTypeMap[exprt.field_str] = customIndex
380- } else {
381- newTypeMap[exprt.field_str] = mappedFuncs.get(exprt.index)
382- }
383- }
384- }
385-
386- typeInfo.typeMap = newTypeMap
387- return typeInfo
388-}

Built with git-ssb-web