Skip to content

[browser] cleanup before memory snapshot #83082

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

Merged
merged 3 commits into from
Mar 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 6 additions & 34 deletions src/mono/wasm/runtime/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,35 +46,8 @@ const skipInstantiateByAssetTypes: {
"dotnetwasm": true,
};

export function get_preferred_icu_asset(): string | null {
if (!runtimeHelpers.config.assets)
return null;

// By setting <WasmIcuDataFileName> user can define what ICU source file they want to load.
// There is no need to check application's culture when <WasmIcuDataFileName> is set.
// If it was not set, then we have 3 "icu" assets in config and we should choose
// only one for loading, the one that matches the application's locale.
const icuAssets = runtimeHelpers.config.assets.filter(a => a["behavior"] == "icu");
if (icuAssets.length === 1)
return icuAssets[0].name;

// reads the browsers locale / the OS's locale
const preferredCulture = ENVIRONMENT_IS_WEB ? navigator.language : Intl.DateTimeFormat().resolvedOptions().locale;
const prefix = preferredCulture.split("-")[0];
const CJK = "icudt_CJK.dat";
const EFIGS = "icudt_EFIGS.dat";
const OTHERS = "icudt_no_CJK.dat";

// not all "fr-*", "it-*", "de-*", "es-*" are in EFIGS, only the one that is mostly used
if (prefix == "en" || ["fr", "fr-FR", "it", "it-IT", "de", "de-DE", "es", "es-ES"].includes(preferredCulture))
return EFIGS;
if (["zh", "ko", "ja"].includes(prefix))
return CJK;
return OTHERS;
}

