From 0235164228604cd4fa0fee0f3398fc1e62b3a2d5 Mon Sep 17 00:00:00 2001 From: Katelyn Gadd Date: Thu, 9 May 2024 21:19:36 -0700 Subject: [PATCH] [mono] miscellaneous AOT optimizations (#102039) * Lazily evaluate full name of methods when creating jiterpreter entry trampolines * Optimize out an unnecessary memset in do_jit_call * Migrate some hot ghashtables to simdhash --- .../runtime/jiterpreter-interp-entry.ts | 81 ++++++++++++------- src/mono/mono/metadata/class.c | 11 +-- src/mono/mono/metadata/image.c | 4 +- src/mono/mono/metadata/loader-internals.h | 4 +- src/mono/mono/metadata/loader.c | 18 ++--- src/mono/mono/metadata/memory-manager.c | 12 ++- src/mono/mono/metadata/metadata-internals.h | 4 +- src/mono/mono/metadata/metadata.c | 7 +- src/mono/mono/mini/CMakeLists.txt | 1 + src/mono/mono/mini/aot-runtime.c | 13 +-- src/mono/mono/mini/interp/interp.c | 9 ++- src/mono/mono/mini/interp/jiterpreter.h | 2 +- .../sample/wasm/simple-raytracer/Program.cs | 2 +- src/mono/sample/wasm/simple-raytracer/main.js | 5 +- 14 files changed, 106 insertions(+), 67 deletions(-) diff --git a/src/mono/browser/runtime/jiterpreter-interp-entry.ts b/src/mono/browser/runtime/jiterpreter-interp-entry.ts index b99917dd2bb0c..3863afb601e64 100644 --- a/src/mono/browser/runtime/jiterpreter-interp-entry.ts +++ b/src/mono/browser/runtime/jiterpreter-interp-entry.ts @@ -91,8 +91,8 @@ class TrampolineInfo { hasThisReference: boolean; unbox: boolean; hasReturnValue: boolean; - name: string; - traceName: string; + private name?: string; + private traceName?: string; defaultImplementation: number; result: number; @@ -100,8 +100,7 @@ class TrampolineInfo { constructor ( imethod: number, method: MonoMethod, argumentCount: number, pParamTypes: NativePointer, - unbox: boolean, hasThisReference: boolean, hasReturnValue: boolean, name: string, - defaultImplementation: number + unbox: boolean, hasThisReference: boolean, hasReturnValue: boolean, defaultImplementation: number ) { this.imethod = imethod; this.method = method; @@ -109,27 +108,49 @@ class TrampolineInfo { this.unbox = unbox; this.hasThisReference = hasThisReference; this.hasReturnValue = hasReturnValue; - this.name = name; this.paramTypes = new Array(argumentCount); for (let i = 0; i < argumentCount; i++) this.paramTypes[i] = getU32_unaligned(pParamTypes + (i * 4)); this.defaultImplementation = defaultImplementation; this.result = 0; - let subName = name; - if (!subName) { - subName = `${this.imethod.toString(16)}_${this.hasThisReference ? "i" : "s"}${this.hasReturnValue ? "_r" : ""}_${this.argumentCount}`; - } else { - // truncate the real method name so that it doesn't make the module too big. this isn't a big deal for module-per-function, - // but since we jit in groups now we need to keep the sizes reasonable. we keep the tail end of the name - // since it is likely to contain the method name and/or signature instead of type and noise - const maxLength = 24; - if (subName.length > maxLength) - subName = subName.substring(subName.length - maxLength, subName.length); - subName = `${this.imethod.toString(16)}_${subName}`; - } - this.traceName = subName; this.hitCount = 0; } + + generateName () { + const namePtr = cwraps.mono_wasm_method_get_full_name(this.method); + try { + const name = utf8ToString(namePtr); + this.name = name; + let subName = name; + if (!subName) { + subName = `${this.imethod.toString(16)}_${this.hasThisReference ? "i" : "s"}${this.hasReturnValue ? "_r" : ""}_${this.argumentCount}`; + } else { + // truncate the real method name so that it doesn't make the module too big. this isn't a big deal for module-per-function, + // but since we jit in groups now we need to keep the sizes reasonable. we keep the tail end of the name + // since it is likely to contain the method name and/or signature instead of type and noise + const maxLength = 24; + if (subName.length > maxLength) + subName = subName.substring(subName.length - maxLength, subName.length); + subName = `${this.imethod.toString(16)}_${subName}`; + } + this.traceName = subName; + } finally { + if (namePtr) + Module._free(namePtr); + } + } + + getTraceName () { + if (!this.traceName) + this.generateName(); + return this.traceName || "unknown"; + } + + getName () { + if (!this.name) + this.generateName(); + return this.name || "unknown"; + } } let mostRecentOptions: JiterpreterOptions | undefined = undefined; @@ -170,8 +191,7 @@ export function mono_interp_record_interp_entry (imethod: number) { // returns function pointer export function mono_interp_jit_wasm_entry_trampoline ( imethod: number, method: MonoMethod, argumentCount: number, pParamTypes: NativePointer, - unbox: boolean, hasThisReference: boolean, hasReturnValue: boolean, name: NativePointer, - defaultImplementation: number + unbox: boolean, hasThisReference: boolean, hasReturnValue: boolean, defaultImplementation: number ): number { // HACK if (argumentCount > maxInlineArgs) @@ -179,8 +199,7 @@ export function mono_interp_jit_wasm_entry_trampoline ( const info = new TrampolineInfo( imethod, method, argumentCount, pParamTypes, - unbox, hasThisReference, hasReturnValue, utf8ToString(name), - defaultImplementation + unbox, hasThisReference, hasReturnValue, defaultImplementation ); if (!fnTable) fnTable = getWasmFunctionTable(); @@ -311,7 +330,7 @@ function flush_wasm_entry_trampoline_jit_queue () { // Function type for compiled traces builder.defineType( - info.traceName, sig, WasmValtype.void, false + info.getTraceName(), sig, WasmValtype.void, false ); } @@ -338,9 +357,10 @@ function flush_wasm_entry_trampoline_jit_queue () { builder.appendULeb(jitQueue.length); for (let i = 0; i < jitQueue.length; i++) { const info = jitQueue[i]; + const traceName = info.getTraceName(); // Function type for our compiled trace - mono_assert(builder.functionTypes[info.traceName], "func type missing"); - builder.appendULeb(builder.functionTypes[info.traceName][0]); + mono_assert(builder.functionTypes[traceName], "func type missing"); + builder.appendULeb(builder.functionTypes[traceName][0]); } // Export section @@ -348,7 +368,8 @@ function flush_wasm_entry_trampoline_jit_queue () { builder.appendULeb(jitQueue.length); for (let i = 0; i < jitQueue.length; i++) { const info = jitQueue[i]; - builder.appendName(info.traceName); + const traceName = info.getTraceName(); + builder.appendName(traceName); builder.appendU8(0); // Imports get added to the function index space, so we need to add // the count of imported functions to get the index of our compiled trace @@ -360,7 +381,8 @@ function flush_wasm_entry_trampoline_jit_queue () { builder.appendULeb(jitQueue.length); for (let i = 0; i < jitQueue.length; i++) { const info = jitQueue[i]; - builder.beginFunction(info.traceName, { + const traceName = info.getTraceName(); + builder.beginFunction(traceName, { "sp_args": WasmValtype.i32, "need_unbox": WasmValtype.i32, "scratchBuffer": WasmValtype.i32, @@ -368,7 +390,7 @@ function flush_wasm_entry_trampoline_jit_queue () { const ok = generate_wasm_body(builder, info); if (!ok) - throw new Error(`Failed to generate ${info.traceName}`); + throw new Error(`Failed to generate ${traceName}`); builder.appendU8(WasmOpcode.end); builder.endFunction(true); @@ -390,9 +412,10 @@ function flush_wasm_entry_trampoline_jit_queue () { // to point to the new jitted trampolines instead of the default implementations for (let i = 0; i < jitQueue.length; i++) { const info = jitQueue[i]; + const traceName = info.getTraceName(); // Get the exported trampoline - const fn = traceInstance.exports[info.traceName]; + const fn = traceInstance.exports[traceName]; // Patch the function pointer for this function to use the trampoline now fnTable.set(info.result, fn); diff --git a/src/mono/mono/metadata/class.c b/src/mono/mono/metadata/class.c index 01888dfbabd57..2209f0f88a1e6 100644 --- a/src/mono/mono/metadata/class.c +++ b/src/mono/mono/metadata/class.c @@ -1168,7 +1168,7 @@ MonoMethod* mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error) { MonoMethod *result; - MonoMethodInflated *iresult, *cached; + MonoMethodInflated *iresult, *cached = NULL; MonoMethodSignature *sig; MonoGenericContext tmp_context; @@ -1223,8 +1223,8 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k // check cache mono_mem_manager_lock (mm); if (!mm->gmethod_cache) - mm->gmethod_cache = g_hash_table_new_full (inflated_method_hash, inflated_method_equal, NULL, (GDestroyNotify)free_inflated_method); - cached = (MonoMethodInflated *)g_hash_table_lookup (mm->gmethod_cache, iresult); + mm->gmethod_cache = dn_simdhash_ght_new_full (inflated_method_hash, inflated_method_equal, NULL, (GDestroyNotify)free_inflated_method, 0, NULL); + dn_simdhash_ght_try_get_value (mm->gmethod_cache, iresult, (void **)&cached); mono_mem_manager_unlock (mm); if (cached) { @@ -1319,9 +1319,10 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k // check cache mono_mem_manager_lock (mm); - cached = (MonoMethodInflated *)g_hash_table_lookup (mm->gmethod_cache, iresult); + cached = NULL; + dn_simdhash_ght_try_get_value (mm->gmethod_cache, iresult, (void **)&cached); if (!cached) { - g_hash_table_insert (mm->gmethod_cache, iresult, iresult); + dn_simdhash_ght_insert (mm->gmethod_cache, iresult, iresult); iresult->owner = mm; cached = iresult; } diff --git a/src/mono/mono/metadata/image.c b/src/mono/mono/metadata/image.c index 74a59c4805cc8..37dec87fe5e82 100644 --- a/src/mono/mono/metadata/image.c +++ b/src/mono/mono/metadata/image.c @@ -2066,9 +2066,9 @@ mono_image_close_except_pools (MonoImage *image) } if (image->method_cache) - g_hash_table_destroy (image->method_cache); + dn_simdhash_free (image->method_cache); if (image->methodref_cache) - g_hash_table_destroy (image->methodref_cache); + dn_simdhash_free (image->methodref_cache); mono_internal_hash_table_destroy (&image->class_cache); mono_conc_hashtable_destroy (image->field_cache); if (image->array_cache) { diff --git a/src/mono/mono/metadata/loader-internals.h b/src/mono/mono/metadata/loader-internals.h index 17a7a1968621d..6fa39c096d101 100644 --- a/src/mono/mono/metadata/loader-internals.h +++ b/src/mono/mono/metadata/loader-internals.h @@ -18,6 +18,7 @@ #include #include #include +#include "../native/containers/dn-simdhash-specializations.h" #if defined(TARGET_OSX) #define MONO_LOADER_LIBRARY_NAME "libcoreclr.dylib" @@ -174,7 +175,8 @@ struct _MonoMemoryManager { MonoAssemblyLoadContext **alcs; // Generic-specific caches - GHashTable *ginst_cache, *gmethod_cache, *gsignature_cache; + GHashTable *gsignature_cache; + dn_simdhash_ght_t *ginst_cache, *gmethod_cache; MonoConcurrentHashTable *gclass_cache; /* mirror caches of ones already on MonoImage. These ones contain generics */ diff --git a/src/mono/mono/metadata/loader.c b/src/mono/mono/metadata/loader.c index 5f9e5c0e7d1f1..467fe0e668c07 100644 --- a/src/mono/mono/metadata/loader.c +++ b/src/mono/mono/metadata/loader.c @@ -1182,12 +1182,12 @@ mono_get_method_checked (MonoImage *image, guint32 token, MonoClass *klass, Mono if (mono_metadata_token_table (token) == MONO_TABLE_METHOD) { if (!image->method_cache) - image->method_cache = g_hash_table_new (NULL, NULL); - result = (MonoMethod *)g_hash_table_lookup (image->method_cache, GINT_TO_POINTER (mono_metadata_token_index (token))); + image->method_cache = dn_simdhash_u32_ptr_new (0, NULL); + dn_simdhash_u32_ptr_try_get_value (image->method_cache, mono_metadata_token_index (token), (void **)&result); } else if (!image_is_dynamic (image)) { if (!image->methodref_cache) - image->methodref_cache = g_hash_table_new (NULL, NULL); - result = (MonoMethod *)g_hash_table_lookup (image->methodref_cache, GINT_TO_POINTER (token)); + image->methodref_cache = dn_simdhash_u32_ptr_new (0, NULL); + dn_simdhash_u32_ptr_try_get_value (image->methodref_cache, token, (void **)&result); } mono_image_unlock (image); @@ -1204,9 +1204,9 @@ mono_get_method_checked (MonoImage *image, guint32 token, MonoClass *klass, Mono MonoMethod *result2 = NULL; if (mono_metadata_token_table (token) == MONO_TABLE_METHOD) - result2 = (MonoMethod *)g_hash_table_lookup (image->method_cache, GINT_TO_POINTER (mono_metadata_token_index (token))); + dn_simdhash_u32_ptr_try_get_value (image->method_cache, mono_metadata_token_index (token), (void **)&result2); else if (!image_is_dynamic (image)) - result2 = (MonoMethod *)g_hash_table_lookup (image->methodref_cache, GINT_TO_POINTER (token)); + dn_simdhash_u32_ptr_try_get_value (image->methodref_cache, token, (void **)&result2); if (result2) { mono_image_unlock (image); @@ -1214,9 +1214,9 @@ mono_get_method_checked (MonoImage *image, guint32 token, MonoClass *klass, Mono } if (mono_metadata_token_table (token) == MONO_TABLE_METHOD) - g_hash_table_insert (image->method_cache, GINT_TO_POINTER (mono_metadata_token_index (token)), result); + dn_simdhash_u32_ptr_try_add (image->method_cache, mono_metadata_token_index (token), result); else if (!image_is_dynamic (image)) - g_hash_table_insert (image->methodref_cache, GINT_TO_POINTER (token), result); + dn_simdhash_u32_ptr_try_add (image->methodref_cache, token, result); } mono_image_unlock (image); @@ -1514,7 +1514,7 @@ mono_method_get_param_token (MonoMethod *method, int index) idx = mono_method_get_index (method); if (idx > 0) { guint param_index = mono_metadata_get_method_params (klass_image, idx, NULL); - + if (index == -1) /* Return value */ return mono_metadata_make_token (MONO_TABLE_PARAM, 0); diff --git a/src/mono/mono/metadata/memory-manager.c b/src/mono/mono/metadata/memory-manager.c index a4de69eaa4681..aeb7373f6b8f2 100644 --- a/src/mono/mono/metadata/memory-manager.c +++ b/src/mono/mono/metadata/memory-manager.c @@ -204,6 +204,14 @@ free_hash (GHashTable **hash) *hash = NULL; } +static void +free_simdhash (dn_simdhash_t **hash) +{ + if (*hash) + dn_simdhash_free (*hash); + *hash = NULL; +} + // Full deletion static void memory_manager_delete (MonoMemoryManager *memory_manager, gboolean debug_unload) @@ -230,8 +238,8 @@ memory_manager_delete (MonoMemoryManager *memory_manager, gboolean debug_unload) MonoMemoryManager *mm = memory_manager; if (mm->gclass_cache) mono_conc_hashtable_destroy (mm->gclass_cache); - free_hash (&mm->ginst_cache); - free_hash (&mm->gmethod_cache); + free_simdhash (&mm->ginst_cache); + free_simdhash (&mm->gmethod_cache); free_hash (&mm->gsignature_cache); free_hash (&mm->szarray_cache); free_hash (&mm->array_cache); diff --git a/src/mono/mono/metadata/metadata-internals.h b/src/mono/mono/metadata/metadata-internals.h index 8c1dfd803b578..fac7b69e385e9 100644 --- a/src/mono/mono/metadata/metadata-internals.h +++ b/src/mono/mono/metadata/metadata-internals.h @@ -418,11 +418,11 @@ struct _MonoImage { /* * Indexed by method tokens and typedef tokens. */ - GHashTable *method_cache; /*protected by the image lock*/ + dn_simdhash_u32_ptr_t *method_cache; /*protected by the image lock*/ MonoInternalHashTable class_cache; /* Indexed by memberref + methodspec tokens */ - GHashTable *methodref_cache; /*protected by the image lock*/ + dn_simdhash_u32_ptr_t *methodref_cache; /*protected by the image lock*/ /* * Indexed by fielddef and memberref tokens diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c index c517703415eab..3b05c485137b9 100644 --- a/src/mono/mono/metadata/metadata.c +++ b/src/mono/mono/metadata/metadata.c @@ -3449,9 +3449,10 @@ mono_metadata_get_canonical_generic_inst (MonoGenericInst *candidate) mono_loader_lock (); if (!mm->ginst_cache) - mm->ginst_cache = g_hash_table_new_full (mono_metadata_generic_inst_hash, mono_metadata_generic_inst_equal, NULL, (GDestroyNotify)free_generic_inst); + mm->ginst_cache = dn_simdhash_ght_new_full (mono_metadata_generic_inst_hash, mono_metadata_generic_inst_equal, NULL, (GDestroyNotify)free_generic_inst, 0, NULL); - MonoGenericInst *ginst = (MonoGenericInst *)g_hash_table_lookup (mm->ginst_cache, candidate); + MonoGenericInst *ginst = NULL; + dn_simdhash_ght_try_get_value (mm->ginst_cache, candidate, (void **)&ginst); if (!ginst) { int size = MONO_SIZEOF_GENERIC_INST + type_argc * sizeof (MonoType *); ginst = (MonoGenericInst *)mono_mem_manager_alloc0 (mm, size); @@ -3465,7 +3466,7 @@ mono_metadata_get_canonical_generic_inst (MonoGenericInst *candidate) for (int i = 0; i < type_argc; ++i) ginst->type_argv [i] = mono_metadata_type_dup (NULL, candidate->type_argv [i]); - g_hash_table_insert (mm->ginst_cache, ginst, ginst); + dn_simdhash_ght_insert (mm->ginst_cache, ginst, ginst); } mono_loader_unlock (); diff --git a/src/mono/mono/mini/CMakeLists.txt b/src/mono/mono/mini/CMakeLists.txt index 9bfc67893bf4e..b9bd9d426bc68 100644 --- a/src/mono/mono/mini/CMakeLists.txt +++ b/src/mono/mono/mini/CMakeLists.txt @@ -54,6 +54,7 @@ set(imported_native_sources ../../../native/containers/dn-simdhash-ptr-ptr.c ../../../native/containers/dn-simdhash-string-ptr.c ../../../native/containers/dn-simdhash-u32-ptr.c + ../../../native/containers/dn-simdhash-ght-compatible.c ../../../native/containers/dn-simdhash-ptrpair-ptr.c) set(mini_common_sources diff --git a/src/mono/mono/mini/aot-runtime.c b/src/mono/mono/mini/aot-runtime.c index db2308595939e..a9709afb81ad6 100644 --- a/src/mono/mono/mini/aot-runtime.c +++ b/src/mono/mono/mini/aot-runtime.c @@ -106,7 +106,7 @@ struct MonoAotModule { GHashTable *name_cache; GHashTable *extra_methods; /* Maps methods to their code */ - GHashTable *method_to_code; + dn_simdhash_ptr_ptr_t *method_to_code; /* Maps pointers into the method info to the methods themselves */ dn_simdhash_ptr_ptr_t *method_ref_to_method; MonoAssemblyName *image_names; @@ -2159,7 +2159,8 @@ load_aot_module (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, gpointer amodule->llvm_got = g_malloc0 (sizeof (gpointer) * amodule->info.llvm_got_size); amodule->globals = globals; amodule->sofile = sofile; - amodule->method_to_code = g_hash_table_new (mono_aligned_addr_hash, NULL); + // FIXME: Select a better default size + amodule->method_to_code = dn_simdhash_ptr_ptr_new (4096, NULL); amodule->extra_methods = g_hash_table_new (NULL, NULL); amodule->shared_got = g_new0 (gpointer, info->nshared_got_entries); @@ -4444,7 +4445,7 @@ load_method (MonoAotModule *amodule, MonoImage *image, MonoMethod *method, guint mono_atomic_inc_i32 (&mono_jit_stats.methods_aot); if (method && method->wrapper_type) - g_hash_table_insert (amodule->method_to_code, method, code); + dn_simdhash_ptr_ptr_try_add (amodule->method_to_code, method, code); /* Commit changes since methods_loaded is accessed outside the lock */ mono_memory_barrier (); @@ -4902,7 +4903,7 @@ mono_aot_get_method (MonoMethod *method, MonoError *error) MonoMethod *orig_method = method; guint32 method_index; MonoAotModule *amodule = m_class_get_image (klass)->aot_module; - guint8 *code; + guint8 *code = NULL; gboolean cache_result = FALSE; ERROR_DECL (inner_error); @@ -4951,7 +4952,7 @@ mono_aot_get_method (MonoMethod *method, MonoError *error) if (method_index == 0xffffff && (method->is_inflated || !method->token)) { /* This hash table is used to avoid the slower search in the extra_method_table in the AOT image */ amodule_lock (amodule); - code = (guint8 *)g_hash_table_lookup (amodule->method_to_code, method); + dn_simdhash_ptr_ptr_try_get_value (amodule->method_to_code, method, (void **)&code); amodule_unlock (amodule); if (code) return code; @@ -5103,7 +5104,7 @@ mono_aot_get_method (MonoMethod *method, MonoError *error) return NULL; if (code && cache_result) { amodule_lock (amodule); - g_hash_table_insert (amodule->method_to_code, orig_method, code); + dn_simdhash_ptr_ptr_try_add (amodule->method_to_code, orig_method, code); amodule_unlock (amodule); } return code; diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 7de2bf84d8485..3e25c7acc2966 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -2824,10 +2824,13 @@ do_jit_call (ThreadContext *context, stackval *ret_sp, stackval *sp, InterpFrame } JitCallCbData cb_data; - memset (&cb_data, 0, sizeof (cb_data)); cb_data.pindex = pindex; cb_data.args = args; + cb_data.ftndesc.interp_method = NULL; + cb_data.ftndesc.method = NULL; if (cinfo->no_wrapper) { + cb_data.ftndesc.addr = NULL; + cb_data.ftndesc.arg = NULL; cb_data.jit_wrapper = cinfo->addr; cb_data.extra_arg = cinfo->extra_arg; } else { @@ -3341,13 +3344,11 @@ interp_create_method_pointer_llvmonly (MonoMethod *method, gboolean unbox, MonoE ) { jiterp_preserve_module(); - const char *name = mono_method_full_name (method, FALSE); gpointer wasm_entry_func = mono_interp_jit_wasm_entry_trampoline ( imethod, method, sig->param_count, (MonoType *)sig->params, unbox, sig->hasthis, sig->ret->type != MONO_TYPE_VOID, - name, entry_func + entry_func ); - g_free((void *)name); // Compiling a trampoline can fail for various reasons, so in that case we will fall back to the pre-existing ones below if (wasm_entry_func) diff --git a/src/mono/mono/mini/interp/jiterpreter.h b/src/mono/mono/mini/interp/jiterpreter.h index ed57b0a0e17b3..e9b3c67cb2937 100644 --- a/src/mono/mono/mini/interp/jiterpreter.h +++ b/src/mono/mono/mini/interp/jiterpreter.h @@ -120,7 +120,7 @@ mono_interp_record_interp_entry (void *fn_ptr); extern gpointer mono_interp_jit_wasm_entry_trampoline ( void *imethod, MonoMethod *method, int argument_count, MonoType *param_types, - int unbox, int has_this, int has_return, const char *name, void *default_implementation + int unbox, int has_this, int has_return, void *default_implementation ); // Fast-path implemented in C diff --git a/src/mono/sample/wasm/simple-raytracer/Program.cs b/src/mono/sample/wasm/simple-raytracer/Program.cs index 5ee605e8ef683..50dec0a2395d8 100644 --- a/src/mono/sample/wasm/simple-raytracer/Program.cs +++ b/src/mono/sample/wasm/simple-raytracer/Program.cs @@ -190,7 +190,7 @@ private static void renderPixel (int i, int j, ref Vec3f light, Intersector inte float hitZ = -999; bool didHitZ = false; for (int s = 0; s < scene.Length; s++) { - ref var sphere = ref scene[s]; + var sphere = scene[s]; if (didHitZ && (hitZ > sphere.Center.z)) continue; diff --git a/src/mono/sample/wasm/simple-raytracer/main.js b/src/mono/sample/wasm/simple-raytracer/main.js index decdf6453c948..7dc3397f0f87e 100644 --- a/src/mono/sample/wasm/simple-raytracer/main.js +++ b/src/mono/sample/wasm/simple-raytracer/main.js @@ -19,8 +19,9 @@ const config = getConfig(); const exports = await getAssemblyExports(config.mainAssemblyName); globalThis.onClick = exports.Program.OnClick; -await dotnet +const runtime = await dotnet .withRuntimeOptions(["--jiterpreter-stats-enabled"]) - .run(); + .create(); +await runtime.runMain(); const btnRender = document.getElementById("btnRender"); btnRender.disabled = false;