5858#include " array.h"
5959#include " castcache.h"
6060#include " dynamicinterfacecastable.h"
61+ #include " frozenobjectheap.h"
6162
6263#ifdef FEATURE_INTERPRETER
6364#include " interpreter.h"
@@ -3495,13 +3496,7 @@ void MethodTable::AllocateRegularStaticBoxes()
34953496
34963497 if (!pField->IsSpecialStatic () && pField->IsByValue ())
34973498 {
3498- TypeHandle th = pField->GetFieldTypeHandleThrowing ();
3499- MethodTable* pFieldMT = th.GetMethodTable ();
3500-
3501- LOG ((LF_CLASSLOADER, LL_INFO10000, " \t Instantiating static of type %s\n " , pFieldMT->GetDebugClassName ()));
3502- OBJECTREF obj = AllocateStaticBox (pFieldMT, HasFixedAddressVTStatics ());
3503-
3504- SetObjectReference ( (OBJECTREF*)(pStaticBase + pField->GetOffset ()), obj);
3499+ AllocateRegularStaticBox (pField, (Object**)(pStaticBase + pField->GetOffset ()));
35053500 }
35063501
35073502 pField++;
@@ -3510,14 +3505,47 @@ void MethodTable::AllocateRegularStaticBoxes()
35103505 GCPROTECT_END ();
35113506}
35123507
3508+ void MethodTable::AllocateRegularStaticBox (FieldDesc* pField, Object** boxedStaticHandle)
3509+ {
3510+ CONTRACTL
3511+ {
3512+ THROWS;
3513+ GC_TRIGGERS;
3514+ MODE_COOPERATIVE;
3515+ CONTRACTL_END;
3516+ }
3517+ _ASSERT (pField->IsStatic () && !pField->IsSpecialStatic () && pField->IsByValue ());
3518+
3519+ // Static fields are not pinned in collectible types so we need to protect the address
3520+ GCPROTECT_BEGININTERIOR (boxedStaticHandle);
3521+ if (VolatileLoad (boxedStaticHandle) == nullptr )
3522+ {
3523+ // Grab field's type handle before we enter lock
3524+ MethodTable* pFieldMT = pField->GetFieldTypeHandleThrowing ().GetMethodTable ();
3525+ bool hasFixedAddr = HasFixedAddressVTStatics ();
3526+
3527+ // Taking a lock since we might come here from multiple threads/places
3528+ CrstHolder crst (GetAppDomain ()->GetStaticBoxInitLock ());
3529+
3530+ // double-checked locking
3531+ if (VolatileLoad (boxedStaticHandle) == nullptr )
3532+ {
3533+ LOG ((LF_CLASSLOADER, LL_INFO10000, " \t Instantiating static of type %s\n " , pFieldMT->GetDebugClassName ()));
3534+ OBJECTREF obj = AllocateStaticBox (pFieldMT, hasFixedAddr, NULL , false );
3535+ SetObjectReference ((OBJECTREF*)(boxedStaticHandle), obj);
3536+ }
3537+ }
3538+ GCPROTECT_END ();
3539+ }
3540+
35133541// ==========================================================================================
3514- OBJECTREF MethodTable::AllocateStaticBox (MethodTable* pFieldMT, BOOL fPinned , OBJECTHANDLE* pHandle)
3542+ OBJECTREF MethodTable::AllocateStaticBox (MethodTable* pFieldMT, BOOL fPinned , OBJECTHANDLE* pHandle, bool canBeFrozen )
35153543{
35163544 CONTRACTL
35173545 {
35183546 THROWS;
35193547 GC_TRIGGERS;
3520- MODE_ANY ;
3548+ MODE_COOPERATIVE ;
35213549 CONTRACTL_END;
35223550 }
35233551
@@ -3526,7 +3554,22 @@ OBJECTREF MethodTable::AllocateStaticBox(MethodTable* pFieldMT, BOOL fPinned, OB
35263554 // Activate any dependent modules if necessary
35273555 pFieldMT->EnsureInstanceActive ();
35283556
3529- OBJECTREF obj = AllocateObject (pFieldMT);
3557+ OBJECTREF obj = NULL ;
3558+ if (canBeFrozen)
3559+ {
3560+ // In case if we don't plan to collect this handle we may try to allocate it on FOH
3561+ _ASSERT (!pFieldMT->ContainsPointers ());
3562+ _ASSERT (pHandle == nullptr );
3563+ FrozenObjectHeapManager* foh = SystemDomain::GetFrozenObjectHeapManager ();
3564+ obj = ObjectToOBJECTREF (foh->TryAllocateObject (pFieldMT, pFieldMT->GetBaseSize ()));
3565+ // obj can be null in case if struct is huge (>64kb)
3566+ if (obj != NULL )
3567+ {
3568+ return obj;
3569+ }
3570+ }
3571+
3572+ obj = AllocateObject (pFieldMT);
35303573
35313574 // Pin the object if necessary
35323575 if (fPinned )
0 commit comments