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 fc9c9d77916c560f4941d9094c11f52ddb30105e..68db43ca65a5e7ae10ae1e513e66316791196080 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 45a04ab40410045929dbd22c254bab18f6139c79..7091ea8a955442c77c09833d05d5b05f3c407736 100644 (file)
@@ -38,6 +38,14 @@ namespace Internal.TypeSystem
             }
         }
 
+        public override bool RequireSecObject
+        {
+            get
+            {
+                return _wrappedMethod.RequireSecObject;
+            }
+        }
+
         public override bool IsNoOptimization
         {
             get
index ab1c4082b40ad4092325599a36686151daecea2b..5884f1dcb4cacaf5cbe6b2a7a364f8aa6943dfe5 100644 (file)
@@ -57,6 +57,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>
@@ -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 225711b24986df0aa9fe64f2789c110a6c3b5c4c..7b21872d31bcf8a74c0c46daebc1dfffaf9d3359 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 eb5e6b39488d26c547c121935a91e71f8e0dbf3c..e0d30dee0e34e293900b228c66f61eb7328068f0 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);
         }