1<#@ template debug="false" hostspecific="false" language="C#" #>
2<#@ assembly name="System.Core" #>
3<#@ import namespace="System.Linq" #>
4<#@ import namespace="System.Text" #>
5<#@ import namespace="System.Collections.Generic" #>
6<#@ output extension=".cs" #>
7// Licensed to the .NET Foundation under one or more agreements.
8// The .NET Foundation licenses this file to you under the MIT license.
9// See the LICENSE file in the project root for more information.
10
11using System.Runtime.CompilerServices;
12
13namespace System.Dynamic
14{
15    internal static partial class UpdateDelegates
16    {
17#if FEATURE_COMPILE
18<#
19for (int i = 1; i <= 10; i++)
20{
21    string genericParameters = string.Join(", ", Enumerable.Range(0, i).Select(j => "T" + j).Concat(new[] { "TRet" }));
22    string parameters = string.Join(", ", new[] { "CallSite site" }.Concat(Enumerable.Range(0, i).Select(j => "T" + j + " arg" + j)));
23    string ruleInvocationArguments = string.Join(", ", new[] { "site" }.Concat(Enumerable.Range(0, i).Select(j => "arg" + j)));
24    string argsArray = i == 0 ? "Array.Empty<object>()" : "new object[] { " + string.Join(", ", Enumerable.Range(0, i).Select(j => "arg" + j)) + " }";
25#>
26        [Obsolete("pregenerated CallSite<T>.Update delegate", error: true)]
27        internal static TRet UpdateAndExecute<#=i#><<#=genericParameters#>>(<#=parameters#>)
28        {
29            //
30            // Declare the locals here upfront. It actually saves JIT stack space.
31            //
32            var @this = (CallSite<Func<CallSite, <#=genericParameters#>>>)site;
33            Func<CallSite, <#=genericParameters#>>[] applicable;
34            Func<CallSite, <#=genericParameters#>> rule, originalRule = @this.Target;
35            TRet result;
36
37
38            //
39            // Create matchmaker and its site. We'll need them regardless.
40            //
41            site = CallSiteOps.CreateMatchmaker(@this);
42
43            //
44            // Level 1 cache lookup
45            //
46            if ((applicable = CallSiteOps.GetRules(@this)) != null)
47            {
48                for (int i = 0; i < applicable.Length; i++)
49                {
50                    rule = applicable[i];
51
52                    //
53                    // Execute the rule
54                    //
55
56                    // if we've already tried it skip it...
57                    if ((object)rule != (object)originalRule)
58                    {
59                        @this.Target = rule;
60                        result = rule(<#=ruleInvocationArguments#>);
61
62                        if (CallSiteOps.GetMatch(site))
63                        {
64                            CallSiteOps.UpdateRules(@this, i);
65                            return result;
66                        }
67
68                        // Rule didn't match, try the next one
69                        CallSiteOps.ClearMatch(site);
70                    }
71                }
72            }
73
74            //
75            // Level 2 cache lookup
76            //
77
78            //
79            // Any applicable rules in level 2 cache?
80            //
81
82            var cache = CallSiteOps.GetRuleCache(@this);
83
84            applicable = cache.GetRules();
85            for (int i = 0; i < applicable.Length; i++)
86            {
87                rule = applicable[i];
88
89                //
90                // Execute the rule
91                //
92                @this.Target = rule;
93
94                try
95                {
96                    result = rule(<#=ruleInvocationArguments#>);
97                    if (CallSiteOps.GetMatch(site))
98                    {
99                        return result;
100                    }
101                }
102                finally
103                {
104                    if (CallSiteOps.GetMatch(site))
105                    {
106                        //
107                        // Rule worked. Add it to level 1 cache
108                        //
109                        CallSiteOps.AddRule(@this, rule);
110                        // and then move it to the front of the L2 cache
111                        CallSiteOps.MoveRule(cache, rule, i);
112                    }
113                }
114
115                // Rule didn't match, try the next one
116                CallSiteOps.ClearMatch(site);
117            }
118
119            //
120            // Miss on Level 0, 1 and 2 caches. Create new rule
121            //
122
123            rule = null;
124            var args = <#=argsArray#>;
125
126            for (; ; )
127            {
128                @this.Target = originalRule;
129                rule = @this.Target = @this.Binder.BindCore(@this, args);
130
131                //
132                // Execute the rule on the matchmaker site
133                //
134
135                try
136                {
137                    result = rule(<#=ruleInvocationArguments#>);
138                    if (CallSiteOps.GetMatch(site))
139                    {
140                        return result;
141                    }
142                }
143                finally
144                {
145                    if (CallSiteOps.GetMatch(site))
146                    {
147                        //
148                        // The rule worked. Add it to level 1 cache.
149                        //
150                        CallSiteOps.AddRule(@this, rule);
151                    }
152                }
153
154                // Rule we got back didn't work, try another one
155                CallSiteOps.ClearMatch(site);
156            }
157        }
158
159        [Obsolete("pregenerated CallSite<T>.Update delegate", error: true)]
160        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
161        internal static TRet NoMatch<#=i#><<#=genericParameters#>>(<#=parameters#>)
162        {
163            site._match = false;
164            return default(TRet);
165        }
166
167
168
169<#
170}
171#>
172<#
173for (int i = 1; i <= 10; i++)
174{
175    string genericParameters = string.Join(", ", Enumerable.Range(0, i).Select(j => "T" + j));
176    string parameters = string.Join(", ", new[] { "CallSite site" }.Concat(Enumerable.Range(0, i).Select(j => "T" + j + " arg" + j)));
177    string ruleInvocationArguments = string.Join(", ", new[] { "site" }.Concat(Enumerable.Range(0, i).Select(j => "arg" + j)));
178    string argsArray = i == 0 ? "Array.Empty<object>()" : "new object[] { " + string.Join(", ", Enumerable.Range(0, i).Select(j => "arg" + j)) + " }";
179#>
180        [Obsolete("pregenerated CallSite<T>.Update delegate", error: true)]
181        internal static void UpdateAndExecuteVoid<#=i#><<#=genericParameters#>>(<#=parameters#>)
182        {
183            //
184            // Declare the locals here upfront. It actually saves JIT stack space.
185            //
186            var @this = (CallSite<Action<CallSite, <#=genericParameters#>>>)site;
187            Action<CallSite, <#=genericParameters#>>[] applicable;
188            Action<CallSite, <#=genericParameters#>> rule, originalRule = @this.Target;
189
190
191            //
192            // Create matchmaker and its site. We'll need them regardless.
193            //
194            site = CallSiteOps.CreateMatchmaker(@this);
195
196            //
197            // Level 1 cache lookup
198            //
199            if ((applicable = CallSiteOps.GetRules(@this)) != null)
200            {
201                for (int i = 0; i < applicable.Length; i++)
202                {
203                    rule = applicable[i];
204
205                    //
206                    // Execute the rule
207                    //
208
209                    // if we've already tried it skip it...
210                    if ((object)rule != (object)originalRule)
211                    {
212                        @this.Target = rule;
213                        rule(<#=ruleInvocationArguments#>);
214
215                        if (CallSiteOps.GetMatch(site))
216                        {
217                            CallSiteOps.UpdateRules(@this, i);
218                            return;
219                        }
220
221                        // Rule didn't match, try the next one
222                        CallSiteOps.ClearMatch(site);
223                    }
224                }
225            }
226
227            //
228            // Level 2 cache lookup
229            //
230
231            //
232            // Any applicable rules in level 2 cache?
233            //
234
235            var cache = CallSiteOps.GetRuleCache(@this);
236
237            applicable = cache.GetRules();
238            for (int i = 0; i < applicable.Length; i++)
239            {
240                rule = applicable[i];
241
242                //
243                // Execute the rule
244                //
245                @this.Target = rule;
246
247                try
248                {
249                    rule(<#=ruleInvocationArguments#>);
250                    if (CallSiteOps.GetMatch(site))
251                    {
252                        return;
253                    }
254                }
255                finally
256                {
257                    if (CallSiteOps.GetMatch(site))
258                    {
259                        //
260                        // Rule worked. Add it to level 1 cache
261                        //
262                        CallSiteOps.AddRule(@this, rule);
263                        // and then move it to the front of the L2 cache
264                        CallSiteOps.MoveRule(cache, rule, i);
265                    }
266                }
267
268                // Rule didn't match, try the next one
269                CallSiteOps.ClearMatch(site);
270            }
271
272            //
273            // Miss on Level 0, 1 and 2 caches. Create new rule
274            //
275
276            rule = null;
277            var args = <#=argsArray#>;
278
279            for (; ; )
280            {
281                @this.Target = originalRule;
282                rule = @this.Target = @this.Binder.BindCore(@this, args);
283
284                //
285                // Execute the rule on the matchmaker site
286                //
287
288                try
289                {
290                    rule(<#=ruleInvocationArguments#>);
291                    if (CallSiteOps.GetMatch(site))
292                    {
293                        return;
294                    }
295                }
296                finally
297                {
298                    if (CallSiteOps.GetMatch(site))
299                    {
300                        //
301                        // The rule worked. Add it to level 1 cache.
302                        //
303                        CallSiteOps.AddRule(@this, rule);
304                    }
305                }
306
307                // Rule we got back didn't work, try another one
308                CallSiteOps.ClearMatch(site);
309            }
310        }
311
312        [Obsolete("pregenerated CallSite<T>.Update delegate", error: true)]
313        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")]
314        internal static void NoMatchVoid<#=i#><<#=genericParameters#>>(<#=parameters#>)
315        {
316            site._match = false;
317            return;
318        }
319<#
320    if (i != 10)
321    {
322#>
323
324
325
326<#
327    }
328}
329#>
330#endif
331    }
332}
333