Skip to content

[do not review] test regression 2#124522

Closed
radekdoulik wants to merge 137 commits intodotnet:mainfrom
radekdoulik:clr-wasm-test-regression-2
Closed

[do not review] test regression 2#124522
radekdoulik wants to merge 137 commits intodotnet:mainfrom
radekdoulik:clr-wasm-test-regression-2

Conversation

@radekdoulik
Copy link
Member

No description provided.

Set `isTailcall` to `false`, when preparing the call. This is similar
to how we set other state vars for the call, so I did it this way.

Alternatively we can reset the `isTailcall` after updating the stack
and frame for tailcalls. That would invalidate the meaning of the
variable for the rest of the tailcall though, so we would need to
rename it at least to signal, that it is valid only in the beginning
of the tailcall.
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @agocke, @dotnet/runtime-infrastructure
See info in area-owners.md if you want to be subscribed.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for running CoreCLR WASM tests with NodeJS and implements native symbol map functionality for better stack trace symbolication in WASM environments. The changes enable running tests on platforms that use NodeJS instead of V8 shell, improving test coverage for CoreCLR on browser/WASM.

Changes:

  • Added --node command-line option to test runners (run.sh, run.py, run.cmd) with automatic default for WASM architecture
  • Implemented WASM symbol map loading and stack trace symbolication for debugging
  • Refactored CoreCLR prestub logic to move DoPrestub calls out of CallDescrWorkerInternal
  • Improved exit code propagation through BrowserHost_ExecuteAssembly and BrowserHost_ShutdownCoreCLR
  • Updated threading tests to use ConditionalFact instead of ActiveIssue annotations
  • Added IsWasm property to PlatformDetection for test filtering
  • Restructured build pipelines for browser_wasm with separate Release and CoreCLR_ReleaseLibraries builds

Reviewed changes

Copilot reviewed 85 out of 86 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/tests/run.sh, run.py, run.cmd Added --node option for NodeJS test execution on WASM
src/tests/Common/CoreCLRTestLibrary/PlatformDetection.cs Added IsWasm property combining IsBrowser and IsWasi
src/tests/Common/CLRTest.Execute.{Bash,Batch}.targets Implemented NodeJS execution path with timeout support
src/tests/baseservices/threading/coverage/OSThreadId/OSThreadId.cs Changed from ActiveIssue to ConditionalFact for threading support
src/tests/Loader/classloader/StaticVirtualMethods/*.il Added ActiveIssue attributes for WASM platform
src/native/libs/System.Native.Browser/diagnostics/symbolicate.ts Implemented symbol map parsing and stack trace symbolication
src/native/corehost/browserhost/loader/logging.ts Refactored error() signature and added normalizeException()
src/native/corehost/browserhost/browserhost.cpp Added BrowserHost_ShutdownCoreCLR with proper exit code handling
src/coreclr/vm/method.hpp Added GetInterpreterCodeWithPrestub() helper method
src/coreclr/vm/wasm/calldescrworkerwasm.cpp Removed prestub call (now called earlier via helper)
src/coreclr/vm/reflectioninvocation.cpp Added prestub call before CallDescrWorkerInternal
src/coreclr/vm/callhelpers.cpp Added prestub calls for PORTABLE_ENTRYPOINTS
src/coreclr/vm/dllimport.cpp Added debug printf statements (issue)
src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs Added missing cookie signatures for interop
src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/*.cs Added EmitSymbolMap property support
eng/pipelines/runtime.yml Restructured browser_wasm build configurations
eng/pipelines/coreclr/templates/*.yml Added browser_wasm test job configurations

Comment on lines +6200 to +6205
printf("Found UCO method %s on type %s\n", methodName, fullQualifiedTypeName);
return;
}
}

printf("Did not find UCO method %s on type %s, looking for a method with the given name\n", methodName, fullQualifiedTypeName);
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug printf statements should not be committed to production code. These should be replaced with proper logging or removed entirely.

Suggested change
printf("Found UCO method %s on type %s\n", methodName, fullQualifiedTypeName);
return;
}
}
printf("Did not find UCO method %s on type %s, looking for a method with the given name\n", methodName, fullQualifiedTypeName);
return;
}
}

Copilot uses AI. Check for mistakes.
Comment on lines 17 to 19
MethodDesc* pMethod = PortableEntryPoint::GetMethodDesc(pCallDescrData->pTarget);
InterpByteCodeStart* targetIp = pMethod->GetInterpreterCode();
if (targetIp == NULL)
{
GCX_PREEMP();
(void)pMethod->DoPrestub(NULL /* MethodTable */, CallerGCMode::Coop);
targetIp = pMethod->GetInterpreterCode();
}
_ASSERTE(targetIp != nullptr);
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The removal of the DoPrestub call and related GC comment changes the behavior significantly. The code now asserts that targetIp is not null instead of lazily calling DoPrestub when needed. This could cause crashes if GetInterpreterCode() returns nullptr. Ensure that all code paths guarantee the interpreter code is set before CallDescrWorkerInternal is called, or restore the prestub logic.

