summaryrefslogtreecommitdiff
path: root/src/vm/methodtablebuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/methodtablebuilder.cpp')
-rw-r--r--src/vm/methodtablebuilder.cpp285
1 files changed, 33 insertions, 252 deletions
diff --git a/src/vm/methodtablebuilder.cpp b/src/vm/methodtablebuilder.cpp
index 3a738df496..f9876608eb 100644
--- a/src/vm/methodtablebuilder.cpp
+++ b/src/vm/methodtablebuilder.cpp
@@ -21,7 +21,6 @@
#include "encee.h"
#include "mdaassistants.h"
#include "ecmakey.h"
-#include "security.h"
#include "customattribute.h"
#include "typestring.h"
@@ -1822,7 +1821,7 @@ MethodTableBuilder::BuildMethodTableThrowing(
GetHalfBakedClass()->SetIsNotTightlyPacked();
#ifdef FEATURE_HFA
- CheckForHFA(pByValueClassCache);
+ GetHalfBakedClass()->CheckForHFA(pByValueClassCache);
#endif
#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
#ifdef FEATURE_HFA
@@ -1844,7 +1843,7 @@ MethodTableBuilder::BuildMethodTableThrowing(
#ifdef FEATURE_HFA
if (HasLayout())
{
- CheckForNativeHFA();
+ GetHalfBakedClass()->CheckForNativeHFA();
}
#endif
@@ -4168,19 +4167,6 @@ VOID MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList,
pszFieldName
);
- // Check if the ValueType field containing non-publics is overlapped
- if (HasExplicitFieldOffsetLayout()
- && pLayoutFieldInfo != NULL
- && pLayoutFieldInfo->m_fIsOverlapped
- && pByValueClass != NULL
- && pByValueClass->GetClass()->HasNonPublicFields())
- {
- if (!Security::CanSkipVerification(GetAssembly()->GetDomainAssembly()))
- {
- BuildMethodTableThrowException(IDS_CLASSLOAD_BADOVERLAP);
- }
- }
-
// We're using FieldDesc::m_pMTOfEnclosingClass to temporarily store the field's size.
//
if (fIsByValue)
@@ -4281,14 +4267,6 @@ VOID MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList,
BAD_FORMAT_NOTHROW_ASSERT(!"ObjectRef in an RVA field");
BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
}
- if (pByValueClass->GetClass()->HasNonPublicFields())
- {
- if (!Security::CanHaveRVA(GetAssembly()))
- {
- BAD_FORMAT_NOTHROW_ASSERT(!"ValueType with non-public fields as a type of an RVA field");
- BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
- }
- }
}
}
@@ -4321,14 +4299,6 @@ VOID MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList,
{
fldSize = GetSizeForCorElementType(FieldDescElementType);
}
- if (!GetModule()->CheckRvaField(rva, fldSize))
- {
- if (!Security::CanHaveRVA(GetAssembly()))
- {
- BAD_FORMAT_NOTHROW_ASSERT(!"Illegal RVA of a mapped field");
- BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
- }
- }
pFD->SetOffsetRVA(rva);
}
@@ -4368,14 +4338,6 @@ VOID MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList,
BAD_FORMAT_NOTHROW_ASSERT(!"ObjectRef in an RVA self-referencing static field");
BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
}
- if (HasNonPublicFields())
- { // RVA ValueTypes with non-public fields must be checked against security
- if (!Security::CanHaveRVA(GetAssembly()))
- {
- BAD_FORMAT_NOTHROW_ASSERT(!"ValueType with non-public fields as a type of an RVA self-referencing static field");
- BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
- }
- }
}
DWORD dwNumInstanceFields = dwCurrentDeclaredField + (HasParent() ? GetParentMethodTable()->GetNumInstanceFields() : 0);
@@ -4464,15 +4426,6 @@ MethodTableBuilder::VerifySelfReferencingStaticValueTypeFields_WithRVA(
{
DWORD rva;
IfFailThrow(GetMDImport()->GetFieldRVA(pFD->GetMemberDef(), &rva));
-
- if (!GetModule()->CheckRvaField(rva, bmtFP->NumInstanceFieldBytes))
- {
- if (!Security::CanHaveRVA(GetAssembly()))
- {
- BAD_FORMAT_NOTHROW_ASSERT(!"Illegal RVA of a mapped self-referencing static field");
- BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
- }
- }
}
}
}
@@ -5126,6 +5079,20 @@ MethodTableBuilder::InitNewMethodDesc(
pNewMD->SetNotInline(true);
}
+ // Check for methods marked as [Intrinsic]
+ if (GetModule()->IsSystem())
+ {
+ HRESULT hr = GetMDImport()->GetCustomAttributeByName(pMethod->GetMethodSignature().GetToken(),
+ g_CompilerServicesIntrinsicAttribute,
+ NULL,
+ NULL);
+
+ if (hr == S_OK)
+ {
+ pNewMD->SetIsJitIntrinsic();
+ }
+ }
+
pNewMD->SetSlot(pMethod->GetSlotIndex());
}
@@ -6937,6 +6904,12 @@ MethodTableBuilder::NeedsNativeCodeSlot(bmtMDMethod * pMDMethod)
}
#endif
+#if defined(FEATURE_JIT_PITCHING)
+ if ((CLRConfig::GetConfigValue(CLRConfig::INTERNAL_JitPitchEnabled) != 0) &&
+ (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_JitPitchMemThreshold) != 0))
+ return TRUE;
+#endif
+
return GetModule()->IsEditAndContinueEnabled();
}
@@ -8216,188 +8189,6 @@ void MethodTableBuilder::StoreEightByteClassification(SystemVStructRegisterPassi
#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
-#ifdef FEATURE_HFA
-//---------------------------------------------------------------------------------------
-//
-VOID
-MethodTableBuilder::CheckForHFA(MethodTable ** pByValueClassCache)
-{
- STANDARD_VM_CONTRACT;
-
- // This method should be called for valuetypes only
- _ASSERTE(IsValueClass());
-
- // No HFAs with explicit layout. There may be cases where explicit layout may be still
- // eligible for HFA, but it is hard to tell the real intent. Make it simple and just
- // unconditionally disable HFAs for explicit layout.
- if (HasExplicitFieldOffsetLayout())
- return;
-
- CorElementType hfaType = ELEMENT_TYPE_END;
-
- FieldDesc *pFieldDescList = GetHalfBakedClass()->GetFieldDescList();
- for (UINT i = 0; i < bmtEnumFields->dwNumInstanceFields; i++)
- {
- FieldDesc *pFD = &pFieldDescList[i];
- CorElementType fieldType = pFD->GetFieldType();
-
- switch (fieldType)
- {
- case ELEMENT_TYPE_VALUETYPE:
- fieldType = pByValueClassCache[i]->GetHFAType();
- break;
-
- case ELEMENT_TYPE_R4:
- case ELEMENT_TYPE_R8:
- break;
-
- default:
- // Not HFA
- return;
- }
-
- // Field type should be a valid HFA type.
- if (fieldType == ELEMENT_TYPE_END)
- {
- return;
- }
-
- // Initialize with a valid HFA type.
- if (hfaType == ELEMENT_TYPE_END)
- {
- hfaType = fieldType;
- }
- // All field types should be equal.
- else if (fieldType != hfaType)
- {
- return;
- }
- }
-
- if (hfaType == ELEMENT_TYPE_END)
- return;
-
- int elemSize = (hfaType == ELEMENT_TYPE_R8) ? sizeof(double) : sizeof(float);
-
- // Note that we check the total size, but do not perform any checks on number of fields:
- // - Type of fields can be HFA valuetype itself
- // - Managed C++ HFA valuetypes have just one <alignment member> of type float to signal that
- // the valuetype is HFA and explicitly specified size
-
- DWORD totalSize = bmtFP->NumInstanceFieldBytes;
-
- if (totalSize % elemSize != 0)
- return;
-
- // On ARM, HFAs can have a maximum of four fields regardless of whether those are float or double.
- if (totalSize / elemSize > 4)
- return;
-
- // All the above tests passed. It's HFA!
- GetHalfBakedMethodTable()->SetIsHFA();
-}
-
-//
-// The managed and unmanaged views of the types can differ for non-blitable types. This method
-// mirrors the HFA type computation for the unmanaged view.
-//
-void MethodTableBuilder::CheckForNativeHFA()
-{
- STANDARD_VM_CONTRACT;
-
- // No HFAs with inheritance
- if (!(IsValueClass() || (GetParentMethodTable() == g_pObjectClass)))
- return;
-
- // No HFAs with explicit layout. There may be cases where explicit layout may be still
- // eligible for HFA, but it is hard to tell the real intent. Make it simple and just
- // unconditionally disable HFAs for explicit layout.
- if (HasExplicitFieldOffsetLayout())
- return;
-
- const FieldMarshaler *pFieldMarshaler = GetLayoutInfo()->GetFieldMarshalers();
- UINT numReferenceFields = GetLayoutInfo()->GetNumCTMFields();
-
- CorElementType hfaType = ELEMENT_TYPE_END;
-
- while (numReferenceFields--)
- {
- CorElementType fieldType = ELEMENT_TYPE_END;
-
- switch (pFieldMarshaler->GetNStructFieldType())
- {
- case NFT_COPY4:
- case NFT_COPY8:
- fieldType = pFieldMarshaler->GetFieldDesc()->GetFieldType();
- if (fieldType != ELEMENT_TYPE_R4 && fieldType != ELEMENT_TYPE_R8)
- return;
- break;
-
- case NFT_NESTEDLAYOUTCLASS:
- fieldType = ((FieldMarshaler_NestedLayoutClass *)pFieldMarshaler)->GetMethodTable()->GetNativeHFAType();
- break;
-
- case NFT_NESTEDVALUECLASS:
- fieldType = ((FieldMarshaler_NestedValueClass *)pFieldMarshaler)->GetMethodTable()->GetNativeHFAType();
- break;
-
- case NFT_FIXEDARRAY:
- fieldType = ((FieldMarshaler_FixedArray *)pFieldMarshaler)->GetElementTypeHandle().GetMethodTable()->GetNativeHFAType();
- break;
-
- case NFT_DATE:
- fieldType = ELEMENT_TYPE_R8;
- break;
-
- default:
- // Not HFA
- return;
- }
-
- // Field type should be a valid HFA type.
- if (fieldType == ELEMENT_TYPE_END)
- {
- return;
- }
-
- // Initialize with a valid HFA type.
- if (hfaType == ELEMENT_TYPE_END)
- {
- hfaType = fieldType;
- }
- // All field types should be equal.
- else if (fieldType != hfaType)
- {
- return;
- }
-
- ((BYTE*&)pFieldMarshaler) += MAXFIELDMARSHALERSIZE;
- }
-
- if (hfaType == ELEMENT_TYPE_END)
- return;
-
- int elemSize = (hfaType == ELEMENT_TYPE_R8) ? sizeof(double) : sizeof(float);
-
- // Note that we check the total size, but do not perform any checks on number of fields:
- // - Type of fields can be HFA valuetype itself
- // - Managed C++ HFA valuetypes have just one <alignment member> of type float to signal that
- // the valuetype is HFA and explicitly specified size
-
- DWORD totalSize = GetHalfBakedClass()->GetNativeSize();
-
- if (totalSize % elemSize != 0)
- return;
-
- // On ARM, HFAs can have a maximum of four fields regardless of whether those are float or double.
- if (totalSize / elemSize > 4)
- return;
-
- // All the above tests passed. It's HFA!
- GetLayoutInfo()->SetNativeHFAType(hfaType);
-}
-#endif // FEATURE_HFA
-
//---------------------------------------------------------------------------------------
//
// make sure that no object fields are overlapped incorrectly and define the
@@ -8633,17 +8424,6 @@ MethodTableBuilder::HandleExplicitLayout(
IDS_CLASSLOAD_EXPLICIT_LAYOUT);
}
- if (!explicitClassTrust.IsVerifiable())
- {
- if (!Security::CanSkipVerification(GetAssembly()->GetDomainAssembly()))
- {
- ThrowFieldLayoutError(GetCl(),
- GetModule(),
- firstObjectOverlapOffset,
- IDS_CLASSLOAD_UNVERIFIABLE_FIELD_LAYOUT);
- }
- }
-
if (!explicitClassTrust.IsNonOverLayed())
{
SetHasOverLayedFields();
@@ -9006,7 +8786,7 @@ void MethodTableBuilder::CopyExactParentSlots(MethodTable *pMT, MethodTable *pAp
//
// Non-canonical method tables either share everything or nothing so it is sufficient to check
// just the first indirection to detect sharing.
- if (pMT->GetVtableIndirections()[0] != pCanonMT->GetVtableIndirections()[0])
+ if (pMT->GetVtableIndirections()[0].GetValueMaybeNull() != pCanonMT->GetVtableIndirections()[0].GetValueMaybeNull())
{
for (DWORD i = 0; i < nParentVirtuals; i++)
{
@@ -9033,7 +8813,7 @@ void MethodTableBuilder::CopyExactParentSlots(MethodTable *pMT, MethodTable *pAp
// We need to re-inherit this slot from the exact parent.
DWORD indirectionIndex = MethodTable::GetIndexOfVtableIndirection(i);
- if (pMT->GetVtableIndirections()[indirectionIndex] == pApproxParentMT->GetVtableIndirections()[indirectionIndex])
+ if (pMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull() == pApproxParentMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull())
{
// The slot lives in a chunk shared from the approximate parent MT
// If so, we need to change to share the chunk from the exact parent MT
@@ -9044,7 +8824,7 @@ void MethodTableBuilder::CopyExactParentSlots(MethodTable *pMT, MethodTable *pAp
_ASSERTE(MethodTable::CanShareVtableChunksFrom(pParentMT, pMT->GetLoaderModule()));
#endif
- pMT->GetVtableIndirections()[indirectionIndex] = pParentMT->GetVtableIndirections()[indirectionIndex];
+ pMT->GetVtableIndirections()[indirectionIndex].SetValueMaybeNull(pParentMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull());
i = MethodTable::GetEndSlotForVtableIndirection(indirectionIndex, nParentVirtuals) - 1;
continue;
@@ -9901,7 +9681,7 @@ MethodTable * MethodTableBuilder::AllocateNewMT(Module *pLoaderModule,
S_SIZE_T cbTotalSize = S_SIZE_T(dwGCSize) + S_SIZE_T(sizeof(MethodTable));
// vtable
- cbTotalSize += MethodTable::GetNumVtableIndirections(dwVirtuals) * sizeof(PTR_PCODE);
+ cbTotalSize += MethodTable::GetNumVtableIndirections(dwVirtuals) * sizeof(MethodTable::VTableIndir_t);
DWORD dwMultipurposeSlotsMask = 0;
@@ -9945,7 +9725,7 @@ MethodTable * MethodTableBuilder::AllocateNewMT(Module *pLoaderModule,
if (dwNumDicts != 0)
{
cbTotalSize += sizeof(GenericsDictInfo);
- cbTotalSize += S_SIZE_T(dwNumDicts) * S_SIZE_T(sizeof(TypeHandle*));
+ cbTotalSize += S_SIZE_T(dwNumDicts) * S_SIZE_T(sizeof(MethodTable::PerInstInfoElem_t));
cbTotalSize += cbInstAndDict;
}
@@ -10050,7 +9830,7 @@ MethodTable * MethodTableBuilder::AllocateNewMT(Module *pLoaderModule,
{
// Share the parent chunk
_ASSERTE(it.GetEndSlot() <= pMTParent->GetNumVirtuals());
- it.SetIndirectionSlot(pMTParent->GetVtableIndirections()[it.GetIndex()]);
+ it.SetIndirectionSlot(pMTParent->GetVtableIndirections()[it.GetIndex()].GetValueMaybeNull());
}
else
{
@@ -10098,19 +9878,20 @@ MethodTable * MethodTableBuilder::AllocateNewMT(Module *pLoaderModule,
// the dictionary pointers follow the interface map
if (dwNumDicts)
{
- Dictionary** pPerInstInfo = (Dictionary**)(pData + offsetOfInstAndDict.Value() + sizeof(GenericsDictInfo));
+ MethodTable::PerInstInfoElem_t *pPerInstInfo = (MethodTable::PerInstInfoElem_t *)(pData + offsetOfInstAndDict.Value() + sizeof(GenericsDictInfo));
pMT->SetPerInstInfo ( pPerInstInfo);
// Fill in the dictionary for this type, if it's instantiated
if (cbInstAndDict)
{
- *(pPerInstInfo + (dwNumDicts-1)) = (Dictionary*) (pPerInstInfo + dwNumDicts);
+ MethodTable::PerInstInfoElem_t *pPInstInfo = (MethodTable::PerInstInfoElem_t *)(pPerInstInfo + (dwNumDicts-1));
+ pPInstInfo->SetValueMaybeNull((Dictionary*) (pPerInstInfo + dwNumDicts));
}
}
#ifdef _DEBUG
- pMT->m_pWriteableData->m_dwLastVerifedGCCnt = (DWORD)-1;
+ pMT->m_pWriteableData.GetValue()->m_dwLastVerifedGCCnt = (DWORD)-1;
#endif // _DEBUG
RETURN(pMT);
@@ -10599,7 +10380,7 @@ MethodTableBuilder::SetupMethodTable2(
// with code:MethodDesc::SetStableEntryPointInterlocked.
//
DWORD indirectionIndex = MethodTable::GetIndexOfVtableIndirection(iCurSlot);
- if (GetParentMethodTable()->GetVtableIndirections()[indirectionIndex] != pMT->GetVtableIndirections()[indirectionIndex])
+ if (GetParentMethodTable()->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull() != pMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull())
pMT->SetSlot(iCurSlot, pMD->GetMethodEntryPoint());
}
else