+ //
+ // Use same anonymous method implementation for scenarios where same
+ // code is used from multiple blocks, e.g. field initializers
+ //
+ if (method == null) {
+ //
+ // Delay an anonymous method definition to avoid emitting unused code
+ // for unreachable blocks or expression trees
+ //
+ method = DoCreateMethodHost (ec);
+ method.Define ();
+ }
+
+ bool is_static = (method.ModFlags & Modifiers.STATIC) != 0;
+ if (is_static && am_cache == null) {
+ //
+ // Creates a field cache to store delegate instance if it's not generic
+ //
+ if (!method.MemberName.IsGeneric) {
+ TypeContainer parent = method.Parent.PartialContainer;
+ int id = parent.Fields == null ? 0 : parent.Fields.Count;
+ am_cache = new Field (parent, new TypeExpression (type, loc),
+ Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED,
+ new MemberName (CompilerGeneratedClass.MakeName (null, "f", "am$cache", id), loc), null);
+ am_cache.Define ();
+ parent.AddField (am_cache);
+ } else {
+ // TODO: Implement caching of generated generic static methods
+ //
+ // Idea:
+ //
+ // Some extra class is needed to capture variable generic type
+ // arguments. Maybe we could re-use anonymous types, with a unique
+ // anonymous method id, but they are quite heavy.
+ //
+ // Consider : "() => typeof(T);"
+ //
+ // We need something like
+ // static class Wrap<Tn, Tm, DelegateType> {
+ // public static DelegateType cache;
+ // }
+ //
+ // We then specialize local variable to capture all generic parameters
+ // and delegate type, e.g. "Wrap<Ta, Tb, DelegateTypeInst> cache;"
+ //
+ }
+ }
+
+ ILGenerator ig = ec.ig;
+ Label l_initialized = ig.DefineLabel ();
+
+ if (am_cache != null) {
+ ig.Emit (OpCodes.Ldsfld, am_cache.FieldBuilder);
+ ig.Emit (OpCodes.Brtrue_S, l_initialized);
+ }
+