Skip to content

Commit

Permalink
Merge pull request #19223 from unoplatform/dev/jela/aot-interp
Browse files Browse the repository at this point in the history
perf(wasm): Split methods containing try/catch/finally blocks
  • Loading branch information
jeromelaban authored Jan 15, 2025
2 parents ebf8095 + f6108bb commit 5485bce
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 64 deletions.
36 changes: 23 additions & 13 deletions src/Uno.UI.Dispatching/Native/NativeDispatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,32 +120,42 @@ private static void DispatchItems()
}
}

RunAction(@this, action);

// Restore the priority to the default for native events
// (i.e. not dispatched by this running loop)
@this._currentPriority = NativeDispatcherPriority.Normal;

if (!didEnqueue && @this.Rendering != null)
{
@this.DispatchWakeUp();
}
}

/// <remarks>
/// This method runs in a separate method in order to workaround for the following issue:
/// https://github.com/dotnet/runtime/issues/111281
/// which prevents AOT on WebAssembly when try/catch/finally are found in the same method.
/// </remarks>
private static void RunAction(NativeDispatcher dispatcher, Action? action)
{
if (action != null)
{
try
{
using (@this._synchronizationContexts[(int)@this._currentPriority].Apply())
using (dispatcher._synchronizationContexts[(int)dispatcher._currentPriority].Apply())
{
action();
}
}
catch (Exception exception)
{
@this.Log().Error("NativeDispatcher unhandled exception", exception);
dispatcher.Log().Error("NativeDispatcher unhandled exception", exception);
}
}
else if (@this.Rendering == null && @this.Log().IsEnabled(LogLevel.Debug))
{
@this.Log().Error("Dispatch queue is empty.");
}

// Restore the priority to the default for native events
// (i.e. not dispatched by this running loop)
@this._currentPriority = NativeDispatcherPriority.Normal;

if (!didEnqueue && @this.Rendering != null)
else if (dispatcher.Rendering == null && dispatcher.Log().IsEnabled(LogLevel.Debug))
{
@this.DispatchWakeUp();
dispatcher.Log().Error("Dispatch queue is empty.");
}
}

Expand Down
28 changes: 18 additions & 10 deletions src/Uno.UI/UI/Xaml/Controls/Frame/Frame.legacy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,20 +140,28 @@ private bool InnerNavigate(PageStackEntry entry, NavigationMode mode)

