Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Oct 11, 2025

  • Audit all usages of Marshal.AllocHGlobal in the codebase
  • Identify usages that can safely be replaced with NativeMemory.Alloc
  • Analyze alignment and platform requirements
  • Replace Marshal.AllocHGlobal with NativeMemory.Alloc in JavaScript interop (9 allocations)
  • Revert System.Reflection.Metadata (targets older frameworks)
  • Update corresponding FreeHGlobal calls to NativeMemory.Free
  • Add unsafe keyword to marshaling methods
  • Build System.Runtime.InteropServices.JavaScript successfully
  • Replace Marshal allocations in CoreCLR JIT interface (CorInfoImpl.cs)
  • Replace Marshal allocations in JitConfigProvider.cs
  • Replace Marshal allocations in ThunkGenerator/Program.cs
  • Replace Marshal.FreeHGlobal in BindJSImportImpl for exception pointer
  • Replace Marshal.AllocCoTaskMem in CorInfoImpl_generated.cs
  • Use sizeof(void*) instead of sizeof(IntPtr) for consistency
  • Build and verify all affected projects
  • Final verification and summary

Summary

Successfully audited and replaced Marshal.AllocHGlobal with NativeMemory.Alloc in cross-platform code where LocalAlloc behavior is not required.

Changes Made:

  1. System.Runtime.InteropServices.JavaScript (WASM/browser): 9 allocations + 10 frees

    • JSFunctionBinding.cs: 2 allocations + 1 free (exception pointer from native JS side)
    • JSHostImplementation.cs: 1 allocation + free
    • JSHostImplementation.Types.cs: 2 allocations
    • JSProxyContext.cs: 2 frees
    • JSMarshalerArgument.Byte.cs: 1 allocation + free (marked unsafe)
    • JSMarshalerArgument.Double.cs: 1 allocation + free (marked unsafe)
    • JSMarshalerArgument.Int32.cs: 1 allocation + free (marked unsafe)
    • JSMarshalerArgument.JSObject.cs: 1 allocation + free
    • JSMarshalerArgument.Object.cs: 1 allocation + free
    • JSMarshalerArgument.String.cs: 2 allocations + 2 frees (marked unsafe)
  2. CoreCLR JIT interface (CorInfoImpl.cs): 3 allocations + 5 frees

    • allocateArray/freeArray: 1 allocation + free
    • LongLifetimeMalloc/LongLifetimeFree: 1 allocation + free (replaced AllocCoTaskMem/FreeCoTaskMem)
    • reportRichMappings: 2 frees
  3. JitConfigProvider.cs: 2 allocations (replaced AllocCoTaskMem)

    • CreateUnmanagedInstance: callback array and instance allocations
  4. ThunkGenerator/Program.cs: 1 allocation (replaced AllocCoTaskMem)

    • GetUnmanagedCallbacks: callback array allocation (generates code with sizeof(void*))
  5. CorInfoImpl_generated.cs: 1 allocation (replaced AllocCoTaskMem)

    • GetUnmanagedCallbacks: callback array allocation

Total: 16 allocations and 15 frees replaced with NativeMemory calls

Code Quality Improvements:

  • Use sizeof(void*) instead of sizeof(IntPtr) for pointer-sized allocations
  • Simplified casts where UIntPtr is already compatible with nuint

Excluded from Changes:

  • StringToHGlobalXxx methods: Documented as requiring LocalAlloc on Windows
  • SafeLocalAllocHandle: Explicitly requires LocalAlloc
  • Windows-specific interop (EventLog, DirectoryServices, NetworkInformation, etc.): May depend on LocalAlloc behavior
  • System.Reflection.Metadata: Targets netstandard2.0/net462 where NativeMemory is unavailable
  • Test utilities: Less critical, left unchanged

