2016-03-07 10:01:24 +00:00
|
|
|
// Copyright 2016 the V8 project authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
2016-10-06 15:43:10 +00:00
|
|
|
// Used for encoding f32 and double constants to bits.
|
|
|
|
let __buffer = new ArrayBuffer(8);
|
|
|
|
let byte_view = new Int8Array(__buffer);
|
|
|
|
let f32_view = new Float32Array(__buffer);
|
|
|
|
let f64_view = new Float64Array(__buffer);
|
|
|
|
|
2016-06-21 19:47:51 +00:00
|
|
|
class Binary extends Array {
|
|
|
|
emit_u8(val) {
|
|
|
|
this.push(val);
|
|
|
|
}
|
|
|
|
|
|
|
|
emit_u16(val) {
|
|
|
|
this.push(val & 0xff);
|
|
|
|
this.push((val >> 8) & 0xff);
|
|
|
|
}
|
|
|
|
|
|
|
|
emit_u32(val) {
|
|
|
|
this.push(val & 0xff);
|
|
|
|
this.push((val >> 8) & 0xff);
|
|
|
|
this.push((val >> 16) & 0xff);
|
|
|
|
this.push((val >> 24) & 0xff);
|
|
|
|
}
|
|
|
|
|
2016-10-06 15:43:10 +00:00
|
|
|
emit_u32v(val) {
|
2016-06-21 19:47:51 +00:00
|
|
|
while (true) {
|
|
|
|
let v = val & 0xff;
|
|
|
|
val = val >>> 7;
|
|
|
|
if (val == 0) {
|
|
|
|
this.push(v);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
this.push(v | 0x80);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
emit_bytes(data) {
|
|
|
|
for (let i = 0; i < data.length; i++) {
|
|
|
|
this.push(data[i] & 0xff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
emit_string(string) {
|
|
|
|
// When testing illegal names, we pass a byte array directly.
|
|
|
|
if (string instanceof Array) {
|
2016-10-06 15:43:10 +00:00
|
|
|
this.emit_u32v(string.length);
|
2016-06-21 19:47:51 +00:00
|
|
|
this.emit_bytes(string);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is the hacky way to convert a JavaScript string to a UTF8 encoded
|
|
|
|
// string only containing single-byte characters.
|
|
|
|
let string_utf8 = unescape(encodeURIComponent(string));
|
2016-10-06 15:43:10 +00:00
|
|
|
this.emit_u32v(string_utf8.length);
|
2016-06-21 19:47:51 +00:00
|
|
|
for (let i = 0; i < string_utf8.length; i++) {
|
|
|
|
this.emit_u8(string_utf8.charCodeAt(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
emit_header() {
|
|
|
|
this.push(kWasmH0, kWasmH1, kWasmH2, kWasmH3,
|
|
|
|
kWasmV0, kWasmV1, kWasmV2, kWasmV3);
|
|
|
|
}
|
|
|
|
|
|
|
|
emit_section(section_code, content_generator) {
|
|
|
|
// Emit section name.
|
2016-09-27 20:46:10 +00:00
|
|
|
this.emit_u8(section_code);
|
2016-06-21 19:47:51 +00:00
|
|
|
// Emit the section to a temporary buffer: its full length isn't know yet.
|
2018-10-26 17:28:37 +00:00
|
|
|
const section = new Binary;
|
2016-06-21 19:47:51 +00:00
|
|
|
content_generator(section);
|
|
|
|
// Emit section length.
|
2016-10-06 15:43:10 +00:00
|
|
|
this.emit_u32v(section.length);
|
2016-06-21 19:47:51 +00:00
|
|
|
// Copy the temporary buffer.
|
2018-11-09 16:54:01 +00:00
|
|
|
// Avoid spread because {section} can be huge.
|
|
|
|
for (let b of section) this.push(b);
|
2016-06-21 19:47:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class WasmFunctionBuilder {
|
2016-10-06 15:43:10 +00:00
|
|
|
constructor(module, name, type_index) {
|
|
|
|
this.module = module;
|
2016-03-07 10:01:24 +00:00
|
|
|
this.name = name;
|
2016-06-21 19:47:51 +00:00
|
|
|
this.type_index = type_index;
|
2016-10-13 16:17:44 +00:00
|
|
|
this.body = [];
|
2018-10-26 11:05:14 +00:00
|
|
|
this.locals = [];
|
|
|
|
this.local_names = [];
|
2016-06-21 19:47:51 +00:00
|
|
|
}
|
2016-03-07 10:01:24 +00:00
|
|
|
|
2017-07-02 19:18:57 +00:00
|
|
|
numLocalNames() {
|
|
|
|
let num_local_names = 0;
|
|
|
|
for (let loc_name of this.local_names) {
|
|
|
|
if (loc_name !== undefined) ++num_local_names;
|
|
|
|
}
|
|
|
|
return num_local_names;
|
|
|
|
}
|
|
|
|
|
2016-06-21 19:47:51 +00:00
|
|
|
exportAs(name) {
|
2016-10-17 11:39:04 +00:00
|
|
|
this.module.addExport(name, this.index);
|
2016-03-07 10:01:24 +00:00
|
|
|
return this;
|
2016-06-21 19:47:51 +00:00
|
|
|
}
|
2016-03-07 10:01:24 +00:00
|
|
|
|
2016-06-21 19:47:51 +00:00
|
|
|
exportFunc() {
|
2016-10-06 15:43:10 +00:00
|
|
|
this.exportAs(this.name);
|
2016-06-21 19:47:51 +00:00
|
|
|
return this;
|
|
|
|
}
|
2016-03-07 19:32:35 +00:00
|
|
|
|
2016-06-21 19:47:51 +00:00
|
|
|
addBody(body) {
|
2017-02-16 14:12:01 +00:00
|
|
|
for (let b of body) {
|
2017-07-26 11:01:21 +00:00
|
|
|
if (typeof b !== 'number' || (b & (~0xFF)) !== 0 )
|
|
|
|
throw new Error('invalid body (entries must be 8 bit numbers): ' + body);
|
2017-02-16 14:12:01 +00:00
|
|
|
}
|
2017-03-31 08:45:15 +00:00
|
|
|
this.body = body.slice();
|
2017-01-15 21:18:53 +00:00
|
|
|
// Automatically add the end for the function block to the body.
|
2017-03-31 08:45:15 +00:00
|
|
|
this.body.push(kExprEnd);
|
2016-03-07 10:01:24 +00:00
|
|
|
return this;
|
2016-06-21 19:47:51 +00:00
|
|
|
}
|
2016-03-07 10:01:24 +00:00
|
|
|
|
2017-01-25 14:10:04 +00:00
|
|
|
addBodyWithEnd(body) {
|
|
|
|
this.body = body;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2018-01-08 11:54:54 +00:00
|
|
|
getNumLocals() {
|
|
|
|
let total_locals = 0;
|
2018-10-26 11:05:14 +00:00
|
|
|
for (let l of this.locals) {
|
2018-01-08 11:54:54 +00:00
|
|
|
for (let type of ["i32", "i64", "f32", "f64", "s128"]) {
|
|
|
|
total_locals += l[type + "_count"] || 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return total_locals;
|
|
|
|
}
|
|
|
|
|
2017-07-02 19:18:57 +00:00
|
|
|
addLocals(locals, names) {
|
2018-01-08 11:54:54 +00:00
|
|
|
const old_num_locals = this.getNumLocals();
|
|
|
|
this.locals.push(locals);
|
|
|
|
if (names) {
|
|
|
|
const missing_names = old_num_locals - this.local_names.length;
|
|
|
|
this.local_names.push(...new Array(missing_names), ...names);
|
|
|
|
}
|
2016-03-07 10:01:24 +00:00
|
|
|
return this;
|
2016-06-21 19:47:51 +00:00
|
|
|
}
|
2016-10-13 16:17:44 +00:00
|
|
|
|
|
|
|
end() {
|
|
|
|
return this.module;
|
|
|
|
}
|
2016-03-07 10:01:24 +00:00
|
|
|
}
|
|
|
|
|
2016-10-06 15:43:10 +00:00
|
|
|
class WasmGlobalBuilder {
|
|
|
|
constructor(module, type, mutable) {
|
|
|
|
this.module = module;
|
|
|
|
this.type = type;
|
|
|
|
this.mutable = mutable;
|
|
|
|
this.init = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
exportAs(name) {
|
2016-10-25 09:44:15 +00:00
|
|
|
this.module.exports.push({name: name, kind: kExternalGlobal,
|
|
|
|
index: this.index});
|
2016-10-06 15:43:10 +00:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-21 19:47:51 +00:00
|
|
|
class WasmModuleBuilder {
|
|
|
|
constructor() {
|
|
|
|
this.types = [];
|
2016-03-07 10:01:24 +00:00
|
|
|
this.imports = [];
|
2016-10-06 15:43:10 +00:00
|
|
|
this.exports = [];
|
2016-08-31 00:35:40 +00:00
|
|
|
this.globals = [];
|
2017-08-01 20:56:39 +00:00
|
|
|
this.exceptions = [];
|
2016-03-07 10:01:24 +00:00
|
|
|
this.functions = [];
|
2018-10-10 22:05:40 +00:00
|
|
|
this.table_length_min = 0;
|
|
|
|
this.table_length_max = undefined;
|
|
|
|
this.element_segments = [];
|
|
|
|
this.data_segments = [];
|
2016-03-07 19:32:35 +00:00
|
|
|
this.explicit = [];
|
2016-10-06 15:43:10 +00:00
|
|
|
this.num_imported_funcs = 0;
|
|
|
|
this.num_imported_globals = 0;
|
2018-09-11 08:38:24 +00:00
|
|
|
this.num_imported_exceptions = 0;
|
2016-06-22 00:51:58 +00:00
|
|
|
return this;
|
2016-06-21 19:47:51 +00:00
|
|
|
}
|
2016-03-07 10:01:24 +00:00
|
|
|
|
2016-06-21 19:47:51 +00:00
|
|
|
addStart(start_index) {
|
2016-03-07 19:32:35 +00:00
|
|
|
this.start_index = start_index;
|
2016-10-13 16:17:44 +00:00
|
|
|
return this;
|
2016-06-21 19:47:51 +00:00
|
|
|
}
|
2016-03-07 19:32:35 +00:00
|
|
|
|
2017-09-14 06:14:48 +00:00
|
|
|
addMemory(min, max, exp, shared) {
|
|
|
|
this.memory = {min: min, max: max, exp: exp, shared: shared};
|
2016-03-07 10:01:24 +00:00
|
|
|
return this;
|
2016-06-21 19:47:51 +00:00
|
|
|
}
|
2016-03-07 10:01:24 +00:00
|
|
|
|
2016-06-21 19:47:51 +00:00
|
|
|
addExplicitSection(bytes) {
|
|
|
|
this.explicit.push(bytes);
|
|
|
|
return this;
|
|
|
|
}
|
2016-03-07 19:32:35 +00:00
|
|
|
|
2017-01-25 11:53:09 +00:00
|
|
|
stringToBytes(name) {
|
|
|
|
var result = new Binary();
|
|
|
|
result.emit_u32v(name.length);
|
|
|
|
for (var i = 0; i < name.length; i++) {
|
|
|
|
result.emit_u8(name.charCodeAt(i));
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
addCustomSection(name, bytes) {
|
|
|
|
name = this.stringToBytes(name);
|
|
|
|
var length = new Binary();
|
|
|
|
length.emit_u32v(name.length + bytes.length);
|
2018-11-09 16:54:01 +00:00
|
|
|
var section = [0, ...length, ...name];
|
|
|
|
// Avoid spread because {bytes} can be huge.
|
|
|
|
for (var b of bytes) section.push(b);
|
|
|
|
this.explicit.push(section);
|
2017-01-25 11:53:09 +00:00
|
|
|
}
|
|
|
|
|
2016-06-21 19:47:51 +00:00
|
|
|
addType(type) {
|
|
|
|
this.types.push(type);
|
2017-08-03 11:35:15 +00:00
|
|
|
var pl = type.params.length; // should have params
|
|
|
|
var rl = type.results.length; // should have results
|
2016-06-21 19:47:51 +00:00
|
|
|
return this.types.length - 1;
|
|
|
|
}
|
2016-03-07 10:01:24 +00:00
|
|
|
|
2016-10-06 15:43:10 +00:00
|
|
|
addGlobal(local_type, mutable) {
|
|
|
|
let glob = new WasmGlobalBuilder(this, local_type, mutable);
|
|
|
|
glob.index = this.globals.length + this.num_imported_globals;
|
|
|
|
this.globals.push(glob);
|
|
|
|
return glob;
|
2016-08-31 00:35:40 +00:00
|
|
|
}
|
|
|
|
|
2017-08-01 20:56:39 +00:00
|
|
|
addException(type) {
|
2018-10-15 14:31:16 +00:00
|
|
|
let type_index = (typeof type) == "number" ? type : this.addType(type);
|
2018-09-11 08:38:24 +00:00
|
|
|
let except_index = this.exceptions.length + this.num_imported_exceptions;
|
2018-10-15 14:31:16 +00:00
|
|
|
this.exceptions.push(type_index);
|
2018-09-11 08:38:24 +00:00
|
|
|
return except_index;
|
2017-08-01 20:56:39 +00:00
|
|
|
}
|
|
|
|
|
2016-06-21 19:47:51 +00:00
|
|
|
addFunction(name, type) {
|
|
|
|
let type_index = (typeof type) == "number" ? type : this.addType(type);
|
2016-10-06 15:43:10 +00:00
|
|
|
let func = new WasmFunctionBuilder(this, name, type_index);
|
|
|
|
func.index = this.functions.length + this.num_imported_funcs;
|
2016-03-07 10:01:24 +00:00
|
|
|
this.functions.push(func);
|
|
|
|
return func;
|
2016-06-21 19:47:51 +00:00
|
|
|
}
|
2016-03-07 10:01:24 +00:00
|
|
|
|
2018-10-26 11:05:14 +00:00
|
|
|
addImport(module, name, type) {
|
2018-09-11 09:03:27 +00:00
|
|
|
if (this.functions.length != 0) {
|
|
|
|
throw new Error('Imported functions must be declared before local ones');
|
|
|
|
}
|
2016-06-21 19:47:51 +00:00
|
|
|
let type_index = (typeof type) == "number" ? type : this.addType(type);
|
2016-10-06 15:43:10 +00:00
|
|
|
this.imports.push({module: module, name: name, kind: kExternalFunction,
|
|
|
|
type: type_index});
|
|
|
|
return this.num_imported_funcs++;
|
2016-06-21 19:47:51 +00:00
|
|
|
}
|
2016-03-08 19:55:36 +00:00
|
|
|
|
2018-10-26 11:05:14 +00:00
|
|
|
addImportedGlobal(module, name, type, mutable = false) {
|
2018-09-11 09:03:27 +00:00
|
|
|
if (this.globals.length != 0) {
|
|
|
|
throw new Error('Imported globals must be declared before local ones');
|
|
|
|
}
|
2016-10-06 15:43:10 +00:00
|
|
|
let o = {module: module, name: name, kind: kExternalGlobal, type: type,
|
2018-04-25 18:12:51 +00:00
|
|
|
mutable: mutable};
|
2016-10-06 15:43:10 +00:00
|
|
|
this.imports.push(o);
|
|
|
|
return this.num_imported_globals++;
|
|
|
|
}
|
|
|
|
|
2018-10-26 11:05:14 +00:00
|
|
|
addImportedMemory(module, name, initial = 0, maximum, shared) {
|
2016-10-25 09:44:15 +00:00
|
|
|
let o = {module: module, name: name, kind: kExternalMemory,
|
2017-09-14 06:14:48 +00:00
|
|
|
initial: initial, maximum: maximum, shared: shared};
|
2016-10-07 09:34:06 +00:00
|
|
|
this.imports.push(o);
|
2016-10-13 16:17:44 +00:00
|
|
|
return this;
|
2016-10-07 09:34:06 +00:00
|
|
|
}
|
|
|
|
|
2018-10-26 11:05:14 +00:00
|
|
|
addImportedTable(module, name, initial, maximum) {
|
2016-10-29 21:06:57 +00:00
|
|
|
let o = {module: module, name: name, kind: kExternalTable, initial: initial,
|
|
|
|
maximum: maximum};
|
|
|
|
this.imports.push(o);
|
|
|
|
}
|
|
|
|
|
2018-10-26 11:05:14 +00:00
|
|
|
addImportedException(module, name, type) {
|
2018-09-11 08:38:24 +00:00
|
|
|
if (this.exceptions.length != 0) {
|
|
|
|
throw new Error('Imported exceptions must be declared before local ones');
|
|
|
|
}
|
2018-10-15 14:31:16 +00:00
|
|
|
let type_index = (typeof type) == "number" ? type : this.addType(type);
|
|
|
|
let o = {module: module, name: name, kind: kExternalException, type: type_index};
|
2018-09-11 08:38:24 +00:00
|
|
|
this.imports.push(o);
|
|
|
|
return this.num_imported_exceptions++;
|
|
|
|
}
|
|
|
|
|
2016-10-17 11:39:04 +00:00
|
|
|
addExport(name, index) {
|
|
|
|
this.exports.push({name: name, kind: kExternalFunction, index: index});
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2016-10-25 09:44:15 +00:00
|
|
|
addExportOfKind(name, kind, index) {
|
|
|
|
this.exports.push({name: name, kind: kind, index: index});
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2016-10-10 14:41:50 +00:00
|
|
|
addDataSegment(addr, data, is_global = false) {
|
2018-11-12 20:53:47 +00:00
|
|
|
this.data_segments.push(
|
|
|
|
{addr: addr, data: data, is_global: is_global, is_active: true});
|
|
|
|
return this.data_segments.length - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
addPassiveDataSegment(data) {
|
|
|
|
this.data_segments.push({data: data, is_active: false});
|
2018-10-10 22:05:40 +00:00
|
|
|
return this.data_segments.length - 1;
|
2016-06-21 19:47:51 +00:00
|
|
|
}
|
2016-03-07 10:01:24 +00:00
|
|
|
|
2016-10-07 09:34:06 +00:00
|
|
|
exportMemoryAs(name) {
|
|
|
|
this.exports.push({name: name, kind: kExternalMemory, index: 0});
|
|
|
|
}
|
|
|
|
|
2018-10-10 22:05:40 +00:00
|
|
|
addElementSegment(base, is_global, array, is_import = false) {
|
|
|
|
this.element_segments.push({base: base, is_global: is_global,
|
2018-11-12 20:53:47 +00:00
|
|
|
array: array, is_active: true});
|
[wasm] Use a Managed<WasmModule> to hold metadata about modules.
This CL refactors the handling of metadata associated with WebAssembly
modules to reduce the duplicate marshalling of data from the C++ world
to the JavaScript world. It does this by wrapping the C++ WasmModule*
object in a Foreign that is rooted from the on-heap WasmCompiledModule
(which is itself just a FixedArray). Upon serialization, the C++ object
is ignored and the original WASM wire bytes are serialized. Upon
deserialization, the C++ object is reconstituted by reparsing the bytes.
This is motivated by increasing complications in implementing the JS
API, in particular WebAssembly.Table, which must perform signature
canonicalization across instances.
Additionally, this CL implements the proper base + offset initialization
behavior for tables.
R=rossberg@chromium.org,bradnelson@chromium.org,mtrofin@chromium.org,yangguo@chromium.org
BUG=v8:5507, chromium:575167, chromium:657316
Review-Url: https://chromiumcodereview.appspot.com/2424623002
Cr-Commit-Position: refs/heads/master@{#40434}
2016-10-19 13:06:44 +00:00
|
|
|
if (!is_global) {
|
|
|
|
var length = base + array.length;
|
2018-10-10 22:05:40 +00:00
|
|
|
if (length > this.table_length_min && !is_import) {
|
|
|
|
this.table_length_min = length;
|
2017-09-05 17:48:46 +00:00
|
|
|
}
|
2018-10-10 22:05:40 +00:00
|
|
|
if (length > this.table_length_max && !is_import) {
|
|
|
|
this.table_length_max = length;
|
2016-10-25 09:44:15 +00:00
|
|
|
}
|
[wasm] Use a Managed<WasmModule> to hold metadata about modules.
This CL refactors the handling of metadata associated with WebAssembly
modules to reduce the duplicate marshalling of data from the C++ world
to the JavaScript world. It does this by wrapping the C++ WasmModule*
object in a Foreign that is rooted from the on-heap WasmCompiledModule
(which is itself just a FixedArray). Upon serialization, the C++ object
is ignored and the original WASM wire bytes are serialized. Upon
deserialization, the C++ object is reconstituted by reparsing the bytes.
This is motivated by increasing complications in implementing the JS
API, in particular WebAssembly.Table, which must perform signature
canonicalization across instances.
Additionally, this CL implements the proper base + offset initialization
behavior for tables.
R=rossberg@chromium.org,bradnelson@chromium.org,mtrofin@chromium.org,yangguo@chromium.org
BUG=v8:5507, chromium:575167, chromium:657316
Review-Url: https://chromiumcodereview.appspot.com/2424623002
Cr-Commit-Position: refs/heads/master@{#40434}
2016-10-19 13:06:44 +00:00
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2018-11-12 20:53:47 +00:00
|
|
|
addPassiveElementSegment(array, is_import = false) {
|
|
|
|
this.element_segments.push({array: array, is_active: false});
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2016-06-21 19:47:51 +00:00
|
|
|
appendToTable(array) {
|
2017-03-22 13:32:59 +00:00
|
|
|
for (let n of array) {
|
|
|
|
if (typeof n != 'number')
|
|
|
|
throw new Error('invalid table (entries have to be numbers): ' + array);
|
|
|
|
}
|
2018-10-10 22:05:40 +00:00
|
|
|
return this.addElementSegment(this.table_length_min, false, array);
|
[wasm] Use a Managed<WasmModule> to hold metadata about modules.
This CL refactors the handling of metadata associated with WebAssembly
modules to reduce the duplicate marshalling of data from the C++ world
to the JavaScript world. It does this by wrapping the C++ WasmModule*
object in a Foreign that is rooted from the on-heap WasmCompiledModule
(which is itself just a FixedArray). Upon serialization, the C++ object
is ignored and the original WASM wire bytes are serialized. Upon
deserialization, the C++ object is reconstituted by reparsing the bytes.
This is motivated by increasing complications in implementing the JS
API, in particular WebAssembly.Table, which must perform signature
canonicalization across instances.
Additionally, this CL implements the proper base + offset initialization
behavior for tables.
R=rossberg@chromium.org,bradnelson@chromium.org,mtrofin@chromium.org,yangguo@chromium.org
BUG=v8:5507, chromium:575167, chromium:657316
Review-Url: https://chromiumcodereview.appspot.com/2424623002
Cr-Commit-Position: refs/heads/master@{#40434}
2016-10-19 13:06:44 +00:00
|
|
|
}
|
|
|
|
|
2018-10-10 22:05:40 +00:00
|
|
|
setTableBounds(min, max) {
|
|
|
|
this.table_length_min = min;
|
|
|
|
this.table_length_max = max;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
setTableLength(length) {
|
|
|
|
this.table_length_min = length;
|
|
|
|
this.table_length_max = length;
|
2016-03-07 10:01:24 +00:00
|
|
|
return this;
|
2016-03-09 22:50:36 +00:00
|
|
|
}
|
|
|
|
|
2017-06-12 09:31:14 +00:00
|
|
|
setName(name) {
|
|
|
|
this.name = name;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2016-10-13 16:17:44 +00:00
|
|
|
toArray(debug = false) {
|
2016-06-21 19:47:51 +00:00
|
|
|
let binary = new Binary;
|
|
|
|
let wasm = this;
|
|
|
|
|
|
|
|
// Add header
|
|
|
|
binary.emit_header();
|
|
|
|
|
|
|
|
// Add type section
|
|
|
|
if (wasm.types.length > 0) {
|
|
|
|
if (debug) print("emitting types @ " + binary.length);
|
2016-09-27 20:46:10 +00:00
|
|
|
binary.emit_section(kTypeSectionCode, section => {
|
2016-10-06 15:43:10 +00:00
|
|
|
section.emit_u32v(wasm.types.length);
|
2016-06-21 19:47:51 +00:00
|
|
|
for (let type of wasm.types) {
|
|
|
|
section.emit_u8(kWasmFunctionTypeForm);
|
2016-10-06 15:43:10 +00:00
|
|
|
section.emit_u32v(type.params.length);
|
2016-06-21 19:47:51 +00:00
|
|
|
for (let param of type.params) {
|
|
|
|
section.emit_u8(param);
|
|
|
|
}
|
2016-10-06 15:43:10 +00:00
|
|
|
section.emit_u32v(type.results.length);
|
2016-06-21 19:47:51 +00:00
|
|
|
for (let result of type.results) {
|
|
|
|
section.emit_u8(result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2016-03-07 10:01:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add imports section
|
2016-03-10 12:36:42 +00:00
|
|
|
if (wasm.imports.length > 0) {
|
2016-06-21 19:47:51 +00:00
|
|
|
if (debug) print("emitting imports @ " + binary.length);
|
2016-09-27 20:46:10 +00:00
|
|
|
binary.emit_section(kImportSectionCode, section => {
|
2016-10-06 15:43:10 +00:00
|
|
|
section.emit_u32v(wasm.imports.length);
|
2016-06-21 19:47:51 +00:00
|
|
|
for (let imp of wasm.imports) {
|
|
|
|
section.emit_string(imp.module);
|
|
|
|
section.emit_string(imp.name || '');
|
2016-10-06 15:43:10 +00:00
|
|
|
section.emit_u8(imp.kind);
|
|
|
|
if (imp.kind == kExternalFunction) {
|
|
|
|
section.emit_u32v(imp.type);
|
|
|
|
} else if (imp.kind == kExternalGlobal) {
|
|
|
|
section.emit_u32v(imp.type);
|
|
|
|
section.emit_u8(imp.mutable);
|
2016-10-07 09:34:06 +00:00
|
|
|
} else if (imp.kind == kExternalMemory) {
|
|
|
|
var has_max = (typeof imp.maximum) != "undefined";
|
2017-09-14 06:14:48 +00:00
|
|
|
var is_shared = (typeof imp.shared) != "undefined";
|
|
|
|
if (is_shared) {
|
|
|
|
section.emit_u8(has_max ? 3 : 2); // flags
|
|
|
|
} else {
|
|
|
|
section.emit_u8(has_max ? 1 : 0); // flags
|
|
|
|
}
|
2016-10-07 09:34:06 +00:00
|
|
|
section.emit_u32v(imp.initial); // initial
|
|
|
|
if (has_max) section.emit_u32v(imp.maximum); // maximum
|
2016-10-29 21:06:57 +00:00
|
|
|
} else if (imp.kind == kExternalTable) {
|
|
|
|
section.emit_u8(kWasmAnyFunctionTypeForm);
|
|
|
|
var has_max = (typeof imp.maximum) != "undefined";
|
|
|
|
section.emit_u8(has_max ? 1 : 0); // flags
|
|
|
|
section.emit_u32v(imp.initial); // initial
|
|
|
|
if (has_max) section.emit_u32v(imp.maximum); // maximum
|
2018-09-11 08:38:24 +00:00
|
|
|
} else if (imp.kind == kExternalException) {
|
2018-10-22 08:39:58 +00:00
|
|
|
section.emit_u32v(kExceptionAttribute);
|
2018-10-15 14:31:16 +00:00
|
|
|
section.emit_u32v(imp.type);
|
2016-10-06 15:43:10 +00:00
|
|
|
} else {
|
|
|
|
throw new Error("unknown/unsupported import kind " + imp.kind);
|
|
|
|
}
|
2016-06-21 19:47:51 +00:00
|
|
|
}
|
|
|
|
});
|
2016-03-07 10:01:24 +00:00
|
|
|
}
|
|
|
|
|
2016-04-21 11:18:41 +00:00
|
|
|
// Add functions declarations
|
2016-03-10 12:36:42 +00:00
|
|
|
if (wasm.functions.length > 0) {
|
2016-06-21 19:47:51 +00:00
|
|
|
if (debug) print("emitting function decls @ " + binary.length);
|
2016-09-27 20:46:10 +00:00
|
|
|
binary.emit_section(kFunctionSectionCode, section => {
|
2016-10-06 15:43:10 +00:00
|
|
|
section.emit_u32v(wasm.functions.length);
|
2016-06-21 19:47:51 +00:00
|
|
|
for (let func of wasm.functions) {
|
2016-10-06 15:43:10 +00:00
|
|
|
section.emit_u32v(func.type_index);
|
2016-06-21 19:47:51 +00:00
|
|
|
}
|
|
|
|
});
|
2016-04-21 11:18:41 +00:00
|
|
|
}
|
|
|
|
|
2018-10-10 22:05:40 +00:00
|
|
|
// Add table section
|
|
|
|
if (wasm.table_length_min > 0) {
|
2016-06-21 19:47:51 +00:00
|
|
|
if (debug) print("emitting table @ " + binary.length);
|
2016-09-27 20:46:10 +00:00
|
|
|
binary.emit_section(kTableSectionCode, section => {
|
|
|
|
section.emit_u8(1); // one table entry
|
|
|
|
section.emit_u8(kWasmAnyFunctionTypeForm);
|
2018-10-10 22:05:40 +00:00
|
|
|
const max = wasm.table_length_max;
|
|
|
|
const has_max = max !== undefined;
|
|
|
|
section.emit_u8(has_max ? kHasMaximumFlag : 0);
|
|
|
|
section.emit_u32v(wasm.table_length_min);
|
|
|
|
if (has_max) section.emit_u32v(max);
|
2016-06-21 19:47:51 +00:00
|
|
|
});
|
2016-04-21 11:18:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add memory section
|
2017-04-07 14:37:30 +00:00
|
|
|
if (wasm.memory !== undefined) {
|
2016-06-21 19:47:51 +00:00
|
|
|
if (debug) print("emitting memory @ " + binary.length);
|
2016-09-27 20:46:10 +00:00
|
|
|
binary.emit_section(kMemorySectionCode, section => {
|
|
|
|
section.emit_u8(1); // one memory entry
|
2017-07-26 11:01:21 +00:00
|
|
|
const has_max = wasm.memory.max !== undefined;
|
2017-09-14 06:14:48 +00:00
|
|
|
const is_shared = wasm.memory.shared !== undefined;
|
|
|
|
// Emit flags (bit 0: reszeable max, bit 1: shared memory)
|
|
|
|
if (is_shared) {
|
|
|
|
section.emit_u8(has_max ? 3 : 2);
|
|
|
|
} else {
|
|
|
|
section.emit_u8(has_max ? 1 : 0);
|
|
|
|
}
|
2016-10-06 15:43:10 +00:00
|
|
|
section.emit_u32v(wasm.memory.min);
|
2017-07-26 11:01:21 +00:00
|
|
|
if (has_max) section.emit_u32v(wasm.memory.max);
|
2016-06-21 19:47:51 +00:00
|
|
|
});
|
2016-04-21 11:18:41 +00:00
|
|
|
}
|
|
|
|
|
2016-09-27 20:46:10 +00:00
|
|
|
// Add global section.
|
|
|
|
if (wasm.globals.length > 0) {
|
|
|
|
if (debug) print ("emitting globals @ " + binary.length);
|
|
|
|
binary.emit_section(kGlobalSectionCode, section => {
|
2016-10-06 15:43:10 +00:00
|
|
|
section.emit_u32v(wasm.globals.length);
|
|
|
|
for (let global of wasm.globals) {
|
|
|
|
section.emit_u8(global.type);
|
|
|
|
section.emit_u8(global.mutable);
|
|
|
|
if ((typeof global.init_index) == "undefined") {
|
|
|
|
// Emit a constant initializer.
|
|
|
|
switch (global.type) {
|
2016-12-21 13:43:00 +00:00
|
|
|
case kWasmI32:
|
2016-09-27 20:46:10 +00:00
|
|
|
section.emit_u8(kExprI32Const);
|
2016-10-06 15:43:10 +00:00
|
|
|
section.emit_u32v(global.init);
|
2016-09-27 20:46:10 +00:00
|
|
|
break;
|
2016-12-21 13:43:00 +00:00
|
|
|
case kWasmI64:
|
2016-09-27 20:46:10 +00:00
|
|
|
section.emit_u8(kExprI64Const);
|
2017-01-13 14:38:37 +00:00
|
|
|
section.emit_u32v(global.init);
|
2016-09-27 20:46:10 +00:00
|
|
|
break;
|
2016-12-21 13:43:00 +00:00
|
|
|
case kWasmF32:
|
2016-09-27 20:46:10 +00:00
|
|
|
section.emit_u8(kExprF32Const);
|
2016-10-06 15:43:10 +00:00
|
|
|
f32_view[0] = global.init;
|
|
|
|
section.emit_u8(byte_view[0]);
|
|
|
|
section.emit_u8(byte_view[1]);
|
|
|
|
section.emit_u8(byte_view[2]);
|
|
|
|
section.emit_u8(byte_view[3]);
|
2016-09-27 20:46:10 +00:00
|
|
|
break;
|
2016-12-21 13:43:00 +00:00
|
|
|
case kWasmF64:
|
2016-10-06 15:43:10 +00:00
|
|
|
section.emit_u8(kExprF64Const);
|
|
|
|
f64_view[0] = global.init;
|
|
|
|
section.emit_u8(byte_view[0]);
|
|
|
|
section.emit_u8(byte_view[1]);
|
|
|
|
section.emit_u8(byte_view[2]);
|
|
|
|
section.emit_u8(byte_view[3]);
|
|
|
|
section.emit_u8(byte_view[4]);
|
|
|
|
section.emit_u8(byte_view[5]);
|
|
|
|
section.emit_u8(byte_view[6]);
|
|
|
|
section.emit_u8(byte_view[7]);
|
2016-09-27 20:46:10 +00:00
|
|
|
break;
|
2016-10-06 15:43:10 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Emit a global-index initializer.
|
|
|
|
section.emit_u8(kExprGetGlobal);
|
|
|
|
section.emit_u32v(global.init_index);
|
2016-09-27 20:46:10 +00:00
|
|
|
}
|
|
|
|
section.emit_u8(kExprEnd); // end of init expression
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2016-04-21 11:18:41 +00:00
|
|
|
|
2018-09-06 08:14:22 +00:00
|
|
|
// Add exceptions.
|
|
|
|
if (wasm.exceptions.length > 0) {
|
|
|
|
if (debug) print("emitting exceptions @ " + binary.length);
|
|
|
|
binary.emit_section(kExceptionSectionCode, section => {
|
|
|
|
section.emit_u32v(wasm.exceptions.length);
|
|
|
|
for (let type of wasm.exceptions) {
|
2018-10-22 08:39:58 +00:00
|
|
|
section.emit_u32v(kExceptionAttribute);
|
2018-10-15 14:31:16 +00:00
|
|
|
section.emit_u32v(type);
|
2018-09-06 08:14:22 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-04-21 11:18:41 +00:00
|
|
|
// Add export table.
|
2017-04-07 14:37:30 +00:00
|
|
|
var mem_export = (wasm.memory !== undefined && wasm.memory.exp);
|
2016-10-06 15:43:10 +00:00
|
|
|
var exports_count = wasm.exports.length + (mem_export ? 1 : 0);
|
|
|
|
if (exports_count > 0) {
|
2016-06-21 19:47:51 +00:00
|
|
|
if (debug) print("emitting exports @ " + binary.length);
|
2016-09-27 20:46:10 +00:00
|
|
|
binary.emit_section(kExportSectionCode, section => {
|
2016-10-06 15:43:10 +00:00
|
|
|
section.emit_u32v(exports_count);
|
|
|
|
for (let exp of wasm.exports) {
|
|
|
|
section.emit_string(exp.name);
|
|
|
|
section.emit_u8(exp.kind);
|
|
|
|
section.emit_u32v(exp.index);
|
2016-06-21 19:47:51 +00:00
|
|
|
}
|
2016-09-27 20:46:10 +00:00
|
|
|
if (mem_export) {
|
|
|
|
section.emit_string("memory");
|
|
|
|
section.emit_u8(kExternalMemory);
|
|
|
|
section.emit_u8(0);
|
|
|
|
}
|
2016-06-21 19:47:51 +00:00
|
|
|
});
|
2016-04-21 11:18:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add start function section.
|
2017-04-07 14:37:30 +00:00
|
|
|
if (wasm.start_index !== undefined) {
|
2016-06-21 19:47:51 +00:00
|
|
|
if (debug) print("emitting start function @ " + binary.length);
|
2016-09-27 20:46:10 +00:00
|
|
|
binary.emit_section(kStartSectionCode, section => {
|
2016-10-06 15:43:10 +00:00
|
|
|
section.emit_u32v(wasm.start_index);
|
2016-06-21 19:47:51 +00:00
|
|
|
});
|
2016-04-21 11:18:41 +00:00
|
|
|
}
|
|
|
|
|
2018-10-10 22:05:40 +00:00
|
|
|
// Add element segments
|
|
|
|
if (wasm.element_segments.length > 0) {
|
|
|
|
if (debug) print("emitting element segments @ " + binary.length);
|
2016-09-27 20:46:10 +00:00
|
|
|
binary.emit_section(kElementSectionCode, section => {
|
2018-10-10 22:05:40 +00:00
|
|
|
var inits = wasm.element_segments;
|
[wasm] Use a Managed<WasmModule> to hold metadata about modules.
This CL refactors the handling of metadata associated with WebAssembly
modules to reduce the duplicate marshalling of data from the C++ world
to the JavaScript world. It does this by wrapping the C++ WasmModule*
object in a Foreign that is rooted from the on-heap WasmCompiledModule
(which is itself just a FixedArray). Upon serialization, the C++ object
is ignored and the original WASM wire bytes are serialized. Upon
deserialization, the C++ object is reconstituted by reparsing the bytes.
This is motivated by increasing complications in implementing the JS
API, in particular WebAssembly.Table, which must perform signature
canonicalization across instances.
Additionally, this CL implements the proper base + offset initialization
behavior for tables.
R=rossberg@chromium.org,bradnelson@chromium.org,mtrofin@chromium.org,yangguo@chromium.org
BUG=v8:5507, chromium:575167, chromium:657316
Review-Url: https://chromiumcodereview.appspot.com/2424623002
Cr-Commit-Position: refs/heads/master@{#40434}
2016-10-19 13:06:44 +00:00
|
|
|
section.emit_u32v(inits.length);
|
|
|
|
|
|
|
|
for (let init of inits) {
|
2018-11-12 20:53:47 +00:00
|
|
|
if (init.is_active) {
|
|
|
|
section.emit_u8(0); // table index / flags
|
|
|
|
if (init.is_global) {
|
|
|
|
section.emit_u8(kExprGetGlobal);
|
|
|
|
} else {
|
|
|
|
section.emit_u8(kExprI32Const);
|
|
|
|
}
|
|
|
|
section.emit_u32v(init.base);
|
|
|
|
section.emit_u8(kExprEnd);
|
[wasm] Use a Managed<WasmModule> to hold metadata about modules.
This CL refactors the handling of metadata associated with WebAssembly
modules to reduce the duplicate marshalling of data from the C++ world
to the JavaScript world. It does this by wrapping the C++ WasmModule*
object in a Foreign that is rooted from the on-heap WasmCompiledModule
(which is itself just a FixedArray). Upon serialization, the C++ object
is ignored and the original WASM wire bytes are serialized. Upon
deserialization, the C++ object is reconstituted by reparsing the bytes.
This is motivated by increasing complications in implementing the JS
API, in particular WebAssembly.Table, which must perform signature
canonicalization across instances.
Additionally, this CL implements the proper base + offset initialization
behavior for tables.
R=rossberg@chromium.org,bradnelson@chromium.org,mtrofin@chromium.org,yangguo@chromium.org
BUG=v8:5507, chromium:575167, chromium:657316
Review-Url: https://chromiumcodereview.appspot.com/2424623002
Cr-Commit-Position: refs/heads/master@{#40434}
2016-10-19 13:06:44 +00:00
|
|
|
} else {
|
2018-11-12 20:53:47 +00:00
|
|
|
section.emit_u8(kPassive); // flags
|
[wasm] Use a Managed<WasmModule> to hold metadata about modules.
This CL refactors the handling of metadata associated with WebAssembly
modules to reduce the duplicate marshalling of data from the C++ world
to the JavaScript world. It does this by wrapping the C++ WasmModule*
object in a Foreign that is rooted from the on-heap WasmCompiledModule
(which is itself just a FixedArray). Upon serialization, the C++ object
is ignored and the original WASM wire bytes are serialized. Upon
deserialization, the C++ object is reconstituted by reparsing the bytes.
This is motivated by increasing complications in implementing the JS
API, in particular WebAssembly.Table, which must perform signature
canonicalization across instances.
Additionally, this CL implements the proper base + offset initialization
behavior for tables.
R=rossberg@chromium.org,bradnelson@chromium.org,mtrofin@chromium.org,yangguo@chromium.org
BUG=v8:5507, chromium:575167, chromium:657316
Review-Url: https://chromiumcodereview.appspot.com/2424623002
Cr-Commit-Position: refs/heads/master@{#40434}
2016-10-19 13:06:44 +00:00
|
|
|
}
|
|
|
|
section.emit_u32v(init.array.length);
|
|
|
|
for (let index of init.array) {
|
|
|
|
section.emit_u32v(index);
|
|
|
|
}
|
2016-09-27 20:46:10 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-04-21 11:18:41 +00:00
|
|
|
// Add function bodies.
|
|
|
|
if (wasm.functions.length > 0) {
|
2016-06-21 19:47:51 +00:00
|
|
|
// emit function bodies
|
|
|
|
if (debug) print("emitting code @ " + binary.length);
|
2016-09-27 20:46:10 +00:00
|
|
|
binary.emit_section(kCodeSectionCode, section => {
|
2016-10-06 15:43:10 +00:00
|
|
|
section.emit_u32v(wasm.functions.length);
|
2016-06-21 19:47:51 +00:00
|
|
|
for (let func of wasm.functions) {
|
|
|
|
// Function body length will be patched later.
|
|
|
|
let local_decls = [];
|
2018-01-08 11:54:54 +00:00
|
|
|
for (let l of func.locals || []) {
|
2016-06-21 19:47:51 +00:00
|
|
|
if (l.i32_count > 0) {
|
2016-12-21 13:43:00 +00:00
|
|
|
local_decls.push({count: l.i32_count, type: kWasmI32});
|
2016-03-07 10:01:24 +00:00
|
|
|
}
|
2016-06-21 19:47:51 +00:00
|
|
|
if (l.i64_count > 0) {
|
2016-12-21 13:43:00 +00:00
|
|
|
local_decls.push({count: l.i64_count, type: kWasmI64});
|
2016-06-21 19:47:51 +00:00
|
|
|
}
|
|
|
|
if (l.f32_count > 0) {
|
2016-12-21 13:43:00 +00:00
|
|
|
local_decls.push({count: l.f32_count, type: kWasmF32});
|
2016-06-21 19:47:51 +00:00
|
|
|
}
|
|
|
|
if (l.f64_count > 0) {
|
2016-12-21 13:43:00 +00:00
|
|
|
local_decls.push({count: l.f64_count, type: kWasmF64});
|
2016-06-21 19:47:51 +00:00
|
|
|
}
|
2017-09-11 12:34:35 +00:00
|
|
|
if (l.s128_count > 0) {
|
|
|
|
local_decls.push({count: l.s128_count, type: kWasmS128});
|
|
|
|
}
|
2018-09-03 10:39:55 +00:00
|
|
|
if (l.anyref_count > 0) {
|
|
|
|
local_decls.push({count: l.anyref_count, type: kWasmAnyRef});
|
|
|
|
}
|
2018-08-30 12:46:48 +00:00
|
|
|
if (l.except_count > 0) {
|
|
|
|
local_decls.push({count: l.except_count, type: kWasmExceptRef});
|
|
|
|
}
|
2016-06-21 19:47:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let header = new Binary;
|
2016-10-06 15:43:10 +00:00
|
|
|
header.emit_u32v(local_decls.length);
|
2016-06-21 19:47:51 +00:00
|
|
|
for (let decl of local_decls) {
|
2016-10-06 15:43:10 +00:00
|
|
|
header.emit_u32v(decl.count);
|
2016-06-21 19:47:51 +00:00
|
|
|
header.emit_u8(decl.type);
|
|
|
|
}
|
|
|
|
|
2016-10-06 15:43:10 +00:00
|
|
|
section.emit_u32v(header.length + func.body.length);
|
2016-06-21 19:47:51 +00:00
|
|
|
section.emit_bytes(header);
|
|
|
|
section.emit_bytes(func.body);
|
|
|
|
}
|
|
|
|
});
|
2016-03-09 22:50:36 +00:00
|
|
|
}
|
2016-03-07 10:01:24 +00:00
|
|
|
|
2016-04-21 11:18:41 +00:00
|
|
|
// Add data segments.
|
2018-10-10 22:05:40 +00:00
|
|
|
if (wasm.data_segments.length > 0) {
|
2016-06-21 19:47:51 +00:00
|
|
|
if (debug) print("emitting data segments @ " + binary.length);
|
2016-09-27 20:46:10 +00:00
|
|
|
binary.emit_section(kDataSectionCode, section => {
|
2018-10-10 22:05:40 +00:00
|
|
|
section.emit_u32v(wasm.data_segments.length);
|
|
|
|
for (let seg of wasm.data_segments) {
|
2018-11-12 20:53:47 +00:00
|
|
|
if (seg.is_active) {
|
|
|
|
section.emit_u8(0); // linear memory index 0 / flags
|
|
|
|
if (seg.is_global) {
|
|
|
|
// initializer is a global variable
|
|
|
|
section.emit_u8(kExprGetGlobal);
|
|
|
|
section.emit_u32v(seg.addr);
|
|
|
|
} else {
|
|
|
|
// initializer is a constant
|
|
|
|
section.emit_u8(kExprI32Const);
|
|
|
|
section.emit_u32v(seg.addr);
|
|
|
|
}
|
|
|
|
section.emit_u8(kExprEnd);
|
2016-10-10 14:41:50 +00:00
|
|
|
} else {
|
2018-11-12 20:53:47 +00:00
|
|
|
section.emit_u8(kPassive); // flags
|
2016-10-10 14:41:50 +00:00
|
|
|
}
|
2016-10-06 15:43:10 +00:00
|
|
|
section.emit_u32v(seg.data.length);
|
2016-06-21 19:47:51 +00:00
|
|
|
section.emit_bytes(seg.data);
|
|
|
|
}
|
|
|
|
});
|
2016-03-07 10:01:24 +00:00
|
|
|
}
|
|
|
|
|
2016-04-21 11:18:41 +00:00
|
|
|
// Add any explicitly added sections
|
2016-06-21 19:47:51 +00:00
|
|
|
for (let exp of wasm.explicit) {
|
|
|
|
if (debug) print("emitting explicit @ " + binary.length);
|
|
|
|
binary.emit_bytes(exp);
|
2016-03-07 19:32:35 +00:00
|
|
|
}
|
|
|
|
|
2017-06-12 09:31:14 +00:00
|
|
|
// Add names.
|
2017-07-02 19:18:57 +00:00
|
|
|
let num_function_names = 0;
|
|
|
|
let num_functions_with_local_names = 0;
|
|
|
|
for (let func of wasm.functions) {
|
|
|
|
if (func.name !== undefined) ++num_function_names;
|
|
|
|
if (func.numLocalNames() > 0) ++num_functions_with_local_names;
|
|
|
|
}
|
|
|
|
if (num_function_names > 0 || num_functions_with_local_names > 0 ||
|
|
|
|
wasm.name !== undefined) {
|
2017-04-07 14:37:30 +00:00
|
|
|
if (debug) print('emitting names @ ' + binary.length);
|
2016-09-27 20:46:10 +00:00
|
|
|
binary.emit_section(kUnknownSectionCode, section => {
|
2017-04-07 14:37:30 +00:00
|
|
|
section.emit_string('name');
|
2017-07-02 19:18:57 +00:00
|
|
|
// Emit module name.
|
2017-06-12 09:31:14 +00:00
|
|
|
if (wasm.name !== undefined) {
|
|
|
|
section.emit_section(kModuleNameCode, name_section => {
|
|
|
|
name_section.emit_string(wasm.name);
|
|
|
|
});
|
|
|
|
}
|
2017-07-02 19:18:57 +00:00
|
|
|
// Emit function names.
|
2017-06-12 09:31:14 +00:00
|
|
|
if (num_function_names > 0) {
|
|
|
|
section.emit_section(kFunctionNamesCode, name_section => {
|
|
|
|
name_section.emit_u32v(num_function_names);
|
|
|
|
for (let func of wasm.functions) {
|
|
|
|
if (func.name === undefined) continue;
|
|
|
|
name_section.emit_u32v(func.index);
|
|
|
|
name_section.emit_string(func.name);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2017-07-02 19:18:57 +00:00
|
|
|
// Emit local names.
|
|
|
|
if (num_functions_with_local_names > 0) {
|
|
|
|
section.emit_section(kLocalNamesCode, name_section => {
|
|
|
|
name_section.emit_u32v(num_functions_with_local_names);
|
|
|
|
for (let func of wasm.functions) {
|
|
|
|
if (func.numLocalNames() == 0) continue;
|
|
|
|
name_section.emit_u32v(func.index);
|
|
|
|
name_section.emit_u32v(func.numLocalNames());
|
|
|
|
for (let i = 0; i < func.local_names.length; ++i) {
|
|
|
|
if (func.local_names[i] === undefined) continue;
|
|
|
|
name_section.emit_u32v(i);
|
|
|
|
name_section.emit_string(func.local_names[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2016-06-21 19:47:51 +00:00
|
|
|
});
|
2016-04-21 11:18:41 +00:00
|
|
|
}
|
|
|
|
|
2016-06-21 19:47:51 +00:00
|
|
|
return binary;
|
|
|
|
}
|
2016-03-07 10:01:24 +00:00
|
|
|
|
2016-10-13 16:17:44 +00:00
|
|
|
toBuffer(debug = false) {
|
2016-06-21 19:47:51 +00:00
|
|
|
let bytes = this.toArray(debug);
|
|
|
|
let buffer = new ArrayBuffer(bytes.length);
|
|
|
|
let view = new Uint8Array(buffer);
|
|
|
|
for (let i = 0; i < bytes.length; i++) {
|
|
|
|
let val = bytes[i];
|
|
|
|
if ((typeof val) == "string") val = val.charCodeAt(0);
|
|
|
|
view[i] = val | 0;
|
2016-03-07 10:01:24 +00:00
|
|
|
}
|
|
|
|
return buffer;
|
2016-06-21 19:47:51 +00:00
|
|
|
}
|
2016-03-07 10:01:24 +00:00
|
|
|
|
2017-01-12 16:48:09 +00:00
|
|
|
instantiate(ffi) {
|
2016-06-21 19:47:51 +00:00
|
|
|
let module = new WebAssembly.Module(this.toBuffer());
|
2017-01-12 16:48:09 +00:00
|
|
|
let instance = new WebAssembly.Instance(module, ffi);
|
2016-06-21 19:47:51 +00:00
|
|
|
return instance;
|
|
|
|
}
|
2017-07-07 13:52:21 +00:00
|
|
|
|
2018-03-22 10:40:10 +00:00
|
|
|
asyncInstantiate(ffi) {
|
|
|
|
return WebAssembly.instantiate(this.toBuffer(), ffi)
|
|
|
|
.then(({module, instance}) => instance);
|
|
|
|
}
|
|
|
|
|
2017-07-07 13:52:21 +00:00
|
|
|
toModule(debug = false) {
|
2017-07-24 19:21:28 +00:00
|
|
|
return new WebAssembly.Module(this.toBuffer(debug));
|
2017-07-07 13:52:21 +00:00
|
|
|
}
|
2016-03-07 10:01:24 +00:00
|
|
|
}
|