Skip to content

[NativeAOT-LLVM] Exclude ExceptionHandling.cs from the WASM build and pass -O1 to emcc #3133

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: feature/NativeAOT-LLVM
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -588,8 +588,6 @@ The .NET Foundation licenses this file to you under the MIT license.
<CustomLinkerArg Condition="'$(NativeDebugSymbols)' != 'true'" Include="-Wl,--strip-all" />
<!-- TODO-LLVM: https://github.com/dotnet/runtimelab/issues/2752. -->
<!--<CustomLinkerArg Condition="'$(NativeDebugSymbols)' != 'true'" Include="-Wl,compress-relocations" />-->
<!-- see https://github.com/emscripten-core/emscripten/issues/16836 for the issue that means we have to force the linker to include these symbols before LTO -->
<!--<CustomLinkerArg Condition="'$(Optimize)' != 'true'" Include="$(WasmOptimizationSetting) -flto" /> -->
<CustomLinkerArg Condition="'$(IlcLlvmTarget)' != ''" Include="-target $(IlcLlvmTarget)" />
</ItemGroup>

Expand All @@ -601,13 +599,15 @@ The .NET Foundation licenses this file to you under the MIT license.
<CustomLinkerArg Include="-s GLOBAL_BASE=$(IlcWasmGlobalBase)" />
<CustomLinkerArg Include="-s TOTAL_STACK=$(IlcWasmStackSize)" />
<CustomLinkerArg Include="-s ERROR_ON_UNDEFINED_SYMBOLS=0" Condition="'$(IlcTreatWarningsAsErrors)' != 'true'" />
<CustomLinkerArg Condition="'$(WasmEnableJSBigIntIntegration)' == 'true'" Include="-s WASM_BIGINT=1" />
<CustomLinkerArg Condition="'$(IlcLlvmExceptionHandlingModel)' == 'cpp'" Include="-s DISABLE_EXCEPTION_CATCHING=0" />

<CustomLinkerArg Include="$(EmccFlags)" />
<CustomLinkerArg Include="-s WASM_BIGINT=1" Condition="'$(WasmEnableJSBigIntIntegration)' == 'true'" />
<CustomLinkerArg Include="-s DISABLE_EXCEPTION_CATCHING=0" Condition="'$(IlcLlvmExceptionHandlingModel)' == 'cpp'" />
<CustomLinkerArg Include="-s MAXIMUM_MEMORY=$(EmccMaximumHeapSize)" Condition="'$(EmccMaximumHeapSize)' != ''" />
<CustomLinkerArg Include="-s INITIAL_MEMORY=$(EmccInitialHeapSize)" Condition="'$(EmccInitialHeapSize)' != ''" />
<CustomLinkerArg Condition="'$(EmccEnableAssertions)' == 'true'" Include="-s ASSERTIONS=1" />
<CustomLinkerArg Include="-s ASSERTIONS=1" Condition="'$(EmccEnableAssertions)' == 'true'" />

<!-- See https://github.com/dotnet/runtimelab/issues/2357 for why we don't run wasm-opt (it would mangle our strack trace info). -->
<CustomLinkerArg Condition="'$(Optimize)' == 'true'" Include="-O1" />
<CustomLinkerArg Include="$(EmccFlags)" />
</ItemGroup>

<!-- wasm-ld only supports listing exports on the command line -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ private static void DispatchException(object exception, RhEHFrameType flags)
}
else
{
if (ShouldTypedClauseCatchThisException(exception, clause.ClauseType, false /* tryUnwrapException, not used for NATIVEAOT */))
if (ShouldTypedClauseCatchThisException(exception, clause.ClauseType))
{
goto FoundHandler;
}
Expand Down Expand Up @@ -869,4 +869,98 @@ public static int Parse(byte* pUnwindInfo, uint* pShadowFrameSize = null, void**
return (int)(pCurrent - pUnwindInfo);
}
}