Copilot uses AI. Check for mistakes.
Comment on lines 375 to 376
GCX_COOP();

Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a redundant GCX_COOP() call at line 375. The code is already in GCX_COOP() mode from line 336. This second call is unnecessary and should be removed.

Suggested change
GCX_COOP();

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings February 18, 2026 10:22
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 79 out of 80 changed files in this pull request and generated 5 comments.

Comment on lines 6199 to +6205
*ppMD = pMD;
printf("Found UCO method %s on type %s\n", methodName, fullQualifiedTypeName);
return;
}
}

printf("Did not find UCO method %s on type %s, looking for a method with the given name\n", methodName, fullQualifiedTypeName);
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug printf statement should not be committed to production code. This will output to stdout in all builds, not just debug builds. If logging is needed, use appropriate logging mechanisms or wrap in #ifdef _DEBUG.

Suggested change
*ppMD = pMD;
printf("Found UCO method %s on type %s\n", methodName, fullQualifiedTypeName);
return;
}
}
printf("Did not find UCO method %s on type %s, looking for a method with the given name\n", methodName, fullQualifiedTypeName);
*ppMD = pMD;
#ifdef _DEBUG
printf("Found UCO method %s on type %s\n", methodName, fullQualifiedTypeName);
#endif // _DEBUG
return;
}
}
#ifdef _DEBUG
printf("Did not find UCO method %s on type %s, looking for a method with the given name\n", methodName, fullQualifiedTypeName);
#endif // _DEBUG

Copilot uses AI. Check for mistakes.
// revisited to ensure correctness.

MethodDesc* pMethod = PortableEntryPoint::GetMethodDesc(pCallDescrData->pTarget);
InterpByteCodeStart* targetIp = pMethod->GetInterpreterCode();
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the DoPrestub call and related GC protection logic appears to assume that GetInterpreterCode() will always return non-null. The assertion at line 19 will crash if the method hasn't been prestubbed. The comment about GC protection being needed suggests this was a known issue. Verify that all callers now ensure prestubbing happens before calling CallDescrWorkerInternal, otherwise this introduces a regression where methods that haven't been jitted will crash instead of being lazily compiled.

Suggested change
InterpByteCodeStart* targetIp = pMethod->GetInterpreterCode();
InterpByteCodeStart* targetIp = pMethod->GetInterpreterCode();
if (targetIp == nullptr)
{
pMethod->DoPrestub(nullptr);
targetIp = pMethod->GetInterpreterCode();
}

