Closed kpreisser closed 18 hours ago
Tagging subscribers to this area: @dotnet/area-system-reflection-emit See info in area-owners.md if you want to be subscribed.
When running the Unit Tests of Jurassic, they succeed when running with .NET 8.0.11, but when changing the target framework to net9.0
, a number of tests are failing, e.g. BitwiseAnd
. I think that the test failures might show the underlying cause of why running the TypeScript compiler in my repro app is producing the incorrect errors.
The BitwiseAnd
tests fails due to the changed JIT behavior of floating-point-to-integer conversion, which is noted in the Breaking Changes in .NET 9.0 document:
generator.Emit(OpCodes.Ldc_I4, 7);
generator.Emit(OpCodes.Conv_R8);
generator.Emit(OpCodes.Neg);
generator.Emit(OpCodes.Conv_U4);
or, in C#:
double d2 = -7;
uint u2 = unchecked((uint)d2);
In .NET 8.0, this results in 0xFFFFFFF9
, whereas in .NET 9.0, this results in 0
. So it looks like this may be caused by an intentional breaking change in the JIT about fp-to-int conversion, and may need to be fixed in Jurassic.
The BitwiseAnd tests fails due to the changed JIT behavior of floating-point-to-integer conversion, which is noted in the Breaking Changes in .NET 9.0 document:
Yes the regression is from adding saturating behavior to the hardware intrinsics that convert floating point values to integer values. I verified the regression locally by building before and after for the commit for that PR.
So it looks like this may be caused by an intentional breaking change in the JIT about fp-to-int conversion, and may need to be fixed in Jurassic.
Yes I suggest filing an issue there.
PTAL @tannergooding @khushal1996
Thank you! I filed paulbartrum/jurassic#228 to fix this in Jurassic.
@steveharter This does look like an effect of floating point to Integer conversion change made in .NET 9. The effect mentioned here is exactly what was changed.
https://github.com/dotnet/runtime/pull/97529 is the change made in .NET.
double d2 = -7;
uint u2 = unchecked((uint)d2);
The above PR will change the value of u2
from 0xFFFFFFF9
to 0
.
Let me know if something needs to be looked at from .NET POV.
Let me know if something needs to be looked at from .NET POV.
There shouldn't be. The code in Jurassic that was depending on this behavior was effectively "already broken".
That is, it would already fail on other hardware where the conversion behavior differed such as Arm64, WASM, or even an x64 machine with AVX512 support (where native unsigned conversion
instructions existed).
We didn't even strictly guarantee the behavior on downlevel x64 hardware, and it could fail due to other considerations such as constant folding or other optimizations that occurred at runtime or compile time. I believe the behavior between x86 and x64 even historically differed at one point, until we moved towards normalizing things more.
Description
Hi!
We are using Jurassic in a .NET application to run JavaScript code. Jurassic compiles JavaScript code into .NET IL (lightweight functions) using
System.Reflection.Emit
.After updating from .NET 8.0.11 to .NET 9.0.0, we found that running the TypeScript Compiler v4.5.5 with Jurassic causes incorrect errors to be reported by the TS compiler (see section Actual Behavior). With .NET 8.0.11, the TS compiler runs fine, just like if you run it on other JS runtimes, such as Node.js or in a browser.
It looks like there is some
kind of regressionbreaking change (see next post) in .NET 9.0 when emitting the IL code or JIT-compiling the IL code, but unfortunately I have no idea what the issue could be (as the TypeScript compiler is a very large JavaScript file).However, I then tested preview versions of .NET 9.0, and found that the issue appears to first occur with .NET 9.0.0-preview.4.24266.19, whereas it still works correctly with .NET 9.0.0-preview.3.24172.9.
I tested this on Windows 11 Version 24H2 (Build 26100.2314) x64, as well as on Ubuntu 24.04 x64.
Reproduction Steps
I created a console application that reproduces the issue. You can find it here: https://github.com/kpreisser/Repro-Net90-Jurassic-TSC-Error/
dotnet run
.Expected behavior
The app should complete without error (ExitCode=0) and should output a text like the following:
The above output is from running with .NET 9.0.0-preview.3.24172.9, which still works correctly.
Actual behavior
The app throws an
InvalidOperationException
due to the TypeScript Compiler reporting several wrong errors about TS interfaces being extended incorrectly:The above output is from running with .NET 9.0.0-preview.4.24266.19, which is the first preview of .NET 9.0 that shows the error.
Regression?
Yes, this worked correctly in .NET 8.0.11, and worked still correctly in .NET 9.0.0-preview.3.24172.9.
Known Workarounds
I don't know of any workarounds; compiler settings that can be set in the project file, such as
CETCompat
,TieredCompilation
,TieredCompilationQuickJit
didn't seem to change the behavior. Also, the behavior is the same when running inDebug
(without optimizations) andRelease
(with optimizations) configurations.Configuration
9.0.0-preview.4.24266.19
(x64)9.0.0
(x64)Other information
No response