diff options
author | Stephane Delcroix <stephane@delcroix.org> | 2016-12-14 13:25:42 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-12-14 13:25:42 +0100 |
commit | d4792dc98dfca29849bedc21519d9cf9ae6f2cb6 (patch) | |
tree | d63399bcc3c99abf141944ebd4f8ff15b32b2f6f /Xamarin.Forms.Build.Tasks/CompiledValueProviders | |
parent | f2fe64ac235871dbed5f1f09812cb5cfc11864e3 (diff) | |
download | xamarin-forms-d4792dc98dfca29849bedc21519d9cf9ae6f2cb6.tar.gz xamarin-forms-d4792dc98dfca29849bedc21519d9cf9ae6f2cb6.tar.bz2 xamarin-forms-d4792dc98dfca29849bedc21519d9cf9ae6f2cb6.zip |
[XamlC] Allow compilation of IValueProviders (#622)
* [XamlC] Allow compilation of IValueProviders
`IValueProvider`s tagged with the appropriate attribute will be bypassed
and the compiled version, if found, will be used.
This first version contains a compiled version of Setter's
IValueProvider and it already reduces the amount of generated IL by 39%
in, e.g. StyleTests.
It's a huge gain because XamlC no longer have to generate
ServiceProviders for those, so the methodbody is smaller, takes less
time to jit, less time to execute and nothing is invoked at runtime,
which probably saves a tons of time as well, as most IValueProvider
implementation heavily uses reflection.
* name bool parameters
Diffstat (limited to 'Xamarin.Forms.Build.Tasks/CompiledValueProviders')
-rw-r--r-- | Xamarin.Forms.Build.Tasks/CompiledValueProviders/ICompiledValueProvider.cs | 13 | ||||
-rw-r--r-- | Xamarin.Forms.Build.Tasks/CompiledValueProviders/SetterValueProvider.cs | 40 |
2 files changed, 53 insertions, 0 deletions
diff --git a/Xamarin.Forms.Build.Tasks/CompiledValueProviders/ICompiledValueProvider.cs b/Xamarin.Forms.Build.Tasks/CompiledValueProviders/ICompiledValueProvider.cs new file mode 100644 index 00000000..37418bd9 --- /dev/null +++ b/Xamarin.Forms.Build.Tasks/CompiledValueProviders/ICompiledValueProvider.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +using Mono.Cecil; +using Mono.Cecil.Cil; +using Xamarin.Forms.Build.Tasks; + +namespace Xamarin.Forms.Xaml +{ + interface ICompiledValueProvider + { + IEnumerable<Instruction> ProvideValue(VariableDefinitionReference vardefref, ModuleDefinition module, BaseNode node, ILContext context); + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Build.Tasks/CompiledValueProviders/SetterValueProvider.cs b/Xamarin.Forms.Build.Tasks/CompiledValueProviders/SetterValueProvider.cs new file mode 100644 index 00000000..163bd9e7 --- /dev/null +++ b/Xamarin.Forms.Build.Tasks/CompiledValueProviders/SetterValueProvider.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; + +using Mono.Cecil; +using Mono.Cecil.Cil; + +using Xamarin.Forms.Xaml; +using Xamarin.Forms.Build.Tasks; + +namespace Xamarin.Forms.Core.XamlC +{ + class SetterValueProvider : ICompiledValueProvider + { + public IEnumerable<Instruction> ProvideValue(VariableDefinitionReference vardefref, ModuleDefinition module, BaseNode node, ILContext context) + { + var valueNode = ((IElementNode)node).Properties[new XmlName("", "Value")]; + + //if it's an elementNode, there's probably no need to convert it + if (valueNode is IElementNode) + yield break; + + var value = ((string)((ValueNode)valueNode).Value); + var bpNode = ((ValueNode)((IElementNode)node).Properties[new XmlName("", "Property")]); + var bpRef = (new BindablePropertyConverter()).GetBindablePropertyFieldReference((string)bpNode.Value, module, bpNode); + + TypeReference _; + var setValueRef = module.Import(module.Import(typeof(Setter)).GetProperty(p => p.Name == "Value", out _).SetMethod); + + //push the setter + yield return Instruction.Create(OpCodes.Ldloc, vardefref.VariableDefinition); + + //push the value + foreach (var instruction in ((ValueNode)valueNode).PushConvertedValue(context, bpRef, valueNode.PushServiceProvider(context, bpRef: bpRef), boxValueTypes: true, unboxValueTypes: false)) + yield return instruction; + + //set the value + yield return Instruction.Create(OpCodes.Callvirt, setValueRef); + } + } +}
\ No newline at end of file |