Skip to content

Commit f6108bb

Browse files
committed
perf(wasm): Split methods containing try/catch/finally blocks
Related to dotnet/runtime#111281
1 parent cdf4548 commit f6108bb

File tree

5 files changed

+123
-64
lines changed

5 files changed

+123
-64
lines changed

src/Uno.UI.Dispatching/Native/NativeDispatcher.cs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -120,32 +120,42 @@ private static void DispatchItems()
120120
}
121121
}
122122

123+
RunAction(@this, action);
124+
125+
// Restore the priority to the default for native events
126+
// (i.e. not dispatched by this running loop)
127+
@this._currentPriority = NativeDispatcherPriority.Normal;
128+
129+
if (!didEnqueue && @this.Rendering != null)
130+
{
131+
@this.DispatchWakeUp();
132+
}
133+
}
134+
135+
/// <remarks>
136+
/// This method runs in a separate method in order to workaround for the following issue:
137+
/// https://github.com/dotnet/runtime/issues/111281
138+
/// which prevents AOT on WebAssembly when try/catch/finally are found in the same method.
139+
/// </remarks>
140+
private static void RunAction(NativeDispatcher dispatcher, Action? action)
141+
{
123142
if (action != null)
124143
{
125144
try
126145
{
127-
using (@this._synchronizationContexts[(int)@this._currentPriority].Apply())
146+
using (dispatcher._synchronizationContexts[(int)dispatcher._currentPriority].Apply())
128147
{
129148
action();
130149
}
131150
}
132151
catch (Exception exception)
133152
{
134-
@this.Log().Error("NativeDispatcher unhandled exception", exception);
153+
dispatcher.Log().Error("NativeDispatcher unhandled exception", exception);
135154
}
136155
}
137-
else if (@this.Rendering == null && @this.Log().IsEnabled(LogLevel.Debug))
138-
{
139-
@this.Log().Error("Dispatch queue is empty.");
140-
}
141-
142-
// Restore the priority to the default for native events
143-
// (i.e. not dispatched by this running loop)
144-
@this._currentPriority = NativeDispatcherPriority.Normal;
145-
146-
if (!didEnqueue && @this.Rendering != null)
156+
else if (dispatcher.Rendering == null && dispatcher.Log().IsEnabled(LogLevel.Debug))
147157
{
148-
@this.DispatchWakeUp();
158+
dispatcher.Log().Error("Dispatch queue is empty.");
149159
}
150160
}
151161

src/Uno.UI/UI/Xaml/Controls/Frame/Frame.legacy.cs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -140,20 +140,28 @@ private bool InnerNavigate(PageStackEntry entry, NavigationMode mode)
140140

