From 8d066072a82bcdfa48779c0cd3e226bd0f90cb52 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Fri, 14 Aug 2026 14:29:55 +0200 Subject: [PATCH 1/5] [TEMP] validate 131537 under Mono wasm-AOT on Chrome TEMP validation branch (do not merge): - move test131537 to Pri0 so innerloop wasm runtime-tests include it - add scoped Mono AOT + Chrome runtime-test lane (tree-scoped to 131537, RunAOTCompilation=true) wired into the runtime-wasm pipeline Reproduces the AOT'd-corelib + force-interpreted-test-assembly config from #131537. --- .../wasm-aot-runtime-test-131537.yml | 54 +++++++++++++++++++ .../runtime-extra-platforms-wasm.yml | 12 +++++ .../regressions/131537/test131537.csproj | 3 +- 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 eng/pipelines/common/templates/wasm-aot-runtime-test-131537.yml diff --git a/eng/pipelines/common/templates/wasm-aot-runtime-test-131537.yml b/eng/pipelines/common/templates/wasm-aot-runtime-test-131537.yml new file mode 100644 index 00000000000000..f427900217d5a0 --- /dev/null +++ b/eng/pipelines/common/templates/wasm-aot-runtime-test-131537.yml @@ -0,0 +1,54 @@ +# TEMP (wasm-aot-131537-validation): validate that the src/tests regression test +# Loader/classloader/generics/regressions/131537 actually runs under the Mono +# wasm-AOT configuration that reproduces #131537 (AOT'd corelib + force-interpreted +# test assembly). Scoped to just that one test via `-tree`, AOT'd locally, run on +# Chrome. Delete this file (and its reference in runtime-extra-platforms-wasm.yml) +# before merging anything real. + +parameters: + alwaysRun: false + isExtraPlatformsBuild: false + isWasmOnlyBuild: false + platforms: [] + extraBuildArgs: '' + useHelixMonitor: false + +jobs: + +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml + buildConfig: Release + runtimeFlavor: mono + platforms: ${{ parameters.platforms }} + variables: + - name: alwaysRunVar + value: ${{ parameters.alwaysRun }} + - name: timeoutPerTestInMinutes + value: 20 + - name: timeoutPerTestCollectionInMinutes + value: 200 + jobParameters: + testGroup: innerloop + isExtraPlatforms: ${{ parameters.isExtraPlatformsBuild }} + nameSuffix: AllSubsets_Mono_RuntimeTests_AOT_131537 + # No runtimeVariant (i.e. not monointerpreter): we want corelib AOT'd, and + # the test csproj force-interprets only test131537.dll via + # _AOT_InternalForceInterpretAssemblies — reproducing the failing config. + buildArgs: -s mono+libs -c $(_BuildConfig) /p:MonoEnableAssertMessages=true /p:InstallV8ForTests=false ${{ parameters.extraBuildArgs }} + timeoutInMinutes: 180 + condition: eq(variables['alwaysRunVar'], true) + postBuildSteps: + - template: /eng/pipelines/common/templates/runtimes/build-runtime-tests-and-send-to-helix.yml + parameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Mono_$(_BuildConfig)_AOT_131537 + # Scope the runtime-test build to just this one test, and AOT it locally + # (RunAOTCompilation=true) so corelib is AOT'd in the produced wasm app. + testBuildArgs: tree Loader/classloader/generics/regressions/131537 /p:RunAOTCompilation=true /p:InstallV8ForTests=false + scenarios: + - WasmTestOnChrome + useHelixMonitor: ${{ parameters.useHelixMonitor }} + extraVariablesTemplates: + - template: /eng/pipelines/common/templates/runtimes/test-variables.yml diff --git a/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml b/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml index 4ba21df5c78571..cff515ae762719 100644 --- a/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml +++ b/eng/pipelines/extra-platforms/runtime-extra-platforms-wasm.yml @@ -249,6 +249,18 @@ jobs: isWasmOnlyBuild: ${{ parameters.isWasmOnlyBuild }} useHelixMonitor: ${{ variables.enableHelixJobMonitor }} + # TEMP (wasm-aot-131537-validation): Mono AOT + Chrome runtime-test lane scoped to + # Loader/classloader/generics/regressions/131537 only. Remove before merging. + - template: /eng/pipelines/common/templates/wasm-aot-runtime-test-131537.yml + parameters: + platforms: + - browser_wasm + extraBuildArgs: /p:AotHostArchitecture=x64 /p:AotHostOS=$(_hostedOS) + isExtraPlatformsBuild: ${{ parameters.isExtraPlatformsBuild }} + isWasmOnlyBuild: ${{ parameters.isWasmOnlyBuild }} + alwaysRun: ${{ parameters.isWasmOnlyBuild }} + useHelixMonitor: ${{ variables.enableHelixJobMonitor }} + - ${{ if and(ne(parameters.isRollingBuild, true), ne(parameters.excludeOptional, true)) }}: - template: /eng/pipelines/common/templates/wasm-library-tests.yml parameters: diff --git a/src/tests/Loader/classloader/generics/regressions/131537/test131537.csproj b/src/tests/Loader/classloader/generics/regressions/131537/test131537.csproj index 06c63a526492bb..19bd0559940276 100644 --- a/src/tests/Loader/classloader/generics/regressions/131537/test131537.csproj +++ b/src/tests/Loader/classloader/generics/regressions/131537/test131537.csproj @@ -1,6 +1,7 @@ - 1 + + 0 From 121b34a60cb975f5e6d14bdd44e8e3ac138ba13d Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Fri, 14 Aug 2026 14:39:12 +0200 Subject: [PATCH 2/5] [TEMP] Revert #132153 runtime fix (keep test) to prove AOT lane catches regression Drop this commit to restore green. With the mono fix reverted, the AOT+Chrome lane should show test131537 failing with 'function signature mismatch', proving the lane exercises the #131537 repro. Test files are intentionally kept. --- src/mono/mono/metadata/jit-icall-reg.h | 1 - src/mono/mono/mini/jit-icalls.c | 9 ------ src/mono/mono/mini/jit-icalls.h | 2 -- src/mono/mono/mini/method-to-ir.c | 42 +++++++------------------- src/mono/mono/mini/mini-runtime.c | 1 - 5 files changed, 11 insertions(+), 44 deletions(-) diff --git a/src/mono/mono/metadata/jit-icall-reg.h b/src/mono/mono/metadata/jit-icall-reg.h index 1d159485bc63af..c58a320f89ab5b 100644 --- a/src/mono/mono/metadata/jit-icall-reg.h +++ b/src/mono/mono/metadata/jit-icall-reg.h @@ -203,7 +203,6 @@ MONO_JIT_ICALL (mono_get_native_calli_wrapper) \ MONO_JIT_ICALL (mono_get_special_static_data) \ MONO_JIT_ICALL (mono_gsharedvt_constrained_call) \ MONO_JIT_ICALL (mono_gsharedvt_value_copy) \ -MONO_JIT_ICALL (mono_helper_box_nullable) \ MONO_JIT_ICALL (mono_helper_compile_generic_method) \ MONO_JIT_ICALL (mono_helper_ldstr) \ MONO_JIT_ICALL (mono_helper_ldstr_mscorlib) \ diff --git a/src/mono/mono/mini/jit-icalls.c b/src/mono/mono/mini/jit-icalls.c index 4d9a95b8181227..fba533310bd2c7 100644 --- a/src/mono/mono/mini/jit-icalls.c +++ b/src/mono/mono/mini/jit-icalls.c @@ -1169,15 +1169,6 @@ mono_helper_newobj_mscorlib (guint32 idx) return obj; } -MonoObject* -mono_helper_box_nullable (gpointer vbuf, MonoClass *klass) -{ - ERROR_DECL (error); - MonoObject *result = mono_nullable_box (vbuf, klass, error); - mono_error_set_pending_exception (error); - return result; -} - /* * On some architectures, gdb doesn't like encountering the cpu breakpoint instructions * in generated code. So instead we emit a call to this function and place a gdb diff --git a/src/mono/mono/mini/jit-icalls.h b/src/mono/mono/mini/jit-icalls.h index 42b394b06b28a7..6e9ea58124e1e3 100644 --- a/src/mono/mono/mini/jit-icalls.h +++ b/src/mono/mono/mini/jit-icalls.h @@ -116,8 +116,6 @@ ICALL_EXPORT MonoString *mono_helper_ldstr_mscorlib (guint32 idx); ICALL_EXPORT MonoObject *mono_helper_newobj_mscorlib (guint32 idx); -ICALL_EXPORT MonoObject *mono_helper_box_nullable (gpointer vbuf, MonoClass *klass); - ICALL_EXPORT double mono_fsub (double a, double b); ICALL_EXPORT double mono_fadd (double a, double b); diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index b7faaa15cf79cc..4545e6e0a21168 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -3403,26 +3403,6 @@ handle_alloc (MonoCompile *cfg, MonoClass *klass, gboolean for_box, int context_ return mono_emit_jit_icall_id (cfg, alloc_ftn, iargs); } -/* - * Box a gsharedvt Nullable via a non-generic runtime helper, passing the value by - * address and the concrete class from the rgctx. This avoids a per-T box wrapper that - * cannot be emitted at AOT time when the consuming assembly runs interpreted. - */ -static MonoInst* -mini_emit_nullable_box_helper (MonoCompile *cfg, MonoInst *val, MonoClass *klass, int context_used) -{ - MonoInst *iargs [2], *addr, *var; - - var = get_vreg_to_inst (cfg, val->dreg); - if (!var) - var = mono_compile_create_var_for_vreg (cfg, m_class_get_byval_arg (klass), OP_LOCAL, val->dreg); - EMIT_NEW_VARLOADA (cfg, addr, var, var->inst_vtype); - - iargs [0] = addr; - iargs [1] = mini_emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS); - return mono_emit_jit_icall (cfg, mono_helper_box_nullable, iargs); -} - /* * Returns NULL and set the cfg exception on error. */ @@ -3445,9 +3425,11 @@ mini_emit_box (MonoCompile *cfg, MonoInst *val, MonoClass *klass, int context_us MonoInst *addr; MonoMethodSignature *sig = mono_method_signature_internal (method); if (mini_is_gsharedvt_klass (klass)) - return mini_emit_nullable_box_helper (cfg, val, klass, context_used); - addr = emit_get_rgctx_method (cfg, context_used, method, - MONO_RGCTX_INFO_METHOD_FTNDESC); + addr = mini_emit_get_gsharedvt_info_klass (cfg, klass, + MONO_RGCTX_INFO_NULLABLE_CLASS_BOX); + else + addr = emit_get_rgctx_method (cfg, context_used, method, + MONO_RGCTX_INFO_METHOD_FTNDESC); cfg->interp_in_signatures = g_slist_prepend_mempool (cfg->mempool, cfg->interp_in_signatures, sig); return mini_emit_llvmonly_calli (cfg, sig, &val, addr); } else { @@ -3513,14 +3495,9 @@ mini_emit_box (MonoCompile *cfg, MonoInst *val, MonoClass *klass, int context_us /* Nullable case */ MONO_START_BB (cfg, is_nullable_bb); - if (cfg->llvm_only) { - MonoInst *box_call = mini_emit_nullable_box_helper (cfg, val, klass, context_used); - EMIT_NEW_UNALU (cfg, res, OP_MOVE, dreg, box_call->dreg); - res->type = STACK_OBJ; - res->klass = klass; - } else { + { MonoInst *box_addr = mini_emit_get_gsharedvt_info_klass (cfg, klass, - MONO_RGCTX_INFO_NULLABLE_CLASS_BOX); + MONO_RGCTX_INFO_NULLABLE_CLASS_BOX); MonoInst *box_call; MonoMethodSignature *box_sig; @@ -3533,7 +3510,10 @@ mini_emit_box (MonoCompile *cfg, MonoInst *val, MonoClass *klass, int context_us box_sig->param_count = 1; box_sig->params [0] = m_class_get_byval_arg (klass); - box_call = mini_emit_calli (cfg, box_sig, &val, box_addr, NULL, NULL); + if (cfg->llvm_only) + box_call = mini_emit_llvmonly_calli (cfg, box_sig, &val, box_addr); + else + box_call = mini_emit_calli (cfg, box_sig, &val, box_addr, NULL, NULL); EMIT_NEW_UNALU (cfg, res, OP_MOVE, dreg, box_call->dreg); res->type = STACK_OBJ; res->klass = klass; diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 6a2099535cbddd..46e28a680b3cc7 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -5114,7 +5114,6 @@ register_icalls (void) register_icall (mono_helper_ldstr, mono_icall_sig_object_ptr_int, FALSE); register_icall (mono_helper_ldstr_mscorlib, mono_icall_sig_object_int, FALSE); register_icall (mono_helper_newobj_mscorlib, mono_icall_sig_object_int, FALSE); - register_icall (mono_helper_box_nullable, mono_icall_sig_object_ptr_ptr, FALSE); register_icall (mono_value_copy_internal, mono_icall_sig_void_ptr_ptr_ptr, FALSE); register_icall (mono_object_castclass_unbox, mono_icall_sig_object_object_ptr, FALSE); register_icall (mono_break, mono_icall_sig_void, TRUE); From 8bf756c7ba14602570d931565585c6d4ffac19a3 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Fri, 14 Aug 2026 15:29:43 +0200 Subject: [PATCH 3/5] [TEMP] build scoped 131537 test as standalone so it produces a Helix work item --- .../common/templates/wasm-aot-runtime-test-131537.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/eng/pipelines/common/templates/wasm-aot-runtime-test-131537.yml b/eng/pipelines/common/templates/wasm-aot-runtime-test-131537.yml index f427900217d5a0..6d71ad543b1f8b 100644 --- a/eng/pipelines/common/templates/wasm-aot-runtime-test-131537.yml +++ b/eng/pipelines/common/templates/wasm-aot-runtime-test-131537.yml @@ -44,6 +44,9 @@ jobs: parameters: creator: dotnet-bot testRunNamePrefixSuffix: Mono_$(_BuildConfig)_AOT_131537 + # Build the single scoped test as a standalone wasm app (not merged) so it + # yields its own Helix work item; merged mode drops a lone test (0 in group). + buildAllTestsAsStandalone: true # Scope the runtime-test build to just this one test, and AOT it locally # (RunAOTCompilation=true) so corelib is AOT'd in the produced wasm app. testBuildArgs: tree Loader/classloader/generics/regressions/131537 /p:RunAOTCompilation=true /p:InstallV8ForTests=false From 8469bb0038555e57cbcca064a4ef5e2b65e4e35f Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Fri, 14 Aug 2026 17:33:54 +0200 Subject: [PATCH 4/5] [TEMP] opt scoped 131537 build into groups 2..n on browser CI (#114123 workaround) --- .../common/templates/wasm-aot-runtime-test-131537.yml | 4 +++- src/tests/build.proj | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/eng/pipelines/common/templates/wasm-aot-runtime-test-131537.yml b/eng/pipelines/common/templates/wasm-aot-runtime-test-131537.yml index 6d71ad543b1f8b..4e1609faa1b3bf 100644 --- a/eng/pipelines/common/templates/wasm-aot-runtime-test-131537.yml +++ b/eng/pipelines/common/templates/wasm-aot-runtime-test-131537.yml @@ -49,7 +49,9 @@ jobs: buildAllTestsAsStandalone: true # Scope the runtime-test build to just this one test, and AOT it locally # (RunAOTCompilation=true) so corelib is AOT'd in the produced wasm app. - testBuildArgs: tree Loader/classloader/generics/regressions/131537 /p:RunAOTCompilation=true /p:InstallV8ForTests=false + # _BuildAllTestGroupsForBrowser: this test is in group 3 (Pri0), and browser CI + # otherwise builds only group 1 (#114123); safe here since only one test is scoped. + testBuildArgs: tree Loader/classloader/generics/regressions/131537 /p:RunAOTCompilation=true /p:InstallV8ForTests=false /p:_BuildAllTestGroupsForBrowser=true scenarios: - WasmTestOnChrome useHelixMonitor: ${{ parameters.useHelixMonitor }} diff --git a/src/tests/build.proj b/src/tests/build.proj index 884ccfcddb0f79..21960e2433cb3a 100644 --- a/src/tests/build.proj +++ b/src/tests/build.proj @@ -205,9 +205,10 @@ From ef2b84a1a5ba9ce5d0adb77b84abc11b6753a76b Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Fri, 14 Aug 2026 19:04:42 +0200 Subject: [PATCH 5/5] [TEMP] make test131537 a self-contained merged runner (wasm work-item path) --- .../common/templates/wasm-aot-runtime-test-131537.yml | 3 --- .../generics/regressions/131537/test131537.csproj | 8 +++++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/eng/pipelines/common/templates/wasm-aot-runtime-test-131537.yml b/eng/pipelines/common/templates/wasm-aot-runtime-test-131537.yml index 4e1609faa1b3bf..f559f532c8be21 100644 --- a/eng/pipelines/common/templates/wasm-aot-runtime-test-131537.yml +++ b/eng/pipelines/common/templates/wasm-aot-runtime-test-131537.yml @@ -44,9 +44,6 @@ jobs: parameters: creator: dotnet-bot testRunNamePrefixSuffix: Mono_$(_BuildConfig)_AOT_131537 - # Build the single scoped test as a standalone wasm app (not merged) so it - # yields its own Helix work item; merged mode drops a lone test (0 in group). - buildAllTestsAsStandalone: true # Scope the runtime-test build to just this one test, and AOT it locally # (RunAOTCompilation=true) so corelib is AOT'd in the produced wasm app. # _BuildAllTestGroupsForBrowser: this test is in group 3 (Pri0), and browser CI diff --git a/src/tests/Loader/classloader/generics/regressions/131537/test131537.csproj b/src/tests/Loader/classloader/generics/regressions/131537/test131537.csproj index 19bd0559940276..b3be7d10e0db8e 100644 --- a/src/tests/Loader/classloader/generics/regressions/131537/test131537.csproj +++ b/src/tests/Loader/classloader/generics/regressions/131537/test131537.csproj @@ -2,13 +2,13 @@ 0 + + true - - - <_AOT_InternalForceInterpretAssemblies Include="test131537.dll" /> + +