dotnet / runtimelab

This repo is for experimentation and exploring new ideas that may or may not make it into the main dotnet/runtime repo.
MIT License
1.42k stars 199 forks source link

[NativeAOT-LLVM] Enable tests and fix bugs #2307

Open SingleAccretion opened 1 year ago

SingleAccretion commented 1 year ago

1) We should never produce "naked" undef/poison values. These can be produced implicitly when doing things like (int)float.NaN. Open questions:

SingleAccretion commented 1 year ago

Reflection smoke test fails on creating a delegate with byref-likes involved. Likely a codegen bug.

Turns out not. This is the RhGetCodeTarget NYI. It is non-trivial to implement RhGetCodeTarget on WASM with current LLVM features. Ideas: 1) Add an LLVM+linker feature that allows fine-grained control over how the indirect function table is constructed. This would allow for an efficient lookup scheme (e. g.: continuous range for unboxing stubs and their targets, stubs are even, targets are odd). 2) Same as 1, but can be done today, at greater complexity cost, by rewriting and/or creating custom .wasm files. 3) Lookup data structures (similar to how native unwind info is used to store this information for instantiating unboxing stubs on Unix). Remains to be seen how expensive this would be size-wise. Note: RhGetCodeTarget is meant to be "cheap" as it is used in delegate equality comparisons. 4) Rewrite code such that RhGetCodeTarget is not needed, e. g. put both the unboxed and boxed entry points into the reflection invoke map. It is not clear how feasible that would be.

SingleAccretion commented 1 year ago

We definitely need System.Runtime.Tests

Small progress report: this is not going too smoothly. We have a few compiler bugs, with those fixed, the tests do compile in Release, but not in Debug because wasm-emscripten-finalize.exe consumes way too much memory (well - it did compile in ~5 hours, but only after OOMing the shell and making the rest of the system hardly usable for that time period).

yowl commented 1 year ago

https://github.com/emscripten-core/emscripten/issues/15921 might be the same , unfortunately it is not resolved.

SingleAccretion commented 1 year ago

It turns out that solving the wasm-emscripten-finalize.exe problem is relatively straightforward: just adding -sWASM_BIGINT is enough to obviate the need to run it (at least in Debug). This speeds builds up by a lot. I think we should do this by default, since we turn EH on by default, and JS BigInt integration has universally better compatibility.

Fixing that, the build builds, yet the runtime complains:

Aborted(CompileError: WebAssembly.instantiate(): Compiling function #54904:"System_Runtime_Tests_System_Text_Tests_RuneTest..." failed: local count too large @+64952968)

Debug WASM code as produced by LLVM tends to be pretty hungry on locals, so not too surprising we're hitting the limits here (which are small, BTW, just 50K locals). This will require deeper investigation whether something can be done on our side with less naive codegen or this needs a more fundamental LLVM fix.

yowl commented 1 year ago

I think we should do this by default

Agree, don't see why not.

SingleAccretion commented 1 year ago

RhGetCodeTarget

I have opened https://github.com/llvm/llvm-project/issues/63449 for the zero-cost implementation way; let's see what LLVM maintainers think.

In the meantime, I'll add a separate mapping table, it is 8/50%+ bytes per each unboxing thunk, but we shouldn't have too many of these, e. g. HelloWasm has ~500, so 4K of additional data.

SingleAccretion commented 1 year ago

Another progress report on libraries tests: it's complicated.

The main issue is that the SingleFileTestRunner, and more importantly the underlying Xunit code (test discoverer) used for NAOT assumes a threaded environment. So we need something custom. One obvious option is to use what Mono uses - an XHarness-based runner. It looks a bit intimidating on first glance, however (consider https://github.com/dotnet/runtime/pull/81052 that is a 3K+ lines PR, plus the fact main code lives in another repo). Another option is to write yet another runner, which seems the most realistic at this point in time.

yowl commented 1 year ago

Does considering moving the threads implementation forwards first have any merit? (so Xunit can be used)

SingleAccretion commented 1 year ago

It's a possibility, I suppose, but I don't see us offering it as the mainstream (and only) option for a few years still, so we need to be able to run tests both ways either way.

jkotas commented 1 year ago

The main issue is that the SingleFileTestRunner, and more importantly the underlying Xunit code (test discoverer) used for NAOT assumes a threaded environment. So we need something custom. One obvious option is to use what Mono uses - an XHarness-based runner.

How does the XHarness-based runner solve the problem that prevents SingleFileTestRunner from working?

I would strongly prefer to adjust one of the existing runners instead of introducing yet another one.

SingleAccretion commented 1 year ago

How does the XHarness-based runner solve the problem that prevents SingleFileTestRunner from working?

It implements test discovery in a threadless manner:

https://github.com/lewing/xharness/blob/cbd98edd36d8763026152cfee248aeb1537b1d4b/src/Microsoft.DotNet.XHarness.TestRunners.Xunit/ThreadlessXunitTestRunner.cs#L89-L104

I would strongly prefer to adjust one of the existing runners instead of introducing yet another one.

Turns out it's not actually difficult to integrate the Mono runner anyway - I now have at least one suite running "successfully" (failing with what looks like a GC hole an allocation helper bug).

SingleAccretion commented 9 months ago

With the recent globalization work, I've ran S.R.Tests again, and many pass, but we ultimately fail on a fail-fast from an NRE in a timer finalizer:

Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.DispatchException (wasm://wasm/System.Runtime.Tests.wasm-18ac67d6:wasm-function[10521]:0x2ffd92)
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.RhpThrowEx (wasm://wasm/System.Runtime.Tests.wasm-18ac67d6:wasm-function[91857]:0x19b4371)
    at System.Runtime.Tests.wasm.S.P.CoreLib.Internal.Runtime.CompilerHelpers.ThrowHelpers.ThrowNullReferenceException (wasm://wasm/System.Runtime.Tests.wasm-18ac67d6:wasm-function[91856]:0x19b4314)
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Threading.PeriodicTimer.Finalize (wasm://wasm/System.Runtime.Tests.wasm-18ac67d6:wasm-function[2601]:0xe15d2)
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime..Finalizer.RhpProcessFinalizersAndReturn (wasm://wasm/System.Runtime.Tests.wasm-18ac67d6:wasm-function[100074]:0x1b34098)
    at System.Runtime.Tests.wasm.RhWaitForPendingFinalizers (wasm://wasm/System.Runtime.Tests.wasm-18ac67d6:wasm-function[741]:0xa57c8)
    at System.Runtime.Tests.wasm.System.Runtime.Tests.System.Tests.WeakReferenceTests.Generic (wasm://wasm/System.Runtime.Tests.wasm-18ac67d6:wasm-function[74769]:0x14b2033)

Interestingly, WASI also fails there.

SingleAccretion commented 9 months ago

Getting past the odd timer failure, S.R.Tests on Browser mostly work, after some minor plumbing:

=== TEST EXECUTION SUMMARY ===
Total: 62583, Errors: 0, Failed: 27, Skipped: 139, Time: 63.0332636s
; And then crashes trying to write XML for some reason

Failures are in more or less expected places:

[FAIL] System.Tests.ExceptionTests.Exception_TargetSite
Assert.Equal() Failure: Values differ
Expected: RuntimeNamedMethodInfo`1 { DeclaringType = typeof(System.Tests.ExceptionTests), IsStatic = True, ReflectedType = typeof(System.Tests.ExceptionTests) }
Actual:   null
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.DispatchException (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[2768]:0xecb6f)
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.RhpThrowEx (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[91847]:0x168909f)
    at System.Runtime.Tests.wasm.xunit.assert.Xunit.Assert.Equal.4<System..Canon> (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[102980]:0x1b29e5b)
    at System.Runtime.Tests.wasm.xunit.assert.Xunit.Assert.Equal.2<System..Canon> (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[102981]:0x1b2acb0)

* ExceptionTests - reported call stack:
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.DispatchException (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[2768]:0xecb6f)
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.RhpThrowEx (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[91847]:0x168909f)
    at System.Runtime.Tests.wasm.System.Runtime.Tests.System.Tests.ExceptionTests.ThrowException (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[62974]:0xf191c9)
    at System.Runtime.Tests.wasm.System.Runtime.Tests.System.Tests.ExceptionTests.ThrowAndRethrowOtherMethod (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[62983]:0xf19d20)

[FAIL] System.Tests.ExceptionTests.ThrowStatementDoesNotResetExceptionStackLineOtherMethod
Assert.Equal() Failure: Strings differ
           ↓ (pos 0)
Expected: "ThrowAndRethrowOtherMethod"
Actual:   "wasm-197266d6:wasm-function[91847]:0x1689"···
           ↑ (pos 0)
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.DispatchException (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[2768]:0xecb6f)
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.RhpThrowEx (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[91847]:0x168909f)
    at System.Runtime.Tests.wasm.xunit.assert.Xunit.Assert.Equal.17 (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[69191]:0x122accb)
    at System.Runtime.Tests.wasm.System.Runtime.Tests.System.Tests.ExceptionTests.VerifyCallStack (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[62979]:0xf197cc)

* ExceptionTests - reported call stack:
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.DispatchException (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[2768]:0xecb6f)
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.RhpThrowEx (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[91847]:0x168909f)
    at System.Runtime.Tests.wasm.System.Runtime.Tests.System.Tests.ExceptionTests.ThrowAndRethrowSameMethod (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[62978]:0xf19583)
    at System.Runtime.Tests.wasm.System.Runtime.Tests.System.Tests.ExceptionTests.ThrowStatementDoesNotResetExceptionStackLineSameMethod (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[62977]:0xf19445)

[FAIL] System.Tests.ExceptionTests.ThrowStatementDoesNotResetExceptionStackLineSameMethod
Assert.Equal() Failure: Strings differ
           ↓ (pos 0)
Expected: "ThrowAndRethrowSameMethod"
Actual:   "wasm-197266d6:wasm-function[2768]:0xecb6f"···
           ↑ (pos 0)
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.DispatchException (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[2768]:0xecb6f)
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.RhpThrowEx (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[91847]:0x168909f)
    at System.Runtime.Tests.wasm.xunit.assert.Xunit.Assert.Equal.17 (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[69191]:0x122accb)
    at System.Runtime.Tests.wasm.System.Runtime.Tests.System.Tests.ExceptionTests.VerifyCallStack (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[62979]:0xf197cc)

[FAIL] System.Tests.ExceptionTests.Exception_TargetSite_Rethrow
System.NullReferenceException : Object reference not set to an instance of an object.
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.DispatchException (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[2768]:0xecb6f)
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.RhpThrowEx (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[91847]:0x168909f)
    at System.Runtime.Tests.wasm.S.P.CoreLib.Internal.Runtime.CompilerHelpers.ThrowHelpers.ThrowNullReferenceException (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[89614]:0x1626938)
    at System.Runtime.Tests.wasm.System.Runtime.Tests.System.Tests.ExceptionTests.Exception.TargetSite.Rethrow (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[62976]:0xf193e1)

[FAIL] System.Tests.ExceptionTests.Exception_TargetSite_OtherMethod
System.NullReferenceException : Object reference not set to an instance of an object.
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.DispatchException (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[2768]:0xecb6f)
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.RhpThrowEx (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[91847]:0x168909f)
    at System.Runtime.Tests.wasm.S.P.CoreLib.Internal.Runtime.CompilerHelpers.ThrowHelpers.ThrowNullReferenceException (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[89614]:0x1626938)
    at System.Runtime.Tests.wasm.System.Runtime.Tests.System.Tests.ExceptionTests.Exception.TargetSite.OtherMethod (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[62975]:0xf192d5)

[FAIL] System.Runtime.CompilerServices.Tests.RuntimeFeatureTests.DynamicCode_Browser
Assert.True() Failure
Expected: True
Actual:   False
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.DispatchException (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[2768]:0xecb6f)
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.RhpThrowEx (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[91847]:0x168909f)
    at System.Runtime.Tests.wasm.xunit.assert.Xunit.Assert.True.2 (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[65930]:0x1041906)
    at System.Runtime.Tests.wasm.System.Runtime.Tests.System.Runtime.CompilerServices.Tests.RuntimeFeatureTests.DynamicCode.Browser (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[59878]:0xdc4131)

; Codegen bugs sneaking in?
[FAIL] System.Tests.TimeSpanTests.Division(timeSpan: 366.00:00:00, factor: -2.7182818284590451, expected: -994.21:23:15.2922633)
Assert.Equal() Failure: Values are not within 14 decimal places
Expected: -2.71828182845905 (rounded from -2.7182818284590451)
Actual:   -2.7182818284590402 (rounded from -2.7182818284590446)
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.DispatchException (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[2768]:0xecb6f)
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.RhpThrowEx (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[91847]:0x168909f)
    at System.Runtime.Tests.wasm.xunit.assert.Xunit.Assert.Equal.5 (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[99645]:0x1a46f4e)
    at System.Runtime.Tests.wasm.System.Runtime.Tests.System.Tests.TimeSpanTests.Division (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[64556]:0xfab4b1)

[FAIL] System.Tests.TimeSpanTests.NamedDivision(timeSpan: 366.00:00:00, factor: -2.7182818284590451, expected: -994.21:23:15.2922633)
Assert.Equal() Failure: Values are not within 14 decimal places
Expected: -2.71828182845905 (rounded from -2.7182818284590451)
Actual:   -2.7182818284590402 (rounded from -2.7182818284590446)
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.DispatchException (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[2768]:0xecb6f)
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.RhpThrowEx (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[91847]:0x168909f)
    at System.Runtime.Tests.wasm.xunit.assert.Xunit.Assert.Equal.5 (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[99645]:0x1a46f4e)
    at System.Runtime.Tests.wasm.System.Runtime.Tests.System.Tests.TimeSpanTests.NamedDivision (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[64562]:0xfabaa8)

; Some PeriodicTimerTests failures which are expected due to NYI
;

[FAIL] System.Tests.TimeZoneInfoTests.GetSystemTimeZones
Assert.Contains() Failure: Filter not matched in collection
Collection: [TimeZoneInfo { }, TimeZoneInfo { }, TimeZoneInfo { }]
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.DispatchException (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[2768]:0xecb6f)
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.RhpThrowEx (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[91847]:0x168909f)
    at System.Runtime.Tests.wasm.xunit.assert.Xunit.Assert.Contains.1<System..Canon> (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[97532]:0x190fc7e)
    at System.Runtime.Tests.wasm.System.Runtime.Tests.System.Tests.TimeZoneInfoTests.GetSystemTimeZones (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[64627]:0xfd3d55)

[FAIL] System.Runtime.ExceptionServices.Tests.ExceptionDispatchInfoTests.StaticThrow_UpdatesStackTraceAppropriately
System.ArgumentNullException : Value cannot be null. (Parameter 'input')
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.DispatchException (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[2768]:0xecb6f)
    at System.Runtime.Tests.wasm.S.P.CoreLib.System.Runtime.EH.RhpThrowEx (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[91847]:0x168909f)
    at System.Runtime.Tests.wasm.System.Text.RegularExpressions.System.Text.RegularExpressions.ThrowHelper.ThrowArgumentNullException (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[73940]:0x131bd6a)
    at System.Runtime.Tests.wasm.System.Text.RegularExpressions.System.Text.RegularExpressions.Regex.Count (wasm://wasm/System.Runtime.Tests.wasm-197266d6:wasm-function[101824]:0x1ad1d23)