IBC fixes (dotnet/coreclr#26738)
authorDavid Wrighton <davidwr@microsoft.com>
Tue, 17 Sep 2019 01:53:47 +0000 (18:53 -0700)
committerGitHub <noreply@github.com>
Tue, 17 Sep 2019 01:53:47 +0000 (18:53 -0700)
* IBC fixes
- Support IntPtr and UIntPtr element types in IBC data
- More defensive coding against structurally incorrect IBC data
- Skip compilation of open method definitions
- Generate IBC data without crashing when the first logged item is an InstantiatedMethod and not a token
- Safely shutdown and emit IBC data from a thread that hasn't been given a Thread object

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

src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/ReadyToRunLibraryRootProvider.cs
src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/IBC/IBCProfileParser.cs
src/coreclr/src/vm/ceeload.cpp
src/coreclr/src/vm/ceemain.cpp

index ff27bc2..acff969 100644 (file)
@@ -37,6 +37,12 @@ namespace ILCompiler
                         {
                             continue;
                         }
+
+                        if (method.IsMethodDefinition)
+                        {
+                            continue;
+                        }
+
                         bool containsSignatureVariables = false;
                         foreach (TypeDesc t in method.Instantiation)
                         {
index 9045168..bbea8f7 100644 (file)
@@ -271,7 +271,14 @@ namespace ILCompiler.IBC
         // externalModule may be null if the exact assembly isn't known
         private uint LookupIbcTypeToken(ref EcmaModule externalModule, uint ibcToken, Dictionary<IBCBlobKey, BlobEntry> blobs)
         {
-            var typeEntry = (BlobEntry.ExternalTypeEntry)blobs[new IBCBlobKey(ibcToken, BlobType.ExternalTypeDef)];
+            if (!blobs.TryGetValue(new IBCBlobKey(ibcToken, BlobType.ExternalTypeDef), out BlobEntry externalTypeDefBlob))
+            {
+                _logger.Writer.WriteLine($"Ibc TypeToken {ibcToken:x} unable to find external typedef");
+                return Cor.Macros.RidToToken(0, CorTokenType.mdtTypeDef); // Nil TypeDef token
+            }
+
+            var typeEntry = (BlobEntry.ExternalTypeEntry)externalTypeDefBlob;
+
             string typeNamespace = null;
             string typeName = Encoding.UTF8.GetString(typeEntry.Name, 0, typeEntry.Name.Length - 1 /* these strings are null terminated */);
             TypeDefinitionHandle enclosingType = default;
@@ -287,7 +294,14 @@ namespace ILCompiler.IBC
                 if (Cor.Macros.TypeFromToken(nameSpaceToken) != CorTokenType.ibcExternalNamespace)
                     throw new Exception($"Ibc TypeToken {ibcToken:x} has Namespace tokens that is not a ibcExternalNamespace");
 
-                var namespaceEntry = (BlobEntry.ExternalNamespaceEntry)blobs[new IBCBlobKey(nameSpaceToken, BlobType.ExternalNamespaceDef)];
+
+                if (!blobs.TryGetValue(new IBCBlobKey(nameSpaceToken, BlobType.ExternalNamespaceDef), out BlobEntry namespaceEntryBlob))
+                {
+                    _logger.Writer.WriteLine($"Ibc TypeToken {ibcToken:x} unable to find external namespace blob '{nameSpaceToken:x}");
+                    return Cor.Macros.RidToToken(0, CorTokenType.mdtTypeDef); // Nil TypeDef token
+                }
+
+                var namespaceEntry = (BlobEntry.ExternalNamespaceEntry)namespaceEntryBlob;
                 typeNamespace = Encoding.UTF8.GetString(namespaceEntry.Name, 0, namespaceEntry.Name.Length - 1 /* these strings are null terminated */);
             }
             else if (!Cor.Macros.IsNilToken(typeEntry.NestedClassToken))
@@ -432,6 +446,10 @@ namespace ILCompiler.IBC
                     return context.GetWellKnownType(WellKnownType.Boolean);
                 case CorElementType.ELEMENT_TYPE_CHAR:
                     return context.GetWellKnownType(WellKnownType.Char);
+                case CorElementType.ELEMENT_TYPE_I: 
+                    return context.GetWellKnownType(WellKnownType.IntPtr); 
+                case CorElementType.ELEMENT_TYPE_U: 
+                    return context.GetWellKnownType(WellKnownType.UIntPtr);
                 case CorElementType.ELEMENT_TYPE_I1:
                     return context.GetWellKnownType(WellKnownType.SByte);
                 case CorElementType.ELEMENT_TYPE_U1:
@@ -542,6 +560,8 @@ namespace ILCompiler.IBC
                 case CorElementType.ELEMENT_TYPE_VOID:
                 case CorElementType.ELEMENT_TYPE_BOOLEAN:
                 case CorElementType.ELEMENT_TYPE_CHAR:
+                case CorElementType.ELEMENT_TYPE_I:
+                case CorElementType.ELEMENT_TYPE_U:
                 case CorElementType.ELEMENT_TYPE_I1:
                 case CorElementType.ELEMENT_TYPE_U1:
                 case CorElementType.ELEMENT_TYPE_I2:
index a54c795..0535165 100644 (file)
@@ -12856,6 +12856,16 @@ idMethodSpec Module::LogInstantiatedMethod(const MethodDesc * md, ULONG flagNum)
     {
         CONTRACT_VIOLATION(ThrowsViolation|FaultViolation|GCViolation);
 
+        if (!m_tokenProfileData) 
+        { 
+            CreateProfilingData(); 
+        } 
+
+        if (!m_tokenProfileData) 
+        { 
+            return idMethodSpecNil; 
+        } 
+
         // get data
         SigBuilder sigBuilder;
 
index 73f9b6e..20dc0bc 100644 (file)
@@ -1449,8 +1449,19 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading)
             {
                 if (g_IBCLogger.InstrEnabled())
                 {
-                    Thread * pThread = GetThread();
-                    ThreadLocalIBCInfo* pInfo = pThread->GetIBCInfo();
+                    Thread * pThread = GetThreadNULLOk();
+                    ThreadLocalIBCInfo* pInfo = NULL;
+
+                    if (pThread != NULL)
+                    {
+                        pInfo = pThread->GetIBCInfo();
+                        if (pInfo == NULL) 
+                        { 
+                            CONTRACT_VIOLATION( ThrowsViolation | FaultViolation); 
+                            pInfo = new ThreadLocalIBCInfo(); 
+                            pThread->SetIBCInfo(pInfo); 
+                        } 
+                    }
 
                     // Acquire the Crst lock before creating the IBCLoggingDisabler object.
                     // Only one thread at a time can be processing an IBC logging event.