| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 class Binary extends Array { | 5 class Binary extends Array { |
| 6 emit_u8(val) { | 6 emit_u8(val) { |
| 7 this.push(val); | 7 this.push(val); |
| 8 } | 8 } |
| 9 | 9 |
| 10 emit_u16(val) { | 10 emit_u16(val) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 } | 54 } |
| 55 } | 55 } |
| 56 | 56 |
| 57 emit_header() { | 57 emit_header() { |
| 58 this.push(kWasmH0, kWasmH1, kWasmH2, kWasmH3, | 58 this.push(kWasmH0, kWasmH1, kWasmH2, kWasmH3, |
| 59 kWasmV0, kWasmV1, kWasmV2, kWasmV3); | 59 kWasmV0, kWasmV1, kWasmV2, kWasmV3); |
| 60 } | 60 } |
| 61 | 61 |
| 62 emit_section(section_code, content_generator) { | 62 emit_section(section_code, content_generator) { |
| 63 // Emit section name. | 63 // Emit section name. |
| 64 this.emit_string(section_names[section_code]); | 64 this.emit_u8(section_code); |
| 65 // Emit the section to a temporary buffer: its full length isn't know yet. | 65 // Emit the section to a temporary buffer: its full length isn't know yet. |
| 66 let section = new Binary; | 66 let section = new Binary; |
| 67 content_generator(section); | 67 content_generator(section); |
| 68 // Emit section length. | 68 // Emit section length. |
| 69 this.emit_varint(section.length); | 69 this.emit_varint(section.length); |
| 70 // Copy the temporary buffer. | 70 // Copy the temporary buffer. |
| 71 this.push(...section); | 71 this.push(...section); |
| 72 } | 72 } |
| 73 } | 73 } |
| 74 | 74 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 } | 140 } |
| 141 | 141 |
| 142 addGlobal(local_type) { | 142 addGlobal(local_type) { |
| 143 this.globals.push(local_type); | 143 this.globals.push(local_type); |
| 144 return this.globals.length - 1; | 144 return this.globals.length - 1; |
| 145 } | 145 } |
| 146 | 146 |
| 147 addFunction(name, type) { | 147 addFunction(name, type) { |
| 148 let type_index = (typeof type) == "number" ? type : this.addType(type); | 148 let type_index = (typeof type) == "number" ? type : this.addType(type); |
| 149 let func = new WasmFunctionBuilder(name, type_index); | 149 let func = new WasmFunctionBuilder(name, type_index); |
| 150 func.index = this.functions.length; | 150 func.index = this.functions.length + this.imports.length; |
| 151 this.functions.push(func); | 151 this.functions.push(func); |
| 152 return func; | 152 return func; |
| 153 } | 153 } |
| 154 | 154 |
| 155 addImportWithModule(module, name, type) { | 155 addImportWithModule(module, name, type) { |
| 156 let type_index = (typeof type) == "number" ? type : this.addType(type); | 156 let type_index = (typeof type) == "number" ? type : this.addType(type); |
| 157 this.imports.push({module: module, name: name, type: type_index}); | 157 this.imports.push({module: module, name: name, type: type_index}); |
| 158 return this.imports.length - 1; | 158 return this.imports.length - 1; |
| 159 } | 159 } |
| 160 | 160 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 175 toArray(debug) { | 175 toArray(debug) { |
| 176 let binary = new Binary; | 176 let binary = new Binary; |
| 177 let wasm = this; | 177 let wasm = this; |
| 178 | 178 |
| 179 // Add header | 179 // Add header |
| 180 binary.emit_header(); | 180 binary.emit_header(); |
| 181 | 181 |
| 182 // Add type section | 182 // Add type section |
| 183 if (wasm.types.length > 0) { | 183 if (wasm.types.length > 0) { |
| 184 if (debug) print("emitting types @ " + binary.length); | 184 if (debug) print("emitting types @ " + binary.length); |
| 185 binary.emit_section(kDeclTypes, section => { | 185 binary.emit_section(kTypeSectionCode, section => { |
| 186 section.emit_varint(wasm.types.length); | 186 section.emit_varint(wasm.types.length); |
| 187 for (let type of wasm.types) { | 187 for (let type of wasm.types) { |
| 188 section.emit_u8(kWasmFunctionTypeForm); | 188 section.emit_u8(kWasmFunctionTypeForm); |
| 189 section.emit_varint(type.params.length); | 189 section.emit_varint(type.params.length); |
| 190 for (let param of type.params) { | 190 for (let param of type.params) { |
| 191 section.emit_u8(param); | 191 section.emit_u8(param); |
| 192 } | 192 } |
| 193 section.emit_varint(type.results.length); | 193 section.emit_varint(type.results.length); |
| 194 for (let result of type.results) { | 194 for (let result of type.results) { |
| 195 section.emit_u8(result); | 195 section.emit_u8(result); |
| 196 } | 196 } |
| 197 } | 197 } |
| 198 }); | 198 }); |
| 199 } | 199 } |
| 200 | 200 |
| 201 if (wasm.globals.length > 0) { | |
| 202 if (debug) print ("emitting globals @ " + binary.length); | |
| 203 binary.emit_section(kDeclGlobals, section => { | |
| 204 section.emit_varint(wasm.globals.length); | |
| 205 for (let global_type of wasm.globals) { | |
| 206 section.emit_varint(0); // length of global name | |
| 207 section.emit_u8(global_type); | |
| 208 section.emit_u8(false); // we do not support exported globals | |
| 209 } | |
| 210 }); | |
| 211 } | |
| 212 | |
| 213 // Add imports section | 201 // Add imports section |
| 214 if (wasm.imports.length > 0) { | 202 if (wasm.imports.length > 0) { |
| 215 if (debug) print("emitting imports @ " + binary.length); | 203 if (debug) print("emitting imports @ " + binary.length); |
| 216 binary.emit_section(kDeclImports, section => { | 204 binary.emit_section(kImportSectionCode, section => { |
| 217 section.emit_varint(wasm.imports.length); | 205 section.emit_varint(wasm.imports.length); |
| 218 for (let imp of wasm.imports) { | 206 for (let imp of wasm.imports) { |
| 219 section.emit_varint(imp.type); | |
| 220 section.emit_string(imp.module); | 207 section.emit_string(imp.module); |
| 221 section.emit_string(imp.name || ''); | 208 section.emit_string(imp.name || ''); |
| 209 section.emit_u8(kExternalFunction); |
| 210 section.emit_varint(imp.type); |
| 222 } | 211 } |
| 223 }); | 212 }); |
| 224 } | 213 } |
| 225 | 214 |
| 226 // Add functions declarations | 215 // Add functions declarations |
| 227 let has_names = false; | 216 let has_names = false; |
| 228 let names = false; | 217 let names = false; |
| 229 let exports = 0; | 218 let exports = 0; |
| 230 if (wasm.functions.length > 0) { | 219 if (wasm.functions.length > 0) { |
| 231 if (debug) print("emitting function decls @ " + binary.length); | 220 if (debug) print("emitting function decls @ " + binary.length); |
| 232 binary.emit_section(kDeclFunctions, section => { | 221 binary.emit_section(kFunctionSectionCode, section => { |
| 233 section.emit_varint(wasm.functions.length); | 222 section.emit_varint(wasm.functions.length); |
| 234 for (let func of wasm.functions) { | 223 for (let func of wasm.functions) { |
| 235 has_names = has_names || (func.name != undefined && | 224 has_names = has_names || (func.name != undefined && |
| 236 func.name.length > 0); | 225 func.name.length > 0); |
| 237 exports += func.exports.length; | 226 exports += func.exports.length; |
| 238 section.emit_varint(func.type_index); | 227 section.emit_varint(func.type_index); |
| 239 } | 228 } |
| 240 }); | 229 }); |
| 241 } | 230 } |
| 242 | 231 |
| 243 // Add table. | 232 // Add table. |
| 244 if (wasm.table.length > 0) { | 233 if (wasm.table.length > 0) { |
| 245 if (debug) print("emitting table @ " + binary.length); | 234 if (debug) print("emitting table @ " + binary.length); |
| 246 binary.emit_section(kDeclTable, section => { | 235 binary.emit_section(kTableSectionCode, section => { |
| 236 section.emit_u8(1); // one table entry |
| 237 section.emit_u8(kWasmAnyFunctionTypeForm); |
| 238 section.emit_u8(1); |
| 247 section.emit_varint(wasm.table.length); | 239 section.emit_varint(wasm.table.length); |
| 248 if (wasm.pad !== null) { | 240 section.emit_varint(wasm.table.length); |
| 249 if (debug) print("emitting table padding @ " + binary.length); | |
| 250 section.emit_varint(wasm.pad); | |
| 251 } | |
| 252 for (let index of wasm.table) { | |
| 253 section.emit_varint(index); | |
| 254 } | |
| 255 }); | 241 }); |
| 256 } | 242 } |
| 257 | 243 |
| 258 // Add memory section | 244 // Add memory section |
| 259 if (wasm.memory != undefined) { | 245 if (wasm.memory != undefined) { |
| 260 if (debug) print("emitting memory @ " + binary.length); | 246 if (debug) print("emitting memory @ " + binary.length); |
| 261 binary.emit_section(kDeclMemory, section => { | 247 binary.emit_section(kMemorySectionCode, section => { |
| 248 section.emit_u8(1); // one memory entry |
| 249 section.emit_varint(kResizableMaximumFlag); |
| 262 section.emit_varint(wasm.memory.min); | 250 section.emit_varint(wasm.memory.min); |
| 263 section.emit_varint(wasm.memory.max); | 251 section.emit_varint(wasm.memory.max); |
| 264 section.emit_u8(wasm.memory.exp ? 1 : 0); | |
| 265 }); | 252 }); |
| 266 } | 253 } |
| 267 | 254 |
| 255 // Add global section. |
| 256 if (wasm.globals.length > 0) { |
| 257 if (debug) print ("emitting globals @ " + binary.length); |
| 258 binary.emit_section(kGlobalSectionCode, section => { |
| 259 section.emit_varint(wasm.globals.length); |
| 260 for (let global_type of wasm.globals) { |
| 261 section.emit_u8(global_type); |
| 262 section.emit_u8(true); // mutable |
| 263 switch (global_type) { |
| 264 case kAstI32: |
| 265 section.emit_u8(kExprI32Const); |
| 266 section.emit_u8(0); |
| 267 break; |
| 268 case kAstI64: |
| 269 section.emit_u8(kExprI64Const); |
| 270 section.emit_u8(0); |
| 271 break; |
| 272 case kAstF32: |
| 273 section.emit_u8(kExprF32Const); |
| 274 section.emit_u32(0); |
| 275 break; |
| 276 case kAstF64: |
| 277 section.emit_u8(kExprI32Const); |
| 278 section.emit_u32(0); |
| 279 section.emit_u32(0); |
| 280 break; |
| 281 } |
| 282 section.emit_u8(kExprEnd); // end of init expression |
| 283 } |
| 284 }); |
| 285 } |
| 268 | 286 |
| 269 // Add export table. | 287 // Add export table. |
| 270 if (exports > 0) { | 288 var mem_export = (wasm.memory != undefined && wasm.memory.exp); |
| 289 if (exports > 0 || mem_export) { |
| 271 if (debug) print("emitting exports @ " + binary.length); | 290 if (debug) print("emitting exports @ " + binary.length); |
| 272 binary.emit_section(kDeclExports, section => { | 291 binary.emit_section(kExportSectionCode, section => { |
| 273 section.emit_varint(exports); | 292 section.emit_varint(exports + (mem_export ? 1 : 0)); |
| 274 for (let func of wasm.functions) { | 293 for (let func of wasm.functions) { |
| 275 for (let exp of func.exports) { | 294 for (let exp of func.exports) { |
| 295 section.emit_string(exp); |
| 296 section.emit_u8(kExternalFunction); |
| 276 section.emit_varint(func.index); | 297 section.emit_varint(func.index); |
| 277 section.emit_string(exp); | |
| 278 } | 298 } |
| 279 } | 299 } |
| 300 if (mem_export) { |
| 301 section.emit_string("memory"); |
| 302 section.emit_u8(kExternalMemory); |
| 303 section.emit_u8(0); |
| 304 } |
| 280 }); | 305 }); |
| 281 } | 306 } |
| 282 | 307 |
| 283 // Add start function section. | 308 // Add start function section. |
| 284 if (wasm.start_index != undefined) { | 309 if (wasm.start_index != undefined) { |
| 285 if (debug) print("emitting start function @ " + binary.length); | 310 if (debug) print("emitting start function @ " + binary.length); |
| 286 binary.emit_section(kDeclStart, section => { | 311 binary.emit_section(kStartSectionCode, section => { |
| 287 section.emit_varint(wasm.start_index); | 312 section.emit_varint(wasm.start_index); |
| 288 }); | 313 }); |
| 289 } | 314 } |
| 290 | 315 |
| 316 // Add table elements. |
| 317 if (wasm.table.length > 0) { |
| 318 if (debug) print("emitting table @ " + binary.length); |
| 319 binary.emit_section(kElementSectionCode, section => { |
| 320 section.emit_u8(1); |
| 321 section.emit_u8(0); // table index |
| 322 section.emit_u8(kExprI32Const); |
| 323 section.emit_u8(0); |
| 324 section.emit_u8(kExprEnd); |
| 325 section.emit_varint(wasm.table.length); |
| 326 for (let index of wasm.table) { |
| 327 section.emit_varint(index); |
| 328 } |
| 329 }); |
| 330 } |
| 331 |
| 291 // Add function bodies. | 332 // Add function bodies. |
| 292 if (wasm.functions.length > 0) { | 333 if (wasm.functions.length > 0) { |
| 293 // emit function bodies | 334 // emit function bodies |
| 294 if (debug) print("emitting code @ " + binary.length); | 335 if (debug) print("emitting code @ " + binary.length); |
| 295 binary.emit_section(kDeclCode, section => { | 336 binary.emit_section(kCodeSectionCode, section => { |
| 296 section.emit_varint(wasm.functions.length); | 337 section.emit_varint(wasm.functions.length); |
| 297 for (let func of wasm.functions) { | 338 for (let func of wasm.functions) { |
| 298 // Function body length will be patched later. | 339 // Function body length will be patched later. |
| 299 let local_decls = []; | 340 let local_decls = []; |
| 300 let l = func.locals; | 341 let l = func.locals; |
| 301 if (l != undefined) { | 342 if (l != undefined) { |
| 302 let local_decls_count = 0; | 343 let local_decls_count = 0; |
| 303 if (l.i32_count > 0) { | 344 if (l.i32_count > 0) { |
| 304 local_decls.push({count: l.i32_count, type: kAstI32}); | 345 local_decls.push({count: l.i32_count, type: kAstI32}); |
| 305 } | 346 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 324 section.emit_varint(header.length + func.body.length); | 365 section.emit_varint(header.length + func.body.length); |
| 325 section.emit_bytes(header); | 366 section.emit_bytes(header); |
| 326 section.emit_bytes(func.body); | 367 section.emit_bytes(func.body); |
| 327 } | 368 } |
| 328 }); | 369 }); |
| 329 } | 370 } |
| 330 | 371 |
| 331 // Add data segments. | 372 // Add data segments. |
| 332 if (wasm.segments.length > 0) { | 373 if (wasm.segments.length > 0) { |
| 333 if (debug) print("emitting data segments @ " + binary.length); | 374 if (debug) print("emitting data segments @ " + binary.length); |
| 334 binary.emit_section(kDeclData, section => { | 375 binary.emit_section(kDataSectionCode, section => { |
| 335 section.emit_varint(wasm.segments.length); | 376 section.emit_varint(wasm.segments.length); |
| 336 for (let seg of wasm.segments) { | 377 for (let seg of wasm.segments) { |
| 378 section.emit_u8(0); // linear memory index 0 |
| 379 section.emit_u8(kExprI32Const); |
| 337 section.emit_varint(seg.addr); | 380 section.emit_varint(seg.addr); |
| 381 section.emit_u8(kExprEnd); |
| 338 section.emit_varint(seg.data.length); | 382 section.emit_varint(seg.data.length); |
| 339 section.emit_bytes(seg.data); | 383 section.emit_bytes(seg.data); |
| 340 } | 384 } |
| 341 }); | 385 }); |
| 342 } | 386 } |
| 343 | 387 |
| 344 // Add any explicitly added sections | 388 // Add any explicitly added sections |
| 345 for (let exp of wasm.explicit) { | 389 for (let exp of wasm.explicit) { |
| 346 if (debug) print("emitting explicit @ " + binary.length); | 390 if (debug) print("emitting explicit @ " + binary.length); |
| 347 binary.emit_bytes(exp); | 391 binary.emit_bytes(exp); |
| 348 } | 392 } |
| 349 | 393 |
| 350 // Add function names. | 394 // Add function names. |
| 351 if (has_names) { | 395 if (has_names) { |
| 352 if (debug) print("emitting names @ " + binary.length); | 396 if (debug) print("emitting names @ " + binary.length); |
| 353 binary.emit_section(kDeclNames, section => { | 397 binary.emit_section(kUnknownSectionCode, section => { |
| 398 section.emit_string("name"); |
| 354 section.emit_varint(wasm.functions.length); | 399 section.emit_varint(wasm.functions.length); |
| 355 for (let func of wasm.functions) { | 400 for (let func of wasm.functions) { |
| 356 var name = func.name == undefined ? "" : func.name; | 401 var name = func.name == undefined ? "" : func.name; |
| 357 section.emit_string(name); | 402 section.emit_string(name); |
| 358 section.emit_u8(0); // local names count == 0 | 403 section.emit_u8(0); // local names count == 0 |
| 359 } | 404 } |
| 360 }); | 405 }); |
| 361 } | 406 } |
| 362 | 407 |
| 363 return binary; | 408 return binary; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 374 } | 419 } |
| 375 return buffer; | 420 return buffer; |
| 376 } | 421 } |
| 377 | 422 |
| 378 instantiate(...args) { | 423 instantiate(...args) { |
| 379 let module = new WebAssembly.Module(this.toBuffer()); | 424 let module = new WebAssembly.Module(this.toBuffer()); |
| 380 let instance = new WebAssembly.Instance(module, ...args); | 425 let instance = new WebAssembly.Instance(module, ...args); |
| 381 return instance; | 426 return instance; |
| 382 } | 427 } |
| 383 } | 428 } |
| OLD | NEW |