// TODO-LLVM-Upstream: create ExceptionHandling.Common.cs and put the things below there.
internal static unsafe partial class EH
{
private enum RhEHFrameType
{
RH_EH_FIRST_FRAME = 1,
RH_EH_FIRST_RETHROW_FRAME = 2,
}

private enum RhEHClauseKind
{
RH_EH_CLAUSE_TYPED = 0,
RH_EH_CLAUSE_FAULT = 1,
RH_EH_CLAUSE_FILTER = 2,
RH_EH_CLAUSE_UNUSED = 3,
}

internal struct MethodRegionInfo
{
}

internal struct ExInfo
{
}

internal struct PAL_LIMITED_CONTEXT
{
}

[StackTraceHidden]
[RuntimeExport("RhExceptionHandling_FailedAllocation")]
public static void FailedAllocation(MethodTable* pEEType, bool fIsOverflow)
{
ExceptionIDs exID = fIsOverflow ? ExceptionIDs.Overflow : ExceptionIDs.OutOfMemory;

// Throw the out of memory exception defined by the classlib, using the input MethodTable*
// to find the correct classlib.

throw pEEType->GetClasslibException(exID);
}

private static bool ShouldTypedClauseCatchThisException(object exception, MethodTable* pClauseType)
{
return TypeCast.IsInstanceOfException(pClauseType, exception);
}

private static void OnFirstChanceExceptionViaClassLib(object exception)
{
IntPtr pOnFirstChanceFunction =
(IntPtr)InternalCalls.RhpGetClasslibFunctionFromEEType(exception.GetMethodTable(), ClassLibFunctionId.OnFirstChance);

if (pOnFirstChanceFunction == IntPtr.Zero)
{
return;
}

try
{
((delegate*<object, void>)pOnFirstChanceFunction)(exception);
}
catch when (true)
{
// disallow all exceptions leaking out of callbacks
}
}

private static void OnUnhandledExceptionViaClassLib(object exception)
{
IntPtr pOnUnhandledExceptionFunction =
(IntPtr)InternalCalls.RhpGetClasslibFunctionFromEEType(exception.GetMethodTable(), ClassLibFunctionId.OnUnhandledException);

if (pOnUnhandledExceptionFunction == IntPtr.Zero)
{
return;
}

try
{
((delegate*<object, void>)pOnUnhandledExceptionFunction)(exception);
}
catch when (true)
{
// disallow all exceptions leaking out of callbacks
}
}

#pragma warning disable IDE0060
internal static void FallbackFailFast(RhFailFastReason reason, object? unhandledException)
{
InternalCalls.RhpFallbackFailFast();
}
#pragma warning restore IDE0060
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,3 @@ FCIMPL0(void*, RhpGetLastPreciseVirtualUnwindFrame)
return static_cast<uint8_t*>(pShadowStack) - sizeof(void*);
}
FCIMPLEND

// We do not use these helpers. TODO-LLVM: exclude them from the WASM build.
FCIMPL4(void*, RhpCallCatchFunclet, void*, void*, void*, void*) { abort(); } FCIMPLEND
FCIMPL3(bool, RhpCallFilterFunclet, void*, void*, void*) { abort(); } FCIMPLEND
FCIMPL2(void, RhpCallFinallyFunclet, void*, void*) { abort(); } FCIMPLEND
Original file line number Diff line number Diff line change
Expand Up @@ -588,9 +588,12 @@
<Compile Include="$(RuntimeBasePath)System\Runtime\MethodTable.Runtime.cs">
<Link>Runtime.Base\src\System\Runtime\MethodTable.Runtime.cs</Link>
</Compile>
<Compile Include="$(RuntimeBasePath)System\Runtime\ExceptionHandling.cs">
<Compile Include="$(RuntimeBasePath)System\Runtime\ExceptionHandling.cs" Condition="'$(WasmAbi)' != 'true'">
<Link>Runtime.Base\src\System\Runtime\ExceptionHandling.cs</Link>
</Compile>
<Compile Include="$(RuntimeBasePath)System\Runtime\ExceptionHandling.wasm.cs" Condition="'$(WasmAbi)' == 'true'">
<Link>Runtime.Base\src\System\Runtime\ExceptionHandling.wasm.cs</Link>
</Compile>
<Compile Include="$(RuntimeBasePath)System\Runtime\InternalCalls.cs">
<Link>Runtime.Base\src\System\Runtime\InternalCalls.cs</Link>
</Compile>
Expand All @@ -612,9 +615,6 @@
<Compile Include="$(AotCommonPath)\Internal\Runtime\TransitionBlock.cs">
<Link>Common\TransitionBlock.cs</Link>
</Compile>
<Compile Include="$(RuntimeBasePath)System\Runtime\ExceptionHandling.wasm.cs" Condition="'$(WasmAbi)' == 'true'">
<Link>Runtime.Base\src\System\Runtime\ExceptionHandling.wasm.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup Condition="'$(InPlaceRuntime)' == 'true'">
<Compile Include="$(IntermediatesDir)\nativeaot\Runtime\Full\AsmOffsets.cs" Condition="'$(WasmAbi)' != 'true'" />
Expand Down
6 changes: 6 additions & 0 deletions src/tests/nativeaot/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,10 @@
<DefineConstants Condition="'$(TargetsWasm)' == 'true'">$(DefineConstants);CODEGEN_WASM</DefineConstants>
<DefineConstants Condition="$(TargetOS) == 'wasi'">$(DefineConstants);CODEGEN_WASI</DefineConstants>
</PropertyGroup>

<ItemGroup>
<!-- Our stack trace implementation is not compatible with post-link optimizations/changes. -->
<!-- Exempt $(EmccExtraArgs) so that quick experimentation from the command line is still possible. -->
<LinkerArg Include="-sERROR_ON_WASM_CHANGES_AFTER_LINK=1" Condition="'$(TargetsBrowser)' == 'true' and '$(EmccExtraArgs)' == ''" />
</ItemGroup>
</Project>
65 changes: 23 additions & 42 deletions src/tests/nativeaot/SmokeTests/HelloWasm/wasmjit-diff.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -496,10 +496,6 @@ if ($Analyze -or $Summary)

