Browse Source

Merge branch 'master' into pr-template

pull/8712/head
Max Katz 4 years ago
committed by GitHub
parent
commit
a6f1b7c0da
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 50
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDeferredResourceTransformer.cs
  2. 26
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs
  3. 152
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs
  4. 2
      src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github

50
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlDeferredResourceTransformer.cs

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using XamlX.Ast; using XamlX.Ast;
using XamlX.Emit; using XamlX.Emit;
@ -47,7 +48,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
return !node.Type.GetClrType().IsValueType; return !node.Type.GetClrType().IsValueType;
} }
class AdderSetter : IXamlPropertySetter, IXamlEmitablePropertySetter<IXamlILEmitter> class AdderSetter : IXamlILOptimizedEmitablePropertySetter, IEquatable<AdderSetter>
{ {
private readonly IXamlMethod _getter; private readonly IXamlMethod _getter;
private readonly IXamlMethod _adder; private readonly IXamlMethod _adder;
@ -58,16 +59,22 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
_adder = adder; _adder = adder;
TargetType = getter.DeclaringType; TargetType = getter.DeclaringType;
Parameters = adder.ParametersWithThis().Skip(1).ToList(); Parameters = adder.ParametersWithThis().Skip(1).ToList();
bool allowNull = Parameters.Last().AcceptsNull();
BinderParameters = new PropertySetterBinderParameters
{
AllowMultiple = true,
AllowXNull = allowNull,
AllowRuntimeNull = allowNull
};
} }
public IXamlType TargetType { get; } public IXamlType TargetType { get; }
public PropertySetterBinderParameters BinderParameters { get; } = new PropertySetterBinderParameters public PropertySetterBinderParameters BinderParameters { get; }
{
AllowMultiple = true
};
public IReadOnlyList<IXamlType> Parameters { get; } public IReadOnlyList<IXamlType> Parameters { get; }
public void Emit(IXamlILEmitter emitter) public void Emit(IXamlILEmitter emitter)
{ {
var locals = new Stack<XamlLocalsPool.PooledLocal>(); var locals = new Stack<XamlLocalsPool.PooledLocal>();
@ -80,11 +87,40 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
} }
emitter.EmitCall(_getter); emitter.EmitCall(_getter);
while (locals.Count > 0) while (locals.Count>0)
using (var loc = locals.Pop()) using (var loc = locals.Pop())
emitter.Ldloc(loc.Local); emitter.Ldloc(loc.Local);
emitter.EmitCall(_adder, true); emitter.EmitCall(_adder, true);
} }
public void EmitWithArguments(
XamlEmitContextWithLocals<IXamlILEmitter, XamlILNodeEmitResult> context,
IXamlILEmitter emitter,
IReadOnlyList<IXamlAstValueNode> arguments)
{
emitter.EmitCall(_getter);
for (var i = 0; i < arguments.Count; ++i)
context.Emit(arguments[i], emitter, Parameters[i]);
emitter.EmitCall(_adder, true);
}
public bool Equals(AdderSetter other)
{
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
return _getter.Equals(other._getter) && _adder.Equals(other._adder);
}
public override bool Equals(object obj)
=> Equals(obj as AdderSetter);
public override int GetHashCode()
=> (_getter.GetHashCode() * 397) ^ _adder.GetHashCode();
} }
} }
} }

26
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs

@ -75,17 +75,17 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{ {
Getter = setterType.Methods.First(m => m.Name == "get_Value"); Getter = setterType.Methods.First(m => m.Name == "get_Value");
var method = setterType.Methods.First(m => m.Name == "set_Value"); var method = setterType.Methods.First(m => m.Name == "set_Value");
Setters.Add(new XamlIlDirectCallPropertySetter(method, types.IBinding)); Setters.Add(new XamlIlDirectCallPropertySetter(method, types.IBinding, false));
Setters.Add(new XamlIlDirectCallPropertySetter(method, types.UnsetValueType)); Setters.Add(new XamlIlDirectCallPropertySetter(method, types.UnsetValueType, false));
Setters.Add(new XamlIlDirectCallPropertySetter(method, targetType)); Setters.Add(new XamlIlDirectCallPropertySetter(method, targetType, targetType.AcceptsNull()));
} }
class XamlIlDirectCallPropertySetter : IXamlPropertySetter, IXamlEmitablePropertySetter<IXamlILEmitter> sealed class XamlIlDirectCallPropertySetter : IXamlPropertySetter, IXamlEmitablePropertySetter<IXamlILEmitter>
{ {
private readonly IXamlMethod _method; private readonly IXamlMethod _method;
private readonly IXamlType _type; private readonly IXamlType _type;
public IXamlType TargetType { get; } public IXamlType TargetType { get; }
public PropertySetterBinderParameters BinderParameters { get; } = new PropertySetterBinderParameters(); public PropertySetterBinderParameters BinderParameters { get; }
public IReadOnlyList<IXamlType> Parameters { get; } public IReadOnlyList<IXamlType> Parameters { get; }
public void Emit(IXamlILEmitter codegen) public void Emit(IXamlILEmitter codegen)
{ {
@ -94,13 +94,27 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
codegen.EmitCall(_method, true); codegen.EmitCall(_method, true);
} }
public XamlIlDirectCallPropertySetter(IXamlMethod method, IXamlType type) public XamlIlDirectCallPropertySetter(IXamlMethod method, IXamlType type, bool allowNull)
{ {
_method = method; _method = method;
_type = type; _type = type;
Parameters = new[] {type}; Parameters = new[] {type};
TargetType = method.ThisOrFirstParameter(); TargetType = method.ThisOrFirstParameter();
BinderParameters = new PropertySetterBinderParameters
{
AllowXNull = allowNull,
AllowRuntimeNull = allowNull
};
} }
private bool Equals(XamlIlDirectCallPropertySetter other)
=> Equals(_method, other._method) && Equals(_type, other._type);
public override bool Equals(object obj)
=> Equals(obj as XamlIlDirectCallPropertySetter);
public override int GetHashCode()
=> (_method.GetHashCode() * 397) ^ _type.GetHashCode();
} }
} }
} }

152
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlAvaloniaPropertyHelper.cs

@ -206,38 +206,64 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
Setters.Insert(0, new UnsetValueSetter(types, original.DeclaringType, field)); Setters.Insert(0, new UnsetValueSetter(types, original.DeclaringType, field));
} }
abstract class AvaloniaPropertyCustomSetter : IXamlPropertySetter, IXamlEmitablePropertySetter<IXamlILEmitter> abstract class AvaloniaPropertyCustomSetter : IXamlILOptimizedEmitablePropertySetter, IEquatable<AvaloniaPropertyCustomSetter>
{ {
protected AvaloniaXamlIlWellKnownTypes Types; protected readonly AvaloniaXamlIlWellKnownTypes Types;
protected IXamlField AvaloniaProperty; protected readonly IXamlField AvaloniaProperty;
public AvaloniaPropertyCustomSetter(AvaloniaXamlIlWellKnownTypes types, protected AvaloniaPropertyCustomSetter(
AvaloniaXamlIlWellKnownTypes types,
IXamlType declaringType, IXamlType declaringType,
IXamlField avaloniaProperty) IXamlField avaloniaProperty,
bool allowNull)
{ {
Types = types; Types = types;
AvaloniaProperty = avaloniaProperty; AvaloniaProperty = avaloniaProperty;
TargetType = declaringType; TargetType = declaringType;
BinderParameters = new PropertySetterBinderParameters
{
AllowXNull = allowNull,
AllowRuntimeNull = allowNull
};
} }
public IXamlType TargetType { get; } public IXamlType TargetType { get; }
public PropertySetterBinderParameters BinderParameters { get; } = new PropertySetterBinderParameters public PropertySetterBinderParameters BinderParameters { get; }
{
AllowXNull = false
};
public IReadOnlyList<IXamlType> Parameters { get; set; } public IReadOnlyList<IXamlType> Parameters { get; set; }
public abstract void Emit(IXamlILEmitter codegen);
public abstract void Emit(IXamlILEmitter emitter);
public abstract void EmitWithArguments(
XamlEmitContextWithLocals<IXamlILEmitter, XamlILNodeEmitResult> context,
IXamlILEmitter emitter,
IReadOnlyList<IXamlAstValueNode> arguments);
public bool Equals(AvaloniaPropertyCustomSetter other)
{
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
return GetType() == other.GetType() && AvaloniaProperty.Equals(other.AvaloniaProperty);
}
public override bool Equals(object obj)
=> Equals(obj as AvaloniaPropertyCustomSetter);
public override int GetHashCode()
=> AvaloniaProperty.GetHashCode();
} }
class BindingSetter : AvaloniaPropertyCustomSetter class BindingSetter : AvaloniaPropertyCustomSetter
{ {
public BindingSetter(AvaloniaXamlIlWellKnownTypes types, public BindingSetter(AvaloniaXamlIlWellKnownTypes types,
IXamlType declaringType, IXamlType declaringType,
IXamlField avaloniaProperty) : base(types, declaringType, avaloniaProperty) IXamlField avaloniaProperty) : base(types, declaringType, avaloniaProperty, false)
{ {
Parameters = new[] {types.IBinding}; Parameters = new[] { types.IBinding };
} }
public override void Emit(IXamlILEmitter emitter) public override void Emit(IXamlILEmitter emitter)
@ -246,10 +272,25 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
emitter emitter
.Stloc(bloc.Local) .Stloc(bloc.Local)
.Ldsfld(AvaloniaProperty) .Ldsfld(AvaloniaProperty)
.Ldloc(bloc.Local) .Ldloc(bloc.Local);
// TODO: provide anchor? EmitAnchorAndBind(emitter);
.Ldnull(); }
emitter.EmitCall(Types.AvaloniaObjectBindMethod, true);
public override void EmitWithArguments(
XamlEmitContextWithLocals<IXamlILEmitter, XamlILNodeEmitResult> context,
IXamlILEmitter emitter,
IReadOnlyList<IXamlAstValueNode> arguments)
{
emitter.Ldsfld(AvaloniaProperty);
context.Emit(arguments[0], emitter, Parameters[0]);
EmitAnchorAndBind(emitter);
}
private void EmitAnchorAndBind(IXamlILEmitter emitter)
{
emitter
.Ldnull() // TODO: provide anchor?
.EmitCall(Types.AvaloniaObjectBindMethod, true);
} }
} }
@ -257,7 +298,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{ {
public BindingWithPrioritySetter(AvaloniaXamlIlWellKnownTypes types, public BindingWithPrioritySetter(AvaloniaXamlIlWellKnownTypes types,
IXamlType declaringType, IXamlType declaringType,
IXamlField avaloniaProperty) : base(types, declaringType, avaloniaProperty) IXamlField avaloniaProperty) : base(types, declaringType, avaloniaProperty, false)
{ {
Parameters = new[] { types.BindingPriority, types.IBinding }; Parameters = new[] { types.BindingPriority, types.IBinding };
} }
@ -265,15 +306,29 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
public override void Emit(IXamlILEmitter emitter) public override void Emit(IXamlILEmitter emitter)
{ {
using (var bloc = emitter.LocalsPool.GetLocal(Types.IBinding)) using (var bloc = emitter.LocalsPool.GetLocal(Types.IBinding))
using (var priorityLocal = emitter.LocalsPool.GetLocal(Types.Int))
emitter emitter
.Stloc(bloc.Local) .Stloc(bloc.Local)
.Stloc(priorityLocal.Local) .Pop() // ignore priority
.Ldsfld(AvaloniaProperty) .Ldsfld(AvaloniaProperty)
.Ldloc(bloc.Local) .Ldloc(bloc.Local);
// TODO: provide anchor? EmitAnchorAndBind(emitter);
.Ldnull(); }
emitter.EmitCall(Types.AvaloniaObjectBindMethod, true);
public override void EmitWithArguments(
XamlEmitContextWithLocals<IXamlILEmitter, XamlILNodeEmitResult> context,
IXamlILEmitter emitter,
IReadOnlyList<IXamlAstValueNode> arguments)
{
emitter.Ldsfld(AvaloniaProperty);
context.Emit(arguments[1], emitter, Parameters[1]);
EmitAnchorAndBind(emitter);
}
private void EmitAnchorAndBind(IXamlILEmitter emitter)
{
emitter
.Ldnull() // TODO: provide anchor?
.EmitCall(Types.AvaloniaObjectBindMethod, true);
} }
} }
@ -281,7 +336,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
{ {
public SetValueWithPrioritySetter(AvaloniaXamlIlWellKnownTypes types, IXamlType declaringType, IXamlField avaloniaProperty, public SetValueWithPrioritySetter(AvaloniaXamlIlWellKnownTypes types, IXamlType declaringType, IXamlField avaloniaProperty,
IXamlType propertyType) IXamlType propertyType)
: base(types, declaringType, avaloniaProperty) : base(types, declaringType, avaloniaProperty, propertyType.AcceptsNull())
{ {
Parameters = new[] { types.BindingPriority, propertyType }; Parameters = new[] { types.BindingPriority, propertyType };
} }
@ -295,9 +350,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
- value - value
*/ */
var method = Types.AvaloniaObjectSetStyledPropertyValue
.MakeGenericMethod(new[] { Parameters[1] });
using (var valueLocal = emitter.LocalsPool.GetLocal(Parameters[1])) using (var valueLocal = emitter.LocalsPool.GetLocal(Parameters[1]))
using (var priorityLocal = emitter.LocalsPool.GetLocal(Types.Int)) using (var priorityLocal = emitter.LocalsPool.GetLocal(Types.Int))
emitter emitter
@ -305,25 +357,57 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
.Stloc(priorityLocal.Local) .Stloc(priorityLocal.Local)
.Ldsfld(AvaloniaProperty) .Ldsfld(AvaloniaProperty)
.Ldloc(valueLocal.Local) .Ldloc(valueLocal.Local)
.Ldloc(priorityLocal.Local) .Ldloc(priorityLocal.Local);
.EmitCall(method, true);
EmitSetStyledPropertyValue(emitter);
}
public override void EmitWithArguments(
XamlEmitContextWithLocals<IXamlILEmitter, XamlILNodeEmitResult> context,
IXamlILEmitter emitter,
IReadOnlyList<IXamlAstValueNode> arguments)
{
emitter.Ldsfld(AvaloniaProperty);
context.Emit(arguments[1], emitter, Parameters[1]);
context.Emit(arguments[0], emitter, Parameters[0]);
EmitSetStyledPropertyValue(emitter);
}
private void EmitSetStyledPropertyValue(IXamlILEmitter emitter)
{
var method = Types.AvaloniaObjectSetStyledPropertyValue.MakeGenericMethod(new[] { Parameters[1] });
emitter.EmitCall(method, true);
} }
} }
class UnsetValueSetter : AvaloniaPropertyCustomSetter class UnsetValueSetter : AvaloniaPropertyCustomSetter
{ {
public UnsetValueSetter(AvaloniaXamlIlWellKnownTypes types, IXamlType declaringType, IXamlField avaloniaProperty) public UnsetValueSetter(AvaloniaXamlIlWellKnownTypes types, IXamlType declaringType, IXamlField avaloniaProperty)
: base(types, declaringType, avaloniaProperty) : base(types, declaringType, avaloniaProperty, false)
{ {
Parameters = new[] {types.UnsetValueType}; Parameters = new[] { types.UnsetValueType };
} }
public override void Emit(IXamlILEmitter codegen) public override void Emit(IXamlILEmitter codegen)
{ {
codegen.Pop();
EmitSetValue(codegen);
}
public override void EmitWithArguments(
XamlEmitContextWithLocals<IXamlILEmitter, XamlILNodeEmitResult> context,
IXamlILEmitter emitter,
IReadOnlyList<IXamlAstValueNode> arguments)
{
EmitSetValue(emitter);
}
private void EmitSetValue(IXamlILEmitter emitter)
{
// Ignore the instance and load one from the static field to avoid extra local variable
var unsetValue = Types.AvaloniaProperty.Fields.First(f => f.Name == "UnsetValue"); var unsetValue = Types.AvaloniaProperty.Fields.First(f => f.Name == "UnsetValue");
codegen
// Ignore the instance and load one from the static field to avoid extra local variable emitter
.Pop()
.Ldsfld(AvaloniaProperty) .Ldsfld(AvaloniaProperty)
.Ldsfld(unsetValue) .Ldsfld(unsetValue)
.Ldc_I4(0) .Ldc_I4(0)

2
src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github

@ -1 +1 @@
Subproject commit a4e6be2d1407abec4f35fcb208848830ce513ead Subproject commit c1c0594ec2c35b08988183b1a5b3e34dfa19179d
Loading…
Cancel
Save