141141
try
142142
{
143-
_isNavigating = true;
143+
bool InternalNavigate(PageStackEntry entry, NavigationMode mode)
144+
{
145+
try
146+
{
147+
_isNavigating = true;
144148

145-
return InnerNavigateUnsafe(entry, mode);
146-
}
147-
catch (Exception exception)
148-
{
149-
NavigationFailed?.Invoke(this, new NavigationFailedEventArgs(entry.SourcePageType, exception));
149+
return InnerNavigateUnsafe(entry, mode);
150+
}
151+
catch (Exception exception)
152+
{
153+
NavigationFailed?.Invoke(this, new NavigationFailedEventArgs(entry.SourcePageType, exception));
150154

151-
if (NavigationFailed == null)
152-
{
153-
Application.Current.RaiseRecoverableUnhandledException(new InvalidOperationException("Navigation failed", exception));
155+
if (NavigationFailed == null)
156+
{
157+
Application.Current.RaiseRecoverableUnhandledException(new InvalidOperationException("Navigation failed", exception));
158+
}
159+
160+
throw;
161+
}
154162
}
155163

156-
throw;
164+
return InternalNavigate(entry, mode);
157165
}
158166
finally
159167
{

src/Uno.UI/UI/Xaml/Internal/EventManager.uno.cs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -129,15 +129,26 @@ public void RaiseSizeChangedEvents()
129129
//if (auto layoutStorage = item.m_pElement->GetLayoutStorage())
130130
{
131131
var args = new SizeChangedEventArgs(item.Element, item.OldSize, item.Element.RenderSize);
132-
// AddRef for args is done on the managed side
133-
try
134-
{
135-
item.Element.RaiseSizeChanged(args);
136-
}
137-
catch
132+
133+
/// <remarks>
134+
/// This method runs in a separate method in order to workaround for the following issue:
135+
/// https://github.com/dotnet/runtime/issues/111281
136+
/// which prevents AOT on WebAssembly when try/catch/finally are found in the same method.
137+
/// </remarks>
138+
static void RaiseItemSizeChanged(SizeChangedQueueItem item, SizeChangedEventArgs args)
138139
{
139-
// Empty catch to have the same behavior as "IGNOREHR" in WinUI.
140+
// AddRef for args is done on the managed side
141+
try
142+
{
143+
item.Element.RaiseSizeChanged(args);
144+
}
145+
catch
146+
{
147+
// Empty catch to have the same behavior as "IGNOREHR" in WinUI.
148+
}
140149
}
150+
151+
RaiseItemSizeChanged(item, args);
141152
}
142153

143154
//TraceIndividualSizeChangedEnd(UINT64(item.m_pElement));

src/Uno.UI/UI/Xaml/Style/Style.cs

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -129,44 +129,56 @@ internal void ApplyTo(DependencyObject o, DependencyPropertyValuePrecedences pre
129129

130130
try
131131
{
132-
ResourceResolver.PushNewScope(_xamlScope);
133-
localPrecedenceDisposable = DependencyObjectExtensions.OverrideLocalPrecedence(o, precedence);
134-
135-
if (_flattenedSetters != null)
132+
/// <remarks>
133+
/// This method runs in a separate method in order to workaround for the following issue:
134+
/// https://github.com/dotnet/runtime/issues/111281
135+
/// which prevents AOT on WebAssembly when try/catch/finally are found in the same method.
136+
/// </remarks>
137+
IDisposable? InnerApplyTo(DependencyObject o, DependencyPropertyValuePrecedences precedence)
136138
{
137-
for (var i = 0; i < _flattenedSetters.Length; i++)
139+
IDisposable? localPrecedenceDisposable;
140+
ResourceResolver.PushNewScope(_xamlScope);
141+
localPrecedenceDisposable = DependencyObjectExtensions.OverrideLocalPrecedence(o, precedence);
142+
143+
if (_flattenedSetters != null)
138144
{
139-
try
145+
for (var i = 0; i < _flattenedSetters.Length; i++)
140146
{
141-
if (TryGetAdjustedSetter(precedence, o, _flattenedSetters[i], out var adjustedSetter))
147+
try
142148
{
143-
using (o.OverrideLocalPrecedence(DependencyPropertyValuePrecedences.ExplicitStyle))
149+
if (TryGetAdjustedSetter(precedence, o, _flattenedSetters[i], out var adjustedSetter))
144150
{
145-
adjustedSetter.ApplyTo(o);
151+
using (o.OverrideLocalPrecedence(DependencyPropertyValuePrecedences.ExplicitStyle))
152+
{
153+
adjustedSetter.ApplyTo(o);
154+
}
155+
}
156+
else
157+
{
158+
_flattenedSetters[i].ApplyTo(o);
146159
}
147160
}
148-
else
149-
{
150-
_flattenedSetters[i].ApplyTo(o);
151-
}
152-
}
153-
catch (Exception ex)
154-
{
155-
// This empty catch is to keep parity with WinUI's IGNOREHR in
156-
// https://github.com/microsoft/microsoft-ui-xaml/blob/93742a178db8f625ba9299f62c21f656e0b195ad/dxaml/xcp/core/core/elements/framework.cpp#L790
157-
if (this.Log().IsEnabled(LogLevel.Debug))
161+
catch (Exception ex)
158162
{
159-
this.Log().LogDebug($"An exception occurred while applying style setter. {ex}");
163+
// This empty catch is to keep parity with WinUI's IGNOREHR in
164+
// https://github.com/microsoft/microsoft-ui-xaml/blob/93742a178db8f625ba9299f62c21f656e0b195ad/dxaml/xcp/core/core/elements/framework.cpp#L790
165+
if (this.Log().IsEnabled(LogLevel.Debug))
166+
{
167+
this.Log().LogDebug($"An exception occurred while applying style setter. {ex}");
168+
}
160169
}
161170
}
162171
}
163-
}
164172

165-
localPrecedenceDisposable?.Dispose();
166-
localPrecedenceDisposable = null;
173+
localPrecedenceDisposable?.Dispose();
174+
localPrecedenceDisposable = null;
175+
176+
// Check tree for resource binding values, since some Setters may have set ThemeResource-backed values
177+
(o as IDependencyObjectStoreProvider)!.Store.UpdateResourceBindings(ResourceUpdateReason.ResolvedOnLoading);
178+
return localPrecedenceDisposable;
179+
}
167180

168-
// Check tree for resource binding values, since some Setters may have set ThemeResource-backed values
169-
(o as IDependencyObjectStoreProvider)!.Store.UpdateResourceBindings(ResourceUpdateReason.ResolvedOnLoading);
181+
localPrecedenceDisposable = InnerApplyTo(o, precedence);
170182
}
171183
finally
172184
{

src/Uno.UI/UI/Xaml/UIElement.Pointers.cs

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,20 +1225,38 @@ private bool RaisePointerEvent(RoutedEvent evt, PointerRoutedEventArgs args, Bub
12251225
}
12261226

12271227
var originalPending = _pendingRaisedEvent;
1228-
try
1229-
{
1230-
_pendingRaisedEvent = (this, evt, args);
12311228

1232-
return RaiseEvent(evt, args, ctx);
1233-
}
1234-
catch (Exception e)
1229+
try
12351230
{
1236-
if (this.Log().IsEnabled(LogLevel.Error))
1231+
/// <remarks>
1232+
/// This method runs in a separate method in order to workaround for the following issue:
1233+
/// https://github.com/dotnet/runtime/issues/111281
1234+
/// which prevents AOT on WebAssembly when try/catch/finally are found in the same method.
1235+
/// </remarks>
1236+
bool InnerRaiseEvent(
1237+
RoutedEvent evt,
1238+
PointerRoutedEventArgs args,
1239+
BubblingContext ctx,
1240+
ref (UIElement sender, RoutedEvent @event, PointerRoutedEventArgs args) pendingRaisedEvent)
12371241
{
1238-
this.Log().Error($"Failed to raise '{evt.Name}': {e}");
1242+
try
1243+
{
1244+
_pendingRaisedEvent = (this, evt, args);
1245+
1246+
return RaiseEvent(evt, args, ctx);
1247+
}
1248+
catch (Exception e)
1249+
{
1250+
if (this.Log().IsEnabled(LogLevel.Error))
1251+
{
1252+
this.Log().Error($"Failed to raise '{evt.Name}': {e}");
1253+
}
1254+
1255+
return false;
1256+
}
12391257
}
12401258

1241-
return false;
1259+
return InnerRaiseEvent(evt, args, ctx, ref _pendingRaisedEvent);
12421260
}
12431261
finally
12441262
{

0 commit comments

Comments
 (0)