diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/debug/daccess/nidump.cpp | 51 | ||||
-rw-r--r-- | src/vm/dllimport.cpp | 4 | ||||
-rw-r--r-- | src/vm/dynamicmethod.cpp | 14 | ||||
-rw-r--r-- | src/vm/genmeth.cpp | 4 | ||||
-rw-r--r-- | src/vm/ilstubcache.cpp | 12 | ||||
-rw-r--r-- | src/vm/method.cpp | 33 | ||||
-rw-r--r-- | src/vm/method.hpp | 94 | ||||
-rw-r--r-- | src/vm/methodimpl.cpp | 69 | ||||
-rw-r--r-- | src/vm/methodimpl.h | 45 | ||||
-rw-r--r-- | src/vm/methodtablebuilder.cpp | 24 | ||||
-rw-r--r-- | src/vm/methodtablebuilder.h | 8 |
11 files changed, 205 insertions, 153 deletions
diff --git a/src/debug/daccess/nidump.cpp b/src/debug/daccess/nidump.cpp index ebce7b4aa0..6e7370834b 100644 --- a/src/debug/daccess/nidump.cpp +++ b/src/debug/daccess/nidump.cpp @@ -7787,20 +7787,20 @@ void NativeImageDumper::DumpMethodDesc( PTR_MethodDesc md, PTR_Module module ) MethodImpl, METHODDESCS); } - _ASSERTE(impl->pImplementedMD == NULL - || isInRange(PTR_TO_TADDR(impl->pImplementedMD))); - if ((impl->pImplementedMD != NULL) && - isInRange(PTR_TO_TADDR(impl->pImplementedMD))) + _ASSERTE(impl->pImplementedMD.IsNull() + || isInRange(PTR_TO_TADDR(impl->GetImpMDsNonNull()))); + if (!impl->pImplementedMD.IsNull() && + isInRange(PTR_TO_TADDR(impl->GetImpMDsNonNull()))) { DisplayWriteFieldAddress( pImplementedMD, - DataPtrToDisplay(dac_cast<TADDR>(impl->pImplementedMD)), - numSlots * sizeof(MethodDesc*), + DataPtrToDisplay(dac_cast<TADDR>(impl->GetImpMDsNonNull())), + numSlots * sizeof(RelativePointer <MethodDesc*>), MethodImpl, METHODDESCS ); } else { DisplayWriteFieldPointer( pImplementedMD, - DataPtrToDisplay(dac_cast<TADDR>(impl->pImplementedMD)), + DataPtrToDisplay(dac_cast<TADDR>(impl->GetImpMDs())), MethodImpl, METHODDESCS ); } DisplayEndVStructure( METHODDESCS ); @@ -7810,19 +7810,19 @@ void NativeImageDumper::DumpMethodDesc( PTR_MethodDesc md, PTR_Module module ) DisplayStartVStructure( "StoredSigMethodDesc", METHODDESCS ); PTR_StoredSigMethodDesc ssmd(md); //display signature information. - if( isInRange(ssmd->m_pSig) ) + if( isInRange(ssmd->GetSigRVA()) ) { - DisplayWriteFieldAddress(m_pSig, DataPtrToDisplay(ssmd->m_pSig), + DisplayWriteFieldAddress(m_pSig, DataPtrToDisplay(ssmd->GetSigRVA()), ssmd->m_cSig, StoredSigMethodDesc, METHODDESCS); } else { - DisplayWriteFieldPointer(m_pSig, DataPtrToDisplay(ssmd->m_pSig), + DisplayWriteFieldPointer(m_pSig, DataPtrToDisplay(ssmd->GetSigRVA()), StoredSigMethodDesc, METHODDESCS); } - CoverageRead(TO_TADDR(ssmd->m_pSig), ssmd->m_cSig); + CoverageRead(TO_TADDR(ssmd->GetSigRVA()), ssmd->m_cSig); DisplayWriteFieldInt( m_cSig, ssmd->m_cSig, StoredSigMethodDesc, METHODDESCS ); #ifdef _WIN64 @@ -7838,10 +7838,10 @@ void NativeImageDumper::DumpMethodDesc( PTR_MethodDesc md, PTR_Module module ) { PTR_DynamicMethodDesc dmd(md); DisplayStartVStructure( "DynamicMethodDesc", METHODDESCS ); - WriteFieldStr( m_pszMethodName, PTR_BYTE(dmd->m_pszMethodName), + WriteFieldStr( m_pszMethodName, PTR_BYTE(dmd->GetMethodName()), DynamicMethodDesc, METHODDESCS ); if( !CHECK_OPT(METHODDESCS) ) - CoverageReadString( PTR_TO_TADDR(dmd->m_pszMethodName) ); + CoverageReadString( PTR_TO_TADDR(dmd->GetMethodName()) ); DisplayWriteFieldPointer( m_pResolver, DPtrToPreferredAddr(dmd->m_pResolver), DynamicMethodDesc, METHODDESCS ); @@ -7885,10 +7885,10 @@ void NativeImageDumper::DumpMethodDesc( PTR_MethodDesc md, PTR_Module module ) METHODDESCS ); WriteFieldStr( m_pszEntrypointName, - PTR_BYTE(TO_TADDR(nd->m_pszEntrypointName)), + PTR_BYTE(dac_cast<TADDR>(ndmd->GetEntrypointName())), NDirectMethodDesc::temp1, METHODDESCS ); if( !CHECK_OPT(METHODDESCS) ) - CoverageReadString(TO_TADDR(nd->m_pszEntrypointName)); + CoverageReadString(dac_cast<TADDR>(ndmd->GetEntrypointName())); if (md->IsQCall()) { DisplayWriteFieldInt( m_dwECallID, @@ -7899,11 +7899,11 @@ void NativeImageDumper::DumpMethodDesc( PTR_MethodDesc md, PTR_Module module ) else { WriteFieldStr( m_pszLibName, - PTR_BYTE(TO_TADDR(nd->m_pszLibName)), + PTR_BYTE(dac_cast<TADDR>(ndmd->GetLibNameRaw())), NDirectMethodDesc::temp1, METHODDESCS ); } if( !CHECK_OPT(METHODDESCS) ) - CoverageReadString( TO_TADDR(nd->m_pszLibName) ); + CoverageReadString( dac_cast<TADDR>(ndmd->GetLibNameRaw()) ); PTR_NDirectWriteableData wnd( nd->m_pWriteableData ); DisplayStartStructureWithOffset( m_pWriteableData, @@ -7917,12 +7917,7 @@ void NativeImageDumper::DumpMethodDesc( PTR_MethodDesc md, PTR_Module module ) CoverageRead( PTR_TO_TADDR(wnd), sizeof(*wnd) ); DisplayEndStructure( METHODDESCS ); //m_pWriteableData - -#ifdef HAS_NDIRECT_IMPORT_PRECODE - PTR_NDirectImportThunkGlue glue(nd->m_pImportThunkGlue); -#else - PTR_NDirectImportThunkGlue glue(PTR_HOST_MEMBER_TADDR(NDirectMethodDesc::temp1, nd, m_ImportThunkGlue)); -#endif + PTR_NDirectImportThunkGlue glue(ndmd->GetNDirectImportThunkGlue()); #ifdef HAS_NDIRECT_IMPORT_PRECODE if (glue == NULL) @@ -8023,7 +8018,7 @@ void NativeImageDumper::DumpMethodDesc( PTR_MethodDesc md, PTR_Module module ) & InstantiatedMethodDesc::KindMask; if( kind == InstantiatedMethodDesc::SharedMethodInstantiation ) { - PTR_DictionaryLayout layout(TO_TADDR(imd->m_pDictLayout)); + PTR_DictionaryLayout layout(dac_cast<TADDR>(imd->GetDictLayoutRaw())); IF_OPT(METHODDESCS) { WriteFieldDictionaryLayout( "m_pDictLayout", @@ -8047,7 +8042,7 @@ void NativeImageDumper::DumpMethodDesc( PTR_MethodDesc md, PTR_Module module ) else if( kind == InstantiatedMethodDesc::WrapperStubWithInstantiations ) { - PTR_MethodDesc wimd(imd->m_pWrappedMethodDesc.GetValue()); + PTR_MethodDesc wimd(imd->IMD_GetWrappedMethodDesc()); if( wimd == NULL || !DoWriteFieldAsFixup( "m_pWrappedMethodDesc", offsetof(InstantiatedMethodDesc, m_pWrappedMethodDesc), fieldsize(InstantiatedMethodDesc, m_pWrappedMethodDesc), @@ -8059,7 +8054,7 @@ void NativeImageDumper::DumpMethodDesc( PTR_MethodDesc md, PTR_Module module ) } else { - _ASSERTE(imd->m_pDictLayout == NULL); + _ASSERTE(imd->m_pDictLayout.IsNull()); DisplayWriteFieldPointer( m_pDictLayout, NULL, InstantiatedMethodDesc, METHODDESCS ); @@ -8075,7 +8070,7 @@ void NativeImageDumper::DumpMethodDesc( PTR_MethodDesc md, PTR_Module module ) else if( kind == InstantiatedMethodDesc::WrapperStubWithInstantiations ) { PTR_InstantiatedMethodDesc wrapped = - PTR_InstantiatedMethodDesc(imd->m_pWrappedMethodDesc.GetValue()); + PTR_InstantiatedMethodDesc(imd->IMD_GetWrappedMethodDesc()); if( CORCOMPILE_IS_POINTER_TAGGED(PTR_TO_TADDR(wrapped)) ) { /* XXX Mon 03/27/2006 @@ -8089,7 +8084,7 @@ void NativeImageDumper::DumpMethodDesc( PTR_MethodDesc md, PTR_Module module ) else { PTR_DictionaryLayout layout(wrapped->IsSharedByGenericMethodInstantiations() - ? TO_TADDR(wrapped->m_pDictLayout) : NULL ); + ? dac_cast<TADDR>(wrapped->GetDictLayoutRaw()) : NULL ); dictSize = DictionaryLayout::GetFirstDictionaryBucketSize(imd->GetNumGenericMethodArgs(), layout); } diff --git a/src/vm/dllimport.cpp b/src/vm/dllimport.cpp index a40754aeb4..b7807119c0 100644 --- a/src/vm/dllimport.cpp +++ b/src/vm/dllimport.cpp @@ -4368,8 +4368,8 @@ void NDirect::PopulateNDirectMethodDesc(NDirectMethodDesc* pNMD, PInvokeStaticSi else { EnsureWritablePages(&pNMD->ndirect); - pNMD->ndirect.m_pszLibName = szLibName; - pNMD->ndirect.m_pszEntrypointName = szEntryPointName; + pNMD->ndirect.m_pszLibName.SetValueMaybeNull(szLibName); + pNMD->ndirect.m_pszEntrypointName.SetValueMaybeNull(szEntryPointName); } #ifdef _TARGET_X86_ diff --git a/src/vm/dynamicmethod.cpp b/src/vm/dynamicmethod.cpp index 2a61f97afd..43f4c696df 100644 --- a/src/vm/dynamicmethod.cpp +++ b/src/vm/dynamicmethod.cpp @@ -272,7 +272,7 @@ DynamicMethodDesc* DynamicMethodTable::GetDynamicMethod(BYTE *psig, DWORD sigSiz // the store sig part of the method desc pNewMD->SetStoredMethodSig((PCCOR_SIGNATURE)psig, sigSize); // the dynamic part of the method desc - pNewMD->m_pszMethodName = name; + pNewMD->m_pszMethodName.SetValueMaybeNull(name); pNewMD->m_dwExtendedFlags = mdPublic | mdStatic | DynamicMethodDesc::nomdLCGMethod; @@ -884,16 +884,16 @@ void DynamicMethodDesc::Destroy(BOOL fDomainUnload) LoaderAllocator *pLoaderAllocator = GetLoaderAllocatorForCode(); LOG((LF_BCL, LL_INFO1000, "Level3 - Destroying DynamicMethod {0x%p}\n", this)); - if (m_pSig) + if (!m_pSig.IsNull()) { - delete[] (BYTE*)m_pSig; - m_pSig = NULL; + delete[] (BYTE*)m_pSig.GetValue(); + m_pSig.SetValueMaybeNull(NULL); } m_cSig = 0; - if (m_pszMethodName) + if (!m_pszMethodName.IsNull()) { - delete[] m_pszMethodName; - m_pszMethodName = NULL; + delete[] m_pszMethodName.GetValue(); + m_pszMethodName.SetValueMaybeNull(NULL); } GetLCGMethodResolver()->Destroy(fDomainUnload); diff --git a/src/vm/genmeth.cpp b/src/vm/genmeth.cpp index c50f806c60..d5b435bb42 100644 --- a/src/vm/genmeth.cpp +++ b/src/vm/genmeth.cpp @@ -465,7 +465,7 @@ InstantiatedMethodDesc::NewInstantiatedMethodDesc(MethodTable *pExactMT, { if (pWrappedMD->IsSharedByGenericMethodInstantiations()) { - pDL = pWrappedMD->AsInstantiatedMethodDesc()->m_pDictLayout; + pDL = pWrappedMD->AsInstantiatedMethodDesc()->GetDictLayoutRaw(); } } else if (getWrappedCode) @@ -1576,7 +1576,7 @@ void InstantiatedMethodDesc::SetupSharedMethodInstantiation(DWORD numGenericArgs _ASSERTE(FitsIn<WORD>(numGenericArgs)); m_wNumGenericArgs = static_cast<WORD>(numGenericArgs); - m_pDictLayout = pDL; + m_pDictLayout.SetValueMaybeNull(pDL); _ASSERTE(IMD_IsSharedByGenericMethodInstantiations()); diff --git a/src/vm/ilstubcache.cpp b/src/vm/ilstubcache.cpp index 95e1845e5b..4e5ce12bca 100644 --- a/src/vm/ilstubcache.cpp +++ b/src/vm/ilstubcache.cpp @@ -167,7 +167,7 @@ MethodDesc* ILStubCache::CreateNewMethodDesc(LoaderHeap* pCreationHeap, MethodTa pMD->SetMemberDef(0); pMD->SetSlot(MethodTable::NO_SLOT); // we can't ever use the slot for dynamic methods // the no metadata part of the method desc - pMD->m_pszMethodName = (PTR_CUTF8)"IL_STUB"; + pMD->m_pszMethodName.SetValue((PTR_CUTF8)"IL_STUB"); pMD->m_dwExtendedFlags = mdPublic | DynamicMethodDesc::nomdILStub; pMD->SetTemporaryEntryPoint(pMT->GetLoaderAllocator(), pamTracker); @@ -294,11 +294,11 @@ MethodDesc* ILStubCache::CreateNewMethodDesc(LoaderHeap* pCreationHeap, MethodTa { switch(dwStubFlags) { - case ILSTUB_ARRAYOP_GET: pMD->m_pszMethodName = (PTR_CUTF8)"IL_STUB_Array_Get"; + case ILSTUB_ARRAYOP_GET: pMD->m_pszMethodName.SetValue((PTR_CUTF8)"IL_STUB_Array_Get"); break; - case ILSTUB_ARRAYOP_SET: pMD->m_pszMethodName = (PTR_CUTF8)"IL_STUB_Array_Set"; + case ILSTUB_ARRAYOP_SET: pMD->m_pszMethodName.SetValue((PTR_CUTF8)"IL_STUB_Array_Set"); break; - case ILSTUB_ARRAYOP_ADDRESS: pMD->m_pszMethodName = (PTR_CUTF8)"IL_STUB_Array_Address"; + case ILSTUB_ARRAYOP_ADDRESS: pMD->m_pszMethodName.SetValue((PTR_CUTF8)"IL_STUB_Array_Address"); break; default: _ASSERTE(!"Unknown array il stub"); } @@ -306,12 +306,12 @@ MethodDesc* ILStubCache::CreateNewMethodDesc(LoaderHeap* pCreationHeap, MethodTa else #endif { - pMD->m_pszMethodName = pMD->GetILStubResolver()->GetStubMethodName(); + pMD->m_pszMethodName.SetValue(pMD->GetILStubResolver()->GetStubMethodName()); } #ifdef _DEBUG - pMD->m_pszDebugMethodName = pMD->m_pszMethodName; + pMD->m_pszDebugMethodName = RelativePointer<PTR_CUTF8>::GetValueAtPtr(PTR_HOST_MEMBER_TADDR(DynamicMethodDesc, pMD, m_pszMethodName)); pMD->m_pszDebugClassName = ILStubResolver::GetStubClassName(pMD); // must be called after type is set pMD->m_pszDebugMethodSignature = FormatSig(pMD, pCreationHeap, pamTracker); pMD->m_pDebugMethodTable.SetValue(pMT); diff --git a/src/vm/method.cpp b/src/vm/method.cpp index c3b13aaa08..ca0ecc178d 100644 --- a/src/vm/method.cpp +++ b/src/vm/method.cpp @@ -2764,7 +2764,7 @@ void MethodDesc::Save(DataImage *image) if (pNewSMD->HasStoredMethodSig()) { - if (!image->IsStored((void *) pNewSMD->m_pSig)) + if (!image->IsStored((void *) pNewSMD->m_pSig.GetValueMaybeNull())) { // Store signatures that doesn't need restore into a read only section. DataImage::ItemKind sigItemKind = DataImage::ITEM_STORED_METHOD_SIG_READONLY; @@ -2780,7 +2780,7 @@ void MethodDesc::Save(DataImage *image) } if (FixupSignatureContainingInternalTypes(image, - (PCCOR_SIGNATURE)pNewSMD->m_pSig, + (PCCOR_SIGNATURE) pNewSMD->m_pSig.GetValueMaybeNull(), pNewSMD->m_cSig, true /*checkOnly if we will need to restore the signature without doing fixup*/)) { @@ -2788,7 +2788,7 @@ void MethodDesc::Save(DataImage *image) } } - image->StoreInternedStructure((void *) pNewSMD->m_pSig, + image->StoreInternedStructure((void *) pNewSMD->m_pSig.GetValueMaybeNull(), pNewSMD->m_cSig, sigItemKind, 1); @@ -2809,9 +2809,9 @@ void MethodDesc::Save(DataImage *image) if (HasMethodInstantiation()) { InstantiatedMethodDesc* pIMD = AsInstantiatedMethodDesc(); - if (pIMD->IMD_IsSharedByGenericMethodInstantiations() && pIMD->m_pDictLayout != NULL) + if (pIMD->IMD_IsSharedByGenericMethodInstantiations() && !pIMD->m_pDictLayout.IsNull()) { - pIMD->m_pDictLayout->Save(image); + pIMD->m_pDictLayout.GetValue()->Save(image); } } if (IsNDirect()) @@ -2887,9 +2887,10 @@ void MethodDesc::Save(DataImage *image) if (IsDynamicMethod()) { DynamicMethodDesc *pDynMeth = AsDynamicMethodDesc(); - if (pDynMeth->m_pszMethodName && !image->IsStored(pDynMeth->m_pszMethodName)) - image->StoreStructure((void *) pDynMeth->m_pszMethodName, - (ULONG)(strlen(pDynMeth->m_pszMethodName) + 1), + if (!pDynMeth->m_pszMethodName.IsNull() + && !image->IsStored(pDynMeth->m_pszMethodName.GetValue())) + image->StoreStructure((void *) pDynMeth->m_pszMethodName.GetValue(), + (ULONG)(strlen(pDynMeth->m_pszMethodName.GetValue()) + 1), DataImage::ITEM_STORED_METHOD_NAME, 1); } @@ -3474,7 +3475,7 @@ MethodDesc::Fixup( if (IsDynamicMethod()) { image->ZeroPointerField(this, offsetof(DynamicMethodDesc, m_pResolver)); - image->FixupPointerField(this, offsetof(DynamicMethodDesc, m_pszMethodName)); + image->FixupRelativePointerField(this, offsetof(DynamicMethodDesc, m_pszMethodName)); } if (GetClassification() == mcInstantiated) @@ -3490,8 +3491,8 @@ MethodDesc::Fixup( { if (pIMD->IMD_IsSharedByGenericMethodInstantiations()) { - pIMD->m_pDictLayout->Fixup(image, TRUE); - image->FixupPointerField(this, offsetof(InstantiatedMethodDesc, m_pDictLayout)); + pIMD->m_pDictLayout.GetValue()->Fixup(image, TRUE); + image->FixupRelativePointerField(this, offsetof(InstantiatedMethodDesc, m_pDictLayout)); } } @@ -3599,7 +3600,7 @@ MethodDesc::Fixup( if (!pNMD->MarshalingRequired()) { // import thunk is only needed if the P/Invoke is inlinable - image->FixupPointerField(this, offsetof(NDirectMethodDesc, ndirect.m_pImportThunkGlue)); + image->FixupRelativePointerField(this, offsetof(NDirectMethodDesc, ndirect.m_pImportThunkGlue)); ((Precode*)pImportThunkGlue)->Fixup(image, this); } else @@ -3612,8 +3613,8 @@ MethodDesc::Fixup( if (!IsQCall()) { - image->FixupPointerField(this, offsetof(NDirectMethodDesc, ndirect.m_pszLibName)); - image->FixupPointerField(this, offsetof(NDirectMethodDesc, ndirect.m_pszEntrypointName)); + image->FixupRelativePointerField(this, offsetof(NDirectMethodDesc, ndirect.m_pszLibName)); + image->FixupRelativePointerField(this, offsetof(NDirectMethodDesc, ndirect.m_pszEntrypointName)); } if (image->IsStored(pNMD->ndirect.m_pStubMD.GetValueMaybeNull())) @@ -3624,7 +3625,7 @@ MethodDesc::Fixup( if (HasStoredSig()) { - image->FixupPointerField(this, offsetof(StoredSigMethodDesc, m_pSig)); + image->FixupRelativePointerField(this, offsetof(StoredSigMethodDesc, m_pSig)); // The DynamicMethodDescs used for IL stubs may have a signature that refers to // runtime types using ELEMENT_TYPE_INTERNAL. We need to fixup these types here. @@ -5357,7 +5358,7 @@ StoredSigMethodDesc::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) { SUPPORTS_DAC; // 'this' already done, see below. - DacEnumMemoryRegion(m_pSig, m_cSig); + DacEnumMemoryRegion(GetSigRVA(), m_cSig); } //******************************************************************************* diff --git a/src/vm/method.hpp b/src/vm/method.hpp index 778ce1cc87..228ef0cd2a 100644 --- a/src/vm/method.hpp +++ b/src/vm/method.hpp @@ -2209,7 +2209,7 @@ class StoredSigMethodDesc : public MethodDesc // Put the sig RVA in here - this allows us to avoid // touching the method desc table when mscorlib is prejitted. - TADDR m_pSig; + RelativePointer<TADDR> m_pSig; DWORD m_cSig; #ifdef _WIN64 // m_dwExtendedFlags is not used by StoredSigMethodDesc itself. @@ -2218,10 +2218,16 @@ class StoredSigMethodDesc : public MethodDesc DWORD m_dwExtendedFlags; #endif + TADDR GetSigRVA() + { + LIMITED_METHOD_DAC_CONTRACT; + return RelativePointer<TADDR>::GetValueMaybeNullAtPtr(PTR_HOST_MEMBER_TADDR(StoredSigMethodDesc, this, m_pSig)); + } + bool HasStoredMethodSig(void) { LIMITED_METHOD_DAC_CONTRACT; - return m_pSig != 0; + return !m_pSig.IsNull(); } PCCOR_SIGNATURE GetStoredMethodSig(DWORD* sigLen = NULL) { @@ -2232,16 +2238,16 @@ class StoredSigMethodDesc : public MethodDesc } #ifdef DACCESS_COMPILE return (PCCOR_SIGNATURE) - DacInstantiateTypeByAddress(m_pSig, m_cSig, true); + DacInstantiateTypeByAddress(GetSigRVA(), m_cSig, true); #else // !DACCESS_COMPILE g_IBCLogger.LogNDirectCodeAccess(this); - return (PCCOR_SIGNATURE)m_pSig; + return (PCCOR_SIGNATURE) m_pSig.GetValueMaybeNull(); #endif // !DACCESS_COMPILE } void SetStoredMethodSig(PCCOR_SIGNATURE sig, DWORD sigBytes) { #ifndef DACCESS_COMPILE - m_pSig = (TADDR)sig; + m_pSig.SetValueMaybeNull((TADDR)sig); m_cSig = sigBytes; #endif // !DACCESS_COMPILE } @@ -2301,7 +2307,7 @@ class DynamicMethodDesc : public StoredSigMethodDesc #endif protected: - PTR_CUTF8 m_pszMethodName; + RelativePointer<PTR_CUTF8> m_pszMethodName; PTR_DynamicResolver m_pResolver; #ifndef _WIN64 @@ -2342,7 +2348,11 @@ public: inline PTR_LCGMethodResolver GetLCGMethodResolver(); inline PTR_ILStubResolver GetILStubResolver(); - PTR_CUTF8 GetMethodName() { LIMITED_METHOD_DAC_CONTRACT; return m_pszMethodName; } + PTR_CUTF8 GetMethodName() + { + LIMITED_METHOD_DAC_CONTRACT; + return RelativePointer<PTR_CUTF8>::GetValueMaybeNullAtPtr(PTR_HOST_MEMBER_TADDR(DynamicMethodDesc, this, m_pszMethodName)); + } WORD GetAttrs() { @@ -2567,11 +2577,11 @@ public: LPVOID m_pNativeNDirectTarget; // Information about the entrypoint - LPCUTF8 m_pszEntrypointName; + RelativePointer<PTR_CUTF8> m_pszEntrypointName; union { - LPCUTF8 m_pszLibName; + RelativePointer<PTR_CUTF8> m_pszLibName; DWORD m_dwECallID; // ECallID for QCalls }; @@ -2579,7 +2589,7 @@ public: PTR_NDirectWriteableData m_pWriteableData; #ifdef HAS_NDIRECT_IMPORT_PRECODE - PTR_NDirectImportThunkGlue m_pImportThunkGlue; + RelativePointer<PTR_NDirectImportThunkGlue> m_pImportThunkGlue; #else // HAS_NDIRECT_IMPORT_PRECODE NDirectImportThunkGlue m_ImportThunkGlue; #endif // HAS_NDIRECT_IMPORT_PRECODE @@ -2702,18 +2712,27 @@ public: ndirect.m_dwECallID = dwID; } + PTR_CUTF8 GetLibNameRaw() + { + LIMITED_METHOD_DAC_CONTRACT; + + return RelativePointer<PTR_CUTF8>::GetValueMaybeNullAtPtr(PTR_HOST_MEMBER_TADDR(NDirectMethodDesc, this, ndirect.m_pszLibName)); + } + +#ifndef DACCESS_COMPILE LPCUTF8 GetLibName() const { LIMITED_METHOD_CONTRACT; - return IsQCall() ? "QCall" : ndirect.m_pszLibName; + return IsQCall() ? "QCall" : ndirect.m_pszLibName.GetValueMaybeNull(); } +#endif // !DACCESS_COMPILE - LPCUTF8 GetEntrypointName() const + PTR_CUTF8 GetEntrypointName() const { - LIMITED_METHOD_CONTRACT; + LIMITED_METHOD_DAC_CONTRACT; - return ndirect.m_pszEntrypointName; + return RelativePointer<PTR_CUTF8>::GetValueMaybeNullAtPtr(PTR_HOST_MEMBER_TADDR(NDirectMethodDesc, this, ndirect.m_pszEntrypointName)); } BOOL IsVarArgs() const @@ -2796,14 +2815,16 @@ public: return ndirect.m_pWriteableData; } - NDirectImportThunkGlue* GetNDirectImportThunkGlue() + PTR_NDirectImportThunkGlue GetNDirectImportThunkGlue() { - LIMITED_METHOD_CONTRACT; + LIMITED_METHOD_DAC_CONTRACT; + + TADDR base = PTR_HOST_MEMBER_TADDR(NDirectMethodDesc, this, ndirect.m_pImportThunkGlue); #ifdef HAS_NDIRECT_IMPORT_PRECODE - return ndirect.m_pImportThunkGlue; + return RelativePointer<PTR_NDirectImportThunkGlue>::GetValueAtPtr(base); #else - return &ndirect.m_ImportThunkGlue; + return dac_cast<PTR_NDirectImportThunkGlue>(base); #endif } @@ -3277,28 +3298,37 @@ public: } #endif // FEATURE_COMINTEROP + PTR_DictionaryLayout GetDictLayoutRaw() + { + LIMITED_METHOD_DAC_CONTRACT; + return RelativePointer<PTR_DictionaryLayout>::GetValueMaybeNullAtPtr(PTR_HOST_MEMBER_TADDR(InstantiatedMethodDesc, this, m_pDictLayout)); + } + + PTR_MethodDesc IMD_GetWrappedMethodDesc() + { + LIMITED_METHOD_DAC_CONTRACT; + + _ASSERTE(IMD_IsWrapperStubWithInstantiations()); + return RelativePointer<PTR_MethodDesc>::GetValueAtPtr(PTR_HOST_MEMBER_TADDR(InstantiatedMethodDesc, this, m_pWrappedMethodDesc)); + } + +#ifndef DACCESS_COMPILE // Get the dictionary layout, if there is one DictionaryLayout* IMD_GetDictionaryLayout() { WRAPPER_NO_CONTRACT; if (IMD_IsWrapperStubWithInstantiations() && IMD_HasMethodInstantiation()) - return IMD_GetWrappedMethodDesc()->AsInstantiatedMethodDesc()->m_pDictLayout; + { + InstantiatedMethodDesc* pIMD = IMD_GetWrappedMethodDesc()->AsInstantiatedMethodDesc(); + return pIMD->m_pDictLayout.GetValueMaybeNull(); + } else if (IMD_IsSharedByGenericMethodInstantiations()) - return m_pDictLayout; + return m_pDictLayout.GetValueMaybeNull(); else return NULL; } - - MethodDesc* IMD_GetWrappedMethodDesc() - { - LIMITED_METHOD_CONTRACT; - - _ASSERTE(IMD_IsWrapperStubWithInstantiations()); - return m_pWrappedMethodDesc.GetValue(); - } - - +#endif // !DACCESS_COMPILE // Setup the IMD as shared code void SetupSharedMethodInstantiation(DWORD numGenericArgs, TypeHandle *pPerInstInfo, DictionaryLayout *pDL); @@ -3345,9 +3375,9 @@ private: friend class MethodDesc; // this fields are currently accessed by MethodDesc::Save/Restore etc. union { - DictionaryLayout * m_pDictLayout; //SharedMethodInstantiation + RelativePointer<PTR_DictionaryLayout> m_pDictLayout; //SharedMethodInstantiation - FixupPointer<PTR_MethodDesc> m_pWrappedMethodDesc; // For WrapperStubWithInstantiations + RelativeFixupPointer<PTR_MethodDesc> m_pWrappedMethodDesc; // For WrapperStubWithInstantiations }; public: // <TODO>make private: JITinterface.cpp accesses through this </TODO> diff --git a/src/vm/methodimpl.cpp b/src/vm/methodimpl.cpp index 1779c2de89..c685e1c8a5 100644 --- a/src/vm/methodimpl.cpp +++ b/src/vm/methodimpl.cpp @@ -72,7 +72,10 @@ PTR_MethodDesc MethodImpl::FindMethodDesc(DWORD slot, PTR_MethodDesc defaultRetu return defaultReturn; } - PTR_MethodDesc result = pImplementedMD[slotIndex]; // The method descs are not offset by one + DPTR(RelativePointer<PTR_MethodDesc>) pRelPtrForSlot = GetImpMDsNonNull(); + // The method descs are not offset by one + TADDR base = dac_cast<TADDR>(pRelPtrForSlot) + slotIndex * sizeof(RelativePointer<MethodDesc *>); + PTR_MethodDesc result = RelativePointer<PTR_MethodDesc>::GetValueMaybeNullAtPtr(base); // Prejitted images may leave NULL in this table if // the methoddesc is declared in another module. @@ -98,13 +101,13 @@ MethodDesc *MethodImpl::RestoreSlot(DWORD index, MethodTable *pMT) NOTHROW; GC_NOTRIGGER; FORBID_FAULT; - PRECONDITION(CheckPointer(pdwSlots)); + PRECONDITION(!pdwSlots.IsNull()); } CONTRACTL_END MethodDesc *result; - PREFIX_ASSUME(pdwSlots != NULL); + PREFIX_ASSUME(!pdwSlots.IsNull()); DWORD slot = GetSlots()[index]; // Since the overridden method is in a different module, we @@ -126,8 +129,9 @@ MethodDesc *MethodImpl::RestoreSlot(DWORD index, MethodTable *pMT) _ASSERTE(result != NULL); // Don't worry about races since we would all be setting the same result - if (EnsureWritableExecutablePagesNoThrow(&pImplementedMD[index], sizeof(pImplementedMD[index]))) - pImplementedMD[index] = result; + if (EnsureWritableExecutablePagesNoThrow(&pImplementedMD.GetValue()[index], + sizeof(pImplementedMD.GetValue()[index]))) + pImplementedMD.GetValue()[index].SetValue(result); return result; } @@ -139,7 +143,7 @@ void MethodImpl::SetSize(LoaderHeap *pHeap, AllocMemTracker *pamTracker, DWORD s THROWS; GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); - PRECONDITION(pdwSlots==NULL && pImplementedMD==NULL); + PRECONDITION(pdwSlots.GetValueMaybeNull()==NULL && pImplementedMD.GetValueMaybeNull()==NULL); INJECT_FAULT(ThrowOutOfMemory()); } CONTRACTL_END; @@ -149,7 +153,7 @@ void MethodImpl::SetSize(LoaderHeap *pHeap, AllocMemTracker *pamTracker, DWORD s S_SIZE_T(size) * S_SIZE_T(sizeof(DWORD)); // DWORD each for the slot numbers // MethodDesc* for each of the implemented methods - S_SIZE_T cbMethodDescs = S_SIZE_T(size) * S_SIZE_T(sizeof(MethodDesc *)); + S_SIZE_T cbMethodDescs = S_SIZE_T(size) * S_SIZE_T(sizeof(RelativePointer<MethodDesc *>)); // Need to align-up the slot entries so that the MethodDesc* array starts on a pointer boundary. cbCountAndSlots.AlignUp(sizeof(MethodDesc*)); @@ -161,29 +165,36 @@ void MethodImpl::SetSize(LoaderHeap *pHeap, AllocMemTracker *pamTracker, DWORD s LPBYTE pAllocData = (BYTE*)pamTracker->Track(pHeap->AllocMem(cbTotal)); // Set the count and slot array - pdwSlots = (DWORD*)pAllocData; + pdwSlots.SetValue((DWORD*)pAllocData); // Set the MethodDesc* array. Make sure to adjust for alignment. - pImplementedMD = (MethodDesc**)ALIGN_UP(pAllocData + cbCountAndSlots.Value(), sizeof(MethodDesc*)); + pImplementedMD.SetValue((RelativePointer<MethodDesc*> *)ALIGN_UP(pAllocData + cbCountAndSlots.Value(), sizeof(RelativePointer <MethodDesc*>))); // Store the count in the first entry - *pdwSlots = size; + *pdwSlots.GetValue() = size; } } /////////////////////////////////////////////////////////////////////////////////////// -void MethodImpl::SetData(DWORD* slots, MethodDesc** md) +void MethodImpl::SetData(DWORD* slots, RelativePointer<MethodDesc*>* md) { CONTRACTL { NOTHROW; GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); - PRECONDITION(CheckPointer(pdwSlots)); + PRECONDITION(!pdwSlots.IsNull()); } CONTRACTL_END; - DWORD dwSize = *pdwSlots; - memcpy(&(pdwSlots[1]), slots, dwSize*sizeof(DWORD)); - memcpy(pImplementedMD, md, dwSize*sizeof(MethodDesc*)); + DWORD *pdwSize = pdwSlots.GetValue(); + DWORD dwSize = *pdwSize; + memcpy(&(pdwSize[1]), slots, dwSize*sizeof(DWORD)); + + RelativePointer<MethodDesc *> *pImplMD = pImplementedMD.GetValue(); + + for (uint32_t i = 0; i < dwSize; ++i) + { + pImplMD[i].SetValue(md[i].GetValue()); + } } #ifdef FEATURE_NATIVE_IMAGE_GENERATION @@ -194,10 +205,10 @@ void MethodImpl::Save(DataImage *image) DWORD size = GetSize(); _ASSERTE(size > 0); - image->StoreStructure(pdwSlots, (size+1)*sizeof(DWORD), + image->StoreStructure(pdwSlots.GetValue(), (size+1)*sizeof(DWORD), DataImage::ITEM_METHOD_DESC_COLD, sizeof(DWORD)); - image->StoreStructure(pImplementedMD, size*sizeof(MethodDesc*), + image->StoreStructure(pImplementedMD.GetValue(), size*sizeof(RelativePointer<MethodDesc*>), DataImage::ITEM_METHOD_DESC_COLD, sizeof(MethodDesc*)); } @@ -214,21 +225,22 @@ void MethodImpl::Fixup(DataImage *image, PVOID p, SSIZE_T offset) // <TODO> Why not use FixupMethodDescPointer? </TODO> // <TODO> Does it matter if the MethodDesc needs a restore? </TODO> - MethodDesc * pMD = pImplementedMD[iMD]; + RelativePointer<MethodDesc *> *pRelPtr = pImplementedMD.GetValue(); + MethodDesc * pMD = pRelPtr[iMD].GetValueMaybeNull(); if (image->CanEagerBindToMethodDesc(pMD) && image->CanHardBindToZapModule(pMD->GetLoaderModule())) { - image->FixupPointerField(pImplementedMD, iMD * sizeof(MethodDesc *)); + image->FixupRelativePointerField(pImplementedMD.GetValue(), iMD * sizeof(RelativePointer<MethodDesc *>)); } else { - image->ZeroPointerField(pImplementedMD, iMD * sizeof(MethodDesc *)); + image->ZeroPointerField(pImplementedMD.GetValue(), iMD * sizeof(RelativePointer<MethodDesc *>)); } } - image->FixupPointerField(p, offset + offsetof(MethodImpl, pdwSlots)); - image->FixupPointerField(p, offset + offsetof(MethodImpl, pImplementedMD)); + image->FixupRelativePointerField(p, offset + offsetof(MethodImpl, pdwSlots)); + image->FixupRelativePointerField(p, offset + offsetof(MethodImpl, pImplementedMD)); } #endif // FEATURE_NATIVE_IMAGE_GENERATION @@ -247,19 +259,20 @@ MethodImpl::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) // 'this' memory should already be enumerated as // part of the base MethodDesc. - if (pdwSlots.IsValid() && GetSize()) + if (GetSlotsRaw().IsValid() && GetSize()) { ULONG32 numSlots = GetSize(); - DacEnumMemoryRegion(dac_cast<TADDR>(pdwSlots), + DacEnumMemoryRegion(dac_cast<TADDR>(GetSlotsRawNonNull()), (numSlots + 1) * sizeof(DWORD)); - if (pImplementedMD.IsValid()) + if (GetImpMDs().IsValid()) { - DacEnumMemoryRegion(dac_cast<TADDR>(pImplementedMD), - numSlots * sizeof(PTR_MethodDesc)); + DacEnumMemoryRegion(dac_cast<TADDR>(GetImpMDsNonNull()), + numSlots * sizeof(RelativePointer<MethodDesc *>)); for (DWORD i = 0; i < numSlots; i++) { - PTR_MethodDesc methodDesc = pImplementedMD[i]; + DPTR(RelativePointer<PTR_MethodDesc>) pRelPtr = GetImpMDsNonNull(); + PTR_MethodDesc methodDesc = pRelPtr[i].GetValueMaybeNull(); if (methodDesc.IsValid()) { methodDesc->EnumMemoryRegions(flags); diff --git a/src/vm/methodimpl.h b/src/vm/methodimpl.h index 0646367f22..453f4ccd4d 100644 --- a/src/vm/methodimpl.h +++ b/src/vm/methodimpl.h @@ -24,8 +24,8 @@ class MethodImpl friend class NativeImageDumper; #endif - PTR_DWORD pdwSlots; // Maintains the slots in sorted order, the first entry is the size - DPTR(PTR_MethodDesc) pImplementedMD; + RelativePointer<PTR_DWORD> pdwSlots; // Maintains the slots in sorted order, the first entry is the size + RelativePointer<DPTR( RelativePointer<PTR_MethodDesc> )> pImplementedMD; public: @@ -49,18 +49,19 @@ public: inline MethodDesc *GetMethodDesc() { WRAPPER_NO_CONTRACT; return m_pImpl->FindMethodDesc(GetSlot(), (PTR_MethodDesc) m_pMD); } }; +#endif // !DACCESS_COMPILE - /////////////////////////////////////////////////////////////////////////////////////// - inline MethodDesc** GetImplementedMDs() + inline DPTR(RelativePointer<PTR_MethodDesc>) GetImpMDs() { - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - } CONTRACTL_END; - return pImplementedMD; + LIMITED_METHOD_DAC_CONTRACT; + return RelativePointer<DPTR(RelativePointer<PTR_MethodDesc>)>::GetValueMaybeNullAtPtr(PTR_HOST_MEMBER_TADDR(MethodImpl, this, pImplementedMD)); + } + + inline DPTR(RelativePointer<PTR_MethodDesc>) GetImpMDsNonNull() + { + LIMITED_METHOD_DAC_CONTRACT; + return RelativePointer<DPTR(RelativePointer<PTR_MethodDesc>)>::GetValueAtPtr(PTR_HOST_MEMBER_TADDR(MethodImpl, this, pImplementedMD)); } -#endif // !DACCESS_COMPILE /////////////////////////////////////////////////////////////////////////////////////// inline DWORD GetSize() @@ -71,10 +72,10 @@ public: PRECONDITION(CheckPointer(this)); } CONTRACTL_END; - if(pdwSlots == NULL) + if(pdwSlots.IsNull()) return 0; else - return *pdwSlots; + return *GetSlotsRawNonNull(); } /////////////////////////////////////////////////////////////////////////////////////// @@ -87,10 +88,22 @@ public: SUPPORTS_DAC; } CONTRACTL_END; - if(pdwSlots == NULL) + if(pdwSlots.IsNull()) return NULL; else - return pdwSlots + 1; + return GetSlotsRawNonNull() + 1; + } + + inline PTR_DWORD GetSlotsRaw() + { + LIMITED_METHOD_DAC_CONTRACT; + return RelativePointer<PTR_DWORD>::GetValueMaybeNullAtPtr(PTR_HOST_MEMBER_TADDR(MethodImpl, this, pdwSlots)); + } + + inline PTR_DWORD GetSlotsRawNonNull() + { + LIMITED_METHOD_DAC_CONTRACT; + return RelativePointer<PTR_DWORD>::GetValueAtPtr(PTR_HOST_MEMBER_TADDR(MethodImpl, this, pdwSlots)); } #ifndef DACCESS_COMPILE @@ -99,7 +112,7 @@ public: void SetSize(LoaderHeap *pHeap, AllocMemTracker *pamTracker, DWORD size); /////////////////////////////////////////////////////////////////////////////////////// - void SetData(DWORD* slots, MethodDesc** md); + void SetData(DWORD* slots, RelativePointer<MethodDesc*> * md); #endif // !DACCESS_COMPILE diff --git a/src/vm/methodtablebuilder.cpp b/src/vm/methodtablebuilder.cpp index 5700a69f7f..01c7ce97ab 100644 --- a/src/vm/methodtablebuilder.cpp +++ b/src/vm/methodtablebuilder.cpp @@ -5917,8 +5917,8 @@ MethodTableBuilder::InitMethodDesc( AllocateFromHighFrequencyHeap(S_SIZE_T(sizeof(NDirectWriteableData))); #ifdef HAS_NDIRECT_IMPORT_PRECODE - pNewNMD->ndirect.m_pImportThunkGlue = Precode::Allocate(PRECODE_NDIRECT_IMPORT, pNewMD, - GetLoaderAllocator(), GetMemTracker())->AsNDirectImportPrecode(); + pNewNMD->ndirect.m_pImportThunkGlue.SetValue(Precode::Allocate(PRECODE_NDIRECT_IMPORT, pNewMD, + GetLoaderAllocator(), GetMemTracker())->AsNDirectImportPrecode()); #else // !HAS_NDIRECT_IMPORT_PRECODE pNewNMD->GetNDirectImportThunkGlue()->Init(pNewNMD); #endif // !HAS_NDIRECT_IMPORT_PRECODE @@ -6163,7 +6163,7 @@ MethodTableBuilder::PlaceMethodImpls() // Allocate some temporary storage. The number of overrides for a single method impl // cannot be greater then the number of vtable slots. DWORD * slots = new (&GetThread()->m_MarshalAlloc) DWORD[bmtVT->cVirtualSlots]; - MethodDesc ** replaced = new (&GetThread()->m_MarshalAlloc) MethodDesc*[bmtVT->cVirtualSlots]; + RelativePointer<MethodDesc *> * replaced = new (&GetThread()->m_MarshalAlloc) RelativePointer<MethodDesc*>[bmtVT->cVirtualSlots]; DWORD iEntry = 0; bmtMDMethod * pCurImplMethod = bmtMethodImpl->GetImplementationMethod(iEntry); @@ -6250,7 +6250,7 @@ MethodTableBuilder::WriteMethodImplData( bmtMDMethod * pImplMethod, DWORD cSlots, DWORD * rgSlots, - MethodDesc ** rgDeclMD) + RelativePointer<MethodDesc *> * rgDeclMD) { STANDARD_VM_CONTRACT; @@ -6280,9 +6280,9 @@ MethodTableBuilder::WriteMethodImplData( { if (rgSlots[j] < rgSlots[i]) { - MethodDesc * mTmp = rgDeclMD[i]; - rgDeclMD[i] = rgDeclMD[j]; - rgDeclMD[j] = mTmp; + MethodDesc * mTmp = rgDeclMD[i].GetValue(); + rgDeclMD[i].SetValue(rgDeclMD[j].GetValue()); + rgDeclMD[j].SetValue(mTmp); DWORD sTmp = rgSlots[i]; rgSlots[i] = rgSlots[j]; @@ -6304,7 +6304,7 @@ MethodTableBuilder::PlaceLocalDeclaration( bmtMDMethod * pDecl, bmtMDMethod * pImpl, DWORD * slots, - MethodDesc ** replaced, + RelativePointer<MethodDesc *> * replaced, DWORD * pSlotIndex) { CONTRACTL @@ -6361,7 +6361,7 @@ MethodTableBuilder::PlaceLocalDeclaration( // We implement this slot, record it slots[*pSlotIndex] = pDecl->GetSlotIndex(); - replaced[*pSlotIndex] = pDecl->GetMethodDesc(); + replaced[*pSlotIndex].SetValue(pDecl->GetMethodDesc()); // increment the counter (*pSlotIndex)++; @@ -6372,7 +6372,7 @@ VOID MethodTableBuilder::PlaceInterfaceDeclaration( bmtRTMethod * pDecl, bmtMDMethod * pImpl, DWORD* slots, - MethodDesc** replaced, + RelativePointer<MethodDesc *> * replaced, DWORD* pSlotIndex) { CONTRACTL { @@ -6477,7 +6477,7 @@ MethodTableBuilder::PlaceParentDeclaration( bmtRTMethod * pDecl, bmtMDMethod * pImpl, DWORD * slots, - MethodDesc ** replaced, + RelativePointer<MethodDesc *> * replaced, DWORD * pSlotIndex) { CONTRACTL { @@ -6522,7 +6522,7 @@ MethodTableBuilder::PlaceParentDeclaration( // We implement this slot, record it slots[*pSlotIndex] = pDeclMD->GetSlot(); - replaced[*pSlotIndex] = pDeclMD; + replaced[*pSlotIndex].SetValue(pDeclMD); // increment the counter (*pSlotIndex)++; diff --git a/src/vm/methodtablebuilder.h b/src/vm/methodtablebuilder.h index d1c99286aa..e5043cf06d 100644 --- a/src/vm/methodtablebuilder.h +++ b/src/vm/methodtablebuilder.h @@ -2734,7 +2734,7 @@ private: bmtMDMethod * pImplMethod, DWORD cSlots, DWORD * rgSlots, - MethodDesc ** rgDeclMD); + RelativePointer<MethodDesc *> * rgDeclMD); // -------------------------------------------------------------------------------------------- // Places a methodImpl pair where the decl is declared by the type being built. @@ -2743,7 +2743,7 @@ private: bmtMDMethod * pDecl, bmtMDMethod * pImpl, DWORD* slots, - MethodDesc** replaced, + RelativePointer<MethodDesc *> * replaced, DWORD* pSlotIndex); // -------------------------------------------------------------------------------------------- @@ -2753,7 +2753,7 @@ private: bmtRTMethod * pDecl, bmtMDMethod * pImpl, DWORD* slots, - MethodDesc** replaced, + RelativePointer<MethodDesc *> * replaced, DWORD* pSlotIndex); // -------------------------------------------------------------------------------------------- @@ -2763,7 +2763,7 @@ private: bmtRTMethod * pDecl, bmtMDMethod * pImpl, DWORD* slots, - MethodDesc** replaced, + RelativePointer<MethodDesc *> * replaced, DWORD* pSlotIndex); // -------------------------------------------------------------------------------------------- |