You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 29ac322
Browse filesBrowse the repository at this point in the historyBrowse files
[Wasm] Build JS Wrappers and JSToWasmCallees Lazily
https://bugs.webkit.org/show_bug.cgi?id=314910
rdar://177187656
Reviewed by Yusuke Suzuki.
Wasm instantiation eagerly built two things that are commonly unused:
1. A WebAssemblyFunction (or WebAssemblyWrapperFunction) wrapper for every
function listed in ModuleInformation::referencedFunctions() — the union of
exports, ref.func targets, and element-segment entries. Many modules never
expose most of those functions to JS.
2. A Wasm::JSToWasmCallee for every defined Wasm function, built inside
IPIntPlan and stored in CalleeGroup::m_jsToWasmCallees. Most internal
functions are never called from JS, so the thunk and frame-size
computation were wasted.
This patch makes both lazy. The resulting eagerness matrix is:
| Function kind | Wrapper | JS->Wasm callee |
|------------------------------------|------------------------------|-----------------|
| Exported | eager (instantiation) | eager-on-create |
| In an active element segment | eager (table-init at link) | eager-on-create |
| Only via passive/dec element seg | lazy (table.init/table.copy) | eager-on-create |
| Only via ref.func | lazy (ref.func execution) | eager-on-create |
| Host import | lazy | n/a |
Wrappers for non-exports are now materialized on demand by the new
JSWebAssemblyInstance::ensureFunctionWrapper(FunctionSpaceIndex), which
folds in the previous makeFunctionWrapper lambda from
WebAssemblyModuleRecord. The eager loop over referencedFunctions() is
replaced with a smaller exports-only loop in WebAssemblyModuleRecord.
Active element segments still create wrappers at instantiation, but only
for the functions they actually contain (via the table-init code path),
not the precomputed union of all referenced functions. ref.func, table
init/copy, const-expr evaluation, and the start-function path all now
route through ensureFunctionWrapper.
JSToWasmCallee construction is removed from IPIntPlan
(takeJSToWasmCallees, ensureEntrypoint, m_entrypoints, m_jsToWasmCallees
are gone). CalleeGroup::ensureJSToWasmCallee(const ModuleInformation&,
FunctionSpaceIndex) creates and caches the JSToWasmCallee on first
demand, guarded by a dedicated m_jsToWasmCalleesLock so it does not
contend with the rest of CalleeGroup::m_lock. WebAssemblyFunction owns a
RefPtr to the boxed callee and exposes ensureJSToWasmCallee, which is
called from WebAssemblyFunction::create so the LLInt and JIT JS->Wasm
entry trampolines (which read m_boxedJSToWasmCallee and m_frameSize
directly via fixed offsets, bypassing callWebAssemblyFunction) always
observe a populated value. WebAssemblyFunction is single-threaded so no
extra locking is needed there.
Also, remove the ModuleInformation::referencedFunctions() function and
related BitVector. The referencedFunctions list was only used to
determine which functions to create wrappers for.
No new tests, no behavior change. Covered by existing tests.
Canonical link: https://commits.webkit.org/313362@main
Copy file name to clipboardExpand all lines: Source/JavaScriptCore/runtime/NativeCallee.h
+8-1Lines changed: 8 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -65,14 +65,21 @@ class BoxedNativeCalleePtrTraits {
65
65
using StorageType = CalleeBits;
66
66
// Use an intermediate cast to uintptr_t to silence unsafe casting warning. It's locally "obvious" (other than the fact that RefPtr uses StorageType's constructor instead of a wrap) the
WASM_VALIDATOR_FAIL_IF(storageType.is<PackedType>(), "type mismatch in array.new_elem: expected `funcref` or `externref`");
2609
2594
2610
2595
WASM_VALIDATOR_FAIL_IF(!isSubtype(elementsSegment.elementType, storageType.unpacked()), "type mismatch in array.new_elem: segment elements have type ", elementsSegment.elementType, " but array.new_elem operation expects elements of type ", storageType.unpacked());
2611
-
// Create function wrappers for any functions in this element segment.
2612
-
// We conservatively assume that the `array.new_canon_elem` instruction will be executed.
2613
-
// An optimization would be to lazily create the wrappers when the array is initialized.
WASM_VALIDATOR_FAIL_IF(dstFieldType.mutability != Mutability::Mutable, "array.init_elem index ", dstTypeIndex, " does not reference a mutable array definition");
2771
2752
2772
2753
WASM_VALIDATOR_FAIL_IF(!isSubtype(segmentElementType, unpackedElementType), "type mismatch in array.init_elem: segment elements have type ", segmentElementType, " but array.init_elem operation expects elements of type ", unpackedElementType);
0 commit comments