@@ -216,7 +216,7 @@ Module * ClassLoader::ComputeLoaderModule(MethodTable * pMT,
216
216
methodInst);
217
217
}
218
218
/* static*/
219
- Module *ClassLoader::ComputeLoaderModule (TypeKey *typeKey)
219
+ Module *ClassLoader::ComputeLoaderModule (const TypeKey *typeKey)
220
220
{
221
221
CONTRACTL
222
222
{
@@ -729,7 +729,7 @@ void ClassLoader::LazyPopulateCaseInsensitiveHashTables()
729
729
}
730
730
731
731
/* static*/
732
- void DECLSPEC_NORETURN ClassLoader::ThrowTypeLoadException (TypeKey *pKey,
732
+ void DECLSPEC_NORETURN ClassLoader::ThrowTypeLoadException (const TypeKey *pKey,
733
733
UINT resIDWhy)
734
734
{
735
735
STATIC_CONTRACT_THROWS;
@@ -743,7 +743,7 @@ void DECLSPEC_NORETURN ClassLoader::ThrowTypeLoadException(TypeKey *pKey,
743
743
744
744
#endif
745
745
746
- TypeHandle ClassLoader::LoadConstructedTypeThrowing (TypeKey *pKey,
746
+ TypeHandle ClassLoader::LoadConstructedTypeThrowing (const TypeKey *pKey,
747
747
LoadTypesFlag fLoadTypes /* = LoadTypes*/ ,
748
748
ClassLoadLevel level /* =CLASS_LOADED*/ ,
749
749
const InstantiationContext *pInstContext /* =NULL*/ )
@@ -858,7 +858,7 @@ void ClassLoader::TryEnsureLoaded(TypeHandle typeHnd, ClassLoadLevel level)
858
858
}
859
859
860
860
/* static */
861
- TypeHandle ClassLoader::LookupTypeKey (TypeKey *pKey, EETypeHashTable *pTable)
861
+ TypeHandle ClassLoader::LookupTypeKey (const TypeKey *pKey, EETypeHashTable *pTable)
862
862
{
863
863
CONTRACTL {
864
864
NOTHROW;
@@ -875,7 +875,7 @@ TypeHandle ClassLoader::LookupTypeKey(TypeKey *pKey, EETypeHashTable *pTable)
875
875
}
876
876
877
877
/* static */
878
- TypeHandle ClassLoader::LookupInLoaderModule (TypeKey *pKey)
878
+ TypeHandle ClassLoader::LookupInLoaderModule (const TypeKey *pKey)
879
879
{
880
880
CONTRACTL {
881
881
NOTHROW;
@@ -895,7 +895,7 @@ TypeHandle ClassLoader::LookupInLoaderModule(TypeKey *pKey)
895
895
896
896
897
897
/* static */
898
- TypeHandle ClassLoader::LookupTypeHandleForTypeKey (TypeKey *pKey)
898
+ TypeHandle ClassLoader::LookupTypeHandleForTypeKey (const TypeKey *pKey)
899
899
{
900
900
CONTRACTL
901
901
{
@@ -1659,12 +1659,6 @@ ClassLoader::~ClassLoader()
1659
1659
}
1660
1660
CONTRACTL_END
1661
1661
1662
- #ifdef _DEBUG
1663
- // Do not walk m_pUnresolvedClassHash at destruct time as it is loaderheap allocated memory
1664
- // and may already have been deallocated via an AllocMemTracker.
1665
- m_pUnresolvedClassHash = (PendingTypeLoadTable*)(UINT_PTR)0xcccccccc ;
1666
- #endif
1667
-
1668
1662
#ifdef _DEBUG
1669
1663
// LOG((
1670
1664
// LF_CLASSLOADER,
@@ -1704,7 +1698,6 @@ ClassLoader::~ClassLoader()
1704
1698
1705
1699
FreeModules ();
1706
1700
1707
- m_UnresolvedClassLock.Destroy ();
1708
1701
m_AvailableClassLock.Destroy ();
1709
1702
m_AvailableTypesLock.Destroy ();
1710
1703
}
@@ -1729,7 +1722,6 @@ ClassLoader::ClassLoader(Assembly *pAssembly)
1729
1722
1730
1723
m_pAssembly = pAssembly;
1731
1724
1732
- m_pUnresolvedClassHash = NULL ;
1733
1725
m_cUnhashedModules = 0 ;
1734
1726
1735
1727
#ifdef _DEBUG
@@ -1760,12 +1752,6 @@ VOID ClassLoader::Init(AllocMemTracker *pamTracker)
1760
1752
{
1761
1753
STANDARD_VM_CONTRACT;
1762
1754
1763
- m_pUnresolvedClassHash = PendingTypeLoadTable::Create (GetAssembly ()->GetLowFrequencyHeap (),
1764
- UNRESOLVED_CLASS_HASH_BUCKETS,
1765
- pamTracker);
1766
-
1767
- m_UnresolvedClassLock.Init (CrstUnresolvedClassLock);
1768
-
1769
1755
// This lock is taken within the classloader whenever we have to enter a
1770
1756
// type in one of the modules governed by the loader.
1771
1757
// The process of creating these types may be reentrant. The ordering has
@@ -2605,7 +2591,7 @@ ClassLoader::LoadApproxParentThrowing(
2605
2591
// Perform a single phase of class loading
2606
2592
// It is the caller's responsibility to lock
2607
2593
/* static*/
2608
- TypeHandle ClassLoader::DoIncrementalLoad (TypeKey *pTypeKey, TypeHandle typeHnd, ClassLoadLevel currentLevel)
2594
+ TypeHandle ClassLoader::DoIncrementalLoad (const TypeKey *pTypeKey, TypeHandle typeHnd, ClassLoadLevel currentLevel)
2609
2595
{
2610
2596
CONTRACTL
2611
2597
{
@@ -2679,7 +2665,7 @@ TypeHandle ClassLoader::DoIncrementalLoad(TypeKey *pTypeKey, TypeHandle typeHnd,
2679
2665
// For canonical instantiations of generic types, create a brand new method table
2680
2666
// For other constructed types, create a type desc and template method table if necessary
2681
2667
// For all other types, create a method table
2682
- TypeHandle ClassLoader::CreateTypeHandleForTypeKey (TypeKey* pKey, AllocMemTracker* pamTracker)
2668
+ TypeHandle ClassLoader::CreateTypeHandleForTypeKey (const TypeKey* pKey, AllocMemTracker* pamTracker)
2683
2669
{
2684
2670
CONTRACT (TypeHandle)
2685
2671
{
@@ -2794,7 +2780,7 @@ TypeHandle ClassLoader::CreateTypeHandleForTypeKey(TypeKey* pKey, AllocMemTracke
2794
2780
// particular, exact parent info (base class and interfaces) is loaded
2795
2781
// in a later phase
2796
2782
/* static*/
2797
- TypeHandle ClassLoader::PublishType (TypeKey *pTypeKey, TypeHandle typeHnd)
2783
+ TypeHandle ClassLoader::PublishType (const TypeKey *pTypeKey, TypeHandle typeHnd)
2798
2784
{
2799
2785
CONTRACTL
2800
2786
{
@@ -2994,7 +2980,7 @@ static void PushFinalLevels(TypeHandle typeHnd, ClassLoadLevel targetLevel, cons
2994
2980
2995
2981
2996
2982
//
2997
- TypeHandle ClassLoader::LoadTypeHandleForTypeKey (TypeKey *pTypeKey,
2983
+ TypeHandle ClassLoader::LoadTypeHandleForTypeKey (const TypeKey *pTypeKey,
2998
2984
TypeHandle typeHnd,
2999
2985
ClassLoadLevel targetLevel/* =CLASS_LOADED*/ ,
3000
2986
const InstantiationContext *pInstContext/* =NULL*/ )
@@ -3018,8 +3004,7 @@ TypeHandle ClassLoader::LoadTypeHandleForTypeKey(TypeKey *pTypeKey,
3018
3004
SString name;
3019
3005
TypeString::AppendTypeKeyDebug (name, pTypeKey);
3020
3006
LOG ((LF_CLASSLOADER, LL_INFO10000, " PHASEDLOAD: LoadTypeHandleForTypeKey for type %s to level %s\n " , name.GetUTF8 (), classLoadLevelName[targetLevel]));
3021
- CrstHolder unresolvedClassLockHolder (&m_UnresolvedClassLock);
3022
- m_pUnresolvedClassHash->Dump ();
3007
+ PendingTypeLoadTable::GetTable ()->Dump ();
3023
3008
}
3024
3009
#endif
3025
3010
@@ -3051,7 +3036,7 @@ TypeHandle ClassLoader::LoadTypeHandleForTypeKey(TypeKey *pTypeKey,
3051
3036
}
3052
3037
3053
3038
//
3054
- TypeHandle ClassLoader::LoadTypeHandleForTypeKeyNoLock (TypeKey *pTypeKey,
3039
+ TypeHandle ClassLoader::LoadTypeHandleForTypeKeyNoLock (const TypeKey *pTypeKey,
3055
3040
ClassLoadLevel targetLevel/* =CLASS_LOADED*/ ,
3056
3041
const InstantiationContext *pInstContext/* =NULL*/ )
3057
3042
{
@@ -3091,11 +3076,11 @@ TypeHandle ClassLoader::LoadTypeHandleForTypeKeyNoLock(TypeKey *pTypeKey,
3091
3076
class PendingTypeLoadHolder
3092
3077
{
3093
3078
Thread * m_pThread;
3094
- PendingTypeLoadEntry * m_pEntry;
3079
+ PendingTypeLoadTable::Entry * m_pEntry;
3095
3080
PendingTypeLoadHolder * m_pPrevious;
3096
3081
3097
3082
public:
3098
- PendingTypeLoadHolder (PendingTypeLoadEntry * pEntry)
3083
+ PendingTypeLoadHolder (PendingTypeLoadTable::Entry * pEntry)
3099
3084
{
3100
3085
LIMITED_METHOD_CONTRACT;
3101
3086
@@ -3114,7 +3099,7 @@ class PendingTypeLoadHolder
3114
3099
m_pThread->SetPendingTypeLoad (m_pPrevious);
3115
3100
}
3116
3101
3117
- static bool CheckForDeadLockOnCurrentThread (PendingTypeLoadEntry * pEntry)
3102
+ static bool CheckForDeadLockOnCurrentThread (PendingTypeLoadTable::Entry * pEntry)
3118
3103
{
3119
3104
LIMITED_METHOD_CONTRACT;
3120
3105
@@ -3136,7 +3121,7 @@ class PendingTypeLoadHolder
3136
3121
//
3137
3122
TypeHandle
3138
3123
ClassLoader::LoadTypeHandleForTypeKey_Body (
3139
- TypeKey * pTypeKey,
3124
+ const TypeKey * pTypeKey,
3140
3125
TypeHandle typeHnd,
3141
3126
ClassLoadLevel targetLevel)
3142
3127
{
@@ -3167,14 +3152,16 @@ ClassLoader::LoadTypeHandleForTypeKey_Body(
3167
3152
#endif
3168
3153
}
3169
3154
3170
- ReleaseHolder<PendingTypeLoadEntry> pLoadingEntry;
3171
- CrstHolderWithState unresolvedClassLockHolder (&m_UnresolvedClassLock, false );
3155
+ ReleaseHolder<PendingTypeLoadTable::Entry> pLoadingEntry;
3156
+ DWORD dwHashedTypeKey;
3157
+ PendingTypeLoadTable::Shard *pPendingTypeLoadShard = PendingTypeLoadTable::GetTable ()->GetShard (*pTypeKey, this , &dwHashedTypeKey);
3158
+ CrstHolderWithState unresolvedClassLockHolder (pPendingTypeLoadShard->GetCrst (), false );
3172
3159
3173
3160
retry:
3174
3161
unresolvedClassLockHolder.Acquire ();
3175
3162
3176
3163
// Is it in the hash of classes currently being loaded?
3177
- pLoadingEntry = m_pUnresolvedClassHash-> GetValue ( pTypeKey);
3164
+ pLoadingEntry = pPendingTypeLoadShard-> FindPendingTypeLoadEntry (dwHashedTypeKey, * pTypeKey);
3178
3165
if (pLoadingEntry)
3179
3166
{
3180
3167
pLoadingEntry->AddRef ();
@@ -3219,15 +3206,8 @@ ClassLoader::LoadTypeHandleForTypeKey_Body(
3219
3206
goto retry;
3220
3207
}
3221
3208
3222
- {
3223
- // Wait for class to be loaded by another thread. This is where we start tracking the
3224
- // entry, so there is an implicit Acquire in our use of Assign here.
3225
- CrstHolder loadingEntryLockHolder (&pLoadingEntry->m_Crst );
3226
- _ASSERTE (pLoadingEntry->HasLock ());
3227
- }
3228
-
3229
3209
// Result of other thread loading the class
3230
- HRESULT hr = pLoadingEntry->m_hrResult ;
3210
+ HRESULT hr = pLoadingEntry->DelayForProgress (&typeHnd) ;
3231
3211
3232
3212
if (FAILED (hr)) {
3233
3213
@@ -3262,9 +3242,6 @@ ClassLoader::LoadTypeHandleForTypeKey_Body(
3262
3242
pLoadingEntry->ThrowException ();
3263
3243
}
3264
3244
3265
- // Get a pointer to the EEClass being loaded
3266
- typeHnd = pLoadingEntry->m_typeHandle ;
3267
-
3268
3245
if (!typeHnd.IsNull ())
3269
3246
{
3270
3247
// If the type load on the other thread loaded the type to the needed level, return it here.
@@ -3294,12 +3271,7 @@ ClassLoader::LoadTypeHandleForTypeKey_Body(
3294
3271
3295
3272
// It was not loaded, and it is not being loaded, so we must load it. Create a new LoadingEntry
3296
3273
// and acquire it immediately so that other threads will block.
3297
- pLoadingEntry = new PendingTypeLoadEntry (*pTypeKey, typeHnd); // this atomically creates a crst and acquires it
3298
-
3299
- if (!(m_pUnresolvedClassHash->InsertValue (pLoadingEntry)))
3300
- {
3301
- COMPlusThrowOM ();
3302
- }
3274
+ pLoadingEntry = pPendingTypeLoadShard->InsertPendingTypeLoadEntry (dwHashedTypeKey, *pTypeKey, typeHnd); // this atomically creates a crst and acquires it
3303
3275
3304
3276
// Leave the global lock, so that other threads may now start waiting on our class's lock
3305
3277
unresolvedClassLockHolder.Release ();
@@ -3337,7 +3309,7 @@ ClassLoader::LoadTypeHandleForTypeKey_Body(
3337
3309
3338
3310
// Unlink this class from the unresolved class list.
3339
3311
unresolvedClassLockHolder.Acquire ();
3340
- m_pUnresolvedClassHash-> DeleteValue (pTypeKey );
3312
+ pPendingTypeLoadShard-> RemovePendingTypeLoadEntry (pLoadingEntry );
3341
3313
3342
3314
// Release the lock before proceeding. The unhandled exception filters take number of locks that
3343
3315
// have ordering violations with this lock.
@@ -3350,13 +3322,13 @@ ClassLoader::LoadTypeHandleForTypeKey_Body(
3350
3322
3351
3323
// Unlink this class from the unresolved class list.
3352
3324
unresolvedClassLockHolder.Acquire ();
3353
- m_pUnresolvedClassHash-> DeleteValue (pTypeKey );
3325
+ pPendingTypeLoadShard-> RemovePendingTypeLoadEntry (pLoadingEntry );
3354
3326
unresolvedClassLockHolder.Release ();
3355
3327
3356
3328
// Unblock any thread waiting to load same type as in TypeLoadEntry. This should be done
3357
- // after pLoadingEntry is removed from m_pUnresolvedClassHash . Otherwise the other thread
3329
+ // after pLoadingEntry is removed from the PendingTypeLoadTable . Otherwise the other thread
3358
3330
// (which was waiting) will keep spinning for a while after waking up, till the current thread removes
3359
- // pLoadingEntry from m_pUnresolvedClassHash . This can cause hang in situation when the current
3331
+ // pLoadingEntry from the PendingTypeLoadTable . This can cause hang in situation when the current
3360
3332
// thread is a background thread and so will get very less processor cycle to perform subsequent
3361
3333
// operations to remove the entry from hash later.
3362
3334
pLoadingEntry->UnblockWaiters ();
0 commit comments