diff options
author | Marek Safar <marek.safar@gmail.com> | 2016-03-10 19:53:21 +0300 |
---|---|---|
committer | Marek Safar <marek.safar@gmail.com> | 2016-03-10 20:08:53 +0300 |
commit | f8474c43504a049923e864eb71cbe98c69e9cdee (patch) | |
tree | a1c5cc344f7738df6953187c3b32f5ce205980a0 | |
parent | d29212628eaa3ff98d0d80c2e9426e43b7144f10 (diff) |
[mcs] Codegen update for specialized struct initialization with awaited element initializer. Fixes #39459mono-4.4.0.40
-rw-r--r-- | mcs/mcs/expression.cs | 16 | ||||
-rw-r--r-- | mcs/tests/test-async-84.cs | 35 | ||||
-rw-r--r-- | mcs/tests/ver-il-net_4_x.xml | 32 |
3 files changed, 81 insertions, 2 deletions
diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index c5139d57f67..bfba44fbb8c 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -6465,7 +6465,7 @@ namespace Mono.CSharp } New n_source = source as New; - if (n_source != null) { + if (n_source != null && n_source.CanEmitOptimizedLocalTarget (ec)) { if (!n_source.Emit (ec, this)) { if (leave_copy) { EmitLoad (ec); @@ -7605,6 +7605,11 @@ namespace Mono.CSharp ec.Emit (OpCodes.Pop); } + public virtual bool CanEmitOptimizedLocalTarget (EmitContext ec) + { + return true; + } + public override void FlowAnalysis (FlowAnalysisContext fc) { if (arguments != null) @@ -12137,7 +12142,7 @@ namespace Mono.CSharp public override void Emit (EmitContext ec) { - if (method == null && TypeSpec.IsValueType (type) && initializers.Initializers.Count > 1 && ec.HasSet (BuilderContext.Options.AsyncBody) && initializers.ContainsEmitWithAwait ()) { + if (!CanEmitOptimizedLocalTarget (ec)) { var fe = ec.GetTemporaryField (type); if (!Emit (ec, fe)) @@ -12225,6 +12230,13 @@ namespace Mono.CSharp return true; } + public override bool CanEmitOptimizedLocalTarget (EmitContext ec) + { + return !(method == null && TypeSpec.IsValueType (type) && + initializers.Initializers.Count > 1 && ec.HasSet (BuilderContext.Options.AsyncBody) && + initializers.ContainsEmitWithAwait ()); + } + protected override IMemoryLocation EmitAddressOf (EmitContext ec, AddressOp Mode) { instance = base.EmitAddressOf (ec, Mode); diff --git a/mcs/tests/test-async-84.cs b/mcs/tests/test-async-84.cs new file mode 100644 index 00000000000..03825613f1f --- /dev/null +++ b/mcs/tests/test-async-84.cs @@ -0,0 +1,35 @@ +using System; +using System.Threading.Tasks; + +struct S +{ + public int value; + public string str; +} + +public class Program +{ + async Task<S> Foo () + { + return new S { + value = 1, + str = await DoAsync () + }; + + } + + static async Task<string> DoAsync () + { + await Task.Yield (); + return "asdafs"; + } + + static int Main () + { + var res = new Program ().Foo ().Result; + if (res.value != 1) + return 1; + + return 0; + } +}
\ No newline at end of file diff --git a/mcs/tests/ver-il-net_4_x.xml b/mcs/tests/ver-il-net_4_x.xml index eca75aea8eb..55a55a8ce00 100644 --- a/mcs/tests/ver-il-net_4_x.xml +++ b/mcs/tests/ver-il-net_4_x.xml @@ -65617,6 +65617,38 @@ </method> </type> </test> + <test name="test-async-84.cs"> + <type name="Program"> + <method name="System.Threading.Tasks.Task`1[S] Foo()" attrs="129"> + <size>33</size> + </method> + <method name="System.Threading.Tasks.Task`1[System.String] DoAsync()" attrs="145"> + <size>33</size> + </method> + <method name="Int32 Main()" attrs="145"> + <size>46</size> + </method> + <method name="Void .ctor()" attrs="6278"> + <size>7</size> + </method> + </type> + <type name="Program+<Foo>c__async0"> + <method name="Void MoveNext()" attrs="486"> + <size>204</size> + </method> + <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486"> + <size>13</size> + </method> + </type> + <type name="Program+<DoAsync>c__async1"> + <method name="Void MoveNext()" attrs="486"> + <size>171</size> + </method> + <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486"> + <size>13</size> + </method> + </type> + </test> <test name="test-cls-00.cs"> <type name="CLSCLass_6"> <method name="Void add_Disposed(Delegate)" attrs="2182"> |