After #2374 native unwinding will only be performed for second-pass handlers, hence, we do not actually need true funclets for second-pass handlers.
This change is the starting point for realizing the benefits of removing this requirement, those being tighter and smaller LLVM, better code quality and better debugging support.
For now, I only did the mechanical "move the code around" part. In particular:
1) We now rewrite the funclet info to match our view of the code to be generated.
2) We eagerly initialize LLVM blocks and move the "generate EH dispatch" code from the end of compilation to its beginning. This is mainly because the LLVM funclet tree requires catchpad instructions for the enclosing handlers to already be generated by the time we're generating handler bodies.
3) Supporting changes like tracking the handler index in the emit context (since now there is no 1-1 correspondence between handlers and funclets).
What is not included in this change:
1) Not generating funclets for faults.
2) Not forcing locals not live into true funclets to the shadow stack.
Diffs from change come mainly from the first commit (generating LLVM blocks in layout order) and are basically LLVM noise, though overall positive. Diffs for the second commit are minimal (-400 bytes code).
Total bytes of base: 3156378
Total bytes of diff: 3154266
Total bytes of delta: -2112 (-0.07% % of base)
Average relative delta: -0.31%
diff is an improvement
average relative diff is an improvement
Top method regressions (percentages):
7 (15.56% of base) : 2834.dasm - S_P_CoreLib_System_Runtime_GCStress__Initialize
13 (10.92% of base) : 2459.dasm - S_P_CoreLib_System_Collections_Generic_Dictionary_2<System___Canon__IntPtr>__TryGetValue
13 (10.92% of base) : 2065.dasm - S_P_CoreLib_System_Collections_Generic_Dictionary_2<System___Canon__Bool>__TryGetValue
7 (10.45% of base) : 2839.dasm - HelloWasm_Program___CallMe
8 (10.26% of base) : 2443.dasm - S_P_CoreLib_System_Number_BigInteger__ToUInt64
2 (10.00% of base) : 2568.dasm - S_P_TypeLoader_Internal_TypeSystem_LockFreeObjectInterner__ConvertIntPtrToValue
6 ( 9.84% of base) : 1873.dasm - S_P_CoreLib_System_Number_BigInteger__DivideGuessTooBig
96 ( 8.83% of base) : 1073.dasm - S_P_CoreLib_System_Reflection_Runtime_TypeInfos_RuntimeTypeInfo__get_ImplementedInterfaces
58 ( 8.02% of base) : 2078.dasm - S_P_CoreLib_System_Globalization_CultureData__GetCultureData
89 ( 6.96% of base) : 1656.dasm - S_P_CoreLib_Internal_Reflection_Extensions_NonPortable_CustomAttributeInstantiator__Convert
13 ( 6.91% of base) : 2052.dasm - S_P_CoreLib_System_Number__MatchChars
5 ( 6.33% of base) : 2771.dasm - S_P_TypeLoader_System_Collections_Generic_LowLevelDictionary_2<S_P_CoreLib_Internal_Runtime_TypeManagerHandle__System___Canon>__GetBucket
5 ( 6.33% of base) : 1192.dasm - S_P_TypeLoader_System_Collections_Generic_LowLevelDictionary_2<S_P_CoreLib_Internal_Runtime_TypeManagerHandle__Int32>__GetBucket
7 ( 6.03% of base) : 1507.dasm - String__Substring
76 ( 5.77% of base) : 2421.dasm - S_P_CoreLib_System_Threading_WaitSubsystem_ThreadWaitInfo__Wait
18 ( 5.71% of base) : 2349.dasm - HelloWasm_Program__TestFilter
11 ( 5.67% of base) : 1104.dasm - S_P_TypeLoader_Internal_Runtime_TypeLoader_RuntimeSignatureHelper__GetModuleInfo
2 ( 5.56% of base) : 3004.dasm - S_P_CoreLib_System_Reflection_ParameterInfo__IsDefined
12 ( 5.56% of base) : 2112.dasm - S_P_CoreLib_System_Globalization_CultureInfo__GetUserDefaultCulture
2 ( 5.41% of base) : 2903.dasm - S_P_CoreLib_System_ArgumentNullException__ThrowIfNull
Top methods only present in diff:
110 ( ∞ of base) : 3101.dasm - HelloWasm_Program__TestVirtualUnwindStackNoPopOnNestedUnwindingCatch$F1_Finally
112 ( ∞ of base) : 3082.dasm - HelloWasm_Program___TestVirtualUnwindStackNoPopOnThrow_g__TestVirtualUnwindStackNoPopOnThrow_NotInTryCatch_229_0$F1_Finally
105 ( ∞ of base) : 3083.dasm - HelloWasm_Program___TestVirtualUnwindStackNoPopOnUnwindingCatch_g__TestVirtualUnwindStackNoPopOnUnwindingCatch_NotInTryCatch_232_1$F1_Finally
105 ( ∞ of base) : 3084.dasm - HelloWasm_Program___TestVirtualUnwindStackNoPopOnUnwindingFault_g__TestVirtualUnwindStackNoPopOnUnwindingFault_NotInTryCatch_237_1$F1_Finally
74 ( ∞ of base) : 3085.dasm - HelloWasm_Program___TestExactUncontainedNestedDispatchIntraFrame_g__TestExactUncontainedNestedDispatchIntraFrame_Fault_246_1$F1_Finally
98 ( ∞ of base) : 3086.dasm - HelloWasm_Program__TryFinally$F1_Finally
29 ( ∞ of base) : 3087.dasm - S_P_CoreLib_System_Globalization_CultureInfo__GetCultureInfo_0$F2_Finally
94 ( ∞ of base) : 3088.dasm - HelloWasm_Program___TestDeepContainedNestedDispatchIntraFrame_g__TestDeepContainedNestedDispatchSingleFrame_TryThree_242_3$F1_Finally
151 ( ∞ of base) : 3089.dasm - HelloWasm_Program___TestExpandingUncontainedNestedDispatchIntraFrame_g__TestExpandingUncontainedNestedDispatchIntraFrame_NestedThrow_248_1$F1_Finally
25 ( ∞ of base) : 3080.dasm - S_P_TypeLoader_Internal_Runtime_TypeLoader_TypeLoaderEnvironment__EnsureTypeHandleForType$F1_Finally
162 ( ∞ of base) : 3090.dasm - HelloWasm_Program___TestClippingUncontainedNestedDispatchIntraFrame_g__TestClippingUncontainedNestedDispatchIntrarame_NestedThrow_247_1$F1_Finally
370 ( ∞ of base) : 3092.dasm - HelloWasm_Program__TestDeepUncontainedNestedDispatchSingleFrame$F1_Finally
141 ( ∞ of base) : 3093.dasm - HelloWasm_Program__TestDeepUncontainedNestedDispatchSingleFrame$F3_Finally
117 ( ∞ of base) : 3094.dasm - HelloWasm_Program__TestExpandingUncontainedNestedDispatchSingleFrame$F1_Finally
110 ( ∞ of base) : 3100.dasm - HelloWasm_Program__TestVirtualUnwindStackNoPopOnNestedUnwindingFault$F1_Finally
128 ( ∞ of base) : 3095.dasm - HelloWasm_Program__TestClippingUncontainedNestedDispatchSingleFrame$F1_Finally
123 ( ∞ of base) : 3096.dasm - HelloWasm_Program__TestExactUncontainedNestedDispatchSingleFrame$F1_Finally
453 ( ∞ of base) : 3097.dasm - HelloWasm_Program__TestDeepContainedNestedDispatchSingleFrame$F1_Finally
304 ( ∞ of base) : 3098.dasm - HelloWasm_Program__TestDeepContainedNestedDispatchSingleFrame$F3_Finally
167 ( ∞ of base) : 3099.dasm - HelloWasm_Program__TestContainedNestedDispatchSingleFrame$F1_Finally
Top method improvements (percentages):
-102 (-70.83% of base) : 2605.dasm - HelloWasm_Program__TestDeepUncontainedNestedDispatchSingleFrame$F2_Finally
-17 (-16.67% of base) : 2252.dasm - S_P_CoreLib_System_Reflection_MemberFilter__GetThunk
-17 (-16.67% of base) : 1671.dasm - S_P_CoreLib_System_Func_2<S_P_CoreLib_System_Reflection_Runtime_Assemblies_NativeFormat_NativeFormatRuntimeAssembly_RuntimeAssemblyKey__System___Canon>__GetThunk
-17 (-16.67% of base) : 1670.dasm - S_P_CoreLib_System_Comparison_1<S_P_CoreLib_Internal_Runtime_CompilerServices_UnboxingStubTargetsMap_UnboxingStubTargetMapping>__GetThunk
-17 (-16.67% of base) : 1669.dasm - S_P_CoreLib_System_Comparison_1<S_P_Reflection_Execution_Internal_Reflection_Execution_ExecutionEnvironmentImplementation_FunctionPointerOffsetPair>__GetThunk
-17 (-16.67% of base) : 1945.dasm - S_P_CoreLib_System_Reflection_Runtime_MethodInfos_CustomMethodInvokerAction__GetThunk
-17 (-16.67% of base) : 1471.dasm - S_P_CoreLib_System_Func_5<System___Canon__System___Canon__System___Canon__Bool__System___Canon>__GetThunk
-17 (-16.67% of base) : 1479.dasm - S_P_CoreLib_System_Func_2<System___Canon__System___Canon>__GetThunk
-17 (-16.67% of base) : 1473.dasm - S_P_CoreLib_System_Runtime_CompilerServices_ConditionalWeakTable_2_CreateValueCallback<System___Canon__System___Canon>__GetThunk
-17 (-16.67% of base) : 1481.dasm - S_P_CoreLib_System_Func_2<System___Canon__S_P_Reflection_Execution_Internal_Reflection_Execution_ExecutionEnvironmentImplementation_FunctionPointersToOffsets>__GetThunk
-17 (-16.67% of base) : 1482.dasm - S_P_CoreLib_System_Func_2<System___Canon__Bool>__GetThunk
-17 (-16.67% of base) : 1483.dasm - HelloWasm_Stack_1_StackDelegate<System___Canon>__GetThunk
-17 (-16.67% of base) : 1696.dasm - S_P_CoreLib_System_Func_2<Char__Bool>__GetThunk
-17 (-16.67% of base) : 1488.dasm - S_P_CoreLib_System_Predicate_1<System___Canon>__GetThunk
-14 (-15.73% of base) : 2250.dasm - S_P_CoreLib_System_Reflection_Runtime_TypeInfos_RuntimeConstructedGenericTypeInfo_TryGetConstructedGenericTypeDelegate__GetThunk
-14 (-15.73% of base) : 1679.dasm - S_P_CoreLib_System_Func_1<Int32>__GetThunk
-14 (-15.73% of base) : 2261.dasm - S_P_CoreLib_System_Runtime_RuntimeObjectFactory__GetThunk
-14 (-15.73% of base) : 2538.dasm - S_P_CoreLib_System_Action__GetThunk
-11 (-14.86% of base) : 2263.dasm - HelloWasm_Program_DelegateToCallFromUnmanaged__GetThunk
-11 (-14.86% of base) : 1695.dasm - S_P_CoreLib_System_Buffers_SpanAction_2<Char__IntPtr>__GetThunk
Top methods only present in base:
-303 (-100.00% of base) : 2619.dasm - HelloWasm_Program__TestDeepContainedNestedDispatchSingleFrame$F5_Finally
-98 (-100.00% of base) : 1365.dasm - HelloWasm_Program__TryFinally$F2_Finally
-113 (-100.00% of base) : 2624.dasm - HelloWasm_Program__TestVirtualUnwindStackNoPopOnNestedUnwindingFault$F4_Finally
-453 (-100.00% of base) : 2618.dasm - HelloWasm_Program__TestDeepContainedNestedDispatchSingleFrame$F9_Finally
-75 (-100.00% of base) : 1363.dasm - HelloWasm_Program___TestExactUncontainedNestedDispatchIntraFrame_g__TestExactUncontainedNestedDispatchIntraFrame_Fault_246_1$F3_Finally
-163 (-100.00% of base) : 2416.dasm - HelloWasm_Program___TestClippingUncontainedNestedDispatchIntraFrame_g__TestClippingUncontainedNestedDispatchIntrarame_NestedThrow_247_1$F3_Finally
-152 (-100.00% of base) : 2414.dasm - HelloWasm_Program___TestExpandingUncontainedNestedDispatchIntraFrame_g__TestExpandingUncontainedNestedDispatchIntraFrame_NestedThrow_248_1$F3_Finally
-124 (-100.00% of base) : 2615.dasm - HelloWasm_Program__TestExactUncontainedNestedDispatchSingleFrame$F3_Finally
-106 (-100.00% of base) : 1361.dasm - HelloWasm_Program___TestVirtualUnwindStackNoPopOnUnwindingFault_g__TestVirtualUnwindStackNoPopOnUnwindingFault_NotInTryCatch_237_1$F3_Finally
-113 (-100.00% of base) : 2627.dasm - HelloWasm_Program__TestVirtualUnwindStackNoPopOnNestedUnwindingCatch$F4_Finally
-131 (-100.00% of base) : 2613.dasm - HelloWasm_Program__TestClippingUncontainedNestedDispatchSingleFrame$F3_Finally
-120 (-100.00% of base) : 2611.dasm - HelloWasm_Program__TestExpandingUncontainedNestedDispatchSingleFrame$F3_Finally
-106 (-100.00% of base) : 1359.dasm - HelloWasm_Program___TestVirtualUnwindStackNoPopOnUnwindingCatch_g__TestVirtualUnwindStackNoPopOnUnwindingCatch_NotInTryCatch_232_1$F3_Finally
-42 (-100.00% of base) : 2606.dasm - HelloWasm_Program__TestDeepUncontainedNestedDispatchSingleFrame$F4_Finally
-29 (-100.00% of base) : 1737.dasm - S_P_CoreLib_System_Globalization_CultureInfo__GetCultureInfo_0$F1_Finally
-113 (-100.00% of base) : 1357.dasm - HelloWasm_Program___TestVirtualUnwindStackNoPopOnThrow_g__TestVirtualUnwindStackNoPopOnThrow_NotInTryCatch_229_0$F4_Finally
-97 (-100.00% of base) : 1840.dasm - HelloWasm_Program___TestDeepContainedNestedDispatchIntraFrame_g__TestDeepContainedNestedDispatchSingleFrame_TryThree_242_3$F2_Finally
-151 (-100.00% of base) : 1269.dasm - S_P_CoreLib_Interop_Sys__ReadLink_0$F1_Finally
-25 (-100.00% of base) : 1107.dasm - S_P_TypeLoader_Internal_Runtime_TypeLoader_TypeLoaderEnvironment__EnsureTypeHandleForType$F2_Finally
-373 (-100.00% of base) : 2604.dasm - HelloWasm_Program__TestDeepUncontainedNestedDispatchSingleFrame$F5_Finally
2102 total methods with Code Size differences (1202 improved, 900 regressed)
After #2374 native unwinding will only be performed for second-pass handlers, hence, we do not actually need true funclets for second-pass handlers.
This change is the starting point for realizing the benefits of removing this requirement, those being tighter and smaller LLVM, better code quality and better debugging support.
For now, I only did the mechanical "move the code around" part. In particular: 1) We now rewrite the funclet info to match our view of the code to be generated. 2) We eagerly initialize LLVM blocks and move the "generate EH dispatch" code from the end of compilation to its beginning. This is mainly because the LLVM funclet tree requires
catchpad
instructions for the enclosing handlers to already be generated by the time we're generating handler bodies. 3) Supporting changes like tracking the handler index in the emit context (since now there is no 1-1 correspondence between handlers and funclets).What is not included in this change: 1) Not generating funclets for faults. 2) Not forcing locals not live into true funclets to the shadow stack.
Diffs from change come mainly from the first commit (generating LLVM blocks in layout order) and are basically LLVM noise, though overall positive. Diffs for the second commit are minimal (-400 bytes code).