Closed
Description
Description
When a very large C# method is encountered the interpreter tries to optimize that method, seemingly fails to do so and leaks memory every time the method is invoked, eventually exhausing the wasm heap.
Reproduction Steps
Build an app with the following t4 template:
<#@template language="C#"#>
<#@output extension="g.cs" #>
public class LargeMethodTest
{
public static Test(string value)
{
int value = 0;
switch(value)
{
<# for(int i=0; i<20000; i++) { #>
case "<#= i #>":
value++;
break;
<# } #>
default:
break;
}
}
}
Then create a loop over the Test
method:
staticvoid TestLargeSwitchCase()
{
var sw = Stopwatch.StartNew();
// Over 1000 iterations so that tiering kicks in
for (int i = 0; i < 2000; i++)
{
LargeMethodTest.Test("42");
}
Console.WriteLine($"Elapsed: {sw.Elapsed}");
}
Expected behavior
The code does not fail and runs to the end.
Actual behavior
The app fails as follows:
Cannot enlarge memory, asked to go up to 4294918144 bytes, but the limit is 4294901760 bytes!
_emscripten_resize_heap @ dotnet.native.js:4293
$sbrk @ dotnet.native.wasm:0x2ce8fa
$dlmalloc @ dotnet.native.wasm:0x2cc5b5
$monoeg_malloc @ dotnet.native.wasm:0x9fbaf
$mono_mempool_alloc @ dotnet.native.wasm:0x119464
$interp_link_bblocks @ dotnet.native.wasm:0x8d21e
$handle_branch @ dotnet.native.wasm:0x8f585
$generate_code @ dotnet.native.wasm:0x85cbd
$generate @ dotnet.native.wasm:0x9306d
$mono_interp_transform_method @ dotnet.native.wasm:0x92b30
$tier_up_method @ dotnet.native.wasm:0x9c627
$mono_interp_tier_up_frame_enter @ dotnet.native.wasm:0x9c37b
$mono_interp_exec_method @ dotnet.native.wasm:0x762dc
$interp_entry @ dotnet.native.wasm:0x7bbad
$interp_entry_instance_1 @ dotnet.native.wasm:0x7bdb8
$aot_instances_aot_wrapper_gsharedvt_in_sig_void_this_obj
Each invocation of the method will show a trace like this one:
Regression?
Not sure, it may have worked before tiering.
Known Workarounds
Use smaller methods
Configuration
.NET 8 RC1
Other information
No response