Skip to content
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

[browser][mt] Update memory views after growth, refactor string processing, fix SharedArrayBuffer detection #86664

Merged
merged 17 commits into from
May 28, 2023
Merged
Show file tree
Hide file tree
Changes from 5 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
3 changes: 2 additions & 1 deletion src/mono/wasm/runtime/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { endMeasure, MeasuredBlock, startMeasure } from "./profiler";
import { AssetEntryInternal } from "./types/internal";
import { AssetEntry } from "./types";
import { InstantiateWasmSuccessCallback, VoidPtr } from "./types/emscripten";
import { decodeUTF8 } from "./strings";

// this need to be run only after onRuntimeInitialized event, when the memory is ready
export function instantiate_asset(asset: AssetEntry, url: string, bytes: Uint8Array): void {
Expand Down Expand Up @@ -157,7 +158,7 @@ export function mono_wasm_load_data_archive(data: Uint8Array, prefix: string): b

let manifest;
try {
const manifestContent = Module.UTF8ArrayToString(data, 8, manifestSize);
const manifestContent = decodeUTF8(data, 8, manifestSize);
manifest = JSON.parse(manifestContent);
if (!(manifest instanceof Array))
return false;
Expand Down
9 changes: 7 additions & 2 deletions src/mono/wasm/runtime/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { toBase64StringImpl } from "./base64";
import cwraps from "./cwraps";
import { VoidPtr, CharPtr } from "./types/emscripten";
import { mono_log_warn } from "./logging";
import { updateGrowableHeapViews } from "./memory";
import { utf8ToString } from "./strings";
const commands_received: any = new Map<number, CommandResponse>();
commands_received.remove = function (key: number): CommandResponse { const value = this.get(key); this.delete(key); return value; };
let _call_function_res_cache: any = {};
Expand Down Expand Up @@ -39,11 +41,13 @@ export function mono_wasm_fire_debugger_agent_message_with_data_to_pause(base64S
}

export function mono_wasm_fire_debugger_agent_message_with_data(data: number, len: number): void {
updateGrowableHeapViews();
const base64String = toBase64StringImpl(new Uint8Array(Module.HEAPU8.buffer, data, len));
mono_wasm_fire_debugger_agent_message_with_data_to_pause(base64String);
}

export function mono_wasm_add_dbg_command_received(res_ok: boolean, id: number, buffer: number, buffer_len: number): void {
updateGrowableHeapViews();
const dbg_command = new Uint8Array(Module.HEAPU8.buffer, buffer, buffer_len);
const base64String = toBase64StringImpl(dbg_command);
const buffer_obj = {
Expand All @@ -59,6 +63,7 @@ export function mono_wasm_add_dbg_command_received(res_ok: boolean, id: number,
}

function mono_wasm_malloc_and_set_debug_buffer(command_parameters: string) {
updateGrowableHeapViews();
if (command_parameters.length > _debugger_buffer_len) {
if (_debugger_buffer)
Module._free(_debugger_buffer);
Expand Down Expand Up @@ -150,7 +155,7 @@ export function mono_wasm_debugger_attached(): void {

export function mono_wasm_set_entrypoint_breakpoint(assembly_name: CharPtr, entrypoint_method_token: number): void {
//keep these assignments, these values are used by BrowserDebugProxy
_assembly_name_str = Module.UTF8ToString(assembly_name).concat(".dll");
_assembly_name_str = utf8ToString(assembly_name).concat(".dll");
_entrypoint_method_token = entrypoint_method_token;
//keep this console.assert, otherwise optimization will remove the assignments
// eslint-disable-next-line no-console
Expand Down Expand Up @@ -341,7 +346,7 @@ export function mono_wasm_release_object(objectId: string): void {
}

export function mono_wasm_debugger_log(level: number, message_ptr: CharPtr): void {
const message = Module.UTF8ToString(message_ptr);
const message = utf8ToString(message_ptr);

if (INTERNAL["logging"] && typeof INTERNAL.logging["debugger"] === "function") {
INTERNAL.logging.debugger(level, message);
Expand Down
5 changes: 3 additions & 2 deletions src/mono/wasm/runtime/diagnostics/server_pthread/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import monoDiagnosticsMock from "consts:monoDiagnosticsMock";
import { PromiseAndController, assertNever } from "../../types/internal";
import { pthread_self } from "../../pthreads/worker";
import { Module, createPromiseController } from "../../globals";
import { createPromiseController } from "../../globals";
import cwraps from "../../cwraps";
import { EventPipeSessionIDImpl } from "../shared/types";
import { CharPtr } from "../../types/emscripten";
Expand Down Expand Up @@ -47,6 +47,7 @@ import {
createBinaryCommandOKReply,
} from "./ipc-protocol/serializer";
import { mono_log_error, mono_log_info, mono_log_debug, mono_log_warn } from "../../logging";
import { utf8ToString } from "../../strings";

function addOneShotProtocolCommandEventListener(src: EventTarget): Promise<ProtocolCommandEvent> {
return new Promise((resolve) => {
Expand Down Expand Up @@ -283,7 +284,7 @@ function parseProtocolCommand(data: ArrayBuffer | BinaryProtocolCommand): ParseC

/// Called by the runtime to initialize the diagnostic server workers
export function mono_wasm_diagnostic_server_on_server_thread_created(websocketUrlPtr: CharPtr): void {
const websocketUrl = Module.UTF8ToString(websocketUrlPtr);
const websocketUrl = utf8ToString(websocketUrlPtr);
mono_log_debug(`mono_wasm_diagnostic_server_on_server_thread_created, url ${websocketUrl}`);
let mock: PromiseAndController<Mock> | undefined = undefined;
if (monoDiagnosticsMock && websocketUrl.startsWith("mock:")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { VoidPtr } from "../../types/emscripten";
import { Module } from "../../globals";
import type { CommonSocket } from "./common-socket";
import { mono_log_debug, mono_log_warn } from "../../logging";
import { updateGrowableHeapViews } from "../../memory";
enum ListenerState {
Sending,
Closed,
Expand All @@ -21,6 +22,7 @@ class SocketGuts {
const buf = new ArrayBuffer(size);
const view = new Uint8Array(buf);
// Can we avoid this copy?
updateGrowableHeapViews();
view.set(new Uint8Array(Module.HEAPU8.buffer, data as unknown as number, size));
this.socket.send(buf);
}
Expand Down
1 change: 1 addition & 0 deletions src/mono/wasm/runtime/dotnet.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ declare interface EmscriptenModule {
getValue(ptr: number, type: string, noSafe?: number | boolean): number;
UTF8ToString(ptr: CharPtr, maxBytesToRead?: number): string;
UTF8ArrayToString(u8Array: Uint8Array, idx?: number, maxBytesToRead?: number): string;
stringToUTF8Array(str: string, heap: Uint8Array, outIdx: number, maxBytesToWrite: number): void;
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;
addFunction(fn: Function, signature: string): number;
Expand Down
17 changes: 9 additions & 8 deletions src/mono/wasm/runtime/hybrid-globalization/change-case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
// The .NET Foundation licenses this file to you under the MIT license.

import { Module } from "../globals";
import { setU16 } from "../memory";
import { updateGrowableHeapViews, setU16 } from "../memory";
import { mono_wasm_new_external_root } from "../roots";
import { conv_string_root } from "../strings";
import { MonoObject, MonoObjectRef, MonoString, MonoStringRef } from "../types/internal";
import { Int32Ptr } from "../types/emscripten";
import { wrap_error_root, wrap_no_error_root } from "../invoke-js";

export function mono_wasm_change_case_invariant(src: number, srcLength: number, dst: number, dstLength: number, toUpper: number, is_exception: Int32Ptr, ex_address: MonoObjectRef) : void{
export function mono_wasm_change_case_invariant(src: number, srcLength: number, dst: number, dstLength: number, toUpper: number, is_exception: Int32Ptr, ex_address: MonoObjectRef): void {
const exceptionRoot = mono_wasm_new_external_root<MonoObject>(ex_address);
try{
try {
const input = get_utf16_string(src, srcLength);
let result = toUpper ? input.toUpperCase() : input.toLowerCase();
// Unicode defines some codepoints which expand into multiple codepoints,
Expand All @@ -20,7 +20,7 @@ export function mono_wasm_change_case_invariant(src: number, srcLength: number,
result = input;

for (let i = 0; i < result.length; i++)
setU16(dst + i*2, result.charCodeAt(i));
setU16(dst + i * 2, result.charCodeAt(i));
wrap_no_error_root(is_exception, exceptionRoot);
}
catch (ex: any) {
Expand All @@ -31,10 +31,10 @@ export function mono_wasm_change_case_invariant(src: number, srcLength: number,
}
}

export function mono_wasm_change_case(culture: MonoStringRef, src: number, srcLength: number, dst: number, destLength: number, toUpper: number, is_exception: Int32Ptr, ex_address: MonoObjectRef) : void{
export function mono_wasm_change_case(culture: MonoStringRef, src: number, srcLength: number, dst: number, destLength: number, toUpper: number, is_exception: Int32Ptr, ex_address: MonoObjectRef): void {
const cultureRoot = mono_wasm_new_external_root<MonoString>(culture),
exceptionRoot = mono_wasm_new_external_root<MonoObject>(ex_address);
try{
try {
const cultureName = conv_string_root(cultureRoot);
if (!cultureName)
throw new Error("Cannot change case, the culture name is null.");
Expand All @@ -44,7 +44,7 @@ export function mono_wasm_change_case(culture: MonoStringRef, src: number, srcLe
result = input;

for (let i = 0; i < destLength; i++)
setU16(dst + i*2, result.charCodeAt(i));
setU16(dst + i * 2, result.charCodeAt(i));
wrap_no_error_root(is_exception, exceptionRoot);
}
catch (ex: any) {
Expand All @@ -56,7 +56,8 @@ export function mono_wasm_change_case(culture: MonoStringRef, src: number, srcLe
}
}

function get_utf16_string(ptr: number, length: number): string{
function get_utf16_string(ptr: number, length: number): string {
updateGrowableHeapViews();
const view = new Uint16Array(Module.HEAPU16.buffer, ptr, length);
let string = "";
for (let i = 0; i < length; i++)
Expand Down
3 changes: 2 additions & 1 deletion src/mono/wasm/runtime/jiterpreter-interp-entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
JiterpreterOptions, getMemberOffset, JiterpMember
} from "./jiterpreter-support";
import { mono_log_error, mono_log_info } from "./logging";
import { utf8ToString } from "./strings";

// Controls miscellaneous diagnostic output.
const trace = 0;
Expand Down Expand Up @@ -166,7 +167,7 @@ export function mono_interp_jit_wasm_entry_trampoline(

const info = new TrampolineInfo(
imethod, method, argumentCount, pParamTypes,
unbox, hasThisReference, hasReturnValue, Module.UTF8ToString(<any>name),
unbox, hasThisReference, hasReturnValue, utf8ToString(<any>name),
defaultImplementation
);
if (!fnTable)
Expand Down
3 changes: 2 additions & 1 deletion src/mono/wasm/runtime/jiterpreter-jit-call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
} from "./jiterpreter-feature-detect";
import cwraps from "./cwraps";
import { mono_log_error, mono_log_info } from "./logging";
import { utf8ToString } from "./strings";

// Controls miscellaneous diagnostic output.
const trace = 0;
Expand Down Expand Up @@ -149,7 +150,7 @@ class TrampolineInfo {
if (useFullNames) {
const pMethodName = method ? cwraps.mono_wasm_method_get_full_name(method) : <any>0;
try {
suffix = Module.UTF8ToString(pMethodName);
suffix = utf8ToString(pMethodName);
} finally {
if (pMethodName)
Module._free(<any>pMethodName);
Expand Down
4 changes: 2 additions & 2 deletions src/mono/wasm/runtime/jiterpreter-opcodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

// Keep this file in sync with mintops.def. The order and values need to match exactly.

import { Module } from "./globals";
import cwraps from "./cwraps";
import { utf8ToString } from "./strings";

export const enum MintOpArgType {
MintOpNoArgs = 0,
Expand Down Expand Up @@ -56,7 +56,7 @@ export function getOpcodeName(opcode: number): string {
let result = opcodeNameCache[opcode];
if (typeof (result) !== "string") {
const pName = cwraps.mono_jiterp_get_opcode_info(opcode, OpcodeInfoType.Name);
opcodeNameCache[opcode] = result = Module.UTF8ToString(<any>pName);
opcodeNameCache[opcode] = result = utf8ToString(<any>pName);
}
return result;
}
Expand Down
10 changes: 9 additions & 1 deletion src/mono/wasm/runtime/jiterpreter-support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { WasmOpcode, WasmSimdOpcode } from "./jiterpreter-opcodes";
import { MintOpcode } from "./mintops";
import cwraps from "./cwraps";
import { mono_log_error, mono_log_info } from "./logging";
import { updateGrowableHeapViews } from "./memory";
import { utf8ToString } from "./strings";

export const maxFailures = 2,
maxMemsetSize = 64,
Expand Down Expand Up @@ -903,6 +905,7 @@ export class BlobBuilder {
constructor() {
this.capacity = 16 * 1024;
this.buffer = <any>Module._malloc(this.capacity);
updateGrowableHeapViews();
Module.HEAPU8.fill(0, this.buffer, this.buffer + this.capacity);
this.size = 0;
this.clear();
Expand All @@ -919,6 +922,7 @@ export class BlobBuilder {
throw new Error("Buffer full");

const result = this.size;
updateGrowableHeapViews();
Module.HEAPU8[this.buffer + (this.size++)] = value;
return result;
}
Expand Down Expand Up @@ -1008,12 +1012,14 @@ export class BlobBuilder {
if (typeof (count) !== "number")
count = this.size;

updateGrowableHeapViews();
Module.HEAPU8.copyWithin(destination.buffer + destination.size, this.buffer, this.buffer + count);
destination.size += count;
}

appendBytes(bytes: Uint8Array, count?: number) {
const result = this.size;
updateGrowableHeapViews();
if (bytes.buffer === Module.HEAPU8.buffer) {
if (typeof (count) !== "number")
count = bytes.length;
Expand Down Expand Up @@ -1067,6 +1073,7 @@ export class BlobBuilder {
}

getArrayView(fullCapacity?: boolean) {
updateGrowableHeapViews();
return new Uint8Array(Module.HEAPU8.buffer, this.buffer, fullCapacity ? this.capacity : this.size);
}
}
Expand Down Expand Up @@ -1483,6 +1490,7 @@ export function copyIntoScratchBuffer(src: NativePointer, size: number): NativeP
if (size > 64)
throw new Error("Scratch buffer size is 64");

updateGrowableHeapViews();
Module.HEAPU8.copyWithin(<any>scratchBuffer, <any>src, <any>src + size);
return scratchBuffer;
}
Expand Down Expand Up @@ -1882,7 +1890,7 @@ export function getOptions() {

function updateOptions() {
const pJson = cwraps.mono_jiterp_get_options_as_json();
const json = Module.UTF8ToString(<any>pJson);
const json = utf8ToString(<any>pJson);
Module._free(<any>pJson);
const blob = JSON.parse(json);

Expand Down
3 changes: 2 additions & 1 deletion src/mono/wasm/runtime/jiterpreter-trace-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Module } from "./globals";
import { NativePointer } from "./types/emscripten";
import {
getU16, getI16,
getU32_unaligned, getI32_unaligned, getF32_unaligned, getF64_unaligned,
getU32_unaligned, getI32_unaligned, getF32_unaligned, getF64_unaligned, updateGrowableHeapViews,
} from "./memory";
import {
WasmOpcode, WasmSimdOpcode,
Expand Down Expand Up @@ -3055,6 +3055,7 @@ function emit_simd(
case MintOpcode.MINT_SIMD_V128_LDC: {
if (builder.options.enableSimd && getIsWasmSimdSupported()) {
builder.local("pLocals");
updateGrowableHeapViews();
builder.v128_const(
Module.HEAPU8.slice(<any>ip + 4, <any>ip + 4 + sizeOfV128)
);
Expand Down
9 changes: 6 additions & 3 deletions src/mono/wasm/runtime/jiterpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { MonoMethod } from "./types/internal";
import { NativePointer } from "./types/emscripten";
import { Module, runtimeHelpers } from "./globals";
import {
updateGrowableHeapViews,
getU16, getU32_unaligned
} from "./memory";
import { WasmOpcode, getOpcodeName } from "./jiterpreter-opcodes";
Expand All @@ -22,6 +23,7 @@ import {
generateWasmBody
} from "./jiterpreter-trace-generator";
import { mono_log_error, mono_log_info, mono_log_warn } from "./logging";
import { utf8ToString } from "./strings";

// Controls miscellaneous diagnostic output.
export const trace = 0;
Expand Down Expand Up @@ -979,15 +981,16 @@ export function mono_interp_tier_prepare_jiterpreter(
let methodFullName: string | undefined;
if (mostRecentOptions.estimateHeat || (instrumentedMethodNames.length > 0) || useFullNames) {
const pMethodName = cwraps.mono_wasm_method_get_full_name(method);
methodFullName = Module.UTF8ToString(pMethodName);
methodFullName = utf8ToString(pMethodName);
Module._free(<any>pMethodName);
}
const methodName = Module.UTF8ToString(cwraps.mono_wasm_method_get_name(method));
const methodName = utf8ToString(cwraps.mono_wasm_method_get_name(method));
info.name = methodFullName || methodName;

const imethod = getU32_unaligned(getMemberOffset(JiterpMember.Imethod) + <any>frame);
const backBranchCount = getU32_unaligned(getMemberOffset(JiterpMember.BackwardBranchOffsetsCount) + imethod);
const pBackBranches = getU32_unaligned(getMemberOffset(JiterpMember.BackwardBranchOffsets) + imethod);
updateGrowableHeapViews();
let backwardBranchTable = backBranchCount
? new Uint16Array(Module.HEAPU8.buffer, pBackBranches, backBranchCount)
: null;
Expand Down Expand Up @@ -1086,7 +1089,7 @@ export function jiterpreter_dump_stats(b?: boolean, concise?: boolean) {
for (let i = 0, c = Math.min(summaryStatCount, targetPointers.length); i < c; i++) {
const targetMethod = Number(targetPointers[i]) | 0;
const pMethodName = cwraps.mono_wasm_method_get_full_name(<any>targetMethod);
const targetMethodName = Module.UTF8ToString(pMethodName);
const targetMethodName = utf8ToString(pMethodName);
const hitCount = callTargetCounts[<any>targetMethod];
Module._free(<any>pMethodName);
mono_log_info(`${targetMethodName} ${hitCount}`);
Expand Down
9 changes: 5 additions & 4 deletions src/mono/wasm/runtime/logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.

/* eslint-disable no-console */
import { INTERNAL, Module, runtimeHelpers } from "./globals";
import { INTERNAL, runtimeHelpers } from "./globals";
import { utf8ToString } from "./strings";
import { CharPtr, VoidPtr } from "./types/emscripten";

const prefix = "MONO_WASM: ";
Expand Down Expand Up @@ -91,11 +92,11 @@ export function mono_wasm_stringify_as_error_with_stack(err: Error | string): st
}

export function mono_wasm_trace_logger(log_domain_ptr: CharPtr, log_level_ptr: CharPtr, message_ptr: CharPtr, fatal: number, user_data: VoidPtr): void {
const origMessage = Module.UTF8ToString(message_ptr);
const origMessage = utf8ToString(message_ptr);
const isFatal = !!fatal;
const domain = Module.UTF8ToString(log_domain_ptr);
const domain = utf8ToString(log_domain_ptr);
const dataPtr = user_data;
const log_level = Module.UTF8ToString(log_level_ptr);
const log_level = utf8ToString(log_level_ptr);

const message = `[MONO] ${origMessage}`;

Expand Down
Loading