From ccb438318982149578c5f190094f5f8a4d98e9cb Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Mon, 2 Sep 2019 15:09:22 +0200 Subject: [PATCH] Add custom `asyncify` section(s) Names of all the asyncified export functions are now added as data of custom "asyncify" sections. This allows to detect them in a JS wrapper and wrap into async JS functions only if necessary. We could come up with a more condensed representation that doesn't duplicate export function names or name of "asyncify" section itself, but this would add unnecessary complexity to implementation with little benefit after Gzip / Brotli, which already take care of duplicated strings quite well. Fixes https://github.com/WebAssembly/binaryen/issues/2322. --- src/passes/Asyncify.cpp | 26 ++++++++++++++++++++++++++ src/wasm-binary.h | 1 + src/wasm/wasm.cpp | 1 + 3 files changed, 28 insertions(+) diff --git a/src/passes/Asyncify.cpp b/src/passes/Asyncify.cpp index 1394cd015e2..5ec2b5264c5 100644 --- a/src/passes/Asyncify.cpp +++ b/src/passes/Asyncify.cpp @@ -1150,6 +1150,32 @@ struct Asyncify : public Pass { runner.setValidateGlobally(false); runner.run(); } + // Mark exported asyncified functions. + // + // This creates a custom section for each function that: + // 1) Is exported and, thus, directly accessible by user. + // 2) Might directly or indirectly start an async operation (and unwind). + // + // Each such section will have a name "asyncify" and name of the export as + // its data. + // + // This gives the JavaScript side an opportunity to wrap functions into an + // `async` variant only if it's necessary, and leave others intact. + auto& userSections = module->userSections; + for (auto& exp : module->exports) { + if (exp->kind != ExternalKind::Function) { + continue; + } + auto* func = module->getFunction(exp->value); + if (!analyzer.needsInstrumentation(func)) { + continue; + } + userSections.resize(userSections.size() + 1); + auto& section = userSections.back(); + section.name = BinaryConsts::UserSections::Asyncify; + auto& name = exp->name; + section.data.assign(name.c_str(), name.c_str() + name.size()); + } // Finally, add function support (that should not have been seen by // the previous passes). addFunctions(module); diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 1c5fa774a58..4eaf7deabe9 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -398,6 +398,7 @@ extern const char* Dylink; extern const char* Linking; extern const char* Producers; extern const char* TargetFeatures; +extern const char* Asyncify; extern const char* AtomicsFeature; extern const char* BulkMemoryFeature; diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index ec23b5c9468..0bb2e3afe01 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -33,6 +33,7 @@ const char* Dylink = "dylink"; const char* Linking = "linking"; const char* Producers = "producers"; const char* TargetFeatures = "target_features"; +const char* Asyncify = "asyncify"; const char* AtomicsFeature = "atomics"; const char* BulkMemoryFeature = "bulk-memory"; const char* ExceptionHandlingFeature = "exception-handling";