Improve performance of Object.GetType for arrays (dotnet/coreclr#10992)
authorJan Kotas <jkotas@microsoft.com>
Mon, 17 Apr 2017 22:37:09 +0000 (17:37 -0500)
committerGitHub <noreply@github.com>
Mon, 17 Apr 2017 22:37:09 +0000 (17:37 -0500)
* Improve performance of Object.GetType for arrays

Cache managed Type object on MethodTable for arrays. Makes Object.GetType for arrays about 5x faster.

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

src/coreclr/src/classlibnative/bcltype/objectnative.cpp
src/coreclr/src/vm/methodtable.h
src/coreclr/src/vm/methodtable.inl
src/coreclr/src/vm/typedesc.cpp

index 82b189d..a90a37a 100644 (file)
@@ -198,12 +198,6 @@ NOINLINE static Object* GetClassHelper(OBJECTREF objRef)
     TypeHandle typeHandle = objRef->GetTypeHandle();
     OBJECTREF refType = NULL;
 
-    // Arrays go down this slow path, at least don't do the full HelperMethodFrame setup
-    // if we are fetching the cached entry.  
-    refType = typeHandle.GetManagedClassObjectFast();
-    if (refType != NULL)
-        return OBJECTREFToObject(refType);
-
     HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_1(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, refType);
 
         refType = typeHandle.GetManagedClassObject();
index d5cb5ba..df60fca 100644 (file)
@@ -414,19 +414,13 @@ struct MethodTableWriteableData
     };
     DWORD      m_dwFlags;                  // Lot of empty bits here.
 
-private:
     /*
      * m_hExposedClassObject is LoaderAllocator slot index to 
-     * a RuntimeType instance for this class.  But
-     * do NOT use it for Arrays or remoted objects!  All arrays of objects 
-     * share the same MethodTable/EEClass.
-     * @GENERICS: this used to live in EEClass but now lives here because it is per-instantiation data
-        * only set in code:MethodTable.GetManagedClassObject
+     * a RuntimeType instance for this class. 
      */
     LOADERHANDLE m_hExposedClassObject;
 
 #ifdef _DEBUG
-public:
     // to avoid verify same method table too many times when it's not changing, we cache the GC count
     // on which the method table is verified. When fast GC STRESS is turned on, we only verify the MT if 
     // current GC count is bigger than the number. Note most thing which will invalidate a MT will require a 
index c762512..9b72d24 100644 (file)
@@ -1770,10 +1770,6 @@ FORCEINLINE OBJECTREF MethodTable::GetManagedClassObjectIfExists()
         return NULL;
     }
 
-    // Only code:MethodTable::GetManagedClassObject sets m_pExposedClassObject and it insures that 
-    // remoted objects and arrays don't get in.  
-    _ASSERTE(!IsArray() && !IsTransparentProxy());
-
     COMPILER_ASSUME(retVal != NULL);
     return retVal;
 }
index 9d84c01..d05cb55 100644 (file)
@@ -837,6 +837,12 @@ OBJECTREF ParamTypeDesc::GetManagedClassObject()
             pLoaderAllocator->ClearHandle(hExposedClassObject);
         }
 
+        if (OwnsTemplateMethodTable())
+        {
+            // Set the handle on template methodtable as well to make Object.GetType for arrays take the fast path
+            EnsureWritablePages(m_TemplateMT.GetValue()->GetWriteableDataForWrite())->m_hExposedClassObject = m_hExposedClassObject;
+        }
+
         // Log the TypeVarTypeDesc access
         g_IBCLogger.LogTypeMethodTableWriteableAccess(&th);