-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
Description
Hey, I am currently experimenting with a custom programming language with the Compiler and VM implementation written in .NET, and I am not quite sure what is wrong.
I have noticed after wanting to check if there is a performance difference between .NET 9 and the latest .NET 10 preview 5, that the VM had a weird runtime error when doing a binary MULTIPLY operation.
The weird thing is that the error place changes if I change the overloaded operator * from [MethodImpl(MethodImplOptions.AggressiveInlining)] to [MethodImpl(MethodImplOptions.NoInlining)]. Then the exception occurs for example for an ADD operation etc.
I also couldn't hit the break point and the test log said both IsNumber props returned true:
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Value operator *(Value left, Value right)
{
if (left.IsNumber && right.IsNumber)
{
return new Value(left.AsNumber() * right.AsNumber());
}
Console.WriteLine($"Left: {left.IsNumber}, Right: {right.IsNumber}");
throw new RuntimeException($"Unsupported operator type * for left '{left}' and right '{right}'");
}The problem only occurs in a release build, in a debug build it works.
I have got the following JIT disassembly (part of it) from 10.0.100-preview.3.25201.16 and 10.0.100-preview.4.25258.110 (there was no difference between 10.0.100-preview.4.25258.110 to 10.0.100-preview.5.25277.114).
The JIT disasm is from the main Execute method that contains the VM main loop switch in a release build.
Some noise like:
10.0.100-preview.3.25201.16:
G_M000_IG34:
mov rcx, gword ptr [r14+0x10]
mov rdx, 0xD1FFAB1E
and rdx, rsi
mov r8, 0xD1FFAB1E
cmp rdx, r8
je SHORT G_M000_IG36 call CORINFO_HELP_STRCNS10.0.100-preview.4.25258.110:
G_M000_IG34:
mov rcx, gword ptr [r14+0x10]
mov rdx, rsi
not rdx
mov r8, 0xD1FFAB1E
and rdx, r8
je SHORT G_M000_IG36 call [CORINFO_HELP_STRCNS]But the largest diff was this (middle part):
10.0.100-preview.3.25201.16:
G_M000_IG67:
call [VmTest.VmObjectList:get_Items():System.Collections.Generic.List`1[VmTest.Value]:this]
mov r14, rax
lea rcx, [rbp-0x88]
call [VmTest.Value:AsNumber():double:this]
vmovddup xmm1, xmm0
vmovddup xmm2, xmm0
vmovddup xmm0, xmm0
vcmppd xmm1, xmm2, xmm1, 0
vandpd xmm0, xmm1, xmm0
vcmppd xmm1, xmm0, xmmword ptr [reloc @RWD00], 13
vcvttsd2si ecx, xmm0
vmovd xmm0, ecx
vpbroadcastd xmm0, xmm0
vpblendvb xmm0, xmm0, xmmword ptr [reloc @RWD16], xmm1
vmovd edx, xmm0
mov rcx, r14
cmp dword ptr [rcx], ecx
call [System.Collections.Generic.List`1[VmTest.Value]:get_Item(int):VmTest.Value:this]
mov rdx, rax
mov rcx, rbx
call [VmTest.VirtualMachine:Push(VmTest.Value):this]
jmp G_M000_IG14810.0.100-preview.4.25258.110:
G_M000_IG67:
call [VmTest.VmObjectList:get_Items():System.Collections.Generic.List`1[VmTest.Value]:this]
mov r14, rax
lea rcx, [rbp-0x88]
call [VmTest.Value:AsNumber():double:this]
vcmpsd xmm1, xmm0, xmm0, 7
vandpd xmm1, xmm1, xmm0
mov ecx, 0xD1FFAB1E
vcvttsd2si edx, xmm1
vucomisd xmm0, qword ptr [reloc @RWD00]
cmovb ecx, edx
mov edx, ecx
mov rcx, r14
cmp dword ptr [rcx], ecx
call [System.Collections.Generic.List`1[VmTest.Value]:get_Item(int):VmTest.Value:this]
mov rdx, rax
mov rcx, rbx
call [VmTest.VirtualMachine:Push(VmTest.Value):this]
jmp G_M000_IG148These are a few times in the diff. The problem seems to occur with and without native AOT.
Reproduction Steps
If desired I can send the project to an MS employee or maybe try to create a minimal project and create a public repository. I want to have it as an open-source project, but currently it's more of a testing ground.
Expected behavior
The executed program should execute like before with 10.0.100-preview.3.25201.16 and .NET 9.
Source code of the custom language:
number counter = 0
for i in 0..1_500
counter += 1
WriteLine("Counter: {counter}")
Output working program (with .NET 9 and .NET 10 preview 3):
FunctionRegistry:Load took 5 ms
ClassRegistry:Load took 1 ms
Counter: 1500Actual behavior
Source code of the custom language:
number counter = 0
for i in 0..1_500
counter += 1
WriteLine("Counter: {counter}")
Output of not working program (with .NET 10 preview 4):
FunctionRegistry:Load took 5 ms
ClassRegistry:Load took 1 ms
Unhandled exception. VmTest.Exceptions.RuntimeException: RuntimeError: Unsupported operator type + for left '1427' and right '1'
at VmTest.VirtualMachine.Execute() in C:\Users\{USER}\source\repos\VmTest\VmTest\VirtualMachine.cs:line 314
at Program.<Main>$(String[] args) in C:\Users\{USER}\source\repos\VmTest\VmTest\Program.cs:line 40As you can see, the left and right operand are both ints (numbers in my language).
Interesting enough is that it does not occur with a lower iteration count like for example 1000.
Regression?
Maybe, it woks with -c Release with 10.0.100-preview.3.25201.16 and fails with 10.0.100-preview.4.25258.110
Known Workarounds
Use .NET 10 preview 3 or run in debug mode.
Configuration
OS: Windows 11 23H2
Architecture: x64
Working:
.NET 9 and 10.0.100-preview.3.25201.16
Not working in release mode (works in debug mode):
= 10.0.100-preview.4.25258.110
Other information
If you have any questions or things I can provide or test please let me know.