export function shouldLoadIcuAsset(asset: AssetEntryInternal, preferredIcuAsset: string | null): boolean {
return !(asset.behavior == "icu" && asset.name != preferredIcuAsset);
export function shouldLoadIcuAsset(asset: AssetEntryInternal): boolean {
return !(asset.behavior == "icu" && asset.name != runtimeHelpers.preferredIcuAsset);
}

export function resolve_asset_path(behavior: AssetBehaviours) {
Expand All @@ -86,7 +59,6 @@ export function resolve_asset_path(behavior: AssetBehaviours) {
return asset;
}
export async function mono_download_assets(): Promise<void> {
const preferredIcuAsset = get_preferred_icu_asset();
if (runtimeHelpers.diagnosticTracing) console.debug("MONO_WASM: mono_download_assets");
runtimeHelpers.maxParallelDownloads = runtimeHelpers.config.maxParallelDownloads || runtimeHelpers.maxParallelDownloads;
runtimeHelpers.enableDownloadRetry = runtimeHelpers.config.enableDownloadRetry || runtimeHelpers.enableDownloadRetry;
Expand All @@ -101,10 +73,10 @@ export async function mono_download_assets(): Promise<void> {
mono_assert(!asset.resolvedUrl || typeof asset.resolvedUrl === "string", "asset resolvedUrl could be string");
mono_assert(!asset.hash || typeof asset.hash === "string", "asset resolvedUrl could be string");
mono_assert(!asset.pendingDownload || typeof asset.pendingDownload === "object", "asset pendingDownload could be object");
if (!skipInstantiateByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset, preferredIcuAsset)) {
if (!skipInstantiateByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset)) {
expected_instantiated_assets_count++;
}
if (!skipDownloadsByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset, preferredIcuAsset)) {
if (!skipDownloadsByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset)) {
expected_downloaded_assets_count++;
promises_of_assets.push(start_asset_download(asset));
}
Expand Down Expand Up @@ -132,10 +104,10 @@ export async function mono_download_assets(): Promise<void> {
const headersOnly = skipBufferByAssetTypes[asset.behavior];
if (!headersOnly) {
mono_assert(asset.isOptional, "Expected asset to have the downloaded buffer");
if (!skipDownloadsByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset, preferredIcuAsset)) {
if (!skipDownloadsByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset)) {
expected_downloaded_assets_count--;
}
if (!skipInstantiateByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset, preferredIcuAsset)) {
if (!skipInstantiateByAssetTypes[asset.behavior] && shouldLoadIcuAsset(asset)) {
expected_instantiated_assets_count--;
}
} else {
Expand Down
4 changes: 0 additions & 4 deletions src/mono/wasm/runtime/dotnet.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,10 @@ declare interface EmscriptenModule {
FS_createPath(parent: string, path: string, canRead?: boolean, canWrite?: boolean): string;
FS_createDataFile(parent: string, name: string, data: TypedArray, canRead: boolean, canWrite: boolean, canOwn?: boolean): string;
FS_readFile(filename: string, opts: any): any;
removeRunDependency(id: string): void;
addRunDependency(id: string): void;
addFunction(fn: Function, signature: string): number;
getWasmTableEntry(index: number): any;
stackSave(): VoidPtr;
stackRestore(stack: VoidPtr): void;
stackAlloc(size: number): VoidPtr;
ready: Promise<unknown>;
instantiateWasm?: InstantiateWasmCallBack;
preInit?: (() => any)[] | (() => any);
preRun?: (() => any)[] | (() => any);
Expand Down
4 changes: 2 additions & 2 deletions src/mono/wasm/runtime/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import BuildConfiguration from "consts:configuration";
import WasmEnableLegacyJsInterop from "consts:WasmEnableLegacyJsInterop";

import { ENVIRONMENT_IS_PTHREAD, exportedRuntimeAPI, moduleExports, set_emscripten_entrypoint, set_imports_exports } from "./imports";
import { DotnetModule, is_nullish, EarlyImports, EarlyExports, EarlyReplacements, RuntimeAPI, CreateDotnetRuntimeType } from "./types";
import { is_nullish, EarlyImports, EarlyExports, EarlyReplacements, RuntimeAPI, CreateDotnetRuntimeType, DotnetModuleInternal } from "./types";
import { configure_emscripten_startup, mono_wasm_pthread_worker_init } from "./startup";

import { create_weak_ref } from "./weak-ref";
Expand Down Expand Up @@ -37,7 +37,7 @@ function initializeImportsAndExports(
replacements: EarlyReplacements,
callbackAPI: any
): RuntimeAPI {
const module = exports.module as DotnetModule;
const module = exports.module as DotnetModuleInternal;
const globalThisAny = globalThis as any;

// we want to have same instance of MONO, BINDING and Module in dotnet iife
Expand Down
26 changes: 26 additions & 0 deletions src/mono/wasm/runtime/icu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,29 @@ export function mono_wasm_globalization_init(): void {
}
}

export function get_preferred_icu_asset(): string | null {
if (!runtimeHelpers.config.assets)
return null;

// By setting <WasmIcuDataFileName> user can define what ICU source file they want to load.
// There is no need to check application's culture when <WasmIcuDataFileName> is set.
// If it was not set, then we have 3 "icu" assets in config and we should choose
// only one for loading, the one that matches the application's locale.
const icuAssets = runtimeHelpers.config.assets.filter(a => a["behavior"] == "icu");
if (icuAssets.length === 1)
return icuAssets[0].name;

// reads the browsers locale / the OS's locale
const preferredCulture = ENVIRONMENT_IS_WEB ? navigator.language : Intl.DateTimeFormat().resolvedOptions().locale;
const prefix = preferredCulture.split("-")[0];
const CJK = "icudt_CJK.dat";
const EFIGS = "icudt_EFIGS.dat";
const OTHERS = "icudt_no_CJK.dat";

// not all "fr-*", "it-*", "de-*", "es-*" are in EFIGS, only the one that is mostly used
if (prefix == "en" || ["fr", "fr-FR", "it", "it-IT", "de", "de-DE", "es", "es-ES"].includes(preferredCulture))
return EFIGS;
if (["zh", "ko", "ja"].includes(prefix))
return CJK;
return OTHERS;
}
4 changes: 2 additions & 2 deletions src/mono/wasm/runtime/imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
/// <reference path="./types/node.d.ts" />

import type { CreateDotnetRuntimeType, DotnetModule, RuntimeAPI, EarlyExports, EarlyImports, ModuleAPI, RuntimeHelpers } from "./types";
import type { EmscriptenModule } from "./types/emscripten";
import type { EmscriptenModule, EmscriptenModuleInternal } from "./types/emscripten";

// these are our public API (except internal)
export let Module: EmscriptenModule & DotnetModule;
export let Module: EmscriptenModule & DotnetModule & EmscriptenModuleInternal;
export let INTERNAL: any;
export let IMPORTS: any;

Expand Down
31 changes: 15 additions & 16 deletions src/mono/wasm/runtime/managed-exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@

import { GCHandle, MarshalerToCs, MarshalerToJs, MonoMethod, mono_assert } from "./types";
import cwraps from "./cwraps";
import { Module, runtimeHelpers, ENVIRONMENT_IS_PTHREAD } from "./imports";
import { runtimeHelpers, ENVIRONMENT_IS_PTHREAD, Module } from "./imports";
import { alloc_stack_frame, get_arg, get_arg_gc_handle, MarshalerType, set_arg_type, set_gc_handle } from "./marshal";
import { invoke_method_and_handle_exception } from "./invoke-cs";
import { marshal_array_to_cs_impl, marshal_exception_to_cs, marshal_intptr_to_cs } from "./marshal-to-cs";
import { marshal_int32_to_js, marshal_string_to_js, marshal_task_to_js } from "./marshal-to-js";

export function init_managed_exports(): void {
const anyModule = Module as any;
const exports_fqn_asm = "System.Runtime.InteropServices.JavaScript";
runtimeHelpers.runtime_interop_module = cwraps.mono_wasm_assembly_load(exports_fqn_asm);
if (!runtimeHelpers.runtime_interop_module)
Expand Down Expand Up @@ -38,7 +37,7 @@ export function init_managed_exports(): void {
mono_assert(get_managed_stack_trace_method, "Can't find GetManagedStackTrace method");

runtimeHelpers.javaScriptExports.call_entry_point = (entry_point: MonoMethod, program_args?: string[]) => {
const sp = anyModule.stackSave();
const sp = Module.stackSave();
try {
const args = alloc_stack_frame(4);
const res = get_arg(args, 1);
Expand All @@ -56,35 +55,35 @@ export function init_managed_exports(): void {
}
return promise;
} finally {
anyModule.stackRestore(sp);
Module.stackRestore(sp);
}
};
runtimeHelpers.javaScriptExports.release_js_owned_object_by_gc_handle = (gc_handle: GCHandle) => {
mono_assert(gc_handle, "Must be valid gc_handle");
const sp = anyModule.stackSave();
const sp = Module.stackSave();
try {
const args = alloc_stack_frame(3);
const arg1 = get_arg(args, 2);
set_arg_type(arg1, MarshalerType.Object);
set_gc_handle(arg1, gc_handle);
invoke_method_and_handle_exception(release_js_owned_object_by_gc_handle_method, args);
} finally {
anyModule.stackRestore(sp);
Module.stackRestore(sp);
}
};
runtimeHelpers.javaScriptExports.create_task_callback = () => {
const sp = anyModule.stackSave();
const sp = Module.stackSave();
try {
const args = alloc_stack_frame(2);
invoke_method_and_handle_exception(create_task_callback_method, args);
const res = get_arg(args, 1);
return get_arg_gc_handle(res);
} finally {
anyModule.stackRestore(sp);
Module.stackRestore(sp);
}
};
runtimeHelpers.javaScriptExports.complete_task = (holder_gc_handle: GCHandle, error?: any, data?: any, res_converter?: MarshalerToCs) => {
const sp = anyModule.stackSave();
const sp = Module.stackSave();
try {
const args = alloc_stack_frame(5);
const arg1 = get_arg(args, 2);
Expand All @@ -101,11 +100,11 @@ export function init_managed_exports(): void {
}
invoke_method_and_handle_exception(complete_task_method, args);
} finally {
anyModule.stackRestore(sp);
Module.stackRestore(sp);
}
};
runtimeHelpers.javaScriptExports.call_delegate = (callback_gc_handle: GCHandle, arg1_js: any, arg2_js: any, arg3_js: any, res_converter?: MarshalerToJs, arg1_converter?: MarshalerToCs, arg2_converter?: MarshalerToCs, arg3_converter?: MarshalerToCs) => {
const sp = anyModule.stackSave();
const sp = Module.stackSave();
try {
const args = alloc_stack_frame(6);

Expand Down Expand Up @@ -134,11 +133,11 @@ export function init_managed_exports(): void {
return res_converter(res);
}
} finally {
anyModule.stackRestore(sp);
Module.stackRestore(sp);
}
};
runtimeHelpers.javaScriptExports.get_managed_stack_trace = (exception_gc_handle: GCHandle) => {
const sp = anyModule.stackSave();
const sp = Module.stackSave();
try {
const args = alloc_stack_frame(3);

Expand All @@ -150,18 +149,18 @@ export function init_managed_exports(): void {
const res = get_arg(args, 1);
return marshal_string_to_js(res);
} finally {
anyModule.stackRestore(sp);
Module.stackRestore(sp);
}
};

if (install_sync_context) {
runtimeHelpers.javaScriptExports.install_synchronization_context = () => {
const sp = anyModule.stackSave();
const sp = Module.stackSave();
try {
const args = alloc_stack_frame(2);
invoke_method_and_handle_exception(install_sync_context, args);
} finally {
anyModule.stackRestore(sp);
Module.stackRestore(sp);
}
};

Expand Down
3 changes: 1 addition & 2 deletions src/mono/wasm/runtime/marshal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ export const JSMarshalerTypeSize = 32;
export const JSMarshalerSignatureHeaderSize = 4 + 4; // without Exception and Result

export function alloc_stack_frame(size: number): JSMarshalerArguments {
const anyModule = Module as any;
const args = anyModule.stackAlloc(JavaScriptMarshalerArgSize * size);
const args = Module.stackAlloc(JavaScriptMarshalerArgSize * size) as any;
mono_assert(args && (<any>args) % 8 == 0, "Arg alignment");
const exc = get_arg(args, 0);
set_arg_type(exc, MarshalerType.None);
Expand Down
13 changes: 6 additions & 7 deletions src/mono/wasm/runtime/polyfills.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ let node_fs: any | undefined = undefined;
let node_url: any | undefined = undefined;

export function init_polyfills(replacements: EarlyReplacements): void {
const anyModule = Module as any;

// performance.now() is used by emscripten and doesn't work in JSC
if (typeof globalThis.performance === "undefined") {
Expand Down Expand Up @@ -123,7 +122,7 @@ export function init_polyfills(replacements: EarlyReplacements): void {
}

// require replacement
const imports = anyModule.imports = (Module.imports || {}) as DotnetModuleConfigImports;
const imports = Module.imports = (Module.imports || {}) as DotnetModuleConfigImports;
const requireWrapper = (wrappedRequire: Function) => (name: string) => {
const resolved = (<any>Module.imports)[name];
if (resolved) {
Expand All @@ -146,20 +145,20 @@ export function init_polyfills(replacements: EarlyReplacements): void {

// script location
runtimeHelpers.scriptDirectory = replacements.scriptDirectory = detectScriptDirectory(replacements);
anyModule.mainScriptUrlOrBlob = replacements.scriptUrl;// this is needed by worker threads
Module.mainScriptUrlOrBlob = replacements.scriptUrl;// this is needed by worker threads
if (BuildConfiguration === "Debug") {
console.debug(`MONO_WASM: starting script ${replacements.scriptUrl}`);
console.debug(`MONO_WASM: starting in ${runtimeHelpers.scriptDirectory}`);
}
if (anyModule.__locateFile === anyModule.locateFile) {
if (Module.__locateFile === Module.locateFile) {
// above it's our early version from dotnet.es6.pre.js, we could replace it with better
anyModule.locateFile = runtimeHelpers.locateFile = (path) => {
Module.locateFile = runtimeHelpers.locateFile = (path) => {
if (isPathAbsolute(path)) return path;
return runtimeHelpers.scriptDirectory + path;
};
} else {
// we use what was given to us
runtimeHelpers.locateFile = anyModule.locateFile;
runtimeHelpers.locateFile = Module.locateFile!;
}

// prefer fetch_like over global fetch for assets
Expand All @@ -177,7 +176,7 @@ export function init_polyfills(replacements: EarlyReplacements): void {

// memory
const originalUpdateGlobalBufferAndViews = replacements.updateGlobalBufferAndViews;
replacements.updateGlobalBufferAndViews = (buffer: ArrayBufferLike) => {
runtimeHelpers.updateGlobalBufferAndViews = replacements.updateGlobalBufferAndViews = (buffer: ArrayBufferLike) => {
originalUpdateGlobalBufferAndViews(buffer);
afterUpdateGlobalBufferAndViews(buffer);
};
Expand Down
Loading