try
{
_isNavigating = true;
bool InternalNavigate(PageStackEntry entry, NavigationMode mode)
{
try
{
_isNavigating = true;

return InnerNavigateUnsafe(entry, mode);
}
catch (Exception exception)
{
NavigationFailed?.Invoke(this, new NavigationFailedEventArgs(entry.SourcePageType, exception));
return InnerNavigateUnsafe(entry, mode);
}
catch (Exception exception)
{
NavigationFailed?.Invoke(this, new NavigationFailedEventArgs(entry.SourcePageType, exception));

if (NavigationFailed == null)
{
Application.Current.RaiseRecoverableUnhandledException(new InvalidOperationException("Navigation failed", exception));
if (NavigationFailed == null)
{
Application.Current.RaiseRecoverableUnhandledException(new InvalidOperationException("Navigation failed", exception));
}

throw;
}
}

throw;
return InternalNavigate(entry, mode);
}
finally
{
Expand Down
25 changes: 18 additions & 7 deletions src/Uno.UI/UI/Xaml/Internal/EventManager.uno.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,26 @@ public void RaiseSizeChangedEvents()
//if (auto layoutStorage = item.m_pElement->GetLayoutStorage())
{
var args = new SizeChangedEventArgs(item.Element, item.OldSize, item.Element.RenderSize);
// AddRef for args is done on the managed side
try
{
item.Element.RaiseSizeChanged(args);
}
catch

/// <remarks>
/// This method runs in a separate method in order to workaround for the following issue:
/// https://github.com/dotnet/runtime/issues/111281
/// which prevents AOT on WebAssembly when try/catch/finally are found in the same method.
/// </remarks>
static void RaiseItemSizeChanged(SizeChangedQueueItem item, SizeChangedEventArgs args)
{
// Empty catch to have the same behavior as "IGNOREHR" in WinUI.
// AddRef for args is done on the managed side
try
{
item.Element.RaiseSizeChanged(args);
}
catch
{
// Empty catch to have the same behavior as "IGNOREHR" in WinUI.
}
}

RaiseItemSizeChanged(item, args);
}

//TraceIndividualSizeChangedEnd(UINT64(item.m_pElement));
Expand Down
62 changes: 37 additions & 25 deletions src/Uno.UI/UI/Xaml/Style/Style.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,44 +129,56 @@ internal void ApplyTo(DependencyObject o, DependencyPropertyValuePrecedences pre

try
{
ResourceResolver.PushNewScope(_xamlScope);
localPrecedenceDisposable = DependencyObjectExtensions.OverrideLocalPrecedence(o, precedence);

if (_flattenedSetters != null)
/// <remarks>
/// This method runs in a separate method in order to workaround for the following issue:
/// https://github.com/dotnet/runtime/issues/111281
/// which prevents AOT on WebAssembly when try/catch/finally are found in the same method.
/// </remarks>
IDisposable? InnerApplyTo(DependencyObject o, DependencyPropertyValuePrecedences precedence)
{
for (var i = 0; i < _flattenedSetters.Length; i++)
IDisposable? localPrecedenceDisposable;
ResourceResolver.PushNewScope(_xamlScope);
localPrecedenceDisposable = DependencyObjectExtensions.OverrideLocalPrecedence(o, precedence);

if (_flattenedSetters != null)
{
try
for (var i = 0; i < _flattenedSetters.Length; i++)
{
if (TryGetAdjustedSetter(precedence, o, _flattenedSetters[i], out var adjustedSetter))
try
{
using (o.OverrideLocalPrecedence(DependencyPropertyValuePrecedences.ExplicitStyle))
if (TryGetAdjustedSetter(precedence, o, _flattenedSetters[i], out var adjustedSetter))
{
adjustedSetter.ApplyTo(o);
using (o.OverrideLocalPrecedence(DependencyPropertyValuePrecedences.ExplicitStyle))
{
adjustedSetter.ApplyTo(o);
}
}
else
{
_flattenedSetters[i].ApplyTo(o);
}
}
else
{
_flattenedSetters[i].ApplyTo(o);
}
}
catch (Exception ex)
{
// This empty catch is to keep parity with WinUI's IGNOREHR in
// https://github.com/microsoft/microsoft-ui-xaml/blob/93742a178db8f625ba9299f62c21f656e0b195ad/dxaml/xcp/core/core/elements/framework.cpp#L790
if (this.Log().IsEnabled(LogLevel.Debug))
catch (Exception ex)
{
this.Log().LogDebug($"An exception occurred while applying style setter. {ex}");
// This empty catch is to keep parity with WinUI's IGNOREHR in
// https://github.com/microsoft/microsoft-ui-xaml/blob/93742a178db8f625ba9299f62c21f656e0b195ad/dxaml/xcp/core/core/elements/framework.cpp#L790
if (this.Log().IsEnabled(LogLevel.Debug))
{
this.Log().LogDebug($"An exception occurred while applying style setter. {ex}");
}
}
}
}
}

localPrecedenceDisposable?.Dispose();
localPrecedenceDisposable = null;
localPrecedenceDisposable?.Dispose();
localPrecedenceDisposable = null;

// Check tree for resource binding values, since some Setters may have set ThemeResource-backed values
(o as IDependencyObjectStoreProvider)!.Store.UpdateResourceBindings(ResourceUpdateReason.ResolvedOnLoading);
return localPrecedenceDisposable;
}

// Check tree for resource binding values, since some Setters may have set ThemeResource-backed values
(o as IDependencyObjectStoreProvider)!.Store.UpdateResourceBindings(ResourceUpdateReason.ResolvedOnLoading);
localPrecedenceDisposable = InnerApplyTo(o, precedence);
}
finally
{
Expand Down
36 changes: 27 additions & 9 deletions src/Uno.UI/UI/Xaml/UIElement.Pointers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1225,20 +1225,38 @@ private bool RaisePointerEvent(RoutedEvent evt, PointerRoutedEventArgs args, Bub
}

var originalPending = _pendingRaisedEvent;
try
{
_pendingRaisedEvent = (this, evt, args);

return RaiseEvent(evt, args, ctx);
}
catch (Exception e)
try
{
if (this.Log().IsEnabled(LogLevel.Error))
/// <remarks>
/// This method runs in a separate method in order to workaround for the following issue:
/// https://github.com/dotnet/runtime/issues/111281
/// which prevents AOT on WebAssembly when try/catch/finally are found in the same method.
/// </remarks>
bool InnerRaiseEvent(
RoutedEvent evt,
PointerRoutedEventArgs args,
BubblingContext ctx,
ref (UIElement sender, RoutedEvent @event, PointerRoutedEventArgs args) pendingRaisedEvent)
{
this.Log().Error($"Failed to raise '{evt.Name}': {e}");
try
{
_pendingRaisedEvent = (this, evt, args);

return RaiseEvent(evt, args, ctx);
}
catch (Exception e)
{
if (this.Log().IsEnabled(LogLevel.Error))
{
this.Log().Error($"Failed to raise '{evt.Name}': {e}");
}

return false;
}
}

return false;
return InnerRaiseEvent(evt, args, ctx, ref _pendingRaisedEvent);
}
finally
{
Expand Down

0 comments on commit 5485bce

Please sign in to comment.