Copilot uses AI. Check for mistakes.
Comment on lines +344 to +351
(
sleep "$timeout_sec"
if [ $? -eq 0 ]; then
echo "Process $pid exceeded timeout of $timeout_sec seconds. Killing..."
if kill -0 "$pid" 2>/dev/null; then
kill -9 "$pid" 2>/dev/null
fi
fi
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The timeout watchdog implementation has a logic issue. The condition if [ $? -eq 0 ] at line 346 always evaluates to true after sleep completes successfully, meaning the watchdog will always try to kill the process even if it completed normally. The watchdog should check if the process is still running before attempting to kill it. Consider using a different synchronization mechanism, such as checking if the PID is still alive inside the watchdog before killing, or using a signal-based approach where the main process signals the watchdog when it completes.

Copilot uses AI. Check for mistakes.
Comment on lines +81 to +82
} catch (exc) {
}
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty catch block silently swallows all exceptions during symbol map initialization. At minimum, log the exception using console.debug or console.error to aid debugging when symbol map parsing fails.

Copilot uses AI. Check for mistakes.
Comment on lines 6199 to +6205
*ppMD = pMD;
printf("Found UCO method %s on type %s\n", methodName, fullQualifiedTypeName);
return;
}
}

printf("Did not find UCO method %s on type %s, looking for a method with the given name\n", methodName, fullQualifiedTypeName);
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug printf statement should not be committed to production code. This will output to stdout in all builds, not just debug builds. If logging is needed, use appropriate logging mechanisms or wrap in #ifdef _DEBUG.

Suggested change
*ppMD = pMD;
printf("Found UCO method %s on type %s\n", methodName, fullQualifiedTypeName);
return;
}
}
printf("Did not find UCO method %s on type %s, looking for a method with the given name\n", methodName, fullQualifiedTypeName);
*ppMD = pMD;
#ifdef _DEBUG
printf("Found UCO method %s on type %s\n", methodName, fullQualifiedTypeName);
#endif // _DEBUG
return;
}
}
#ifdef _DEBUG
printf("Did not find UCO method %s on type %s, looking for a method with the given name\n", methodName, fullQualifiedTypeName);
#endif // _DEBUG

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings February 18, 2026 12:52
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 75 out of 76 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/tests/JIT/Directed/Misc/function_pointer/MutualThdRecur-fptr.il:14

  • This IL file now declares Microsoft.DotNet.XUnitExtensions, System.Runtime, and TestLibrary twice in the extern list. Duplicate .assembly extern entries are easy to overlook and can break ilasm/build or cause confusing metadata. Remove the duplicate declarations and keep a single extern per assembly.

Comment on lines +206 to +209
# Set default for RunWithNodeJS when using wasm architecture
if [ "$buildArch" = "wasm" ] && [ -z "$RunWithNodeJS" ]; then
export RunWithNodeJS=1
fi
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RunWithNodeJS is defaulted on any buildArch=wasm, even when buildOS=wasi is explicitly selected. That will pass --node into run.py and set RunWithNodeJS=1 for WASI runs, but NodeJS is only applicable to browser/wasm execution. Consider gating the default to the browser scenario only (e.g., only when buildOS is unset or equals browser).

Copilot uses AI. Check for mistakes.
Comment on lines +6200 to +6205
printf("Found UCO method %s on type %s\n", methodName, fullQualifiedTypeName);
return;
}
}

printf("Did not find UCO method %s on type %s, looking for a method with the given name\n", methodName, fullQualifiedTypeName);
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new printf diagnostics in LookupUnmanagedCallersOnlyMethodByName will emit to stdout on every lookup, which can severely impact performance and pollute test output/logs. Please remove these prints or gate them behind an existing logging facility/conditional compilation (e.g., a debug-only or feature-specific trace macro).

Suggested change
printf("Found UCO method %s on type %s\n", methodName, fullQualifiedTypeName);
return;
}
}
printf("Did not find UCO method %s on type %s, looking for a method with the given name\n", methodName, fullQualifiedTypeName);
return;
}
}

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-Infrastructure-coreclr NO-REVIEW Experimental/testing PR, do NOT review it

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants

Comments