$RegressionCount = 0
$ImprovementCount = 0
$HaveRegressionDiffs = $false
$HaveImprovementDiffs = $false
$HaveBaseOnlyMethods = $false
$HaveDiffOnlyMethods = $false
$AverageRelativeCodeSizeDelta = 0.0
foreach ($Diff in $Diffs)
{
Expand All @@ -517,24 +513,13 @@ if ($Analyze -or $Summary)
# Just skip them for now.
if ($Diff.Base.Size -eq 0)
{
$HaveDiffOnlyMethods = $true
continue
}
if ($Diff.Diff.Size -eq 0)
{
$HaveBaseOnlyMethods = $true
continue
}

if ($IsRegression)
{
$HaveRegressionDiffs = $true
}
else
{
$HaveImprovementDiffs = $true
}

$AverageRelativeCodeSizeDelta += $Diff.CodeSizeDelta / $Diff.Base.Size
}

Expand All @@ -558,8 +543,13 @@ if ($Analyze -or $Summary)
Write-Host " average relative diff is $($AverageRelativeCodeSizeDelta -lt 0 ? 'an improvement' : 'a regression')"
Write-Host ""

function ShowRelativeDiffs($DiffsToShow, $Message, $ShowBaseOnlyMethods = $false, $ShowDiffOnlyMethods = $false)
function ShowRelativeDiffs($DiffsToShow, $Message)
{
if ($DiffsToShow.Length -eq 0)
{
return
}

Write-Host $Message

$DiffsShown = 0
Expand All @@ -570,42 +560,33 @@ if ($Analyze -or $Summary)
break
}

$IsBaseOnlyMethod = $Diff.Diff.Size -eq 0
$IsDiffOnlyMethod = $Diff.Base.Size -eq 0
if (($ShowBaseOnlyMethods -eq $IsBaseOnlyMethod) -and ($ShowDiffOnlyMethods -eq $IsDiffOnlyMethod))
{
Write-Host (" {0,8} ({1,6:P} of base) : {2} - {3}" -f
$Diff.CodeSizeDelta, ($Diff.CodeSizeDelta / $Diff.Base.Size), $Diff.DiffFileName, $Diff.Name)
$DiffsShown++
}
Write-Host(" {0,8} ({1,6:P} of base) : {2} - {3}" -f
$Diff.CodeSizeDelta, ($Diff.CodeSizeDelta / $Diff.Base.Size), $Diff.DiffFileName, $Diff.Name)
$DiffsShown++
}
Write-Host ""
}

if ($RegressionCount -ne 0)
{
$RegressionDiffs = $Diffs | sort { $_.CodeSizeDelta / $_.Base.Size } -Descending | where CodeSizeDelta -gt 0
if ($HaveRegressionDiffs)
{
ShowRelativeDiffs $RegressionDiffs "Top method regressions (percentages):"
}
if ($HaveDiffOnlyMethods)
{
ShowRelativeDiffs $RegressionDiffs "Top methods only present in diff:" -ShowDiffOnlyMethods $true
}
$RegressionDiffs = $Diffs | where CodeSizeDelta -gt 0

$ActualRegressionDiffs = $RegressionDiffs | where { $_.Base.Size -ne 0 } | sort { $_.CodeSizeDelta / $_.Base.Size } -Descending
ShowRelativeDiffs $ActualRegressionDiffs "Top method regressions (percentages):"

$DiffOnlyDiffs = $RegressionDiffs | where { $_.Base.Size -eq 0 } | sort CodeSizeDelta -Descending
ShowRelativeDiffs $DiffOnlyDiffs "Top methods only present in diff:"
}

if ($ImprovementCount -ne 0)
{
$ImprovementDiffs = $Diffs | sort { $_.CodeSizeDelta / $_.Base.Size } | where CodeSizeDelta -lt 0
if ($HaveImprovementDiffs)
{
ShowRelativeDiffs $ImprovementDiffs "Top method improvements (percentages):"
}
if ($HaveBaseOnlyMethods)
{
ShowRelativeDiffs $ImprovementDiffs "Top methods only present in base:" -ShowBaseOnlyMethods $true
}
$ImprovementDiffs = $Diffs | where CodeSizeDelta -lt 0

$ActualImprovementDiffs = $ImprovementDiffs | where { $_.Diff.Size -ne 0 } | sort { $_.CodeSizeDelta / $_.Base.Size }
ShowRelativeDiffs $ActualImprovementDiffs "Top method improvements (percentages):"

$BaseOnlyDiffs = $ImprovementDiffs | where { $_.Diff.Size -eq 0 } | sort CodeSizeDelta
ShowRelativeDiffs $BaseOnlyDiffs "Top methods only present in base:"
}

Write-Host "$($Diffs.Count) total methods with Code Size differences ($ImprovementCount improved, $RegressionCount regressed)"
Expand Down