Don't use JSON for custom section format

This commit migrates away from using Serde for the custom section in
wasm executables. This is a refactoring of a purely-internal data
structure to `wasm-bindgen` and should have no visible functional change
on users.

The motivation for this commit is two fold:

* First, the compile times using `serde_json` and `serde_derive` for the
  syntax extension isn't the most fun.
* Second, eventually we're going to want to stablize the layout of the
  custom section, and it's highly unlikely to be json!

Primarily, though, the intention of this commit is to improve the
cold-cache compile time of `wasm-bindgen` by ensuring that for new users
this project builds as quickly as possible. By removing some heavyweight
dependencies from the procedural macro, `serde`, `serde_derive`, and
`serde_json`, we're able to get a pretty nice build time improvement for
the `wasm-bindgen` crate itself:

|             | single-core build | parallel build |
|-------------|-------------------|----------------|
| master      |             36.5s |          17.3s |
| this commit |             20.5s |          11.8s |

These are't really end-all-be-all wins but they're much better
especially on the spectrum of weaker CPUs (in theory modeled by the
single-core case showing we have 42% less CPU work in theory).
This commit is contained in:
Alex Crichton
2018-08-26 15:43:33 -07:00
parent aac8696d05
commit f749c7cf95
12 changed files with 752 additions and 385 deletions

View File

@ -10,7 +10,3 @@ description = """
Shared support between wasm-bindgen and wasm-bindgen cli, an internal
dependency.
"""
[dependencies]
serde_derive = "1"
serde = "1"

View File

@ -1,139 +1,118 @@
#![doc(html_root_url = "https://docs.rs/wasm-bindgen-shared/0.2")]
#[macro_use]
extern crate serde_derive;
// The schema is so unstable right now we just force it to change whenever this
// package's version changes, which happens on all publishes.
pub const SCHEMA_VERSION: &str = env!("CARGO_PKG_VERSION");
#[derive(Deserialize)]
pub struct ProgramOnlySchema {
pub schema_version: String,
pub version: String,
#[macro_export]
macro_rules! shared_api {
($mac:ident) => ($mac! {
struct Program<'a> {
exports: Vec<Export<'a>>,
enums: Vec<Enum<'a>>,
imports: Vec<Import<'a>>,
structs: Vec<Struct<'a>>,
// version: &'a str,
// schema_version: &'a str,
}
#[derive(Deserialize, Serialize)]
pub struct Program {
pub exports: Vec<Export>,
pub enums: Vec<Enum>,
pub imports: Vec<Import>,
pub structs: Vec<Struct>,
pub version: String,
pub schema_version: String,
struct Import<'a> {
module: Option<&'a str>,
js_namespace: Option<&'a str>,
kind: ImportKind<'a>,
}
#[derive(Deserialize, Serialize)]
pub struct Import {
pub module: Option<String>,
pub js_namespace: Option<String>,
pub kind: ImportKind,
}
#[derive(Deserialize, Serialize)]
#[serde(tag = "kind", rename_all = "lowercase")]
pub enum ImportKind {
Function(ImportFunction),
Static(ImportStatic),
Type(ImportType),
enum ImportKind<'a> {
Function(ImportFunction<'a>),
Static(ImportStatic<'a>),
Type(ImportType<'a>),
Enum(ImportEnum),
}
#[derive(Deserialize, Serialize)]
pub struct ImportFunction {
pub shim: String,
pub catch: bool,
pub variadic: bool,
pub method: Option<MethodData>,
pub structural: bool,
pub function: Function,
struct ImportFunction<'a> {
shim: &'a str,
catch: bool,
variadic: bool,
method: Option<MethodData<'a>>,
structural: bool,
function: Function<'a>,
}
#[derive(Deserialize, Serialize)]
pub struct MethodData {
pub class: String,
pub kind: MethodKind,
struct MethodData<'a> {
class: &'a str,
kind: MethodKind<'a>,
}
#[derive(Deserialize, Serialize)]
pub enum MethodKind {
enum MethodKind<'a> {
Constructor,
Operation(Operation),
Operation(Operation<'a>),
}
#[derive(Deserialize, Serialize)]
pub struct Operation {
pub is_static: bool,
pub kind: OperationKind,
struct Operation<'a> {
is_static: bool,
kind: OperationKind<'a>,
}
#[derive(Deserialize, Serialize)]
pub enum OperationKind {
enum OperationKind<'a> {
Regular,
Getter(String),
Setter(String),
Getter(&'a str),
Setter(&'a str),
IndexingGetter,
IndexingSetter,
IndexingDeleter,
}
#[derive(Deserialize, Serialize)]
pub struct ImportStatic {
pub name: String,
pub shim: String,
struct ImportStatic<'a> {
name: &'a str,
shim: &'a str,
}
#[derive(Deserialize, Serialize)]
pub struct ImportType {
pub name: String,
pub instanceof_shim: String,
pub vendor_prefixes: Vec<String>,
struct ImportType<'a> {
name: &'a str,
instanceof_shim: &'a str,
vendor_prefixes: Vec<&'a str>,
}
#[derive(Deserialize, Serialize)]
pub struct ImportEnum {}
struct ImportEnum {}
#[derive(Deserialize, Serialize)]
pub struct Export {
pub class: Option<String>,
pub method: bool,
pub consumed: bool,
pub is_constructor: bool,
pub function: Function,
pub comments: Vec<String>,
struct Export<'a> {
class: Option<&'a str>,
method: bool,
consumed: bool,
is_constructor: bool,
function: Function<'a>,
comments: Vec<&'a str>,
}
#[derive(Deserialize, Serialize)]
pub struct Enum {
pub name: String,
pub variants: Vec<EnumVariant>,
pub comments: Vec<String>,
struct Enum<'a> {
name: &'a str,
variants: Vec<EnumVariant<'a>>,
comments: Vec<&'a str>,
}
#[derive(Deserialize, Serialize)]
pub struct EnumVariant {
pub name: String,
pub value: u32,
struct EnumVariant<'a> {
name: &'a str,
value: u32,
}
#[derive(Deserialize, Serialize)]
pub struct Function {
pub name: String,
struct Function<'a> {
name: &'a str,
}
#[derive(Deserialize, Serialize)]
pub struct Struct {
pub name: String,
pub fields: Vec<StructField>,
pub comments: Vec<String>,
struct Struct<'a> {
name: &'a str,
fields: Vec<StructField<'a>>,
comments: Vec<&'a str>,
}
#[derive(Deserialize, Serialize)]
pub struct StructField {
pub name: String,
pub readonly: bool,
pub comments: Vec<String>,
struct StructField<'a> {
name: &'a str,
readonly: bool,
comments: Vec<&'a str>,
}
}) // end of mac case
} // end of mac definition
pub fn new_function(struct_name: &str) -> String {
let mut name = format!("__wbg_");