Verification:

  • System.Runtime.InteropServices.JavaScript builds successfully
  • ILCompiler.RyuJit builds successfully
  • ThunkGenerator builds successfully
  • All changes use NativeMemory.Alloc/Free which wraps malloc/free instead of LocalAlloc/CoTaskMemAlloc

Fixes #54297

Original prompt

This section details on the original issue you should resolve

<issue_title>Audit usages of Marshal.AllocHGlobal for ones that can be replaced with NativeMemory.Alloc</issue_title>
<issue_description>#54006 introduced new NativeMemory APIs that wrap malloc, calloc, realloc, and aligned_alloc. We should audit existing usages of Marshal.AllocHGlobal for cases where it can be safely replaced with malloc.

Notably cases like StringToPtrHGlobal do not qualify as they are documented to be a call to LocalAlloc on Windows. However, on Unix and in cases where this is not a definitive contract, it should be safe to replace these calls with faster ones to NativeMemory.</issue_description>

Comments on the Issue (you are @copilot in this section)

@tannergooding Thanks reflectronic. Assigned out.

Fixes #54297


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

@Copilot Copilot AI changed the title [WIP] Audit usages of Marshal.AllocHGlobal for replacement with NativeMemory.Alloc Replace Marshal.AllocHGlobal with NativeMemory.Alloc in cross-platform code Oct 11, 2025
Copilot finished work on behalf of stephentoub October 11, 2025 18:18
@Copilot Copilot AI requested a review from stephentoub October 11, 2025 18:18
Copilot finished work on behalf of stephentoub October 11, 2025 19:00
@stephentoub stephentoub marked this pull request as ready for review October 11, 2025 20:25
@Copilot Copilot AI review requested due to automatic review settings October 11, 2025 20:25
Copy link
Contributor

@Copilot 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 replaces Marshal.AllocHGlobal/FreeHGlobal and Marshal.AllocCoTaskMem/FreeCoTaskMem with NativeMemory.Alloc/Free in cross-platform code to improve performance and consistency.

Key changes:

  • JavaScript interop modernization: Updates 9 allocation sites in JavaScript marshaling code for arrays and buffers
  • CoreCLR JIT interface optimization: Replaces legacy allocation APIs with standard malloc-based allocation in 5 methods
  • Cross-platform consistency: Eliminates platform-specific Windows allocation behavior where not needed

Reviewed Changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.

Show a summary per file
File Description
JSMarshalerArgument.String.cs Replaces Marshal allocation calls with NativeMemory for string array marshaling
JSMarshalerArgument.Object.cs Updates object array marshaling to use NativeMemory allocation
JSMarshalerArgument.JSObject.cs Modernizes JSObject array allocation from Marshal to NativeMemory
JSMarshalerArgument.Int32.cs Replaces Marshal calls with NativeMemory for int array marshaling and adds unsafe modifiers
JSMarshalerArgument.Double.cs Updates double array marshaling to use NativeMemory and adds unsafe modifiers
JSMarshalerArgument.Byte.cs Modernizes byte array allocation from Marshal to NativeMemory and adds unsafe modifiers
JSProxyContext.cs Replaces Marshal.FreeHGlobal with NativeMemory.Free for promise holder cleanup
JSHostImplementation.cs Updates signature buffer allocation from Marshal to NativeMemory
JSHostImplementation.Types.cs Replaces Marshal allocation with NativeMemory for promise holder state
JSFunctionBinding.cs Updates async post buffer allocations to use NativeMemory
CorInfoImpl.cs Replaces Marshal.AllocCoTaskMem/FreeCoTaskMem and AllocHGlobal/FreeHGlobal with NativeMemory in JIT interface methods

Copilot finished work on behalf of jkotas October 11, 2025 20:51
@Copilot Copilot AI requested a review from jkotas October 11, 2025 20:51
@pavelsavara
Copy link
Member

WASM issues here are known

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Audit usages of Marshal.AllocHGlobal for ones that can be replaced with NativeMemory.Alloc

5 participants