Skip to content

Commit 3386b86

Browse files
authored
[browser] make cwraps more conditional (#87274)
1 parent 9e93f42 commit 3386b86

File tree

17 files changed

+146
-92
lines changed

17 files changed

+146
-92
lines changed

src/mono/sample/wasm/browser-eventpipe/Wasm.Browser.EventPipe.Sample.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
<ItemGroup>
1616
<WasmExtraFilesToDeploy Include="index.html" />
17+
<WasmExtraFilesToDeploy Include="main.js" />
1718
<WasmExtraFilesToDeploy Include="mock.js" Condition="'$(MonoDiagnosticsMock)' == 'true'"/>
1819
<!-- this option requires running dotnet-dsrouter and a real dotnet-trace client -->
1920
<WasmExtraConfig Condition="'$(MonoDiagnosticsMock)' != 'true'" Include="environmentVariables" Value='

src/mono/wasm/build/WasmApp.Native.targets

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,8 @@
266266
<EmscriptenEnvVars Include="EM_FROZEN_CACHE=True" />
267267
<EmscriptenEnvVars Include="DISABLE_LEGACY_JS_INTEROP=1" Condition="'$(WasmEnableLegacyJsInterop)' == 'false'" />
268268
<EmscriptenEnvVars Include="DISABLE_LEGACY_JS_INTEROP=0" Condition="'$(WasmEnableLegacyJsInterop)' != 'false'" />
269+
<EmscriptenEnvVars Include="ENABLE_AOT_PROFILER=$([System.Convert]::ToInt32($(WasmProfilers.Contains('aot'))))" />
270+
<EmscriptenEnvVars Include="ENABLE_BROWSER_PROFILER=$([System.Convert]::ToInt32($(WasmProfilers.Contains('browser'))))" />
269271
</ItemGroup>
270272

271273
<ItemGroup Condition="'$(WasmAllowUndefinedSymbols)' == 'true'">

src/mono/wasm/runtime/cwraps.ts

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
import MonoWasmThreads from "consts:monoWasmThreads";
5+
import WasmEnableLegacyJsInterop from "consts:wasmEnableLegacyJsInterop";
6+
47
import type {
58
MonoArray, MonoAssembly, MonoClass,
69
MonoMethod, MonoObject,
710
MonoType, MonoObjectRef, MonoStringRef, JSMarshalerArguments
811
} from "./types/internal";
912
import type { VoidPtr, CharPtrPtr, Int32Ptr, CharPtr, ManagedPointer } from "./types/emscripten";
10-
import WasmEnableLegacyJsInterop from "consts:WasmEnableLegacyJsInterop";
11-
import { disableLegacyJsInterop, Module } from "./globals";
13+
import { linkerDisableLegacyJsInterop, linkerEnableAotProfiler, linkerEnableBrowserProfiler, Module } from "./globals";
1214
import { mono_log_error } from "./logging";
1315

14-
type SigLine = [lazy: boolean, name: string, returnType: string | null, argTypes?: string[], opts?: any];
16+
type SigLine = [lazyOrSkip: boolean | (() => boolean), name: string, returnType: string | null, argTypes?: string[], opts?: any];
1517

1618
const legacy_interop_cwraps: SigLine[] = WasmEnableLegacyJsInterop ? [
1719
[true, "mono_wasm_array_get_ref", "void", ["number", "number", "number"]],
@@ -29,6 +31,17 @@ const legacy_interop_cwraps: SigLine[] = WasmEnableLegacyJsInterop ? [
2931
[true, "mono_wasm_array_length_ref", "number", ["number"]],
3032
] : [];
3133

34+
const diagnostics_cwraps: SigLine[] = MonoWasmThreads ? [
35+
// MONO.diagnostics
36+
[true, "mono_wasm_event_pipe_enable", "bool", ["string", "number", "number", "string", "bool", "number"]],
37+
[true, "mono_wasm_event_pipe_session_start_streaming", "bool", ["number"]],
38+
[true, "mono_wasm_event_pipe_session_disable", "bool", ["number"]],
39+
[true, "mono_wasm_diagnostic_server_create_thread", "bool", ["string", "number"]],
40+
[true, "mono_wasm_diagnostic_server_thread_attach_to_runtime", "void", []],
41+
[true, "mono_wasm_diagnostic_server_post_resume_runtime", "void", []],
42+
[true, "mono_wasm_diagnostic_server_create_stream", "number", []],
43+
] : [];
44+
3245
// when the method is assigned/cached at usage, instead of being invoked directly from cwraps, it can't be marked lazy, because it would be re-bound on each call
3346
const fn_signatures: SigLine[] = [
3447
// MONO
@@ -61,22 +74,14 @@ const fn_signatures: SigLine[] = [
6174
[true, "mono_wasm_assembly_get_entry_point", "number", ["number", "number"]],
6275
[true, "mono_wasm_class_get_type", "number", ["number"]],
6376

64-
// MONO.diagnostics
65-
[true, "mono_wasm_event_pipe_enable", "bool", ["string", "number", "number", "string", "bool", "number"]],
66-
[true, "mono_wasm_event_pipe_session_start_streaming", "bool", ["number"]],
67-
[true, "mono_wasm_event_pipe_session_disable", "bool", ["number"]],
68-
[true, "mono_wasm_diagnostic_server_create_thread", "bool", ["string", "number"]],
69-
[true, "mono_wasm_diagnostic_server_thread_attach_to_runtime", "void", []],
70-
[true, "mono_wasm_diagnostic_server_post_resume_runtime", "void", []],
71-
[true, "mono_wasm_diagnostic_server_create_stream", "number", []],
72-
7377
//INTERNAL
7478
[false, "mono_wasm_exit", "void", ["number"]],
7579
[true, "mono_wasm_getenv", "number", ["string"]],
7680
[true, "mono_wasm_set_main_args", "void", ["number", "number"]],
7781
[false, "mono_wasm_enable_on_demand_gc", "void", ["number"]],
7882
// These two need to be lazy because they may be missing
79-
[true, "mono_wasm_profiler_init_aot", "void", ["string"]],
83+
[() => !linkerEnableAotProfiler, "mono_wasm_profiler_init_aot", "void", ["string"]],
84+
[() => !linkerEnableBrowserProfiler, "mono_wasm_profiler_init_aot", "void", ["string"]],
8085
[true, "mono_wasm_profiler_init_browser", "void", ["number"]],
8186
[false, "mono_wasm_exec_regression", "number", ["number", "string"]],
8287
[false, "mono_wasm_invoke_method_bound", "number", ["number", "number", "number"]],
@@ -132,6 +137,7 @@ const fn_signatures: SigLine[] = [
132137
[true, "mono_jiterp_get_opcode_info", "number", ["number", "number"]],
133138
[true, "mono_wasm_is_zero_page_reserved", "number", []],
134139
[true, "mono_jiterp_is_special_interface", "number", ["number"]],
140+
...diagnostics_cwraps,
135141
...legacy_interop_cwraps
136142
];
137143

@@ -152,6 +158,22 @@ export interface t_LegacyCwraps {
152158
mono_wasm_array_length_ref(array: MonoObjectRef): number;
153159
}
154160

161+
export interface t_DiagnosticsCwraps {
162+
// MONO.diagnostics
163+
mono_wasm_event_pipe_enable(outputPath: string | null, stream: VoidPtr, bufferSizeInMB: number, providers: string, rundownRequested: boolean, outSessionId: VoidPtr): boolean;
164+
mono_wasm_event_pipe_session_start_streaming(sessionId: number): boolean;
165+
mono_wasm_event_pipe_session_disable(sessionId: number): boolean;
166+
mono_wasm_diagnostic_server_create_thread(websocketURL: string, threadIdOutPtr: VoidPtr): boolean;
167+
mono_wasm_diagnostic_server_thread_attach_to_runtime(): void;
168+
mono_wasm_diagnostic_server_post_resume_runtime(): void;
169+
mono_wasm_diagnostic_server_create_stream(): VoidPtr;
170+
}
171+
172+
export interface t_ProfilerCwraps {
173+
mono_wasm_profiler_init_aot(desc: string): void;
174+
mono_wasm_profiler_init_browser(desc: string): void;
175+
}
176+
155177
export interface t_Cwraps {
156178
// MONO
157179
mono_wasm_register_root(start: VoidPtr, size: number, name: string): number;
@@ -182,23 +204,11 @@ export interface t_Cwraps {
182204
mono_wasm_assembly_get_entry_point(assembly: MonoAssembly, idx: number): MonoMethod;
183205
mono_wasm_intern_string_ref(strRef: MonoStringRef): void;
184206

185-
186-
// MONO.diagnostics
187-
mono_wasm_event_pipe_enable(outputPath: string | null, stream: VoidPtr, bufferSizeInMB: number, providers: string, rundownRequested: boolean, outSessionId: VoidPtr): boolean;
188-
mono_wasm_event_pipe_session_start_streaming(sessionId: number): boolean;
189-
mono_wasm_event_pipe_session_disable(sessionId: number): boolean;
190-
mono_wasm_diagnostic_server_create_thread(websocketURL: string, threadIdOutPtr: VoidPtr): boolean;
191-
mono_wasm_diagnostic_server_thread_attach_to_runtime(): void;
192-
mono_wasm_diagnostic_server_post_resume_runtime(): void;
193-
mono_wasm_diagnostic_server_create_stream(): VoidPtr;
194-
195207
//INTERNAL
196208
mono_wasm_exit(exit_code: number): number;
197209
mono_wasm_getenv(name: string): CharPtr;
198210
mono_wasm_enable_on_demand_gc(enable: number): void;
199211
mono_wasm_set_main_args(argc: number, argv: VoidPtr): void;
200-
mono_wasm_profiler_init_aot(desc: string): void;
201-
mono_wasm_profiler_init_browser(desc: string): void;
202212
mono_wasm_exec_regression(verbose_level: number, image: string): number;
203213
mono_wasm_invoke_method_bound(method: MonoMethod, args: JSMarshalerArguments, fail: MonoStringRef): number;
204214
mono_wasm_write_managed_pointer_unsafe(destination: VoidPtr | MonoObjectRef, pointer: ManagedPointer): void;
@@ -265,6 +275,8 @@ const wrapped_c_functions: t_Cwraps = <any>{};
265275

266276
export default wrapped_c_functions;
267277
export const legacy_c_functions: t_LegacyCwraps & t_Cwraps = wrapped_c_functions as any;
278+
export const diagnostics_c_functions: t_DiagnosticsCwraps & t_Cwraps = wrapped_c_functions as any;
279+
export const profiler_c_functions: t_ProfilerCwraps & t_Cwraps = wrapped_c_functions as any;
268280

269281
// see src/mono/wasm/driver.c I52_ERROR_xxx
270282
export const enum I52Error {
@@ -275,7 +287,7 @@ export const enum I52Error {
275287

276288
const fastCwrapTypes = ["void", "number", null];
277289

278-
function cwrap(name: string, returnType: string | null, argTypes: string[] | undefined, opts: any, throwOnError: boolean): Function {
290+
function cwrap(name: string, returnType: string | null, argTypes: string[] | undefined, opts: any): Function {
279291
// Attempt to bypass emscripten's generated wrapper if it is safe to do so
280292
let fce =
281293
// Special cwrap options disable the fast path
@@ -301,29 +313,29 @@ function cwrap(name: string, returnType: string | null, argTypes: string[] | und
301313

302314
if (typeof (fce) !== "function") {
303315
const msg = `cwrap ${name} not found or not a function`;
304-
if (throwOnError)
305-
throw new Error(msg);
306-
else
307-
mono_log_error("" + msg);
316+
throw new Error(msg);
308317
}
309318
return fce;
310319
}
311320

312321
export function init_c_exports(): void {
313-
const lfns = WasmEnableLegacyJsInterop && !disableLegacyJsInterop ? legacy_interop_cwraps : [];
322+
const lfns = WasmEnableLegacyJsInterop && !linkerDisableLegacyJsInterop ? legacy_interop_cwraps : [];
314323
const fns = [...fn_signatures, ...lfns];
315324
for (const sig of fns) {
316325
const wf: any = wrapped_c_functions;
317-
const [lazy, name, returnType, argTypes, opts] = sig;
318-
if (lazy) {
326+
const [lazyOrSkip, name, returnType, argTypes, opts] = sig;
327+
const maybeSkip = typeof lazyOrSkip === "function";
328+
if (lazyOrSkip === true || maybeSkip) {
319329
// lazy init on first run
320330
wf[name] = function (...args: any[]) {
321-
const fce = cwrap(name, returnType, argTypes, opts, true);
331+
const isNotSkipped = !maybeSkip || !lazyOrSkip();
332+
mono_assert(isNotSkipped, () => `cwrap ${name} should not be called when binding was skipped`);
333+
const fce = cwrap(name, returnType, argTypes, opts);
322334
wf[name] = fce;
323335
return fce(...args);
324336
};
325337
} else {
326-
const fce = cwrap(name, returnType, argTypes, opts, false);
338+
const fce = cwrap(name, returnType, argTypes, opts);
327339
wf[name] = fce;
328340
}
329341
}

src/mono/wasm/runtime/diagnostics/browser/controller.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
import cwraps from "../../cwraps";
4+
import MonoWasmThreads from "consts:monoWasmThreads";
5+
6+
import { diagnostics_c_functions as cwraps } from "../../cwraps";
57
import { INTERNAL } from "../../globals";
68
import { mono_log_info, mono_log_debug, mono_log_warn } from "../../logging";
79
import { withStackAlloc, getI32 } from "../../memory";
@@ -52,6 +54,7 @@ export function getController(): ServerController {
5254
}
5355

5456
export async function startDiagnosticServer(websocket_url: string): Promise<ServerController | null> {
57+
mono_assert(MonoWasmThreads, "The diagnostic server requires threads to be enabled during build time.");
5558
const sizeOfPthreadT = 4;
5659
mono_log_info(`starting the diagnostic server url: ${websocket_url}`);
5760
const result: number | undefined = withStackAlloc(sizeOfPthreadT, (pthreadIdPtr) => {

src/mono/wasm/runtime/diagnostics/index.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -41,23 +41,22 @@ export async function mono_wasm_init_diagnostics(): Promise<void> {
4141
if (!MonoWasmThreads) {
4242
mono_log_warn("ignoring diagnostics options because this runtime does not support diagnostics");
4343
return;
44-
} else {
45-
const options = diagnostic_options_from_environment();
46-
if (!options)
47-
return;
48-
diagnosticsInitialized = true;
49-
if (!is_nullish(options?.server)) {
50-
if (options.server.connectUrl === undefined || typeof (options.server.connectUrl) !== "string") {
51-
throw new Error("server.connectUrl must be a string");
52-
}
53-
const url = options.server.connectUrl;
54-
const suspend = boolsyOption(options.server.suspend);
55-
const controller = await startDiagnosticServer(url);
56-
if (controller) {
57-
diagnosticsServerEnabled = true;
58-
if (suspend) {
59-
suspendOnStartup = true;
60-
}
44+
}
45+
const options = diagnostic_options_from_environment();
46+
if (!options)
47+
return;
48+
diagnosticsInitialized = true;
49+
if (!is_nullish(options?.server)) {
50+
if (options.server.connectUrl === undefined || typeof (options.server.connectUrl) !== "string") {
51+
throw new Error("server.connectUrl must be a string");
52+
}
53+
const url = options.server.connectUrl;
54+
const suspend = boolsyOption(options.server.suspend);
55+
const controller = await startDiagnosticServer(url);
56+
if (controller) {
57+
diagnosticsServerEnabled = true;
58+
if (suspend) {
59+
suspendOnStartup = true;
6160
}
6261
}
6362
}
@@ -144,6 +143,7 @@ function diagnostic_options_from_ports_spec(val: string): DiagnosticOptions | nu
144143
}
145144

146145
export function mono_wasm_diagnostic_server_on_runtime_server_init(out_options: VoidPtr): void {
146+
mono_assert(MonoWasmThreads, "The diagnostic server requires threads to be enabled during build time.");
147147
if (diagnosticsServerEnabled) {
148148
/* called on the main thread when the runtime is sufficiently initialized */
149149
const controller = getController();

src/mono/wasm/runtime/diagnostics/server_pthread/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
/// <reference lib="webworker" />
5-
5+
import MonoWasmThreads from "consts:monoWasmThreads";
66
import monoDiagnosticsMock from "consts:monoDiagnosticsMock";
7+
78
import { PromiseAndController, assertNever } from "../../types/internal";
89
import { pthread_self } from "../../pthreads/worker";
910
import { createPromiseController } from "../../globals";
10-
import cwraps from "../../cwraps";
11+
import { diagnostics_c_functions as cwraps } from "../../cwraps";
1112
import { EventPipeSessionIDImpl } from "../shared/types";
1213
import { CharPtr } from "../../types/emscripten";
1314
import {
@@ -284,6 +285,7 @@ function parseProtocolCommand(data: ArrayBuffer | BinaryProtocolCommand): ParseC
284285

285286
/// Called by the runtime to initialize the diagnostic server workers
286287
export function mono_wasm_diagnostic_server_on_server_thread_created(websocketUrlPtr: CharPtr): void {
288+
mono_assert(MonoWasmThreads, "The diagnostic server requires threads to be enabled during build time.");
287289
const websocketUrl = utf8ToString(websocketUrlPtr);
288290
mono_log_debug(`mono_wasm_diagnostic_server_on_server_thread_created, url ${websocketUrl}`);
289291
let mock: PromiseAndController<Mock> | undefined = undefined;

src/mono/wasm/runtime/diagnostics/server_pthread/streaming-session.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
3-
import {
4-
EventPipeSessionIDImpl
5-
} from "../shared/types";
3+
import MonoWasmThreads from "consts:monoWasmThreads";
4+
5+
import { EventPipeSessionIDImpl } from "../shared/types";
66
import { EventPipeSocketConnection, takeOverSocket } from "./socket-connection";
77
import { StreamQueue, allocateQueue } from "./stream-queue";
88
import type { MockRemoteSocket } from "../mock";
99
import type { VoidPtr } from "../../types/emscripten";
10-
import cwraps from "../../cwraps";
10+
import { diagnostics_c_functions as cwraps } from "../../cwraps";
1111
import {
1212
EventPipeCommandCollectTracing2,
1313
EventPipeCollectTracingCommandProvider,
@@ -24,6 +24,7 @@ export class EventPipeStreamingSession {
2424
}
2525

2626
export async function makeEventPipeStreamingSession(ws: WebSocket | MockRemoteSocket, cmd: EventPipeCommandCollectTracing2): Promise<EventPipeStreamingSession> {
27+
mono_assert(MonoWasmThreads, "The diagnostic server requires threads to be enabled during build time.");
2728
// First, create the native IPC stream and get its queue.
2829
const ipcStreamAddr = cwraps.mono_wasm_diagnostic_server_create_stream(); // FIXME: this should be a wrapped in a JS object so we can free it when we're done.
2930
const queueAddr = getQueueAddrFromStreamAddr(ipcStreamAddr);

src/mono/wasm/runtime/diagnostics/shared/create-session.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import * as memory from "../../memory";
55
import { VoidPtr } from "../../types/emscripten";
6-
import cwraps from "../../cwraps";
6+
import { diagnostics_c_functions as cwraps } from "../../cwraps";
77
import type { EventPipeSessionIDImpl } from "./types";
88

99
const sizeOfInt32 = 4;

src/mono/wasm/runtime/es6/dotnet.es6.lib.js

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77

88
// because we can't pass custom define symbols to acorn optimizer, we use environment variables to pass other build options
99
const DISABLE_LEGACY_JS_INTEROP = process.env.DISABLE_LEGACY_JS_INTEROP === "1";
10+
const ENABLE_BROWSER_PROFILER = process.env.ENABLE_BROWSER_PROFILER === "1";
11+
const ENABLE_AOT_PROFILER = process.env.ENABLE_AOT_PROFILER === "1";
1012

11-
function setup(disableLegacyJsInterop) {
13+
function setup(linkerSetup) {
1214
const pthreadReplacements = {};
1315
const dotnet_replacements = {
1416
fetch: globalThis.fetch,
@@ -29,8 +31,8 @@ function setup(disableLegacyJsInterop) {
2931

3032
Module.__dotnet_runtime.passEmscriptenInternals({
3133
isPThread: ENVIRONMENT_IS_PTHREAD,
32-
disableLegacyJsInterop,
33-
quit_, ExitStatus
34+
quit_, ExitStatus,
35+
...linkerSetup
3436
});
3537
Module.__dotnet_runtime.initializeReplacements(dotnet_replacements);
3638

@@ -58,7 +60,11 @@ function setup(disableLegacyJsInterop) {
5860
}
5961

6062
const postset = `
61-
DOTNET.setup(${DISABLE_LEGACY_JS_INTEROP ? "true" : "false"});
63+
DOTNET.setup({ `+
64+
`linkerDisableLegacyJsInterop: ${DISABLE_LEGACY_JS_INTEROP ? "true" : "false"},` +
65+
`linkerEnableAotProfiler: ${ENABLE_AOT_PROFILER ? "true" : "false"}, ` +
66+
`linkerEnableBrowserProfiler: ${ENABLE_BROWSER_PROFILER ? "true" : "false"}` +
67+
`});
6268
`;
6369

6470
const DotnetSupportLib = {
@@ -131,6 +137,22 @@ linked_functions = [...linked_functions,
131137
"mono_wasm_install_js_worker_interop",
132138
"mono_wasm_uninstall_js_worker_interop",
133139
]
140+
141+
if (ENABLE_AOT_PROFILER) {
142+
linked_functions = [...linked_functions,
143+
"mono_wasm_invoke_js_with_args_ref",
144+
"mono_wasm_get_object_property_ref",
145+
"mono_wasm_set_object_property_ref",
146+
"mono_wasm_get_by_index_ref",
147+
"mono_wasm_set_by_index_ref",
148+
"mono_wasm_get_global_object_ref",
149+
"mono_wasm_create_cs_owned_object_ref",
150+
"mono_wasm_typed_array_to_array_ref",
151+
"mono_wasm_typed_array_from_ref",
152+
"mono_wasm_invoke_js_blazor",
153+
]
154+
}
155+
134156
#endif
135157
if (!DISABLE_LEGACY_JS_INTEROP) {
136158
linked_functions = [...linked_functions,

0 commit comments

Comments
 (0)