Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEgor Bogatov <egorbo@gmail.com>2022-11-13 23:48:33 +0300
committerGitHub <noreply@github.com>2022-11-13 23:48:33 +0300
commitcabb8b089fd3d84fc46446c2079ddc1981b55fd9 (patch)
tree0e10026be06abd151eb3aa5d15406a38ee693f98
parentcc712fd7cb63fe92b730de0ac15a9012c7935cc9 (diff)
Allocate boxed static structs on Frozen Object Heap and remove getFieldAddress (#77737)HEADmain
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
-rw-r--r--src/coreclr/inc/CrstTypes.def4
-rw-r--r--src/coreclr/inc/corinfo.h11
-rw-r--r--src/coreclr/inc/crsttypes_generated.h47
-rw-r--r--src/coreclr/inc/icorjitinfoimpl_generated.h4
-rw-r--r--src/coreclr/inc/jiteeversionguid.h10
-rw-r--r--src/coreclr/jit/ICorJitInfo_names_generated.h1
-rw-r--r--src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp10
-rw-r--r--src/coreclr/jit/assertionprop.cpp3
-rw-r--r--src/coreclr/jit/compiler.h1
-rw-r--r--src/coreclr/jit/emitarm.cpp5
-rw-r--r--src/coreclr/jit/emitxarch.cpp14
-rw-r--r--src/coreclr/jit/fginline.cpp3
-rw-r--r--src/coreclr/jit/gentree.cpp10
-rw-r--r--src/coreclr/jit/gentree.h6
-rw-r--r--src/coreclr/jit/importer.cpp91
-rw-r--r--src/coreclr/jit/morph.cpp98
-rw-r--r--src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs19
-rw-r--r--src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs78
-rw-r--r--src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt1
-rw-r--r--src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs4
-rw-r--r--src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs4
-rw-r--r--src/coreclr/tools/aot/jitinterface/jitinterface_generated.h11
-rw-r--r--src/coreclr/tools/superpmi/superpmi-shared/agnostic.h6
-rw-r--r--src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp2
-rw-r--r--src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h1
-rw-r--r--src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp35
-rw-r--r--src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h6
-rw-r--r--src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp13
-rw-r--r--src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp8
-rw-r--r--src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp7
-rw-r--r--src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp7
-rw-r--r--src/coreclr/vm/appdomain.cpp1
-rw-r--r--src/coreclr/vm/appdomain.hpp7
-rw-r--r--src/coreclr/vm/frozenobjectheap.cpp4
-rw-r--r--src/coreclr/vm/jitinterface.cpp116
-rw-r--r--src/coreclr/vm/jitinterface.h1
-rw-r--r--src/coreclr/vm/methodtable.cpp79
-rw-r--r--src/coreclr/vm/methodtable.h3
-rw-r--r--src/tests/baseservices/compilerservices/FixedAddressValueType/FixedAddressValueType.cs77
39 files changed, 293 insertions, 515 deletions
diff --git a/src/coreclr/inc/CrstTypes.def b/src/coreclr/inc/CrstTypes.def
index 2179a45cadf..7ea873e18a3 100644
--- a/src/coreclr/inc/CrstTypes.def
+++ b/src/coreclr/inc/CrstTypes.def
@@ -577,3 +577,7 @@ End
Crst PgoData
AcquiredBefore LoaderHeap
End
+
+Crst StaticBoxInit
+ AcquiredBefore LoaderHeap FrozenObjectHeap
+End
diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h
index b4faaf34861..e42d8a64f9d 100644
--- a/src/coreclr/inc/corinfo.h
+++ b/src/coreclr/inc/corinfo.h
@@ -141,7 +141,7 @@ The first 4 options are mutually exclusive
have managed thread local statics, which work through the HELPER. Support for this is considered
legacy, and going forward, the EE should
- * <NONE> This is a normal static field. Its address in memory is determined by getFieldAddress. (see
+ * <NONE> This is a normal static field. Its address in memory is determined by getFieldInfo. (see
also CORINFO_FLG_STATIC_IN_HEAP).
@@ -1719,7 +1719,7 @@ struct CORINFO_FIELD_INFO
CorInfoIsAccessAllowedResult accessAllowed;
CORINFO_HELPER_DESC accessCalloutHelper;
- CORINFO_CONST_LOOKUP fieldLookup; // Used by Ready-to-Run
+ CORINFO_CONST_LOOKUP fieldLookup;
};
//----------------------------------------------------------------------------
@@ -3200,13 +3200,6 @@ public:
void **ppIndirection = NULL
) = 0;
-
- // return the data's address (for static fields only)
- virtual void* getFieldAddress(
- CORINFO_FIELD_HANDLE field,
- void **ppIndirection = NULL
- ) = 0;
-
//------------------------------------------------------------------------------
// getReadonlyStaticFieldValue: returns true and the actual field's value if the given
// field represents a statically initialized readonly field of any type.
diff --git a/src/coreclr/inc/crsttypes_generated.h b/src/coreclr/inc/crsttypes_generated.h
index 366e60cf9d2..93cd272894b 100644
--- a/src/coreclr/inc/crsttypes_generated.h
+++ b/src/coreclr/inc/crsttypes_generated.h
@@ -112,28 +112,29 @@ enum CrstType
CrstSingleUseLock = 94,
CrstSpecialStatics = 95,
CrstStackSampler = 96,
- CrstStressLog = 97,
- CrstStubCache = 98,
- CrstStubDispatchCache = 99,
- CrstStubUnwindInfoHeapSegments = 100,
- CrstSyncBlockCache = 101,
- CrstSyncHashLock = 102,
- CrstSystemBaseDomain = 103,
- CrstSystemDomain = 104,
- CrstSystemDomainDelayedUnloadList = 105,
- CrstThreadIdDispenser = 106,
- CrstThreadStore = 107,
- CrstTieredCompilation = 108,
- CrstTypeEquivalenceMap = 109,
- CrstTypeIDMap = 110,
- CrstUMEntryThunkCache = 111,
- CrstUMEntryThunkFreeListLock = 112,
- CrstUniqueStack = 113,
- CrstUnresolvedClassLock = 114,
- CrstUnwindInfoTableLock = 115,
- CrstVSDIndirectionCellLock = 116,
- CrstWrapperTemplate = 117,
- kNumberOfCrstTypes = 118
+ CrstStaticBoxInit = 97,
+ CrstStressLog = 98,
+ CrstStubCache = 99,
+ CrstStubDispatchCache = 100,
+ CrstStubUnwindInfoHeapSegments = 101,
+ CrstSyncBlockCache = 102,
+ CrstSyncHashLock = 103,
+ CrstSystemBaseDomain = 104,
+ CrstSystemDomain = 105,
+ CrstSystemDomainDelayedUnloadList = 106,
+ CrstThreadIdDispenser = 107,
+ CrstThreadStore = 108,
+ CrstTieredCompilation = 109,
+ CrstTypeEquivalenceMap = 110,
+ CrstTypeIDMap = 111,
+ CrstUMEntryThunkCache = 112,
+ CrstUMEntryThunkFreeListLock = 113,
+ CrstUniqueStack = 114,
+ CrstUnresolvedClassLock = 115,
+ CrstUnwindInfoTableLock = 116,
+ CrstVSDIndirectionCellLock = 117,
+ CrstWrapperTemplate = 118,
+ kNumberOfCrstTypes = 119
};
#endif // __CRST_TYPES_INCLUDED
@@ -241,6 +242,7 @@ int g_rgCrstLevelMap[] =
5, // CrstSingleUseLock
0, // CrstSpecialStatics
0, // CrstStackSampler
+ -1, // CrstStaticBoxInit
-1, // CrstStressLog
5, // CrstStubCache
0, // CrstStubDispatchCache
@@ -364,6 +366,7 @@ LPCSTR g_rgCrstNameMap[] =
"CrstSingleUseLock",
"CrstSpecialStatics",
"CrstStackSampler",
+ "CrstStaticBoxInit",
"CrstStressLog",
"CrstStubCache",
"CrstStubDispatchCache",
diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h
index dc05dced40a..9b1cd429542 100644
--- a/src/coreclr/inc/icorjitinfoimpl_generated.h
+++ b/src/coreclr/inc/icorjitinfoimpl_generated.h
@@ -616,10 +616,6 @@ unsigned getClassDomainID(
CORINFO_CLASS_HANDLE cls,
void** ppIndirection) override;
-void* getFieldAddress(
- CORINFO_FIELD_HANDLE field,
- void** ppIndirection) override;
-
bool getReadonlyStaticFieldValue(
CORINFO_FIELD_HANDLE field,
uint8_t* buffer,
diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h
index 601ba406d83..b24885dcbeb 100644
--- a/src/coreclr/inc/jiteeversionguid.h
+++ b/src/coreclr/inc/jiteeversionguid.h
@@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
#define GUID_DEFINED
#endif // !GUID_DEFINED
-constexpr GUID JITEEVersionIdentifier = { /* e452af1d-0a1a-44a8-a5b3-ef6074b8ab4a */
- 0xe452af1d,
- 0x0a1a,
- 0x44a8,
- {0xa5, 0xb3, 0xef, 0x60, 0x74, 0xb8, 0xab, 0x4a}
+constexpr GUID JITEEVersionIdentifier = { /* c0c94f6c-5358-4a3d-be83-b2a9d1b2545e */
+ 0xc0c94f6c,
+ 0x5358,
+ 0x4a3d,
+ {0xbe, 0x83, 0xb2, 0xa9, 0xd1, 0xb2, 0x54, 0x5e}
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/coreclr/jit/ICorJitInfo_names_generated.h b/src/coreclr/jit/ICorJitInfo_names_generated.h
index ed00cc19112..2971c082849 100644
--- a/src/coreclr/jit/ICorJitInfo_names_generated.h
+++ b/src/coreclr/jit/ICorJitInfo_names_generated.h
@@ -155,7 +155,6 @@ DEF_CLR_API(getCallInfo)
DEF_CLR_API(canAccessFamily)
DEF_CLR_API(isRIDClassDomainID)
DEF_CLR_API(getClassDomainID)
-DEF_CLR_API(getFieldAddress)
DEF_CLR_API(getReadonlyStaticFieldValue)
DEF_CLR_API(getStaticFieldCurrentClass)
DEF_CLR_API(getVarArgsHandle)
diff --git a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp
index 8cedeccd487..9b5c73589b6 100644
--- a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp
+++ b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp
@@ -1479,16 +1479,6 @@ unsigned WrapICorJitInfo::getClassDomainID(
return temp;
}
-void* WrapICorJitInfo::getFieldAddress(
- CORINFO_FIELD_HANDLE field,
- void** ppIndirection)
-{
- API_ENTER(getFieldAddress);
- void* temp = wrapHnd->getFieldAddress(field, ppIndirection);
- API_LEAVE(getFieldAddress);
- return temp;
-}
-
bool WrapICorJitInfo::getReadonlyStaticFieldValue(
CORINFO_FIELD_HANDLE field,
uint8_t* buffer,
diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp
index 9a4be3c6e4e..a3797e0f51a 100644
--- a/src/coreclr/jit/assertionprop.cpp
+++ b/src/coreclr/jit/assertionprop.cpp
@@ -3197,8 +3197,7 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree)
case TYP_SIMD32:
{
- simd32_t value = vnStore->ConstantValue<simd32_t>(vnCns);
-
+ simd32_t value = vnStore->ConstantValue<simd32_t>(vnCns);
GenTreeVecCon* vecCon = gtNewVconNode(tree->TypeGet());
vecCon->gtSimd32Val = value;
diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h
index 34a0b475d09..154cb199b75 100644
--- a/src/coreclr/jit/compiler.h
+++ b/src/coreclr/jit/compiler.h
@@ -5733,7 +5733,6 @@ private:
GenTree* fgMorphField(GenTree* tree, MorphAddrContext* mac);
GenTree* fgMorphExpandInstanceField(GenTree* tree, MorphAddrContext* mac);
GenTree* fgMorphExpandTlsFieldAddr(GenTree* tree);
- GenTree* fgMorphExpandStaticField(GenTree* tree);
bool fgCanFastTailCall(GenTreeCall* call, const char** failReason);
#if FEATURE_FASTTAILCALL
bool fgCallHasMustCopyByrefParameter(GenTreeCall* callee);
diff --git a/src/coreclr/jit/emitarm.cpp b/src/coreclr/jit/emitarm.cpp
index a546d5aaab9..741d2d50dfb 100644
--- a/src/coreclr/jit/emitarm.cpp
+++ b/src/coreclr/jit/emitarm.cpp
@@ -4012,10 +4012,7 @@ void emitter::emitIns_R_C(instruction ins, emitAttr attr, regNumber reg, CORINFO
}
else
{
- assert(!jitStaticFldIsGlobAddr(fldHnd));
- addr = (ssize_t)emitComp->info.compCompHnd->getFieldAddress(fldHnd, NULL);
- if (addr == NULL)
- NO_WAY("could not obtain address of static field");
+ assert(!"Normal statics are expected to be handled in the importer");
}
// We can use reg to load the constant address,
diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp
index 5dacf783fa5..635ef39fcf1 100644
--- a/src/coreclr/jit/emitxarch.cpp
+++ b/src/coreclr/jit/emitxarch.cpp
@@ -12977,18 +12977,8 @@ BYTE* emitter::emitOutputCV(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc)
else
{
// Special case: mov reg, fs:[ddd] or mov reg, [ddd]
- if (jitStaticFldIsGlobAddr(fldh))
- {
- addr = nullptr;
- }
- else
- {
- addr = (BYTE*)emitComp->info.compCompHnd->getFieldAddress(fldh, nullptr);
- if (addr == nullptr)
- {
- NO_WAY("could not obtain address of static field");
- }
- }
+ assert(jitStaticFldIsGlobAddr(fldh));
+ addr = nullptr;
}
BYTE* target = (addr + offs);
diff --git a/src/coreclr/jit/fginline.cpp b/src/coreclr/jit/fginline.cpp
index 9922e2cec43..dcd6a8b3bdd 100644
--- a/src/coreclr/jit/fginline.cpp
+++ b/src/coreclr/jit/fginline.cpp
@@ -1608,7 +1608,8 @@ Statement* Compiler::fgInlinePrependStatements(InlineInfo* inlineInfo)
GenTree* op2 = argNode->AsOp()->gtOp2;
if (op1->IsCall() &&
((op1->AsCall()->gtCallMoreFlags & GTF_CALL_M_HELPER_SPECIAL_DCE) != 0) &&
- (op2->gtOper == GT_FIELD) && ((op2->gtFlags & GTF_EXCEPT) == 0))
+ op2->OperIs(GT_IND) && op2->gtGetOp1()->IsIconHandle() &&
+ ((op2->gtFlags & GTF_EXCEPT) == 0))
{
JITDUMP("\nPerforming special dce on unused arg [%06u]:"
" actual arg [%06u] helper call [%06u]\n",
diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp
index 24081df5c38..506d5fb0f89 100644
--- a/src/coreclr/jit/gentree.cpp
+++ b/src/coreclr/jit/gentree.cpp
@@ -18079,6 +18079,16 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* pIsExact, b
}
}
}
+ else if (base->IsIconHandle(GTF_ICON_CONST_PTR, GTF_ICON_STATIC_HDL))
+ {
+ // Check if we have IND(ICON_HANDLE) that represents a static field
+ FieldSeq* fldSeq = base->AsIntCon()->gtFieldSeq;
+ if ((fldSeq != nullptr) && (fldSeq->GetOffset() == base->AsIntCon()->IconValue()))
+ {
+ CORINFO_FIELD_HANDLE fldHandle = base->AsIntCon()->gtFieldSeq->GetFieldHandle();
+ objClass = gtGetFieldClassHandle(fldHandle, pIsExact, pIsNonNull);
+ }
+ }
}
break;
diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h
index b78096914eb..b349a813286 100644
--- a/src/coreclr/jit/gentree.h
+++ b/src/coreclr/jit/gentree.h
@@ -2209,6 +2209,12 @@ public:
return (gtOper == GT_CNS_INT) && ((gtFlags & GTF_ICON_HDL_MASK) == handleType);
}
+ template <typename... T>
+ bool IsIconHandle(GenTreeFlags handleType, T... rest) const
+ {
+ return IsIconHandle(handleType) || IsIconHandle(rest...);
+ }
+
// Return just the part of the flags corresponding to the GTF_ICON_*_HDL flag.
// For non-icon handle trees, returns GTF_EMPTY.
GenTreeFlags GetIconHandleFlag() const
diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp
index 19e2c842393..062181d15ea 100644
--- a/src/coreclr/jit/importer.cpp
+++ b/src/coreclr/jit/importer.cpp
@@ -1615,9 +1615,9 @@ GenTree* Compiler::impNormStructVal(GenTree* structVal, CORINFO_CLASS_HANDLE str
// In case of a chained GT_COMMA case, we sink the last
// GT_COMMA below the blockNode addr.
GenTree* blockNodeAddr = blockNode->AsOp()->gtOp1;
- assert(blockNodeAddr->gtType == TYP_BYREF);
+ assert(blockNodeAddr->TypeIs(TYP_BYREF, TYP_I_IMPL));
GenTree* commaNode = parent;
- commaNode->gtType = TYP_BYREF;
+ commaNode->gtType = blockNodeAddr->gtType;
commaNode->AsOp()->gtOp2 = blockNodeAddr;
blockNode->AsOp()->gtOp1 = commaNode;
if (parent == structVal)
@@ -4374,6 +4374,9 @@ GenTree* Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedT
FieldSeq::FieldKind fieldKind =
isSharedStatic ? FieldSeq::FieldKind::SharedStatic : FieldSeq::FieldKind::SimpleStatic;
+ bool hasConstAddr = (pFieldInfo->fieldAccessor == CORINFO_FIELD_STATIC_ADDRESS) ||
+ (pFieldInfo->fieldAccessor == CORINFO_FIELD_STATIC_RVA_ADDRESS);
+
FieldSeq* innerFldSeq;
FieldSeq* outerFldSeq;
if (isBoxedStatic)
@@ -4383,14 +4386,11 @@ GenTree* Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedT
}
else
{
- bool hasConstAddr = (pFieldInfo->fieldAccessor == CORINFO_FIELD_STATIC_ADDRESS) ||
- (pFieldInfo->fieldAccessor == CORINFO_FIELD_STATIC_RVA_ADDRESS);
-
ssize_t offset;
if (hasConstAddr)
{
- offset = reinterpret_cast<ssize_t>(info.compCompHnd->getFieldAddress(pResolvedToken->hField));
- assert(offset != 0);
+ assert(pFieldInfo->fieldLookup.accessType == IAT_VALUE);
+ offset = reinterpret_cast<ssize_t>(pFieldInfo->fieldLookup.addr);
}
else
{
@@ -4401,6 +4401,7 @@ GenTree* Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedT
outerFldSeq = nullptr;
}
+ bool isStaticReadOnlyInitedRef = false;
GenTree* op1;
switch (pFieldInfo->fieldAccessor)
{
@@ -4493,53 +4494,41 @@ GenTree* Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedT
default:
{
- // Do we need the address of a static field?
- //
- if (access & CORINFO_ACCESS_ADDRESS)
+// TODO-CQ: enable this optimization for 32 bit targets.
+#ifdef TARGET_64BIT
+ if (!isBoxedStatic && (lclTyp == TYP_REF) && ((access & CORINFO_ACCESS_ADDRESS) == 0))
{
- void** pFldAddr = nullptr;
- void* fldAddr = info.compCompHnd->getFieldAddress(pResolvedToken->hField, (void**)&pFldAddr);
-
- // We should always be able to access this static's address directly.
- assert(pFldAddr == nullptr);
-
- // Create the address node.
- GenTreeFlags handleKind = isBoxedStatic ? GTF_ICON_STATIC_BOX_PTR : GTF_ICON_STATIC_HDL;
- op1 = gtNewIconHandleNode((size_t)fldAddr, handleKind, innerFldSeq);
- INDEBUG(op1->AsIntCon()->gtTargetHandle = reinterpret_cast<size_t>(pResolvedToken->hField));
-
- if (pFieldInfo->fieldFlags & CORINFO_FLG_FIELD_INITCLASS)
+ bool isSpeculative = true;
+ if ((info.compCompHnd->getStaticFieldCurrentClass(pResolvedToken->hField, &isSpeculative) !=
+ NO_CLASS_HANDLE))
{
- op1->gtFlags |= GTF_ICON_INITCLASS;
+ isStaticReadOnlyInitedRef = !isSpeculative;
}
}
- else // We need the value of a static field
- {
- op1 = gtNewFieldRef(lclTyp, pResolvedToken->hField);
-
- if (pFieldInfo->fieldFlags & CORINFO_FLG_FIELD_INITCLASS)
- {
- op1->gtFlags |= GTF_FLD_INITCLASS;
- }
-
- if (isBoxedStatic)
- {
- op1->ChangeType(TYP_REF); // points at boxed object
- op1 = gtNewOperNode(GT_ADD, TYP_BYREF, op1, gtNewIconNode(TARGET_POINTER_SIZE, outerFldSeq));
-
- if (varTypeIsStruct(lclTyp))
- {
- // Constructor adds GTF_GLOB_REF. Note that this is *not* GTF_EXCEPT.
- op1 = gtNewObjNode(pFieldInfo->structType, op1);
- }
- else
- {
- op1 = gtNewOperNode(GT_IND, lclTyp, op1);
- op1->gtFlags |= (GTF_GLOB_REF | GTF_IND_NONFAULTING);
- }
- }
+#endif // TARGET_64BIT
- return op1;
+ assert(hasConstAddr);
+ assert(pFieldInfo->fieldLookup.addr != nullptr);
+ assert(pFieldInfo->fieldLookup.accessType == IAT_VALUE);
+ size_t fldAddr = reinterpret_cast<size_t>(pFieldInfo->fieldLookup.addr);
+ GenTreeFlags handleKind;
+ if (isBoxedStatic)
+ {
+ handleKind = GTF_ICON_STATIC_BOX_PTR;
+ }
+ else if (isStaticReadOnlyInitedRef)
+ {
+ handleKind = GTF_ICON_CONST_PTR;
+ }
+ else
+ {
+ handleKind = GTF_ICON_STATIC_HDL;
+ }
+ op1 = gtNewIconHandleNode(fldAddr, handleKind, innerFldSeq);
+ INDEBUG(op1->AsIntCon()->gtTargetHandle = reinterpret_cast<size_t>(pResolvedToken->hField));
+ if (pFieldInfo->fieldFlags & CORINFO_FLG_FIELD_INITCLASS)
+ {
+ op1->gtFlags |= GTF_ICON_INITCLASS;
}
break;
}
@@ -4563,6 +4552,10 @@ GenTree* Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedT
op1 = gtNewOperNode(GT_IND, lclTyp, op1);
op1->gtFlags |= GTF_GLOB_REF;
}
+ if (isStaticReadOnlyInitedRef)
+ {
+ op1->gtFlags |= (GTF_IND_INVARIANT | GTF_IND_NONFAULTING | GTF_IND_NONNULL);
+ }
}
return op1;
diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp
index 2ea9f1225e3..c86087a6778 100644
--- a/src/coreclr/jit/morph.cpp
+++ b/src/coreclr/jit/morph.cpp
@@ -5033,7 +5033,7 @@ GenTree* Compiler::fgMorphField(GenTree* tree, MorphAddrContext* mac)
}
else
{
- tree = fgMorphExpandStaticField(tree);
+ assert(!"Normal statics are expected to be handled in the importer");
}
// Pass down the current mac; if non null we are computing an address
@@ -5371,102 +5371,6 @@ GenTree* Compiler::fgMorphExpandTlsFieldAddr(GenTree* tree)
return tree;
}
-//------------------------------------------------------------------------
-// fgMorphExpandStaticField: Expand a simple static field load.
-//
-// Transforms the field into an explicit indirection off of a constant
-// address.
-//
-// Arguments:
-// tree - The GT_FIELD tree
-//
-// Return Value:
-// The expanded tree - a GT_IND.
-//
-GenTree* Compiler::fgMorphExpandStaticField(GenTree* tree)
-{
- // Note we do not support "FIELD_ADDR"s for simple statics.
- assert(tree->OperIs(GT_FIELD) && tree->AsField()->IsStatic());
-
- // If we can we access the static's address directly
- // then pFldAddr will be NULL and
- // fldAddr will be the actual address of the static field
- //
- CORINFO_FIELD_HANDLE fieldHandle = tree->AsField()->gtFldHnd;
- void** pFldAddr = nullptr;
- void* fldAddr = info.compCompHnd->getFieldAddress(fieldHandle, (void**)&pFldAddr);
-
- // We should always be able to access this static field address directly
- //
- assert(pFldAddr == nullptr);
-
- // For boxed statics, this direct address will be for the box. We have already added
- // the indirection for the field itself and attached the sequence, in importation.
- FieldSeq* fieldSeq = nullptr;
- bool isBoxedStatic = gtIsStaticFieldPtrToBoxedStruct(tree->TypeGet(), fieldHandle);
- if (!isBoxedStatic)
- {
- // Only simple statics get importred as GT_FIELDs.
- fieldSeq = GetFieldSeqStore()->Create(fieldHandle, reinterpret_cast<size_t>(fldAddr),
- FieldSeq::FieldKind::SimpleStatic);
- }
-
- // TODO-CQ: enable this optimization for 32 bit targets.
- bool isStaticReadOnlyInited = false;
-#ifdef TARGET_64BIT
- if (tree->TypeIs(TYP_REF) && !isBoxedStatic)
- {
- bool pIsSpeculative = true;
- if (info.compCompHnd->getStaticFieldCurrentClass(fieldHandle, &pIsSpeculative) != NO_CLASS_HANDLE)
- {
- isStaticReadOnlyInited = !pIsSpeculative;
- }
- }
-#endif // TARGET_64BIT
-
- GenTreeFlags handleKind = GTF_EMPTY;
- if (isBoxedStatic)
- {
- handleKind = GTF_ICON_STATIC_BOX_PTR;
- }
- else if (isStaticReadOnlyInited)
- {
- handleKind = GTF_ICON_CONST_PTR;
- }
- else
- {
- handleKind = GTF_ICON_STATIC_HDL;
- }
- GenTreeIntCon* addr = gtNewIconHandleNode((size_t)fldAddr, handleKind, fieldSeq);
- INDEBUG(addr->gtTargetHandle = reinterpret_cast<size_t>(fieldHandle));
-
- // Translate GTF_FLD_INITCLASS to GTF_ICON_INITCLASS, if we need to.
- if (((tree->gtFlags & GTF_FLD_INITCLASS) != 0) && !isStaticReadOnlyInited)
- {
- tree->gtFlags &= ~GTF_FLD_INITCLASS;
- addr->gtFlags |= GTF_ICON_INITCLASS;
- }
-
- tree->SetOper(GT_IND);
- tree->AsOp()->gtOp1 = addr;
-
- if (isBoxedStatic)
- {
- // The box for the static cannot be null, and is logically invariant, since it
- // represents (a base for) the static's address.
- tree->gtFlags |= (GTF_IND_INVARIANT | GTF_IND_NONFAULTING | GTF_IND_NONNULL);
- }
- else if (isStaticReadOnlyInited)
- {
- JITDUMP("Marking initialized static read-only field '%s' as invariant.\n", eeGetFieldName(fieldHandle));
-
- // Static readonly field is not null at this point (see getStaticFieldCurrentClass impl).
- tree->gtFlags |= (GTF_IND_INVARIANT | GTF_IND_NONFAULTING | GTF_IND_NONNULL);
- }
-
- return tree;
-}
-
//------------------------------------------------------------------------------
// fgMorphCallInline: attempt to inline a call
//
diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
index 7b1ce731f25..ce51202d1ae 100644
--- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
+++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
@@ -3346,25 +3346,6 @@ namespace Internal.JitInterface
private uint getClassDomainID(CORINFO_CLASS_STRUCT_* cls, ref void* ppIndirection)
{ throw new NotImplementedException("getClassDomainID"); }
- private void* getFieldAddress(CORINFO_FIELD_STRUCT_* field, void** ppIndirection)
- {
- FieldDesc fieldDesc = HandleToObject(field);
- Debug.Assert(fieldDesc.HasRva);
- ISymbolNode node = _compilation.GetFieldRvaData(fieldDesc);
- void *handle = (void *)ObjectToHandle(node);
- if (node.RepresentsIndirectionCell)
- {
- *ppIndirection = handle;
- return null;
- }
- else
- {
- if (ppIndirection != null)
- *ppIndirection = null;
- return handle;
- }
- }
-
private CORINFO_CLASS_STRUCT_* getStaticFieldCurrentClass(CORINFO_FIELD_STRUCT_* field, byte* pIsSpeculative)
{
if (pIsSpeculative != null)
diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs
index 40218af44e7..ddc81d77eb7 100644
--- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs
+++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs
@@ -2244,21 +2244,6 @@ namespace Internal.JitInterface
}
[UnmanagedCallersOnly]
- private static void* _getFieldAddress(IntPtr thisHandle, IntPtr* ppException, CORINFO_FIELD_STRUCT_* field, void** ppIndirection)
- {
- var _this = GetThis(thisHandle);
- try
- {
- return _this.getFieldAddress(field, ppIndirection);
- }
- catch (Exception ex)
- {
- *ppException = _this.AllocException(ex);
- return default;
- }
- }
-
- [UnmanagedCallersOnly]
private static byte _getReadonlyStaticFieldValue(IntPtr thisHandle, IntPtr* ppException, CORINFO_FIELD_STRUCT_* field, byte* buffer, int bufferSize, byte ignoreMovableObjects)
{
var _this = GetThis(thisHandle);
@@ -2700,7 +2685,7 @@ namespace Internal.JitInterface
private static IntPtr GetUnmanagedCallbacks()
{
- void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 182);
+ void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 181);
callbacks[0] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, byte>)&_isIntrinsic;
callbacks[1] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, uint>)&_getMethodAttribs;
@@ -2853,37 +2838,36 @@ namespace Internal.JitInterface
callbacks[148] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, CORINFO_CLASS_STRUCT_*, byte>)&_canAccessFamily;
callbacks[149] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, byte>)&_isRIDClassDomainID;
callbacks[150] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, void**, uint>)&_getClassDomainID;
- callbacks[151] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, void**, void*>)&_getFieldAddress;
- callbacks[152] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, byte*, int, byte, byte>)&_getReadonlyStaticFieldValue;
- callbacks[153] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, byte*, CORINFO_CLASS_STRUCT_*>)&_getStaticFieldCurrentClass;
- callbacks[154] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_SIG_INFO*, void**, IntPtr>)&_getVarArgsHandle;
- callbacks[155] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_SIG_INFO*, byte>)&_canGetVarArgsHandle;
- callbacks[156] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_MODULE_STRUCT_*, mdToken, void**, InfoAccessType>)&_constructStringLiteral;
- callbacks[157] = (delegate* unmanaged<IntPtr, IntPtr*, void**, InfoAccessType>)&_emptyStringLiteral;
- callbacks[158] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, void**, uint>)&_getFieldThreadLocalStoreID;
- callbacks[159] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_MODULE_STRUCT_*, CORINFO_MODULE_STRUCT_*, void>)&_addActiveDependency;
- callbacks[160] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, CORINFO_CLASS_STRUCT_*, CORINFO_METHOD_STRUCT_*, DelegateCtorArgs*, CORINFO_METHOD_STRUCT_*>)&_GetDelegateCtor;
- callbacks[161] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, void>)&_MethodCompileComplete;
- callbacks[162] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_RESOLVED_TOKEN*, CORINFO_SIG_INFO*, CORINFO_GET_TAILCALL_HELPERS_FLAGS, CORINFO_TAILCALL_HELPERS*, byte>)&_getTailCallHelpers;
- callbacks[163] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_RESOLVED_TOKEN*, byte, byte>)&_convertPInvokeCalliToCall;
- callbacks[164] = (delegate* unmanaged<IntPtr, IntPtr*, InstructionSet, byte, byte>)&_notifyInstructionSetUsage;
- callbacks[165] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CONST_LOOKUP*, void>)&_updateEntryPointForTailCall;
- callbacks[166] = (delegate* unmanaged<IntPtr, IntPtr*, AllocMemArgs*, void>)&_allocMem;
- callbacks[167] = (delegate* unmanaged<IntPtr, IntPtr*, byte, byte, uint, void>)&_reserveUnwindInfo;
- callbacks[168] = (delegate* unmanaged<IntPtr, IntPtr*, byte*, byte*, uint, uint, uint, byte*, CorJitFuncKind, void>)&_allocUnwindInfo;
- callbacks[169] = (delegate* unmanaged<IntPtr, IntPtr*, UIntPtr, void*>)&_allocGCInfo;
- callbacks[170] = (delegate* unmanaged<IntPtr, IntPtr*, uint, void>)&_setEHcount;
- callbacks[171] = (delegate* unmanaged<IntPtr, IntPtr*, uint, CORINFO_EH_CLAUSE*, void>)&_setEHinfo;
- callbacks[172] = (delegate* unmanaged<IntPtr, IntPtr*, uint, byte*, IntPtr, byte>)&_logMsg;
- callbacks[173] = (delegate* unmanaged<IntPtr, IntPtr*, byte*, int, byte*, int>)&_doAssert;
- callbacks[174] = (delegate* unmanaged<IntPtr, IntPtr*, CorJitResult, void>)&_reportFatalError;
- callbacks[175] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, PgoInstrumentationSchema**, uint*, byte**, PgoSource*, HRESULT>)&_getPgoInstrumentationResults;
- callbacks[176] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, PgoInstrumentationSchema*, uint, byte**, HRESULT>)&_allocPgoInstrumentationBySchema;
- callbacks[177] = (delegate* unmanaged<IntPtr, IntPtr*, uint, CORINFO_SIG_INFO*, CORINFO_METHOD_STRUCT_*, void>)&_recordCallSite;
- callbacks[178] = (delegate* unmanaged<IntPtr, IntPtr*, void*, void*, void*, ushort, ushort, int, void>)&_recordRelocation;
- callbacks[179] = (delegate* unmanaged<IntPtr, IntPtr*, void*, ushort>)&_getRelocTypeHint;
- callbacks[180] = (delegate* unmanaged<IntPtr, IntPtr*, uint>)&_getExpectedTargetArchitecture;
- callbacks[181] = (delegate* unmanaged<IntPtr, IntPtr*, CORJIT_FLAGS*, uint, uint>)&_getJitFlags;
+ callbacks[151] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, byte*, int, byte, byte>)&_getReadonlyStaticFieldValue;
+ callbacks[152] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, byte*, CORINFO_CLASS_STRUCT_*>)&_getStaticFieldCurrentClass;
+ callbacks[153] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_SIG_INFO*, void**, IntPtr>)&_getVarArgsHandle;
+ callbacks[154] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_SIG_INFO*, byte>)&_canGetVarArgsHandle;
+ callbacks[155] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_MODULE_STRUCT_*, mdToken, void**, InfoAccessType>)&_constructStringLiteral;
+ callbacks[156] = (delegate* unmanaged<IntPtr, IntPtr*, void**, InfoAccessType>)&_emptyStringLiteral;
+ callbacks[157] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_FIELD_STRUCT_*, void**, uint>)&_getFieldThreadLocalStoreID;
+ callbacks[158] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_MODULE_STRUCT_*, CORINFO_MODULE_STRUCT_*, void>)&_addActiveDependency;
+ callbacks[159] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, CORINFO_CLASS_STRUCT_*, CORINFO_METHOD_STRUCT_*, DelegateCtorArgs*, CORINFO_METHOD_STRUCT_*>)&_GetDelegateCtor;
+ callbacks[160] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, void>)&_MethodCompileComplete;
+ callbacks[161] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_RESOLVED_TOKEN*, CORINFO_SIG_INFO*, CORINFO_GET_TAILCALL_HELPERS_FLAGS, CORINFO_TAILCALL_HELPERS*, byte>)&_getTailCallHelpers;
+ callbacks[162] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_RESOLVED_TOKEN*, byte, byte>)&_convertPInvokeCalliToCall;
+ callbacks[163] = (delegate* unmanaged<IntPtr, IntPtr*, InstructionSet, byte, byte>)&_notifyInstructionSetUsage;
+ callbacks[164] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CONST_LOOKUP*, void>)&_updateEntryPointForTailCall;
+ callbacks[165] = (delegate* unmanaged<IntPtr, IntPtr*, AllocMemArgs*, void>)&_allocMem;
+ callbacks[166] = (delegate* unmanaged<IntPtr, IntPtr*, byte, byte, uint, void>)&_reserveUnwindInfo;
+ callbacks[167] = (delegate* unmanaged<IntPtr, IntPtr*, byte*, byte*, uint, uint, uint, byte*, CorJitFuncKind, void>)&_allocUnwindInfo;
+ callbacks[168] = (delegate* unmanaged<IntPtr, IntPtr*, UIntPtr, void*>)&_allocGCInfo;
+ callbacks[169] = (delegate* unmanaged<IntPtr, IntPtr*, uint, void>)&_setEHcount;
+ callbacks[170] = (delegate* unmanaged<IntPtr, IntPtr*, uint, CORINFO_EH_CLAUSE*, void>)&_setEHinfo;
+ callbacks[171] = (delegate* unmanaged<IntPtr, IntPtr*, uint, byte*, IntPtr, byte>)&_logMsg;
+ callbacks[172] = (delegate* unmanaged<IntPtr, IntPtr*, byte*, int, byte*, int>)&_doAssert;
+ callbacks[173] = (delegate* unmanaged<IntPtr, IntPtr*, CorJitResult, void>)&_reportFatalError;
+ callbacks[174] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, PgoInstrumentationSchema**, uint*, byte**, PgoSource*, HRESULT>)&_getPgoInstrumentationResults;
+ callbacks[175] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, PgoInstrumentationSchema*, uint, byte**, HRESULT>)&_allocPgoInstrumentationBySchema;
+ callbacks[176] = (delegate* unmanaged<IntPtr, IntPtr*, uint, CORINFO_SIG_INFO*, CORINFO_METHOD_STRUCT_*, void>)&_recordCallSite;
+ callbacks[177] = (delegate* unmanaged<IntPtr, IntPtr*, void*, void*, void*, ushort, ushort, int, void>)&_recordRelocation;
+ callbacks[178] = (delegate* unmanaged<IntPtr, IntPtr*, void*, ushort>)&_getRelocTypeHint;
+ callbacks[179] = (delegate* unmanaged<IntPtr, IntPtr*, uint>)&_getExpectedTargetArchitecture;
+ callbacks[180] = (delegate* unmanaged<IntPtr, IntPtr*, CORJIT_FLAGS*, uint, uint>)&_getJitFlags;
return (IntPtr)callbacks;
}
diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt
index d33bea88a4c..6b94ca32742 100644
--- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt
+++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt
@@ -307,7 +307,6 @@ FUNCTIONS
bool canAccessFamily(CORINFO_METHOD_HANDLE hCaller, CORINFO_CLASS_HANDLE hInstanceType);
bool isRIDClassDomainID(CORINFO_CLASS_HANDLE cls);
unsigned getClassDomainID (CORINFO_CLASS_HANDLE cls, void **ppIndirection);
- void* getFieldAddress(CORINFO_FIELD_HANDLE field, VOIDSTARSTAR ppIndirection);
bool getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint8_t *buffer, int bufferSize, bool ignoreMovableObjects);
CORINFO_CLASS_HANDLE getStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, BoolStar pIsSpeculative);
CORINFO_VARARGS_HANDLE getVarArgsHandle(CORINFO_SIG_INFO *pSig, void **ppIndirection);
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs
index 974590abe9e..773e4df50c2 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs
@@ -1499,6 +1499,10 @@ namespace Internal.JitInterface
// TODO: Handle the case when the RVA is in the TLS range
fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_RVA_ADDRESS;
+ ISymbolNode node = _compilation.GetFieldRvaData(field);
+ pResult->fieldLookup.addr = (void*)ObjectToHandle(node);
+ pResult->fieldLookup.accessType = node.RepresentsIndirectionCell ? InfoAccessType.IAT_PVALUE : InfoAccessType.IAT_VALUE;
+
// We are not going through a helper. The constructor has to be triggered explicitly.
if (!IsClassPreInited(field.OwningType))
{
diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs
index d4641674406..76725e2fc1e 100644
--- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs
+++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs
@@ -2063,6 +2063,10 @@ namespace Internal.JitInterface
// TODO: Handle the case when the RVA is in the TLS range
fieldAccessor = CORINFO_FIELD_ACCESSOR.CORINFO_FIELD_STATIC_RVA_ADDRESS;
+ ISymbolNode node = _compilation.GetFieldRvaData(field);
+ pResult->fieldLookup.addr = (void*)ObjectToHandle(node);
+ pResult->fieldLookup.accessType = node.RepresentsIndirectionCell ? InfoAccessType.IAT_PVALUE : InfoAccessType.IAT_VALUE;
+
// We are not going through a helper. The constructor has to be triggered explicitly.
if (_compilation.HasLazyStaticConstructor(field.OwningType))
{
diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h
index 4f2f5944d2d..2326246a090 100644
--- a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h
+++ b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h
@@ -162,7 +162,6 @@ struct JitInterfaceCallbacks
bool (* canAccessFamily)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE hCaller, CORINFO_CLASS_HANDLE hInstanceType);
bool (* isRIDClassDomainID)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls);
unsigned (* getClassDomainID)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls, void** ppIndirection);
- void* (* getFieldAddress)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, void** ppIndirection);
bool (* getReadonlyStaticFieldValue)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, uint8_t* buffer, int bufferSize, bool ignoreMovableObjects);
CORINFO_CLASS_HANDLE (* getStaticFieldCurrentClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, bool* pIsSpeculative);
CORINFO_VARARGS_HANDLE (* getVarArgsHandle)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_SIG_INFO* pSig, void** ppIndirection);
@@ -1657,16 +1656,6 @@ public:
return temp;
}
- virtual void* getFieldAddress(
- CORINFO_FIELD_HANDLE field,
- void** ppIndirection)
-{
- CorInfoExceptionClass* pException = nullptr;
- void* temp = _callbacks->getFieldAddress(_thisHandle, &pException, field, ppIndirection);
- if (pException != nullptr) throw pException;
- return temp;
-}
-
virtual bool getReadonlyStaticFieldValue(
CORINFO_FIELD_HANDLE field,
uint8_t* buffer,
diff --git a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h
index b4e16e87703..6c9da5cb6b3 100644
--- a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h
+++ b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h
@@ -198,12 +198,6 @@ struct Agnostic_GetOSRInfo
unsigned ilOffset;
};
-struct Agnostic_GetFieldAddress
-{
- DWORDLONG ppIndirection;
- DWORDLONG fieldAddress;
-};
-
struct Agnostic_GetStaticFieldCurrentClass
{
DWORDLONG classHandle;
diff --git a/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp
index 327435391fc..e0cb6a6020e 100644
--- a/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp
+++ b/src/coreclr/tools/superpmi/superpmi-shared/compileresult.cpp
@@ -926,7 +926,7 @@ void CompileResult::applyRelocs(RelocContext* rc, unsigned char* block1, ULONG b
if (index == -1)
{
// See if the original address is in the replay address map. This happens for
- // relocations on static field addresses found via getFieldAddress().
+ // relocations on static field addresses found via getFieldInfo().
void* origAddr = repAddressMap((void*)tmp.target);
if ((origAddr != (void*)-1) && (origAddr != nullptr))
{
diff --git a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h
index 588d96884df..66c6b910f45 100644
--- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h
+++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h
@@ -79,7 +79,6 @@ LWM(GetDefaultEqualityComparerClass, DWORDLONG, DWORDLONG)
LWM(GetDelegateCtor, Agnostic_GetDelegateCtorIn, Agnostic_GetDelegateCtorOut)
LWM(GetEEInfo, DWORD, Agnostic_CORINFO_EE_INFO)
LWM(GetEHinfo, DLD, Agnostic_CORINFO_EH_CLAUSE)
-LWM(GetFieldAddress, DWORDLONG, Agnostic_GetFieldAddress)
LWM(GetReadonlyStaticFieldValue, DLDD, DD)
LWM(GetStaticFieldCurrentClass, DWORDLONG, Agnostic_GetStaticFieldCurrentClass)
LWM(GetFieldClass, DWORDLONG, DWORDLONG)
diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp
index cb6db7560e2..91b6daf5250 100644
--- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp
+++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp
@@ -3628,41 +3628,6 @@ CORINFO_METHOD_HANDLE MethodContext::repEmbedMethodHandle(CORINFO_METHOD_HANDLE
return (CORINFO_METHOD_HANDLE)value.B;
}
-void MethodContext::recGetFieldAddress(CORINFO_FIELD_HANDLE field, void** ppIndirection, void* result, CorInfoType cit)
-{
- if (GetFieldAddress == nullptr)
- GetFieldAddress = new LightWeightMap<DWORDLONG, Agnostic_GetFieldAddress>();
-
- Agnostic_GetFieldAddress value;
- if (ppIndirection == nullptr)
- value.ppIndirection = 0;
- else
- value.ppIndirection = CastPointer(*ppIndirection);
- value.fieldAddress = CastPointer(result);
-
- DWORDLONG key = CastHandle(field);
- GetFieldAddress->Add(key, value);
- DEBUG_REC(dmpGetFieldAddress(key, value));
-}
-void MethodContext::dmpGetFieldAddress(DWORDLONG key, const Agnostic_GetFieldAddress& value)
-{
- printf("GetFieldAddress key fld-%016llX, value ppi-%016llX addr-%016llX", key, value.ppIndirection, value.fieldAddress);
-}
-void* MethodContext::repGetFieldAddress(CORINFO_FIELD_HANDLE field, void** ppIndirection)
-{
- DWORDLONG key = CastHandle(field);
- AssertMapAndKeyExist(GetFieldAddress, key, ": key %016llX", key);
-
- Agnostic_GetFieldAddress value = GetFieldAddress->Get(key);
- DEBUG_REP(dmpGetFieldAddress(key, value));
-
- if (ppIndirection != nullptr)
- {
- *ppIndirection = (void*)value.ppIndirection;
- }
- return (void*)value.fieldAddress;
-}
-
void MethodContext::recGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint8_t* buffer, int bufferSize, bool ignoreMovableObjects, bool result)
{
if (GetReadonlyStaticFieldValue == nullptr)
diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h
index 184102f757d..95272063455 100644
--- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h
+++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h
@@ -488,10 +488,6 @@ public:
void dmpEmbedMethodHandle(DWORDLONG key, DLDL value);
CORINFO_METHOD_HANDLE repEmbedMethodHandle(CORINFO_METHOD_HANDLE handle, void** ppIndirection);
- void recGetFieldAddress(CORINFO_FIELD_HANDLE field, void** ppIndirection, void* result, CorInfoType cit);
- void dmpGetFieldAddress(DWORDLONG key, const Agnostic_GetFieldAddress& value);
- void* repGetFieldAddress(CORINFO_FIELD_HANDLE field, void** ppIndirection);
-
void recGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint8_t* buffer, int bufferSize, bool ignoreMovableObjects, bool result);
void dmpGetReadonlyStaticFieldValue(DLDD key, DD value);
bool repGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint8_t* buffer, int bufferSize, bool ignoreMovableObjects);
@@ -1008,7 +1004,7 @@ enum mcPackets
Packet_GetDelegateCtor = 49,
Packet_GetEEInfo = 50,
Packet_GetEHinfo = 51,
- Packet_GetFieldAddress = 52,
+ //Packet_GetFieldAddress = 52,
Packet_GetFieldClass = 53,
Packet_GetFieldInClass = 54,
Packet_GetFieldInfo = 55,
diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp
index 9e91b15de69..377a302dd8f 100644
--- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp
+++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp
@@ -1755,19 +1755,6 @@ unsigned interceptor_ICJI::getClassDomainID(CORINFO_CLASS_HANDLE cls, void** ppI
return temp;
}
-// return the data's address (for static fields only)
-void* interceptor_ICJI::getFieldAddress(CORINFO_FIELD_HANDLE field, void** ppIndirection)
-{
- mc->cr->AddCall("getFieldAddress");
- void* temp = original_ICorJitInfo->getFieldAddress(field, ppIndirection);
-
- // Figure out the element type so we know how much we can load
- CORINFO_CLASS_HANDLE cch;
- CorInfoType cit = getFieldType(field, &cch, NULL);
- mc->recGetFieldAddress(field, ppIndirection, temp, cit);
- return temp;
-}
-
bool interceptor_ICJI::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint8_t* buffer, int bufferSize, bool ignoreMovableObjects)
{
mc->cr->AddCall("getReadonlyStaticFieldValue");
diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp
index 2ecdf378351..dd75ac3001d 100644
--- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp
+++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp
@@ -1211,14 +1211,6 @@ unsigned interceptor_ICJI::getClassDomainID(
return original_ICorJitInfo->getClassDomainID(cls, ppIndirection);
}
-void* interceptor_ICJI::getFieldAddress(
- CORINFO_FIELD_HANDLE field,
- void** ppIndirection)
-{
- mcs->AddCall("getFieldAddress");
- return original_ICorJitInfo->getFieldAddress(field, ppIndirection);
-}
-
bool interceptor_ICJI::getReadonlyStaticFieldValue(
CORINFO_FIELD_HANDLE field,
uint8_t* buffer,
diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp
index 1e0593ec325..31c507acf85 100644
--- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp
+++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp
@@ -1060,13 +1060,6 @@ unsigned interceptor_ICJI::getClassDomainID(
return original_ICorJitInfo->getClassDomainID(cls, ppIndirection);
}
-void* interceptor_ICJI::getFieldAddress(
- CORINFO_FIELD_HANDLE field,
- void** ppIndirection)
-{
- return original_ICorJitInfo->getFieldAddress(field, ppIndirection);
-}
-
bool interceptor_ICJI::getReadonlyStaticFieldValue(
CORINFO_FIELD_HANDLE field,
uint8_t* buffer,
diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp
index a86f7d27184..7fab36946f4 100644
--- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp
+++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp
@@ -1530,13 +1530,6 @@ unsigned MyICJI::getClassDomainID(CORINFO_CLASS_HANDLE cls, void** ppIndirection
return jitInstance->mc->repGetClassDomainID(cls, ppIndirection);
}
-// return the data's address (for static fields only)
-void* MyICJI::getFieldAddress(CORINFO_FIELD_HANDLE field, void** ppIndirection)
-{
- jitInstance->mc->cr->AddCall("getFieldAddress");
- return jitInstance->mc->repGetFieldAddress(field, ppIndirection);
-}
-
bool MyICJI::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint8_t* buffer, int bufferSize, bool ignoreMovableObjects)
{
jitInstance->mc->cr->AddCall("getReadonlyStaticFieldValue");
diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp
index 74c74041a49..1397c1673d0 100644
--- a/src/coreclr/vm/appdomain.cpp
+++ b/src/coreclr/vm/appdomain.cpp
@@ -637,6 +637,7 @@ void BaseDomain::Init()
m_NativeTypeLoadLock.Init(CrstInteropData, CrstFlags(CRST_REENTRANCY), TRUE);
m_crstLoaderAllocatorReferences.Init(CrstLoaderAllocatorReferences);
+ m_crstStaticBoxInitLock.Init(CrstStaticBoxInit);
// Has to switch thread to GC_NOTRIGGER while being held (see code:BaseDomain#AssemblyListLock)
m_crstAssemblyList.Init(CrstAssemblyList, CrstFlags(
CRST_GC_NOTRIGGER_WHEN_TAKEN | CRST_DEBUGGER_THREAD | CRST_TAKEN_DURING_SHUTDOWN));
diff --git a/src/coreclr/vm/appdomain.hpp b/src/coreclr/vm/appdomain.hpp
index 18b4d4fd3f5..1296adbed0d 100644
--- a/src/coreclr/vm/appdomain.hpp
+++ b/src/coreclr/vm/appdomain.hpp
@@ -1088,6 +1088,12 @@ public:
return &m_crstLoaderAllocatorReferences;
}
+ CrstExplicitInit* GetStaticBoxInitLock()
+ {
+ LIMITED_METHOD_CONTRACT;
+ return &m_crstStaticBoxInitLock;
+ }
+
static CrstStatic* GetMethodTableExposedClassObjectLock()
{
LIMITED_METHOD_CONTRACT;
@@ -1112,6 +1118,7 @@ protected:
CrstExplicitInit m_DomainLocalBlockCrst;
// Used to protect the reference lists in the collectible loader allocators attached to this appdomain
CrstExplicitInit m_crstLoaderAllocatorReferences;
+ CrstExplicitInit m_crstStaticBoxInitLock;
//#AssemblyListLock
// Used to protect the assembly list. Taken also by GC or debugger thread, therefore we have to avoid
diff --git a/src/coreclr/vm/frozenobjectheap.cpp b/src/coreclr/vm/frozenobjectheap.cpp
index a1ed1c8b46d..8fe40c3cc37 100644
--- a/src/coreclr/vm/frozenobjectheap.cpp
+++ b/src/coreclr/vm/frozenobjectheap.cpp
@@ -37,6 +37,10 @@ Object* FrozenObjectHeapManager::TryAllocateObject(PTR_MethodTable type, size_t
_ASSERT(type != nullptr);
_ASSERT(FOH_COMMIT_SIZE >= MIN_OBJECT_SIZE);
+#ifdef FEATURE_64BIT_ALIGNMENT
+ _ASSERT(!type->RequiresAlign8());
+#endif
+
// NOTE: objectSize is expected be the full size including header
_ASSERT(objectSize >= MIN_OBJECT_SIZE);
diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp
index 9c8d9cbe59c..e39d70e9910 100644
--- a/src/coreclr/vm/jitinterface.cpp
+++ b/src/coreclr/vm/jitinterface.cpp
@@ -1480,6 +1480,8 @@ void CEEInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken,
DWORD fieldFlags = 0;
pResult->offset = pField->GetOffset();
+ pResult->fieldLookup.addr = nullptr;
+
if (pField->IsStatic())
{
fieldFlags |= CORINFO_FLG_FIELD_STATIC;
@@ -1496,16 +1498,17 @@ void CEEInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken,
// Provide helper to use if the JIT is not able to emit the TLS access
// as intrinsic
pResult->helper = CORINFO_HELP_GETSTATICFIELDADDR_TLS;
-
pResult->offset = module->GetFieldTlsOffset(pResult->offset);
}
else
{
fieldAccessor = CORINFO_FIELD_STATIC_RVA_ADDRESS;
+ pResult->fieldLookup.addr = pField->GetStaticAddressHandle(NULL);
+ pResult->fieldLookup.accessType = IAT_VALUE;
}
// We are not going through a helper. The constructor has to be triggered explicitly.
- if (!pFieldMT->IsClassPreInited())
+ if (!pFieldMT->IsClassInited())
fieldFlags |= CORINFO_FLG_FIELD_INITCLASS;
}
else
@@ -1545,9 +1548,41 @@ void CEEInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken,
{
fieldAccessor = CORINFO_FIELD_STATIC_ADDRESS;
+ // Allocate space for the local class if necessary, but don't trigger
+ // class construction.
+ DomainLocalModule* pLocalModule = pFieldMT->GetDomainLocalModule();
+ pLocalModule->PopulateClass(pFieldMT);
+
// We are not going through a helper. The constructor has to be triggered explicitly.
- if (!pFieldMT->IsClassPreInited())
+ if (!pFieldMT->IsClassInited())
fieldFlags |= CORINFO_FLG_FIELD_INITCLASS;
+
+ GCX_COOP();
+
+ pResult->fieldLookup.addr = pField->GetStaticAddressHandle((void*)pField->GetBase());
+ if (fieldFlags & CORINFO_FLG_FIELD_STATIC_IN_HEAP)
+ {
+ Object* frozenObj = VolatileLoad((Object**)pResult->fieldLookup.addr);
+
+ if (frozenObj == nullptr)
+ {
+ // Boxed static is not yet set, allocate it
+ pFieldMT->AllocateRegularStaticBox(pField, (BYTE*)pResult->fieldLookup.addr);
+ frozenObj = VolatileLoad((Object**)pResult->fieldLookup.addr);
+ }
+
+ _ASSERT(frozenObj != nullptr);
+
+ // ContainsPointers here is unnecessary but it's cheaper than IsInFrozenSegment
+ // for structs containing gc handles
+ if (!frozenObj->GetMethodTable()->ContainsPointers() &&
+ GCHeapUtilities::GetGCHeap()->IsInFrozenSegment(frozenObj))
+ {
+ pResult->fieldLookup.addr = frozenObj->GetData();
+ fieldFlags &= ~CORINFO_FLG_FIELD_STATIC_IN_HEAP;
+ }
+ }
+ pResult->fieldLookup.accessType = IAT_VALUE;
}
}
@@ -11963,54 +11998,6 @@ InfoAccessType CEEJitInfo::emptyStringLiteral(void ** ppValue)
return result;
}
-/*********************************************************************/
-void* CEEJitInfo::getFieldAddress(CORINFO_FIELD_HANDLE fieldHnd,
- void **ppIndirection)
-{
- CONTRACTL {
- THROWS;
- GC_TRIGGERS;
- MODE_PREEMPTIVE;
- } CONTRACTL_END;
-
- void *result = NULL;
-
- if (ppIndirection != NULL)
- *ppIndirection = NULL;
-
- JIT_TO_EE_TRANSITION();
-
- FieldDesc* field = (FieldDesc*) fieldHnd;
-
- MethodTable* pMT = field->GetEnclosingMethodTable();
-
- _ASSERTE(!pMT->ContainsGenericVariables());
-
- void *base = NULL;
-
- if (!field->IsRVA())
- {
- // <REVISIT_TODO>@todo: assert that the current method being compiled is unshared</REVISIT_TODO>
- // We must not call here for statics of collectible types.
- _ASSERTE(!pMT->Collectible());
-
- // Allocate space for the local class if necessary, but don't trigger
- // class construction.
- DomainLocalModule *pLocalModule = pMT->GetDomainLocalModule();
- pLocalModule->PopulateClass(pMT);
-
- GCX_COOP();
-
- base = (void *) field->GetBase();
- }
-
- result = field->GetStaticAddressHandle(base);
-
- EE_TO_JIT_TRANSITION();
-
- return result;
-}
-
bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t* buffer, int bufferSize, bool ignoreMovableObjects)
{
CONTRACTL {
@@ -14562,33 +14549,6 @@ InfoAccessType CEEInfo::emptyStringLiteral(void ** ppValue)
UNREACHABLE(); // only called on derived class.
}
-void* CEEInfo::getFieldAddress(CORINFO_FIELD_HANDLE fieldHnd,
- void **ppIndirection)
-{
- CONTRACTL{
- THROWS;
- GC_TRIGGERS;
- MODE_PREEMPTIVE;
- } CONTRACTL_END;
-
- void *result = NULL;
-
- if (ppIndirection != NULL)
- *ppIndirection = NULL;
-
- JIT_TO_EE_TRANSITION();
-
- FieldDesc* field = (FieldDesc*)fieldHnd;
-
- _ASSERTE(field->IsRVA());
-
- result = field->GetStaticAddressHandle(NULL);
-
- EE_TO_JIT_TRANSITION();
-
- return result;
-}
-
CORINFO_CLASS_HANDLE CEEInfo::getStaticFieldCurrentClass(CORINFO_FIELD_HANDLE fieldHnd,
bool* pIsSpeculative)
{
diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h
index c0fcb0a92fb..4460c413b76 100644
--- a/src/coreclr/vm/jitinterface.h
+++ b/src/coreclr/vm/jitinterface.h
@@ -944,7 +944,6 @@ public:
InfoAccessType constructStringLiteral(CORINFO_MODULE_HANDLE scopeHnd, mdToken metaTok, void **ppValue) override final;
InfoAccessType emptyStringLiteral(void ** ppValue) override final;
- void* getFieldAddress(CORINFO_FIELD_HANDLE field, void **ppIndirection) override final;
CORINFO_CLASS_HANDLE getStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, bool* pIsSpeculative) override final;
void* getMethodSync(CORINFO_METHOD_HANDLE ftnHnd, void **ppIndirection) override final;
diff --git a/src/coreclr/vm/methodtable.cpp b/src/coreclr/vm/methodtable.cpp
index d42d4e3efc1..121774a513e 100644
--- a/src/coreclr/vm/methodtable.cpp
+++ b/src/coreclr/vm/methodtable.cpp
@@ -58,6 +58,7 @@
#include "array.h"
#include "castcache.h"
#include "dynamicinterfacecastable.h"
+#include "frozenobjectheap.h"
#ifdef FEATURE_INTERPRETER
#include "interpreter.h"
@@ -3483,7 +3484,6 @@ void MethodTable::AllocateRegularStaticBoxes()
PTR_BYTE pStaticBase = GetGCStaticsBasePointer();
GCPROTECT_BEGININTERIOR(pStaticBase);
-
{
FieldDesc *pField = HasGenericsStaticsInfo() ?
GetGenericsStaticFieldDescs() : (GetApproxFieldDescListRaw() + GetNumIntroducedInstanceFields());
@@ -3491,33 +3491,70 @@ void MethodTable::AllocateRegularStaticBoxes()
while (pField < pFieldEnd)
{
- _ASSERTE(pField->IsStatic());
-
if (!pField->IsSpecialStatic() && pField->IsByValue())
{
- TypeHandle th = pField->GetFieldTypeHandleThrowing();
- MethodTable* pFieldMT = th.GetMethodTable();
-
- LOG((LF_CLASSLOADER, LL_INFO10000, "\tInstantiating static of type %s\n", pFieldMT->GetDebugClassName()));
- OBJECTREF obj = AllocateStaticBox(pFieldMT, HasFixedAddressVTStatics());
-
- SetObjectReference( (OBJECTREF*)(pStaticBase + pField->GetOffset()), obj);
+ AllocateRegularStaticBox(pField, pStaticBase + pField->GetOffset());
}
-
pField++;
}
}
GCPROTECT_END();
}
+void MethodTable::AllocateRegularStaticBox(FieldDesc* pField, BYTE* fieldAddress)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ CONTRACTL_END;
+ }
+ _ASSERT(pField->IsStatic() && !pField->IsSpecialStatic() && pField->IsByValue());
+
+ Object** boxedStaticHandle = reinterpret_cast<Object**>(fieldAddress);
+
+ if (VolatileLoad(boxedStaticHandle) != nullptr)
+ {
+ // Boxed static is already initialized
+ return;
+ }
+
+ // Grab field's type handle before we enter lock
+ TypeHandle th = pField->GetFieldTypeHandleThrowing();
+
+ // Taking a lock since we might come here from multiple threads/places
+ CrstHolder crst(GetAppDomain()->GetStaticBoxInitLock());
+
+ // double-checked locking
+ if (VolatileLoad(boxedStaticHandle) != nullptr)
+ {
+ // Boxed static is already initialized
+ return;
+ }
+
+ MethodTable* pFieldMT = th.GetMethodTable();
+ LOG((LF_CLASSLOADER, LL_INFO10000, "\tInstantiating static of type %s\n", pFieldMT->GetDebugClassName()));
+ bool canBeFrozen = !pFieldMT->ContainsPointers() && !Collectible();
+#ifdef FEATURE_64BIT_ALIGNMENT
+ if (pFieldMT->RequiresAlign8())
+ {
+ // 64bit alignment is not yet supported in FOH for 32bit targets
+ canBeFrozen = false;
+ }
+#endif
+ OBJECTREF obj = AllocateStaticBox(pFieldMT, HasFixedAddressVTStatics(), NULL, canBeFrozen);
+ SetObjectReference((OBJECTREF*)boxedStaticHandle, obj);
+}
+
//==========================================================================================
-OBJECTREF MethodTable::AllocateStaticBox(MethodTable* pFieldMT, BOOL fPinned, OBJECTHANDLE* pHandle)
+OBJECTREF MethodTable::AllocateStaticBox(MethodTable* pFieldMT, BOOL fPinned, OBJECTHANDLE* pHandle, bool canBeFrozen)
{
CONTRACTL
{
THROWS;
GC_TRIGGERS;
- MODE_ANY;
+ MODE_COOPERATIVE;
CONTRACTL_END;
}
@@ -3526,7 +3563,21 @@ OBJECTREF MethodTable::AllocateStaticBox(MethodTable* pFieldMT, BOOL fPinned, OB
// Activate any dependent modules if necessary
pFieldMT->EnsureInstanceActive();
- OBJECTREF obj = AllocateObject(pFieldMT);
+ OBJECTREF obj = NULL;
+ if (canBeFrozen)
+ {
+ // In case if we don't plan to collect this handle we may try to allocate it on FOH
+ _ASSERT(!pFieldMT->ContainsPointers());
+ FrozenObjectHeapManager* foh = SystemDomain::GetFrozenObjectHeapManager();
+ obj = ObjectToOBJECTREF(foh->TryAllocateObject(pFieldMT, pFieldMT->GetBaseSize()));
+ // obj can be null in case if struct is huge (>64kb)
+ if (obj != NULL)
+ {
+ return obj;
+ }
+ }
+
+ obj = AllocateObject(pFieldMT);
// Pin the object if necessary
if (fPinned)
diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h
index a378ec69ad5..e7e24c8d8ae 100644
--- a/src/coreclr/vm/methodtable.h
+++ b/src/coreclr/vm/methodtable.h
@@ -831,7 +831,8 @@ public:
// instantiations of the superclass or interfaces e.g. System.Int32 : IComparable<System.Int32>
void AllocateRegularStaticBoxes();
- static OBJECTREF AllocateStaticBox(MethodTable* pFieldMT, BOOL fPinned, OBJECTHANDLE* pHandle = 0);
+ void AllocateRegularStaticBox(FieldDesc* pField, BYTE* fieldAddress);
+ static OBJECTREF AllocateStaticBox(MethodTable* pFieldMT, BOOL fPinned, OBJECTHANDLE* pHandle = 0, bool canBeFrozen = false);
void CheckRestore();
diff --git a/src/tests/baseservices/compilerservices/FixedAddressValueType/FixedAddressValueType.cs b/src/tests/baseservices/compilerservices/FixedAddressValueType/FixedAddressValueType.cs
index a8a61132b19..56667c70cd2 100644
--- a/src/tests/baseservices/compilerservices/FixedAddressValueType/FixedAddressValueType.cs
+++ b/src/tests/baseservices/compilerservices/FixedAddressValueType/FixedAddressValueType.cs
@@ -1,59 +1,50 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
//
+
using System;
using System.Runtime.CompilerServices;
-public struct Age {
- public int years;
- public int months;
-}
-
-public class FreeClass
+public struct Age
{
- public static Age FreeAge;
-
- public static unsafe IntPtr AddressOfFreeAge()
- {
- fixed (Age* pointer = &FreeAge)
- { return (IntPtr) pointer; }
- }
+ public int years;
+ public int months;
}
public class FixedClass
{
- [FixedAddressValueType]
- public static Age FixedAge;
-
- public static unsafe IntPtr AddressOfFixedAge()
- {
- fixed (Age* pointer = &FixedAge)
- { return (IntPtr) pointer; }
- }
+ [FixedAddressValueType]
+ public static Age FixedAge;
+
+ public static unsafe IntPtr AddressOfFixedAge()
+ {
+ fixed (Age* pointer = &FixedAge)
+ {
+ return (IntPtr)pointer;
+ }
+ }
}
public class Example
{
- public static int Main()
- {
- // Get addresses of static Age fields.
- IntPtr freePtr1 = FreeClass.AddressOfFreeAge();
-
- IntPtr fixedPtr1 = FixedClass.AddressOfFixedAge();
-
- // Garbage collection.
- GC.Collect(3, GCCollectionMode.Forced, true, true);
- GC.WaitForPendingFinalizers();
-
- // Get addresses of static Age fields after garbage collection.
- IntPtr freePtr2 = FreeClass.AddressOfFreeAge();
- IntPtr fixedPtr2 = FixedClass.AddressOfFixedAge();
-
- if(freePtr1 != freePtr2 && fixedPtr1 == fixedPtr2)
- {
- return 100;
- }
-
- return -1;
- }
+ public static int Main()
+ {
+ for (int i = 0; i < 1000; i++)
+ {
+ IntPtr fixedPtr1 = FixedClass.AddressOfFixedAge();
+
+ // Garbage collection.
+ GC.Collect(3, GCCollectionMode.Forced, true, true);
+ GC.WaitForPendingFinalizers();
+
+ // Get addresses of static Age fields after garbage collection.
+ IntPtr fixedPtr2 = FixedClass.AddressOfFixedAge();
+
+ if (fixedPtr1 != fixedPtr2)
+ {
+ return -1;
+ }
+ }
+ return 100;
+ }
}