Fix crossgen2 for methods with StackCrawlMark (dotnet/coreclr#27050)
authorJan Vorlicek <janvorli@microsoft.com>
Mon, 7 Oct 2019 19:44:47 +0000 (21:44 +0200)
committerGitHub <noreply@github.com>
Mon, 7 Oct 2019 19:44:47 +0000 (21:44 +0200)
* Fix crossgen2 for methods with StackCrawlMark

Methods using StackCrawlMark (like Assembly.GetExecutingAssembly)
require that the method is not inlined. Such methods are marked by
System.Security.DynamicSecurityMethod attribute.

This change adds proper handling of such methods, mimicking exactly what
old crossgen does.

Commit migrated from https://github.com/dotnet/coreclr/commit/98c2d5ff70059d115fe38bc6c19956a721e33558

src/coreclr/src/tools/crossgen2/Common/JitInterface/CorInfoImpl.cs
src/coreclr/src/tools/crossgen2/Common/TypeSystem/CodeGen/MethodDelegator.CodeGen.cs
src/coreclr/src/tools/crossgen2/Common/TypeSystem/CodeGen/MethodDesc.CodeGen.cs
src/coreclr/src/tools/crossgen2/Common/TypeSystem/Ecma/EcmaMethod.cs
src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs

index fc9c9d7..68db43c 100644 (file)
@@ -661,6 +661,13 @@ namespace Internal.JitInterface
                 result |= CorInfoFlag.CORINFO_FLG_PINVOKE;
             }
 
+#if READYTORUN
+            if (method.RequireSecObject)
+            {
+                result |= CorInfoFlag.CORINFO_FLG_DONT_INLINE_CALLER;
+            }
+#endif
+
             if (method.IsAggressiveOptimization)
             {
                 result |= CorInfoFlag.CORINFO_FLG_AGGRESSIVE_OPT;
index 45a04ab..7091ea8 100644 (file)
@@ -38,6 +38,14 @@ namespace Internal.TypeSystem
             }
         }
 
+        public override bool RequireSecObject
+        {
+            get
+            {
+                return _wrappedMethod.RequireSecObject;
+            }
+        }
+
         public override bool IsNoOptimization
         {
             get
index ab1c408..5884f1d 100644 (file)
@@ -58,6 +58,20 @@ namespace Internal.TypeSystem
         }
 
         /// <summary>
+        /// Gets a value indicating whether this method was marked with the
+        /// System.Security.DynamicSecurityMethod attribute. For such methods
+        /// runtime needs to be able to find their caller, their caller's caller
+        /// or the method itself on the call stack using stack walking.
+        /// </summary>
+        public virtual bool RequireSecObject
+        {
+            get
+            {
+                return false;
+            }
+        }
+
+        /// <summary>
         /// Gets a value specifying whether this method should not be optimized.
         /// </summary>
         public virtual bool IsNoOptimization
@@ -168,6 +182,14 @@ namespace Internal.TypeSystem
             }
         }
 
+        public override bool RequireSecObject
+        {
+            get
+            {
+                return _methodDef.RequireSecObject;
+            }
+        }
+
         public override bool IsNoOptimization
         {
             get
@@ -252,6 +274,14 @@ namespace Internal.TypeSystem
             }
         }
 
+        public override bool RequireSecObject
+        {
+            get
+            {
+                return _typicalMethodDef.RequireSecObject;
+            }
+        }
+
         public override bool IsNoOptimization
         {
             get
index 225711b..7b21872 100644 (file)
@@ -14,23 +14,24 @@ namespace Internal.TypeSystem.Ecma
     {
         private static class MethodFlags
         {
-            public const int BasicMetadataCache     = 0x0001;
-            public const int Virtual                = 0x0002;
-            public const int NewSlot                = 0x0004;
-            public const int Abstract               = 0x0008;
-            public const int Final                  = 0x0010;
-            public const int NoInlining             = 0x0020;
-            public const int AggressiveInlining     = 0x0040;
-            public const int RuntimeImplemented     = 0x0080;
-            public const int InternalCall           = 0x0100;
-            public const int Synchronized           = 0x0200;
-            public const int AggressiveOptimization = 0x0400;
-            public const int NoOptimization         = 0x0800;
-
-            public const int AttributeMetadataCache = 0x1000;
-            public const int Intrinsic              = 0x2000;
-            public const int NativeCallable         = 0x4000;
-            public const int RuntimeExport          = 0x8000;
+            public const int BasicMetadataCache     = 0x00001;
+            public const int Virtual                = 0x00002;
+            public const int NewSlot                = 0x00004;
+            public const int Abstract               = 0x00008;
+            public const int Final                  = 0x00010;
+            public const int NoInlining             = 0x00020;
+            public const int AggressiveInlining     = 0x00040;
+            public const int RuntimeImplemented     = 0x00080;
+            public const int InternalCall           = 0x00100;
+            public const int Synchronized           = 0x00200;
+            public const int AggressiveOptimization = 0x00400;
+            public const int NoOptimization         = 0x00800;
+            public const int RequireSecObject       = 0x01000;
+
+            public const int AttributeMetadataCache = 0x02000;
+            public const int Intrinsic              = 0x04000;
+            public const int NativeCallable         = 0x08000;
+            public const int RuntimeExport          = 0x10000;
         };
 
         private EcmaType _type;
@@ -143,6 +144,9 @@ namespace Internal.TypeSystem.Ecma
                 if ((methodAttributes & MethodAttributes.Final) != 0)
                     flags |= MethodFlags.Final;
 
+                if ((methodAttributes & MethodAttributes.RequireSecObject) != 0)
+                    flags |= MethodFlags.RequireSecObject;
+
                 if ((methodImplAttributes & MethodImplAttributes.NoInlining) != 0)
                     flags |= MethodFlags.NoInlining;
 
@@ -266,6 +270,14 @@ namespace Internal.TypeSystem.Ecma
             }
         }
 
+        public override bool RequireSecObject
+        {
+            get
+            {
+                return (GetMethodFlags(MethodFlags.BasicMetadataCache | MethodFlags.RequireSecObject) & MethodFlags.RequireSecObject) != 0;
+            }
+        }
+
         public override bool IsAggressiveOptimization
         {
             get
index eb5e6b3..e0d30de 100644 (file)
@@ -63,6 +63,13 @@ namespace ILCompiler
 
         public bool CanInline(MethodDesc caller, MethodDesc callee)
         {
+            // Check to see if the method requires a security object.  This means they call demand and
+            // shouldn't be inlined.
+            if (callee.RequireSecObject)
+            {
+                return false;
+            }
+
             return NodeFactory.CompilationModuleGroup.CanInline(caller, callee);
         }