-
Notifications
You must be signed in to change notification settings - Fork 5.1k
[wasm-mt] Use asset loading for dotnet.worker.js; update WasmAppBuilder #73697
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
a90464e
673cd1f
e12de7b
a0e71e4
5db8e8c
af2b21a
f1c7d59
0a8357b
e655a46
8c686a2
aa2d070
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
import { Module } from "../../imports"; | ||
import { pthread_ptr } from "./types"; | ||
|
||
/** @module emscripten-internals accessors to the functions in the emscripten PThreads library, including | ||
* the low-level representations of {@linkcode pthread_ptr} thread info structs, etc. | ||
* Additionally, note that some of these functions are replaced by {@linkcode file://./emscripten-replacements.ts}. | ||
* These have a hard dependency on the version of Emscripten that we are using and may need to be kept in sync with | ||
* {@linkcode file://./../../../emsdk/upstream/emscripten/src/library_pthread.js} | ||
*/ | ||
|
||
// This is what we know about the Emscripten PThread library | ||
interface PThreadLibrary { | ||
unusedWorkers: Worker[]; | ||
pthreads: PThreadInfoMap; | ||
allocateUnusedWorker: () => void; | ||
loadWasmModuleToWorker: (worker: Worker, onFinishedLoading?: (worker: Worker) => void) => void; | ||
} | ||
|
||
interface EmscriptenPThreadInfo { | ||
threadInfoStruct: pthread_ptr; | ||
} | ||
|
||
/// N.B. emscripten deletes the `pthread` property from the worker when it is not actively running a pthread | ||
interface PThreadWorker extends Worker { | ||
pthread: EmscriptenPThreadInfo; | ||
} | ||
|
||
interface PThreadObject { | ||
worker: PThreadWorker; | ||
} | ||
|
||
interface PThreadInfoMap { | ||
[key: pthread_ptr]: PThreadObject | undefined; | ||
} | ||
|
||
|
||
function isRunningPThreadWorker(w: Worker): w is PThreadWorker { | ||
return (<any>w).pthread !== undefined; | ||
} | ||
|
||
/// These utility functions dig into Emscripten internals | ||
const Internals = { | ||
get modulePThread(): PThreadLibrary { | ||
return (<any>Module).PThread as PThreadLibrary; | ||
}, | ||
getWorker: (pthread_ptr: pthread_ptr): PThreadWorker | undefined => { | ||
// see https://github.com/emscripten-core/emscripten/pull/16239 | ||
return Internals.modulePThread.pthreads[pthread_ptr]?.worker; | ||
}, | ||
getThreadId: (worker: Worker): pthread_ptr | undefined => { | ||
/// See library_pthread.js in Emscripten. | ||
/// They hang a "pthread" object from the worker if the worker is running a thread, and remove it when the thread stops by doing `pthread_exit` or when it's joined using `pthread_join`. | ||
if (!isRunningPThreadWorker(worker)) | ||
return undefined; | ||
const emscriptenThreadInfo = worker.pthread; | ||
return emscriptenThreadInfo.threadInfoStruct; | ||
}, | ||
allocateUnusedWorker: (): void => { | ||
/// See library_pthread.js in Emscripten. | ||
/// This function allocates a new worker and adds it to the pool of workers. | ||
/// It's called when the pool of workers is empty and a new thread is created. | ||
Internals.modulePThread.allocateUnusedWorker(); | ||
}, | ||
getUnusedWorkerPool: (): Worker[] => { | ||
return Internals.modulePThread.unusedWorkers; | ||
}, | ||
loadWasmModuleToWorker: (worker: Worker, onFinishedLoading: () => void): void => { | ||
Internals.modulePThread.loadWasmModuleToWorker(worker, onFinishedLoading); | ||
} | ||
}; | ||
|
||
|
||
export default Internals; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
import MonoWasmThreads from "consts:monoWasmThreads"; | ||
import { PThreadReplacements } from "../../types"; | ||
import { afterLoadWasmModuleToWorker } from "../browser"; | ||
import { afterThreadInitTLS } from "../worker"; | ||
import Internals from "./emscripten-internals"; | ||
import { resolve_asset_path } from "../../assets"; | ||
import { mono_assert } from "../../types"; | ||
|
||
|
||
/** @module emscripten-replacements Replacements for individual functions in the emscripten PThreads library. | ||
* These have a hard dependency on the version of Emscripten that we are using and may need to be kept in sync with | ||
* {@linkcode file://./../../../emsdk/upstream/emscripten/src/library_pthread.js} | ||
*/ | ||
|
||
export function replaceEmscriptenPThreadLibrary(replacements: PThreadReplacements): void { | ||
if (MonoWasmThreads) { | ||
const originalLoadWasmModuleToWorker = replacements.loadWasmModuleToWorker; | ||
replacements.loadWasmModuleToWorker = (worker: Worker, onFinishedLoading?: (worker: Worker) => void): void => { | ||
originalLoadWasmModuleToWorker(worker, onFinishedLoading); | ||
afterLoadWasmModuleToWorker(worker); | ||
}; | ||
const originalThreadInitTLS = replacements.threadInitTLS; | ||
replacements.threadInitTLS = (): void => { | ||
originalThreadInitTLS(); | ||
afterThreadInitTLS(); | ||
}; | ||
// const originalAllocateUnusedWorker = replacements.allocateUnusedWorker; | ||
replacements.allocateUnusedWorker = replacementAllocateUnusedWorker; | ||
} | ||
} | ||
|
||
/// We replace Module["PThreads"].allocateUnusedWorker with this version that knows about assets | ||
function replacementAllocateUnusedWorker(): void { | ||
console.debug("MONO_WASM: replacementAllocateUnusedWorker"); | ||
const asset = resolve_asset_path("js-module-threads"); | ||
const uri = asset.resolvedUrl; | ||
mono_assert(uri !== undefined, "could not resolve the uri for the js-module-threads asset"); | ||
const worker = new Worker(uri); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should subscribe onError here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and maybe proxy the console in the worker, similar way how it was done in crypto worker. See how we passed the json.stringify(runtimeHelpers.config) and then only forward console when enabled. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Emscripten installs an onerror handler of their own that will overwrite ours. we can set one up later (in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
ok, i'll see if I can add that over the weekend; if not, there's a task to do it in the tracking issue |
||
Internals.getUnusedWorkerPool().push(worker); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,8 @@ | ||
{ | ||
"extends": "../../tsconfig.shared.json" | ||
"extends": "../../tsconfig.shared.json", | ||
"include": [ | ||
"../../**/*.ts", | ||
"../../**/*.d.ts" | ||
] | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
/// pthread_t in C | ||
export type pthread_ptr = number; |
Uh oh!
There was an error while loading. Please reload this page.