From 8c5a78bf0c6d1e0f55733d51f04e05470d7427ac Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 17 Aug 2021 15:19:13 -0700 Subject: [PATCH 1/9] Delete clrjit_crossgen target --- src/coreclr/jit/CMakeLists.txt | 4 ---- src/coreclr/jit/crossgen/CMakeLists.txt | 6 ------ src/coreclr/zap/CMakeLists.txt | 4 ---- 3 files changed, 14 deletions(-) delete mode 100644 src/coreclr/jit/crossgen/CMakeLists.txt diff --git a/src/coreclr/jit/CMakeLists.txt b/src/coreclr/jit/CMakeLists.txt index 629ea1ae4bc9d7..ae033295cee5fa 100644 --- a/src/coreclr/jit/CMakeLists.txt +++ b/src/coreclr/jit/CMakeLists.txt @@ -482,10 +482,6 @@ endfunction() set(JIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -if (FEATURE_MERGE_JIT_AND_ENGINE) - add_subdirectory(crossgen) -endif (FEATURE_MERGE_JIT_AND_ENGINE) - # Creates a static library "clrjit_static" to link into the VM. add_subdirectory(static) diff --git a/src/coreclr/jit/crossgen/CMakeLists.txt b/src/coreclr/jit/crossgen/CMakeLists.txt deleted file mode 100644 index 30d35e8cde59ed..00000000000000 --- a/src/coreclr/jit/crossgen/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -add_library_clr(clrjit_crossgen ${SOURCES} ${JIT_ARCH_SOURCES}) -if(FEATURE_MERGE_JIT_AND_ENGINE) - target_link_libraries(clrjit_crossgen ${JIT_LINK_LIBRARIES} ${JIT_ARCH_LINK_LIBRARIES}) -endif(FEATURE_MERGE_JIT_AND_ENGINE) -set_target_properties(clrjit_crossgen PROPERTIES CROSSGEN_COMPONENT TRUE) -target_precompile_headers(clrjit_static PRIVATE [["jitpch.h"]]) diff --git a/src/coreclr/zap/CMakeLists.txt b/src/coreclr/zap/CMakeLists.txt index 12bcebbcbf3897..972568e7becb3e 100644 --- a/src/coreclr/zap/CMakeLists.txt +++ b/src/coreclr/zap/CMakeLists.txt @@ -50,7 +50,3 @@ endif(CLR_CMAKE_TARGET_WIN32) add_library_clr(corzap_crossgen STATIC ${ZAP_SOURCES}) set_target_properties(corzap_crossgen PROPERTIES CROSSGEN_COMPONENT TRUE) target_precompile_headers(corzap_crossgen PRIVATE [["common.h"]]) - -if(FEATURE_MERGE_JIT_AND_ENGINE) - target_link_libraries(corzap_crossgen clrjit_crossgen) -endif(FEATURE_MERGE_JIT_AND_ENGINE) From ec6c6338a4a598cfa8118825dedbb103572e2039 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 17 Aug 2021 15:20:45 -0700 Subject: [PATCH 2/9] Delete corzap_crosgen target and all of its code since it's unreferenced. --- src/coreclr/zap/CMakeLists.txt | 52 - src/coreclr/zap/common.h | 64 - src/coreclr/zap/nativeformatwriter.cpp | 575 ---- src/coreclr/zap/nativeformatwriter.h | 354 -- src/coreclr/zap/svcworker.cpp | 227 -- src/coreclr/zap/zapcode.cpp | 1786 ---------- src/coreclr/zap/zapcode.h | 956 ------ src/coreclr/zap/zapheaders.cpp | 720 ---- src/coreclr/zap/zapheaders.h | 402 --- src/coreclr/zap/zapimage.cpp | 3764 --------------------- src/coreclr/zap/zapimage.h | 1103 ------ src/coreclr/zap/zapimport.cpp | 2284 ------------- src/coreclr/zap/zapimport.h | 553 --- src/coreclr/zap/zapinfo.cpp | 4326 ------------------------ src/coreclr/zap/zapinfo.h | 288 -- src/coreclr/zap/zapinnerptr.cpp | 66 - src/coreclr/zap/zapinnerptr.h | 143 - src/coreclr/zap/zaplog.h | 43 - src/coreclr/zap/zapmetadata.cpp | 362 -- src/coreclr/zap/zapmetadata.h | 221 -- src/coreclr/zap/zapnodetype.h | 117 - src/coreclr/zap/zapper.cpp | 1699 ---------- src/coreclr/zap/zapperstats.cpp | 246 -- src/coreclr/zap/zapperstats.h | 91 - src/coreclr/zap/zapreadytorun.cpp | 874 ----- src/coreclr/zap/zapreadytorun.h | 65 - src/coreclr/zap/zaprelocs.cpp | 427 --- src/coreclr/zap/zaprelocs.h | 128 - src/coreclr/zap/zapwrapper.cpp | 200 -- src/coreclr/zap/zapwrapper.h | 141 - src/coreclr/zap/zapwriter.cpp | 697 ---- src/coreclr/zap/zapwriter.h | 752 ---- 32 files changed, 23726 deletions(-) delete mode 100644 src/coreclr/zap/CMakeLists.txt delete mode 100644 src/coreclr/zap/common.h delete mode 100644 src/coreclr/zap/nativeformatwriter.cpp delete mode 100644 src/coreclr/zap/nativeformatwriter.h delete mode 100644 src/coreclr/zap/svcworker.cpp delete mode 100644 src/coreclr/zap/zapcode.cpp delete mode 100644 src/coreclr/zap/zapcode.h delete mode 100644 src/coreclr/zap/zapheaders.cpp delete mode 100644 src/coreclr/zap/zapheaders.h delete mode 100644 src/coreclr/zap/zapimage.cpp delete mode 100644 src/coreclr/zap/zapimage.h delete mode 100644 src/coreclr/zap/zapimport.cpp delete mode 100644 src/coreclr/zap/zapimport.h delete mode 100644 src/coreclr/zap/zapinfo.cpp delete mode 100644 src/coreclr/zap/zapinfo.h delete mode 100644 src/coreclr/zap/zapinnerptr.cpp delete mode 100644 src/coreclr/zap/zapinnerptr.h delete mode 100644 src/coreclr/zap/zaplog.h delete mode 100644 src/coreclr/zap/zapmetadata.cpp delete mode 100644 src/coreclr/zap/zapmetadata.h delete mode 100644 src/coreclr/zap/zapnodetype.h delete mode 100644 src/coreclr/zap/zapper.cpp delete mode 100644 src/coreclr/zap/zapperstats.cpp delete mode 100644 src/coreclr/zap/zapperstats.h delete mode 100644 src/coreclr/zap/zapreadytorun.cpp delete mode 100644 src/coreclr/zap/zapreadytorun.h delete mode 100644 src/coreclr/zap/zaprelocs.cpp delete mode 100644 src/coreclr/zap/zaprelocs.h delete mode 100644 src/coreclr/zap/zapwrapper.cpp delete mode 100644 src/coreclr/zap/zapwrapper.h delete mode 100644 src/coreclr/zap/zapwriter.cpp delete mode 100644 src/coreclr/zap/zapwriter.h diff --git a/src/coreclr/zap/CMakeLists.txt b/src/coreclr/zap/CMakeLists.txt deleted file mode 100644 index 972568e7becb3e..00000000000000 --- a/src/coreclr/zap/CMakeLists.txt +++ /dev/null @@ -1,52 +0,0 @@ -set(ZAP_SOURCES - svcworker.cpp - zapper.cpp - zaprelocs.cpp - zapcode.cpp - zapheaders.cpp - zapimage.cpp - zapinfo.cpp - zapimport.cpp - zapinnerptr.cpp - zapmetadata.cpp - zapwriter.cpp - zapwrapper.cpp - zapperstats.cpp - nativeformatwriter.cpp -) - -set(ZAP_HEADERS - zaprelocs.h - zapcode.h - zapheaders.h - zapimage.h - zapinfo.h - zapimport.h - zapinnerptr.h - zaplog.h - zapmetadata.h - zapnodetype.h - zapwriter.h - zapwrapper.h - zapperstats.h - nativeformatwriter.h -) - -if (FEATURE_READYTORUN) - list(APPEND ZAP_SOURCES - zapreadytorun.cpp - nativeformatwriter.cpp - ) - list(APPEND ZAP_HEADERS - zapreadytorun.h - nativeformatwriter.h - ) -endif (FEATURE_READYTORUN) - -if (CLR_CMAKE_TARGET_WIN32) - list(APPEND ZAP_SOURCES ${ZAP_HEADERS}) -endif(CLR_CMAKE_TARGET_WIN32) - -add_library_clr(corzap_crossgen STATIC ${ZAP_SOURCES}) -set_target_properties(corzap_crossgen PROPERTIES CROSSGEN_COMPONENT TRUE) -target_precompile_headers(corzap_crossgen PRIVATE [["common.h"]]) diff --git a/src/coreclr/zap/common.h b/src/coreclr/zap/common.h deleted file mode 100644 index beb744e3f9156d..00000000000000 --- a/src/coreclr/zap/common.h +++ /dev/null @@ -1,64 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -//***************************************************************************** -// common.h -// - -// -// Precompiled headers. -// -//***************************************************************************** -#ifndef __COMMON_H__ -#define __COMMON_H__ - -#include -#include -#include -#include -#include -#include -#include -#include - -#if !defined(TARGET_X86) || defined(TARGET_UNIX) -#ifndef FEATURE_EH_FUNCLETS -#define FEATURE_EH_FUNCLETS -#endif -#endif // !TARGET_X86 || TARGET_UNIX - -#ifdef TARGET_64BIT -typedef unsigned __int64 TARGET_POINTER_TYPE; -#else -typedef unsigned int TARGET_POINTER_TYPE; -#endif - -#include "utilcode.h" -#include "corjit.h" -#include "corcompile.h" -#include "iceefilegen.h" -#include "corpriv.h" -#include "gcinfotypes.h" - -#include "holder.h" -#include "ex.h" -#include "corbbtprof.h" -#include "clrnt.h" -#include "contract.h" -#include "psapi.h" -#include "log.h" -#include "ngen.h" -#include "pedecoder.h" -#include "guidfromname.h" -#include "../dlls/mscorrc/resource.h" -#include "zaplog.h" -#include "clrversion.h" - -#include "loaderheap.h" - -#include "zapper.h" -#include "zapwriter.h" -#include "zapimage.h" - -#include "zapperstats.h" - -#endif // __COMMON_H__ diff --git a/src/coreclr/zap/nativeformatwriter.cpp b/src/coreclr/zap/nativeformatwriter.cpp deleted file mode 100644 index 91de6573857130..00000000000000 --- a/src/coreclr/zap/nativeformatwriter.cpp +++ /dev/null @@ -1,575 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// --------------------------------------------------------------------------- -// NativeFormatWriter -// -// Utilities to write native data to images, that can be read by the NativeFormat.Reader class -// --------------------------------------------------------------------------- - -#include "common.h" - -#include "nativeformatwriter.h" - -#include - -namespace NativeFormat -{ - // - // Same encoding as what's used by CTL - // - void NativeWriter::WriteUnsigned(unsigned d) - { - if (d < 128) - { - WriteByte((byte)(d*2 + 0)); - } - else if (d < 128*128) - { - WriteByte((byte)(d*4 + 1)); - WriteByte((byte)(d >> 6)); - } - else if (d < 128*128*128) - { - WriteByte((byte)(d*8 + 3)); - WriteByte((byte)(d >> 5)); - WriteByte((byte)(d >> 13)); - } - else if (d < 128*128*128*128) - { - WriteByte((byte)(d*16 + 7)); - WriteByte((byte)(d >> 4)); - WriteByte((byte)(d >> 12)); - WriteByte((byte)(d >> 20)); - } - else - { - WriteByte((byte)15); - WriteUInt32(d); - } - } - - unsigned NativeWriter::GetUnsignedEncodingSize(unsigned d) - { - if (d < 128) return 1; - if (d < 128*128) return 2; - if (d < 128*128*128) return 3; - if (d < 128*128*128*128) return 4; - return 5; - } - - void NativeWriter::WriteSigned(int i) - { - unsigned d = (unsigned)i; - if (d + 64 < 128) - { - WriteByte((byte)(d*2 + 0)); - } - else if (d + 64*128 < 128*128) - { - WriteByte((byte)(d*4 + 1)); - WriteByte((byte)(d >> 6)); - } - else if (d + 64*128*128 < 128*128*128) - { - WriteByte((byte)(d*8 + 3)); - WriteByte((byte)(d >> 5)); - WriteByte((byte)(d >> 13)); - } - else if (d + 64*128*128*128 < 128*128*128*128) - { - WriteByte((byte)(d*16 + 7)); - WriteByte((byte)(d >> 4)); - WriteByte((byte)(d >> 12)); - WriteByte((byte)(d >> 20)); - } - else - { - WriteByte((byte)15); - WriteUInt32(d); - } - } - - void NativeWriter::WriteRelativeOffset(Vertex * pVal) - { - WriteSigned(GetExpectedOffset(pVal) - GetCurrentOffset()); - } - - int NativeWriter::GetExpectedOffset(Vertex * pVal) - { - assert(pVal->m_offset != Vertex::NotPlaced); - - if (pVal->m_iteration == -1) - { - // If the offsets are not determined yet, use the maximum possible encoding - return 0x7FFFFFFF; - } - - int offset = pVal->m_offset; - - // If the offset was not update in this iteration yet, adjust it by delta we have accumulated in this iteration so far. - // This adjustment allows the offsets to converge faster. - if (pVal->m_iteration < m_iteration) - offset += m_offsetAdjustment; - - return offset; - } - - vector& NativeWriter::Save() - { - assert(m_phase == Initial); - - for (auto pSection : m_Sections) for (auto pVertex : *pSection) - { - pVertex->m_offset = GetCurrentOffset(); - pVertex->m_iteration = m_iteration; - pVertex->Save(this); - } - - // Aggresive phase that only allows offsets to shrink. - m_phase = Shrinking; - for (;;) - { - m_iteration++; - m_Buffer.clear(); - - m_offsetAdjustment = 0; - - for (auto pSection : m_Sections) for (auto pVertex : *pSection) - { - int currentOffset = GetCurrentOffset(); - - // Only allow the offsets to shrink. - m_offsetAdjustment = min(m_offsetAdjustment, currentOffset - pVertex->m_offset); - - pVertex->m_offset += m_offsetAdjustment; - - if (pVertex->m_offset < currentOffset) - { - // It is possible for the encoding of relative offsets to grow during some iterations. - // Ignore this growth because of it should disappear during next iteration. - RollbackTo(pVertex->m_offset); - } - assert(pVertex->m_offset == GetCurrentOffset()); - - pVertex->m_iteration = m_iteration; - - pVertex->Save(this); - } - - // We are not able to shrink anymore. We cannot just return here. It is possible that we have rolledback - // above because of we shrinked too much. - if (m_offsetAdjustment == 0) - break; - - // Limit number of shrinking interations. This limit is meant to be hit in corner cases only. - if (m_iteration > 10) - break; - } - - // Conservative phase that only allows the offsets to grow. It is guaranteed to converge. - m_phase = Growing; - for (;;) - { - m_iteration++; - m_Buffer.clear(); - - m_offsetAdjustment = 0; - m_paddingSize = 0; - - for (auto pSection : m_Sections) for (auto pVertex : *pSection) - { - int currentOffset = GetCurrentOffset(); - - // Only allow the offsets to grow. - m_offsetAdjustment = max(m_offsetAdjustment, currentOffset - pVertex->m_offset); - - pVertex->m_offset += m_offsetAdjustment; - - if (pVertex->m_offset > currentOffset) - { - // Padding - int padding = pVertex->m_offset - currentOffset; - m_paddingSize += padding; - WritePad(padding); - } - assert(pVertex->m_offset == GetCurrentOffset()); - - pVertex->m_iteration = m_iteration; - - pVertex->Save(this); - } - - if (m_offsetAdjustment == 0) - return m_Buffer; - } - - m_phase = Done; - } - - Vertex * NativeSection::Place(Vertex * pVertex) - { - assert(pVertex->m_offset == Vertex::NotPlaced); - pVertex->m_offset = Vertex::Placed; - push_back(pVertex); - - return pVertex; - } - - Vertex * VertexArray::ExpandBlock(size_t index, int depth, bool place, bool * pIsLeaf) - { - if (depth == 1) - { - Vertex * pFirst = (index < m_Entries.size()) ? m_Entries[index] : nullptr; - Vertex * pSecond = ((index + 1) < m_Entries.size()) ? m_Entries[index + 1] : nullptr; - - if (pFirst == nullptr && pSecond == nullptr) - return nullptr; - - if (pFirst == nullptr || pSecond == nullptr) - { - VertexLeaf * pLeaf = new VertexLeaf(); - if (place) - m_pSection->Place(pLeaf); - - pLeaf->m_pVertex = (pFirst == nullptr) ? pSecond : pFirst; - pLeaf->m_leafIndex = ((pFirst == nullptr) ? (index + 1) : index) & (_blockSize - 1); - - *pIsLeaf = true; - return pLeaf; - } - - VertexTree * pTree = new VertexTree(); - if (place) - m_pSection->Place(pTree); - - pTree->m_pFirst = pFirst; - pTree->m_pSecond = pSecond; - - m_pSection->Place(pSecond); - - return pTree; - } - else - { - VertexTree * pTree = new VertexTree(); - if (place) - m_pSection->Place(pTree); - - bool fFirstIsLeaf = false, fSecondIsLeaf = false; - Vertex * pFirst = ExpandBlock(index, depth - 1, false, &fFirstIsLeaf); - Vertex * pSecond = ExpandBlock(index + (size_t{ 1 } << (depth - 1)), depth - 1, true, &fSecondIsLeaf); - - Vertex * pPop; - - if ((pFirst == nullptr && pSecond == nullptr)) - { - if (place) - { - pPop = m_pSection->Pop(); - assert(pPop == pTree); - } - - delete pTree; - return nullptr; - } - - if ((pFirst == nullptr) && fSecondIsLeaf) - { - pPop = m_pSection->Pop(); - assert(pPop == pSecond); - - if (place) - { - pPop = m_pSection->Pop(); - assert(pPop == pTree); - } - - delete pTree; - - if (place) - m_pSection->Place(pSecond); - - *pIsLeaf = true; - return pSecond; - } - - if ((pSecond == nullptr) && fFirstIsLeaf) - { - if (place) - { - pPop = m_pSection->Pop(); - assert(pPop == pTree); - } - - delete pTree; - - if (place) - m_pSection->Place(pFirst); - - *pIsLeaf = true; - return pFirst; - } - - pTree->m_pFirst = pFirst; - pTree->m_pSecond = pSecond; - - return pTree; - } - } - - void VertexArray::ExpandLayout() - { - VertexLeaf * pNullBlock = nullptr; - for (size_t i = 0; i < m_Entries.size(); i += _blockSize) - { - bool fIsLeaf; - Vertex * pBlock = ExpandBlock(i, 4, true, &fIsLeaf); - - if (pBlock == nullptr) - { - if (pNullBlock == nullptr) - { - pNullBlock = new VertexLeaf(); - pNullBlock->m_leafIndex = _blockSize; - pNullBlock->m_pVertex = nullptr; - m_pSection->Place(pNullBlock); - } - pBlock = pNullBlock; - } - - m_Blocks.push_back(pBlock); - } - - // Start with maximum size entries - m_entryIndexSize = 2; - } - - void VertexArray::VertexLeaf::Save(NativeWriter * pWriter) - { - pWriter->WriteUnsigned(m_leafIndex << 2); - - if (m_pVertex != nullptr) - m_pVertex->Save(pWriter); - } - - void VertexArray::VertexTree::Save(NativeWriter * pWriter) - { - unsigned value = (m_pFirst != nullptr) ? 1 : 0; - - if (m_pSecond != nullptr) - { - value |= 2; - - int delta = pWriter->GetExpectedOffset(m_pSecond) - pWriter->GetCurrentOffset(); - assert(delta >= 0); - value |= (delta << 2); - } - - pWriter->WriteUnsigned(value); - - if (m_pFirst != nullptr) - m_pFirst->Save(pWriter); - } - - void VertexArray::Save(NativeWriter * pWriter) - { - // Lowest two bits are entry index size, the rest is number of elements - pWriter->WriteUnsigned((m_Entries.size() << 2) | m_entryIndexSize); - - int blocksOffset = pWriter->GetCurrentOffset(); - int maxOffset = 0; - - for (auto pBlock : m_Blocks) - { - int offset = pWriter->GetExpectedOffset(pBlock) - blocksOffset; - assert(offset >= 0); - - maxOffset = max(offset, maxOffset); - - if (m_entryIndexSize == 0) - { - pWriter->WriteByte((byte)offset); - } - else - if (m_entryIndexSize == 1) - { - pWriter->WriteUInt16((UInt16)offset); - } - else - { - pWriter->WriteUInt32((UInt32)offset); - } - } - - int newEntryIndexSize = 0; - if (maxOffset > 0xFF) - { - newEntryIndexSize++; - if (maxOffset > 0xFFFF) - newEntryIndexSize++; - } - - if (pWriter->IsGrowing()) - { - if (newEntryIndexSize > m_entryIndexSize) - { - // Ensure that the table will be redone with new entry index size - pWriter->UpdateOffsetAdjustment(1); - - m_entryIndexSize = newEntryIndexSize; - } - } - else - { - if (newEntryIndexSize < m_entryIndexSize) - { - // Ensure that the table will be redone with new entry index size - pWriter->UpdateOffsetAdjustment(-1); - - m_entryIndexSize = newEntryIndexSize; - } - } - } - - // - // VertexHashtable - // - - // Returns 1 + log2(x) rounded up, 0 iff x == 0 - static unsigned HighestBit(unsigned x) - { - unsigned ret = 0; - while (x != 0) - { - x >>= 1; - ret++; - } - return ret; - } - - // Helper method to back patch entry index in the bucket table - static void PatchEntryIndex(NativeWriter * pWriter, int patchOffset, int entryIndexSize, int entryIndex) - { - if (entryIndexSize == 0) - { - pWriter->PatchByteAt(patchOffset, (byte)entryIndex); - } - else - if (entryIndexSize == 1) - { - pWriter->PatchByteAt(patchOffset, (byte)entryIndex); - pWriter->PatchByteAt(patchOffset + 1, (byte)(entryIndex >> 8)); - } - else - { - pWriter->PatchByteAt(patchOffset, (byte)entryIndex); - pWriter->PatchByteAt(patchOffset + 1, (byte)(entryIndex >> 8)); - pWriter->PatchByteAt(patchOffset + 2, (byte)(entryIndex >> 16)); - pWriter->PatchByteAt(patchOffset + 3, (byte)(entryIndex >> 24)); - } - } - - void VertexHashtable::Save(NativeWriter * pWriter) - { - // Compute the layout of the table if we have not done it yet - if (m_nBuckets == 0) - ComputeLayout(); - - int nEntries = (int)m_Entries.size(); - int startOffset = pWriter->GetCurrentOffset(); - int bucketMask = (m_nBuckets - 1); - - // Lowest two bits are entry index size, the rest is log2 number of buckets - int numberOfBucketsShift = HighestBit(m_nBuckets) - 1; - pWriter->WriteByte(static_cast((numberOfBucketsShift << 2) | m_entryIndexSize)); - - int bucketsOffset = pWriter->GetCurrentOffset(); - - pWriter->WritePad((m_nBuckets + 1) << m_entryIndexSize); - - // For faster lookup at runtime, we store the first entry index even though it is redundant (the value can be - // inferred from number of buckets) - PatchEntryIndex(pWriter, bucketsOffset, m_entryIndexSize, pWriter->GetCurrentOffset() - bucketsOffset); - - int iEntry = 0; - - for (int iBucket = 0; iBucket < m_nBuckets; iBucket++) - { - while (iEntry < nEntries) - { - Entry &e = m_Entries[iEntry]; - - if (((e.hashcode >> 8) & bucketMask) != (unsigned)iBucket) - break; - - int currentOffset = pWriter->GetCurrentOffset(); - pWriter->UpdateOffsetAdjustment(currentOffset - e.offset); - e.offset = currentOffset; - - pWriter->WriteByte((byte)e.hashcode); - pWriter->WriteRelativeOffset(e.pVertex); - - iEntry++; - } - - int patchOffset = bucketsOffset + ((iBucket + 1) << m_entryIndexSize); - - PatchEntryIndex(pWriter, patchOffset, m_entryIndexSize, pWriter->GetCurrentOffset() - bucketsOffset); - } - assert(iEntry == nEntries); - - int maxIndexEntry = (pWriter->GetCurrentOffset() - bucketsOffset); - int newEntryIndexSize = 0; - if (maxIndexEntry > 0xFF) - { - newEntryIndexSize++; - if (maxIndexEntry > 0xFFFF) - newEntryIndexSize++; - } - - if (pWriter->IsGrowing()) - { - if (newEntryIndexSize > m_entryIndexSize) - { - // Ensure that the table will be redone with new entry index size - pWriter->UpdateOffsetAdjustment(1); - - m_entryIndexSize = newEntryIndexSize; - } - } - else - { - if (newEntryIndexSize < m_entryIndexSize) - { - // Ensure that the table will be redone with new entry index size - pWriter->UpdateOffsetAdjustment(-1); - - m_entryIndexSize = newEntryIndexSize; - } - } - } - - void VertexHashtable::ComputeLayout() - { - unsigned bucketsEstimate = (unsigned)(m_Entries.size() / m_nFillFactor); - - // Round number of buckets up to the power of two - m_nBuckets = 1 << HighestBit(bucketsEstimate); - - // Lowest byte of the hashcode is used for lookup within the bucket. Keep it sorted too so that - // we can use the ordering to terminate the lookup prematurely. - unsigned mask = ((m_nBuckets - 1) << 8) | 0xFF; - - // sort it by hashcode - std::sort(m_Entries.begin(), m_Entries.end(), - [=](Entry const& a, Entry const& b) - { - return (a.hashcode & mask) < (b.hashcode & mask); - } - ); - - // Start with maximum size entries - m_entryIndexSize = 2; - } -} diff --git a/src/coreclr/zap/nativeformatwriter.h b/src/coreclr/zap/nativeformatwriter.h deleted file mode 100644 index 3d8752f0be053b..00000000000000 --- a/src/coreclr/zap/nativeformatwriter.h +++ /dev/null @@ -1,354 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// --------------------------------------------------------------------------- -// NativeFormatWriter -// -// Utilities to write native data to images, that can be read by the NativeFormat.Reader class -// --------------------------------------------------------------------------- - -#pragma once - -#include -#include - -// To reduce differences between C# and C++ versions -#define byte uint8_t - -#define UInt16 uint16_t -#define UInt32 uint32_t -#define UInt64 uint64_t - -#include - -namespace NativeFormat -{ - using namespace std; - - class NativeSection; - class NativeWriter; - - class Vertex - { - friend class NativeWriter; - friend class NativeSection; - - int m_offset; - int m_iteration; // Iteration that the offset is valid for - - static const int NotPlaced = -1; - static const int Placed = -2; - - public: - Vertex() - : m_offset(Vertex::NotPlaced), m_iteration(-1) - { - } - - virtual ~Vertex() {} - - virtual void Save(NativeWriter * pWriter) = 0; - - int GetOffset() - { - assert(m_offset >= 0); - return m_offset; - } - }; - - class NativeSection : vector - { - friend class NativeWriter; - - public: - Vertex * Place(Vertex * pVertex); - - Vertex * Pop() - { - Vertex * pVertex = *(end() - 1); - erase(end() - 1); - - assert(pVertex->m_offset == Vertex::Placed); - pVertex->m_offset = Vertex::NotPlaced; - - return pVertex; - } - }; - - class NativeWriter - { - vector m_Sections; - - enum SavePhase - { - Initial, - Shrinking, - Growing, - Done - }; - - vector m_Buffer; - int m_iteration; - SavePhase m_phase; // Current save phase - int m_offsetAdjustment; // Cumulative offset adjustment compared to previous iteration - int m_paddingSize; // How much padding was used - - public: - NativeWriter() - { - m_iteration = 0; - m_phase = Initial; - } - - NativeSection * NewSection() - { - NativeSection * pSection = new NativeSection(); - m_Sections.push_back(pSection); - return pSection; - } - - void WriteByte(byte b) - { - m_Buffer.push_back(b); - } - - void WriteUInt16(UInt16 value) - { - WriteByte((byte)value); - WriteByte((byte)(value>>8)); - } - - void WriteUInt32(UInt32 value) - { - WriteByte((byte)value); - WriteByte((byte)(value>>8)); - WriteByte((byte)(value>>16)); - WriteByte((byte)(value>>24)); - } - - void WritePad(unsigned size) - { - while (size > 0) - { - WriteByte(0); - size--; - } - } - - bool IsGrowing() - { - return m_phase == Growing; - } - - void UpdateOffsetAdjustment(int offsetDelta) - { - switch (m_phase) - { - case Shrinking: - m_offsetAdjustment = min(m_offsetAdjustment, offsetDelta); - break; - case Growing: - m_offsetAdjustment = max(m_offsetAdjustment, offsetDelta); - break; - default: - break; - } - } - - void RollbackTo(int offset) - { - m_Buffer.erase(m_Buffer.begin() + offset, m_Buffer.end()); - } - - void RollbackTo(int offset, int offsetAdjustment) - { - m_offsetAdjustment = offsetAdjustment; - RollbackTo(offset); - } - - void PatchByteAt(int offset, byte value) - { - m_Buffer[offset] = value; - } - - // - // Same encoding as what's used by CTL - // - void WriteUnsigned(unsigned d); - static unsigned GetUnsignedEncodingSize(unsigned d); - - template - void WriteUnsigned(T d) - { - WriteUnsigned((unsigned)d); - } - - void WriteSigned(int i); - - void WriteRelativeOffset(Vertex * pVal); - - int GetExpectedOffset(Vertex * pVal); - - int GetCurrentOffset(Vertex * pVal) - { - if (pVal->m_iteration != m_iteration) - return -1; - return pVal->m_offset; - } - - void SetCurrentOffset(Vertex * pVal) - { - pVal->m_iteration = m_iteration; - pVal->m_offset = GetCurrentOffset(); - } - - int GetCurrentOffset() - { - return (int)m_Buffer.size(); - } - - int GetNumberOfIterations() - { - return m_iteration; - } - - int GetPaddingSize() - { - return m_paddingSize; - } - - vector& Save(); - }; - - - // - // Data structure building blocks - // - - class UnsignedConstant : public Vertex - { - unsigned m_value; - - public: - UnsignedConstant(unsigned value) - : m_value(value) - { - } - - virtual void Save(NativeWriter * pWriter) - { - pWriter->WriteUnsigned(m_value); - } - }; - - // - // Sparse array. Good for random access based on index - // - class VertexArray : public Vertex - { - vector m_Entries; - - NativeSection * m_pSection; - vector m_Blocks; - - static const int _blockSize = 16; - - // Current size of index entry - int m_entryIndexSize; // 0 - uint8, 1 - uint16, 2 - uint32 - - class VertexLeaf : public Vertex - { - public: - Vertex * m_pVertex; - size_t m_leafIndex; - - virtual void Save(NativeWriter * pWriter); - }; - - class VertexTree : public Vertex - { - public: - Vertex * m_pFirst; - Vertex * m_pSecond; - - virtual void Save(NativeWriter * pWriter); - }; - - Vertex * ExpandBlock(size_t index, int depth, bool place, bool * pLeaf); - - public: - VertexArray(NativeSection * pSection) - : m_pSection(pSection) - { - } - - void Set(int index, Vertex * pElement) - { - while ((size_t)index >= m_Entries.size()) - m_Entries.push_back(nullptr); - - m_Entries[index] = pElement; - } - - void ExpandLayout(); - - virtual void Save(NativeWriter * pWriter); - }; - - // - // Hashtable. Good for random access based on hashcode + key - // - class VertexHashtable : public Vertex - { - struct Entry - { - Entry() - : offset(-1), hashcode(0), pVertex(NULL) - { - } - - Entry(unsigned hashcode, Vertex * pVertex) - : offset(0), hashcode(hashcode), pVertex(pVertex) - { - } - - int offset; - - unsigned hashcode; - Vertex * pVertex; - }; - - vector m_Entries; - - // How many entries to target per bucket. Higher fill factor means smaller size, but worse runtime perf. - int m_nFillFactor; - - // Number of buckets choosen for the table. Must be power of two. 0 means that the table is still open for mutation. - int m_nBuckets; - - // Current size of index entry - int m_entryIndexSize; // 0 - uint8, 1 - uint16, 2 - uint32 - - void ComputeLayout(); - - public: - static const int DefaultFillFactor = 13; - - VertexHashtable(int fillFactor = DefaultFillFactor) - { - m_nBuckets = 0; - - m_nFillFactor = fillFactor; - } - - void Append(unsigned hashcode, Vertex * pElement) - { - // The table needs to be open for mutation - assert(m_nBuckets == 0); - - m_Entries.push_back(Entry(hashcode, pElement)); - } - - virtual void Save(NativeWriter * pWriter); - }; -}; diff --git a/src/coreclr/zap/svcworker.cpp b/src/coreclr/zap/svcworker.cpp deleted file mode 100644 index 78f7b4f9eefda6..00000000000000 --- a/src/coreclr/zap/svcworker.cpp +++ /dev/null @@ -1,227 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - - -/********************************************************************** -svcworker.cpp -- logic for the runtime implementation of the native -image service. - -Overview: the runtime implementation is accessed via a local COM -server implemented in ngen.exe. That server is simply a stub that -loads the most recent runtime and calls into the actual implementation -in this file. There are three entrypoints in mscorwks.dll that -are called by the local service in ngen.exe: - -NGenWorkerRegisterServer -- called to register ngen.exe as the current - COM server for CLSID_CorSvcWorker -NGenWorkerUnregisterServer -- unregister ngen.exe as the current COM - server for CLSID_CorSvcWorker -NGenWorkerEmbedding() -- called when COM invoked the COM server with - the "-Embedding" flag. Implements the logic for registering the class - factory for CLSID_CorSvcWorker and controlling the lifetime of the - COM server. -**********************************************************************/ - -#include "common.h" - -ILocalServerLifetime *g_pLocalServerLifetime = NULL; - -SvcLogger::SvcLogger() - : pss(NULL), - pCorSvcLogger(NULL) -{ -} - -inline void SvcLogger::CheckInit() -{ - if(pss == NULL) - { - StackSString* psstemp = new StackSString(); - StackSString* pssOrig = InterlockedCompareExchangeT(&pss, psstemp, NULL); - if(pssOrig) - delete psstemp; - } -} - -SvcLogger::~SvcLogger() -{ - if (pCorSvcLogger) - { -// pCorSvcLogger->Release(); - pCorSvcLogger = NULL; - } - if (pss) - delete pss; -} - -void SvcLogger::ReleaseLogger() -{ - if (pCorSvcLogger) - { - pCorSvcLogger->Release(); - pCorSvcLogger = NULL; - } -} - -void SvcLogger::Printf(const CHAR *format, ...) -{ - StackSString s; - - va_list args; - va_start(args, format); - s.VPrintf(format, args); - va_end(args); - - if (pCorSvcLogger) - { - LogHelper(s); - } - else - { - wprintf( W("%s"), s.GetUnicode() ); - } -} - -void SvcLogger::SvcPrintf(const CHAR *format, ...) -{ - StackSString s; - - va_list args; - va_start(args, format); - s.VPrintf(format, args); - va_end(args); - - LogHelper(s); -} - -void SvcLogger::Printf(const WCHAR *format, ...) -{ - StackSString s; - - va_list args; - va_start(args, format); - s.VPrintf(format, args); - va_end(args); - - if (pCorSvcLogger) - { - LogHelper(s); - } - else - { - wprintf( W("%s"), s.GetUnicode() ); - } -} - -void SvcLogger::Printf(CorSvcLogLevel logLevel, const WCHAR *format, ...) -{ - StackSString s; - - va_list args; - va_start(args, format); - s.VPrintf(format, args); - va_end(args); - - if (pCorSvcLogger) - { - LogHelper(s, logLevel); - } - else - { - wprintf( W("%s"), s.GetUnicode()); - } -} - -void SvcLogger::SvcPrintf(const WCHAR *format, ...) -{ - StackSString s; - - va_list args; - va_start(args, format); - s.VPrintf(format, args); - va_end(args); - - LogHelper(s); -} - -void SvcLogger::Log(const WCHAR *message, CorSvcLogLevel logLevel) -{ - LogHelper(StackSString(message), logLevel); -} - -void SvcLogger::LogHelper(SString s, CorSvcLogLevel logLevel) -{ - CheckInit(); - pss->Append(s); - - // Does s contain a newline? - SString::Iterator i = pss->Begin(); - if (pss->FindASCII(i, "\n")) - { - if (pCorSvcLogger) - { - BSTRHolder bstrHolder(::SysAllocString(pss->GetUnicode())); - // Can't use the IfFailThrow macro here because in checked - // builds that macros will try to log an error message - // that will recursively return to this method. - HRESULT hr = pCorSvcLogger->Log(logLevel, bstrHolder); - if (FAILED(hr)) - ThrowHR(hr); - } - pss->Clear(); - } -} - -void SvcLogger::SetSvcLogger(ICorSvcLogger *pCorSvcLoggerArg) -{ - ReleaseLogger(); - this->pCorSvcLogger = pCorSvcLoggerArg; - if (pCorSvcLoggerArg) - { - pCorSvcLogger->AddRef(); - } -} - -BOOL SvcLogger::HasSvcLogger() -{ - return (this->pCorSvcLogger != NULL); -} - -ICorSvcLogger* SvcLogger::GetSvcLogger() -{ - return pCorSvcLogger; -} - - -namespace -{ - SvcLogger *g_SvcLogger = NULL; -} - -// As NGen is currently single-threaded, this function is intentionally not thread safe. -// If necessary, change it into an interlocked function. -SvcLogger *GetSvcLogger() -{ - if (g_SvcLogger == NULL) - { - g_SvcLogger = new SvcLogger(); - } - return g_SvcLogger; -} - -BOOL HasSvcLogger() -{ - if (g_SvcLogger != NULL) - { - return g_SvcLogger->HasSvcLogger(); - } - return FALSE; -} - -#ifdef CROSSGEN_COMPILE -void SetSvcLogger(ICorSvcLogger *pCorSvcLogger) -{ - GetSvcLogger()->SetSvcLogger(pCorSvcLogger); -} -#endif - diff --git a/src/coreclr/zap/zapcode.cpp b/src/coreclr/zap/zapcode.cpp deleted file mode 100644 index 039ed6763555f5..00000000000000 --- a/src/coreclr/zap/zapcode.cpp +++ /dev/null @@ -1,1786 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapCode.cpp -// - -// -// Everything directly related to zapping of native code -// - The code itself -// - Code headers -// - All XXX infos: GC Info, EH Info, Unwind Info, ... -// -// ====================================================================================== - -#include "common.h" - -#include "zapcode.h" - -#include "zapimport.h" - -#include "zapinnerptr.h" - -#ifdef FEATURE_READYTORUN_COMPILER -#include "zapreadytorun.h" -#endif - -#ifdef REDHAWK -#include "rhcodeinfo.h" -#include "rhbinder.h" -#include "modulegcinfoencoder.h" -#endif // REDHAWK - -// -// The image layout algorithm -// - -ZapVirtualSection * ZapImage::GetCodeSection(CodeType codeType) -{ - switch (codeType) - { - case ProfiledHot: - return m_pHotCodeSection; - case ProfiledCold: - return m_pColdCodeSection; - case Unprofiled: - return m_pCodeSection; - } - - UNREACHABLE(); -} - -#if defined(FEATURE_EH_FUNCLETS) -ZapVirtualSection * ZapImage::GetUnwindDataSection(CodeType codeType) -{ -#ifdef REDHAWK - return m_pUnwindDataSection; -#else - switch (codeType) - { - case ProfiledHot: - return m_pHotUnwindDataSection; - case ProfiledCold: - return m_pColdUnwindDataSection; - case Unprofiled: - return m_pUnwindDataSection; - } - -#endif // REDHAWK - UNREACHABLE(); -} -#endif // defined(FEATURE_EH_FUNCLETS) - -ZapVirtualSection * ZapImage::GetRuntimeFunctionSection(CodeType codeType) -{ - switch (codeType) - { - case ProfiledHot: - return m_pHotRuntimeFunctionSection; - case ProfiledCold: - return m_pColdRuntimeFunctionSection; - case Unprofiled: - return m_pRuntimeFunctionSection; - } - - UNREACHABLE(); -} - -ZapVirtualSection * ZapImage::GetCodeMethodDescSection(CodeType codeType) -{ - switch (codeType) - { - case ProfiledHot: - return m_pHotCodeMethodDescsSection; - case Unprofiled: - return m_pCodeMethodDescsSection; - default: - UNREACHABLE(); - } -} - -ZapVirtualSection* ZapImage::GetUnwindInfoLookupSection(CodeType codeType) -{ - switch(codeType) - { - case ProfiledHot: - return m_pHotRuntimeFunctionLookupSection; - case Unprofiled: - return m_pRuntimeFunctionLookupSection; - default: - UNREACHABLE(); - } -} - -void ZapImage::GetCodeCompilationRange(CodeType codeType, COUNT_T * start, COUNT_T * end) -{ - _ASSERTE(start && end); - -#ifdef REDHAWK - *start = 0; - *end = m_MethodCompilationOrder.GetCount(); -#else - switch (codeType) - { - case ProfiledHot: - *start = 0; - *end = m_iUntrainedMethod; - break; - case ProfiledCold: - *start = 0; - *end = m_MethodCompilationOrder.GetCount(); - break; - case Unprofiled: - *start = m_iUntrainedMethod; - *end = m_MethodCompilationOrder.GetCount(); - break; - } -#endif // REDHAWK -} - -void ZapImage::OutputCode(CodeType codeType) -{ - // Note there are three codeTypes: ProfiledHot, Unprofiled and ProfiledCold -#if defined(REDHAWK) - SectionMethodListGenerator map; -#endif - - bool fCold = (codeType == ProfiledCold); - CorInfoRegionKind regionKind = (codeType == ProfiledHot) ? CORINFO_REGION_HOT : CORINFO_REGION_COLD; - BeginRegion(regionKind); - - ZapVirtualSection * pCodeSection = GetCodeSection(codeType); - ZapVirtualSection * pRuntimeFunctionSection = GetRuntimeFunctionSection(codeType); - -#if defined (FEATURE_EH_FUNCLETS) - ZapVirtualSection * pUnwindDataSection = GetUnwindDataSection(codeType); -#endif // defined (FEATURE_EH_FUNCLETS) - - DWORD codeSize = 0; - - // We should start with empty code section - _ASSERTE(pRuntimeFunctionSection->GetNodeCount() == 0); - _ASSERTE(pCodeSection->GetNodeCount() == 0); - - COUNT_T startMethod, endMethod; -#ifdef REDHAWK // TritonTBD - DWORD currentOffset = 0; -#endif // REDHAWK - - GetCodeCompilationRange(codeType, &startMethod, &endMethod); - - DWORD dwStartMethodIndex = (codeType == Unprofiled) ? m_pHotRuntimeFunctionSection->GetNodeCount() : 0; - - for (COUNT_T curMethod = startMethod; curMethod < endMethod; curMethod++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[curMethod]; - - ZapBlobWithRelocs * pCode = fCold ? pMethod->m_pColdCode : pMethod->m_pCode; - if (pCode == NULL) - { - continue; - } - - if (!fCold) - { - pMethod->m_methodIndex = dwStartMethodIndex + pRuntimeFunctionSection->GetNodeCount(); - } - else - { - pMethod->m_methodIndex = (DWORD)-1; - } - - //Count the method size for use by ZapUnwindInfoLookupTable - codeSize = AlignUp(codeSize, pCode->GetAlignment()); - codeSize += pCode->GetSize(); - - pCodeSection->Place(pCode); - -#ifdef REDHAWK - DWORD codeOffset = AlignUp(currentOffset, pCode->GetAlignment()); - codeOffset = map.AlignToMethodStartGranularity(codeOffset); - map.NoticeMethod(codeOffset, pCode->GetSize()); - currentOffset = codeOffset + pCode->GetSize(); -#endif - - ZapReloc * pRelocs = pCode->GetRelocs(); - if (pRelocs != NULL) - { - for (ZapReloc * pReloc = pRelocs; pReloc->m_type != IMAGE_REL_INVALID; pReloc++) - { - ZapNode * pTarget = pReloc->m_pTargetNode; - - ZapNodeType type = pTarget->GetType(); - if (type == ZapNodeType_InnerPtr) - { - pTarget = ((ZapInnerPtr *)pTarget)->GetBase(); - type = pTarget->GetType(); - } - - switch (type) - { - case ZapNodeType_StubDispatchCell: - // Optimizations may create redundant references to the StubDispatchCell - if (!pTarget->IsPlaced()) - { - m_pStubDispatchDataTable->PlaceStubDispatchCell((ZapImport *)pTarget); - } - break; - case ZapNodeType_MethodEntryPoint: - pTarget = m_pMethodEntryPoints->CanDirectCall((ZapMethodEntryPoint *)pTarget, pMethod); - if (pTarget != NULL) - { - pReloc->m_pTargetNode = pTarget; - } - break; - case ZapNodeType_Stub: - if (!pTarget->IsPlaced()) - { - m_pStubsSection->Place(pTarget); - } - break; - case ZapNodeType_HelperThunk: - if (!pTarget->IsPlaced()) - { - // This should place the most frequently used JIT helpers first and together - m_pHelperTableSection->Place(pTarget); - } - break; - case ZapNodeType_LazyHelperThunk: - if (!pTarget->IsPlaced()) - { - ((ZapLazyHelperThunk *)pTarget)->Place(this); - } - break; - case ZapNodeType_Import_ModuleHandle: - case ZapNodeType_Import_ClassHandle: - case ZapNodeType_Import_StringHandle: - case ZapNodeType_Import_Helper: - // Place all potentially eager imports - if (!pTarget->IsPlaced()) - m_pImportTable->PlaceImport((ZapImport *)pTarget); - break; - - case ZapNodeType_ExternalMethodThunk: - if (!pTarget->IsPlaced()) - m_pExternalMethodDataTable->PlaceExternalMethodThunk((ZapImport *)pTarget); - break; - - case ZapNodeType_ExternalMethodCell: - if (!pTarget->IsPlaced()) - m_pExternalMethodDataTable->PlaceExternalMethodCell((ZapImport *)pTarget); - break; - -#ifdef FEATURE_READYTORUN_COMPILER - case ZapNodeType_DynamicHelperCell: - if (!pTarget->IsPlaced()) - m_pDynamicHelperDataTable->PlaceDynamicHelperCell((ZapImport *)pTarget); - break; - - case ZapNodeType_IndirectHelperThunk: - if (!pTarget->IsPlaced()) - m_pImportTable->PlaceIndirectHelperThunk(pTarget); - break; -#endif - - case ZapNodeType_GenericSignature: - if (!pTarget->IsPlaced()) - m_pImportTable->PlaceBlob((ZapBlob *)pTarget); - break; - default: - break; - } - } - } - -#if defined (FEATURE_EH_FUNCLETS) - // - // Place unwind data - // - - InlineSArray unwindInfos; - - ZapUnwindInfo * pFragment; - - // Go over all fragments and append their unwind infos in this section - for (pFragment = pMethod->m_pUnwindInfoFragments; - pFragment != NULL; - pFragment = pFragment->GetNextFragment()) - { - ZapNode * pFragmentCode = pFragment->GetCode(); - _ASSERTE(pFragmentCode == pMethod->m_pCode || pFragmentCode == pMethod->m_pColdCode); - - if (pFragmentCode == pCode) - { - unwindInfos.Append(pFragment); - } - } - - // The runtime function section must be ordered correctly relative to code layout - // in the image. Sort the unwind infos by their offset - _ASSERTE(unwindInfos.GetCount() > 0); - qsort(&unwindInfos[0], unwindInfos.GetCount(), sizeof(ZapUnwindInfo *), ZapUnwindInfo::CompareUnwindInfo); - - // Set the initial unwind info for the hot and cold sections - if (fCold) - { - _ASSERTE(pMethod->m_pColdUnwindInfo == NULL); - pMethod->m_pColdUnwindInfo = unwindInfos[0]; - } - else - { - _ASSERTE(pMethod->m_pUnwindInfo == NULL); - pMethod->m_pUnwindInfo = unwindInfos[0]; - } - - for (COUNT_T iUnwindInfo = 0; iUnwindInfo < unwindInfos.GetCount(); iUnwindInfo++) - { - ZapUnwindInfo * pUnwindInfo = unwindInfos[iUnwindInfo]; - pRuntimeFunctionSection->Place(pUnwindInfo); - - ZapNode * pUnwindData = pUnwindInfo->GetUnwindData(); - - if (!pUnwindData->IsPlaced()) - { - pUnwindDataSection->Place(pUnwindData); - } - } - -#else // defined (FEATURE_EH_FUNCLETS) - - ZapUnwindInfo * pUnwindInfo; - if (fCold) - { - // Chained unwind info - pUnwindInfo = new (GetHeap()) ZapUnwindInfo(pCode, 0, 0, pMethod->m_pUnwindInfo); - pMethod->m_pColdUnwindInfo = pUnwindInfo; - } - else - { - pUnwindInfo = new (GetHeap()) ZapUnwindInfo(pCode, 0, 0, pMethod->m_pGCInfo); - pMethod->m_pUnwindInfo = pUnwindInfo; - } - pRuntimeFunctionSection->Place(pUnwindInfo); - -#endif // defined (FEATURE_EH_FUNCLETS) - - if (m_stats != NULL) - { - CorInfoIndirectCallReason reason; - BOOL direct = m_pPreloader->CanSkipMethodPreparation(NULL, pMethod->GetHandle(), &reason); - - if (direct && pMethod->m_pFixupList != NULL) - { - reason = CORINFO_INDIRECT_CALL_FIXUPS; - direct = FALSE; - } - - if (direct) - { - m_stats->m_directMethods++; - } - else - { - m_stats->m_prestubMethods++; - m_stats->m_indirectMethodReasons[reason]++; - } - } - } - -#ifdef REDHAWK - // Redhawk needs any trailing padding to be 0xcc - DWORD cbPad = AlignUp(currentOffset, sizeof(DWORD)) - currentOffset; - if (cbPad != 0) - { - ZapBlob * pBlob = ZapBlob::NewBlob(this, NULL, cbPad); - memset(pBlob->GetData(), DEFAULT_CODE_BUFFER_INIT, cbPad); - pCodeSection->Place(pBlob); - currentOffset += cbPad; - } - - map.Output(this, m_pCodeMgrSection, numMethods); -#else - COUNT_T nUnwindInfos = pRuntimeFunctionSection->GetNodeCount(); - - if (nUnwindInfos != 0) - { - if (IsReadyToRunCompilation()) - { - // TODO: Implement - } - else - if (!fCold) - { - ZapVirtualSection * pCodeMethodDescSection = GetCodeMethodDescSection(codeType); - pCodeMethodDescSection->Place(new (GetHeap()) ZapCodeMethodDescs(startMethod, endMethod, nUnwindInfos)); - - ZapVirtualSection* pUnwindInfoLookupSection = GetUnwindInfoLookupSection(codeType); - pUnwindInfoLookupSection->Place(new (GetHeap()) ZapUnwindInfoLookupTable(pRuntimeFunctionSection, pCodeSection, codeSize)); - } - else - { - m_pColdCodeMapSection->Place(new (GetHeap()) ZapColdCodeMap(pRuntimeFunctionSection)); - } - } -#endif - - EndRegion(regionKind); -} - -void ZapImage::OutputCodeInfo(CodeType codeType) -{ - CorInfoRegionKind regionKind = (codeType == ProfiledHot) ? CORINFO_REGION_HOT : CORINFO_REGION_COLD; - BeginRegion(regionKind); - - for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - - // - // We are either outputing the ProfiledHot methods - // or the unprofiled and cold methods - // - if ((pMethod->m_ProfilingDataFlags & (1 << ReadMethodCode)) != (codeType == ProfiledHot)) - { - // Wrong kind so skip - continue; - } - - if (pMethod->m_pROData != NULL) - m_pReadOnlyDataSection->Place(pMethod->m_pROData); - -#ifndef REDHAWK - // Note: for Redhawk we place EH info via OutputEHInfo(). - if (pMethod->m_pExceptionInfo != NULL) - { - ZapNode* pCode = pMethod->m_pCode; - m_pExceptionInfoLookupTable->PlaceExceptionInfoEntry(pCode, pMethod->m_pExceptionInfo); - } -#endif // REDHAWK - - if (pMethod->m_pFixupList != NULL && !IsReadyToRunCompilation()) - pMethod->m_pFixupInfo = m_pImportTable->PlaceFixups(pMethod->m_pFixupList); - } - - EndRegion(regionKind); -} - -void ZapImage::OutputProfileData() -{ - if (m_pInstrumentSection == NULL) - { - return; - } - - ZapProfileData * pPrevious = NULL; - - for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - - if (pMethod->m_pProfileData == NULL) - { - continue; - } - - ZapProfileData * pHeader = new (GetHeap()) ZapProfileData(pMethod); - - m_pInstrumentSection->Place(pHeader); - m_pInstrumentSection->Place(pMethod->m_pProfileData); - - if (pPrevious != NULL) - { - pPrevious->SetNext(pHeader); - } - - pPrevious = pHeader; - } -} - -void ZapImage::OutputDebugInfo() -{ - m_pDebugInfoTable->PrepareLayout(); - for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++) - { - m_pDebugInfoTable->PlaceDebugInfo(m_MethodCompilationOrder[i]); - } - m_pDebugInfoTable->FinishLayout(); -} - -void ZapImage::OutputGCInfo() -{ -#ifndef REDHAWK - struct MaskValue - { - DWORD mask; - DWORD value; - }; - - static const MaskValue gcInfoSequence[] = - { - { (1 << CommonReadGCInfo) , (1 << CommonReadGCInfo) }, // c flag on, r flag don't care - { (1 << CommonReadGCInfo)|(1 << ReadGCInfo), (1 << ReadGCInfo) }, // r flag on, c flag off - { (1 << CommonReadGCInfo)|(1 << ReadGCInfo), 0 }, // both flags off - { 0, 0 } - }; - - // Make three passes over the gc infos, emitting them in order of decreasing hotness, - // and for stuff that wasn't touched by anyone we put it in the cold section - for (const MaskValue *pMaskValue = gcInfoSequence; pMaskValue->mask; pMaskValue++) - { - for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - - if ((pMethod->m_ProfilingDataFlags & pMaskValue->mask) != pMaskValue->value) - { - continue; - } - - ZapGCInfo * pGCInfo = pMethod->m_pGCInfo; - - // Given that GC Info can be interned it may have been placed already on - // this or a previous pass through the compiled methods. If it hasn't already - // been placed then we place it in the appropriate section. - if (!pGCInfo->IsPlaced()) - { - // A) it was touched, and here they are placed in order of flags above - if (pMaskValue->value) - { - m_pHotTouchedGCSection->Place(pGCInfo); - } - // B) the method that it is attached to is in the trained section - else if (iPlace(pGCInfo); - } - // C) it wasn't touched _and_ it is related to untrained code - else - { - m_pGCSection->Place(pGCInfo); - } - } - } - - // Just after placing those touched in an IBC scenario, place those that - // should be prioritized regardless of the corresponding method's IBC information. - // (Currently, this is used to pack the gc info of IL stubs that cannot be directly tracked by IBC.) - if (pMaskValue->value == (1 << ReadGCInfo)) - { - for (COUNT_T i = 0; i < m_PrioritizedGCInfo.GetCount(); i++) - { - ZapGCInfo * pGCInfo = m_PrioritizedGCInfo[i]; - if (!pGCInfo->IsPlaced()) - { - m_pHotGCSection->Place(pGCInfo); - } - } - } - } -#else // REDHAWK - // - ModuleGcInfoEncoder * pEncoder = GetGcInfoEncoder(); - - m_pUnwindInfoBlob = pEncoder->ConstructUnwindInfoBlob(this); - m_pCallsiteInfoBlob = pEncoder->ConstructCallsiteInfoBlob(this); - ZapBlob * pShortcutMap = pEncoder->ConstructDeltaShortcutMap(this); - - // @TODO: we could fold this loop into ConstructMethodInfoBlob, but then we'd have to keep a separate - // list of method infos inside the ModuleGcInfoEncoder.. - for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - pEncoder->EncodeMethodInfo(pMethod->m_pGCInfo); - } - ZapBlob * pMethodInfos = pEncoder->ConstructMethodInfoBlob(this); - - for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - // At this point pMethod->m_pGCInfo is really a pointer that the encoder owns. - // We must pass it back to the encoder so it can encode it and pass back a proper ZapBlob * - pMethod->m_pGCInfo = pEncoder->FindMethodInfo(this, pMethod->m_pGCInfo); - } - - m_pGCSection->Place(pShortcutMap); - m_pGCSection->Place(pMethodInfos); - if (m_pUnwindInfoBlob) - m_pGCSection->Place(m_pUnwindInfoBlob); - - if (m_pCallsiteInfoBlob) - m_pGCSection->Place(m_pCallsiteInfoBlob); - - // - // Create the method-number-to-gc-info table - // - UINT32 methodInfoSize = pMethodInfos->GetSize(); - - COUNT_T nMethods = m_MethodCompilationOrder.GetCount(); - UINT16 elemSize = 4; - - if (methodInfoSize <= 0x10000) - { - elemSize = 2; - - // Remember the element size for this map in the module header - m_moduleHeaderFlags |= ModuleHeader::SmallGCInfoListEntriesFlag; - } - - // Create the table - SIZE_T tableSize = elemSize * nMethods; - ZapBlob * pMethodToGcInfoMap = ZapBlob::NewBlob(this, NULL, tableSize); - - UINT16* pwTableEntries = (UINT16*) pMethodToGcInfoMap->GetData(); - UINT32* pdwTableEntries = (UINT32*) pwTableEntries; - - for (COUNT_T i = 0; i < nMethods; i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - ZapGCInfo * pGCInfo = pMethod->m_pGCInfo; - - UINT32 uOffset = 0; - if (pGCInfo->GetType() == ZapNodeType_InnerPtr) - { - uOffset = ((ZapInnerPtr*)pGCInfo)->GetOffset(); - } - else - { - assert(ZapNodeType_Blob == pGCInfo->GetType()); - assert(pGCInfo == pMethodInfos); - } - - if (2 == elemSize) - { - assert(uOffset <= 0xFFFF); - pwTableEntries[i] = uOffset; - } - else - { - pdwTableEntries[i] = uOffset; - } - } - - m_pMethodToGCInfoMap->Place(pMethodToGcInfoMap); -#endif // REDHAWK -} - -#ifdef REDHAWK -// Place all ZapExceptionInfo blobs into the exception section, and form the lookup table that we'll -// use at runtime to find EH info for a given method. -void ZapImage::OutputEHInfo() -{ - // For non-REDHAWK builds, we output EH info with the other per-method data in OutputCodeInfo(). - - // @TODO: consider emitting EH info in order of increasing hotness, like we do for GC info. - - // Place EH info for every method that has EH. - for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - ZapExceptionInfo * pEHInfo = pMethod->m_pExceptionInfo; - - if ((pEHInfo != NULL) && !pEHInfo->IsPlaced()) - { - // We add relocs to the exception info here, at the last possible momement before placing - // them. That's because adding relocs changes the exception info, but prior to this we - // want to be able to use the data of the exception info as a hash key for interning. - AddRelocsForEHClauses(pEHInfo); - m_pExceptionSection->Place(pEHInfo); - } - } - - // Get the offsets for each EH blob that we will emit. - MapSHash ehinfoOffsets; - UINT32 ehinfoSize; - - ehinfoSize = m_pExceptionSection->FillInNodeOffsetMap(&ehinfoOffsets); - - // Chose a table entry size. - COUNT_T nMethods = m_MethodCompilationOrder.GetCount(); - UINT16 elemSize = 4; - - if (ehinfoSize <= 0x10000) - { - elemSize = 2; - - // Remember the element size for this map in the module header - m_moduleHeaderFlags |= ModuleHeader::SmallEHInfoListEntriesFlag; - } - - // Create the table. - SIZE_T tableSize = elemSize * nMethods; - SArray tableData(tableSize); - - UINT16* pwTableEntries = (UINT16*)&tableData[0]; - UINT32* pdwTableEntries = (UINT32*) pwTableEntries; - - // Fill in the offset for each method that has EH info. For methods that have no - // EH info, we will use a sentinel offset of -1. - for (COUNT_T i = 0; i < nMethods; i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - ZapExceptionInfo * pEHInfo = pMethod->m_pExceptionInfo; - - UINT32 uOffset = -1; - - if (pEHInfo != NULL) - { - ehinfoOffsets.Lookup(pEHInfo, &uOffset); - assert(uOffset != -1); // Can't have a valid offset match the sentinel! - assert((4 == elemSize) || (uOffset <= 0xFFFF)); // Size must fit in 2 bytes if we're using hte small rep. - } - - if (2 == elemSize) - { - pwTableEntries[i] = uOffset; - } - else - { - pdwTableEntries[i] = uOffset; - } - } - - m_pMethodToEHInfoMap->Place(ZapBlob::NewBlob(this, &tableData[0], tableSize)); -} -#endif // REDHAWK - -#ifdef REDHAWK -// Add relocs for any EEType references in any typed EH clauses for the given EH Info. -void ZapImage::AddRelocsForEHClauses(ZapExceptionInfo * pExceptionInfo) -{ - EE_ILEXCEPTION *pEHInfo = (EE_ILEXCEPTION *)pExceptionInfo->GetData(); - _ASSERTE(pEHInfo != NULL); - - // One set of relocs for the entire set of clauses. Size assuming that every clause has a token. - ZapReloc * pRelocs = (ZapReloc *) - new (GetHeap()) BYTE[sizeof(ZapReloc) * pEHInfo->EHCount() + sizeof(ZapRelocationType)]; - - DWORD relocIndex = 0; - - // Add relocs for EEType references each typed clause. - for (int i = 0; i < pEHInfo->EHCount(); i++) - { - EE_ILEXCEPTION_CLAUSE *pClause = pEHInfo->EHClause(i); - - if ((pClause->Flags == COR_ILEXCEPTION_CLAUSE_NONE) || - (pClause->Flags == COR_ILEXCEPTION_CLAUSE_INDIRECT_TYPE_REFERENCE)) - { - ZapNode *pEETypeNode = (ZapNode*)pClause->EETypeReference; - - // @TODO: we're using a full pointer for each EEType reference in the EH clause. This will be - // 64bits on a 64bit system, though, which is twice as large as it needs to be. We should make - // these 32bit RVA's and compute the final address at runtime when we start supporting 64bit - // systems. See comments in ZapInfo::setEHinfo() for more details. - // - // N.B! If we move to RVAs, then the runtime structure that matches the EE_ILEXCEPTION struct - // needs to have a padding field removed. (The C++ compiler introduced 4 bytes of padding between - // 'DataSize' and 'Clauses' because 'Clauses' has a pointer field in it. This padding will - // disappear when we change the pointers to RVAs.) - pRelocs[relocIndex].m_type = IMAGE_REL_BASED_PTR; - pRelocs[relocIndex].m_pTargetNode = pEETypeNode; - pRelocs[relocIndex].m_offset = (BYTE*)pClause - (BYTE*)pEHInfo + offsetof(EE_ILEXCEPTION_CLAUSE, EETypeReference); - pExceptionInfo->ZeroPointer(pRelocs[relocIndex].m_offset); - relocIndex++; - } - } - - // Did we end up with any relocs? If so, then add them to the blob. - if (relocIndex > 0) - { - // Set sentinel - C_ASSERT(offsetof(ZapReloc, m_type) == 0); - pRelocs[relocIndex].m_type = IMAGE_REL_INVALID; - - pExceptionInfo->SetRelocs(pRelocs); - } -} -#endif // REDHAWK - -// -// ZapMethodHeader -// - -#ifdef TARGET_X86 -DWORD ZapCodeBlob::ComputeRVA(ZapWriter * pZapWriter, DWORD dwPos) -{ - void * pData = GetData(); - SIZE_T size = GetSize(); - DWORD dwAlignment = GetAlignment(); - - dwPos = AlignUp(dwPos, dwAlignment); - - // - // Padding for straddler relocations. - // - - // The maximum size of padding - const DWORD cbAdjustForDynamicBaseMax = 256; - - // Find padding that gives us minimum number of straddlers - DWORD nMinStraddlers = MAXDWORD; - DWORD bestPad = 0; - for (DWORD pad = 0; pad < cbAdjustForDynamicBaseMax; pad += dwAlignment) - { - COUNT_T nStraddlers = GetCountOfStraddlerRelocations(dwPos + pad); - if (nStraddlers < nMinStraddlers) - { - nMinStraddlers = nStraddlers; - bestPad = pad; - - // It won't get better than this. - if (nMinStraddlers == 0) - break; - } - } - - DWORD dwPaddedPos = dwPos + bestPad; - SetRVA(dwPaddedPos); - - return dwPaddedPos + size; -} - -template -class ZapCodeBlobConst : public ZapCodeBlob -{ -protected: - ZapCodeBlobConst(SIZE_T cbSize) - : ZapCodeBlob(cbSize) - { - } - -public: - virtual UINT GetAlignment() - { - return alignment; - } - - static ZapCodeBlob * NewBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize) - { - S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapCodeBlobConst)) + S_SIZE_T(cbSize); - if(cbAllocSize.IsOverflow()) - ThrowHR(COR_E_OVERFLOW); - - void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize.Value()]; - - ZapCodeBlob * pZapCodeBlob = new (pMemory) ZapCodeBlobConst(cbSize); - - if (pData != NULL) - memcpy((void*)(pZapCodeBlob + 1), pData, cbSize); - - return pZapCodeBlob; - } -}; - -ZapCodeBlob * ZapCodeBlob::NewAlignedBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, SIZE_T cbAlignment) -{ - switch (cbAlignment) - { - case 1: - return ZapCodeBlobConst<1>::NewBlob(pWriter, pData, cbSize); - case 2: - return ZapCodeBlobConst<2>::NewBlob(pWriter, pData, cbSize); - case 4: - return ZapCodeBlobConst<4>::NewBlob(pWriter, pData, cbSize); - case 8: - return ZapCodeBlobConst<8>::NewBlob(pWriter, pData, cbSize); - case 16: - return ZapCodeBlobConst<16>::NewBlob(pWriter, pData, cbSize); - - default: - _ASSERTE(!"Requested alignment not supported"); - return NULL; - } -} -#endif // TARGET_X86 - -// See function prototype for details on why this iterator is "partial" -BOOL ZapMethodHeader::PartialTargetMethodIterator::GetNext(CORINFO_METHOD_HANDLE *pHnd) -{ - _ASSERTE(pHnd != NULL); - - if (m_pCurReloc == NULL) - { - return FALSE; - } - - while (m_pCurReloc->m_type != IMAGE_REL_INVALID) - { - ZapNode * pTarget = m_pCurReloc->m_pTargetNode; - ZapNodeType type = pTarget->GetType(); - - m_pCurReloc++; - - if (type == ZapNodeType_InnerPtr) - { - pTarget = ((ZapInnerPtr *)pTarget)->GetBase(); - type = pTarget->GetType(); - } - - if (type == ZapNodeType_MethodEntryPoint) - { - *pHnd = ((ZapMethodEntryPoint *)pTarget)->GetHandle(); - return TRUE; - } - } - - return FALSE; -} - -void ZapCodeMethodDescs::Save(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - COUNT_T nUnwindInfos = 0; - - for (COUNT_T curMethod = m_iStartMethod; curMethod < m_iEndMethod; curMethod++) - { - ZapMethodHeader * pMethod = pImage->m_MethodCompilationOrder[curMethod]; - DWORD dwRVA = pImage->m_pPreloader->MapMethodHandle(pMethod->GetHandle()); - - if (pMethod->m_pExceptionInfo != NULL) - dwRVA |= HAS_EXCEPTION_INFO_MASK; - - pImage->Write(&dwRVA, sizeof(dwRVA)); - nUnwindInfos++; - -#ifdef FEATURE_EH_FUNCLETS - ZapUnwindInfo * pFragment = pMethod->m_pUnwindInfoFragments; - while (pFragment != NULL) - { - if (pFragment != pMethod->m_pUnwindInfo && pFragment->GetCode() == pMethod->m_pCode) - { - dwRVA = 0; - pImage->Write(&dwRVA, sizeof(dwRVA)); - nUnwindInfos++; - } - - pFragment = pFragment->GetNextFragment(); - } -#endif - } - _ASSERTE(nUnwindInfos == m_nUnwindInfos); -} - -// -// ZapMethodEntryPoint -// - -void ZapMethodEntryPoint::Resolve(ZapImage * pImage) -{ - DWORD rvaValue = pImage->m_pPreloader->MapMethodEntryPoint(GetHandle()); -#ifdef _DEBUG - if (rvaValue == NULL) - { - mdMethodDef token; - pImage->GetCompileInfo()->GetMethodDef(GetHandle(), &token); - pImage->Error(token, S_OK, 0, W("MapMethodEntryPoint failed")); - } - else -#endif - { - SetRVA(rvaValue); - } -} - -ZapMethodEntryPoint * ZapMethodEntryPointTable::GetMethodEntryPoint(CORINFO_METHOD_HANDLE handle, CORINFO_ACCESS_FLAGS accessFlags) -{ - ZapMethodEntryPoint * pMethodEntryPoint = m_entries.Lookup(MethodEntryPointKey(handle, accessFlags)); - - if (pMethodEntryPoint != NULL) - return pMethodEntryPoint; - -#ifdef _DEBUG - mdMethodDef token; - m_pImage->GetCompileInfo()->GetMethodDef(handle, &token); -#endif - - pMethodEntryPoint = new (m_pImage->GetHeap()) ZapMethodEntryPoint(handle, accessFlags); - m_entries.Add(pMethodEntryPoint); - return pMethodEntryPoint; -} - -void ZapMethodEntryPointTable::Resolve() -{ - for (MethodEntryPointTable::Iterator i = m_entries.Begin(), end = m_entries.End(); i != end; i++) - { - ZapMethodEntryPoint * pMethodEntryPoint = *i; - - // Skip unused entrypoints - they may be omitted in the image - if (!pMethodEntryPoint->IsUsed()) - continue; - - pMethodEntryPoint->Resolve(m_pImage); - } -} - -ZapNode * ZapMethodEntryPointTable::CanDirectCall(ZapMethodEntryPoint * pMethodEntryPoint, ZapMethodHeader * pCaller) -{ - CORINFO_METHOD_HANDLE caller = pCaller->GetHandle(); - CORINFO_METHOD_HANDLE callee = pMethodEntryPoint->GetHandle(); - - CorInfoIndirectCallReason reason; - if (m_pImage->canIntraModuleDirectCall(caller, callee, &reason, pMethodEntryPoint->GetAccessFlags())) - { - ZapNode * pCode = m_pImage->GetCompiledMethod(callee)->GetCode(); -#ifdef TARGET_ARM - pCode = m_pImage->GetInnerPtr(pCode, THUMB_CODE); -#endif // TARGET_ARM - return pCode; - } - else - { - if (!pMethodEntryPoint->IsUsed()) - { - // This method entry point is going to be used for indirect call. - // Record this so that later we will assign it an RVA. - pMethodEntryPoint->SetIsUsed(); - } - return NULL; - } -} - -#ifdef FEATURE_EH_FUNCLETS -ZapGCInfo * ZapGCInfoTable::GetGCInfo(PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo) -{ - ZapGCInfo * pNode = m_blobs.Lookup(GCInfoKey(pGCInfo, cbGCInfo, pUnwindInfo, cbUnwindInfo)); - - if (pNode != NULL) - { - return pNode; - } - - pNode = ZapGCInfo::NewGCInfo(m_pImage, pGCInfo, cbGCInfo, pUnwindInfo, cbUnwindInfo); - m_blobs.Add(pNode); - return pNode; -} - -ZapGCInfo * ZapGCInfo::NewGCInfo(ZapWriter * pWriter, PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo) -{ - S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapGCInfo)) + S_SIZE_T(cbGCInfo) + S_SIZE_T(cbUnwindInfo); - if(cbAllocSize.IsOverflow()) - ThrowHR(COR_E_OVERFLOW); - - void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize.Value()]; - - ZapGCInfo * pZapGCInfo = new (pMemory) ZapGCInfo(cbGCInfo, cbUnwindInfo); - - memcpy(pZapGCInfo->GetGCInfo(), pGCInfo, cbGCInfo); - memcpy(pZapGCInfo->GetUnwindInfo(), pUnwindInfo, cbUnwindInfo); - -#if !defined(TARGET_X86) - // Make sure the personality routine thunk is created - pZapGCInfo->GetPersonalityRoutine(ZapImage::GetImage(pWriter)); -#endif // !defined(TARGET_X86) - return pZapGCInfo; -} -#else -ZapGCInfo * ZapGCInfoTable::GetGCInfo(PVOID pBlob, SIZE_T cbBlob) -{ - ZapGCInfo * pNode = m_blobs.Lookup(ZapBlob::SHashKey(pBlob, cbBlob)); - - if (pNode != NULL) - { - return pNode; - } - - pNode = ZapBlob::NewBlob(m_pImage, pBlob, cbBlob); - m_blobs.Add(pNode); - return pNode; -} -#endif - -// -// ZapUnwindInfo -// - -void ZapUnwindInfo::Save(ZapWriter * pZapWriter) -{ - T_RUNTIME_FUNCTION runtimeFunction; - -#if defined(TARGET_ARM) || defined(TARGET_ARM64) - RUNTIME_FUNCTION__SetBeginAddress(&runtimeFunction, GetStartAddress()); - runtimeFunction.UnwindData = m_pUnwindData->GetRVA(); -#elif defined(TARGET_AMD64) - runtimeFunction.BeginAddress = GetStartAddress(); - runtimeFunction.EndAddress = GetEndAddress(); - ULONG unwindData = m_pUnwindData->GetRVA(); - if (m_pUnwindData->GetType() == ZapNodeType_UnwindInfo) // Chained unwind info - unwindData |= RUNTIME_FUNCTION_INDIRECT; - runtimeFunction.UnwindData = unwindData; -#elif defined(TARGET_X86) - runtimeFunction.BeginAddress = GetStartAddress(); - ULONG unwindData = m_pUnwindData->GetRVA(); - if (m_pUnwindData->GetType() == ZapNodeType_UnwindInfo) // Chained unwind info - unwindData |= RUNTIME_FUNCTION_INDIRECT; - runtimeFunction.UnwindData = unwindData; -#else - PORTABILITY_ASSERT("ZapUnwindInfo"); -#endif - - pZapWriter->Write(&runtimeFunction, sizeof(runtimeFunction)); -} - -#if defined(FEATURE_EH_FUNCLETS) -// Compare the unwind infos by their offset -int __cdecl ZapUnwindInfo::CompareUnwindInfo(const void* a_, const void* b_) -{ - ZapUnwindInfo * a = *(ZapUnwindInfo **)a_; - ZapUnwindInfo * b = *(ZapUnwindInfo **)b_; - - if (a->GetStartOffset() > b->GetStartOffset()) - { - _ASSERTE(a->GetStartOffset() >= b->GetEndOffset()); - return 1; - } - - if (a->GetStartOffset() < b->GetStartOffset()) - { - _ASSERTE(a->GetEndOffset() <= b->GetEndOffset()); - return -1; - } - - _ASSERTE(a == b); - return 0; -} - -#if defined(TARGET_AMD64) - -UINT ZapUnwindData::GetAlignment() -{ - return sizeof(ULONG); -} - -DWORD ZapUnwindData::GetSize() -{ - DWORD dwSize = ZapBlob::GetSize(); - -#ifndef REDHAWK - // Add space for personality routine, it must be 4-byte aligned. - // Everything in the UNWIND_INFO has already had its size included in size - dwSize = AlignUp(dwSize, sizeof(ULONG)); - - dwSize += sizeof(ULONG); -#endif //REDHAWK - - return dwSize; -} - -void ZapUnwindData::Save(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - PVOID pData = GetData(); - DWORD dwSize = GetBlobSize(); - - UNWIND_INFO * pUnwindInfo = (UNWIND_INFO *)pData; - - // Check whether the size is what we expect it to be - _ASSERTE(dwSize == offsetof(UNWIND_INFO, UnwindCode) + pUnwindInfo->CountOfUnwindCodes * sizeof(UNWIND_CODE)); -#ifndef REDHAWK - pUnwindInfo->Flags = UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER; -#endif //REDHAWK - - pZapWriter->Write(pData, dwSize); - -#ifndef REDHAWK - DWORD dwPad = AlignmentPad(dwSize, sizeof(DWORD)); - if (dwPad != 0) - pZapWriter->WritePad(dwPad); - - ULONG personalityRoutine = GetPersonalityRoutine(pImage)->GetRVA(); - pZapWriter->Write(&personalityRoutine, sizeof(personalityRoutine)); -#endif //REDHAWK -} - -#elif defined(TARGET_X86) - -UINT ZapUnwindData::GetAlignment() -{ - return sizeof(BYTE); -} - -DWORD ZapUnwindData::GetSize() -{ - return ZapBlob::GetSize(); -} - -void ZapUnwindData::Save(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - PVOID pData = GetData(); - DWORD dwSize = GetBlobSize(); - - pZapWriter->Write(pData, dwSize); -} - -#elif defined(TARGET_ARM) || defined(TARGET_ARM64) - -UINT ZapUnwindData::GetAlignment() -{ - return sizeof(ULONG); -} - -DWORD ZapUnwindData::GetSize() -{ - DWORD dwSize = ZapBlob::GetSize(); - - // Add space for personality routine, it must be 4-byte aligned. - // Everything in the UNWIND_INFO has already had its size included in size - dwSize = AlignUp(dwSize, sizeof(ULONG)); - dwSize += sizeof(ULONG); - - return dwSize; -} - -void ZapUnwindData::Save(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - PVOID pData = GetData(); - DWORD dwSize = GetBlobSize(); - - UNWIND_INFO * pUnwindInfo = (UNWIND_INFO *)pData; - - // Set the 'X' bit to indicate that there is a personality routine associated with this method - *(LONG *)pUnwindInfo |= (1<<20); - - pZapWriter->Write(pData, dwSize); - - DWORD dwPad = AlignmentPad(dwSize, sizeof(DWORD)); - if (dwPad != 0) - pZapWriter->WritePad(dwPad); - - ULONG personalityRoutine = GetPersonalityRoutine(pImage)->GetRVA(); - pZapWriter->Write(&personalityRoutine, sizeof(personalityRoutine)); -} - -#else -UINT ZapUnwindData::GetAlignment() -{ - PORTABILITY_ASSERT("ZapUnwindData::GetAlignment"); - return sizeof(ULONG); -} -DWORD ZapUnwindData::GetSize() -{ - PORTABILITY_ASSERT("ZapUnwindData::GetSize"); - return -1; -} -void ZapUnwindData::Save(ZapWriter * pZapWriter) -{ - PORTABILITY_ASSERT("ZapUnwindData::Save"); -} - -#endif - -ZapNode * ZapUnwindData::GetPersonalityRoutine(ZapImage * pImage) -{ - // Use different personality routine pointer for filter funclets so that we can quickly tell at runtime - // whether funclet is a filter. -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - ReadyToRunHelper helperNum = IsFilterFunclet() ? READYTORUN_HELPER_PersonalityRoutineFilterFunclet : READYTORUN_HELPER_PersonalityRoutine; - return pImage->GetImportTable()->GetPlacedIndirectHelperThunk(helperNum); - } -#endif - return pImage->GetHelperThunk(IsFilterFunclet() ? CORINFO_HELP_EE_PERSONALITY_ROUTINE_FILTER_FUNCLET : CORINFO_HELP_EE_PERSONALITY_ROUTINE); -} - -ZapUnwindData * ZapUnwindData::NewUnwindData(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, BOOL fIsFilterFunclet) -{ - SIZE_T cbAllocSize = sizeof(ZapUnwindData) + cbSize; - - void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize]; - - ZapUnwindData * pZapUnwindData = fIsFilterFunclet ? - (new (pMemory) ZapFilterFuncletUnwindData(cbSize)) : (new (pMemory) ZapUnwindData(cbSize)); - - memcpy((void*)(pZapUnwindData + 1), pData, cbSize); - -#if !defined(TARGET_X86) - // Make sure the personality routine thunk is created - pZapUnwindData->GetPersonalityRoutine(ZapImage::GetImage(pWriter)); -#endif // !defined(TARGET_X86) - - return pZapUnwindData; -} - -ZapUnwindData * ZapUnwindDataTable::GetUnwindData(PVOID pBlob, SIZE_T cbBlob, BOOL fIsFilterFunclet) -{ - ZapUnwindData * pNode = (ZapUnwindData *)m_blobs.Lookup(ZapUnwindDataKey(pBlob, cbBlob, fIsFilterFunclet)); - - if (pNode != NULL) - { - return pNode; - } - - pNode = ZapUnwindData::NewUnwindData(m_pImage, pBlob, cbBlob, fIsFilterFunclet); - m_blobs.Add(pNode); - return pNode; -} -#endif // FEATURE_EH_FUNCLETS - -// -// ZapDebugInfo -// - -ZapDebugInfo * ZapDebugInfoTable::GetDebugInfo(PVOID pBlob, SIZE_T cbBlob) -{ - ZapDebugInfo * pNode = m_blobs.Lookup(ZapBlob::SHashKey(pBlob, cbBlob)); - m_nCount++; - - if (pNode != NULL) - { - return pNode; - } - - pNode = ZapBlob::NewBlob(m_pImage, pBlob, cbBlob); - m_blobs.Add(pNode); - return pNode; -} - -void ZapDebugInfoTable::PrepareLayout() -{ - if (m_nCount == 0) - return; - - // Make sure that the number of methods is odd number - m_nCount |= 1; - - m_pTable = new (m_pImage->GetHeap()) ZapNode * [m_nCount]; -} - -void ZapDebugInfoTable::PlaceDebugInfo(ZapMethodHeader * pMethod) -{ - // Place the debug info blob if it is not placed yet - ZapBlob * pDebugInfo = pMethod->GetDebugInfo(); - if (pDebugInfo == NULL) - { - return; - } - - if (!pDebugInfo->IsPlaced()) - { - m_pImage->m_pDebugSection->Place(pDebugInfo); - } - - mdMethodDef md; - IfFailThrow(m_pImage->GetCompileInfo()->GetMethodDef(pMethod->GetHandle(), &md)); - - COUNT_T index = GetDebugRidEntryHash(md) % m_nCount; - - ZapNode * pHead = m_pTable[index]; - if (pHead == NULL) - { - // The common case - single rid entry. - m_pTable[index] = pMethod; - return; - } - - // Create linked list of labelled entries if we do not have one yet - if (pHead->GetType() != ZapNodeType_DebugInfoLabelledEntry) - { - m_pTable[index] = new (m_pImage->GetHeap()) LabelledEntry((ZapMethodHeader *)pHead); - } - - // Insert the method at the end of the linked list - LabelledEntry * pEntry = (LabelledEntry *)m_pTable[index]; - while (pEntry->m_pNext != NULL) - pEntry = pEntry->m_pNext; - - pEntry->m_pNext = new (m_pImage->GetHeap()) LabelledEntry(pMethod); -} - -void ZapDebugInfoTable::FinishLayout() -{ - // Go over the table again and place all labelled entries - for (COUNT_T i = 0; i < m_nCount; i++) - { - ZapNode * pNode = m_pTable[i]; - - if (pNode == NULL || pNode->GetType() != ZapNodeType_DebugInfoLabelledEntry) - continue; - - LabelledEntry * pEntry = (LabelledEntry *)pNode; - - while (pEntry != NULL) - { - m_pImage->m_pDebugSection->Place(pEntry); - pEntry = pEntry->m_pNext; - } - } -} - -void ZapDebugInfoTable::Save(ZapWriter * pZapWriter) -{ - for (COUNT_T i = 0; i < m_nCount; i++) - { - CORCOMPILE_DEBUG_ENTRY entry = 0; - - ZapNode * pNode = m_pTable[i]; - - if (pNode != NULL) - { - if (pNode->GetType() == ZapNodeType_DebugInfoLabelledEntry) - entry |= pNode->GetRVA() | CORCOMPILE_DEBUG_MULTIPLE_ENTRIES; - else - entry = ((ZapMethodHeader *)pNode)->GetDebugInfo()->GetRVA(); - } - - pZapWriter->Write(&entry, sizeof(entry)); - } -} - -void ZapDebugInfoTable::LabelledEntry::Save(ZapWriter * pZapWriter) -{ - CORCOMPILE_DEBUG_LABELLED_ENTRY entry; - - entry.nativeCodeRVA = m_pMethod->GetCode()->GetRVA(); - entry.debugInfoOffset = m_pMethod->GetDebugInfo()->GetRVA(); - - if (m_pNext != NULL) - entry.debugInfoOffset |= CORCOMPILE_DEBUG_MULTIPLE_ENTRIES; - - pZapWriter->Write(&entry, sizeof(entry)); -} - -// -// ZapProfileData -// -void ZapProfileData::Save(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - CORCOMPILE_METHOD_PROFILE_LIST profileData; - - ZeroMemory(&profileData, sizeof(CORCOMPILE_METHOD_PROFILE_LIST)); - - if (m_pNext != NULL) - pImage->WriteReloc(&profileData, - offsetof(CORCOMPILE_METHOD_PROFILE_LIST, next), - m_pNext, 0, IMAGE_REL_BASED_PTR); - - pZapWriter->Write(&profileData, sizeof(CORCOMPILE_METHOD_PROFILE_LIST)); -} - - -// Zapping of ExeptionInfoTable -ZapExceptionInfoLookupTable::ZapExceptionInfoLookupTable(ZapImage *pImage) : m_pImage(pImage) -{ - _ASSERTE(m_pImage->m_pExceptionSection != NULL); - m_pImage->m_pExceptionSection->Place(this); -} - -void ZapExceptionInfoLookupTable::PlaceExceptionInfoEntry(ZapNode* pCode, ZapExceptionInfo* pExceptionInfo) -{ - ExceptionInfoEntry entry; - entry.m_pCode = pCode; - entry.m_pExceptionInfo = pExceptionInfo; - m_exceptionInfoEntries.Append(entry); - m_pImage->m_pExceptionSection->Place(pExceptionInfo); -} - -DWORD ZapExceptionInfoLookupTable::GetSize() -{ - if (m_exceptionInfoEntries.GetCount() == 0) - return 0; - - DWORD numExceptionInfoEntries = m_exceptionInfoEntries.GetCount(); - // 1 sentential entry at the end of the table. - return (numExceptionInfoEntries + 1) * sizeof(CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY); -} - -void ZapExceptionInfoLookupTable::Save(ZapWriter* pZapWriter) -{ - - if(m_exceptionInfoEntries.GetCount() == 0) - return; - - for(COUNT_T i = 0; i < m_exceptionInfoEntries.GetCount(); ++i) - { - DWORD methodStartRVA = m_exceptionInfoEntries[i].m_pCode->GetRVA(); - - ZapExceptionInfo* pExceptionInfo = m_exceptionInfoEntries[i].m_pExceptionInfo; - - CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY lookupEntry; - - lookupEntry.MethodStartRVA = methodStartRVA; - lookupEntry.ExceptionInfoRVA = pExceptionInfo->GetRVA(); - - pZapWriter->Write(&lookupEntry, sizeof(CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY)); - -#ifdef _DEBUG - // Make sure there are no gaps between 2 consecutive CORCOMPILE_EXCEPTION_CLAUSE - // We use pointer arithmatic to calculate the number of EHClause for a method. - if (i != 0) - { - ZapExceptionInfo* pPreviousExceptionInfo = m_exceptionInfoEntries[i-1].m_pExceptionInfo; - DWORD size = pExceptionInfo->GetRVA() - pPreviousExceptionInfo->GetRVA(); - DWORD ehClauseSize = size % sizeof(CORCOMPILE_EXCEPTION_CLAUSE); - CONSISTENCY_CHECK_MSG(ehClauseSize == 0, "There must be no gaps between 2 successive clause arrays, please check ZapExceptionInfo alignment"); - } -#endif - } - - // write a sentinal entry.. this entry helps to find the number of EHClauses for the last entry - CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY sentinalEntry; - - ExceptionInfoEntry lastEntry = m_exceptionInfoEntries[m_exceptionInfoEntries.GetCount() -1]; - - ZapExceptionInfo* pLastExceptionInfo = lastEntry.m_pExceptionInfo; - - sentinalEntry.MethodStartRVA = (DWORD)-1; - - // points just after the end of the Exception table - // the sentinal node m_pExceptionInfo pointer actually points to an invalid CORCOMPILE_EXCEPTION_CLAUSE - // area. The lookup algorithm will never dereference the sentinal pointer, and hence this is safe - sentinalEntry.ExceptionInfoRVA = pLastExceptionInfo->GetRVA() + pLastExceptionInfo->GetSize(); - - pZapWriter->Write(&sentinalEntry, sizeof(CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY)); -} - - -DWORD ZapUnwindInfoLookupTable::GetSize() -{ - // Sentinal entry at the end - return (GetNumEntries() + 1) * sizeof (DWORD); -} - -void ZapUnwindInfoLookupTable::Save(ZapWriter* pZapWriter) -{ - ZapVirtualSection * pRuntimeFunctionSection = m_pRuntimeFunctionSection; - - // Create Lookup entries. - // 1 lookup entry for each RUNTIME_FUNCTION_LOOKUP_STRIDE K of code. - COUNT_T nUnwindInfos = pRuntimeFunctionSection->GetNodeCount(); - - DWORD dwCodeSectionStartAddress = m_pCodeSection->GetRVA(); - - DWORD nLookupEntries = 0; - DWORD entry; - - DWORD nTotalLookupEntries = GetNumEntries(); - - // write out the first entry - entry = 0; - pZapWriter->Write(&entry, sizeof(DWORD)); - nLookupEntries++; - if (nLookupEntries == nTotalLookupEntries) - goto WriteSentinel; - - for (COUNT_T i = 1; i < nUnwindInfos; ++i) - { - ZapUnwindInfo* pUnwindInfo = (ZapUnwindInfo*)pRuntimeFunctionSection->GetNode(i); - DWORD RelativePC = pUnwindInfo->GetStartAddress() - dwCodeSectionStartAddress; - - COUNT_T iCurrentIndex = RelativePC / RUNTIME_FUNCTION_LOOKUP_STRIDE; - - // Note that we should not be using pUnwindInfo->GetEndAddress() here. The binary search - // in the VM that's accelerated by this table does not look at the EndAddress either, and - // so not using EndAddress here assures consistency. - COUNT_T iPreviousIndex = (RelativePC - 1)/ RUNTIME_FUNCTION_LOOKUP_STRIDE; - - while(iPreviousIndex >= nLookupEntries) - { - entry = i - 1; - pZapWriter->Write(&entry, sizeof(DWORD)); - nLookupEntries++; - if (nLookupEntries == nTotalLookupEntries) - goto WriteSentinel; - } - - if (iCurrentIndex == nLookupEntries) - { - entry = i; - pZapWriter->Write(&entry, sizeof(DWORD)); - nLookupEntries++; - if (nLookupEntries == nTotalLookupEntries) - goto WriteSentinel; - } - } - -WriteSentinel: - // There should always be one sentinel entry at the end. The sentinel entry will - // be good to cover the rest of the section to account for extra padding. - _ASSERTE(nLookupEntries <= nTotalLookupEntries); - - while (nLookupEntries <= nTotalLookupEntries) - { - entry = nUnwindInfos - 1; - pZapWriter->Write(&entry, sizeof (DWORD)); - nLookupEntries ++; - } -} - -DWORD ZapColdCodeMap::GetSize() -{ - return m_pRuntimeFunctionSection->GetNodeCount() * sizeof(CORCOMPILE_COLD_METHOD_ENTRY); -} - -void ZapColdCodeMap::Save(ZapWriter* pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - ZapNode * pPendingCode = NULL; - COUNT_T curMethod = 0; - - COUNT_T nUnwindInfos = m_pRuntimeFunctionSection->GetNodeCount(); - for (COUNT_T i = 0; i < nUnwindInfos; ++i) - { - CORCOMPILE_COLD_METHOD_ENTRY entry; - - ZapUnwindInfo* pUnwindInfo = (ZapUnwindInfo*)m_pRuntimeFunctionSection->GetNode(i); - -#ifdef FEATURE_EH_FUNCLETS - if (pUnwindInfo->GetCode() == pPendingCode) - { - entry.mainFunctionEntryRVA = 0; - entry.hotCodeSize = 0; - } - else -#endif - { - pPendingCode = pUnwindInfo->GetCode(); - - ZapMethodHeader * pMethod; - - for (;;) - { - pMethod = pImage->m_MethodCompilationOrder[curMethod]; - if (pMethod->m_pColdCode == pPendingCode) - break; - curMethod++; - } - -#ifdef FEATURE_EH_FUNCLETS - entry.mainFunctionEntryRVA = pMethod->m_pUnwindInfo->GetRVA(); -#endif - - entry.hotCodeSize = pMethod->m_pCode->GetSize(); - } - - pZapWriter->Write(&entry, sizeof(entry)); - } -} - -DWORD ZapHelperThunk::GetSize() -{ - return (m_dwHelper & CORCOMPILE_HELPER_PTR) ? TARGET_POINTER_SIZE : HELPER_TABLE_ENTRY_LEN; -} - -void ZapHelperThunk::Save(ZapWriter * pZapWriter) -{ -#ifdef _DEBUG - LOG((LF_ZAP, LL_INFO1000000, "Emitting JIT helper table entry for helper %3d (%s)\n", - (USHORT) m_dwHelper, s_rgHelperNames[(USHORT) m_dwHelper])); -#endif // _DEBUG - - // Save the index of the helper, the actual code for the thunk will be generated at runtime - pZapWriter->Write(&m_dwHelper, sizeof(DWORD)); - - DWORD pad = GetSize() - sizeof(DWORD); - if (pad > 0) - { - void * pPad = _alloca(pad); - memset(pPad, DEFAULT_CODE_BUFFER_INIT, pad); - pZapWriter->Write(pPad, pad); - } -} - -void ZapLazyHelperThunk::Place(ZapImage * pImage) -{ - m_pArg = pImage->m_pPreloadSections[CORCOMPILE_SECTION_MODULE]; - - m_pTarget = pImage->GetHelperThunk(m_dwHelper); - - pImage->m_pLazyHelperSection->Place(this); -} - -DWORD ZapLazyHelperThunk::GetSize() -{ - return SaveWorker(NULL); -} - -void ZapLazyHelperThunk::Save(ZapWriter * pZapWriter) -{ - SaveWorker(pZapWriter); -} - -DWORD ZapLazyHelperThunk::SaveWorker(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - BYTE buffer[42]; // Buffer big enough to hold any reasonable helper thunk sequence - BYTE * p = buffer; - -#if defined(TARGET_X86) - // mov edx, module - *p++ = 0xBA; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), m_pArg, 0, IMAGE_REL_BASED_PTR); - p += 4; - - // jmp JIT_StrCns - *p++ = 0xE9; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), m_pTarget, 0, IMAGE_REL_BASED_REL32); - p += 4; -#elif defined(TARGET_AMD64) - *p++ = 0x48; - *p++ = 0x8D; -#ifdef UNIX_AMD64_ABI - // lea rsi, module - *p++ = 0x35; -#else - // lea rdx, module - *p++ = 0x15; -#endif - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), m_pArg, 0, IMAGE_REL_BASED_REL32); - p += 4; - - // jmp JIT_StrCns - *p++ = 0xE9; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), m_pTarget, 0, IMAGE_REL_BASED_REL32); - p += 4; -#elif defined(TARGET_ARM) - // movw r1, module - *(WORD *)(p + 0) = 0xf240; - *(WORD *)(p + 2) = 1 << 8; - // movt r1, module - *(WORD *)(p + 4) = 0xf2c0; - *(WORD *)(p + 6) = 1 << 8; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), m_pArg, 0, IMAGE_REL_BASED_THUMB_MOV32); - p += 8; - - // b JIT_StrCns - *(WORD *)(p + 0) = 0xf000; - *(WORD *)(p + 2) = 0xb800; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), m_pTarget, 0, IMAGE_REL_BASED_THUMB_BRANCH24); - p += 4; -#elif defined(TARGET_ARM64) - // ldr x1, [PC+8] - *(DWORD *)(p) =0x58000041; - p += 4; - // b JIT_StrCns - *(DWORD *)(p) = 0x14000000; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), m_pTarget, 0, IMAGE_REL_ARM64_BRANCH26); - p += 4; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), m_pArg, 0, IMAGE_REL_BASED_PTR); - p += 8; -#else - PORTABILITY_ASSERT("ZapLazyHelperThunk::Save"); -#endif - - _ASSERTE((DWORD)(p - buffer) <= sizeof(buffer)); - - if (pZapWriter != NULL) - pZapWriter->Write(&buffer, (int)(p - buffer)); - - return (DWORD) (p - buffer); -} diff --git a/src/coreclr/zap/zapcode.h b/src/coreclr/zap/zapcode.h deleted file mode 100644 index cd9b7ccbf19310..00000000000000 --- a/src/coreclr/zap/zapcode.h +++ /dev/null @@ -1,956 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapCode.h -// - -// -// ZapNodes for everything directly related to zapping of native code -// -// code:ZapMethodHeader -// code:ZapMethodEntryPoint -// code:ZapMethodEntryPointTable -// code:ZapDebugInfo -// code:ZapProfileData -// code:ZapHelperTable -// code:ZapGCInfoTable - - -// -// ====================================================================================== - -#ifndef __ZAPCODE_H__ -#define __ZAPCODE_H__ - -// Forward declarations - -class ZapBlobWithRelocs; - -#ifdef REDHAWK -typedef ZapNode ZapGCInfo; -#else -#if defined(FEATURE_EH_FUNCLETS) -class ZapGCInfo; -#else -typedef ZapBlob ZapGCInfo; -#endif -#endif // REDHAWK - -typedef ZapBlob ZapDebugInfo; -typedef ZapBlob ZapFixupInfo; -#ifdef REDHAWK -typedef ZapBlobWithRelocs ZapExceptionInfo; -#else -typedef ZapBlob ZapExceptionInfo; -#endif - -class ZapUnwindInfo; - -class ZapImport; - -class ZapInfo; - -class ZapGCRefMapTable; - -//--------------------------------------------------------------------------------------- -// -// ZapMethodHeader is the main node that all information about the compiled code is hanging from -// -class ZapMethodHeader : public ZapNode -{ - // All other kinds of method headers are tightly coupled with the main method header - friend class ZapProfileData; - friend class ZapCodeMethodDescs; - friend class ZapColdCodeMap; - - friend class MethodCodeComparer; - - friend class ZapImage; - friend class ZapInfo; - - CORINFO_METHOD_HANDLE m_handle; - CORINFO_CLASS_HANDLE m_classHandle; - - ZapBlobWithRelocs * m_pCode; - ZapBlobWithRelocs * m_pColdCode; // May be NULL - - ZapUnwindInfo * m_pUnwindInfo; - ZapUnwindInfo * m_pColdUnwindInfo; // May be NULL - -#ifdef FEATURE_EH_FUNCLETS - ZapUnwindInfo * m_pUnwindInfoFragments; // Linked list of all unwind info fragments -#endif - - ZapBlobWithRelocs * m_pROData; // May be NULL - - ZapBlobWithRelocs * m_pProfileData; // May be NULL - - ZapGCInfo * m_pGCInfo; - ZapDebugInfo * m_pDebugInfo; - - union // May be NULL - { - ZapImport ** m_pFixupList; // Valid before place phase - ZapFixupInfo * m_pFixupInfo; // Valid after place phase - }; - - ZapExceptionInfo * m_pExceptionInfo; // May be NULL - - unsigned m_ProfilingDataFlags; - - unsigned m_compilationOrder; - unsigned m_cachedLayoutOrder; - - DWORD m_methodIndex; - - ZapMethodHeader() - { - } - -public: - CORINFO_METHOD_HANDLE GetHandle() - { - return m_handle; - } - - CORINFO_CLASS_HANDLE GetClassHandle() - { - return m_classHandle; - } - - DWORD GetMethodIndex() - { - return m_methodIndex; - } - - ZapBlobWithRelocs * GetCode() - { - return m_pCode; - } - - ZapBlobWithRelocs * GetColdCode() - { - return m_pColdCode; - } - - BOOL HasFixups() - { - return m_pFixupList != NULL; - } - - ZapNode * GetFixupList() - { - return m_pFixupInfo; - } - - ZapDebugInfo * GetDebugInfo() - { - return m_pDebugInfo; - } - - unsigned GetCompilationOrder() - { - return m_compilationOrder; - } - - unsigned GetCachedLayoutOrder() - { - return m_cachedLayoutOrder; - } - virtual ZapNodeType GetType() - { - return ZapNodeType_MethodHeader; - } - - // Iterate over as many of the methods called by this method - // as are easy to determine. Currently this is implemented - // by walking the Reloc list and so is only as complete as - // the current state of the Relocs. Note that the implementation - // ignores virtual calls and calls in the cold code section. - class PartialTargetMethodIterator - { - public: - PartialTargetMethodIterator(ZapMethodHeader* pMethod) - : m_pMethod(pMethod) - { - ZapBlobWithRelocs * pCode = pMethod->GetCode(); - m_pCurReloc = pCode ? pCode->GetRelocs() : NULL; - } - - BOOL GetNext(CORINFO_METHOD_HANDLE *pHnd); - - private: - ZapMethodHeader* m_pMethod; - ZapReloc* m_pCurReloc; - }; - -}; - -#if defined(TARGET_X86) -class ZapCodeBlob : public ZapBlobWithRelocs -{ -protected: - ZapCodeBlob(SIZE_T cbSize) - : ZapBlobWithRelocs(cbSize) - { - } - -public: - static ZapCodeBlob * NewAlignedBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, SIZE_T cbAlignment); - - virtual DWORD ComputeRVA(ZapWriter * pZapWriter, DWORD dwPos); -}; -#else -typedef ZapBlobWithRelocs ZapCodeBlob; -#endif - -class ZapCodeMethodDescs : public ZapNode -{ - COUNT_T m_iStartMethod; - COUNT_T m_iEndMethod; - COUNT_T m_nUnwindInfos; - -public: - ZapCodeMethodDescs(COUNT_T startMethod, COUNT_T endMethod, COUNT_T nUnwindInfos) - : m_iStartMethod(startMethod), m_iEndMethod(endMethod), m_nUnwindInfos(nUnwindInfos) - { - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual DWORD GetSize() - { - return m_nUnwindInfos * sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_CodeManagerMap; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -//--------------------------------------------------------------------------------------- -// -// ZapMethodEntryPoint is special type of placeholder. Unlike normal placeholder, it -// carries extra CORINFO_ACCESS_FLAGS that is used to opt into the direct call even -// when it would not be otherwise possible. -// -class ZapMethodEntryPoint : public ZapNode -{ - CORINFO_METHOD_HANDLE m_handle; // Target method being called - BYTE m_accessFlags; // CORINFO_ACCESS_FLAGS - BYTE m_fUsed; // Entrypoint is used - needs to be resolved - - ZapNode *m_pEntryPoint; // only used for abstract methods to remember the precode - -public: - ZapMethodEntryPoint(CORINFO_METHOD_HANDLE handle, CORINFO_ACCESS_FLAGS accessFlags) - : m_handle(handle), m_accessFlags(static_cast(accessFlags)) - { - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_MethodEntryPoint; - } - - CORINFO_METHOD_HANDLE GetHandle() - { - return m_handle; - } - - CORINFO_ACCESS_FLAGS GetAccessFlags() - { - return (CORINFO_ACCESS_FLAGS)m_accessFlags; - } - - void SetIsUsed() - { - m_fUsed = true; - } - - BOOL IsUsed() - { - return m_fUsed; - } - - void Resolve(ZapImage * pImage); -}; - -class ZapMethodEntryPointTable -{ - struct MethodEntryPointKey - { - MethodEntryPointKey(CORINFO_METHOD_HANDLE handle, CORINFO_ACCESS_FLAGS accessFlags) - : m_handle(handle), m_accessFlags(accessFlags) - { - } - - CORINFO_METHOD_HANDLE m_handle; // Target method being called - CORINFO_ACCESS_FLAGS m_accessFlags; - }; - - class MethodEntryPointTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef MethodEntryPointKey key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return MethodEntryPointKey(e->GetHandle(), e->GetAccessFlags()); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return (k1.m_handle == k2.m_handle) && (k1.m_accessFlags == k2.m_accessFlags); - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(size_t)k.m_handle ^ (count_t)k.m_accessFlags; - } - - static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } - }; - - typedef SHash< MethodEntryPointTraits > MethodEntryPointTable; - - MethodEntryPointTable m_entries; - ZapImage * m_pImage; - -public: - ZapMethodEntryPointTable(ZapImage * pImage) - : m_pImage(pImage) - { - } - - void Preallocate(COUNT_T cbILImage) - { - PREALLOCATE_HASHTABLE(ZapMethodEntryPointTable::m_entries, 0.0018, cbILImage); - } - - ZapMethodEntryPoint * GetMethodEntryPoint(CORINFO_METHOD_HANDLE handle, CORINFO_ACCESS_FLAGS accessFlags); - - ZapNode * CanDirectCall(ZapMethodEntryPoint * pMethodEntryPoint, ZapMethodHeader * pCaller); - - void Resolve(); -}; - -//--------------------------------------------------------------------------------------- -// -// Zapping of unwind info -// -class ZapUnwindInfo : public ZapNode -{ - ZapNode * m_pCode; - - DWORD m_dwStartOffset; - DWORD m_dwEndOffset; - - ZapNode * m_pUnwindData; - - ZapUnwindInfo * m_pNextFragment; - -public: - ZapUnwindInfo(ZapNode * pCode, DWORD dwStartOffset, DWORD dwEndOffset, ZapNode * pUnwindData = NULL) - : m_pCode(pCode), - m_dwStartOffset(dwStartOffset), - m_dwEndOffset(dwEndOffset), - m_pUnwindData(pUnwindData) - { - } - - ZapNode * GetCode() - { - return m_pCode; - } - - DWORD GetStartOffset() - { - return m_dwStartOffset; - } - - DWORD GetEndOffset() - { - return m_dwEndOffset; - } - - DWORD GetStartAddress() - { - return m_pCode->GetRVA() + GetStartOffset(); - } - - DWORD GetEndAddress() - { - return m_pCode->GetRVA() + GetEndOffset(); - } - // Used to set unwind data lazily - void SetUnwindData(ZapNode * pUnwindData) - { - _ASSERTE(m_pUnwindData == NULL); - m_pUnwindData = pUnwindData; - } - - ZapNode * GetUnwindData() - { - return m_pUnwindData; - } - - void SetNextFragment(ZapUnwindInfo * pFragment) - { - _ASSERTE(m_pNextFragment == NULL); - m_pNextFragment = pFragment; - } - - ZapUnwindInfo * GetNextFragment() - { - return m_pNextFragment; - } - - virtual UINT GetAlignment() - { - return sizeof(ULONG); - } - - virtual DWORD GetSize() - { - return sizeof(T_RUNTIME_FUNCTION); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_UnwindInfo; - } - - virtual void Save(ZapWriter * pZapWriter); - - static int __cdecl CompareUnwindInfo(const void * a, const void * b); -}; - -#ifdef FEATURE_EH_FUNCLETS -//--------------------------------------------------------------------------------------- -// -// Zapping of unwind data -// -class ZapUnwindData : public ZapBlob -{ -public: - ZapUnwindData(SIZE_T cbSize) - : ZapBlob(cbSize) - { - } - - virtual UINT GetAlignment(); - - virtual DWORD GetSize(); - - virtual ZapNodeType GetType() - { - return ZapNodeType_UnwindData; - } - - BOOL IsFilterFunclet() - { - return GetType() == ZapNodeType_FilterFuncletUnwindData; - } - - ZapNode * GetPersonalityRoutine(ZapImage * pImage); - virtual void Save(ZapWriter * pZapWriter); - - static ZapUnwindData * NewUnwindData(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, BOOL fIsFilterFunclet); -}; - -class ZapFilterFuncletUnwindData : public ZapUnwindData -{ -public: - ZapFilterFuncletUnwindData(SIZE_T cbSize) - : ZapUnwindData(cbSize) - { - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_FilterFuncletUnwindData; - } -}; -class ZapUnwindDataTable -{ - ZapImage * m_pImage; - - struct ZapUnwindDataKey - { - ZapUnwindDataKey(PVOID pUnwindData, SIZE_T cbUnwindData, BOOL fIsFilterFunclet) - : m_unwindData(pUnwindData, cbUnwindData), m_fIsFilterFunclet(fIsFilterFunclet) - { - } - - ZapBlob::SHashKey m_unwindData; - BOOL m_fIsFilterFunclet; - }; - - class ZapUnwindDataTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef ZapUnwindDataKey key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return ZapUnwindDataKey(e->GetData(), e->GetBlobSize(), e->IsFilterFunclet()); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return ZapBlob::SHashTraits::Equals(k1.m_unwindData, k2.m_unwindData) && (k1.m_fIsFilterFunclet == k2.m_fIsFilterFunclet); - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return ZapBlob::SHashTraits::Hash(k.m_unwindData) ^ k.m_fIsFilterFunclet; - } - - static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } - }; - // Hashtable with all unwind data blobs. If two methods have unwind data - // we store it just once. - SHash< ZapUnwindDataTraits > m_blobs; - -public: - ZapUnwindDataTable(ZapImage * pImage) - : m_pImage(pImage) - { - } - - void Preallocate(COUNT_T cbILImage) - { - PREALLOCATE_HASHTABLE(ZapUnwindDataTable::m_blobs, 0.0003, cbILImage); - } - - ZapUnwindData * GetUnwindData(PVOID pBlob, SIZE_T cbBlob, BOOL fIsFilterFunclet); -}; -#endif // FEATURE_EH_FUNCLETS - - -//--------------------------------------------------------------------------------------- -// -// Zapping of GC info -// -#ifdef FEATURE_EH_FUNCLETS -class ZapGCInfo : public ZapUnwindData -{ - DWORD m_cbGCInfo; - -public: - ZapGCInfo(SIZE_T cbGCInfo, SIZE_T cbUnwindInfo) - : ZapUnwindData(cbUnwindInfo), m_cbGCInfo((DWORD)cbGCInfo) - { - if (m_cbGCInfo > ZAPWRITER_MAX_SIZE) - ThrowHR(COR_E_OVERFLOW); - } - - virtual PBYTE GetData() - { - return (PBYTE)(this + 1); - } - - PBYTE GetGCInfo() - { - return GetData() + GetUnwindInfoSize(); - } - - DWORD GetGCInfoSize() - { - return m_cbGCInfo; - } - - PBYTE GetUnwindInfo() - { - return GetData(); - } - - DWORD GetUnwindInfoSize() - { - return GetBlobSize(); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_UnwindDataAndGCInfo; - } - - virtual DWORD GetSize() - { - return ZapUnwindData::GetSize() + m_cbGCInfo; - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapUnwindData::Save(pZapWriter); - - pZapWriter->Write(GetGCInfo(), GetGCInfoSize()); - } - - static ZapGCInfo * NewGCInfo(ZapWriter * pWriter, PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo); -}; - -class ZapGCInfoTable -{ - ZapImage * m_pImage; - - struct GCInfoKey - { - GCInfoKey(PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo) - : m_gcInfo(pGCInfo, cbGCInfo), m_unwindInfo(pUnwindInfo, cbUnwindInfo) - { - } - - ZapBlob::SHashKey m_gcInfo; - ZapBlob::SHashKey m_unwindInfo; - }; - - class GCInfoTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef GCInfoKey key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return GCInfoKey(e->GetGCInfo(), e->GetGCInfoSize(), e->GetUnwindInfo(), e->GetUnwindInfoSize()); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return ZapBlob::SHashTraits::Equals(k1.m_gcInfo, k2.m_gcInfo) && ZapBlob::SHashTraits::Equals(k1.m_unwindInfo, k2.m_unwindInfo); - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return ZapBlob::SHashTraits::Hash(k.m_gcInfo) ^ ZapBlob::SHashTraits::Hash(k.m_unwindInfo); - } - - static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } - }; - - // Hashtable with all GC info blobs. If two methods have same GC info - // we store it just once. - SHash< GCInfoTraits > m_blobs; - -public: - ZapGCInfoTable(ZapImage * pImage) - : m_pImage(pImage) - { - } - - void Preallocate(COUNT_T cbILImage) - { - PREALLOCATE_HASHTABLE(ZapGCInfoTable::m_blobs, 0.0021, cbILImage); - } - - // Returns interned instance of the GC info blob - ZapGCInfo * GetGCInfo(PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo); -}; -#else -class ZapGCInfoTable -{ - ZapImage * m_pImage; - - // Hashtable with all GC info blobs. If two methods have same GC info - // we store it just once. - SHash< NoRemoveSHashTraits < ZapBlob::SHashTraits > > m_blobs; - -public: - ZapGCInfoTable(ZapImage * pImage) - : m_pImage(pImage) - { - } - - void Preallocate(COUNT_T cbILImage) - { - PREALLOCATE_HASHTABLE(ZapGCInfoTable::m_blobs, 0.0021, cbILImage); - } - - // Returns interned instance of the GC info blob - ZapGCInfo * GetGCInfo(PVOID pBlob, SIZE_T cbBlob); -}; -#endif - -//--------------------------------------------------------------------------------------- -// -// Zapping of debug info for native code -// -class ZapDebugInfoTable : public ZapNode -{ - COUNT_T m_nCount; - ZapNode ** m_pTable; - - ZapImage * m_pImage; - - // Hashtable with all debug info blobs. If two methods have same debug info - // we store it just once. - SHash< NoRemoveSHashTraits < ZapBlob::SHashTraits > > m_blobs; - - class LabelledEntry : public ZapNode - { - public: - LabelledEntry * m_pNext; - ZapMethodHeader * m_pMethod; - - LabelledEntry(ZapMethodHeader * pMethod) - : m_pMethod(pMethod) - { - } - - virtual DWORD GetSize() - { - return sizeof(CORCOMPILE_DEBUG_LABELLED_ENTRY); - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_DebugInfoLabelledEntry; - } - - virtual void Save(ZapWriter * pZapWriter); - }; - -public: - ZapDebugInfoTable(ZapImage * pImage) - : m_pImage(pImage) - { - } - - void Preallocate(COUNT_T cbILImage) - { - PREALLOCATE_HASHTABLE(ZapDebugInfoTable::m_blobs, 0.0024, cbILImage); - } - - // Returns interned instance of the debug info blob - ZapDebugInfo * GetDebugInfo(PVOID pBlob, SIZE_T cbBlob); - - void PrepareLayout(); - void PlaceDebugInfo(ZapMethodHeader * pMethod); - void FinishLayout(); - - virtual DWORD GetSize() - { - return m_nCount * sizeof(CORCOMPILE_DEBUG_RID_ENTRY); - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_DebugInfoTable; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -//--------------------------------------------------------------------------------------- -// -// Zapping of IBC profile data collection area -// -class ZapProfileData : public ZapNode -{ - ZapMethodHeader * m_pMethod; - ZapProfileData * m_pNext; - -public: - ZapProfileData(ZapMethodHeader * pMethod) - : m_pMethod(pMethod) - { - } - - void SetNext(ZapProfileData * pNext) - { - m_pNext = pNext; - } - - virtual DWORD GetSize() - { - return sizeof(CORCOMPILE_METHOD_PROFILE_LIST); - } - - virtual UINT GetAlignment() - { - return TARGET_POINTER_SIZE; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_ProfileData; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -// Zapping of ExceptionInfoTable -// ExceptionInfoTable is a lookup table that has 1 entry for each method with EH information. -// The table is sorted by method start address, so binary search is used during runtime to find -// the EH info for a given method given a method start address. -class ZapExceptionInfoLookupTable : public ZapNode -{ -private: - typedef struct - { - ZapNode* m_pCode; - ZapExceptionInfo* m_pExceptionInfo; - } ExceptionInfoEntry; - - SArray m_exceptionInfoEntries; - ZapImage* m_pImage; -public: - ZapExceptionInfoLookupTable(ZapImage *pImage); - - void PlaceExceptionInfoEntry(ZapNode* pCode, ZapExceptionInfo* pExceptionInfo); - - virtual ZapNodeType GetType() - { - return ZapNodeType_ExceptionInfoTable; - } - virtual UINT GetAlignment() - { - return TARGET_POINTER_SIZE; - } - virtual DWORD GetSize(); - virtual void Save(ZapWriter* pZapWriter); -}; - - -class ZapUnwindInfoLookupTable : public ZapNode -{ - -public: - ZapUnwindInfoLookupTable(ZapVirtualSection * pRuntimeFunctionSection, ZapNode * pCodeSection, DWORD totalCodeSize): - m_pRuntimeFunctionSection(pRuntimeFunctionSection), m_pCodeSection(pCodeSection), m_TotalCodeSize(totalCodeSize) - { - } - - COUNT_T GetNumEntries() - { - return m_TotalCodeSize/RUNTIME_FUNCTION_LOOKUP_STRIDE + 1; - } - virtual ZapNodeType GetType() - { - return ZapNodeType_UnwindInfoLookupTable; - } - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - virtual DWORD GetSize(); - virtual void Save(ZapWriter* pZapWriter); - -private: - ZapVirtualSection * m_pRuntimeFunctionSection; - ZapNode * m_pCodeSection; - DWORD m_TotalCodeSize; -}; - -class ZapColdCodeMap : public ZapNode -{ -public: - ZapColdCodeMap(ZapVirtualSection * pRuntimeFunctionSection): - m_pRuntimeFunctionSection (pRuntimeFunctionSection) - { - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_ColdCodeMap; - } - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - virtual DWORD GetSize(); - virtual void Save(ZapWriter* pZapWriter); - -private: - ZapVirtualSection * m_pRuntimeFunctionSection; -}; - -// -//--------------------------------------------------------------------------------------- -// -// Jump thunk for JIT helper -// -#ifdef _DEBUG -const static PCSTR s_rgHelperNames[] = { -#define JITHELPER(code,pfnHelper,sig) #code , -#define DYNAMICJITHELPER(code,pfnHelper,sig) " " #code , -#include -}; -#endif // _DEBUG - -class ZapHelperThunk : public ZapNode -{ - DWORD m_dwHelper; - -public: - ZapHelperThunk(DWORD dwHelper) - : m_dwHelper(dwHelper) - { -#ifdef _DEBUG - static_assert_no_msg(COUNTOF(s_rgHelperNames) == CORINFO_HELP_COUNT); - LOG((LF_ZAP, LL_INFO1000000, "Created ZapHelperThunk for helper %3d (%s)\n", - (USHORT)m_dwHelper, s_rgHelperNames[(USHORT)m_dwHelper])); -#endif // _DEBUG - } - - virtual DWORD GetSize(); - - virtual ZapNodeType GetType() - { - return ZapNodeType_HelperThunk; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -class ZapLazyHelperThunk : public ZapNode -{ - CorInfoHelpFunc m_dwHelper; - - ZapNode * m_pArg; - ZapNode * m_pTarget; - - DWORD SaveWorker(ZapWriter * pZapWriter); - -public: - ZapLazyHelperThunk(CorInfoHelpFunc dwHelper) - : m_dwHelper(dwHelper) - { - } - - void Place(ZapImage * pImage); - - virtual DWORD GetSize(); - - virtual ZapNodeType GetType() - { - return ZapNodeType_LazyHelperThunk; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -#endif // __ZAPCODE_H__ diff --git a/src/coreclr/zap/zapheaders.cpp b/src/coreclr/zap/zapheaders.cpp deleted file mode 100644 index f416e5a2884a9d..00000000000000 --- a/src/coreclr/zap/zapheaders.cpp +++ /dev/null @@ -1,720 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapHeaders.cpp -// - -// -// Zapping of headers (IMAGE_COR20_HEADER, CORCOMPILE_HEADER, etc.) -// -// ====================================================================================== - -#include "common.h" - -#include "zapheaders.h" - -#include "zapcode.h" -#include "zaprelocs.h" -#include "zapmetadata.h" -#include "zapimport.h" - -#include -#include - -// -// IMAGE_COR20_HEADER -// - -void ZapImage::SaveCorHeader() -{ - IMAGE_COR20_HEADER corHeader; - - ZeroMemory(&corHeader, sizeof(corHeader)); - - corHeader.cb = VAL32(sizeof(IMAGE_COR20_HEADER)); - corHeader.MajorRuntimeVersion = VAL16(COR_VERSION_MAJOR); - corHeader.MinorRuntimeVersion = VAL16(COR_VERSION_MINOR); - corHeader.Flags = VAL32(COMIMAGE_FLAGS_IL_LIBRARY); - -#ifdef TARGET_X86 - if (IsReadyToRunCompilation()) - { - // Mark the ready-to-run image as x86-specific - corHeader.Flags |= VAL32(COMIMAGE_FLAGS_32BITREQUIRED); - } -#endif - - if (m_ModuleDecoder.HasManagedEntryPoint()) - corHeader.EntryPointToken = VAL32(m_ModuleDecoder.GetEntryPointToken()); - - SetDirectoryData(&corHeader.ManagedNativeHeader, m_pNativeHeader); - SetDirectoryData(&corHeader.Resources, m_pResources); - SetDirectoryData(&corHeader.MetaData, m_pILMetaData); - - Write(&corHeader, sizeof(corHeader)); -} - -// -// CORCOMPILE_HEADER -// -void ZapImage::SaveNativeHeader() -{ - CORCOMPILE_HEADER nativeHeader; - - ZeroMemory(&nativeHeader, sizeof(nativeHeader)); - - nativeHeader.Signature = CORCOMPILE_SIGNATURE; - nativeHeader.MajorVersion = CORCOMPILE_MAJOR_VERSION; - nativeHeader.MinorVersion = CORCOMPILE_MINOR_VERSION; - - // - // Fill in data in native image header - // - - nativeHeader.ImageBase = (TADDR) GetNativeBaseAddress(); - - if (m_ModuleDecoder.HasDirectoryEntry(IMAGE_DIRECTORY_ENTRY_SECURITY)) - nativeHeader.Flags |= CORCOMPILE_HEADER_HAS_SECURITY_DIRECTORY; - - nativeHeader.COR20Flags = m_ModuleDecoder.GetCorHeader()->Flags; - -#ifdef CROSSGEN_COMPILE - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_CrossGenAssumeInputSigned)) - { - // Bug fix #814972 - // In buildlabs NI images are produced before binaries are strongname signed or authenticode signed. - // which results in crossgen'ed NI different on the user box vs. the one from build lab. - // Setting source IL authenticode signed and strong name bit for crossgen'ed images should make both the images identical. - nativeHeader.Flags |= CORCOMPILE_HEADER_HAS_SECURITY_DIRECTORY; - - if (m_ModuleDecoder.GetCorHeader()->StrongNameSignature.Size != 0) - nativeHeader.COR20Flags |= COMIMAGE_FLAGS_STRONGNAMESIGNED; - } -#endif - - if (m_ModuleDecoder.HasReadyToRunHeader()) - { - // Pretend that ready-to-run images are IL-only - nativeHeader.COR20Flags |= COMIMAGE_FLAGS_ILONLY; - - // Pretend that ready-to-run images do not have a native header - nativeHeader.COR20Flags &= ~COMIMAGE_FLAGS_IL_LIBRARY; - - // Remember whether the source IL image had ReadyToRun header - nativeHeader.Flags |= CORCOMPILE_HEADER_IS_READY_TO_RUN; - } - - if (m_fHaveProfileData) - nativeHeader.Flags |= CORCOMPILE_HEADER_IS_IBC_OPTIMIZED; - - DWORD dwPEKind, dwMachine; - m_ModuleDecoder.GetPEKindAndMachine(&dwPEKind, &dwMachine); - nativeHeader.PEKind = dwPEKind; - nativeHeader.Machine = (WORD)dwMachine; - - nativeHeader.Characteristics = m_ModuleDecoder.GetCharacteristics(); - - - SetDirectoryData(&nativeHeader.EEInfoTable, m_pEEInfoTable); - SetDirectoryData(&nativeHeader.HelperTable, m_pHelperTableSection); - SetDirectoryData(&nativeHeader.ImportSections, m_pImportSectionsTable); - SetDirectoryData(&nativeHeader.StubsData, m_pStubsSection); - SetDirectoryData(&nativeHeader.VersionInfo, m_pVersionInfo); - SetDirectoryData(&nativeHeader.Dependencies, m_pDependencies); - SetDirectoryData(&nativeHeader.DebugMap, m_pDebugInfoTable); - SetDirectoryData(&nativeHeader.VirtualSectionsTable, m_pVirtualSectionsTable); - SetDirectoryData(&nativeHeader.ModuleImage, m_pPreloadSections[CORCOMPILE_SECTION_MODULE]); - SetDirectoryData(&nativeHeader.CodeManagerTable, m_pCodeManagerEntry); - SetDirectoryData(&nativeHeader.ProfileDataList, m_pInstrumentSection); - SetDirectoryData(&nativeHeader.ManifestMetaData, m_pAssemblyMetaData); - - Write(&nativeHeader, sizeof(nativeHeader)); -} - -// -// CORCOMPILE_CODE_MANAGER_ENTRY -// -void ZapImage::SaveCodeManagerEntry() -{ - CORCOMPILE_CODE_MANAGER_ENTRY codeManagerEntry; - - ZeroMemory(&codeManagerEntry, sizeof(codeManagerEntry)); - - SetDirectoryData(&codeManagerEntry.HotCode, m_pHotCodeSection); - SetDirectoryData(&codeManagerEntry.Code, m_pCodeSection); - SetDirectoryData(&codeManagerEntry.ColdCode, m_pColdCodeSection); - - SetDirectoryData(&codeManagerEntry.ROData, m_pReadOnlyDataSection); - - // - //Initialize additional sections for diagnostics - // - - codeManagerEntry.HotIBCMethodOffset = (m_iIBCMethod < m_iUntrainedMethod && m_iIBCMethod < m_MethodCompilationOrder.GetCount()) ? - (m_MethodCompilationOrder[m_iIBCMethod]->GetCode()->GetRVA() - m_pHotCodeSection->GetRVA()) : m_pHotCodeSection->GetSize(); - - codeManagerEntry.HotGenericsMethodOffset = (m_iGenericsMethod < m_iUntrainedMethod && m_iGenericsMethod < m_MethodCompilationOrder.GetCount()) ? - (m_MethodCompilationOrder[m_iGenericsMethod]->GetCode()->GetRVA() - m_pHotCodeSection->GetRVA()) : m_pHotCodeSection->GetSize(); - - COUNT_T i; - for (i = m_iUntrainedMethod; i < m_MethodCompilationOrder.GetCount(); i++) - { - ZapNode * pColdCode = m_MethodCompilationOrder[i]->GetColdCode(); - if (pColdCode != NULL) - { - codeManagerEntry.ColdUntrainedMethodOffset = pColdCode->GetRVA() - m_pColdCodeSection->GetRVA(); - break; - } - } - if (i == m_MethodCompilationOrder.GetCount()) - codeManagerEntry.ColdUntrainedMethodOffset = m_pColdCodeSection->GetSize(); - - - if (m_stats) - { -#define ACCUM_SIZE(dest, src) if( src != NULL ) dest+= src->GetSize() - // this is probably supposed to mean Hot+Unprofiled - ACCUM_SIZE(m_stats->m_totalHotCodeSize, m_pHotCodeSection); - ACCUM_SIZE(m_stats->m_totalUnprofiledCodeSize, m_pCodeSection); - ACCUM_SIZE(m_stats->m_totalColdCodeSize, m_pColdCodeSection); - ACCUM_SIZE(m_stats->m_totalCodeSizeInProfiledMethods, m_pHotCodeSection); -#undef ACCUM_SIZE - m_stats->m_totalColdCodeSizeInProfiledMethods = codeManagerEntry.ColdUntrainedMethodOffset; - } - - Write(&codeManagerEntry, sizeof(codeManagerEntry)); -} - -// -// Version Resource -// - -// Needed for RT_VERSION. -#define MAKEINTRESOURCE(v) MAKEINTRESOURCEW(v) - -void ZapWin32ResourceDirectory::Save(ZapWriter * pZapWriter) -{ - // - // The IMAGE_RESOURCE_DIRECTORY resource data structure is followed by a number of IMAGE_RESOURCE_DIRECTORY_ENTRY entries, which can either - // point to other resource directories (RVAs to other ZapWin32ResourceDirectory nodes), or point to actual resource data (RVAs to a number - // of IMAGE_RESOURCE_DATA_ENTRY entries that immediately follow the IMAGE_RESOURCE_DIRECTORY_ENTRY entries). - // - - // - // Sorting for resources is done in the following way accoring to the PE format specifications: - // 1) First, all the IMAGE_RESOURCE_DIRECTORY_ENTRY entries where the ID is a name string, sorted by names - // 2) Second, all the IMAGE_RESOURCE_DIRECTORY_ENTRY entries with non-string IDs, sorted by IDs. - // - struct ResourceSorter - { - bool operator() (DataOrSubDirectoryEntry& a, DataOrSubDirectoryEntry& b) - { - if (a.m_nameOrIdIsString && !b.m_nameOrIdIsString) - return true; - if (!a.m_nameOrIdIsString && b.m_nameOrIdIsString) - return false; - if (a.m_nameOrIdIsString) - return wcscmp(((ZapWin32ResourceString*)(a.m_pNameOrId))->GetString(), ((ZapWin32ResourceString*)(b.m_pNameOrId))->GetString()) < 0; - else - return a.m_pNameOrId < b.m_pNameOrId; - } - } resourceSorter; - std::sort(m_entries.begin(), m_entries.end(), resourceSorter); - - - IMAGE_RESOURCE_DIRECTORY directory; - ZeroMemory(&directory, sizeof(IMAGE_RESOURCE_DIRECTORY)); - - for (auto& entry : m_entries) - { - if (entry.m_nameOrIdIsString) - directory.NumberOfNamedEntries++; - else - directory.NumberOfIdEntries++; - } - pZapWriter->Write(&directory, sizeof(IMAGE_RESOURCE_DIRECTORY)); - - // Offsets are based from the beginning of the resources blob (see PE format documentation) - DWORD dataEntryRVA = this->GetRVA() - m_pWin32ResourceSection->GetRVA() - + sizeof(IMAGE_RESOURCE_DIRECTORY) + - (DWORD)m_entries.size() * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY); - - for (auto& entry : m_entries) - { - IMAGE_RESOURCE_DIRECTORY_ENTRY dirEntry; - ZeroMemory(&dirEntry, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY)); - - if (entry.m_nameOrIdIsString) - { - // Offsets are based from the beginning of the resources blob (see PE format documentation) - dirEntry.NameOffset = ((ZapWin32ResourceString*)(entry.m_pNameOrId))->GetRVA() - m_pWin32ResourceSection->GetRVA(); - dirEntry.NameIsString = true; - } - else - { - _ASSERT(IS_INTRESOURCE(entry.m_pNameOrId)); - dirEntry.Id = (WORD)((ULONG_PTR)entry.m_pNameOrId & 0xffff); - } - - if (entry.m_dataIsSubDirectory) - { - // Offsets are based from the beginning of the resources blob (see PE format documentation) - dirEntry.OffsetToDirectory = entry.m_pDataOrSubDirectory->GetRVA() - m_pWin32ResourceSection->GetRVA(); - dirEntry.DataIsDirectory = true; - } - else - { - dirEntry.OffsetToData = dataEntryRVA; - dataEntryRVA += sizeof(IMAGE_RESOURCE_DATA_ENTRY); - } - - pZapWriter->Write(&dirEntry, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY)); - } - - for (auto& entry : m_entries) - { - if (entry.m_dataIsSubDirectory) - continue; - - IMAGE_RESOURCE_DATA_ENTRY dataEntry; - ZeroMemory(&dataEntry, sizeof(IMAGE_RESOURCE_DATA_ENTRY)); - - dataEntry.OffsetToData = entry.m_pDataOrSubDirectory->GetRVA(); - dataEntry.Size = entry.m_pDataOrSubDirectory->GetSize(); - - pZapWriter->Write(&dataEntry, sizeof(IMAGE_RESOURCE_DATA_ENTRY)); - } -} - -void ZapImage::CopyWin32Resources() -{ -#ifdef FEATURE_PREJIT - if (!IsReadyToRunCompilation()) - { - // When compiling a fragile NGEN image, in order to avoid the risk of regression, only copy the RT_VERSION resource over so it - // is easy to see in the dumps where the ngened module came from. For R2R, we copy all resources (new behavior). - COUNT_T cbResourceData; - PVOID pResourceData = m_ModuleDecoder.GetWin32Resource(MAKEINTRESOURCE(1), RT_VERSION, &cbResourceData); - - if (!pResourceData || !cbResourceData) - return; - - ZapBlob * pVersionData = new (GetHeap()) ZapBlobPtr(pResourceData, cbResourceData); - - ZapWin32ResourceDirectory* pTypeDirectory = new (GetHeap()) ZapWin32ResourceDirectory(m_pWin32ResourceSection); - ZapWin32ResourceDirectory* pNameDirectory = new (GetHeap()) ZapWin32ResourceDirectory(m_pWin32ResourceSection); - ZapWin32ResourceDirectory* pLanguageDirectory = new (GetHeap()) ZapWin32ResourceDirectory(m_pWin32ResourceSection); - - pTypeDirectory->AddEntry(RT_VERSION, false, pNameDirectory, true); - pNameDirectory->AddEntry(MAKEINTRESOURCE(1), false, pLanguageDirectory, true); - pLanguageDirectory->AddEntry(MAKEINTRESOURCE(0), false, pVersionData, false); - - pTypeDirectory->PlaceNodeAndDependencies(m_pWin32ResourceSection); - - m_pWin32ResourceSection->Place(pVersionData); - - SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_RESOURCE, m_pWin32ResourceSection); - - return; - } -#endif - - class ResourceEnumerationCallback - { - ZapImage* m_pZapImage; - PEDecoder* m_pModuleDecoder; - - std::vector m_dataEntries; - std::vector m_stringEntries; - - ZapWin32ResourceDirectory* m_pRootDirectory; - ZapWin32ResourceDirectory* m_pCurrentTypesDirectory; - ZapWin32ResourceDirectory* m_pCurrentNamesDirectory; - - bool AddResource(LPCWSTR lpszResourceName, LPCWSTR lpszResourceType, DWORD langID, BYTE* pResourceData, COUNT_T cbResourceData) - { - ZapBlob* pDataBlob = new (m_pZapImage->GetHeap()) ZapBlobPtr(pResourceData, cbResourceData); - m_dataEntries.push_back(pDataBlob); - - m_pCurrentNamesDirectory->AddEntry((PVOID)(ULONG_PTR)langID, false, pDataBlob, false); - - return true; - } - - ZapWin32ResourceDirectory* CreateResourceSubDirectory(ZapWin32ResourceDirectory* pRootDir, LPCWSTR pNameOrId) - { - bool nameIsString = !IS_INTRESOURCE(pNameOrId); - - PVOID pIdOrNameZapNode = (PVOID)pNameOrId; - if (nameIsString) - { - pIdOrNameZapNode = new (m_pZapImage->GetHeap()) ZapWin32ResourceString(pNameOrId); - m_stringEntries.push_back((ZapBlob*)pIdOrNameZapNode); - } - - ZapWin32ResourceDirectory* pResult = new (m_pZapImage->GetHeap()) ZapWin32ResourceDirectory(m_pZapImage->m_pWin32ResourceSection); - pRootDir->AddEntry(pIdOrNameZapNode, nameIsString, pResult, true); - - return pResult; - } - - public: - ResourceEnumerationCallback(PEDecoder* pModuleDecoder, ZapImage* pZapImage) - : m_pZapImage(pZapImage), m_pModuleDecoder(pModuleDecoder) - { - m_pRootDirectory = new (pZapImage->GetHeap()) ZapWin32ResourceDirectory(pZapImage->m_pWin32ResourceSection); - m_pCurrentTypesDirectory = m_pCurrentNamesDirectory = NULL; - } - - static bool EnumResourcesCallback(LPCWSTR lpszResourceName, LPCWSTR lpszResourceType, DWORD langID, BYTE* data, COUNT_T cbData, void *context) - { - ResourceEnumerationCallback* pCallback = (ResourceEnumerationCallback*)context; - // Third level in the enumeration: resources by langid for each name/type. - - // Note that this callback is not equivalent to the Windows enumeration apis as this api provides the resource data - // itself, and the resources are guaranteed to be present directly in the associated binary. This does not exactly - // match the Windows api, but it is exactly what we want when copying all resource data. - - return pCallback->AddResource(lpszResourceName, lpszResourceType, langID, data, cbData); - } - - static bool EnumResourceNamesCallback(LPCWSTR lpszResourceName, LPCWSTR lpszResourceType, void *context) - { - // Second level in the enumeration: resources by names for each resource type - - ResourceEnumerationCallback* pCallback = (ResourceEnumerationCallback*)context; - pCallback->m_pCurrentNamesDirectory = pCallback->CreateResourceSubDirectory(pCallback->m_pCurrentTypesDirectory, lpszResourceName); - - return pCallback->m_pModuleDecoder->EnumerateWin32Resources(lpszResourceName, lpszResourceType, ResourceEnumerationCallback::EnumResourcesCallback, context); - } - - static bool EnumResourceTypesCallback(LPCWSTR lpszType, void *context) - { - // First level in the enumeration: resources by types - - // Skip IBC resources - if (!IS_INTRESOURCE(lpszType) && (wcscmp(lpszType, W("IBC")) == 0)) - return true; - - ResourceEnumerationCallback* pCallback = (ResourceEnumerationCallback*)context; - pCallback->m_pCurrentTypesDirectory = pCallback->CreateResourceSubDirectory(pCallback->m_pRootDirectory, lpszType); - - return pCallback->m_pModuleDecoder->EnumerateWin32ResourceNames(lpszType, ResourceEnumerationCallback::EnumResourceNamesCallback, context); - } - - void PlaceResourceNodes(ZapVirtualSection* pWin32ResourceSection) - { - m_pRootDirectory->PlaceNodeAndDependencies(pWin32ResourceSection); - - // - // These strings are stored together after the last Resource Directory entry and before the first Resource Data entry. This - // minimizes the impact of these variable-length strings on the alignment of the fixed-size directory entries - // - for (auto& entry : m_stringEntries) - pWin32ResourceSection->Place(entry); - - for (auto& entry : m_dataEntries) - pWin32ResourceSection->Place(entry); - } - }; - - ResourceEnumerationCallback callbacks(&m_ModuleDecoder, this); - - HMODULE hModule = (HMODULE)dac_cast(m_ModuleDecoder.GetBase()); - - // - // Resources are binary-sorted tree structure. By convention, Windows uses three levels - // for resources: Type, Name, Language. To reduces the overall complexity, we'll copy and store resources in the - // "neutral" language only. - // - - if (!m_ModuleDecoder.EnumerateWin32ResourceTypes(ResourceEnumerationCallback::EnumResourceTypesCallback, &callbacks)) - { - ThrowHR(E_FAIL); - } - else - { - callbacks.PlaceResourceNodes(m_pWin32ResourceSection); - - SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_RESOURCE, m_pWin32ResourceSection); - } -} -#undef MAKEINTRESOURCE - - -// -// Debug Directory -// - -void ZapDebugDirectory::SaveOriginalDebugDirectoryEntry(ZapWriter *pZapWriter) -{ - if (m_ppDebugData != nullptr) - { - for (DWORD i = 0; i < m_nDebugDirectory; i++) - { - if (m_ppDebugData[i] != nullptr) - { - m_pDebugDirectory[i].SizeOfData = m_ppDebugData[i]->GetSize(); - m_pDebugDirectory[i].AddressOfRawData = m_ppDebugData[i]->GetRVA(); - - // Compute the absolute file (seek) pointer. We need to reach to the matching physical section to do that. - ZapPhysicalSection * pPhysicalSection = ZapImage::GetImage(pZapWriter)->m_pTextSection; - - DWORD dwOffset = m_ppDebugData[i]->GetRVA() - pPhysicalSection->GetRVA(); - _ASSERTE(dwOffset < pPhysicalSection->GetSize()); - - m_pDebugDirectory[i].PointerToRawData = pPhysicalSection->GetFilePos() + dwOffset; - } - else - { - m_pDebugDirectory[i].SizeOfData = 0; - m_pDebugDirectory[i].AddressOfRawData = 0; - m_pDebugDirectory[i].PointerToRawData = 0; - } - } - - pZapWriter->Write(m_pDebugDirectory, sizeof(IMAGE_DEBUG_DIRECTORY) * m_nDebugDirectory); - } -} - -void ZapDebugDirectory::SaveNGenDebugDirectoryEntry(ZapWriter *pZapWriter) -{ -#if !defined(NO_NGENPDB) - _ASSERTE(pZapWriter); - - IMAGE_DEBUG_DIRECTORY debugDirectory = {0}; - if (m_nDebugDirectory > 0) - { - memcpy(&debugDirectory, m_pDebugDirectory, sizeof(IMAGE_DEBUG_DIRECTORY)); - } - debugDirectory.Type = IMAGE_DEBUG_TYPE_CODEVIEW; - debugDirectory.SizeOfData = m_pNGenPdbDebugData->GetSize(); - debugDirectory.AddressOfRawData = m_pNGenPdbDebugData->GetRVA(); - // Make sure the "is portable pdb" indicator (MinorVersion == 0x504d) is clear - // for the NGen debug directory entry since this debug directory is copied - // from an existing entry which could be a portable pdb. - debugDirectory.MinorVersion = 0; - { - ZapPhysicalSection *pPhysicalSection = ZapImage::GetImage(pZapWriter)->m_pTextSection; - DWORD dwOffset = m_pNGenPdbDebugData->GetRVA() - pPhysicalSection->GetRVA(); - _ASSERTE(dwOffset < pPhysicalSection->GetSize()); - debugDirectory.PointerToRawData = pPhysicalSection->GetFilePos() + dwOffset; - } - pZapWriter->Write(&debugDirectory, sizeof(debugDirectory)); -#endif // NO_NGENPDB -} - -void ZapDebugDirectory::Save(ZapWriter * pZapWriter) -{ - _ASSERTE(pZapWriter); - - if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_NGenEnableCreatePdb)) { - SaveOriginalDebugDirectoryEntry(pZapWriter); - SaveNGenDebugDirectoryEntry(pZapWriter); - } else { - SaveNGenDebugDirectoryEntry(pZapWriter); - SaveOriginalDebugDirectoryEntry(pZapWriter); - } -} - -ZapPEExports::ZapPEExports(LPCWSTR dllPath) -{ - m_dllFileName = wcsrchr(dllPath, DIRECTORY_SEPARATOR_CHAR_W); - if (m_dllFileName != NULL) - m_dllFileName++; - else - m_dllFileName = dllPath; -} - -DWORD ZapPEExports::GetSize() -{ - return DWORD(sizeof(IMAGE_EXPORT_DIRECTORY) + wcslen(m_dllFileName) * sizeof(BYTE) + 1); -} - -void ZapPEExports::Save(ZapWriter * pZapWriter) -{ - _ASSERTE(pZapWriter); - - IMAGE_EXPORT_DIRECTORY exports; - ZeroMemory(&exports, sizeof(exports)); - - exports.Name = pZapWriter->GetCurrentRVA() + sizeof(exports); - - // Write out exports header - pZapWriter->Write(&exports, sizeof(exports)); - - // Write out string that exports.Name points at. - for (LPCWSTR ptr = m_dllFileName; ; ptr++) - { - pZapWriter->Write((PVOID) ptr, 1); - if (*ptr == 0) - break; - } -} - -// If the IL image has IMAGE_DIRECTORY_ENTRY_DEBUG with information about the PDB, -// copy that information over to the ngen image. -// This lets the debugger find out information about the PDB without loading -// the IL image. -// Note that we support using ngen images (from the GAC) without -// loading the ngen image. So not only is this a perf optimization for the debugger -// scenario, but it is also needed for dump-debugging where loading the IL -// is not an option. - -void ZapImage::CopyDebugDirEntry() -{ - // Insert an NGEN PDB debug directory entry *before* the IL PDB debug directory entry - // (if one exists), so that we don't break tools that look for an IL PDB. - { - // This entry is initially empty. It is filled in ZapImage::GenerateFile. - RSDS rsds = {0}; - m_pNGenPdbDebugData = ZapBlob::NewBlob(static_cast(this), &rsds, sizeof rsds); - } - - // IL PDB entry: copy of the (first of possibly many) IMAGE_DEBUG_DIRECTORY entry - // in the IL image - DWORD nDebugEntry = 0; - PIMAGE_DEBUG_DIRECTORY pDebugDir = NULL; - ZapNode **ppDebugData = NULL; - - if (m_ModuleDecoder.HasDirectoryEntry(IMAGE_DIRECTORY_ENTRY_DEBUG)) { - COUNT_T debugEntrySize; - TADDR pDebugEntry = m_ModuleDecoder.GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_DEBUG, &debugEntrySize); - - if (debugEntrySize != 0) { - - if (debugEntrySize < sizeof(IMAGE_DEBUG_DIRECTORY) || 0 != (debugEntrySize % sizeof(IMAGE_DEBUG_DIRECTORY))) { - m_zapper->Warning(W("IMAGE_DIRECTORY_ENTRY_DEBUG size (%d) should be a multiple of %d\n"), - debugEntrySize, sizeof(IMAGE_DEBUG_DIRECTORY)); - } else { - - // Since pDebugEntry is an array of IMAGE_DEBUG_DIRECTORYs, debugEntrySize - // should be a multiple of sizeof(IMAGE_DEBUG_DIRECTORY). - _ASSERTE(0 == (debugEntrySize % sizeof(IMAGE_DEBUG_DIRECTORY))); - - nDebugEntry = DWORD(debugEntrySize / sizeof(IMAGE_DEBUG_DIRECTORY)); - pDebugDir = new (GetHeap()) IMAGE_DEBUG_DIRECTORY[nDebugEntry]; - memcpy(pDebugDir, (const void *)pDebugEntry, sizeof(IMAGE_DEBUG_DIRECTORY) * nDebugEntry); - ppDebugData = new (GetHeap()) ZapNode*[nDebugEntry]; - memset(ppDebugData, 0, nDebugEntry * sizeof(ZapNode*)); - - for (DWORD i = 0; i < nDebugEntry; i++) - { - // Some compilers set PointerToRawData but not AddressOfRawData as they put the - // data at the end of the file in an unmapped part of the file - - RVA rvaOfRawData = (pDebugDir[i].AddressOfRawData != NULL) - ? pDebugDir[i].AddressOfRawData : m_ModuleDecoder.OffsetToRva(pDebugDir[i].PointerToRawData); - - ULONG cbDebugData = pDebugDir[i].SizeOfData; - - if (cbDebugData != 0) { - if (!m_ModuleDecoder.CheckRva(rvaOfRawData, cbDebugData)) - m_zapper->Warning(W("IMAGE_DIRECTORY_ENTRY_DEBUG points to bad data\n")); - else - ppDebugData[i] = new (GetHeap()) ZapBlobPtr((PVOID)m_ModuleDecoder.GetRvaData(rvaOfRawData), cbDebugData); - } - } - } - } - } - - ZapDebugDirectory * pDebugDirectory = new (GetHeap()) ZapDebugDirectory(m_pNGenPdbDebugData, - nDebugEntry, - pDebugDir, - ppDebugData); - - m_pDebugSection->Place(pDebugDirectory); - m_pDebugSection->Place(m_pNGenPdbDebugData); - if (ppDebugData) - { - for (DWORD i = 0; i < nDebugEntry; i++) - { - if (ppDebugData[i] != nullptr) - m_pDebugSection->Place(ppDebugData[i]); - } - } - - SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_DEBUG, pDebugDirectory); -} - -DWORD ZapVirtualSectionsTable::GetSize() -{ - DWORD nSectionInfos = 0; - - COUNT_T nPhysicalSections = m_pImage->GetPhysicalSectionCount(); - for (COUNT_T iPhysicalSection = 0; iPhysicalSection < nPhysicalSections; iPhysicalSection++) - { - ZapPhysicalSection * pPhysicalSection = m_pImage->GetPhysicalSection(iPhysicalSection); - - DWORD dwPreviousType = 0; - - COUNT_T nVirtualSections = pPhysicalSection->GetVirtualSectionCount(); - for (COUNT_T iVirtualSection = 0; iVirtualSection < nVirtualSections; iVirtualSection++) - { - ZapVirtualSection * pVirtualSection = pPhysicalSection->GetVirtualSection(iVirtualSection); - - if (pVirtualSection->GetNodeCount() == 0) - continue; - - DWORD dwSectionType = pVirtualSection->GetSectionType(); - if (dwSectionType == 0) - continue; - - // Fold sections with the same type together - if (dwPreviousType != dwSectionType) - { - dwPreviousType = dwSectionType; - nSectionInfos++; - } - } - } - - return nSectionInfos * sizeof(CORCOMPILE_VIRTUAL_SECTION_INFO); -} - -void ZapVirtualSectionsTable::Save(ZapWriter * pZapWriter) -{ - COUNT_T nPhysicalSections = m_pImage->GetPhysicalSectionCount(); - for (COUNT_T iPhysicalSection = 0; iPhysicalSection < nPhysicalSections; iPhysicalSection++) - { - ZapPhysicalSection * pPhysicalSection = m_pImage->GetPhysicalSection(iPhysicalSection); - - CORCOMPILE_VIRTUAL_SECTION_INFO sectionInfo; - - sectionInfo.SectionType = 0; - - COUNT_T nVirtualSections = pPhysicalSection->GetVirtualSectionCount(); - for (COUNT_T iVirtualSection = 0; iVirtualSection < nVirtualSections; iVirtualSection++) - { - ZapVirtualSection * pVirtualSection = pPhysicalSection->GetVirtualSection(iVirtualSection); - - if (pVirtualSection->GetNodeCount() == 0) - continue; - - DWORD dwSectionType = pVirtualSection->GetSectionType(); - if (dwSectionType == 0) - continue; - - // Fold sections with the same type together - if (sectionInfo.SectionType != dwSectionType) - { - if (sectionInfo.SectionType != 0) - { - pZapWriter->Write(§ionInfo, sizeof(sectionInfo)); - } - - sectionInfo.SectionType = dwSectionType; - sectionInfo.VirtualAddress = pVirtualSection->GetRVA(); - } - - // Update section size - sectionInfo.Size = (pVirtualSection->GetRVA() + pVirtualSection->GetSize()) - sectionInfo.VirtualAddress; - } - - if (sectionInfo.SectionType != 0) - { - pZapWriter->Write(§ionInfo, sizeof(sectionInfo)); - } - } -} diff --git a/src/coreclr/zap/zapheaders.h b/src/coreclr/zap/zapheaders.h deleted file mode 100644 index 0e27132b731da6..00000000000000 --- a/src/coreclr/zap/zapheaders.h +++ /dev/null @@ -1,402 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapHeaders.h -// - -// -// Zapping of headers (IMAGE_COR20_HEADER, CORCOMPILE_HEADER, etc.) -// -// ====================================================================================== - -#ifndef __ZAPHEADERS_H__ -#define __ZAPHEADERS_H__ - -#include - -// -// IMAGE_COR20_HEADER -// - -class ZapCorHeader : public ZapNode -{ -public: - ZapCorHeader(ZapImage * pImage) - { - } - - virtual DWORD GetSize() - { - return sizeof(IMAGE_COR20_HEADER); - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_CorHeader; - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapImage::GetImage(pZapWriter)->SaveCorHeader(); - } -}; - -// -// CORCOMPILE_HEADER -// - -class ZapNativeHeader : public ZapNode -{ -public: - ZapNativeHeader(ZapImage * pImage) - { - } - - virtual DWORD GetSize() - { - return sizeof(CORCOMPILE_HEADER); - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_NativeHeader; - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapImage::GetImage(pZapWriter)->SaveNativeHeader(); - } -}; - -// -// CORCOMPILE_VERSION_INFO -// -class ZapVersionInfo : public ZapNode -{ - CORCOMPILE_VERSION_INFO m_versionInfo; - -public: - ZapVersionInfo(CORCOMPILE_VERSION_INFO * pVersionInfo) - { - memcpy(&m_versionInfo, pVersionInfo, sizeof(m_versionInfo)); - } - - CORCOMPILE_VERSION_INFO * GetData() - { - return &m_versionInfo; - } - - virtual DWORD GetSize() - { - return sizeof(CORCOMPILE_VERSION_INFO); - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_VersionInfo; - } - - virtual void Save(ZapWriter * pZapWriter) - { - pZapWriter->Write(&m_versionInfo, sizeof(m_versionInfo)); - } -}; - -// -// CORCOMPILE_CORCOMPILE_DEPENDENCY -// -class ZapDependencies : public ZapNode -{ - DWORD m_cDependencies; - CORCOMPILE_DEPENDENCY * m_pDependencies; - -public: - ZapDependencies(CORCOMPILE_DEPENDENCY * pDependencies, DWORD cDependencies) - : m_cDependencies(cDependencies), m_pDependencies(pDependencies) - { - } - - virtual DWORD GetSize() - { - return sizeof(CORCOMPILE_DEPENDENCY) * m_cDependencies; - } - - virtual UINT GetAlignment() - { - return sizeof(ULARGE_INTEGER); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_Dependencies; - } - - virtual void Save(ZapWriter * pZapWriter) - { - pZapWriter->Write(m_pDependencies, sizeof(CORCOMPILE_DEPENDENCY) * m_cDependencies); - } -}; - -// -// CORCOMPILE_CODE_MANAGER_ENTRY -// - -class ZapCodeManagerEntry : public ZapNode -{ -public: - ZapCodeManagerEntry(ZapImage * pImage) - { - } - - virtual DWORD GetSize() - { - return sizeof(CORCOMPILE_CODE_MANAGER_ENTRY); - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_CodeManagerEntry; - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapImage::GetImage(pZapWriter)->SaveCodeManagerEntry(); - } -}; - -// -// Win32 Resources -// - -class ZapWin32ResourceString : public ZapNode -{ - // - // This ZapNode maps the IMAGE_RESOURCE_DIR_STRING_U resource data structure for storing strings. - // - - LPWSTR m_pString; - -public: - ZapWin32ResourceString(LPCWSTR pString) - { - size_t strLen = wcslen(pString); - _ASSERT(pString != NULL && strLen < 0xffff); - - m_pString = new WCHAR[strLen + 1]; - wcscpy(m_pString, pString); - m_pString[strLen] = L'\0'; - } - - ~ZapWin32ResourceString() - { - delete[] m_pString; - } - - LPCWSTR GetString() { return m_pString; } - - virtual DWORD GetSize() - { - return sizeof(WORD) + sizeof(WCHAR) * (DWORD)wcslen(m_pString); - } - - virtual UINT GetAlignment() - { - return sizeof(WORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_Blob; - } - - virtual void Save(ZapWriter * pZapWriter) - { - WORD size = (WORD)wcslen(m_pString); - pZapWriter->Write(&size, sizeof(WORD)); - pZapWriter->Write((PVOID)m_pString, sizeof(WCHAR) * size); - } -}; - -class ZapWin32ResourceDirectory : public ZapNode -{ - // - // This ZapNode maps the IMAGE_RESOURCE_DIRECTORY resource data structure for storing a resource directory. Each directory - // is then followed by a number of IMAGE_RESOURCE_DIRECTORY_ENTRY entries, which can either point to other resource directories (RVAs - // to other ZapWin32ResourceDirectory nodes), or point to actual resource data (RVAs to a number of IMAGE_RESOURCE_DATA_ENTRY entries - // that immediately follow the IMAGE_RESOURCE_DIRECTORY_ENTRY entries). - // - // Refer to the PE resources format for more information (https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#the-rsrc-section) - // - - struct DataOrSubDirectoryEntry - { - PVOID m_pNameOrId; - bool m_nameOrIdIsString; - ZapNode* m_pDataOrSubDirectory; - bool m_dataIsSubDirectory; - }; - std::vector m_entries; - ZapVirtualSection* m_pWin32ResourceSection; - -public: - ZapWin32ResourceDirectory(ZapVirtualSection* pWin32ResourceSection) - : m_pWin32ResourceSection(pWin32ResourceSection) - { } - - void AddEntry(PVOID pNameOrId, bool nameOrIdIsString, ZapNode* pDataOrSubDirectory, bool dataIsSubDirectory) - { - DataOrSubDirectoryEntry entry; - entry.m_pDataOrSubDirectory = pDataOrSubDirectory; - entry.m_dataIsSubDirectory = dataIsSubDirectory; - entry.m_pNameOrId = pNameOrId; - entry.m_nameOrIdIsString = nameOrIdIsString; - - m_entries.push_back(entry); - } - - virtual DWORD GetSize() - { - DWORD size = sizeof(IMAGE_RESOURCE_DIRECTORY) + (DWORD)m_entries.size() * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY); - for (auto& entry : m_entries) - { - if (!entry.m_dataIsSubDirectory) - size += sizeof(IMAGE_RESOURCE_DATA_ENTRY); - } - return size; - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_Win32Resources; - } - - void PlaceNodeAndDependencies(ZapVirtualSection* pWin32ResourceSection) - { - pWin32ResourceSection->Place(this); - - for (auto& entry : m_entries) - { - if (entry.m_dataIsSubDirectory) - { - ZapWin32ResourceDirectory* pSubDirNode = (ZapWin32ResourceDirectory*)entry.m_pDataOrSubDirectory; - pSubDirNode->PlaceNodeAndDependencies(pWin32ResourceSection); - } - } - } - - virtual void Save(ZapWriter * pZapWriter); -}; - - -// -// Debug Directory -// - -class ZapDebugDirectory : public ZapNode -{ - ZapNode * m_pNGenPdbDebugData; - DWORD m_nDebugDirectory; - IMAGE_DEBUG_DIRECTORY * m_pDebugDirectory; - ZapNode ** m_ppDebugData; - -public: - ZapDebugDirectory(ZapNode *pNGenPdbDebugData, DWORD nDebugDirectory, PIMAGE_DEBUG_DIRECTORY pDebugDirectory, ZapNode ** ppDebugData) - : m_pNGenPdbDebugData(pNGenPdbDebugData), - m_nDebugDirectory(nDebugDirectory), - m_pDebugDirectory(pDebugDirectory), - m_ppDebugData(ppDebugData) - { - } - - virtual DWORD GetSize() - { -#if defined(NO_NGENPDB) - return sizeof(IMAGE_DEBUG_DIRECTORY) * m_nDebugDirectory; -#else - // Add one for NGen PDB debug directory entry - return sizeof(IMAGE_DEBUG_DIRECTORY) * (m_nDebugDirectory + 1); -#endif // NO_NGENPDB - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_DebugDirectory; - } - - void SaveOriginalDebugDirectoryEntry(ZapWriter *pZapWriter); - void SaveNGenDebugDirectoryEntry(ZapWriter *pZapWriter); - virtual void Save(ZapWriter * pZapWriter); -}; - -// -// PE Style exports. Currently can only save an empty list of exports -// but this is useful because it avoids the DLL being seen as Resource Only -// (which then causes SymServer to avoid copying its PDB to the cloud). -// - -class ZapPEExports : public ZapNode -{ - LPCWSTR m_dllFileName; // Just he DLL name without the path. - -public: - ZapPEExports(LPCWSTR dllPath); - virtual DWORD GetSize(); - virtual UINT GetAlignment() { return sizeof(DWORD); } - virtual void Save(ZapWriter * pZapWriter); -}; - -// -// List of all sections for diagnostic purposes - -class ZapVirtualSectionsTable : public ZapNode -{ - ZapImage * m_pImage; - -public: - - ZapVirtualSectionsTable(ZapImage * pImage) - : m_pImage(pImage) - { - } - - virtual DWORD GetSize(); - - virtual ZapNodeType GetType() - { - return ZapNodeType_VirtualSectionsTable; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -#endif // __ZAPHEADERS_H__ diff --git a/src/coreclr/zap/zapimage.cpp b/src/coreclr/zap/zapimage.cpp deleted file mode 100644 index 693921963d84a4..00000000000000 --- a/src/coreclr/zap/zapimage.cpp +++ /dev/null @@ -1,3764 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapImage.cpp -// - -// -// NGEN-specific infrastructure for writing PE files. -// -// ====================================================================================== - -#include "common.h" -#include "strsafe.h" - -#include "zaprelocs.h" - -#include "zapinnerptr.h" -#include "zapwrapper.h" - -#include "zapheaders.h" -#include "zapmetadata.h" -#include "zapcode.h" -#include "zapimport.h" - -#ifdef FEATURE_READYTORUN_COMPILER -#include "zapreadytorun.h" -#endif - -#include "md5.h" - -// This is RTL_CONTAINS_FIELD from ntdef.h -#define CONTAINS_FIELD(Struct, Size, Field) \ - ( (((PCHAR)(&(Struct)->Field)) + sizeof((Struct)->Field)) <= (((PCHAR)(Struct))+(Size)) ) - -/* --------------------------------------------------------------------------- * - * Destructor wrapper objects - * --------------------------------------------------------------------------- */ - -ZapImage::ZapImage(Zapper *zapper) - : m_zapper(zapper), - m_stats(new ZapperStats()) - /* Everything else is initialized to 0 by default */ -{ -} - -ZapImage::~ZapImage() -{ -#ifdef ZAP_HASHTABLE_TUNING - // If ZAP_HASHTABLE_TUNING is defined, preallocate is overloaded to print the tuning constants - Preallocate(); -#endif - - // - // Clean up. - // - if (m_stats != NULL) - delete m_stats; - - if (m_pModuleFileName != NULL) - delete [] m_pModuleFileName; - - if (m_pMDImport != NULL) - m_pMDImport->Release(); - - if (m_pAssemblyEmit != NULL) - m_pAssemblyEmit->Release(); - - if (m_profileDataFile != NULL) - UnmapViewOfFile(m_profileDataFile); - - if (m_pPreloader) - m_pPreloader->Release(); - - if (m_pImportSectionsTable != NULL) - m_pImportSectionsTable->~ZapImportSectionsTable(); - - if (m_pGCInfoTable != NULL) - m_pGCInfoTable->~ZapGCInfoTable(); - -#ifdef FEATURE_EH_FUNCLETS - if (m_pUnwindDataTable != NULL) - m_pUnwindDataTable->~ZapUnwindDataTable(); -#endif - - if (m_pStubDispatchDataTable != NULL) - m_pStubDispatchDataTable->~ZapImportSectionSignatures(); - - if (m_pExternalMethodDataTable != NULL) - m_pExternalMethodDataTable->~ZapImportSectionSignatures(); - - if (m_pDynamicHelperDataTable != NULL) - m_pDynamicHelperDataTable->~ZapImportSectionSignatures(); - - if (m_pDebugInfoTable != NULL) - m_pDebugInfoTable->~ZapDebugInfoTable(); - - if (m_pVirtualSectionsTable != NULL) - m_pVirtualSectionsTable->~ZapVirtualSectionsTable(); - - if (m_pILMetaData != NULL) - m_pILMetaData->~ZapILMetaData(); - - if (m_pBaseRelocs != NULL) - m_pBaseRelocs->~ZapBaseRelocs(); - - if (m_pAssemblyMetaData != NULL) - m_pAssemblyMetaData->~ZapMetaData(); - - // - // Destruction of auxiliary tables in alphabetical order - // - - if (m_pImportTable != NULL) - m_pImportTable->~ZapImportTable(); - - if (m_pInnerPtrs != NULL) - m_pInnerPtrs->~ZapInnerPtrTable(); - - if (m_pMethodEntryPoints != NULL) - m_pMethodEntryPoints->~ZapMethodEntryPointTable(); - - if (m_pWrappers != NULL) - m_pWrappers->~ZapWrapperTable(); -} - -void ZapImage::InitializeSections() -{ - AllocateVirtualSections(); - - m_pCorHeader = new (GetHeap()) ZapCorHeader(this); - m_pHeaderSection->Place(m_pCorHeader); - - SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_COMHEADER, m_pCorHeader); - - m_pNativeHeader = new (GetHeap()) ZapNativeHeader(this); - m_pHeaderSection->Place(m_pNativeHeader); - - m_pCodeManagerEntry = new (GetHeap()) ZapCodeManagerEntry(this); - m_pHeaderSection->Place(m_pCodeManagerEntry); - - m_pImportSectionsTable = new (GetHeap()) ZapImportSectionsTable(this); - m_pImportTableSection->Place(m_pImportSectionsTable); - - m_pExternalMethodDataTable = new (GetHeap()) ZapImportSectionSignatures(this, m_pExternalMethodThunkSection, m_pGCSection); - m_pExternalMethodDataSection->Place(m_pExternalMethodDataTable); - - m_pStubDispatchDataTable = new (GetHeap()) ZapImportSectionSignatures(this, m_pStubDispatchCellSection, m_pGCSection); - m_pStubDispatchDataSection->Place(m_pStubDispatchDataTable); - - m_pImportTable = new (GetHeap()) ZapImportTable(this); - - m_pGCInfoTable = new (GetHeap()) ZapGCInfoTable(this); - m_pExceptionInfoLookupTable = new (GetHeap()) ZapExceptionInfoLookupTable(this); - -#ifdef FEATURE_EH_FUNCLETS - m_pUnwindDataTable = new (GetHeap()) ZapUnwindDataTable(this); -#endif - - m_pEEInfoTable = ZapBlob::NewAlignedBlob(this, NULL, sizeof(CORCOMPILE_EE_INFO_TABLE), TARGET_POINTER_SIZE); - m_pEETableSection->Place(m_pEEInfoTable); - - // - // Allocate Helper table, and fill it out - // - - m_pHelperThunks = new (GetHeap()) ZapNode * [CORINFO_HELP_COUNT]; - - m_pILMetaData = new (GetHeap()) ZapILMetaData(this); - m_pILMetaDataSection->Place(m_pILMetaData); - - m_pDebugInfoTable = new (GetHeap()) ZapDebugInfoTable(this); - m_pDebugSection->Place(m_pDebugInfoTable); - - m_pBaseRelocs = new (GetHeap()) ZapBaseRelocs(this); - m_pBaseRelocsSection->Place(m_pBaseRelocs); - - SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_BASERELOC, m_pBaseRelocsSection); - - // - // Initialization of auxiliary tables in alphabetical order - // - m_pInnerPtrs = new (GetHeap()) ZapInnerPtrTable(this); - m_pMethodEntryPoints = new (GetHeap()) ZapMethodEntryPointTable(this); - m_pWrappers = new (GetHeap()) ZapWrapperTable(this); - - // Place the virtual sections tables in debug section. It exists for diagnostic purposes - // only and should not be touched under normal circumstances - m_pVirtualSectionsTable = new (GetHeap()) ZapVirtualSectionsTable(this); - m_pDebugSection->Place(m_pVirtualSectionsTable); - -#ifndef ZAP_HASHTABLE_TUNING - Preallocate(); -#endif -} - -#ifdef FEATURE_READYTORUN_COMPILER -void ZapImage::InitializeSectionsForReadyToRun() -{ - AllocateVirtualSections(); - - // Preload sections are not used for ready to run. Clear the pointers to them to catch accidental use. - for (int i = 0; i < CORCOMPILE_SECTION_COUNT; i++) - m_pPreloadSections[i] = NULL; - - m_pCorHeader = new (GetHeap()) ZapCorHeader(this); - m_pHeaderSection->Place(m_pCorHeader); - - SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_COMHEADER, m_pCorHeader); - - m_pNativeHeader = new (GetHeap()) ZapReadyToRunHeader(this); - m_pHeaderSection->Place(m_pNativeHeader); - - m_pImportSectionsTable = new (GetHeap()) ZapImportSectionsTable(this); - m_pHeaderSection->Place(m_pImportSectionsTable); - - { -#define COMPILER_NAME "CoreCLR" - - const char* pCompilerIdentifier = COMPILER_NAME " " VER_FILEVERSION_STR; - ZapBlob * pCompilerIdentifierBlob = new (GetHeap()) ZapBlobPtr((PVOID)pCompilerIdentifier, strlen(pCompilerIdentifier) + 1); - - GetReadyToRunHeader()->RegisterSection(ReadyToRunSectionType::CompilerIdentifier, pCompilerIdentifierBlob); - m_pHeaderSection->Place(pCompilerIdentifierBlob); - } - - m_pImportTable = new (GetHeap()) ZapImportTable(this); - - for (int i=0; iPlace(m_pDelayLoadInfoDataTable[i]); - } - - m_pDynamicHelperDataTable = new (GetHeap()) ZapImportSectionSignatures(this, m_pDynamicHelperCellSection); - m_pDynamicHelperDataSection->Place(m_pDynamicHelperDataTable); - - m_pExternalMethodDataTable = new (GetHeap()) ZapImportSectionSignatures(this, m_pExternalMethodCellSection, m_pGCSection); - m_pExternalMethodDataSection->Place(m_pExternalMethodDataTable); - - m_pStubDispatchDataTable = new (GetHeap()) ZapImportSectionSignatures(this, m_pStubDispatchCellSection, m_pGCSection); - m_pStubDispatchDataSection->Place(m_pStubDispatchDataTable); - - m_pGCInfoTable = new (GetHeap()) ZapGCInfoTable(this); - -#ifdef FEATURE_EH_FUNCLETS - m_pUnwindDataTable = new (GetHeap()) ZapUnwindDataTable(this); -#endif - - m_pILMetaData = new (GetHeap()) ZapILMetaData(this); - m_pILMetaDataSection->Place(m_pILMetaData); - - m_pBaseRelocs = new (GetHeap()) ZapBaseRelocs(this); - m_pBaseRelocsSection->Place(m_pBaseRelocs); - - SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_BASERELOC, m_pBaseRelocsSection); - - // - // Initialization of auxiliary tables in alphabetical order - // - m_pInnerPtrs = new (GetHeap()) ZapInnerPtrTable(this); - - m_pExceptionInfoLookupTable = new (GetHeap()) ZapExceptionInfoLookupTable(this); - - // - // Always allocate slot for module - it is used to determine that the image is used - // - m_pImportTable->GetPlacedHelperImport(READYTORUN_HELPER_Module); - - // - // Make sure the import sections table is in the image, so we can find the slot for module - // - _ASSERTE(m_pImportSectionsTable->GetSize() != 0); - GetReadyToRunHeader()->RegisterSection(ReadyToRunSectionType::ImportSections, m_pImportSectionsTable); -} -#endif // FEATURE_READYTORUN_COMPILER - - -#define DATA_MEM_READONLY IMAGE_SCN_MEM_READ -#define DATA_MEM_WRITABLE IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE -#define XDATA_MEM IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE -#define TEXT_MEM IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ - -void ZapImage::AllocateVirtualSections() -{ - // - // Allocate all virtual sections in the order they will appear in the final image - // - // To maximize packing of the data in the native image, the number of named physical sections is minimized - - // the named physical sections are used just for memory protection control. All items with the same memory - // protection are packed together in one physical section. - // - - { - // - // .data section - // - DWORD access = DATA_MEM_WRITABLE; - - ZapPhysicalSection * pDataSection = NewPhysicalSection(".data", IMAGE_SCN_CNT_INITIALIZED_DATA | access); - - m_pPreloadSections[CORCOMPILE_SECTION_MODULE] = NewVirtualSection(pDataSection, IBCUnProfiledSection | HotRange | ModuleSection); - - m_pEETableSection = NewVirtualSection(pDataSection, IBCUnProfiledSection | HotRange | EETableSection); // Could be marked bss if it makes sense - - // These are all known to be hot or writeable - m_pPreloadSections[CORCOMPILE_SECTION_WRITE] = NewVirtualSection(pDataSection, IBCProfiledSection | HotRange | WriteDataSection); - m_pPreloadSections[CORCOMPILE_SECTION_HOT_WRITEABLE] = NewVirtualSection(pDataSection, IBCProfiledSection | HotRange | WriteableDataSection); // hot for reading, potentially written to - m_pPreloadSections[CORCOMPILE_SECTION_WRITEABLE] = NewVirtualSection(pDataSection, IBCProfiledSection | ColdRange | WriteableDataSection); // Cold based on IBC profiling data. - m_pPreloadSections[CORCOMPILE_SECTION_HOT] = NewVirtualSection(pDataSection, IBCProfiledSection | HotRange | DataSection); - - m_pPreloadSections[CORCOMPILE_SECTION_RVA_STATICS_HOT] = NewVirtualSection(pDataSection, IBCProfiledSection | HotRange | RVAStaticsSection); - - m_pDelayLoadInfoTableSection[ZapImportSectionType_Eager] = NewVirtualSection(pDataSection, IBCUnProfiledSection | HotRange | DelayLoadInfoTableEagerSection, TARGET_POINTER_SIZE); - - // - // Allocate dynamic info tables - // - - // Place the HOT CorCompileTables now, the cold ones would be placed later in this routine (after other HOT sections) - for (int i=0; im_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR)) - { - m_pInstrumentSection = NewVirtualSection(pDataSection, IBCUnProfiledSection | ColdRange | InstrumentSection, TARGET_POINTER_SIZE); - } - } - - // No RWX pages in ready to run images - if (!IsReadyToRunCompilation()) - { - DWORD access = XDATA_MEM; - - // - // .xdata section - // - ZapPhysicalSection * pXDataSection = NewPhysicalSection(".xdata", IMAGE_SCN_CNT_INITIALIZED_DATA | access); - - // Some sections are placed in a sorted order. Hot items are placed first, - // then cold items. These sections are marked as HotColdSortedRange since - // they are neither completely hot, nor completely cold. - m_pVirtualImportThunkSection = NewVirtualSection(pXDataSection, IBCProfiledSection | HotColdSortedRange | VirtualImportThunkSection, HELPER_TABLE_ALIGN); - m_pExternalMethodThunkSection = NewVirtualSection(pXDataSection, IBCProfiledSection | HotColdSortedRange | ExternalMethodThunkSection, HELPER_TABLE_ALIGN); - m_pHelperTableSection = NewVirtualSection(pXDataSection, IBCProfiledSection | HotColdSortedRange| HelperTableSection, HELPER_TABLE_ALIGN); - - // hot for writing, i.e. profiling has indicated a write to this item, so at least one write likely per item at some point - m_pPreloadSections[CORCOMPILE_SECTION_METHOD_PRECODE_WRITE] = NewVirtualSection(pXDataSection, IBCProfiledSection | HotRange | MethodPrecodeWriteSection, TARGET_POINTER_SIZE); - m_pPreloadSections[CORCOMPILE_SECTION_METHOD_PRECODE_HOT] = NewVirtualSection(pXDataSection, IBCProfiledSection | HotRange | MethodPrecodeSection, TARGET_POINTER_SIZE); - - // - // cold sections - // - m_pPreloadSections[CORCOMPILE_SECTION_METHOD_PRECODE_COLD] = NewVirtualSection(pXDataSection, IBCProfiledSection | ColdRange | MethodPrecodeSection, TARGET_POINTER_SIZE); - m_pPreloadSections[CORCOMPILE_SECTION_METHOD_PRECODE_COLD_WRITEABLE] = NewVirtualSection(pXDataSection, IBCProfiledSection | ColdRange | MethodPrecodeWriteableSection, TARGET_POINTER_SIZE); - } - - { - // code:NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod and code:NativeImageJitManager::GetFunctionEntry expects - // sentinel value right after end of .pdata section. - static const DWORD dwRuntimeFunctionSectionSentinel = (DWORD)-1; - - - // - // .text section - // -#if defined(TARGET_ARM) - // for ARM, put the resource section at the end if it's very large - this - // is because b and bl instructions have a limited distance range of +-16MB - // which we should not exceed if we can avoid it. - // we draw the limit at 1 MB resource size, somewhat arbitrarily - COUNT_T resourceSize; - m_ModuleDecoder.GetResources(&resourceSize); - BOOL bigResourceSection = resourceSize >= 1024*1024; -#endif - ZapPhysicalSection * pTextSection = NewPhysicalSection(".text", IMAGE_SCN_CNT_CODE | TEXT_MEM); - m_pTextSection = pTextSection; - - // Marked as HotRange since it contains items that are always touched by - // the OS during NGEN image loading (i.e. VersionInfo) - m_pWin32ResourceSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | Win32ResourcesSection); - - // Marked as a HotRange since it is always touched during Ngen image load. - m_pHeaderSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | HeaderSection); - - // Marked as a HotRange since it is always touched during Ngen image binding. - m_pMetaDataSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | MetadataSection); - - m_pImportTableSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | ImportTableSection, sizeof(DWORD)); - - m_pDelayLoadInfoDelayListSectionEager = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | DelayLoadInfoDelayListSection, sizeof(DWORD)); - - // - // GC Info for methods which were profiled hot AND had their GC Info touched during profiling - // - m_pHotTouchedGCSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | GCInfoSection, sizeof(DWORD)); - - m_pLazyHelperSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | HelperTableSection, MINIMUM_CODE_ALIGN); - m_pLazyHelperSection->SetDefaultFill(DEFAULT_CODE_BUFFER_INIT); - - m_pLazyMethodCallHelperSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | HelperTableSection, MINIMUM_CODE_ALIGN); - m_pLazyMethodCallHelperSection->SetDefaultFill(DEFAULT_CODE_BUFFER_INIT); - - int codeSectionAlign = DEFAULT_CODE_ALIGN; - - m_pHotCodeSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | CodeSection, codeSectionAlign); - m_pHotCodeSection->SetDefaultFill(DEFAULT_CODE_BUFFER_INIT); - -#if defined(FEATURE_EH_FUNCLETS) - m_pHotUnwindDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | UnwindDataSection, sizeof(DWORD)); // .rdata area - - // All RuntimeFunctionSections have to be together for FEATURE_EH_FUNCLETS - m_pHotRuntimeFunctionSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | RuntimeFunctionSection, sizeof(DWORD)); // .pdata area - m_pRuntimeFunctionSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ColdRange | RuntimeFunctionSection, sizeof(DWORD)); - m_pColdRuntimeFunctionSection = NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | RuntimeFunctionSection, sizeof(DWORD)); - - // The following sentinel section is just a padding for RuntimeFunctionSection - Apply same classification - NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | RuntimeFunctionSection, sizeof(DWORD)) - ->Place(new (GetHeap()) ZapBlobPtr((PVOID)&dwRuntimeFunctionSectionSentinel, sizeof(DWORD))); -#endif // defined(FEATURE_EH_FUNCLETS) - - m_pStubsSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | StubsSection); - m_pReadOnlyDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ReadonlyDataSection); - - m_pDynamicHelperDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ExternalMethodDataSection, sizeof(DWORD)); - m_pExternalMethodDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ExternalMethodDataSection, sizeof(DWORD)); - m_pStubDispatchDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | StubDispatchDataSection, sizeof(DWORD)); - - m_pHotRuntimeFunctionLookupSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | RuntimeFunctionSection, sizeof(DWORD)); -#if !defined(FEATURE_EH_FUNCLETS) - m_pHotRuntimeFunctionSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | RuntimeFunctionSection, sizeof(DWORD)); - - // The following sentinel section is just a padding for RuntimeFunctionSection - Apply same classification - NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | RuntimeFunctionSection, sizeof(DWORD)) - ->Place(new (GetHeap()) ZapBlobPtr((PVOID)&dwRuntimeFunctionSectionSentinel, sizeof(DWORD))); -#endif - m_pHotCodeMethodDescsSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | CodeManagerSection, sizeof(DWORD)); - - m_pDelayLoadInfoDelayListSectionHot = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | DelayLoadInfoDelayListSection, sizeof(DWORD)); - - // - // The hot set of read-only data structures. Note that read-only data structures are the things that we can (and aggressively do) intern - // to share between different owners. However, this can have a bad interaction with IBC, which performs its ordering optimizations without - // knowing that NGen may jumble around layout with interning. Thankfully, it is a relatively small percentage of the items that are duplicates - // (many of them used a great deal to add up to large interning savings). This means that we can track all of the interned items for which we - // actually find any duplicates and put those in a small section. For the rest, where there wasn't a duplicate in the entire image, we leave the - // singleton in its normal place in the READONLY_HOT section, which was selected carefully by IBC. - // - m_pPreloadSections[CORCOMPILE_SECTION_READONLY_SHARED_HOT] = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | ReadonlySharedSection, TARGET_POINTER_SIZE); - m_pPreloadSections[CORCOMPILE_SECTION_READONLY_HOT] = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | ReadonlySection, TARGET_POINTER_SIZE); - - // - // GC Info for methods which were touched during profiling but didn't explicitly have - // their GC Info touched during profiling - // - m_pHotGCSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | GCInfoSection, sizeof(DWORD)); - -#if !defined(TARGET_ARM) - // For ARM, put these sections more towards the end because bl/b instructions have limited displacement - - // IL - m_pILSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ILSection, sizeof(DWORD)); - - //ILMetadata/Resources sections are reported as a statically known warm ranges for now. - m_pILMetaDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ILMetadataSection, sizeof(DWORD)); -#endif // TARGET_ARM - -#if defined(TARGET_ARM) - if (!bigResourceSection) // for ARM, put the resource section at the end if it's very large - see comment above -#endif - m_pResourcesSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | WarmRange | ResourcesSection); - - // - // Allocate the unprofiled code section and code manager nibble map here - // - m_pCodeSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ColdRange | CodeSection, codeSectionAlign); - m_pCodeSection->SetDefaultFill(DEFAULT_CODE_BUFFER_INIT); - - m_pRuntimeFunctionLookupSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ColdRange | RuntimeFunctionSection, sizeof(DWORD)); -#if !defined(FEATURE_EH_FUNCLETS) - m_pRuntimeFunctionSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ColdRange | RuntimeFunctionSection, sizeof(DWORD)); - - // The following sentinel section is just a padding for RuntimeFunctionSection - Apply same classification - NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ColdRange | RuntimeFunctionSection, sizeof(DWORD)) - ->Place(new (GetHeap()) ZapBlobPtr((PVOID)&dwRuntimeFunctionSectionSentinel, sizeof(DWORD))); -#endif - m_pCodeMethodDescsSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ColdRange | CodeHeaderSection,sizeof(DWORD)); - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - m_pAvailableTypesSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | WarmRange | ReadonlySection); - m_pAttributePresenceSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | WarmRange | ReadonlyDataSection, 16/* Must be 16 byte aligned */); - } -#endif - -#if defined(FEATURE_EH_FUNCLETS) - m_pUnwindDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ColdRange | UnwindDataSection, sizeof(DWORD)); -#endif // defined(FEATURE_EH_FUNCLETS) - - m_pPreloadSections[CORCOMPILE_SECTION_READONLY_WARM] = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ReadonlySection, TARGET_POINTER_SIZE); - m_pPreloadSections[CORCOMPILE_SECTION_READONLY_VCHUNKS] = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ReadonlySection, TARGET_POINTER_SIZE); - m_pPreloadSections[CORCOMPILE_SECTION_READONLY_DICTIONARY] = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ReadonlySection, TARGET_POINTER_SIZE); - - // - // GC Info for methods which were not touched in profiling - // - m_pGCSection = NewVirtualSection(pTextSection, IBCProfiledSection | ColdRange | GCInfoSection, sizeof(DWORD)); - - m_pDelayLoadInfoDelayListSectionCold = NewVirtualSection(pTextSection, IBCProfiledSection | ColdRange | DelayLoadInfoDelayListSection, sizeof(DWORD)); - - m_pPreloadSections[CORCOMPILE_SECTION_READONLY_COLD] = NewVirtualSection(pTextSection, IBCProfiledSection | ColdRange | ReadonlySection, TARGET_POINTER_SIZE); - - // - // Allocate the cold code section near the end of the image - // - m_pColdCodeSection = NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | CodeSection, codeSectionAlign); - m_pColdCodeSection->SetDefaultFill(DEFAULT_CODE_BUFFER_INIT); - -#if defined(TARGET_ARM) - // For ARM, put these sections more towards the end because bl/b instructions have limited displacement - - // IL - m_pILSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ILSection, sizeof(DWORD)); - - //ILMetadata/Resources sections are reported as a statically known warm ranges for now. - m_pILMetaDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ILMetadataSection, sizeof(DWORD)); - - if (bigResourceSection) // for ARM, put the resource section at the end if it's very large - see comment above - m_pResourcesSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | WarmRange | ResourcesSection); -#endif // TARGET_ARM - m_pColdCodeMapSection = NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | CodeManagerSection, sizeof(DWORD)); - -#if !defined(FEATURE_EH_FUNCLETS) - m_pColdRuntimeFunctionSection = NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | RuntimeFunctionSection, sizeof(DWORD)); - - // The following sentinel section is just a padding for RuntimeFunctionSection - Apply same classification - NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | RuntimeFunctionSection, sizeof(DWORD)) - ->Place(new (GetHeap()) ZapBlobPtr((PVOID)&dwRuntimeFunctionSectionSentinel, sizeof(DWORD))); -#endif - -#if defined(FEATURE_EH_FUNCLETS) - m_pColdUnwindDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | UnwindDataSection, sizeof(DWORD)); -#endif // defined(FEATURE_EH_FUNCLETS) - - // - // Allocate space for compressed LookupMaps (ridmaps). This needs to come after the .data physical - // section (which is currently true for the .text section) and late enough in the .text section to be - // after any structure referenced by the LookupMap (current MethodTables and MethodDescs). This is a - // hard requirement since the compression algorithm requires that all referenced data structures have - // been laid out by the time we come to lay out the compressed nodes. - // - m_pPreloadSections[CORCOMPILE_SECTION_COMPRESSED_MAPS] = NewVirtualSection(pTextSection, IBCProfiledSection | ColdRange | CompressedMapsSection, sizeof(DWORD)); - - m_pExceptionSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ExceptionSection, sizeof(DWORD)); - - // - // Debug info is sometimes used during exception handling to build stacktrace - // - m_pDebugSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | ColdRange | DebugSection, sizeof(DWORD)); - } - - { - // - // .reloc section - // - - ZapPhysicalSection * pRelocSection = NewPhysicalSection(".reloc", IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_MEM_READ); - - // .reloc section is always read by the OS when the image is opted in ASLR - // (Vista+ default behavior). - m_pBaseRelocsSection = NewVirtualSection(pRelocSection, IBCUnProfiledSection | HotRange | BaseRelocsSection); - - } -} - -void ZapImage::Preallocate() -{ - COUNT_T cbILImage = m_ModuleDecoder.GetSize(); - - // Curb the estimate to handle corner cases gracefully - cbILImage = min(cbILImage, 50000000); - - PREALLOCATE_HASHTABLE(ZapImage::m_CompiledMethods, 0.0050, cbILImage); - PREALLOCATE_HASHTABLE(ZapImage::m_ClassLayoutOrder, 0.0003, cbILImage); - - // - // Preallocation of auxiliary tables in alphabetical order - // - m_pImportTable->Preallocate(cbILImage); - m_pInnerPtrs->Preallocate(cbILImage); - m_pMethodEntryPoints->Preallocate(cbILImage); - m_pWrappers->Preallocate(cbILImage); - - if (m_pILMetaData != NULL) - m_pILMetaData->Preallocate(cbILImage); - m_pGCInfoTable->Preallocate(cbILImage); -#ifdef FEATURE_EH_FUNCLETS - m_pUnwindDataTable->Preallocate(cbILImage); -#endif // FEATURE_EH_FUNCLETS - m_pDebugInfoTable->Preallocate(cbILImage); -} - -void ZapImage::SetVersionInfo(CORCOMPILE_VERSION_INFO * pVersionInfo) -{ - m_pVersionInfo = new (GetHeap()) ZapVersionInfo(pVersionInfo); - m_pHeaderSection->Place(m_pVersionInfo); -} - -void ZapImage::SetDependencies(CORCOMPILE_DEPENDENCY *pDependencies, DWORD cDependencies) -{ - m_pDependencies = new (GetHeap()) ZapDependencies(pDependencies, cDependencies); - m_pHeaderSection->Place(m_pDependencies); -} - -void ZapImage::SetPdbFileName(const SString &strFileName) -{ - m_pdbFileName.Set(strFileName); -} - -#ifdef FEATURE_EH_FUNCLETS -void ZapImage::SetRuntimeFunctionsDirectoryEntry() -{ - // - // Runtime functions span multiple virtual sections and so there is no natural ZapNode * to cover them all. - // Create dummy ZapNode * that covers them all for IMAGE_DIRECTORY_ENTRY_EXCEPTION directory entry. - // - ZapVirtualSection * rgRuntimeFunctionSections[] = { - m_pHotRuntimeFunctionSection, - m_pRuntimeFunctionSection, - m_pColdRuntimeFunctionSection - }; - - DWORD dwTotalSize = 0, dwStartRVA = (DWORD)-1, dwEndRVA = 0; - - for (size_t i = 0; i < _countof(rgRuntimeFunctionSections); i++) - { - ZapVirtualSection * pSection = rgRuntimeFunctionSections[i]; - - DWORD dwSize = pSection->GetSize(); - if (dwSize == 0) - continue; - - DWORD dwRVA = pSection->GetRVA(); - - dwTotalSize += dwSize; - - dwStartRVA = min(dwStartRVA, dwRVA); - dwEndRVA = max(dwEndRVA, dwRVA + dwSize); - } - - if (dwTotalSize != 0) - { - // Verify that there are no holes between the sections - _ASSERTE(dwStartRVA + dwTotalSize == dwEndRVA); - - ZapNode * pAllRuntimeFunctionSections = new (GetHeap()) ZapDummyNode(dwTotalSize); - pAllRuntimeFunctionSections->SetRVA(dwStartRVA); - - // Write the address of the sorted pdata to the optionalHeader.DataDirectory - SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_EXCEPTION, pAllRuntimeFunctionSections); - } -} -#endif // FEATURE_EH_FUNCLETS - -// Assign RVAs to all ZapNodes -void ZapImage::ComputeRVAs() -{ - ZapWriter::ComputeRVAs(); - - if (!IsReadyToRunCompilation()) - { - m_pMethodEntryPoints->Resolve(); - m_pWrappers->Resolve(); - } - - m_pInnerPtrs->Resolve(); - -#ifdef FEATURE_EH_FUNCLETS - SetRuntimeFunctionsDirectoryEntry(); -#endif - -#if defined(_DEBUG) -#ifdef FEATURE_SYMDIFF - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_SymDiffDump)) - { - COUNT_T curMethod = 0; - COUNT_T numMethods = m_MethodCompilationOrder.GetCount(); - - for (; curMethod < numMethods; curMethod++) - { - bool fCold = false; - //if(curMethod >= m_iUntrainedMethod) fCold = true; - - ZapMethodHeader * pMethod = m_MethodCompilationOrder[curMethod]; - - ZapBlobWithRelocs * pCode = fCold ? pMethod->m_pColdCode : pMethod->m_pCode; - if (pCode == NULL) - { - continue; - } - CORINFO_METHOD_HANDLE handle = pMethod->GetHandle(); - mdMethodDef token; - GetCompileInfo()->GetMethodDef(handle, &token); - GetSvcLogger()->Printf(W("(EntryPointRVAMap (MethodToken %0X) (RVA %0X) (SIZE %0X))\n"), token, pCode->GetRVA(), pCode->GetSize()); - } - - } -#endif // FEATURE_SYMDIFF -#endif //_DEBUG -} - -class ZapFileStream : public IStream -{ - HANDLE m_hFile; - MD5 m_hasher; - -public: - ZapFileStream() - : m_hFile(INVALID_HANDLE_VALUE) - { - m_hasher.Init(); - } - - ~ZapFileStream() - { - Close(); - } - - void SetHandle(HANDLE hFile) - { - _ASSERTE(m_hFile == INVALID_HANDLE_VALUE); - m_hFile = hFile; - } - - // IUnknown methods: - STDMETHODIMP_(ULONG) AddRef() - { - return 1; - } - - STDMETHODIMP_(ULONG) Release() - { - return 1; - } - - STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv) - { - HRESULT hr = S_OK; - if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IStream)) { - *ppv = static_cast(this); - } - else { - hr = E_NOINTERFACE; - } - return hr; - } - - // ISequentialStream methods: - STDMETHODIMP Read(void *pv, ULONG cb, ULONG *pcbRead) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Write(void const *pv, ULONG cb, ULONG *pcbWritten) - { - HRESULT hr = S_OK; - - _ASSERTE(m_hFile != INVALID_HANDLE_VALUE); - - m_hasher.HashMore(pv, cb); - - // We are calling with lpOverlapped == NULL so pcbWritten has to be present - // to prevent crashes in Win7 and below. - _ASSERTE(pcbWritten); - - if (!::WriteFile(m_hFile, pv, cb, pcbWritten, NULL)) - { - hr = HRESULT_FROM_GetLastError(); - goto Exit; - } - - Exit: - return hr; - } - - // IStream methods: - STDMETHODIMP Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) - { - HRESULT hr = S_OK; - - _ASSERTE(m_hFile != INVALID_HANDLE_VALUE); - - DWORD dwFileOrigin; - switch (dwOrigin) { - case STREAM_SEEK_SET: - dwFileOrigin = FILE_BEGIN; - break; - - case STREAM_SEEK_CUR: - dwFileOrigin = FILE_CURRENT; - break; - - case STREAM_SEEK_END: - dwFileOrigin = FILE_END; - break; - - default: - hr = E_UNEXPECTED; - goto Exit; - } - if (!::SetFilePointerEx(m_hFile, dlibMove, (LARGE_INTEGER *)plibNewPosition, dwFileOrigin)) - { - hr = HRESULT_FROM_GetLastError(); - goto Exit; - } - - Exit: - return hr; - } - - STDMETHODIMP SetSize(ULARGE_INTEGER libNewSize) - { - HRESULT hr = S_OK; - - _ASSERTE(m_hFile != INVALID_HANDLE_VALUE); - - hr = Seek(*(LARGE_INTEGER *)&libNewSize, FILE_BEGIN, NULL); - if (FAILED(hr)) - { - goto Exit; - } - - if (!::SetEndOfFile(m_hFile)) - { - hr = HRESULT_FROM_GetLastError(); - goto Exit; - } - - Exit: - return hr; - } - - STDMETHODIMP CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Commit(DWORD grfCommitFlags) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Revert() - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Stat(STATSTG *pstatstg, DWORD grfStatFlag) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Clone(IStream **ppIStream) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - HRESULT Close() - { - HRESULT hr = S_OK; - - HANDLE hFile = m_hFile; - if (hFile != INVALID_HANDLE_VALUE) - { - m_hFile = INVALID_HANDLE_VALUE; - - if (!::CloseHandle(hFile)) - { - hr = HRESULT_FROM_GetLastError(); - goto Exit; - } - } - - Exit: - return hr; - } - - void SuppressClose() - { - m_hFile = INVALID_HANDLE_VALUE; - } - - void GetHash(MD5HASHDATA* pHash) - { - m_hasher.GetHashValue(pHash); - } -}; - -HANDLE ZapImage::GenerateFile(LPCWSTR wszOutputFileName, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig) -{ - ZapFileStream outputStream; - - HANDLE hFile = WszCreateFile(wszOutputFileName, - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_DELETE, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, - NULL); - - if (hFile == INVALID_HANDLE_VALUE) - ThrowLastError(); - - outputStream.SetHandle(hFile); - - Save(&outputStream); - - LARGE_INTEGER filePos; - - if (m_pNativeHeader != NULL) - { - // Write back the updated CORCOMPILE_HEADER (relocs and guid is not correct the first time around) - filePos.QuadPart = m_pTextSection->GetFilePos() + - (m_pNativeHeader->GetRVA() - m_pTextSection->GetRVA()); - IfFailThrow(outputStream.Seek(filePos, STREAM_SEEK_SET, NULL)); - m_pNativeHeader->Save(this); - FlushWriter(); - } - - GUID signature = {0}; - - static_assert_no_msg(sizeof(GUID) == sizeof(MD5HASHDATA)); - outputStream.GetHash((MD5HASHDATA*)&signature); - - { - // Write the debug directory entry for the NGEN PDB - RSDS rsds = {0}; - - rsds.magic = VAL32(0x53445352); // "SDSR"; - rsds.age = 1; - // our PDB signature will be the same as our NGEN signature. - // However we want the printed version of the GUID to be the same as the - // byte dump of the signature so we swap bytes to make this work. - // - // * See code:CCorSvcMgr::CreatePdb for where this is used. - BYTE* asBytes = (BYTE*) &signature; - rsds.signature.Data1 = ((asBytes[0] * 256 + asBytes[1]) * 256 + asBytes[2]) * 256 + asBytes[3]; - rsds.signature.Data2 = asBytes[4] * 256 + asBytes[5]; - rsds.signature.Data3 = asBytes[6] * 256 + asBytes[7]; - memcpy(&rsds.signature.Data4, &asBytes[8], 8); - - _ASSERTE(!m_pdbFileName.IsEmpty()); - ZeroMemory(&rsds.path[0], sizeof(rsds.path)); - if (WideCharToMultiByte(CP_UTF8, - 0, - m_pdbFileName.GetUnicode(), - m_pdbFileName.GetCount(), - &rsds.path[0], - sizeof(rsds.path) - 1, // -1 to keep the buffer zero terminated - NULL, - NULL) == 0) - ThrowHR(E_FAIL); - - ULONG cbWritten = 0; - filePos.QuadPart = m_pTextSection->GetFilePos() + (m_pNGenPdbDebugData->GetRVA() - m_pTextSection->GetRVA()); - IfFailThrow(outputStream.Seek(filePos, STREAM_SEEK_SET, NULL)); - IfFailThrow(outputStream.Write(&rsds, sizeof rsds, &cbWritten)); - } - - if (m_pVersionInfo != NULL) - { - ULONG cbWritten; - - filePos.QuadPart = m_pTextSection->GetFilePos() + - (m_pVersionInfo->GetRVA() - m_pTextSection->GetRVA()) + - offsetof(CORCOMPILE_VERSION_INFO, signature); - IfFailThrow(outputStream.Seek(filePos, STREAM_SEEK_SET, NULL)); - IfFailThrow(outputStream.Write(&signature, sizeof(signature), &cbWritten)); - - if (pNativeImageSig != NULL) - *pNativeImageSig = signature; - } - else - { - _ASSERTE(pNativeImageSig == NULL); - } - - outputStream.SuppressClose(); - return hFile; -} - - -HANDLE ZapImage::SaveImage(LPCWSTR wszOutputFileName, LPCWSTR wszDllPath, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig) -{ - if(!IsReadyToRunCompilation() || IsLargeVersionBubbleEnabled()) - { - OutputManifestMetadata(); - } - - OutputTables(); - - // Create an empty export table. This makes tools like symchk not think - // that native images are resource-only DLLs. It is important to NOT - // be a resource-only DLL because those DLL's PDBS are not put up on the - // symbol server and we want NGEN PDBS to be placed there. - ZapPEExports* exports = new(GetHeap()) ZapPEExports(wszDllPath); - m_pDebugSection->Place(exports); - SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_EXPORT, exports); - - ComputeRVAs(); - - if (!IsReadyToRunCompilation()) - { - m_pPreloader->FixupRVAs(); - } - - HANDLE hFile = GenerateFile(wszOutputFileName, pNativeImageSig); - - if (m_zapper->m_pOpt->m_verbose) - { - PrintStats(wszOutputFileName); - } - - return hFile; -} - -void ZapImage::PrintStats(LPCWSTR wszOutputFileName) -{ -#define ACCUM_SIZE(dest, src) if( src != NULL ) dest+= src->GetSize() - ACCUM_SIZE(m_stats->m_gcInfoSize, m_pHotTouchedGCSection); - ACCUM_SIZE(m_stats->m_gcInfoSize, m_pHotGCSection); - ACCUM_SIZE(m_stats->m_gcInfoSize, m_pGCSection); -#if defined(FEATURE_EH_FUNCLETS) - ACCUM_SIZE(m_stats->m_unwindInfoSize, m_pUnwindDataSection); - ACCUM_SIZE(m_stats->m_unwindInfoSize, m_pHotRuntimeFunctionSection); - ACCUM_SIZE(m_stats->m_unwindInfoSize, m_pRuntimeFunctionSection); - ACCUM_SIZE(m_stats->m_unwindInfoSize, m_pColdRuntimeFunctionSection); -#endif // defined(FEATURE_EH_FUNCLETS) - - // - // Get the size of the input & output files - // - - { - WIN32_FIND_DATA inputData; - FindHandleHolder inputHandle = WszFindFirstFile(m_pModuleFileName, &inputData); - if (inputHandle != INVALID_HANDLE_VALUE) - m_stats->m_inputFileSize = inputData.nFileSizeLow; - } - - { - WIN32_FIND_DATA outputData; - FindHandleHolder outputHandle = WszFindFirstFile(wszOutputFileName, &outputData); - if (outputHandle != INVALID_HANDLE_VALUE) - m_stats->m_outputFileSize = outputData.nFileSizeLow; - } - - ACCUM_SIZE(m_stats->m_metadataSize, m_pAssemblyMetaData); - - DWORD dwPreloadSize = 0; - for (int iSection = 0; iSection < CORCOMPILE_SECTION_COUNT; iSection++) - ACCUM_SIZE(dwPreloadSize, m_pPreloadSections[iSection]); - m_stats->m_preloadImageSize = dwPreloadSize; - - ACCUM_SIZE(m_stats->m_hotCodeMgrSize, m_pHotCodeMethodDescsSection); - ACCUM_SIZE(m_stats->m_unprofiledCodeMgrSize, m_pCodeMethodDescsSection); - ACCUM_SIZE(m_stats->m_coldCodeMgrSize, m_pHotRuntimeFunctionLookupSection); - - ACCUM_SIZE(m_stats->m_eeInfoTableSize, m_pEEInfoTable); - ACCUM_SIZE(m_stats->m_helperTableSize, m_pHelperTableSection); - ACCUM_SIZE(m_stats->m_dynamicInfoTableSize, m_pImportSectionsTable); - - ACCUM_SIZE(m_stats->m_dynamicInfoDelayListSize, m_pDelayLoadInfoDelayListSectionEager); - ACCUM_SIZE(m_stats->m_dynamicInfoDelayListSize, m_pDelayLoadInfoDelayListSectionHot); - ACCUM_SIZE(m_stats->m_dynamicInfoDelayListSize, m_pDelayLoadInfoDelayListSectionCold); - - ACCUM_SIZE(m_stats->m_debuggingTableSize, m_pDebugSection); - ACCUM_SIZE(m_stats->m_headerSectionSize, m_pGCSection); - ACCUM_SIZE(m_stats->m_codeSectionSize, m_pHotCodeSection); - ACCUM_SIZE(m_stats->m_coldCodeSectionSize, m_pColdCodeSection); - ACCUM_SIZE(m_stats->m_exceptionSectionSize, m_pExceptionSection); - ACCUM_SIZE(m_stats->m_readOnlyDataSectionSize, m_pReadOnlyDataSection); - ACCUM_SIZE(m_stats->m_relocSectionSize, m_pBaseRelocsSection); - ACCUM_SIZE(m_stats->m_ILMetadataSize, m_pILMetaData); - ACCUM_SIZE(m_stats->m_virtualImportThunkSize, m_pVirtualImportThunkSection); - ACCUM_SIZE(m_stats->m_externalMethodThunkSize, m_pExternalMethodThunkSection); - ACCUM_SIZE(m_stats->m_externalMethodDataSize, m_pExternalMethodDataSection); -#undef ACCUM_SIZE - - if (m_stats->m_failedMethods) - m_zapper->Warning(W("Warning: %d methods (%d%%) could not be compiled.\n"), - m_stats->m_failedMethods, (m_stats->m_failedMethods*100) / m_stats->m_methods); - if (m_stats->m_failedILStubs) - m_zapper->Warning(W("Warning: %d IL STUB methods could not be compiled.\n"), - m_stats->m_failedMethods); - m_stats->PrintStats(); -} - -// Align native images to 64K -const SIZE_T BASE_ADDRESS_ALIGNMENT = 0xffff; -const double CODE_EXPANSION_FACTOR = 3.6; - -void ZapImage::CalculateZapBaseAddress() -{ - static SIZE_T nextBaseAddressForMultiModule; - - SIZE_T baseAddress = 0; - - { - // Read the actual preferred base address from the disk - - // Note that we are reopening the file here. We are not guaranteed to get the same file. - // The worst thing that can happen is that we will read a bogus preferred base address from the file. - HandleHolder hFile(WszCreateFile(m_pModuleFileName, - GENERIC_READ, - FILE_SHARE_READ|FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL)); - if (hFile == INVALID_HANDLE_VALUE) - ThrowLastError(); - - HandleHolder hFileMap(WszCreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL)); - if (hFileMap == NULL) - ThrowLastError(); - - MapViewHolder base(MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0)); - if (base == NULL) - ThrowLastError(); - - DWORD dwFileLen = SafeGetFileSize(hFile, 0); - if (dwFileLen == INVALID_FILE_SIZE) - ThrowLastError(); - - PEDecoder peFlat((void *)base, (COUNT_T)dwFileLen); - - baseAddress = (SIZE_T) peFlat.GetPreferredBase(); - } - - // See if the header has the linker's default preferred base address - if (baseAddress == (SIZE_T) 0x00400000) - { - if (m_fManifestModule) - { - // Set the base address for the main assembly with the manifest - - if (!m_ModuleDecoder.IsDll()) - { -#if defined(TARGET_X86) - // We use 30000000 for an exe - baseAddress = 0x30000000; -#elif defined(TARGET_64BIT) - // We use 04000000 for an exe - // which is remapped to 0x644`88000000 on x64 - baseAddress = 0x04000000; -#endif - } - else - { -#if defined(TARGET_X86) - // We start a 31000000 for the main assembly with the manifest - baseAddress = 0x31000000; -#elif defined(TARGET_64BIT) - // We start a 05000000 for the main assembly with the manifest - // which is remapped to 0x644`8A000000 on x64 - baseAddress = 0x05000000; -#endif - } - } - else // is dependent assembly of a multi-module assembly - { - // Set the base address for a dependent multi-module assembly - - // We should have already set the nextBaseAddressForMultiModule - // when we compiled the manifest module - _ASSERTE(nextBaseAddressForMultiModule != 0); - baseAddress = nextBaseAddressForMultiModule; - } - } - else - { - // - // For some assemblies we have to move the ngen image base address up - // past the end of IL image so that that we don't have a conflict. - // - // CoreCLR currently always loads both the IL and the native image, so - // move the native image out of the way. - { - baseAddress += m_ModuleDecoder.GetVirtualSize(); - } - } - - if (m_zapper->GetCustomBaseAddress() != 0) - { - //set baseAddress here from crossgen options - baseAddress = m_zapper->GetCustomBaseAddress(); - } - - // Round to a multiple of 64K - // 64K is the allocation granularity of VirtualAlloc. (Officially this number is not a constant - - // we should be querying the system for its allocation granularity, but we do this all over the place - // currently.) - - baseAddress = (baseAddress + BASE_ADDRESS_ALIGNMENT) & ~BASE_ADDRESS_ALIGNMENT; - - // - // Calculate the nextBaseAddressForMultiModule - // - SIZE_T tempBaseAddress = baseAddress; - tempBaseAddress += (SIZE_T) (CODE_EXPANSION_FACTOR * (double) m_ModuleDecoder.GetVirtualSize()); - tempBaseAddress += BASE_ADDRESS_ALIGNMENT; - tempBaseAddress = (tempBaseAddress + BASE_ADDRESS_ALIGNMENT) & ~BASE_ADDRESS_ALIGNMENT; - - nextBaseAddressForMultiModule = tempBaseAddress; - - // - // Now we remap the 32-bit address range used for x86 and PE32 images into the - // upper address range used on 64-bit platforms - // -#if USE_UPPER_ADDRESS // Implies TARGET_64BIT - if (baseAddress < 0x80000000) - { - if (baseAddress < 0x40000000) - baseAddress += 0x40000000; // We map [00000000..3fffffff] to [644'80000000..644'ffffffff] - else - baseAddress -= 0x40000000; // We map [40000000..7fffffff] to [644'00000000..644'7fffffff] - - baseAddress *= UPPER_ADDRESS_MAPPING_FACTOR; - baseAddress += CLR_UPPER_ADDRESS_MIN; - } -#endif - - // Apply the calculated base address. - SetBaseAddress(baseAddress); - - m_NativeBaseAddress = baseAddress; -} - -void ZapImage::Open(CORINFO_MODULE_HANDLE hModule, - IMetaDataAssemblyEmit *pEmit) -{ - m_hModule = hModule; - m_fManifestModule = (hModule == m_zapper->m_pEECompileInfo->GetAssemblyModule(m_zapper->m_hAssembly)); - - m_ModuleDecoder = *m_zapper->m_pEECompileInfo->GetModuleDecoder(hModule); - - - // - // Get file name, and base address from module - // - - StackSString moduleFileName; - m_zapper->m_pEECompileInfo->GetModuleFileName(hModule, moduleFileName); - - DWORD fileNameLength = moduleFileName.GetCount(); - m_pModuleFileName = new WCHAR[fileNameLength+1]; - wcscpy_s(m_pModuleFileName, fileNameLength+1, moduleFileName.GetUnicode()); - - // - // Load the IBC Profile data for the assembly if it exists - // - LoadProfileData(); - - // - // Get metadata of module to be compiled - // - m_pMDImport = m_zapper->m_pEECompileInfo->GetModuleMetaDataImport(m_hModule); - _ASSERTE(m_pMDImport != NULL); - - // - // Open new assembly metadata data for writing. We may not use it, - // if so we'll just discard it at the end. - // - if (pEmit != NULL) - { - pEmit->AddRef(); - m_pAssemblyEmit = pEmit; - } - else - { - // Hardwire the metadata version to be the current runtime version so that the ngen image - // does not change when the directory runtime is installed in different directory (e.g. v2.0.x86chk vs. v2.0.80826). - BSTRHolder strVersion(SysAllocString(CLR_METADATA_VERSION_L)); - VARIANT versionOption; - V_VT(&versionOption) = VT_BSTR; - V_BSTR(&versionOption) = strVersion; - IfFailThrow(m_zapper->m_pMetaDataDispenser->SetOption(MetaDataRuntimeVersion, &versionOption)); - - IfFailThrow(m_zapper->m_pMetaDataDispenser-> - DefineScope(CLSID_CorMetaDataRuntime, 0, IID_IMetaDataAssemblyEmit, - (IUnknown **) &m_pAssemblyEmit)); - } - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - InitializeSectionsForReadyToRun(); - } - else -#endif - { - InitializeSections(); - } - - // Set the module base address for the ngen native image - CalculateZapBaseAddress(); -} - - - - -// -// Load the module and populate all the data-structures -// - -void ZapImage::Preload() -{ - - CorProfileData * pProfileData = NewProfileData(); - m_pPreloader = m_zapper->m_pEECompileInfo->PreloadModule(m_hModule, this, pProfileData); -} - -// -// Store the module -// - -void ZapImage::LinkPreload() -{ - m_pPreloader->Link(); -} - -void ZapImage::OutputManifestMetadata() -{ - // - // Write out manifest metadata - // - - // - // First, see if we have useful metadata to store - // - - BOOL fMetadata = FALSE; - - if (m_pAssemblyEmit != NULL) - { - // - // We may have added some assembly refs for exports. - // - - NonVMComHolder pAssemblyImport; - IfFailThrow(m_pAssemblyEmit->QueryInterface(IID_IMetaDataAssemblyImport, - (void **)&pAssemblyImport)); - - NonVMComHolder pImport; - IfFailThrow(m_pAssemblyEmit->QueryInterface(IID_IMetaDataImport, - (void **)&pImport)); - - HCORENUM hEnum = 0; - ULONG cRefs; - IfFailThrow(pAssemblyImport->EnumAssemblyRefs(&hEnum, NULL, 0, &cRefs)); - IfFailThrow(pImport->CountEnum(hEnum, &cRefs)); - pImport->CloseEnum(hEnum); - - if (cRefs > 0) - fMetadata = TRUE; - - // - // If we are the main module, we have the assembly def for the zap file. - // - - mdAssembly a; - if (pAssemblyImport->GetAssemblyFromScope(&a) == S_OK) - fMetadata = TRUE; - } - - if (fMetadata) - { - // Metadata creates a new MVID for every instantiation. - // However, we want the generated ngen image to always be the same - // for the same input. So set the metadata MVID to NGEN_IMAGE_MVID. - - NonVMComHolder pMDInternalEmit; - IfFailThrow(m_pAssemblyEmit->QueryInterface(IID_IMDInternalEmit, - (void**)&pMDInternalEmit)); - - IfFailThrow(pMDInternalEmit->ChangeMvid(NGEN_IMAGE_MVID)); - - m_pAssemblyMetaData = new (GetHeap()) ZapMetaData(); - m_pAssemblyMetaData->SetMetaData(m_pAssemblyEmit); - - m_pMetaDataSection->Place(m_pAssemblyMetaData); - } -} - -void ZapImage::OutputTables() -{ - // - // Copy over any resources to the native image - // - - COUNT_T size; - PVOID resource = (PVOID)m_ModuleDecoder.GetResources(&size); - - if (size != 0) - { - m_pResources = new (GetHeap()) ZapBlobPtr(resource, size); - m_pResourcesSection->Place(m_pResources); - } - - CopyDebugDirEntry(); - CopyWin32Resources(); - - if (m_pILMetaData != NULL) - { - m_pILMetaData->CopyIL(); - m_pILMetaData->CopyMetaData(); - } - - if (IsReadyToRunCompilation()) - { - m_pILMetaData->CopyRVAFields(); - } - - // Copy over the timestamp from IL image for determinism - SetTimeDateStamp(m_ModuleDecoder.GetTimeDateStamp()); - - SetSubsystem(m_ModuleDecoder.GetSubsystem()); - - { - USHORT dllCharacteristics = 0; - -#ifndef TARGET_64BIT - dllCharacteristics |= IMAGE_DLLCHARACTERISTICS_NO_SEH; -#endif - -#ifdef TARGET_ARM - // Images without NX compat bit set fail to load on ARM - dllCharacteristics |= IMAGE_DLLCHARACTERISTICS_NX_COMPAT; -#endif - - // Copy over selected DLL characteristics bits from IL image - dllCharacteristics |= (m_ModuleDecoder.GetDllCharacteristics() & - (IMAGE_DLLCHARACTERISTICS_NX_COMPAT | IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE | IMAGE_DLLCHARACTERISTICS_APPCONTAINER)); - -#ifdef _DEBUG - if (0 == CLRConfig::GetConfigValue(CLRConfig::INTERNAL_NoASLRForNgen)) -#endif // _DEBUG - { - dllCharacteristics |= IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; -#ifdef TARGET_64BIT - // Large address aware, required for High Entry VA, is always enabled for 64bit native images. - dllCharacteristics |= IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA; -#endif - } - - SetDllCharacteristics(dllCharacteristics); - } - - if (IsReadyToRunCompilation()) - { - - SetSizeOfStackReserve(m_ModuleDecoder.GetSizeOfStackReserve()); - SetSizeOfStackCommit(m_ModuleDecoder.GetSizeOfStackCommit()); - } - -#if defined(TARGET_UNIX) && !defined(TARGET_64BIT) - // To minimize wasted VA space on 32-bit systems, align file to page boundaries (presumed to be 4K). - SetFileAlignment(0x1000); -#elif defined(TARGET_ARM) && defined(FEATURE_CORESYSTEM) - if (!IsReadyToRunCompilation()) - { - // On ARM CoreSys builds, crossgen will use 4k file alignment, as requested by Phone perf team - // to improve perf on phones with compressed system partitions. - SetFileAlignment(0x1000); - } -#endif -} - -ZapImage::CompileStatus ZapImage::CompileProfileDataWorker(mdToken token, unsigned methodProfilingDataFlags) -{ - if ((TypeFromToken(token) != mdtMethodDef) || - (!m_pMDImport->IsValidToken(token))) - { - m_zapper->Info(W("Warning: Invalid method token %08x in profile data.\n"), token); - return NOT_COMPILED; - } - -#ifdef _DEBUG - static ConfigDWORD g_NgenOrder; - - if ((g_NgenOrder.val(CLRConfig::INTERNAL_NgenOrder) & 2) == 2) - { - const ProfileDataHashEntry * foundEntry = profileDataHashTable.LookupPtr(token); - - if (foundEntry == NULL) - return NOT_COMPILED; - - // The md must match. - _ASSERTE(foundEntry->md == token); - // The target position cannot be 0. - _ASSERTE(foundEntry->pos > 0); - } -#endif - - // Now compile the method - return TryCompileMethodDef(token, methodProfilingDataFlags); -} - -// ProfileDisableInlining -// Before we start compiling any methods we may need to suppress the inlining -// of certain methods based upon our profile data. -// This method will arrange to disable this inlining. -// -void ZapImage::ProfileDisableInlining() -{ - // We suppress the inlining of any Hot methods that have the ExcludeHotMethodCode flag. - // We want such methods to be Jitted at runtime rather than compiled in the AOT native image. - // The inlining of such a method also need to be suppressed. - // - ProfileDataSection* methodProfileData = &(m_profileDataSections[MethodProfilingData]); - if (methodProfileData->tableSize > 0) - { - for (DWORD i = 0; i < methodProfileData->tableSize; i++) - { - CORBBTPROF_TOKEN_INFO * pTokenInfo = &(methodProfileData->pTable[i]); - unsigned methodProfilingDataFlags = pTokenInfo->flags; - - // Hot methods can be marked to be excluded from the AOT native image. - // We also need to disable inlining of such methods. - // - if ((methodProfilingDataFlags & (1 << DisableInlining)) != 0) - { - // Disable the inlining of this method - // - // @ToDo: Figure out how to disable inlining for this method. - } - } - } -} - -// CompileHotRegion -// Performs the compilation and placement for all methods in the "Hot" code region -// Methods placed in this region typically correspond to all of the methods that were -// executed during any of the profiling scenarios. -// -void ZapImage::CompileHotRegion() -{ - // Compile all of the methods that were executed during profiling into the "Hot" code region. - // - BeginRegion(CORINFO_REGION_HOT); - - CorProfileData* pProfileData = GetProfileData(); - - ProfileDataSection* methodProfileData = &(m_profileDataSections[MethodProfilingData]); - if (methodProfileData->tableSize > 0) - { - // record the start of hot IBC methods. - m_iIBCMethod = m_MethodCompilationOrder.GetCount(); - - // - // Compile the hot methods in the order specified in the MethodProfilingData - // - for (DWORD i = 0; i < methodProfileData->tableSize; i++) - { - CompileStatus compileResult = NOT_COMPILED; - CORBBTPROF_TOKEN_INFO * pTokenInfo = &(methodProfileData->pTable[i]); - - mdToken token = pTokenInfo->token; - unsigned methodProfilingDataFlags = pTokenInfo->flags; - _ASSERTE(methodProfilingDataFlags != 0); - - if (TypeFromToken(token) == mdtMethodDef) - { - // - // Compile a non-generic method - // - compileResult = CompileProfileDataWorker(token, methodProfilingDataFlags); - } - else if (TypeFromToken(token) == ibcMethodSpec) - { - // - // Compile a generic/parameterized method - // - CORBBTPROF_BLOB_PARAM_SIG_ENTRY *pBlobSigEntry = pProfileData->GetBlobSigEntry(token); - - if (pBlobSigEntry == NULL) - { - m_zapper->Info(W("Warning: Did not find definition for method token %08x in profile data.\n"), token); - } - else // (pBlobSigEntry != NULL) - { - _ASSERTE(pBlobSigEntry->blob.token == token); - - // decode method desc - CORINFO_METHOD_HANDLE pMethod = m_pPreloader->FindMethodForProfileEntry(pBlobSigEntry); - - if (pMethod) - { - m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(pMethod); - - compileResult = TryCompileInstantiatedMethod(pMethod, methodProfilingDataFlags); - } - else - { - // This generic/parameterized method is not part of the native image - // Either the IBC type specified no longer exists or it is a SIMD types - // or the type can't be loaded in a ReadyToRun native image because of - // a cross-module type dependencies. - // - compileResult = COMPILE_EXCLUDED; - } - } - } - - // Update the 'flags' and 'compileResult' saved in the profileDataHashTable hash table. - // - hashBBUpdateFlagsAndCompileResult(token, methodProfilingDataFlags, compileResult); - } - // record the start of hot Generics methods. - m_iGenericsMethod = m_MethodCompilationOrder.GetCount(); - } - - // record the start of untrained code - m_iUntrainedMethod = m_MethodCompilationOrder.GetCount(); - - EndRegion(CORINFO_REGION_HOT); -} - -// CompileColdRegion -// Performs the compilation and placement for all methods in the "Cold" code region -// Methods placed in this region typically correspond to all of the methods that were -// NOT executed during any of the profiling scenarios. -// -void ZapImage::CompileColdRegion() -{ - // Compile all of the methods that were NOT executed during profiling into the "Cold" code region. - // - - BeginRegion(CORINFO_REGION_COLD); - - IMDInternalImport * pMDImport = m_pMDImport; - - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumAllInit(mdtMethodDef); - - mdMethodDef md; - while (pMDImport->EnumNext(&hEnum, &md)) - { - // - // Compile the remaining methods that weren't compiled during the CompileHotRegion phase - // - TryCompileMethodDef(md, 0); - } - - // Compile any generic code which lands in this LoaderModule - // that resulted from the above compilations - CORINFO_METHOD_HANDLE handle = m_pPreloader->NextUncompiledMethod(); - while (handle != NULL) - { - TryCompileInstantiatedMethod(handle, 0); - handle = m_pPreloader->NextUncompiledMethod(); - } - - EndRegion(CORINFO_REGION_COLD); -} - -// PlaceMethodIL -// Copy the IL for all method into the AOT native image -// -void ZapImage::PlaceMethodIL() -{ - // Place the IL for all of the methods - // - IMDInternalImport * pMDImport = m_pMDImport; - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumAllInit(mdtMethodDef); - - mdMethodDef md; - while (pMDImport->EnumNext(&hEnum, &md)) - { - if (m_pILMetaData != NULL) - { - // Copy IL for all methods. We treat errors during copying IL - // over as fatal error. These errors are typically caused by - // corrupted IL images. - // - m_pILMetaData->EmitMethodIL(md); - } - } -} - -void ZapImage::Compile() -{ - // - // Compile all of the methods for our AOT native image - // - - bool doNothingNgen = false; -#ifdef _DEBUG - static ConfigDWORD fDoNothingNGen; - doNothingNgen = !!fDoNothingNGen.val(CLRConfig::INTERNAL_ZapDoNothing); -#endif - - ProfileDisableInlining(); - - if (!doNothingNgen) - { - CompileHotRegion(); - - CompileColdRegion(); - } - - PlaceMethodIL(); - - // Compute a preferred class layout order based on analyzing the graph - // of which classes contain calls to other classes. - ComputeClassLayoutOrder(); - - // Sort the unprofiled methods by this preferred class layout, if available - if (m_fHasClassLayoutOrder) - { - SortUnprofiledMethodsByClassLayoutOrder(); - } - - if (IsReadyToRunCompilation()) - { - // Pretend that no methods are trained, so that everything is in single code section - // READYTORUN: FUTURE: More than one code section - m_iUntrainedMethod = 0; - } - - OutputCode(ProfiledHot); - OutputCode(Unprofiled); - OutputCode(ProfiledCold); - - OutputCodeInfo(ProfiledHot); - OutputCodeInfo(ProfiledCold); // actually both Unprofiled and ProfiledCold - - OutputGCInfo(); - OutputProfileData(); - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - OutputEntrypointsTableForReadyToRun(); - OutputDebugInfoForReadyToRun(); - OutputTypesTableForReadyToRun(m_pMDImport); - OutputAttributePresenceFilter(m_pMDImport); - OutputInliningTableForReadyToRun(); - OutputProfileDataForReadyToRun(); - if (IsLargeVersionBubbleEnabled()) - { - OutputManifestMetadataForReadyToRun(); - } - } - else -#endif - { - OutputDebugInfo(); - } -} - -struct CompileMethodStubContext -{ - ZapImage * pImage; - unsigned methodProfilingDataFlags; - ZapImage::CompileStatus enumCompileStubResult; - - CompileMethodStubContext(ZapImage * _image, unsigned _methodProfilingDataFlags) - { - pImage = _image; - methodProfilingDataFlags = _methodProfilingDataFlags; - enumCompileStubResult = ZapImage::NOT_COMPILED; - } -}; - -//----------------------------------------------------------------------------- -// This method is a callback function use to compile any IL_STUBS that are -// associated with a normal IL method. It is called from CompileMethodStubIfNeeded -// via the function pointer stored in the CompileMethodStubContext. -// It handles the temporary change to the m_compilerFlags and removes any flags -// that we don't want set when compiling IL_STUBS. -//----------------------------------------------------------------------------- - -// static void __stdcall -void ZapImage::TryCompileMethodStub(LPVOID pContext, CORINFO_METHOD_HANDLE hStub, CORJIT_FLAGS jitFlags) -{ - STANDARD_VM_CONTRACT; - - // The caller must always set the IL_STUB flag - _ASSERTE(jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)); - - CompileMethodStubContext *pCompileContext = reinterpret_cast(pContext); - ZapImage *pImage = pCompileContext->pImage; - - CORJIT_FLAGS oldFlags = pImage->m_zapper->m_pOpt->m_compilerFlags; - - CORJIT_FLAGS* pCompilerFlags = &pImage->m_zapper->m_pOpt->m_compilerFlags; - pCompilerFlags->Add(jitFlags); - pCompilerFlags->Clear(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE); - pCompilerFlags->Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE); - pCompilerFlags->Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_EnC); - pCompilerFlags->Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); - - mdMethodDef md = mdMethodDefNil; - - pCompileContext->enumCompileStubResult = pImage->TryCompileMethodWorker(hStub, md, - pCompileContext->methodProfilingDataFlags); - - pImage->m_zapper->m_pOpt->m_compilerFlags = oldFlags; -} - -//----------------------------------------------------------------------------- -// Helper for ZapImage::TryCompileMethodDef that indicates whether a given method def token refers to a -// "vtable gap" method. These are pseudo-methods used to lay out the vtable for COM interop and as such don't -// have any associated code (or even a method handle). -//----------------------------------------------------------------------------- -BOOL ZapImage::IsVTableGapMethod(mdMethodDef md) -{ - HRESULT hr; - DWORD dwAttributes; - - // Get method attributes and check that RTSpecialName was set for the method (this means the name has - // semantic import to the runtime and must be formatted rigorously with one of a few well-known rules). - // Note that we just return false on any failure path since this will just lead to our caller continuing - // to throw the exception they were about to anyway. - hr = m_pMDImport->GetMethodDefProps(md, &dwAttributes); - if (FAILED(hr) || !IsMdRTSpecialName(dwAttributes)) - return FALSE; - - // Now check the name of the method. All vtable gap methods will have a prefix of "_VtblGap". - LPCSTR szMethod; - PCCOR_SIGNATURE pvSigBlob; - ULONG cbSigBlob; - hr = m_pMDImport->GetNameAndSigOfMethodDef(md, &pvSigBlob, &cbSigBlob, &szMethod); - if (FAILED(hr) || (strncmp(szMethod, "_VtblGap", 8) != 0)) - return FALSE; - - // If we make it to here we have a vtable gap method. - return TRUE; -} - -//----------------------------------------------------------------------------- -// This function is called for non-generic methods in the current assembly, -// and for the typical "System.__Canon" instantiations of generic methods -// in the current assembly. -//----------------------------------------------------------------------------- - -ZapImage::CompileStatus ZapImage::TryCompileMethodDef(mdMethodDef md, unsigned methodProfilingDataFlags) -{ - _ASSERTE(!IsNilToken(md)); - - CORINFO_METHOD_HANDLE handle = NULL; - CompileStatus result = NOT_COMPILED; - - if (ShouldCompileMethodDef(md)) - { - handle = m_pPreloader->LookupMethodDef(md); - if (handle == nullptr) - { - result = LOOKUP_FAILED; - } - } - else - { - result = COMPILE_EXCLUDED; - } - - if (handle == NULL) - return result; - - // compile the method - // - CompileStatus methodCompileStatus = TryCompileMethodWorker(handle, md, methodProfilingDataFlags); - - // Don't bother compiling the IL_STUBS if we failed to compile the parent IL method - // - if (methodCompileStatus == COMPILE_SUCCEED) - { - CompileMethodStubContext context(this, methodProfilingDataFlags); - - // compile stubs associated with the method - m_pPreloader->GenerateMethodStubs(handle, m_zapper->m_pOpt->m_ngenProfileImage, - &TryCompileMethodStub, - &context); - } - - return methodCompileStatus; -} - - -//----------------------------------------------------------------------------- -// This function is called for non-"System.__Canon" instantiations of generic methods. -// These could be methods defined in other assemblies too. -//----------------------------------------------------------------------------- - -ZapImage::CompileStatus ZapImage::TryCompileInstantiatedMethod(CORINFO_METHOD_HANDLE handle, - unsigned methodProfilingDataFlags) -{ - if (IsReadyToRunCompilation()) - { - if (!GetCompileInfo()->IsInCurrentVersionBubble(m_zapper->m_pEEJitInfo->getMethodModule(handle))) - return COMPILE_EXCLUDED; - } - - if (!ShouldCompileInstantiatedMethod(handle)) - return COMPILE_EXCLUDED; - - // If we compiling this method because it was specified by the IBC profile data - // then issue a warning if this method is not on our uncompiled method list. - // - if (methodProfilingDataFlags != 0) - { - if (methodProfilingDataFlags & (1 << ReadMethodCode)) - { - // When we have stale IBC data the method could have been rejected from this image. - if (!m_pPreloader->IsUncompiledMethod(handle)) - { - const char* szClsName; - const char* szMethodName = m_zapper->m_pEEJitInfo->getMethodName(handle, &szClsName); - - SString fullname(SString::Utf8, szClsName); - fullname.AppendUTF8(NAMESPACE_SEPARATOR_STR); - fullname.AppendUTF8(szMethodName); - - m_zapper->Info(W("Warning: Invalid method instantiation in profile data: %s\n"), fullname.GetUnicode()); - - return NOT_COMPILED; - } - } - } - - CompileStatus methodCompileStatus = TryCompileMethodWorker(handle, mdMethodDefNil, methodProfilingDataFlags); - - // Don't bother compiling the IL_STUBS if we failed to compile the parent IL method - // - if (methodCompileStatus == COMPILE_SUCCEED) - { - CompileMethodStubContext context(this, methodProfilingDataFlags); - - // compile stubs associated with the method - m_pPreloader->GenerateMethodStubs(handle, m_zapper->m_pOpt->m_ngenProfileImage, - &TryCompileMethodStub, - &context); - } - - return methodCompileStatus; -} - -//----------------------------------------------------------------------------- - -ZapImage::CompileStatus ZapImage::TryCompileMethodWorker(CORINFO_METHOD_HANDLE handle, mdMethodDef md, - unsigned methodProfilingDataFlags) -{ - _ASSERTE(handle != NULL); - - if (m_zapper->m_pOpt->m_onlyOneMethod && (m_zapper->m_pOpt->m_onlyOneMethod != md)) - return NOT_COMPILED; - - if (GetCompileInfo()->HasCustomAttribute(handle, "System.Runtime.BypassNGenAttribute")) - return NOT_COMPILED; - -#ifdef FEATURE_READYTORUN_COMPILER - // This is a quick workaround to opt specific methods out of ReadyToRun compilation to work around bugs. - if (IsReadyToRunCompilation()) - { - if (GetCompileInfo()->HasCustomAttribute(handle, "System.Runtime.BypassReadyToRunAttribute")) - return NOT_COMPILED; - } -#endif - - // Do we have a profile entry for this method? - // - if (methodProfilingDataFlags != 0) - { - // Report the profiling data flags for layout of the EE data structures - m_pPreloader->SetMethodProfilingFlags(handle, methodProfilingDataFlags); - - // Hot methods can be marked to be excluded from the AOT native image. - // A Jitted method executes faster than a ReadyToRun compiled method. - // - if ((methodProfilingDataFlags & (1 << ExcludeHotMethodCode)) != 0) - { - // returning COMPILE_HOT_EXCLUDED excludes this method from the AOT native image - return COMPILE_HOT_EXCLUDED; - } - - // Cold methods can be marked to be excluded from the AOT native image. - // We can reduce the size of the AOT native image by selectively - // excluding the code for some of the cold methods. - // - if ((methodProfilingDataFlags & (1 << ExcludeColdMethodCode)) != 0) - { - // returning COMPILE_COLD_EXCLUDED excludes this method from the AOT native image - return COMPILE_COLD_EXCLUDED; - } - - // If the code was never executed based on the profile data - // then don't compile this method now. Wait until later - // when we are compiling the methods in the cold section. - // - if ((methodProfilingDataFlags & (1 << ReadMethodCode)) == 0) - { - // returning NOT_COMPILED will defer until later the compilation of this method - return NOT_COMPILED; - } - } - else // we are compiling methods for the cold region - { - // Retrieve any information that we have about a previous compilation attempt of this method - const ProfileDataHashEntry* pEntry = profileDataHashTable.LookupPtr(md); - - // When Partial Ngen is specified we will omit the AOT native code for every - // method that does not have profile data - // - if (pEntry == nullptr && m_zapper->m_pOpt->m_fPartialNGen) - { - // returning COMPILE_COLD_EXCLUDED excludes this method from the AOT native image - return COMPILE_COLD_EXCLUDED; - } - - if (pEntry != nullptr) - { - if ((pEntry->status == COMPILE_HOT_EXCLUDED) || (pEntry->status == COMPILE_COLD_EXCLUDED)) - { - // returning COMPILE_HOT_EXCLUDED excludes this method from the AOT native image - return pEntry->status; - } - } - } - - // Have we already compiled it? - if (GetCompiledMethod(handle) != NULL) - return ALREADY_COMPILED; - - _ASSERTE(m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB) || IsNilToken(md) || handle == m_pPreloader->LookupMethodDef(md)); - - CompileStatus result = NOT_COMPILED; - - CORINFO_MODULE_HANDLE module; - - // We only compile IL_STUBs from the current assembly - if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) - module = m_hModule; - else - module = m_zapper->m_pEEJitInfo->getMethodModule(handle); - - ZapInfo zapInfo(this, md, handle, module, methodProfilingDataFlags); - - EX_TRY - { - zapInfo.CompileMethod(); - result = COMPILE_SUCCEED; - } - EX_CATCH - { - // Continue unwinding if fatal error was hit. - if (FAILED(g_hrFatalError)) - ThrowHR(g_hrFatalError); - - Exception *ex = GET_EXCEPTION(); - HRESULT hrException = ex->GetHR(); - - CorZapLogLevel level; - -#ifdef CROSSGEN_COMPILE - // Warnings should not go to stderr during crossgen - level = CORZAP_LOGLEVEL_WARNING; -#else - level = CORZAP_LOGLEVEL_ERROR; - - m_zapper->m_failed = TRUE; -#endif - - result = COMPILE_FAILED; - -#ifdef FEATURE_READYTORUN_COMPILER - // NYI features in R2R - Stop crossgen from spitting unnecessary - // messages to the console - if (IsReadyToRunCompilation()) - { - // When compiling the method, we may receive an exception when the - // method uses a feature that is Not Implemented for ReadyToRun - // or a Type Load exception if the method uses a SIMD type. - // - // We skip the compilation of such methods and we don't want to - // issue a warning or error - // - if ((hrException == E_NOTIMPL) || (hrException == (HRESULT)IDS_CLASSLOAD_GENERAL)) - { - result = NOT_COMPILED; - level = CORZAP_LOGLEVEL_INFO; - } - } -#endif - { - StackSString message; - ex->GetMessage(message); - - // FileNotFound errors here can be converted into a single error string per ngen compile, - // and the detailed error is available with verbose logging - if (hrException == COR_E_FILENOTFOUND) - { - StackSString logMessage(W("System.IO.FileNotFoundException: ")); - logMessage.Append(message); - FileNotFoundError(logMessage.GetUnicode()); - level = CORZAP_LOGLEVEL_INFO; - } - - m_zapper->Print(level, W("%s while compiling method %s\n"), message.GetUnicode(), zapInfo.m_currentMethodName.GetUnicode()); - - if ((result == COMPILE_FAILED) && (m_stats != NULL)) - { - if (!m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) - m_stats->m_failedMethods++; - else - m_stats->m_failedILStubs++; - } - } - } - EX_END_CATCH(SwallowAllExceptions); - - return result; -} - - -// Should we compile this method, defined in the ngen'ing module? -// Result is FALSE if any of the controls (only used by prejit.exe) exclude the method -BOOL ZapImage::ShouldCompileMethodDef(mdMethodDef md) -{ - DWORD partialNGenStressVal = PartialNGenStressPercentage(); - if (partialNGenStressVal) - { - _ASSERTE(partialNGenStressVal <= 100); - DWORD methodPercentageVal = (md % 100) + 1; - if (methodPercentageVal <= partialNGenStressVal) - return FALSE; - } - - mdTypeDef td; - IfFailThrow(m_pMDImport->GetParentToken(md, &td)); - -#ifdef FEATURE_COMINTEROP - mdToken tkExtends; - if (td != mdTypeDefNil) - { - IfFailThrow(m_pMDImport->GetTypeDefProps(td, NULL, &tkExtends)); - - mdAssembly tkAssembly; - DWORD dwAssemblyFlags; - - IfFailThrow(m_pMDImport->GetAssemblyFromScope(&tkAssembly)); - if (TypeFromToken(tkAssembly) == mdtAssembly) - { - IfFailThrow(m_pMDImport->GetAssemblyProps(tkAssembly, - NULL, NULL, // Public Key - NULL, // Hash Algorithm - NULL, // Name - NULL, // MetaData - &dwAssemblyFlags)); - - if (IsAfContentType_WindowsRuntime(dwAssemblyFlags)) - { - if (TypeFromToken(tkExtends) == mdtTypeRef) - { - LPCSTR szNameSpace = NULL; - LPCSTR szName = NULL; - IfFailThrow(m_pMDImport->GetNameOfTypeRef(tkExtends, &szNameSpace, &szName)); - - if (!strcmp(szNameSpace, "System") && !_stricmp((szName), "Attribute")) - { - return FALSE; - } - } - } - } - } -#endif - -#ifdef _DEBUG - static ConfigMethodSet fZapOnly; - fZapOnly.ensureInit(CLRConfig::INTERNAL_ZapOnly); - - static ConfigMethodSet fZapExclude; - fZapExclude.ensureInit(CLRConfig::INTERNAL_ZapExclude); - - PCCOR_SIGNATURE pvSigBlob; - ULONG cbSigBlob; - - // Get the name of the current method and its class - LPCSTR szMethod; - IfFailThrow(m_pMDImport->GetNameAndSigOfMethodDef(md, &pvSigBlob, &cbSigBlob, &szMethod)); - - LPCWSTR wszClass = W(""); - SString sClass; - - if (td != mdTypeDefNil) - { - LPCSTR szNameSpace = NULL; - LPCSTR szName = NULL; - - IfFailThrow(m_pMDImport->GetNameOfTypeDef(td, &szName, &szNameSpace)); - - const SString nameSpace(SString::Utf8, szNameSpace); - const SString name(SString::Utf8, szName); - sClass.MakeFullNamespacePath(nameSpace, name); - wszClass = sClass.GetUnicode(); - } - - MAKE_UTF8PTR_FROMWIDE(szClass, wszClass); - - if (!fZapOnly.isEmpty() && !fZapOnly.contains(szMethod, szClass, pvSigBlob)) - { - LOG((LF_ZAP, LL_INFO1000, "Rejecting compilation of method %08x, %s::%s\n", md, szClass, szMethod)); - return FALSE; - } - - if (fZapExclude.contains(szMethod, szClass, pvSigBlob)) - { - LOG((LF_ZAP, LL_INFO1000, "Rejecting compilation of method %08x, %s::%s\n", md, szClass, szMethod)); - return FALSE; - } - - LOG((LF_ZAP, LL_INFO1000, "Compiling method %08x, %s::%s\n", md, szClass, szMethod)); -#endif - - return TRUE; -} - - -BOOL ZapImage::ShouldCompileInstantiatedMethod(CORINFO_METHOD_HANDLE handle) -{ - DWORD partialNGenStressVal = PartialNGenStressPercentage(); - if (partialNGenStressVal) - { - _ASSERTE(partialNGenStressVal <= 100); - DWORD methodPercentageVal = (m_zapper->m_pEEJitInfo->getMethodHash(handle) % 100) + 1; - if (methodPercentageVal <= partialNGenStressVal) - return FALSE; - } - - return TRUE; -} - -HRESULT ZapImage::PrintTokenDescription(CorZapLogLevel level, mdToken token) -{ - HRESULT hr; - - if (RidFromToken(token) == 0) - return S_OK; - - LPCSTR szNameSpace = NULL; - LPCSTR szName = NULL; - - if (m_pMDImport->IsValidToken(token)) - { - switch (TypeFromToken(token)) - { - case mdtMemberRef: - { - mdToken parent; - IfFailRet(m_pMDImport->GetParentOfMemberRef(token, &parent)); - if (RidFromToken(parent) != 0) - { - PrintTokenDescription(level, parent); - m_zapper->Print(level, W(".")); - } - IfFailRet(m_pMDImport->GetNameAndSigOfMemberRef(token, NULL, NULL, &szName)); - break; - } - - case mdtMethodDef: - { - mdToken parent; - IfFailRet(m_pMDImport->GetParentToken(token, &parent)); - if (RidFromToken(parent) != 0) - { - PrintTokenDescription(level, parent); - m_zapper->Print(level, W(".")); - } - IfFailRet(m_pMDImport->GetNameOfMethodDef(token, &szName)); - break; - } - - case mdtTypeRef: - { - IfFailRet(m_pMDImport->GetNameOfTypeRef(token, &szNameSpace, &szName)); - break; - } - - case mdtTypeDef: - { - IfFailRet(m_pMDImport->GetNameOfTypeDef(token, &szName, &szNameSpace)); - break; - } - - default: - break; - } - } - else - { - szName = "InvalidToken"; - } - - SString fullName; - - if (szNameSpace != NULL) - { - const SString nameSpace(SString::Utf8, szNameSpace); - const SString name(SString::Utf8, szName); - fullName.MakeFullNamespacePath(nameSpace, name); - } - else - { - fullName.SetUTF8(szName); - } - - m_zapper->Print(level, W("%s"), fullName.GetUnicode()); - - return S_OK; -} - - -HRESULT ZapImage::LocateProfileData() -{ - if (m_zapper->m_pOpt->m_ignoreProfileData) - { - return S_FALSE; - } - - // - // In the past, we have ignored profile data when instrumenting the assembly. - // However, this creates significant differences between the tuning image and the eventual - // optimized image (e.g. generic instantiations) which in turn leads to missed data during - // training and cold touches during execution. Instead, we take advantage of any IBC data - // the assembly already has and attempt to make the tuning image as close as possible to - // the final image. - // -#if 0 - if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR)) - return S_FALSE; -#endif - - // - // See if there's profile data in the resource section of the PE - // - m_pRawProfileData = (BYTE*)m_ModuleDecoder.GetWin32Resource(W("PROFILE_DATA"), W("IBC"), &m_cRawProfileData); - - if ((m_pRawProfileData != NULL) && (m_cRawProfileData != 0)) - { - m_zapper->Info(W("Found embedded profile resource in %s.\n"), m_pModuleFileName); - return S_OK; - } - - static ConfigDWORD g_UseIBCFile; - if (g_UseIBCFile.val(CLRConfig::EXTERNAL_UseIBCFile) != 1) - return S_OK; - - // - // Couldn't find profile resource--let's see if there's an ibc file to use instead - // - - SString path(m_pModuleFileName); - - SString::Iterator dot = path.End(); - if (path.FindBack(dot, '.')) - { - SString slName(SString::Literal, "ibc"); - path.Replace(dot+1, path.End() - (dot+1), slName); - - HandleHolder hFile = WszCreateFile(path.GetUnicode(), - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, - NULL); - if (hFile != INVALID_HANDLE_VALUE) - { - HandleHolder hMapFile = WszCreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); - DWORD dwFileLen = SafeGetFileSize(hFile, 0); - if (dwFileLen != INVALID_FILE_SIZE) - { - if (hMapFile == NULL) - { - m_zapper->Warning(W("Found profile data file %s, but could not open it"), path.GetUnicode()); - } - else - { - m_zapper->Info(W("Found ibc file %s.\n"), path.GetUnicode()); - - m_profileDataFile = (BYTE*) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0); - - m_pRawProfileData = m_profileDataFile; - m_cRawProfileData = dwFileLen; - } - } - } - } - - return S_OK; -} - - -bool ZapImage::CanConvertIbcData() -{ - static ConfigDWORD g_iConvertIbcData; - DWORD val = g_iConvertIbcData.val(CLRConfig::UNSUPPORTED_ConvertIbcData); - return (val != 0); -} - -HRESULT ZapImage::parseProfileData() -{ - if (m_pRawProfileData == NULL) - { - return S_FALSE; - } - - ProfileReader profileReader(m_pRawProfileData, m_cRawProfileData); - - CORBBTPROF_FILE_HEADER *fileHeader; - - READ(fileHeader, CORBBTPROF_FILE_HEADER); - if (fileHeader->HeaderSize < sizeof(CORBBTPROF_FILE_HEADER)) - { - _ASSERTE(!"HeaderSize is too small"); - return E_FAIL; - } - - // Read any extra header data. It will be needed for V3 files. - - DWORD extraHeaderDataSize = fileHeader->HeaderSize - sizeof(CORBBTPROF_FILE_HEADER); - void *extraHeaderData = profileReader.Read(extraHeaderDataSize); - - bool convertFromV1 = false; - bool minified = false; - - if (fileHeader->Magic != CORBBTPROF_MAGIC) - { - _ASSERTE(!"ibcHeader contains bad values"); - return E_FAIL; - } - - // CoreCLR should never be presented with V1 IBC data. - if (fileHeader->Version == CORBBTPROF_V3_VERSION) - { - CORBBTPROF_FILE_OPTIONAL_HEADER *optionalHeader = - (CORBBTPROF_FILE_OPTIONAL_HEADER *)extraHeaderData; - - if (!optionalHeader || - !CONTAINS_FIELD(optionalHeader, extraHeaderDataSize, Size) || - (optionalHeader->Size > extraHeaderDataSize)) - { - m_zapper->Info(W("Optional header missing or corrupt.")); - return E_FAIL; - } - - if (CONTAINS_FIELD(optionalHeader, optionalHeader->Size, FileFlags)) - { - minified = !!(optionalHeader->FileFlags & CORBBTPROF_FILE_FLAG_MINIFIED); - - if (!m_zapper->m_pOpt->m_fPartialNGenSet) - { - m_zapper->m_pOpt->m_fPartialNGen = !!(optionalHeader->FileFlags & CORBBTPROF_FILE_FLAG_PARTIAL_NGEN); - } - } - } - else if (fileHeader->Version != CORBBTPROF_V2_VERSION) - { - m_zapper->Info(W("Discarding profile data with unknown version.")); - return S_FALSE; - } - - // This module has profile data (this ends up controlling the layout of physical and virtual - // sections within the image, see ZapImage::AllocateVirtualSections. - m_fHaveProfileData = true; - m_zapper->m_pOpt->m_fHasAnyProfileData = true; - - CORBBTPROF_SECTION_TABLE_HEADER *sectionHeader; - READ(sectionHeader, CORBBTPROF_SECTION_TABLE_HEADER); - - // - // Parse the section table - // - - for (ULONG i = 0; i < sectionHeader->NumEntries; i++) - { - CORBBTPROF_SECTION_TABLE_ENTRY *entry; - READ(entry,CORBBTPROF_SECTION_TABLE_ENTRY); - - SectionFormat format = sectionHeader->Entries[i].FormatID; - _ASSERTE(format >= 0); - if (format < 0) - { - continue; - } - - if (convertFromV1) - { - if (format < LastTokenFlagSection) - { - format = (SectionFormat) (format + 1); - } - } - - _ASSERTE(format < SectionFormatCount); - - if (format < SectionFormatCount) - { - BYTE *start = m_pRawProfileData + sectionHeader->Entries[i].Data.Offset; - BYTE *end = start + sectionHeader->Entries[i].Data.Size; - - if ((start > m_pRawProfileData) && - (end < m_pRawProfileData + m_cRawProfileData) && - (start < end)) - { - _ASSERTE(m_profileDataSections[format].pData == 0); - _ASSERTE(m_profileDataSections[format].dataSize == 0); - - m_profileDataSections[format].pData = start; - m_profileDataSections[format].dataSize = (DWORD) (end - start); - } - else - { - _ASSERTE(!"Invalid profile section offset or size"); - return E_FAIL; - } - } - } - - HRESULT hr = S_OK; - - if (convertFromV1) - { - hr = convertProfileDataFromV1(); - if (FAILED(hr)) - { - return hr; - } - } - else if (minified) - { - hr = RehydrateProfileData(); - if (FAILED(hr)) - { - return hr; - } - } - else - { - // - // For those sections that are collections of tokens, further parse that format to get - // the token pointer and number of tokens - // - - for (int format = FirstTokenFlagSection; format < SectionFormatCount; format++) - { - if (m_profileDataSections[format].pData) - { - SEEK(((ULONG) (m_profileDataSections[format].pData - m_pRawProfileData))); - - CORBBTPROF_TOKEN_LIST_SECTION_HEADER *header; - READ(header, CORBBTPROF_TOKEN_LIST_SECTION_HEADER); - - DWORD tableSize = header->NumTokens; - DWORD dataSize = (m_profileDataSections[format].dataSize - sizeof(CORBBTPROF_TOKEN_LIST_SECTION_HEADER)); - DWORD expectedSize = tableSize * sizeof (CORBBTPROF_TOKEN_INFO); - - if (dataSize == expectedSize) - { - BYTE * startOfTable = m_profileDataSections[format].pData + sizeof(CORBBTPROF_TOKEN_LIST_SECTION_HEADER); - m_profileDataSections[format].tableSize = tableSize; - m_profileDataSections[format].pTable = (CORBBTPROF_TOKEN_INFO *) startOfTable; - } - else - { - _ASSERTE(!"Invalid CORBBTPROF_TOKEN_LIST_SECTION_HEADER header"); - return E_FAIL; - } - } - } - } - - ZapImage::ProfileDataSection * DataSection_ScenarioInfo = & m_profileDataSections[ScenarioInfo]; - if (DataSection_ScenarioInfo->pData != NULL) - { - CORBBTPROF_SCENARIO_INFO_SECTION_HEADER * header = (CORBBTPROF_SCENARIO_INFO_SECTION_HEADER *) DataSection_ScenarioInfo->pData; - m_profileDataNumRuns = header->TotalNumRuns; - } - - return S_OK; -} - - -HRESULT ZapImage::convertProfileDataFromV1() -{ - if (m_pRawProfileData == NULL) - { - return S_FALSE; - } - - // - // For those sections that are collections of tokens, further parse that format to get - // the token pointer and number of tokens - // - - ProfileReader profileReader(m_pRawProfileData, m_cRawProfileData); - - for (SectionFormat format = FirstTokenFlagSection; format < SectionFormatCount; format = (SectionFormat) (format + 1)) - { - if (m_profileDataSections[format].pData) - { - SEEK(((ULONG) (m_profileDataSections[format].pData - m_pRawProfileData))); - - CORBBTPROF_TOKEN_LIST_SECTION_HEADER *header; - READ(header, CORBBTPROF_TOKEN_LIST_SECTION_HEADER); - - DWORD tableSize = header->NumTokens; - - if (tableSize == 0) - { - m_profileDataSections[format].tableSize = 0; - m_profileDataSections[format].pTable = NULL; - continue; - } - - DWORD dataSize = (m_profileDataSections[format].dataSize - sizeof(CORBBTPROF_TOKEN_LIST_SECTION_HEADER)); - DWORD expectedSize = tableSize * sizeof (CORBBTPROF_TOKEN_LIST_ENTRY_V1); - - if (dataSize == expectedSize) - { - DWORD newDataSize = tableSize * sizeof (CORBBTPROF_TOKEN_INFO); - - if (newDataSize < dataSize) - return E_FAIL; - - BYTE * startOfTable = new (GetHeap()) BYTE[newDataSize]; - - CORBBTPROF_TOKEN_LIST_ENTRY_V1 * pOldEntry; - CORBBTPROF_TOKEN_INFO * pNewEntry; - - pOldEntry = (CORBBTPROF_TOKEN_LIST_ENTRY_V1 *) (m_profileDataSections[format].pData + sizeof(CORBBTPROF_TOKEN_LIST_SECTION_HEADER)); - pNewEntry = (CORBBTPROF_TOKEN_INFO *) startOfTable; - - for (DWORD i=0; itoken = pOldEntry->token; - pNewEntry->flags = pOldEntry->flags; - pNewEntry->scenarios = 1; - - pOldEntry++; - pNewEntry++; - } - m_profileDataSections[format].tableSize = tableSize; - m_profileDataSections[format].pTable = (CORBBTPROF_TOKEN_INFO *) startOfTable; - } - else - { - _ASSERTE(!"Invalid CORBBTPROF_TOKEN_LIST_SECTION_HEADER header"); - return E_FAIL; - } - } - } - - _ASSERTE(m_profileDataSections[ScenarioInfo].pData == 0); - _ASSERTE(m_profileDataSections[ScenarioInfo].dataSize == 0); - - // - // Convert the MethodBlockCounts format from V1 to V2 - // - CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER_V1 * mbcSectionHeader = NULL; - if (m_profileDataSections[MethodBlockCounts].pData) - { - // - // Compute the size of the method block count stream - // - BYTE * dstPtr = NULL; - BYTE * srcPtr = m_profileDataSections[MethodBlockCounts].pData; - DWORD maxSizeToRead = m_profileDataSections[MethodBlockCounts].dataSize; - DWORD totalSizeNeeded = 0; - DWORD totalSizeRead = 0; - - mbcSectionHeader = (CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER_V1 *) srcPtr; - - totalSizeRead += sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER_V1); - totalSizeNeeded += sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER); - srcPtr += sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER_V1); - - if (totalSizeRead > maxSizeToRead) - { - return E_FAIL; - } - - for (DWORD i=0; (i < mbcSectionHeader->NumMethods); i++) - { - CORBBTPROF_METHOD_HEADER_V1* methodEntry = (CORBBTPROF_METHOD_HEADER_V1 *) srcPtr; - DWORD sizeRead = 0; - DWORD sizeWrite = 0; - - sizeRead += methodEntry->HeaderSize; - sizeRead += methodEntry->Size; - sizeWrite += sizeof(CORBBTPROF_METHOD_HEADER); - sizeWrite += methodEntry->Size; - - totalSizeRead += sizeRead; - totalSizeNeeded += sizeWrite; - - if (totalSizeRead > maxSizeToRead) - { - return E_FAIL; - } - - srcPtr += sizeRead; - } - assert(totalSizeRead == maxSizeToRead); - - // Reset the srcPtr - srcPtr = m_profileDataSections[MethodBlockCounts].pData; - - BYTE * newMethodData = new (GetHeap()) BYTE[totalSizeNeeded]; - - dstPtr = newMethodData; - - memcpy(dstPtr, srcPtr, sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER)); - srcPtr += sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER_V1); - dstPtr += sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER); - - for (DWORD i=0; (i < mbcSectionHeader->NumMethods); i++) - { - CORBBTPROF_METHOD_HEADER_V1 * methodEntryV1 = (CORBBTPROF_METHOD_HEADER_V1 *) srcPtr; - CORBBTPROF_METHOD_HEADER * methodEntry = (CORBBTPROF_METHOD_HEADER *) dstPtr; - DWORD sizeRead = 0; - DWORD sizeWrite = 0; - - methodEntry->method.token = methodEntryV1->MethodToken; - methodEntry->method.ILSize = 0; - methodEntry->method.cBlock = (methodEntryV1->Size / sizeof(CORBBTPROF_BLOCK_DATA)); - sizeRead += methodEntryV1->HeaderSize; - sizeWrite += sizeof(CORBBTPROF_METHOD_HEADER); - - memcpy( dstPtr + sizeof(CORBBTPROF_METHOD_HEADER), - srcPtr + sizeof(CORBBTPROF_METHOD_HEADER_V1), - (methodEntry->method.cBlock * sizeof(CORBBTPROF_BLOCK_DATA))); - sizeRead += methodEntryV1->Size; - sizeWrite += (methodEntry->method.cBlock * sizeof(CORBBTPROF_BLOCK_DATA)); - - methodEntry->size = sizeWrite; - methodEntry->cDetail = 0; - srcPtr += sizeRead; - dstPtr += sizeWrite; - } - - m_profileDataSections[MethodBlockCounts].pData = newMethodData; - m_profileDataSections[MethodBlockCounts].dataSize = totalSizeNeeded; - } - - // - // Allocate the scenario info section - // - { - DWORD sizeNeeded = sizeof(CORBBTPROF_SCENARIO_INFO_SECTION_HEADER) + sizeof(CORBBTPROF_SCENARIO_HEADER); - BYTE * newData = new (GetHeap()) BYTE[sizeNeeded]; - BYTE * dstPtr = newData; - { - CORBBTPROF_SCENARIO_INFO_SECTION_HEADER *siHeader = (CORBBTPROF_SCENARIO_INFO_SECTION_HEADER *) dstPtr; - - if (mbcSectionHeader != NULL) - siHeader->TotalNumRuns = mbcSectionHeader->NumRuns; - else - siHeader->TotalNumRuns = 1; - - siHeader->NumScenarios = 1; - - dstPtr += sizeof(CORBBTPROF_SCENARIO_INFO_SECTION_HEADER); - } - { - CORBBTPROF_SCENARIO_HEADER *sHeader = (CORBBTPROF_SCENARIO_HEADER *) dstPtr; - - sHeader->scenario.ordinal = 1; - sHeader->scenario.mask = 1; - sHeader->scenario.priority = 0; - sHeader->scenario.numRuns = 0; - sHeader->scenario.cName = 0; - - sHeader->size = sHeader->Size(); - - dstPtr += sizeof(CORBBTPROF_SCENARIO_HEADER); - } - m_profileDataSections[ScenarioInfo].pData = newData; - m_profileDataSections[ScenarioInfo].dataSize = sizeNeeded; - } - - // - // Convert the BlobStream format from V1 to V2 - // - if (m_profileDataSections[BlobStream].dataSize > 0) - { - // - // Compute the size of the blob stream - // - - BYTE * srcPtr = m_profileDataSections[BlobStream].pData; - BYTE * dstPtr = NULL; - DWORD maxSizeToRead = m_profileDataSections[BlobStream].dataSize; - DWORD totalSizeNeeded = 0; - DWORD totalSizeRead = 0; - bool done = false; - - while (!done) - { - CORBBTPROF_BLOB_ENTRY_V1* blobEntry = (CORBBTPROF_BLOB_ENTRY_V1 *) srcPtr; - DWORD sizeWrite = 0; - DWORD sizeRead = 0; - - if ((blobEntry->blobType >= MetadataStringPool) && (blobEntry->blobType <= MetadataUserStringPool)) - { - sizeWrite += sizeof(CORBBTPROF_BLOB_POOL_ENTRY); - sizeWrite += blobEntry->cBuffer; - sizeRead += sizeof(CORBBTPROF_BLOB_ENTRY_V1); - sizeRead += blobEntry->cBuffer; - } - else if ((blobEntry->blobType >= ParamTypeSpec) && (blobEntry->blobType <= ParamMethodSpec)) - { - sizeWrite += sizeof(CORBBTPROF_BLOB_PARAM_SIG_ENTRY); - sizeWrite += blobEntry->cBuffer; - if (blobEntry->blobType == ParamMethodSpec) - { - sizeWrite -= 1; // Adjust for ENCODE_METHOD_SIG prefix removal - } - sizeRead += sizeof(CORBBTPROF_BLOB_ENTRY_V1); - sizeRead += blobEntry->cBuffer; - } - else if (blobEntry->blobType == EndOfBlobStream) - { - sizeWrite += sizeof(CORBBTPROF_BLOB_ENTRY); - sizeRead += sizeof(CORBBTPROF_BLOB_ENTRY_V1); - done = true; - } - else - { - return E_FAIL; - } - - totalSizeNeeded += sizeWrite; - totalSizeRead += sizeRead; - - if (sizeRead > maxSizeToRead) - { - return E_FAIL; - } - - srcPtr += sizeRead; - } - - assert(totalSizeRead == maxSizeToRead); - - // Reset the srcPtr - srcPtr = m_profileDataSections[BlobStream].pData; - - BYTE * newBlobData = new (GetHeap()) BYTE[totalSizeNeeded]; - - dstPtr = newBlobData; - done = false; - - while (!done) - { - CORBBTPROF_BLOB_ENTRY_V1* blobEntryV1 = (CORBBTPROF_BLOB_ENTRY_V1 *) srcPtr; - DWORD sizeWrite = 0; - DWORD sizeRead = 0; - - if ((blobEntryV1->blobType >= MetadataStringPool) && (blobEntryV1->blobType <= MetadataUserStringPool)) - { - CORBBTPROF_BLOB_POOL_ENTRY* blobPoolEntry = (CORBBTPROF_BLOB_POOL_ENTRY*) dstPtr; - - blobPoolEntry->blob.type = blobEntryV1->blobType; - blobPoolEntry->blob.size = sizeof(CORBBTPROF_BLOB_POOL_ENTRY) + blobEntryV1->cBuffer; - blobPoolEntry->cBuffer = blobEntryV1->cBuffer; - memcpy(blobPoolEntry->buffer, blobEntryV1->pBuffer, blobEntryV1->cBuffer); - - sizeWrite += sizeof(CORBBTPROF_BLOB_POOL_ENTRY); - sizeWrite += blobEntryV1->cBuffer; - sizeRead += sizeof(CORBBTPROF_BLOB_ENTRY_V1); - sizeRead += blobEntryV1->cBuffer; - } - else if ((blobEntryV1->blobType >= ParamTypeSpec) && (blobEntryV1->blobType <= ParamMethodSpec)) - { - CORBBTPROF_BLOB_PARAM_SIG_ENTRY* blobSigEntry = (CORBBTPROF_BLOB_PARAM_SIG_ENTRY*) dstPtr; - - blobSigEntry->blob.type = blobEntryV1->blobType; - blobSigEntry->blob.size = sizeof(CORBBTPROF_BLOB_PARAM_SIG_ENTRY) + blobEntryV1->cBuffer; - blobSigEntry->blob.token = 0; - blobSigEntry->cSig = blobEntryV1->cBuffer; - - if (blobEntryV1->blobType == ParamMethodSpec) - { - // Adjust cSig and blob.size - blobSigEntry->cSig--; - blobSigEntry->blob.size--; - } - memcpy(blobSigEntry->sig, blobEntryV1->pBuffer, blobSigEntry->cSig); - - sizeWrite += sizeof(CORBBTPROF_BLOB_PARAM_SIG_ENTRY); - sizeWrite += blobSigEntry->cSig; - sizeRead += sizeof(CORBBTPROF_BLOB_ENTRY_V1); - sizeRead += blobEntryV1->cBuffer; - } - else if (blobEntryV1->blobType == EndOfBlobStream) - { - CORBBTPROF_BLOB_ENTRY* blobEntry = (CORBBTPROF_BLOB_ENTRY*) dstPtr; - - blobEntry->type = blobEntryV1->blobType; - blobEntry->size = sizeof(CORBBTPROF_BLOB_ENTRY); - - sizeWrite += sizeof(CORBBTPROF_BLOB_ENTRY); - sizeRead += sizeof(CORBBTPROF_BLOB_ENTRY_V1); - done = true; - } - else - { - return E_FAIL; - } - srcPtr += sizeRead; - dstPtr += sizeWrite; - } - - m_profileDataSections[BlobStream].pData = newBlobData; - m_profileDataSections[BlobStream].dataSize = totalSizeNeeded; - } - else - { - m_profileDataSections[BlobStream].pData = NULL; - m_profileDataSections[BlobStream].dataSize = 0; - } - - return S_OK; -} - -void ZapImage::RehydrateBasicBlockSection() -{ - ProfileDataSection §ion = m_profileDataSections[MethodBlockCounts]; - if (!section.pData) - { - return; - } - - ProfileReader reader(section.pData, section.dataSize); - - m_profileDataNumRuns = reader.Read(); - - // The IBC data provides a hint to the number of basic blocks, which is - // used here to determine how much space to allocate for the rehydrated - // data. - unsigned int blockCountHint = reader.Read(); - - unsigned int numMethods = reader.Read(); - - unsigned int expectedLength = - sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER) + - sizeof(CORBBTPROF_METHOD_HEADER) * numMethods + - sizeof(CORBBTPROF_BLOCK_DATA) * blockCountHint; - - BinaryWriter writer(expectedLength, GetHeap()); - - writer.Write(numMethods); - - mdToken lastMethodToken = 0x06000000; - - CORBBTPROF_METHOD_HEADER methodHeader; - methodHeader.cDetail = 0; - methodHeader.method.ILSize = 0; - - for (unsigned int i = 0; i < numMethods; ++i) - { - // Translate the method header - unsigned int size = reader.Read7BitEncodedInt(); - unsigned int startPosition = reader.GetCurrentPos(); - - mdToken token = reader.ReadTokenWithMemory(lastMethodToken); - unsigned int ilSize = reader.Read7BitEncodedInt(); - unsigned int firstBlockHitCount = reader.Read7BitEncodedInt(); - - unsigned int numOtherBlocks = reader.Read7BitEncodedInt(); - - methodHeader.method.cBlock = 1 + numOtherBlocks; - methodHeader.method.token = token; - methodHeader.method.ILSize = ilSize; - methodHeader.size = (DWORD)methodHeader.Size(); - - writer.Write(methodHeader); - - CORBBTPROF_BLOCK_DATA blockData; - - // The first block is handled specially. - blockData.ILOffset = 0; - blockData.ExecutionCount = firstBlockHitCount; - - writer.Write(blockData); - - // Translate the rest of the basic blocks - for (unsigned int j = 0; j < numOtherBlocks; ++j) - { - blockData.ILOffset = reader.Read7BitEncodedInt(); - blockData.ExecutionCount = reader.Read7BitEncodedInt(); - - writer.Write(blockData); - } - - if (!reader.Seek(startPosition + size)) - { - ThrowHR(E_FAIL); - } - } - - // If the expected and actual lengths differ, the result will still be - // correct but performance may suffer slightly because of reallocations. - _ASSERTE(writer.GetWrittenSize() == expectedLength); - - section.pData = writer.GetBuffer(); - section.dataSize = writer.GetWrittenSize(); -} - -void ZapImage::RehydrateTokenSection(int sectionFormat, unsigned int flagTable[255]) -{ - ProfileDataSection §ion = m_profileDataSections[sectionFormat]; - ProfileReader reader(section.pData, section.dataSize); - - unsigned int numTokens = reader.Read(); - - unsigned int dataLength = sizeof(unsigned int) + - numTokens * sizeof(CORBBTPROF_TOKEN_INFO); - BinaryWriter writer(dataLength, GetHeap()); - - writer.Write(numTokens); - - mdToken lastToken = (sectionFormat - FirstTokenFlagSection) << 24; - - CORBBTPROF_TOKEN_INFO tokenInfo; - tokenInfo.scenarios = 1; - - for (unsigned int i = 0; i < numTokens; ++i) - { - tokenInfo.token = reader.ReadTokenWithMemory(lastToken); - tokenInfo.flags = reader.ReadFlagWithLookup(flagTable); - - writer.Write(tokenInfo); - } - - _ASSERTE(writer.GetWrittenSize() == dataLength); - - section.pData = writer.GetBuffer(); - section.dataSize = writer.GetWrittenSize(); - section.pTable = (CORBBTPROF_TOKEN_INFO *)(section.pData + sizeof(unsigned int)); - section.tableSize = numTokens; -} - -void ZapImage::RehydrateBlobStream() -{ - ProfileDataSection §ion = m_profileDataSections[BlobStream]; - - ProfileReader reader(section.pData, section.dataSize); - - // Evidence suggests that rehydrating the blob stream in Framework binaries - // increases the size from 1.5-2x. When this was written, 1.85x minimized - // the amount of extra memory allocated (about 48K in the worst case). - BinaryWriter writer((DWORD)(section.dataSize * 1.85f), GetHeap()); - - mdToken LastBlobToken = 0; - mdToken LastAssemblyToken = 0x23000000; - mdToken LastExternalTypeToken = 0x62000000; - mdToken LastExternalNamespaceToken = 0x61000000; - mdToken LastExternalSignatureToken = 0x63000000; - - int blobType = 0; - do - { - // Read the blob header. - - unsigned int sizeToRead = reader.Read7BitEncodedInt(); - unsigned int startPositionRead = reader.GetCurrentPos(); - - blobType = reader.Read7BitEncodedInt(); - mdToken token = reader.ReadTokenWithMemory(LastBlobToken); - - // Write out the blob header. - - // Note the location in the write stream, and write a 0 there. Once - // this blob has been written in its entirety, this location can be - // used to calculate the real size and to go back to the right place - // to write it. - - unsigned int startPositionWrite = writer.GetWrittenSize(); - writer.Write(0U); - - writer.Write(blobType); - writer.Write(token); - - // All blobs (except the end-of-stream indicator) end as: - // - // Two blob types (handled immediately below) include tokens as well. - // Handle those first, then handle the common case. - - if (blobType == ExternalTypeDef) - { - writer.Write(reader.ReadTokenWithMemory(LastAssemblyToken)); - writer.Write(reader.ReadTokenWithMemory(LastExternalTypeToken)); - writer.Write(reader.ReadTokenWithMemory(LastExternalNamespaceToken)); - } - else if (blobType == ExternalMethodDef) - { - writer.Write(reader.ReadTokenWithMemory(LastExternalTypeToken)); - writer.Write(reader.ReadTokenWithMemory(LastExternalSignatureToken)); - } - - if ((blobType >= MetadataStringPool) && (blobType < IllegalBlob)) - { - // This blob is of known type and ends with data. - unsigned int dataLength = reader.Read7BitEncodedInt(); - char *data = (char *)reader.Read(dataLength); - - if (!data) - { - ThrowHR(E_FAIL); - } - - writer.Write(dataLength); - writer.Write(data, dataLength); - } - - // Write the size for this blob. - - writer.WriteAt(startPositionWrite, - writer.GetWrittenSize() - startPositionWrite); - - // Move to the next blob. - - if (!reader.Seek(startPositionRead + sizeToRead)) - { - ThrowHR(E_FAIL); - } - } - while (blobType != EndOfBlobStream); - - section.pData = writer.GetBuffer(); - section.dataSize = writer.GetWrittenSize(); -} - -HRESULT ZapImage::RehydrateProfileData() -{ - HRESULT hr = S_OK; - unsigned int flagTable[255]; - memset(flagTable, 0xFF, sizeof(flagTable)); - - EX_TRY - { - RehydrateBasicBlockSection(); - RehydrateBlobStream(); - for (int format = FirstTokenFlagSection; - format < SectionFormatCount; - ++format) - { - if (m_profileDataSections[format].pData) - { - RehydrateTokenSection(format, flagTable); - } - } - } - EX_CATCH_HRESULT_NO_ERRORINFO(hr); - - return hr; -} - -HRESULT ZapImage::hashMethodBlockCounts() -{ - ProfileDataSection * DataSection_MethodBlockCounts = & m_profileDataSections[MethodBlockCounts]; - - if (!DataSection_MethodBlockCounts->pData) - { - return E_FAIL; - } - - ProfileReader profileReader(DataSection_MethodBlockCounts->pData, DataSection_MethodBlockCounts->dataSize); - - CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER *mbcHeader; - READ(mbcHeader,CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER); - - for (DWORD i = 0; i < mbcHeader->NumMethods; i++) - { - ProfileDataHashEntry newEntry; - newEntry.pos = profileReader.GetCurrentPos(); - - CORBBTPROF_METHOD_HEADER *methodHeader; - READ(methodHeader,CORBBTPROF_METHOD_HEADER); - newEntry.md = methodHeader->method.token; - newEntry.size = methodHeader->size; - newEntry.flags = 0; - newEntry.status = NOT_COMPILED; - - // Add the new entry to the table - profileDataHashTable.Add(newEntry); - - // Skip the profileData so we can read the next method. - void *profileData; - READ_SIZE(profileData, void, (methodHeader->size - sizeof(CORBBTPROF_METHOD_HEADER))); - } - - return S_OK; -} - -void ZapImage::hashBBUpdateFlagsAndCompileResult(mdToken token, unsigned methodProfilingDataFlags, ZapImage::CompileStatus compileResult) -{ - // SHash only supports replacing an entry so we setup our newEntry and then perform a lookup - // - ProfileDataHashEntry newEntry; - newEntry.md = token; - newEntry.flags = methodProfilingDataFlags; - newEntry.status = compileResult; - - const ProfileDataHashEntry* pEntry = profileDataHashTable.LookupPtr(token); - if (pEntry != nullptr) - { - assert(pEntry->md == newEntry.md); - assert(pEntry->flags == 0); // the flags should not be set at this point. - - // Copy and keep the two fields that were previously set - newEntry.size = pEntry->size; - newEntry.pos = pEntry->pos; - } - else // We have a method that doesn't have basic block counts - { - newEntry.size = 0; - newEntry.pos = 0; - } - profileDataHashTable.AddOrReplace(newEntry); -} - -void ZapImage::LoadProfileData() -{ - HRESULT hr = E_FAIL; - - m_fHaveProfileData = false; - m_pRawProfileData = NULL; - m_cRawProfileData = 0; - - EX_TRY - { - hr = LocateProfileData(); - - if (hr == S_OK) - { - hr = parseProfileData(); - if (hr == S_OK) - { - hr = hashMethodBlockCounts(); - } - } - } - EX_CATCH - { - hr = E_FAIL; - } - EX_END_CATCH(SwallowAllExceptions); - - if (hr != S_OK) - { - m_fHaveProfileData = false; - m_pRawProfileData = NULL; - m_cRawProfileData = 0; - - if (FAILED(hr)) - { - m_zapper->Warning(W("Warning: Invalid profile data was ignored for %s\n"), m_pModuleFileName); - } - } - -#ifdef CROSSGEN_COMPILE - if (m_zapper->m_pOpt->m_fPartialNGen && (m_pRawProfileData == NULL || m_cRawProfileData == 0)) - { - ThrowHR(CLR_E_CROSSGEN_NO_IBC_DATA_FOUND); - } -#endif -} - -// Initializes our form of the profile data stored in the assembly. - -CorProfileData * ZapImage::NewProfileData() -{ - this->m_pCorProfileData = new CorProfileData(&m_profileDataSections[0]); - - return this->m_pCorProfileData; -} - -// Returns the profile data stored in the assembly. - -CorProfileData * ZapImage::GetProfileData() -{ - _ASSERTE(this->m_pCorProfileData != NULL); - - return this->m_pCorProfileData; -} - -CorProfileData::CorProfileData(void * rawProfileData) -{ - ZapImage::ProfileDataSection * profileData = (ZapImage::ProfileDataSection *) rawProfileData; - - for (DWORD format = 0; format < SectionFormatCount; format++) - { - this->profilingTokenFlagsData[format].count = profileData[format].tableSize; - this->profilingTokenFlagsData[format].data = profileData[format].pTable; - } - - this->blobStream = (CORBBTPROF_BLOB_ENTRY *) profileData[BlobStream].pData; -} - - -// Determines whether a method can be called directly from another method (without -// going through the prestub) in the current module. -// callerFtn=NULL implies any/unspecified caller in the current module. -// -// Returns NULL if 'calleeFtn' cannot be called directly *at the current time* -// Else returns the direct address that 'calleeFtn' can be called at. - - -bool ZapImage::canIntraModuleDirectCall( - CORINFO_METHOD_HANDLE callerFtn, - CORINFO_METHOD_HANDLE targetFtn, - CorInfoIndirectCallReason *pReason, - CORINFO_ACCESS_FLAGS accessFlags/*=CORINFO_ACCESS_ANY*/) -{ - CorInfoIndirectCallReason reason; - if (pReason == NULL) - pReason = &reason; - *pReason = CORINFO_INDIRECT_CALL_UNKNOWN; - - // The caller should have checked that the method is in current loader module - _ASSERTE(m_hModule == m_zapper->m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(targetFtn)); - - // No direct calls at all under some circumstances - - if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE) - && !m_pPreloader->IsDynamicMethod(callerFtn)) - { - *pReason = CORINFO_INDIRECT_CALL_PROFILING; - goto CALL_VIA_ENTRY_POINT; - } - - // Does the method's class have a cctor, etc? - - if (!m_pPreloader->CanSkipMethodPreparation(callerFtn, targetFtn, pReason, accessFlags)) - goto CALL_VIA_ENTRY_POINT; - - ZapMethodHeader * pMethod; - pMethod = GetCompiledMethod(targetFtn); - - // If we have not compiled the method, then we can't call directly - - if (pMethod == NULL) - { - *pReason = CORINFO_INDIRECT_CALL_NO_CODE; - goto CALL_VIA_ENTRY_POINT; - } - - // Does the method have fixups? - - if (pMethod->HasFixups() != NULL) - { - *pReason = CORINFO_INDIRECT_CALL_FIXUPS; - goto CALL_VIA_ENTRY_POINT; - } - -#ifdef _DEBUG - const char* clsName, * methodName; - methodName = m_zapper->m_pEEJitInfo->getMethodName(targetFtn, &clsName); - LOG((LF_ZAP, LL_INFO10000, "getIntraModuleDirectCallAddr: Success %s::%s\n", - clsName, methodName)); -#endif - - return true; - -CALL_VIA_ENTRY_POINT: - -#ifdef _DEBUG - methodName = m_zapper->m_pEEJitInfo->getMethodName(targetFtn, &clsName); - LOG((LF_ZAP, LL_INFO10000, "getIntraModuleDirectCallAddr: Via EntryPoint %s::%s\n", - clsName, methodName)); -#endif - - return false; -} - -// -// Relocations -// - -void ZapImage::WriteReloc(PVOID pSrc, int offset, ZapNode * pTarget, int targetOffset, ZapRelocationType type) -{ - _ASSERTE(!IsWritingRelocs()); - - _ASSERTE(m_pBaseRelocs != NULL); - m_pBaseRelocs->WriteReloc(pSrc, offset, pTarget, targetOffset, type); -} - -ZapImage * ZapImage::GetZapImage() -{ - return this; -} - -void ZapImage::FileNotFoundError(LPCWSTR pszMessage) -{ - SString message(pszMessage); - - for (COUNT_T i = 0; i < fileNotFoundErrorsTable.GetCount(); i++) - { - // Check to see if same error has already been displayed for this ngen operation - if (message.Equals(fileNotFoundErrorsTable[i])) - return; - } - - CorZapLogLevel level; - -#ifdef CROSSGEN_COMPILE - // Warnings should not go to stderr during crossgen - level = CORZAP_LOGLEVEL_WARNING; -#else - level = CORZAP_LOGLEVEL_ERROR; -#endif - - m_zapper->Print(level, W("Warning: %s.\n"), pszMessage); - - fileNotFoundErrorsTable.Append(message); -} - -void ZapImage::Error(mdToken token, HRESULT hr, UINT resID, LPCWSTR message) -{ - // Missing dependencies are reported as fatal errors in code:CompilationDomain::BindAssemblySpec. - // Avoid printing redundant error message for them. - if (FAILED(g_hrFatalError)) - ThrowHR(g_hrFatalError); - - // COM introduces the notion of a vtable gap method, which is not a real method at all but instead - // aids in the explicit layout of COM interop vtables. These methods have no implementation and no - // direct runtime state tracking them. Trying to lookup a method handle for a vtable gap method will - // throw an exception but we choose to let that happen and filter out the warning here in the - // handler because (a) vtable gap methods are rare and (b) it's not all that cheap to identify them - // beforehand. - if ((TypeFromToken(token) == mdtMethodDef) && IsVTableGapMethod(token)) - { - return; - } - - CorZapLogLevel level = CORZAP_LOGLEVEL_ERROR; - - // Some warnings are demoted to informational level - if (resID == IDS_EE_SIMD_NGEN_DISALLOWED) - { - // Suppress printing of "Target-dependent SIMD vector types may not be used with ngen." - level = CORZAP_LOGLEVEL_INFO; - } - - if (resID == IDS_EE_HWINTRINSIC_NGEN_DISALLOWED) - { - // Suppress printing of "Hardware intrinsics may not be used with ngen." - level = CORZAP_LOGLEVEL_INFO; - } - -#ifdef CROSSGEN_COMPILE - if ((resID == IDS_IBC_MISSING_EXTERNAL_TYPE) || - (resID == IDS_IBC_MISSING_EXTERNAL_METHOD)) - { - // Suppress printing IBC related warnings except in verbose mode. - if (m_zapper->m_pOpt->m_ignoreErrors && !m_zapper->m_pOpt->m_verbose) - return; - - // Suppress printing of "The generic type/method specified by the IBC data is not available to this assembly" - level = CORZAP_LOGLEVEL_INFO; - } -#endif - - if (m_zapper->m_pOpt->m_ignoreErrors) - { -#ifdef CROSSGEN_COMPILE - // Warnings should not go to stderr during crossgen - if (level == CORZAP_LOGLEVEL_ERROR) - { - level = CORZAP_LOGLEVEL_WARNING; - } -#endif - m_zapper->Print(level, W("Warning: ")); - } - else - { - m_zapper->Print(level, W("Error: ")); - } - - if (message != NULL) - m_zapper->Print(level, W("%s"), message); - else - m_zapper->PrintErrorMessage(level, hr); - - m_zapper->Print(level, W(" while resolving 0x%x - "), token); - PrintTokenDescription(level, token); - m_zapper->Print(level, W(".\n")); - - if (m_zapper->m_pOpt->m_ignoreErrors) - return; - - IfFailThrow(hr); -} - -ZapNode * ZapImage::GetInnerPtr(ZapNode * pNode, SSIZE_T offset) -{ - return m_pInnerPtrs->Get(pNode, offset); -} - -ZapNode * ZapImage::GetHelperThunk(CorInfoHelpFunc ftnNum) -{ - ZapNode * pHelperThunk = m_pHelperThunks[ftnNum]; - - if (pHelperThunk == NULL) - { - pHelperThunk = new (GetHeap()) ZapHelperThunk(ftnNum); -#ifdef TARGET_ARM - pHelperThunk = GetInnerPtr(pHelperThunk, THUMB_CODE); -#endif - m_pHelperThunks[ftnNum] = pHelperThunk; - } - - // Ensure that the thunk is placed - ZapNode * pTarget = pHelperThunk; - if (pTarget->GetType() == ZapNodeType_InnerPtr) - pTarget = ((ZapInnerPtr *)pTarget)->GetBase(); - if (!pTarget->IsPlaced()) - m_pHelperTableSection->Place(pTarget); - - return pHelperThunk; -} - -// -// Compute a class-layout order based on a breadth-first traversal of -// the class graph (based on what classes contain calls to other classes). -// We cannot afford time or space to build the graph, so we do processing -// in place. -// -void ZapImage::ComputeClassLayoutOrder() -{ - // In order to make the computation efficient, we need to store per-class - // intermediate values in the class layout field. These come in two forms: - // - // - An entry with the UNSEEN_CLASS_FLAG set is one that is yet to be encountered. - // - An entry with METHOD_INDEX_FLAG set is an index into the m_MethodCompilationOrder list - // indicating where the unprofiled methods of this class begin - // - // Both flags begin set (by InitializeClassLayoutOrder) since the value initialized is - // the method index and the class has not been encountered by the algorithm. - // When a class layout has been computed, both of these flags will have been stripped. - - - // Early-out in the (probably impossible) case that these bits weren't available - if (m_MethodCompilationOrder.GetCount() >= UNSEEN_CLASS_FLAG || - m_MethodCompilationOrder.GetCount() >= METHOD_INDEX_FLAG) - { - return; - } - - // Allocate the queue for the breadth-first traversal. - // Note that the use of UNSEEN_CLASS_FLAG ensures that no class is enqueued more - // than once, so we can use that bound for the size of the queue. - CORINFO_CLASS_HANDLE * classQueue = new CORINFO_CLASS_HANDLE[m_ClassLayoutOrder.GetCount()]; - - unsigned classOrder = 0; - for (COUNT_T i = m_iUntrainedMethod; i < m_MethodCompilationOrder.GetCount(); i++) - { - unsigned classQueueNext = 0; - unsigned classQueueEnd = 0; - COUNT_T methodIndex = 0; - - // - // Find an unprocessed method to seed the next breadth-first traversal. - // - - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - const ClassLayoutOrderEntry * pEntry = m_ClassLayoutOrder.LookupPtr(pMethod->m_classHandle); - _ASSERTE(pEntry); - - if ((pEntry->m_order & UNSEEN_CLASS_FLAG) == 0) - { - continue; - } - - // - // Enqueue the method's class and start the traversal. - // - - classQueue[classQueueEnd++] = pMethod->m_classHandle; - ((ClassLayoutOrderEntry *)pEntry)->m_order &= ~UNSEEN_CLASS_FLAG; - - while (classQueueNext < classQueueEnd) - { - // - // Dequeue a class and pull out the index of its first method - // - - CORINFO_CLASS_HANDLE dequeuedClassHandle = classQueue[classQueueNext++]; - _ASSERTE(dequeuedClassHandle != NULL); - - pEntry = m_ClassLayoutOrder.LookupPtr(dequeuedClassHandle); - _ASSERTE(pEntry); - _ASSERTE((pEntry->m_order & UNSEEN_CLASS_FLAG) == 0); - _ASSERTE((pEntry->m_order & METHOD_INDEX_FLAG) != 0); - - methodIndex = pEntry->m_order & ~METHOD_INDEX_FLAG; - _ASSERTE(methodIndex < m_MethodCompilationOrder.GetCount()); - - // - // Set the real layout order of the class, and examine its unprofiled methods - // - - ((ClassLayoutOrderEntry *)pEntry)->m_order = ++classOrder; - - pMethod = m_MethodCompilationOrder[methodIndex]; - _ASSERTE(pMethod->m_classHandle == dequeuedClassHandle); - - while (pMethod->m_classHandle == dequeuedClassHandle) - { - - // - // For each unprofiled method, find target classes and enqueue any that haven't been seen - // - - ZapMethodHeader::PartialTargetMethodIterator it(pMethod); - - CORINFO_METHOD_HANDLE targetMethodHandle; - while (it.GetNext(&targetMethodHandle)) - { - CORINFO_CLASS_HANDLE targetClassHandle = GetJitInfo()->getMethodClass(targetMethodHandle); - if (targetClassHandle != pMethod->m_classHandle) - { - pEntry = m_ClassLayoutOrder.LookupPtr(targetClassHandle); - - if (pEntry && (pEntry->m_order & UNSEEN_CLASS_FLAG) != 0) - { - _ASSERTE(classQueueEnd < m_ClassLayoutOrder.GetCount()); - classQueue[classQueueEnd++] = targetClassHandle; - - ((ClassLayoutOrderEntry *)pEntry)->m_order &= ~UNSEEN_CLASS_FLAG; - } - } - } - - if (++methodIndex == m_MethodCompilationOrder.GetCount()) - { - break; - } - - pMethod = m_MethodCompilationOrder[methodIndex]; - } - } - } - - for (COUNT_T i = m_iUntrainedMethod; i < m_MethodCompilationOrder.GetCount(); i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - pMethod->m_cachedLayoutOrder = LookupClassLayoutOrder(pMethod->m_classHandle); - } - - m_fHasClassLayoutOrder = true; - - delete [] classQueue; -} - -static int __cdecl LayoutOrderCmp(const void* a_, const void* b_) -{ - ZapMethodHeader * a = *((ZapMethodHeader**)a_); - ZapMethodHeader * b = *((ZapMethodHeader**)b_); - - int layoutDiff = a->GetCachedLayoutOrder() - b->GetCachedLayoutOrder(); - if (layoutDiff != 0) - return layoutDiff; - - // Use compilation order as secondary key to get predictable ordering within the bucket - return a->GetCompilationOrder() - b->GetCompilationOrder(); -} - -void ZapImage::SortUnprofiledMethodsByClassLayoutOrder() -{ - qsort(&m_MethodCompilationOrder[m_iUntrainedMethod], m_MethodCompilationOrder.GetCount() - m_iUntrainedMethod, sizeof(ZapMethodHeader *), LayoutOrderCmp); -} diff --git a/src/coreclr/zap/zapimage.h b/src/coreclr/zap/zapimage.h deleted file mode 100644 index 10705b98e36512..00000000000000 --- a/src/coreclr/zap/zapimage.h +++ /dev/null @@ -1,1103 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapImage.h -// - -// -// NGEN-specific infrastructure for writing PE files. -// -// ====================================================================================== - -#ifndef __ZAPIMAGE_H__ -#define __ZAPIMAGE_H__ - -class ZapMetaData; -class ZapILMetaData; -class ZapCorHeader; -class ZapNativeHeader; -class ZapVersionInfo; -class ZapDependencies; -class ZapCodeManagerEntry; - -class ZapReadyToRunHeader; - -class ZapInnerPtrTable; -class ZapMethodEntryPointTable; -class ZapWrapperTable; - -class ZapBaseRelocs; - -class ZapBlobWithRelocs; - -//class ZapGCInfoTable; -#ifdef FEATURE_EH_FUNCLETS -class ZapUnwindDataTable; -#endif - -class ZapImportTable; -class ZapImportSectionsTable; -class ZapImportSectionSignatures; - -class ZapVirtualSectionsTable; -class DataImage; - -class ZapperStats; - -#undef SAFERELEASE -#define SAFERELEASE(p) if ((p) != NULL) { IUnknown * _ = (p); (p) = NULL; _->Release(); }; - -#if defined(TARGET_X86) || defined(TARGET_AMD64) -#define DEFAULT_CODE_BUFFER_INIT 0xcc // breakpoint -#else -#define DEFAULT_CODE_BUFFER_INIT 0 -#endif - -#ifdef TARGET_64BIT -// Optimize for speed -#define DEFAULT_CODE_ALIGN 16 -#else -// Optimize for size. -#define DEFAULT_CODE_ALIGN 4 -#endif - -#ifdef TARGET_ARM -#define MINIMUM_CODE_ALIGN 2 -#elif TARGET_ARM64 -#define MINIMUM_CODE_ALIGN 4 -#else -#define MINIMUM_CODE_ALIGN 1 -#endif - -// Various zapper hashtables are preallocated based on the size of IL image to reduce amount of -// rehashing we have to do. Turn ZAP_HASHTABLE_TUNING on to collect data for the tuning of initial hashtable sizes. -// #define ZAP_HASHTABLE_TUNING - -#ifdef ZAP_HASHTABLE_TUNING - -#define PREALLOCATE_HASHTABLE(table, quotient, cbILImage) \ - PREALLOCATE_HASHTABLE_NOT_NEEDED(table, cbILImage) - -#define PREALLOCATE_HASHTABLE_NOT_NEEDED(table, cbILImage) \ - do { \ - GetSvcLogger()->Printf(W("HashTable:\t%S\t%d\t%f\n"), #table, table.GetCount(), (double)table.GetCount() / (double)cbILImage); \ - } while (0) - -#define PREALLOCATE_ARRAY(array, quotient, cbILImage) \ - do { \ - GetSvcLogger()->Printf(W("Array:\t%S\t%d\t%f\n"), #array, array.GetCount(), (double)array.GetCount() / (double)cbILImage); \ - } while (0) - -#else // ZAP_HASHTABLE_TUNING - -#define PREALLOCATE_HASHTABLE(table, quotient, cbILImage) \ - do { \ - COUNT_T nSize = (COUNT_T)(quotient * \ - ((double)table.s_density_factor_denominator / (double)table.s_density_factor_numerator) * \ - cbILImage); \ - if (nSize > table.s_minimum_allocation) \ - table.Reallocate(nSize); \ - } while (0) - -#define PREALLOCATE_HASHTABLE_NOT_NEEDED(table, cbILImage) - -#define PREALLOCATE_ARRAY(array, quotient, cbILImage) \ - do { \ - COUNT_T nSize = (COUNT_T)(quotient * \ - cbILImage); \ - array.Preallocate(nSize); \ - } while (0) - -#endif // ZAP_HASHTABLE_TUNING - -//--------------------------------------------------------------------------------------- -// -// ZapImportSectionType is enum describing import sections allocated in the image -// -enum ZapImportSectionType -{ - ZapImportSectionType_Handle, // Unspecified handle - ZapImportSectionType_TypeHandle, // Type and method handles have to have their own section so we can restore them correctly - ZapImportSectionType_MethodHandle, -#ifdef TARGET_ARM - ZapImportSectionType_PCode, // Code pointers have to be in a own section on ARM because of they are tagged differently -#endif - ZapImportSectionType_StringHandle, // String handles require special handling for interning - ZapImportSectionType_Count, - - ZapImportSectionType_Hot = 0, // We have two sets of the section - hot and cold - ZapImportSectionType_Cold = ZapImportSectionType_Count, - - ZapImportSectionType_Eager = 2 * ZapImportSectionType_Count, // And one section for eager loaded handles - - ZapImportSectionType_Total = 2 * ZapImportSectionType_Count + 1, -}; - -#include "zaprelocs.h" -#include "zapinfo.h" -#include "zapcode.h" - -class ZapImage - : public ZapWriter - , public ICorCompileDataStore -{ - friend class Zapper; - friend class ZapInfo; - friend class ZapILMetaData; - friend class ZapImportTable; - friend class ZapCodeMethodDescs; - friend class ZapColdCodeMap; - friend class ZapReadyToRunHeader; - - private: - - Zapper *m_zapper; - - // - // Output module - // - - LPWSTR m_pOutputFileFullName; // Name of the temp ngen file to generate (including the path) - - // - // Make all virtual section pointers public for now. It should be cleaned up as we get more sophisticated layout - // algorithm in place. - // -public: - ZapPhysicalSection * m_pTextSection; - - // - // All virtual sections of the native image in alphabetical order - // - - ZapVirtualSection * m_pBaseRelocsSection; - ZapVirtualSection * m_pCodeSection; - ZapVirtualSection * m_pColdCodeSection; - ZapVirtualSection * m_pDebugSection; - ZapVirtualSection * m_pDelayLoadInfoDelayListSectionEager; - ZapVirtualSection * m_pDelayLoadInfoDelayListSectionCold; - ZapVirtualSection * m_pDelayLoadInfoDelayListSectionHot; - ZapVirtualSection * m_pDelayLoadInfoTableSection[ZapImportSectionType_Total]; - ZapVirtualSection * m_pStubsSection; - ZapVirtualSection * m_pEETableSection; - ZapVirtualSection * m_pExceptionSection; - ZapVirtualSection * m_pGCSection; - ZapVirtualSection * m_pHeaderSection; - ZapVirtualSection * m_pHelperTableSection; - ZapVirtualSection * m_pLazyHelperSection; - ZapVirtualSection * m_pLazyMethodCallHelperSection; - ZapVirtualSection * m_pHotCodeSection; - ZapVirtualSection * m_pHotGCSection; - ZapVirtualSection * m_pHotTouchedGCSection; - ZapVirtualSection * m_pILMetaDataSection; - ZapVirtualSection * m_pILSection; - ZapVirtualSection * m_pImportTableSection; - ZapVirtualSection * m_pInstrumentSection; - ZapVirtualSection * m_pMetaDataSection; - ZapVirtualSection * m_pReadOnlyDataSection; - ZapVirtualSection * m_pResourcesSection; - ZapVirtualSection * m_pWin32ResourceSection; - ZapVirtualSection * m_pStubDispatchCellSection; - ZapVirtualSection * m_pStubDispatchDataSection; - ZapVirtualSection * m_pDynamicHelperCellSection; - ZapVirtualSection * m_pDynamicHelperDataSection; - ZapVirtualSection * m_pVirtualImportThunkSection; - ZapVirtualSection * m_pExternalMethodThunkSection; - ZapVirtualSection * m_pExternalMethodCellSection; - ZapVirtualSection * m_pExternalMethodDataSection; - ZapVirtualSection * m_pHotRuntimeFunctionSection; - ZapVirtualSection * m_pRuntimeFunctionSection; - ZapVirtualSection * m_pColdRuntimeFunctionSection; - ZapVirtualSection * m_pHotCodeMethodDescsSection; - ZapVirtualSection * m_pCodeMethodDescsSection; - ZapVirtualSection * m_pHotRuntimeFunctionLookupSection; - ZapVirtualSection * m_pRuntimeFunctionLookupSection; - ZapVirtualSection * m_pColdCodeMapSection; -#if defined(FEATURE_EH_FUNCLETS) - ZapVirtualSection * m_pHotUnwindDataSection; - ZapVirtualSection * m_pUnwindDataSection; - ZapVirtualSection * m_pColdUnwindDataSection; -#endif // defined(FEATURE_EH_FUNCLETS) - -#ifdef FEATURE_READYTORUN_COMPILER - ZapVirtualSection * m_pAvailableTypesSection; - ZapVirtualSection * m_pAttributePresenceSection; -#endif - - // Preloader sections - ZapVirtualSection * m_pPreloadSections[CORCOMPILE_SECTION_COUNT]; - - ZapExceptionInfoLookupTable* m_pExceptionInfoLookupTable; -public: - // TODO: Remove once all EE datastructures are converted to ZapNodes - ICorCompilePreloader * m_pPreloader; - DataImage * m_pDataImage; - -public: - // TODO: The stats should be removed once we have all information available in nidump - ZapperStats *m_stats; - -private: - IMetaDataAssemblyEmit *m_pAssemblyEmit; // native image manifest - ZapMetaData * m_pAssemblyMetaData; - - ZapVersionInfo * m_pVersionInfo; - ZapDependencies * m_pDependencies; - - SString m_pdbFileName; - - ZapCodeManagerEntry * m_pCodeManagerEntry; - - ZapBlob * m_pEEInfoTable; - - // - // Auxiliary tables - // - ZapImportTable * m_pImportTable; - - ZapImportSectionsTable * m_pImportSectionsTable; - - ZapInnerPtrTable * m_pInnerPtrs; - - ZapMethodEntryPointTable * m_pMethodEntryPoints; - - ZapWrapperTable * m_pWrappers; - - ZapBaseRelocs * m_pBaseRelocs; - - ULONGLONG m_NativeBaseAddress; - - ULONGLONG GetNativeBaseAddress() - { - return m_NativeBaseAddress; - } - - void CalculateZapBaseAddress(); - - // Preallocate hashtables to avoid rehashing - void Preallocate(); - - ZapGCInfoTable * m_pGCInfoTable; - -#ifdef FEATURE_EH_FUNCLETS - ZapUnwindDataTable * m_pUnwindDataTable; -#endif - - ZapImportSectionSignatures * m_pDelayLoadInfoDataTable[ZapImportSectionType_Total]; - ZapImportSectionSignatures * m_pStubDispatchDataTable; - ZapImportSectionSignatures * m_pExternalMethodDataTable; - ZapImportSectionSignatures * m_pDynamicHelperDataTable; - - ZapVirtualSectionsTable * m_pVirtualSectionsTable; - - ZapDebugInfoTable * m_pDebugInfoTable; - - ZapILMetaData * m_pILMetaData; - - ZapCorHeader * m_pCorHeader; - - ZapNode * m_pResources; - - ZapNode * m_pNativeHeader; - - ZapBlob * m_pNGenPdbDebugData; - - ULONG m_totalHotCodeSize; - ULONG m_totalColdCodeSize; - - ULONG m_totalCodeSizeInProfiledMethods; - ULONG m_totalColdCodeSizeInProfiledMethods; - - //information to track the boundaries of the different subsections within - //the hot section. - COUNT_T m_iIBCMethod; - COUNT_T m_iGenericsMethod; - COUNT_T m_iUntrainedMethod; - - // - // Input module - // - - LPWSTR m_pModuleFileName; // file name of the module being compiled, including path - CORINFO_MODULE_HANDLE m_hModule; // Module being compiled - PEDecoder m_ModuleDecoder; - IMDInternalImport * m_pMDImport; - bool m_fManifestModule; // Is this the assembly-manifest-module - bool m_fHaveProfileData; - - ZapNode ** m_pHelperThunks; // Array of on demand allocated JIT helper thunks - - // - // Profile source - // - - BYTE * m_profileDataFile; - BYTE * m_pRawProfileData; - COUNT_T m_cRawProfileData; - CorProfileData * m_pCorProfileData; - -public: - enum CompileStatus { - // Failure status values are negative - LOOKUP_FAILED = -2, - COMPILE_FAILED = -1, - - // Info status values are [0..9] - NOT_COMPILED = 0, - COMPILE_EXCLUDED = 1, - COMPILE_HOT_EXCLUDED = 2, - COMPILE_COLD_EXCLUDED = 3, - - // Successful status values are 10 or greater - COMPILE_SUCCEED = 10, - ALREADY_COMPILED = 11 - }; - -private: - // A hash table entry that contains the profile infomation and the CompileStatus for a given method - struct ProfileDataHashEntry - { - mdMethodDef md; // The method.token, also used as the key for the ProfileDataHashTable - DWORD size; // The size of the CORBBTPROF_BLOCK_DATA region, set by ZapImage::hashBBProfileData() - ULONG pos; // the offset to the CORBBTPROF_BLOCK_DATA region, set by ZapImage::hashBBProfileData() - - unsigned flags; // The methodProfilingDataFlags, set by ZapImage::CompileHotRegion() - CompileStatus status; // The compileResult, set by ZapImage::CompileHotRegion() - }; - - class ProfileDataHashTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef const mdMethodDef key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e.md; - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return k1 == k2; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)k; - } - - static const element_t Null() - { - LIMITED_METHOD_CONTRACT; - ProfileDataHashEntry e; - e.md = 0; - e.size = 0; - e.pos = 0; - e.flags = 0; - e.status = NOT_COMPILED; - return e; - } - - static bool IsNull(const element_t &e) - { - LIMITED_METHOD_CONTRACT; - // returns true if both md and pos are zero - return (e.md == 0) && (e.pos == 0); - } - }; - typedef SHash ProfileDataHashTable; - - ProfileDataHashTable profileDataHashTable; - - SArray fileNotFoundErrorsTable; - void FileNotFoundError(LPCWSTR pszMessage); - -public: - struct ProfileDataSection - { - BYTE *pData; - DWORD dataSize; - DWORD tableSize; - CORBBTPROF_TOKEN_INFO *pTable; - }; - -private: - ProfileDataSection m_profileDataSections[SectionFormatCount]; - - DWORD m_profileDataNumRuns; - - CorInfoRegionKind m_currentRegionKind; - - BOOL IsAssemblyBeingCompiled(CORINFO_MODULE_HANDLE module) { - return ((module == m_hModule) || - (m_zapper->m_pEECompileInfo->GetModuleAssembly(module) == m_zapper->m_hAssembly)); - } - - class ZapMethodTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef CORINFO_METHOD_HANDLE key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e->GetHandle(); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return k1 == k2; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(size_t)k; - } - }; - - typedef SHash ZapMethodHashTable; - - ZapMethodHashTable m_CompiledMethods; - - SArray m_MethodCompilationOrder; - - SArray m_PrioritizedGCInfo; - -#ifndef FEATURE_FULL_NGEN - class MethodCodeTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef ZapMethodHeader * key_t; - - static FORCEINLINE key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e; - } - - static BOOL Equals(key_t k1, key_t k2); - static COUNT_T Hash(key_t k); - - static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } - }; - - typedef SHash ZapMethodCodeHashTable; - - ZapMethodCodeHashTable m_CodeDeduplicator; -#endif // FEATURE_FULL_NGEN - - struct ClassLayoutOrderEntry - { - CORINFO_CLASS_HANDLE m_cls; - unsigned m_order; - - ClassLayoutOrderEntry() - : m_cls(0), m_order(0) - { - } - - ClassLayoutOrderEntry(CORINFO_CLASS_HANDLE cls, unsigned order) - : m_cls(cls), m_order(order) - { - } - }; - - class ClassLayoutOrderTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef CORINFO_CLASS_HANDLE key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e.m_cls; - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return k1 == k2; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(size_t)k; - } - static const element_t Null() { LIMITED_METHOD_CONTRACT; return element_t(0,0); } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e.m_cls == 0; } - }; - - typedef SHash ClassLayoutOrderHashTable; - - ClassLayoutOrderHashTable m_ClassLayoutOrder; - - // See ComputeClassLayoutOrder for an explanation of these flags - #define UNSEEN_CLASS_FLAG (0x80000000) - #define METHOD_INDEX_FLAG (0x40000000) - - // The class layout order needs to be initialized with the first index - // in m_MethodCompilationOrder of a method in the given class. - inline void InitializeClassLayoutOrder(CORINFO_CLASS_HANDLE cls, unsigned order) - { - WRAPPER_NO_CONTRACT; - - if (!m_ClassLayoutOrder.LookupPtr(cls)) - { - ClassLayoutOrderEntry entry(cls, order | UNSEEN_CLASS_FLAG | METHOD_INDEX_FLAG); - m_ClassLayoutOrder.Add(entry); - } - } - -public: - inline unsigned LookupClassLayoutOrder(CORINFO_CLASS_HANDLE cls) - { - WRAPPER_NO_CONTRACT; - - const ClassLayoutOrderEntry *pEntry = m_ClassLayoutOrder.LookupPtr(cls); - _ASSERTE(!pEntry || pEntry->m_order != 0); - - return pEntry ? pEntry->m_order : 0; - } - -private: - - // - // The image layout algorithm - // - - enum CodeType - { - ProfiledHot, - ProfiledCold, - Unprofiled - }; - - ZapVirtualSection * GetCodeSection(CodeType codeType); - ZapVirtualSection * GetRuntimeFunctionSection(CodeType codeType); - ZapVirtualSection * GetCodeMethodDescSection(CodeType codeType); - ZapVirtualSection * GetUnwindInfoLookupSection(CodeType codeType); - -#if defined(FEATURE_EH_FUNCLETS) - ZapVirtualSection * GetUnwindDataSection(CodeType codeType); -#endif - - void GetCodeCompilationRange(CodeType codeType, COUNT_T * start, COUNT_T * end); - - void OutputCode(CodeType codeType); - void OutputCodeInfo(CodeType codeType); - - void OutputGCInfo(); - - void OutputDebugInfo(); - void OutputProfileData(); - - void OutputEntrypointsTableForReadyToRun(); - void OutputDebugInfoForReadyToRun(); - void OutputTypesTableForReadyToRun(IMDInternalImport * pMDImport); - void OutputInliningTableForReadyToRun(); - void OutputProfileDataForReadyToRun(); - void OutputManifestMetadataForReadyToRun(); - HRESULT ComputeAttributePresenceTable(IMDInternalImport * pMDImport, SArray *table); - void OutputAttributePresenceFilter(IMDInternalImport * pMDImport); - - void CopyDebugDirEntry(); - void CopyWin32Resources(); - - void OutputManifestMetadata(); - void OutputTables(); - - // Assign RVAs to all ZapNodes - void ComputeRVAs(); - - HANDLE GenerateFile(LPCWSTR wszOutputFileName, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig); - - void PrintStats(LPCWSTR wszOutputFileName); - - bool m_fHasClassLayoutOrder; - - void ComputeClassLayoutOrder(); - void SortUnprofiledMethodsByClassLayoutOrder(); - - HRESULT GetPdbFileNameFromModuleFilePath(__in_z const WCHAR* pwszModuleFilePath, - __out_ecount(dwPdbFileNameBufferSize) char * pwszPdbFileName, - DWORD dwPdbFileNameBufferSize); - -public: - ZapImage(Zapper *zapper); - virtual ~ZapImage(); - - // ---------------------------------------------------------------------------------------------------------- - // - // Utility function for converting ZapWriter * to ZapImage *. This cast should not be done directly by the code - // so that the relationship between ZapWriter and ZapImage is abstracted away. - // - static ZapImage * GetImage(ZapWriter * pZapWriter) - { - return (ZapImage *)pZapWriter; - } - - // ---------------------------------------------------------------------------------------------------------- - // - // Add relocation record. This method is meant to be called from the Save method of custom ZapNodes right - // before the given datastructure is written into the native image. - // - // Arguments: - // pSrc - the datastructure being written - // offset - offset of the relocation within the datastructure - // pTarget - target of the relocation - // targetOffset - adjusment of the target (usually 0) - // type - relocation type (IMAGE_REL_BASED_XXX enum, note that we have private additions to this enum: - // IMAGE_REL_BASED_PTR - architecture specific reloc of virtual address - // IMAGE_REL_BASED_ABSOLUTE_TAGGED - absolute stored in the middle 30-bits, used for fixups. - // IMAGE_REL_BASED_RELPTR - pointer stored as address relative delta - // IMAGE_REL_BASED_RELPTR32 - pointer stored as address relative 32-bit delta - // - void WriteReloc(PVOID pSrc, int offset, ZapNode * pTarget, int targetOffset, ZapRelocationType type); - - void Open(CORINFO_MODULE_HANDLE hModule, IMetaDataAssemblyEmit *pEmit); - - void InitializeSections(); - void InitializeSectionsForReadyToRun(); - - // Wrapper of ZapWriter::NewVirtualSection that sets sectionType - ZapVirtualSection * NewVirtualSection(ZapPhysicalSection * pPhysicalSection, DWORD sectionType /* ZapVirtualSectionType */, DWORD dwAlignment = 16, ZapVirtualSection * pInsertAfter = NULL) - { - ZapVirtualSection * pSection = ZapWriter::NewVirtualSection(pPhysicalSection, dwAlignment, pInsertAfter); - pSection->SetSectionType(sectionType); - return pSection; - } - - void AllocateVirtualSections(); - - HANDLE SaveImage(LPCWSTR wszOutputFileName, LPCWSTR wszDllPath, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig); - - void Preload(); - void LinkPreload(); - - void SetVersionInfo(CORCOMPILE_VERSION_INFO * pVersionInfo); - void SetDependencies(CORCOMPILE_DEPENDENCY *pDependencies, DWORD cDependencies); - void SetPdbFileName(const SString &strFileName); - -#ifdef FEATURE_EH_FUNCLETS - void SetRuntimeFunctionsDirectoryEntry(); -#endif - - void SaveCorHeader(); - void SaveNativeHeader(); - void SaveCodeManagerEntry(); - - void Compile(); - - ZapMethodHeader * GetCompiledMethod(CORINFO_METHOD_HANDLE handle) - { - return m_CompiledMethods.Lookup(handle); - } - - static void __stdcall TryCompileMethodStub(LPVOID pContext, CORINFO_METHOD_HANDLE hStub, CORJIT_FLAGS jitFlags); - static DWORD EncodeModuleHelper(LPVOID compileContext, CORINFO_MODULE_HANDLE referencedModule); - - BOOL IsVTableGapMethod(mdMethodDef md); - - CompileStatus TryCompileMethodDef(mdMethodDef md, unsigned methodProfilingDataFlags); - CompileStatus TryCompileInstantiatedMethod(CORINFO_METHOD_HANDLE handle, unsigned methodProfilingDataFlags); - CompileStatus TryCompileMethodWorker(CORINFO_METHOD_HANDLE handle, mdMethodDef md, unsigned methodProfilingDataFlags); - - BOOL ShouldCompileMethodDef(mdMethodDef md); - BOOL ShouldCompileInstantiatedMethod(CORINFO_METHOD_HANDLE handle); - - bool canIntraModuleDirectCall(CORINFO_METHOD_HANDLE callerFtn, - CORINFO_METHOD_HANDLE targetFtn, - CorInfoIndirectCallReason *pReason = NULL, - CORINFO_ACCESS_FLAGS accessFlags = CORINFO_ACCESS_ANY); - - CORINFO_MODULE_HANDLE GetModuleHandle() - { - return m_hModule; - } - - IMetaDataAssemblyEmit * GetAssemblyEmit() - { - return m_pAssemblyEmit; - } - - ZapWrapperTable * GetWrappers() - { - return m_pWrappers; - } - - ZapImportTable * GetImportTable() - { - return m_pImportTable; - } - - ZapImportSectionsTable * GetImportSectionsTable() - { - return m_pImportSectionsTable; - } - - ZapNode * GetEEInfoTable() - { - return m_pEEInfoTable; - } - - ZapReadyToRunHeader * GetReadyToRunHeader() - { - _ASSERTE(IsReadyToRunCompilation()); - return (ZapReadyToRunHeader *)m_pNativeHeader; - } - - ZapNode * GetInnerPtr(ZapNode * pNode, SSIZE_T offset); - - CorInfoRegionKind GetCurrentRegionKind() - { - return m_currentRegionKind; - } - - // - // Called from ZapImportTable::PlaceBlob - // to determine wheather to place the new signature Blob - // into the HotImports or the ColdImports section. - // - // The Assert will fire if BeginRegion was not called - // to setup the region - // - bool IsCurrentCodeRegionHot() - { - if (GetCurrentRegionKind() == CORINFO_REGION_HOT) - { - return true; - } - else if (GetCurrentRegionKind() == CORINFO_REGION_COLD) - { - return false; - } - _ASSERTE(!"unsupported RegionKind"); - return false; - } - - // - // Marks the start of a region where we want to place any - // new signature Blobs into the Hot/Cold region - // - void BeginRegion(CorInfoRegionKind regionKind) - { - _ASSERTE(GetCurrentRegionKind() == CORINFO_REGION_NONE); - m_currentRegionKind = regionKind; - } - - // - // Marks the end of a region and we no longer expect to - // need any new signature Blobs - // - void EndRegion(CorInfoRegionKind regionKind) - { - _ASSERTE(GetCurrentRegionKind() == regionKind); - m_currentRegionKind = CORINFO_REGION_NONE; - } - - ICorCompilationDomain * GetDomain() - { - return m_zapper->m_pDomain; - } - - ICorDynamicInfo * GetJitInfo() - { - return m_zapper->m_pEEJitInfo; - } - - ICorCompileInfo * GetCompileInfo() - { - return m_zapper->m_pEECompileInfo; - } - - ZapperOptions * GetZapperOptions() - { - return m_zapper->m_pOpt; - } - - ZapNode * GetHelperThunkIfExists(CorInfoHelpFunc ftnNum) - { - return m_pHelperThunks[ftnNum]; - } - - ZapNode * GetHelperThunk(CorInfoHelpFunc ftnNum); - - BOOL HasClassLayoutOrder() - { - return m_fHasClassLayoutOrder; - } - - HRESULT PrintTokenDescription(CorZapLogLevel level, mdToken token); - - // ICorCompileDataStore - - // Returns ZapImage - virtual ZapImage * GetZapImage(); - void Error(mdToken token, HRESULT error, UINT resID, LPCWSTR message); - - // Returns virtual section for EE datastructures - ZapVirtualSection * GetSection(CorCompileSection section) - { - return m_pPreloadSections[section]; - } - - HRESULT LocateProfileData(); - HRESULT parseProfileData(); - HRESULT convertProfileDataFromV1(); - HRESULT hashMethodBlockCounts(); - void hashBBUpdateFlagsAndCompileResult(mdToken token, unsigned methodProfilingDataFlags, CompileStatus compileResult); - - void RehydrateBasicBlockSection(); - void RehydrateTokenSection(int sectionFormat, unsigned int flagTable[255]); - void RehydrateBlobStream(); - HRESULT RehydrateProfileData(); - - void LoadProfileData(); - CorProfileData * NewProfileData(); - CorProfileData * GetProfileData(); - bool CanConvertIbcData(); - - CompileStatus CompileProfileDataWorker(mdToken token, unsigned methodProfilingDataFlags); - - void ProfileDisableInlining(); - void CompileHotRegion(); - void CompileColdRegion(); - void PlaceMethodIL(); -}; - -class BinaryWriter -{ -private: - char *m_buffer; - unsigned int m_length; - unsigned int m_currentPosition; - ZapHeap *m_heap; - -private: - // Make sure that the buffer is at least newLength bytes long; - // expand it if necessary. - void RequireLength(unsigned int newLength) - { - if (newLength <= m_length) - { - return; - } - - if (newLength < (m_length * 3) / 2) - { - newLength = (m_length * 3) / 2; - } - - char *newBuffer = new (m_heap) char[newLength]; - - memcpy(newBuffer, m_buffer, m_length); - - m_length = newLength; - m_buffer = newBuffer; - } - -public: - BinaryWriter(unsigned int initialLength, ZapHeap *heap) - { - m_heap = heap; - m_length = initialLength; - m_buffer = new (m_heap) char[initialLength]; - m_currentPosition = 0; - } - - template - void WriteAt(unsigned int position, const T &v) - { - RequireLength(position + sizeof(T)); - - *(T *)(m_buffer + position) = v; - } - - template - void Write(const T &v) - { - WriteAt(m_currentPosition, v); - m_currentPosition += sizeof(T); - } - - void Write(const char *data, unsigned int length) - { - RequireLength(m_currentPosition + length); - - memcpy(m_buffer + m_currentPosition, data, length); - m_currentPosition += length; - } - - BYTE *GetBuffer() - { - return (BYTE *)m_buffer; - } - - unsigned int GetWrittenSize() - { - return m_currentPosition; - } -}; - -class ProfileReader -{ -public: - ProfileReader(void *buffer, ULONG length) - { - profileBuffer = (char *) buffer; - bufferSize = length; - currentPos = 0; - } - - bool Seek(ULONG pos) - { - if (pos <= bufferSize) - { - currentPos = pos; - return true; - } - else - { - _ASSERTE(!"ProfileReader: attempt to seek out of bounds"); - return false; - } - } - - void *Read(ULONG size) - { - ULONG oldPos = currentPos; - - if (!Seek(currentPos + size)) - { - return NULL; - } - - return (void *)(profileBuffer + oldPos); - } - - template T Read() - { - T* pResult = (T*)Read(sizeof(T)); - - if (!pResult) - { - ThrowHR(E_FAIL); - } - - return *pResult; - } - - // Read an integer a la BinaryReader.Read7BitEncodedInt. - unsigned int Read7BitEncodedInt() - { - unsigned int result = 0; - int shift = 0; - unsigned char current = 0x80; - - while ((currentPos < bufferSize) && - (shift <= 28)) - { - current = profileBuffer[currentPos++]; - result |= (current & 0x7f) << shift; - shift += 7; - - if (!(current & 0x80)) - { - return result; - } - } - - _ASSERTE(!"Improperly encoded value"); - ThrowHR(E_FAIL); - } - - // Read a token given a 'memory' value--the last token of this type read - // from the stream. The encoding takes advantage of the fact that two - // adjacent tokens in the file are usually of the same type, and therefore - // share a high byte. With the high byte removed the rest of the token can - // be encoded more efficiently. - mdToken ReadTokenWithMemory(mdToken &memory) - { - mdToken current; - mdToken result; - - current = Read7BitEncodedInt(); - - unsigned char highByte = ((current >> 24) & 0xff); - - if (highByte == 0) - { - result = current | (memory & 0xff000000); - } - else if (highByte == 0xff) - { - result = current & 0x00ffffff; - } - else - { - result = current; - } - - memory = result; - - return result; - } - - // Read a 32-bit flag value using a lookup table built while processing the - // file. Flag values are represented by a one-byte index. If the index - // hasn't occurred before in the file, it is followed by the four-byte flag - // value it represents. The index 255 is used as an escape code--it is - // always followed by a flag value. - // flagTable must have 255 entries and they must all start as 0xFFFFFFFF. - unsigned int ReadFlagWithLookup(unsigned int flagTable[255]) - { - unsigned char index; - unsigned int flags; - - index = Read(); - - if ((index < 255) && (flagTable[index] != 0xffffffff)) - { - return flagTable[index]; - } - - flags = Read(); - - if (index < 255) - { - flagTable[index] = flags; - } - - return flags; - } - - ULONG GetCurrentPos() - { - _ASSERTE(currentPos <= bufferSize); - return currentPos; - } - -private: - char *profileBuffer; - ULONG bufferSize; - ULONG currentPos; -}; - -struct RSDS { - DWORD magic; - GUID signature; - DWORD age; - char path[MAX_LONGPATH]; -}; - -#define SEEK(pos) \ - if (!profileReader.Seek(pos)) return E_FAIL; - -#define READ_SIZE(dst,type,size) \ - dst = (type *) profileReader.Read(size); \ - if (!dst) return E_FAIL; - -#define READ(dst,type) \ - READ_SIZE(dst,type,sizeof(type)) - -#endif // __ZAPIMAGE_H__ diff --git a/src/coreclr/zap/zapimport.cpp b/src/coreclr/zap/zapimport.cpp deleted file mode 100644 index c60868f60ea271..00000000000000 --- a/src/coreclr/zap/zapimport.cpp +++ /dev/null @@ -1,2284 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapImport.cpp -// - -// -// Zapping of soft bound references to elements outside the current module -// -// ====================================================================================== - -#include "common.h" - -#include "zapimport.h" - -#include "nibblestream.h" -#include "sigbuilder.h" - -#if defined(FEATURE_READYTORUN_COMPILER) -// A flag to indicate that a helper call uses VSD -const DWORD READYTORUN_HELPER_FLAG_VSD = 0x10000000; -#endif - -// -// ZapImportTable -// - -ZapImportTable::ModuleReferenceEntry * ZapImportTable::GetModuleReference(CORINFO_MODULE_HANDLE handle) -{ - ModuleReferenceEntry * pEntry = m_moduleReferences.Lookup(handle); - - if (pEntry != NULL) - return pEntry; - - if (!GetCompileInfo()->IsInCurrentVersionBubble(handle)) - { - // FUTURE TODO: Version resilience - _ASSERTE(!"Invalid reference to module outside of current version bubble"); - ThrowHR(E_FAIL); - } - - pEntry = new (m_pImage->GetHeap()) ModuleReferenceEntry(); - pEntry->m_module = handle; - - GetCompileInfo()->EncodeModuleAsIndex(m_pImage->GetModuleHandle(), handle, - &pEntry->m_index, - m_pImage->GetAssemblyEmit()); - - m_moduleReferences.Add(pEntry); - - return pEntry; -} - -ZapBlob * ZapImportTable::GetBlob(SigBuilder * pSigBuilder, BOOL fEager) -{ - DWORD cbBlob; - PVOID pSignature = pSigBuilder->GetSignature(&cbBlob); - - if (fEager) - { - // Use dedicated section for blobs of eager fixups - return ZapBlob::NewBlob(m_pImage, pSignature, cbBlob); - } - - ZapBlob * pBlob = m_blobs.Lookup(ZapBlob::SHashKey(pSignature, cbBlob)); - - if (pBlob == NULL) - { - pBlob = ZapBlob::NewBlob(m_pImage, pSignature, cbBlob); - - m_blobs.Add(pBlob); - } - - return pBlob; -} - -ZapBlob * ZapImportTable::PlaceImportBlob(ZapImport * pImport, BOOL fEager) -{ - ZapBlob * pBlob; - if (pImport->HasBlob()) - { - pBlob = pImport->GetBlob(); - } - else - { - SigBuilder sigBuilder; - pImport->EncodeSignature(this, &sigBuilder); - - pBlob = GetBlob(&sigBuilder, fEager); - - pImport->SetBlob(pBlob); - } - - if (!pBlob->IsPlaced()) - PlaceBlob(pBlob, fEager); - - return pBlob; -} - -static const struct ImportSectionProperties -{ - BYTE Type; - BYTE EntrySize; - WORD Flags; -} -c_ImportSectionProperties[ZapImportSectionType_Count] = -{ - { /* ZapImportSectionType_Handle, */ CORCOMPILE_IMPORT_TYPE_UNKNOWN, 0, 0 }, - { /* ZapImportSectionType_TypeHandle, */ CORCOMPILE_IMPORT_TYPE_TYPE_HANDLE, TARGET_POINTER_SIZE, 0 }, - { /* ZapImportSectionType_MethodHandle, */ CORCOMPILE_IMPORT_TYPE_METHOD_HANDLE, TARGET_POINTER_SIZE, 0 }, -#ifdef TARGET_ARM - { /* ZapImportSectionType_PCode, */ CORCOMPILE_IMPORT_TYPE_UNKNOWN, 0, CORCOMPILE_IMPORT_FLAGS_PCODE }, -#endif - { /* ZapImportSectionType_StringHandle, */ CORCOMPILE_IMPORT_TYPE_STRING_HANDLE, TARGET_POINTER_SIZE, 0 }, -}; - -void ZapImportTable::PlaceImport(ZapImport * pImport) -{ - BOOL fIsEager, fNeedsSignature; - ZapImportSectionType table = pImport->ComputePlacement(m_pImage, &fIsEager, &fNeedsSignature); - - if (fIsEager) - { - table = ZapImportSectionType_Eager; - } - else - if (!m_pImage->IsCurrentCodeRegionHot()) - { - table = (ZapImportSectionType)(table + ZapImportSectionType_Cold); - } - - _ASSERTE(table < ZapImportSectionType_Total); - - - if (fNeedsSignature) - { - PlaceImportBlob(pImport, fIsEager); - } - - ZapVirtualSection * pVirtualSection = m_pImage->m_pDelayLoadInfoTableSection[table]; - - if (m_nImportSectionSizes[table] == 0) - { - const ImportSectionProperties * pProps = &c_ImportSectionProperties[table % ZapImportSectionType_Count]; - - WORD flags = pProps->Flags; - - if (fIsEager) - flags |= CORCOMPILE_IMPORT_FLAGS_EAGER; - - m_nImportSectionIndices[table] = m_pImage->GetImportSectionsTable()->Append(pProps->Type, flags, pProps->EntrySize, - pVirtualSection, m_pImage->m_pDelayLoadInfoDataTable[table]); - } - - pImport->SetSectionIndexAndOffset(m_nImportSectionIndices[table], m_nImportSectionSizes[table]); - - pVirtualSection->Place(pImport); - - m_nImportSectionSizes[table] += pImport->GetSize(); -} - -// Sort ZapImport* by CorCompileTokenTable as primary key and offset within the table as secondary key -static int __cdecl fixupCmp(const void* a_, const void* b_) -{ - ZapImport *a = *(ZapImport **)a_; - ZapImport *b = *(ZapImport **)b_; - - int tableDiff = a->GetSectionIndex() - b->GetSectionIndex(); - if (tableDiff != 0) - return tableDiff; - - // Sort by offset within the table - return (a->GetOffset() - b->GetOffset()); -} - -void ZapImportTable::PlaceFixups(ZapImport ** pImports, NibbleWriter& writer) -{ - COUNT_T nImports = 0; - - for (;;) - { - ZapImport * pImport = pImports[nImports]; - if (pImport == NULL) // end of the list - break; - if (!pImport->IsPlaced()) - PlaceImport(pImport); - nImports++; - } - - qsort(pImports, nImports, sizeof(ZapImport *), fixupCmp); - - // - // Build the encoded fixup list - // - - int curTableIndex = -1; - DWORD curOffset = 0; - - for (COUNT_T iImport = 0; iImport < nImports; iImport++) - { - ZapImport * pImport = pImports[iImport]; - - int tableIndex = pImport->GetSectionIndex(); - unsigned offset = pImport->GetOffset(); - - _ASSERTE(offset % TARGET_POINTER_SIZE == 0); - offset /= TARGET_POINTER_SIZE; - - if (tableIndex != curTableIndex) - { - // Write delta relative to the previous table index - _ASSERTE(tableIndex > curTableIndex); - if (curTableIndex != -1) - { - writer.WriteEncodedU32(0); // table separator, so add except for the first entry - writer.WriteEncodedU32(tableIndex - curTableIndex); // add table index delta - } - else - { - writer.WriteEncodedU32(tableIndex); - } - curTableIndex = tableIndex; - - // This is the first fixup in the current table. - // We will write it out completely (without delta-encoding) - writer.WriteEncodedU32(offset); - } - else - { - // This is not the first entry in the current table. - // We will write out the delta relative to the previous fixup value - int delta = offset - curOffset; - _ASSERTE(delta > 0); - writer.WriteEncodedU32(delta); - } - - // future entries for this table would be relative to this rva - curOffset = offset; - } - - writer.WriteEncodedU32(0); // table separator - writer.WriteEncodedU32(0); // fixup list ends - - writer.Flush(); -} - -ZapFixupInfo * ZapImportTable::PlaceFixups(ZapImport ** pImports) -{ - NibbleWriter writer; - - PlaceFixups(pImports, writer); - - DWORD cbBlob; - PVOID pBlob = writer.GetBlob(&cbBlob); - - // - // Intern the fixup info - // - - ZapFixupInfo * pFixupInfo = m_blobs.Lookup(ZapBlob::SHashKey(pBlob, cbBlob)); - - if (pFixupInfo == NULL) - { - // Fixup infos are mixed with other blobs - pFixupInfo = ZapBlob::NewBlob(m_pImage, pBlob, cbBlob); - m_blobs.Add(pFixupInfo); - } - - if (!pFixupInfo->IsPlaced()) - PlaceBlob(pFixupInfo); - - return pFixupInfo; -} - -void ZapImportTable::PlaceBlob(ZapBlob * pBlob, BOOL fEager) -{ - ZapVirtualSection * pSection; - if (fEager) - pSection = m_pImage->m_pDelayLoadInfoDelayListSectionEager; - else - if (m_pImage->IsCurrentCodeRegionHot()) - pSection = m_pImage->m_pDelayLoadInfoDelayListSectionHot; - else - pSection = m_pImage->m_pDelayLoadInfoDelayListSectionCold; - pSection->Place(pBlob); -} - -// ====================================================================================== -// -// Generic signatures -// -ZapGenericSignature * ZapImportTable::GetGenericSignature(PVOID signature, BOOL fMethod) -{ -#ifdef REDHAWK - _ASSERTE(!"NYI"); - return NULL; -#else - SigBuilder sigBuilder; - GetCompileInfo()->EncodeGenericSignature(signature, fMethod, &sigBuilder, this, EncodeModuleHelper); - - DWORD cbSig; - PVOID pSig = sigBuilder.GetSignature(&cbSig); - - ZapGenericSignature * pGenericSignature = (ZapGenericSignature *)m_genericSignatures.Lookup(ZapBlob::SHashKey(pSig, cbSig)); - - if (pGenericSignature != NULL) - return pGenericSignature; - - S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapGenericSignature)) + S_SIZE_T(cbSig); - - if (cbAllocSize.IsOverflow()) - ThrowHR(COR_E_OVERFLOW); - - void * pMemory = new (m_pImage->GetHeap()) BYTE[cbAllocSize.Value()]; - - pGenericSignature = new (pMemory) ZapGenericSignature(cbSig); - memcpy((void *)(pGenericSignature + 1), pSig, cbSig); - - m_genericSignatures.Add(pGenericSignature); - - return pGenericSignature; -#endif // REDHAWK -} - -// At ngen time Zapper::CompileModule PlaceFixups called from -// code:ZapSig.GetSignatureForTypeHandle -// -/*static*/ DWORD ZapImportTable::EncodeModuleHelper( LPVOID compileContext, - CORINFO_MODULE_HANDLE referencedModule) -{ - _ASSERTE(!IsReadyToRunCompilation() || IsLargeVersionBubbleEnabled()); - ZapImportTable * pTable = (ZapImportTable *)compileContext; - return pTable->GetIndexOfModule(referencedModule); -} - -void ZapImport::Save(ZapWriter * pZapWriter) -{ - if (IsReadyToRunCompilation()) - { - TARGET_POINTER_TYPE value = 0; - pZapWriter->Write(&value, sizeof(value)); - return; - } - - TARGET_POINTER_TYPE token = CORCOMPILE_TAG_TOKEN(GetBlob()->GetRVA()); - pZapWriter->Write(&token, sizeof(token)); -} - -// -// CORCOMPILE_CODE_IMPORT_SECTION -// - -COUNT_T ZapImportSectionsTable::Append(BYTE Type, USHORT Flags, BYTE EntrySize, ZapVirtualSection * pSection, ZapNode * pSignatures, ZapNode * pAuxiliaryData) -{ - ImportSection entry; - - entry.m_pSection = pSection; - entry.m_pSignatures = pSignatures; - entry.m_pAuxiliaryData = pAuxiliaryData; - entry.m_Flags = Flags; - entry.m_Type = Type; - entry.m_EntrySize = EntrySize; - - m_ImportSectionsTable.Append(entry); - - return m_ImportSectionsTable.GetCount() - 1; -} - -DWORD ZapImportSectionsTable::GetSize() -{ - return m_ImportSectionsTable.GetCount() * sizeof(CORCOMPILE_IMPORT_SECTION); -} - -void ZapImportSectionsTable::Save(ZapWriter * pZapWriter) -{ - COUNT_T nSections = m_ImportSectionsTable.GetCount(); - for (COUNT_T iSection = 0; iSection < nSections; iSection++) - { - ImportSection * p = &m_ImportSectionsTable[iSection]; - - CORCOMPILE_IMPORT_SECTION entry; - - ZapWriter::SetDirectoryData(&entry.Section, p->m_pSection); - - entry.Flags = p->m_Flags; - entry.Type = p->m_Type; - entry.EntrySize = p->m_EntrySize; - - entry.Signatures = (p->m_pSignatures != NULL) ? p->m_pSignatures->GetRVA() : NULL; - entry.AuxiliaryData = (p->m_pAuxiliaryData != NULL) ? p->m_pAuxiliaryData->GetRVA() : NULL; - - pZapWriter->Write(&entry, sizeof(entry)); - } -} - - -ZapImportSectionSignatures::ZapImportSectionSignatures(ZapImage * pImage, ZapVirtualSection * pImportSection, ZapVirtualSection * pGCSection) - : m_pImportSection(pImportSection), m_pImage(pImage) -{ - if (pGCSection != NULL) - { - m_pGCRefMapTable = new (pImage->GetHeap()) ZapGCRefMapTable(pImage); - pGCSection->Place(m_pGCRefMapTable); - } -} - -ZapImportSectionSignatures::~ZapImportSectionSignatures() -{ - if (m_pGCRefMapTable != NULL) - m_pGCRefMapTable->~ZapGCRefMapTable(); -} - -DWORD ZapImportSectionSignatures::GetSize() -{ - return m_pImportSection->GetNodeCount() * sizeof(DWORD); -} - -void ZapImportSectionSignatures::Save(ZapWriter * pZapWriter) -{ - COUNT_T nCount = m_pImportSection->GetNodeCount(); - for (COUNT_T i = 0; i < nCount; i++) - { - ZapNode * pNode = m_pImportSection->GetNode(i); - DWORD dwRVA = ((ZapImport *)pNode)->GetBlob()->GetRVA(); - pZapWriter->Write(&dwRVA, sizeof(dwRVA)); - } -} - -// ====================================================================================== -// -// Special lazy imports for lazily resolved method calls -// - -// -// External method thunk is a patchable thunk used for cross-module direct calls -// -class ZapExternalMethodThunk : public ZapImport -{ -public: - ZapExternalMethodThunk() - { - } - - CORINFO_METHOD_HANDLE GetMethod() - { - return (CORINFO_METHOD_HANDLE)GetHandle(); - } - - virtual DWORD GetSize() - { - return sizeof(CORCOMPILE_EXTERNAL_METHOD_THUNK); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_ExternalMethodThunk; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)GetHandle(); - - CORINFO_MODULE_HANDLE referencingModule; - mdToken token = pTable->GetCompileInfo()->TryEncodeMethodAsToken(handle, NULL, &referencingModule); - if (token != mdTokenNil) - { - _ASSERTE(TypeFromToken(token) == mdtMethodDef || TypeFromToken(token) == mdtMemberRef); - - pTable->EncodeModule( - (TypeFromToken(token) == mdtMethodDef) ? ENCODE_METHOD_ENTRY_DEF_TOKEN : ENCODE_METHOD_ENTRY_REF_TOKEN, - referencingModule, pSigBuilder); - - pSigBuilder->AppendData(RidFromToken(token)); - } - else - { - pTable->EncodeMethod(ENCODE_METHOD_ENTRY, handle, pSigBuilder); - } - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -void ZapExternalMethodThunk::Save(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - ZapNode * helper = pImage->GetHelperThunk(CORINFO_HELP_EE_EXTERNAL_FIXUP); - - CORCOMPILE_EXTERNAL_METHOD_THUNK thunk; - memset(&thunk, DEFAULT_CODE_BUFFER_INIT, sizeof(thunk)); -#if defined(TARGET_X86) || defined(TARGET_AMD64) - thunk.callJmp[0] = 0xE8; // call rel32 - pImage->WriteReloc(&thunk, 1, helper, 0, IMAGE_REL_BASED_REL32); - thunk.precodeType = _PRECODE_EXTERNAL_METHOD_THUNK; -#elif defined(TARGET_ARM) - // Setup the call to ExternalMethodFixupStub - // - // mov r12, pc - // - // Per ARM architecture reference manual section A2.3, - // reading the value of PC register will read the address - // of the current instruction plus 4. In this case, - // R12 will containing the address of "F004" below once - // the "mov" is executed. - // - // Since this is 4 bytes ahead of the start of the thunk, - // the assembly helper we will call into will adjust this - // so that we point to the start of the thunk correctly. - thunk.m_rgCode[0] = 0x46fc; - - // ldr pc, [pc, #4] - thunk.m_rgCode[1] = 0xf8df; - thunk.m_rgCode[2] = 0xf004; - - // Setup the initial target to be our assembly helper. - pImage->WriteReloc(&thunk, offsetof(CORCOMPILE_EXTERNAL_METHOD_THUNK, m_pTarget), helper, 0, IMAGE_REL_BASED_PTR); -#elif defined(TARGET_ARM64) - - thunk.m_rgCode[0] = 0x1000000C; //adr x12, #0 - thunk.m_rgCode[1] = 0xF940098A; //ldr x10, [x12, #16] - thunk.m_rgCode[2] = 0xD61F0140; //br x10 - - pImage->WriteReloc(&thunk, offsetof(CORCOMPILE_EXTERNAL_METHOD_THUNK, m_pTarget), helper, 0, IMAGE_REL_BASED_PTR); -#else - PORTABILITY_ASSERT("ZapExternalMethodThunk::Save"); - -#endif - - pZapWriter->Write(&thunk, sizeof(thunk)); - _ASSERTE(sizeof(thunk) == GetSize()); -} - -void ZapImportSectionSignatures::PlaceExternalMethodThunk(ZapImport * pImport) -{ - ZapExternalMethodThunk * pThunk = (ZapExternalMethodThunk *)pImport; - - if (m_pImportSection->GetNodeCount() == 0) - { - m_dwIndex = m_pImage->GetImportSectionsTable()->Append(CORCOMPILE_IMPORT_TYPE_EXTERNAL_METHOD, CORCOMPILE_IMPORT_FLAGS_CODE, - sizeof(CORCOMPILE_EXTERNAL_METHOD_THUNK), m_pImportSection, this, m_pGCRefMapTable); - - // Make sure the helper created - m_pImage->GetHelperThunk(CORINFO_HELP_EE_EXTERNAL_FIXUP); - } - - // Add entry to both the the cell and data sections - m_pImportSection->Place(pThunk); - - m_pImage->GetImportTable()->PlaceImportBlob(pThunk); - - m_pGCRefMapTable->Append(pThunk->GetMethod()); -} - -ZapImport * ZapImportTable::GetExternalMethodThunk(CORINFO_METHOD_HANDLE handle) -{ - return GetImport((PVOID)handle); -} - -// -// Stub dispatch cell is lazily initialized indirection used for virtual stub dispatch -// -class ZapStubDispatchCell : public ZapImport -{ - ZapNode * m_pDelayLoadHelper; - -public: - void SetDelayLoadHelper(ZapNode * pDelayLoadHelper) - { - _ASSERTE(m_pDelayLoadHelper == NULL); - m_pDelayLoadHelper = pDelayLoadHelper; - } - - CORINFO_METHOD_HANDLE GetMethod() - { - return (CORINFO_METHOD_HANDLE)GetHandle(); - } - - CORINFO_CLASS_HANDLE GetClass() - { - return (CORINFO_CLASS_HANDLE)GetHandle2(); - } - - virtual DWORD GetSize() - { - return TARGET_POINTER_SIZE; - } - - virtual UINT GetAlignment() - { - return TARGET_POINTER_SIZE; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_StubDispatchCell; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - CORINFO_MODULE_HANDLE referencingModule = pTable->GetJitInfo()->getClassModule(GetClass()); - referencingModule = pTable->TryEncodeModule(ENCODE_VIRTUAL_ENTRY_SLOT, referencingModule, pSigBuilder); - - DWORD slot = pTable->GetCompileInfo()->TryEncodeMethodSlot(GetMethod()); - - // We expect the encoding to always succeed - _ASSERTE(slot != (DWORD)-1); - - pSigBuilder->AppendData(slot); - - pTable->EncodeClassInContext(referencingModule, GetClass(), pSigBuilder); - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - TARGET_POINTER_TYPE cell; - pImage->WriteReloc(&cell, 0, m_pDelayLoadHelper, 0, IMAGE_REL_BASED_PTR); - pZapWriter->Write(&cell, sizeof(cell)); - } -}; - -ZapImport * ZapImportTable::GetStubDispatchCell(CORINFO_CLASS_HANDLE typeHnd, CORINFO_METHOD_HANDLE methHnd) -{ - // Do not intern stub dispatch imports. Each callsite should get own cell. - ZapImport * pImport = new (m_pImage->GetHeap()) ZapStubDispatchCell(); - pImport->SetHandle(methHnd); - pImport->SetHandle2(typeHnd); - return pImport; -} - -void ZapImportSectionSignatures::PlaceStubDispatchCell(ZapImport * pImport) -{ - ZapStubDispatchCell * pCell = (ZapStubDispatchCell *)pImport; - - if (m_pImportSection->GetNodeCount() == 0) - { - m_dwIndex = m_pImage->GetImportSectionsTable()->Append(CORCOMPILE_IMPORT_TYPE_STUB_DISPATCH, CORCOMPILE_IMPORT_FLAGS_PCODE, - TARGET_POINTER_SIZE, m_pImportSection, this, m_pGCRefMapTable); - } - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - // Create the delay load helper - ReadyToRunHelper helper = (ReadyToRunHelper)(READYTORUN_HELPER_DelayLoad_MethodCall | READYTORUN_HELPER_FLAG_VSD); - ZapNode * pDelayLoadHelper = m_pImage->GetImportTable()->GetPlacedIndirectHelperThunk(helper, (PVOID)(SIZE_T)m_dwIndex); - pCell->SetDelayLoadHelper(pDelayLoadHelper); - } - else -#endif - { - pCell->SetDelayLoadHelper(m_pImage->GetHelperThunk(CORINFO_HELP_EE_VSD_FIXUP)); - } - - // Add entry to both the cell and data sections - m_pImportSection->Place(pCell); - - m_pImage->GetImportTable()->PlaceImportBlob(pCell); - - m_pGCRefMapTable->Append(pCell->GetMethod(), true); -} - -// -// External method cell is lazily initialized indirection used for method calls -// -class ZapExternalMethodCell : public ZapImport -{ - ZapNode * m_pDelayLoadHelper; - -public: - void SetDelayLoadHelper(ZapNode * pDelayLoadHelper) - { - _ASSERTE(m_pDelayLoadHelper == NULL); - m_pDelayLoadHelper = pDelayLoadHelper; - } - CORINFO_METHOD_HANDLE GetMethod() - { - return (CORINFO_METHOD_HANDLE)GetHandle(); - } - - virtual DWORD GetSize() - { - return TARGET_POINTER_SIZE; - } - - virtual UINT GetAlignment() - { - return TARGET_POINTER_SIZE; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_ExternalMethodCell; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)GetHandle(); - - CORINFO_MODULE_HANDLE referencingModule; - mdToken token = pTable->GetCompileInfo()->TryEncodeMethodAsToken(handle, NULL, &referencingModule); - if (token != mdTokenNil) - { - _ASSERTE(TypeFromToken(token) == mdtMethodDef || TypeFromToken(token) == mdtMemberRef); - - pTable->EncodeModule( - (TypeFromToken(token) == mdtMethodDef) ? ENCODE_METHOD_ENTRY_DEF_TOKEN : ENCODE_METHOD_ENTRY_REF_TOKEN, - referencingModule, pSigBuilder); - - pSigBuilder->AppendData(RidFromToken(token)); - } - else - { - pTable->EncodeMethod(ENCODE_METHOD_ENTRY, handle, pSigBuilder); - } - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - TARGET_POINTER_TYPE cell; - pImage->WriteReloc(&cell, 0, m_pDelayLoadHelper, 0, IMAGE_REL_BASED_PTR); - pZapWriter->Write(&cell, sizeof(cell)); - } -}; - -ZapImport * ZapImportTable::GetExternalMethodCell(CORINFO_METHOD_HANDLE handle) -{ - return GetImport((PVOID)handle); -} - -void ZapImportSectionSignatures::PlaceExternalMethodCell(ZapImport * pImport) -{ - ZapExternalMethodCell * pCell = (ZapExternalMethodCell *)pImport; - - if (m_pImportSection->GetNodeCount() == 0) - { - m_dwIndex = m_pImage->GetImportSectionsTable()->Append(CORCOMPILE_IMPORT_TYPE_STUB_DISPATCH, CORCOMPILE_IMPORT_FLAGS_PCODE, - TARGET_POINTER_SIZE, m_pImportSection, this, m_pGCRefMapTable); - } - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - // Create the delay load helper - ZapNode * pDelayLoadHelper = m_pImage->GetImportTable()->GetPlacedIndirectHelperThunk(READYTORUN_HELPER_DelayLoad_MethodCall, (PVOID)(SIZE_T)m_dwIndex); - pCell->SetDelayLoadHelper(pDelayLoadHelper); - } - else -#endif - { - pCell->SetDelayLoadHelper(m_pImage->GetHelperThunk(CORINFO_HELP_EE_EXTERNAL_FIXUP)); - } - - // Add entry to both the cell and data sections - m_pImportSection->Place(pCell); - - m_pImage->GetImportTable()->PlaceImportBlob(pCell); - - m_pGCRefMapTable->Append(pCell->GetMethod()); -} - -// -// Virtual import thunk is a patchable thunk used for cross-module virtual calls. -// -class ZapVirtualMethodThunk : public ZapImport -{ -public: - virtual DWORD GetSize() - { - return sizeof(CORCOMPILE_VIRTUAL_IMPORT_THUNK); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_VirtualMethodThunk; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - // Virtual import thunks do not have signatures - _ASSERTE(false); - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -void ZapVirtualMethodThunk::Save(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - CORCOMPILE_VIRTUAL_IMPORT_THUNK thunk; - memset(&thunk, DEFAULT_CODE_BUFFER_INIT, sizeof(thunk)); - - // On ARM, the helper would already have the thumb-bit set. Refer to - // GetHelperThunk implementation. - ZapNode * helper = pImage->GetHelperThunk(CORINFO_HELP_EE_VTABLE_FIXUP); - _ASSERTE(FitsIn((SIZE_T)GetHandle2() - 1)); - USHORT slotNum = (USHORT)((SIZE_T)GetHandle2() - 1); - -#if defined(TARGET_X86) || defined(TARGET_AMD64) - thunk.callJmp[0] = 0xE8; // call rel32 - pImage->WriteReloc(&thunk, 1, helper, 0, IMAGE_REL_BASED_REL32); - - // Mark this as a Virtual Import Thunk - thunk.precodeType = _PRECODE_VIRTUAL_IMPORT_THUNK; -#elif defined(TARGET_ARM) - // Setup the call to VirtualMethodFixupStub - // - // mov r12, pc - // - // Per ARM architecture reference manual section A2.3, - // reading the value of PC register will read the address - // of the current instruction plus 4. In this case, - // R12 will containing the address of "F004" below once - // the "mov" is executed. - // - // Since this is 4 bytes ahead of the start of the thunk, - // the assembly helper we will call into will adjust this - // so that we point to the start of the thunk correctly. - thunk.m_rgCode[0] = 0x46fc; - - // ldr pc, [pc, #4] - thunk.m_rgCode[1] = 0xf8df; - thunk.m_rgCode[2] = 0xf004; - - // Slot ID is setup below, so now setup the initial target - // to be our assembly helper. - pImage->WriteReloc(&thunk, offsetof(CORCOMPILE_VIRTUAL_IMPORT_THUNK, m_pTarget), helper, 0, IMAGE_REL_BASED_PTR); - #elif defined(TARGET_ARM64) - - thunk.m_rgCode[0] = 0x1000000C; //adr x12, #0 - thunk.m_rgCode[1] = 0xF940098A; //ldr x10, [x12, #16] - thunk.m_rgCode[2] = 0xD61F0140; //br x10 - - // Slot ID is setup below, so now setup the initial target - // to be our assembly helper. - pImage->WriteReloc(&thunk, offsetof(CORCOMPILE_VIRTUAL_IMPORT_THUNK, m_pTarget), helper, 0, IMAGE_REL_BASED_PTR); -#else - PORTABILITY_ASSERT("ZapVirtualMethodThunk::Save"); -#endif - - thunk.slotNum = slotNum; - - pZapWriter->Write(&thunk, sizeof(thunk)); -} - -void ZapImportTable::PlaceVirtualImportThunk(ZapImport * pVirtualImportThunk) -{ - if (m_pImage->m_pVirtualImportThunkSection->GetNodeCount() == 0) - { - m_pImage->GetImportSectionsTable()->Append(CORCOMPILE_IMPORT_TYPE_VIRTUAL_METHOD, CORCOMPILE_IMPORT_FLAGS_CODE, - sizeof(CORCOMPILE_VIRTUAL_IMPORT_THUNK), m_pImage->m_pVirtualImportThunkSection); - - // Make sure the helper created - m_pImage->GetHelperThunk(CORINFO_HELP_EE_VTABLE_FIXUP); - } - - m_pImage->m_pVirtualImportThunkSection->Place(pVirtualImportThunk); -} - -ZapImport * ZapImportTable::GetVirtualImportThunk(CORINFO_METHOD_HANDLE handle, int slot) -{ - return GetImport(handle, (PVOID)(SIZE_T)(slot+1)); -} - -// ====================================================================================== -// -// GCRefMapTable is used to encode for GC references locations for lazily resolved calls -// - -void ZapGCRefMapTable::Append(CORINFO_METHOD_HANDLE handle, bool isDispatchCell) -{ - m_pImage->GetCompileInfo()->GetCallRefMap(handle, &m_GCRefMapBuilder, isDispatchCell); - m_nCount++; -} - -DWORD ZapGCRefMapTable::GetSize() -{ - if (m_nCount == 0) return 0; - - COUNT_T nLookupEntries = (1 + m_nCount / GCREFMAP_LOOKUP_STRIDE); - - return (nLookupEntries * sizeof(DWORD)) + m_GCRefMapBuilder.GetBlobLength(); -} - -void ZapGCRefMapTable::Save(ZapWriter * pZapWriter) -{ - if (m_nCount == 0) return; - - COUNT_T nLookupEntries = (1 + m_nCount / GCREFMAP_LOOKUP_STRIDE); - - DWORD dwBlobLength; - BYTE * pBlob = (BYTE *)m_GCRefMapBuilder.GetBlob(&dwBlobLength); - - DWORD pos = 0; - COUNT_T iLookupEntry = 0; - for (;;) - { - DWORD relOfs = (nLookupEntries * sizeof(DWORD)) + pos; - pZapWriter->Write(&relOfs, sizeof(relOfs)); - iLookupEntry++; - - if (iLookupEntry >= nLookupEntries) - break; - - for (int i = 0; i < GCREFMAP_LOOKUP_STRIDE; i++) - { - while ((*(pBlob + pos) & 0x80) != 0) - pos++; - pos++; - - _ASSERTE(pos <= dwBlobLength); - } - } - - pZapWriter->Write(pBlob, dwBlobLength); -} - -// ====================================================================================== -// -// Getters for existing imports. -// - -ZapImport * ZapImportTable::GetExistingClassHandleImport(CORINFO_CLASS_HANDLE handle) -{ - return GetExistingImport(ZapNodeType_Import_ClassHandle, handle); -} - -ZapImport * ZapImportTable::GetExistingFieldHandleImport(CORINFO_FIELD_HANDLE handle) -{ - return GetExistingImport(ZapNodeType_Import_FieldHandle, handle); -} - -ZapImport * ZapImportTable::GetExistingMethodHandleImport(CORINFO_METHOD_HANDLE handle) -{ - return GetExistingImport(ZapNodeType_Import_MethodHandle, handle); -} - -CORINFO_MODULE_HANDLE ZapImportTable::TryEncodeModule(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_MODULE_HANDLE module, SigBuilder * pSigBuilder) -{ - if (!GetCompileInfo()->IsInCurrentVersionBubble(module)) - module = GetImage()->GetModuleHandle(); - - EncodeModule(kind, module, pSigBuilder); - return module; -} - -void ZapImportTable::EncodeModule(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_MODULE_HANDLE module, SigBuilder * pSigBuilder) -{ - if (module != GetImage()->GetModuleHandle()) - { - _ASSERTE(!IsReadyToRunCompilation() || IsLargeVersionBubbleEnabled()); - pSigBuilder->AppendByte(kind | ENCODE_MODULE_OVERRIDE); - pSigBuilder->AppendData(GetIndexOfModule(module)); - } - else - { - pSigBuilder->AppendByte(kind); - } -} - -void ZapImportTable::EncodeClass(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_CLASS_HANDLE handle, SigBuilder * pSigBuilder) -{ - CORINFO_MODULE_HANDLE referencingModule = GetJitInfo()->getClassModule(handle); - referencingModule = TryEncodeModule(kind, referencingModule, pSigBuilder); - GetCompileInfo()->EncodeClass(referencingModule, handle, pSigBuilder, this, EncodeModuleHelper); -} - -void ZapImportTable::EncodeClassInContext(CORINFO_MODULE_HANDLE context, CORINFO_CLASS_HANDLE handle, SigBuilder * pSigBuilder) -{ - GetCompileInfo()->EncodeClass(context, handle, pSigBuilder, this, EncodeModuleHelper); -} - -void ZapImportTable::EncodeField(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, SigBuilder * pSigBuilder, - CORINFO_RESOLVED_TOKEN * pResolvedToken, BOOL fEncodeUsingResolvedTokenSpecStreams) -{ - CORINFO_CLASS_HANDLE clsHandle = GetJitInfo()->getFieldClass(handle); - CORINFO_MODULE_HANDLE referencingModule = GetJitInfo()->getClassModule(clsHandle); - referencingModule = TryEncodeModule(kind, referencingModule, pSigBuilder); - GetCompileInfo()->EncodeField(referencingModule, handle, pSigBuilder, this, EncodeModuleHelper, - pResolvedToken, fEncodeUsingResolvedTokenSpecStreams); -} - -void ZapImportTable::EncodeMethod(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, SigBuilder * pSigBuilder, - CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken, BOOL fEncodeUsingResolvedTokenSpecStreams) -{ - CORINFO_CLASS_HANDLE clsHandle = GetJitInfo()->getMethodClass(handle); - CORINFO_MODULE_HANDLE referencingModule = GetJitInfo()->getClassModule(clsHandle); - referencingModule = TryEncodeModule(kind, referencingModule, pSigBuilder); - GetCompileInfo()->EncodeMethod(referencingModule, handle, pSigBuilder, this, EncodeModuleHelper, - pResolvedToken, pConstrainedResolvedToken, fEncodeUsingResolvedTokenSpecStreams); -} - -// ====================================================================================== -// -// Actual imports -// - -class ZapModuleHandleImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_ModuleHandle; - } - - virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature) - { - ZapImport::ComputePlacement(pImage, pfIsEager, pfNeedsSignature); - - CORINFO_MODULE_HANDLE handle = (CORINFO_MODULE_HANDLE)GetHandle(); - if (pImage->m_pPreloader->CanEmbedModuleHandle(handle)) - { - *pfIsEager = TRUE; - } - - return ZapImportSectionType_Handle; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeModule(ENCODE_MODULE_HANDLE, (CORINFO_MODULE_HANDLE)GetHandle(), pSigBuilder); - } -}; - -ZapImport * ZapImportTable::GetModuleHandleImport(CORINFO_MODULE_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapClassHandleImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_ClassHandle; - } - - virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature) - { - ZapImport::ComputePlacement(pImage, pfIsEager, pfNeedsSignature); - - if (IsReadyToRunCompilation()) - return ZapImportSectionType_Handle; - - CORINFO_CLASS_HANDLE handle = (CORINFO_CLASS_HANDLE)GetHandle(); - if (pImage->m_pPreloader->CanEmbedClassHandle(handle)) - { - // We may have entries pointing to our module that exist in the handle table to trigger restore. - if (pImage->GetCompileInfo()->GetLoaderModuleForEmbeddableType(handle) == pImage->GetModuleHandle()) - { - *pfNeedsSignature = FALSE; - } - else - { - *pfIsEager = TRUE; - } - } - - return ZapImportSectionType_TypeHandle; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeClass(ENCODE_TYPE_HANDLE, (CORINFO_CLASS_HANDLE)GetHandle(), pSigBuilder); - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - // We may have entries pointing to our module that exist in the handle table to trigger restore. - if (!HasBlob()) - { - PVOID cell; - ZapNode handle(pImage->m_pPreloader->MapClassHandle((CORINFO_CLASS_HANDLE)GetHandle())); - pImage->WriteReloc(&cell, 0, &handle, 0, IMAGE_REL_BASED_PTR); - pZapWriter->Write(&cell, sizeof(cell)); - } - else - { - ZapImport::Save(pZapWriter); - } - } -}; - -ZapImport * ZapImportTable::GetClassHandleImport(CORINFO_CLASS_HANDLE handle, PVOID pUniqueId) -{ - // pUniqueId is workaround for loading of generic parent method table. It would be nice to clean it up. - if (pUniqueId != NULL) - { - return GetImport(handle, pUniqueId); - } - - ZapImport * pImport = GetImport(handle); - - if (IsReadyToRunCompilation() && !pImport->HasBlob()) - { - SigBuilder sigBuilder; - - EncodeClass(ENCODE_TYPE_HANDLE, handle, &sigBuilder); - - pImport->SetBlob(GetBlob(&sigBuilder)); - } - - return pImport; -} - -class ZapFieldHandleImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_FieldHandle; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeField(ENCODE_FIELD_HANDLE, (CORINFO_FIELD_HANDLE)GetHandle(), pSigBuilder); - } -}; - -ZapImport * ZapImportTable::GetFieldHandleImport(CORINFO_FIELD_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapMethodHandleImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_MethodHandle; - } - - virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature) - { - ZapImport::ComputePlacement(pImage, pfIsEager, pfNeedsSignature); - - if (IsReadyToRunCompilation()) - return ZapImportSectionType_Handle; - - CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)GetHandle(); - if (pImage->m_pPreloader->CanEmbedMethodHandle(handle)) - { - // We may have entries pointing to our module that exist in the handle table to trigger restore. - if (pImage->GetCompileInfo()->GetLoaderModuleForEmbeddableMethod(handle) == pImage->GetModuleHandle()) - { - *pfNeedsSignature = FALSE; - } - } - - return ZapImportSectionType_MethodHandle; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeMethod(ENCODE_METHOD_HANDLE, (CORINFO_METHOD_HANDLE)GetHandle(), pSigBuilder); - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - // We may have entries pointing to our module that exist in the handle table to trigger restore. - if (!HasBlob()) - { - PVOID cell; - ZapNode handle(pImage->m_pPreloader->MapMethodHandle((CORINFO_METHOD_HANDLE)GetHandle())); - pImage->WriteReloc(&cell, 0, &handle, 0, IMAGE_REL_BASED_PTR); - pZapWriter->Write(&cell, sizeof(cell)); - } - else - { - ZapImport::Save(pZapWriter); - } - } -}; - -ZapImport * ZapImportTable::GetMethodHandleImport(CORINFO_METHOD_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapStringHandleImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_StringHandle; - } - - virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature) - { - ZapImport::ComputePlacement(pImage, pfIsEager, pfNeedsSignature); - - // Empty string - if ((mdString)(size_t)GetHandle2() == mdtString) - { - *pfIsEager = TRUE; - return ZapImportSectionType_Handle; - } - - return ZapImportSectionType_StringHandle; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - CORINFO_MODULE_HANDLE referencingModule = (CORINFO_MODULE_HANDLE)GetHandle(); - - pTable->EncodeModule(ENCODE_STRING_HANDLE, referencingModule, pSigBuilder); - - mdString token = (mdString)(size_t)GetHandle2(); - pSigBuilder->AppendData(RidFromToken(token)); - } -}; - -ZapImport * ZapImportTable::GetStringHandleImport(CORINFO_MODULE_HANDLE tokenScope, mdString metaTok) -{ - return GetImport(tokenScope, (PVOID)(size_t)metaTok); -} - -class ZapFunctionEntryImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_FunctionEntry; - } - -#ifdef TARGET_ARM - virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature) - { - ZapImport::ComputePlacement(pImage, pfIsEager, pfNeedsSignature); - return ZapImportSectionType_PCode; - } -#endif - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)GetHandle(); - - CORINFO_MODULE_HANDLE referencingModule; - mdToken token = pTable->GetCompileInfo()->TryEncodeMethodAsToken(handle, NULL, &referencingModule); - if (token != mdTokenNil) - { - _ASSERTE(TypeFromToken(token) == mdtMethodDef || TypeFromToken(token) == mdtMemberRef); - _ASSERTE(!pTable->GetCompileInfo()->IsUnmanagedCallersOnlyMethod(handle)); - - pTable->EncodeModule( - (TypeFromToken(token) == mdtMethodDef) ? ENCODE_METHOD_ENTRY_DEF_TOKEN : ENCODE_METHOD_ENTRY_REF_TOKEN, - referencingModule, pSigBuilder); - - pSigBuilder->AppendData(RidFromToken(token)); - } - else - { - pTable->EncodeMethod(ENCODE_METHOD_ENTRY, handle, pSigBuilder); - } - } - - virtual void Save(ZapWriter * pZapWriter) - { - SIZE_T token = CORCOMPILE_TAG_PCODE(GetBlob()->GetRVA()); - pZapWriter->Write(&token, sizeof(token)); - } -}; - -ZapImport * ZapImportTable::GetFunctionEntryImport(CORINFO_METHOD_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapStaticFieldAddressImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_StaticFieldAddress; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeField(ENCODE_STATIC_FIELD_ADDRESS, (CORINFO_FIELD_HANDLE)GetHandle(), pSigBuilder); - } - - virtual DWORD GetSize() - { - return 2 * TARGET_POINTER_SIZE; - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapImport::Save(pZapWriter); - - TADDR value = 0; - pZapWriter->Write(&value, sizeof(value)); - } -}; - -ZapImport * ZapImportTable::GetStaticFieldAddressImport(CORINFO_FIELD_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapClassDomainIdImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_ClassDomainId; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeClass(ENCODE_CLASS_ID_FOR_STATICS, (CORINFO_CLASS_HANDLE)GetHandle(), pSigBuilder); - } -}; - -ZapImport * ZapImportTable::GetClassDomainIdImport(CORINFO_CLASS_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapModuleDomainIdImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_ModuleDomainId; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - if (GetHandle() != NULL) - { - pTable->EncodeModule(ENCODE_MODULE_ID_FOR_STATICS, (CORINFO_MODULE_HANDLE)GetHandle(), pSigBuilder); - } - else - { - _ASSERTE(GetHandle2() != NULL); - - pTable->EncodeClass(ENCODE_MODULE_ID_FOR_GENERIC_STATICS, (CORINFO_CLASS_HANDLE)GetHandle2(), pSigBuilder); - } - } -}; - -ZapImport * ZapImportTable::GetModuleDomainIdImport(CORINFO_MODULE_HANDLE handleToModule, CORINFO_CLASS_HANDLE handleToClass) -{ - _ASSERTE(((void *)handleToModule != (void *)handleToClass) && ((handleToModule == NULL) || (handleToClass == NULL))); - - return GetImport(handleToModule, handleToClass); -} - -class ZapSyncLockImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_SyncLock; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeClass(ENCODE_SYNC_LOCK, (CORINFO_CLASS_HANDLE)GetHandle(), pSigBuilder); - } -}; - -ZapImport * ZapImportTable::GetSyncLockImport(CORINFO_CLASS_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapIndirectPInvokeTargetImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_IndirectPInvokeTarget; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeMethod(ENCODE_INDIRECT_PINVOKE_TARGET, (CORINFO_METHOD_HANDLE)GetHandle(), pSigBuilder); - } -}; - -ZapImport * ZapImportTable::GetIndirectPInvokeTargetImport(CORINFO_METHOD_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapPInvokeTargetImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_PInvokeTarget; - } - - virtual void EncodeSignature(ZapImportTable* pTable, SigBuilder* pSigBuilder) - { - pTable->EncodeMethod(ENCODE_PINVOKE_TARGET, (CORINFO_METHOD_HANDLE)GetHandle(), pSigBuilder); - } -}; - -ZapImport * ZapImportTable::GetPInvokeTargetImport(CORINFO_METHOD_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapProfilingHandleImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_ProfilingHandle; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeMethod(ENCODE_PROFILING_HANDLE, (CORINFO_METHOD_HANDLE)GetHandle(), pSigBuilder); - } - - virtual DWORD GetSize() - { - // fixup cell, 3 pointers to interception method (Enter/Leave/Tailcall) and opaque handle - return kZapProfilingHandleImportValueIndexCount * TARGET_POINTER_SIZE; - } - - virtual void Save(ZapWriter * pZapWriter) - { - // Save fixup cell - ZapImport::Save(pZapWriter); - - // Save zeroes for the rest of the entries - - // If this assert fires, someone changed the - // kZapProfilingHandleImportValueIndex... enum values without updating me! - _ASSERTE(kZapProfilingHandleImportValueIndexCount == 5); - - TADDR value = 0; - pZapWriter->Write(&value, sizeof(value)); - pZapWriter->Write(&value, sizeof(value)); - pZapWriter->Write(&value, sizeof(value)); - pZapWriter->Write(&value, sizeof(value)); - } -}; - -ZapImport * ZapImportTable::GetProfilingHandleImport(CORINFO_METHOD_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapVarArgImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_VarArg; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - _ASSERTE((CORINFO_MODULE_HANDLE)GetHandle() == pTable->GetImage()->GetModuleHandle()); - - mdToken token = (mdToken)(size_t)GetHandle2(); - switch (TypeFromToken(token)) - { - case mdtSignature: - pSigBuilder->AppendByte(ENCODE_VARARGS_SIG); - break; - - case mdtMemberRef: - pSigBuilder->AppendByte(ENCODE_VARARGS_METHODREF); - break; - - case mdtMethodDef: - pSigBuilder->AppendByte(ENCODE_VARARGS_METHODDEF); - break; - - default: - _ASSERTE(!"Bogus token for signature"); - } - - pSigBuilder->AppendData(RidFromToken(token)); - } -}; - -ZapImport * ZapImportTable::GetVarArgImport(CORINFO_MODULE_HANDLE handle, mdToken sigOrMemberRefOrDef) -{ - return GetImport(handle, (PVOID)(size_t)sigOrMemberRefOrDef); -} - -class ZapActiveDependencyImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_ActiveDependency; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeModule(ENCODE_ACTIVE_DEPENDENCY, (CORINFO_MODULE_HANDLE)GetHandle(), pSigBuilder); - pSigBuilder->AppendData(pTable->GetIndexOfModule((CORINFO_MODULE_HANDLE)GetHandle2())); - } -}; - -ZapImport * ZapImportTable::GetActiveDependencyImport(CORINFO_MODULE_HANDLE moduleFrom, CORINFO_MODULE_HANDLE moduleTo) -{ - return GetImport(moduleFrom, moduleTo); -} - -ZapImport * ZapImportTable::GetClassImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_RESOLVED_TOKEN * pResolvedToken) -{ - CORINFO_CLASS_HANDLE handle = (CORINFO_CLASS_HANDLE) pResolvedToken->hClass; - - ZapImport * pImport = GetImport(handle, (PVOID)kind); - - if (!pImport->HasBlob()) - { - SigBuilder sigBuilder; - - EncodeClass(kind, handle, &sigBuilder); - - pImport->SetBlob(GetBlob(&sigBuilder)); - } - - return pImport; -} - -ZapImport * ZapImportTable::GetMethodImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, - CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken /*=NULL*/) -{ - SigBuilder sigBuilder; - EncodeMethod(kind, handle, &sigBuilder, pResolvedToken, pConstrainedResolvedToken); - - return GetImportForSignature((PVOID)handle, &sigBuilder); -} - -ZapImport * ZapImportTable::GetFieldImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken) -{ - SigBuilder sigBuilder; - EncodeField(kind, handle, &sigBuilder, pResolvedToken); - - return GetImportForSignature((PVOID)handle, &sigBuilder); -} - -#ifdef FEATURE_READYTORUN_COMPILER -ZapImport * ZapImportTable::GetCheckTypeLayoutImport(CORINFO_CLASS_HANDLE handle) -{ - ZapImport * pImport = GetImport(handle, (PVOID)ENCODE_CHECK_TYPE_LAYOUT); - - if (!pImport->HasBlob()) - { - SigBuilder sigBuilder; - - sigBuilder.AppendData(ENCODE_CHECK_TYPE_LAYOUT); - - GetCompileInfo()->EncodeClass(m_pImage->GetModuleHandle(), handle, &sigBuilder, NULL, NULL); - - GetCompileInfo()->EncodeTypeLayout(handle, &sigBuilder); - - pImport->SetBlob(GetBlob(&sigBuilder)); - } - - return pImport; -} - -ZapImport * ZapImportTable::GetCheckFieldOffsetImport(CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, DWORD offset) -{ - SigBuilder sigBuilder; - - sigBuilder.AppendData(ENCODE_CHECK_FIELD_OFFSET); - - sigBuilder.AppendData(offset); - - GetCompileInfo()->EncodeField(m_pImage->GetModuleHandle(), handle, &sigBuilder, NULL, NULL, pResolvedToken); - - EncodeField(ENCODE_CHECK_FIELD_OFFSET, handle, &sigBuilder, pResolvedToken); - - return GetImportForSignature((PVOID)handle, &sigBuilder); -} -#endif // FEATURE_READYTORUN_COMPILER - -ZapImport * ZapImportTable::GetStubDispatchCell(CORINFO_RESOLVED_TOKEN * pResolvedToken) -{ - CORINFO_METHOD_HANDLE handle = pResolvedToken->hMethod; - - SigBuilder sigBuilder; - - DWORD slot = GetCompileInfo()->TryEncodeMethodSlot(handle); - if (slot != (DWORD) -1) - { - CORINFO_CLASS_HANDLE clsHandle = pResolvedToken->hClass; - - CORINFO_MODULE_HANDLE referencingModule = GetJitInfo()->getClassModule(clsHandle); - - referencingModule = TryEncodeModule(ENCODE_VIRTUAL_ENTRY_SLOT, referencingModule, &sigBuilder); - - sigBuilder.AppendData(slot); - - EncodeClassInContext(referencingModule, clsHandle, &sigBuilder); - } - else - { - CORINFO_MODULE_HANDLE referencingModule; - mdToken token = GetCompileInfo()->TryEncodeMethodAsToken(handle, pResolvedToken, &referencingModule); - if (token != mdTokenNil) - { - _ASSERTE(TypeFromToken(token) == mdtMethodDef || TypeFromToken(token) == mdtMemberRef); - - EncodeModule( - (TypeFromToken(token) == mdtMethodDef) ? ENCODE_VIRTUAL_ENTRY_DEF_TOKEN : ENCODE_VIRTUAL_ENTRY_REF_TOKEN, - referencingModule, &sigBuilder); - - sigBuilder.AppendData(RidFromToken(token)); - } - else - { - EncodeMethod(ENCODE_VIRTUAL_ENTRY, handle, &sigBuilder, pResolvedToken); - } - } - - // For now, always optimize ready to run for size and startup performance - share cells between callsites - return GetImportForSignature((PVOID)handle, &sigBuilder); -} - -ZapImport * ZapImportTable::GetExternalMethodCell(CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken) -{ - SigBuilder sigBuilder; - - CORINFO_MODULE_HANDLE referencingModule; - mdToken token = GetCompileInfo()->TryEncodeMethodAsToken(handle, pResolvedToken, &referencingModule); - if (token != mdTokenNil) - { - _ASSERTE(TypeFromToken(token) == mdtMethodDef || TypeFromToken(token) == mdtMemberRef); - - EncodeModule( - (TypeFromToken(token) == mdtMethodDef) ? ENCODE_METHOD_ENTRY_DEF_TOKEN : ENCODE_METHOD_ENTRY_REF_TOKEN, - referencingModule, &sigBuilder); - - sigBuilder.AppendData(RidFromToken(token)); - } - else - { - EncodeMethod(ENCODE_METHOD_ENTRY, handle, &sigBuilder, pResolvedToken, pConstrainedResolvedToken, false); - } - - return GetImportForSignature((PVOID)handle, &sigBuilder); -} - - -#ifdef FEATURE_READYTORUN_COMPILER - -class ZapDynamicHelperCell : public ZapImport -{ - ZapNode * m_pDelayLoadHelper; - -public: - void SetDelayLoadHelper(ZapNode * pDelayLoadHelper) - { - _ASSERTE(m_pDelayLoadHelper == NULL); - m_pDelayLoadHelper = pDelayLoadHelper; - } - - virtual DWORD GetSize() - { - return TARGET_POINTER_SIZE; - } - - virtual UINT GetAlignment() - { - return TARGET_POINTER_SIZE; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_DynamicHelperCell; - } - - CORCOMPILE_FIXUP_BLOB_KIND GetKind() - { - int kind = (int)(SIZE_T)GetHandle(); - - if ((kind & 1) == 1) - { - return (CORCOMPILE_FIXUP_BLOB_KIND)(kind >> 1); - } - else - { - _ASSERTE( - (GetBlob()->GetSize() > 0) && ( - GetBlob()->GetData()[0] == ENCODE_DICTIONARY_LOOKUP_THISOBJ || - GetBlob()->GetData()[0] == ENCODE_DICTIONARY_LOOKUP_METHOD || - GetBlob()->GetData()[0] == ENCODE_DICTIONARY_LOOKUP_TYPE)); - - return (CORCOMPILE_FIXUP_BLOB_KIND)GetBlob()->GetData()[0]; - } - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - // Encode should be unreachable for ready-to-run cells - _ASSERTE(false); - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - TARGET_POINTER_TYPE cell; - pImage->WriteReloc(&cell, 0, m_pDelayLoadHelper, 0, IMAGE_REL_BASED_PTR); - pZapWriter->Write(&cell, sizeof(cell)); - } -}; - -static ReadyToRunHelper GetDelayLoadHelperForDynamicHelper(CORCOMPILE_FIXUP_BLOB_KIND kind) -{ - switch (kind) - { - case ENCODE_NEW_HELPER: - case ENCODE_NEW_ARRAY_HELPER: - case ENCODE_STATIC_BASE_NONGC_HELPER: - case ENCODE_STATIC_BASE_GC_HELPER: - case ENCODE_THREAD_STATIC_BASE_NONGC_HELPER: - case ENCODE_THREAD_STATIC_BASE_GC_HELPER: - case ENCODE_CCTOR_TRIGGER: - case ENCODE_FIELD_ADDRESS: - case ENCODE_DICTIONARY_LOOKUP_THISOBJ: - case ENCODE_DICTIONARY_LOOKUP_TYPE: - case ENCODE_DICTIONARY_LOOKUP_METHOD: - return READYTORUN_HELPER_DelayLoad_Helper; - - case ENCODE_CHKCAST_HELPER: - case ENCODE_ISINSTANCEOF_HELPER: - return READYTORUN_HELPER_DelayLoad_Helper_Obj; - - case ENCODE_VIRTUAL_ENTRY: - // case ENCODE_VIRTUAL_ENTRY_DEF_TOKEN: - // case ENCODE_VIRTUAL_ENTRY_REF_TOKEN: - // case ENCODE_VIRTUAL_ENTRY_SLOT: - return READYTORUN_HELPER_DelayLoad_Helper_Obj; - - case ENCODE_DELEGATE_CTOR: - return READYTORUN_HELPER_DelayLoad_Helper_ObjObj; - - default: - UNREACHABLE(); - } -} - -void ZapImportSectionSignatures::PlaceDynamicHelperCell(ZapImport * pImport) -{ - ZapDynamicHelperCell * pCell = (ZapDynamicHelperCell *)pImport; - - if (m_pImportSection->GetNodeCount() == 0) - { - m_dwIndex = m_pImage->GetImportSectionsTable()->Append(CORCOMPILE_IMPORT_TYPE_UNKNOWN, CORCOMPILE_IMPORT_FLAGS_PCODE, - TARGET_POINTER_SIZE, m_pImportSection, this, m_pGCRefMapTable); - } - - // Create the delay load helper - ReadyToRunHelper helperNum = GetDelayLoadHelperForDynamicHelper(pCell->GetKind()); - ZapNode * pDelayLoadHelper = m_pImage->GetImportTable()->GetPlacedIndirectHelperThunk(helperNum, (PVOID)(SIZE_T)m_dwIndex); - - pCell->SetDelayLoadHelper(pDelayLoadHelper); - - // Add entry to both the the cell and data sections - m_pImportSection->Place(pCell); - - m_pImage->GetImportTable()->PlaceImportBlob(pCell); -} - -ZapImport * ZapImportTable::GetDictionaryLookupCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE containingMethod, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_LOOKUP_KIND * pLookup) -{ - _ASSERTE(pLookup->needsRuntimeLookup); - - SigBuilder sigBuilder; - - sigBuilder.AppendData(kind); - - if (kind == ENCODE_DICTIONARY_LOOKUP_THISOBJ) - { - CORINFO_CLASS_HANDLE hClassContext = GetJitInfo()->getMethodClass(containingMethod); - GetCompileInfo()->EncodeClass(m_pImage->GetModuleHandle(), hClassContext, &sigBuilder, this, EncodeModuleHelper); - } - - switch (pLookup->runtimeLookupFlags) - { - case READYTORUN_FIXUP_TypeHandle: - case READYTORUN_FIXUP_DeclaringTypeHandle: - { - if (pResolvedToken->pTypeSpec == NULL) - { - _ASSERTE(!"Invalid IL that directly references __Canon"); - ThrowHR(E_NOTIMPL); - } - - if (pLookup->runtimeLookupFlags == READYTORUN_FIXUP_DeclaringTypeHandle) - { - _ASSERTE(pLookup->runtimeLookupArgs != NULL); - sigBuilder.AppendData(ENCODE_DECLARINGTYPE_HANDLE); - GetCompileInfo()->EncodeClass(m_pImage->GetModuleHandle(), (CORINFO_CLASS_HANDLE)pLookup->runtimeLookupArgs, &sigBuilder, this, EncodeModuleHelper); - } - else - { - sigBuilder.AppendData(ENCODE_TYPE_HANDLE); - } - - if (pResolvedToken->tokenType == CORINFO_TOKENKIND_Newarr) - sigBuilder.AppendElementType(ELEMENT_TYPE_SZARRAY); - sigBuilder.AppendBlob((PVOID)pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec); - } - break; - - case READYTORUN_FIXUP_MethodHandle: - EncodeMethod(ENCODE_METHOD_HANDLE, pResolvedToken->hMethod, &sigBuilder, pResolvedToken, NULL, TRUE); - break; - - case READYTORUN_FIXUP_MethodEntry: - EncodeMethod(ENCODE_METHOD_ENTRY, pResolvedToken->hMethod, &sigBuilder, pResolvedToken, (CORINFO_RESOLVED_TOKEN*)pLookup->runtimeLookupArgs, TRUE); - break; - - case READYTORUN_FIXUP_VirtualEntry: - EncodeMethod(ENCODE_VIRTUAL_ENTRY, pResolvedToken->hMethod, &sigBuilder, pResolvedToken, NULL, TRUE); - break; - - case READYTORUN_FIXUP_FieldHandle: - EncodeField(ENCODE_FIELD_HANDLE, pResolvedToken->hField, &sigBuilder, pResolvedToken, TRUE); - break; - - default: - _ASSERTE(!"Invalid R2R fixup kind!"); - ThrowHR(E_NOTIMPL); - } - - return GetImportForSignature((void*)containingMethod, &sigBuilder); -} - -ZapImport * ZapImportTable::GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_CLASS_HANDLE handle) -{ - ZapImport * pImport = GetImport((void *)(uintptr_t)((kind << 1) | 1), handle); - - if (!pImport->HasBlob()) - { - SigBuilder sigBuilder; - - sigBuilder.AppendData(kind); - - GetCompileInfo()->EncodeClass(m_pImage->GetModuleHandle(), handle, &sigBuilder, this, EncodeModuleHelper); - pImport->SetBlob(GetBlob(&sigBuilder)); - } - - return pImport; -} - -ZapImport * ZapImportTable::GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, - CORINFO_CLASS_HANDLE delegateType /*=NULL*/) -{ - SigBuilder sigBuilder; - - EncodeMethod(kind, handle, &sigBuilder, pResolvedToken); - - if (delegateType != NULL) - { - _ASSERTE(kind == ENCODE_DELEGATE_CTOR); - GetCompileInfo()->EncodeClass(m_pImage->GetModuleHandle(), delegateType, &sigBuilder, this, EncodeModuleHelper); - } - - return GetImportForSignature((void *)(uintptr_t)((kind << 1) | 1), &sigBuilder); -} - -ZapImport * ZapImportTable::GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken) -{ - SigBuilder sigBuilder; - - EncodeField(kind, handle, &sigBuilder, pResolvedToken); - - return GetImportForSignature((void *)(uintptr_t)((kind << 1) | 1), &sigBuilder); -} - -class ZapIndirectHelperThunk : public ZapImport -{ - DWORD SaveWorker(ZapWriter * pZapWriter); - -public: - ReadyToRunHelper GetReadyToRunHelper() - { - return (ReadyToRunHelper)((DWORD)(SIZE_T)GetHandle() & ~READYTORUN_HELPER_FLAG_VSD); - } - - DWORD GetSectionIndex() - { - return (DWORD)(SIZE_T)GetHandle2(); - } - - BOOL IsDelayLoadHelper() - { - ReadyToRunHelper helper = GetReadyToRunHelper(); - return (helper == READYTORUN_HELPER_DelayLoad_MethodCall) || - (helper == READYTORUN_HELPER_DelayLoad_Helper) || - (helper == READYTORUN_HELPER_DelayLoad_Helper_Obj) || - (helper == READYTORUN_HELPER_DelayLoad_Helper_ObjObj); - } - - BOOL IsDelayLoadMethodCallHelper() - { - ReadyToRunHelper helper = GetReadyToRunHelper(); - return (helper == READYTORUN_HELPER_DelayLoad_MethodCall); - } - - BOOL IsVSD() - { - return ((DWORD)(SIZE_T)GetHandle() & READYTORUN_HELPER_FLAG_VSD) != 0; - } - - BOOL IsLazyHelper() - { - ReadyToRunHelper helper = GetReadyToRunHelper(); - return (helper == READYTORUN_HELPER_GetString); - } - - DWORD GetSize() - { - return SaveWorker(NULL); - } - - void Save(ZapWriter * pZapWriter) - { - SaveWorker(pZapWriter); - } - - virtual UINT GetAlignment() - { - return MINIMUM_CODE_ALIGN; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_IndirectHelperThunk; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - // Encode should be unreachable for ready-to-run cells - _ASSERTE(false); - } -}; - -#ifdef TARGET_ARM -static void MovRegImm(BYTE* p, int reg) -{ - *(WORD *)(p + 0) = 0xF240; - *(WORD *)(p + 2) = (UINT16)(reg << 8); - *(WORD *)(p + 4) = 0xF2C0; - *(WORD *)(p + 6) = (UINT16)(reg << 8); -} -#endif // TARGET_ARM - -DWORD ZapIndirectHelperThunk::SaveWorker(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - BYTE buffer[44]; - BYTE * p = buffer; - -#if defined(TARGET_X86) - if (IsDelayLoadHelper()) - { - // xor eax, eax - *p++ = 0x33; - *p++ = 0xC0; - - // push index - *p++ = 0x6A; - _ASSERTE(GetSectionIndex() <= 0x7F); - *p++ = (BYTE)GetSectionIndex(); - - // push [module] - *p++ = 0xFF; - *p++ = 0x35; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_PTR); - p += 4; - } - else - if (IsLazyHelper()) - { - // mov edx, [module] - *p++ = 0x8B; - *p++ = 0x15; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_PTR); - p += 4; - } - - // jmp [helper] - *p++ = 0xFF; - *p++ = 0x25; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(GetReadyToRunHelper()), 0, IMAGE_REL_BASED_PTR); - p += 4; -#elif defined(TARGET_AMD64) - if (IsDelayLoadHelper()) - { - if (IsVSD()) - { - // mov rax, r11 - *p++ = 0x49; - *p++ = 0x8b; - *p++ = 0xc3; - } - else - { - // xor eax, eax - *p++ = 0x33; - *p++ = 0xC0; - } - - // push index - *p++ = 0x6A; - _ASSERTE(GetSectionIndex() <= 0x7F); - *p++ = (BYTE)GetSectionIndex(); - - // push [module] - *p++ = 0xFF; - *p++ = 0x35; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_REL32); - p += 4; - } - else - if (IsLazyHelper()) - { - *p++ = 0x48; - *p++ = 0x8B; -#ifdef UNIX_AMD64_ABI - // mov rsi, [module] - *p++ = 0x35; -#else - // mov rdx, [module] - *p++ = 0x15; -#endif - if (pImage != NULL) - pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_REL32); - p += 4; - } - - // jmp [helper] - *p++ = 0xFF; - *p++ = 0x25; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(GetReadyToRunHelper()), 0, IMAGE_REL_BASED_REL32); - p += 4; -#elif defined(TARGET_ARM) - if (IsDelayLoadHelper()) - { - // r4 contains indirection cell - // push r4 - *(WORD *)(p + 0) = 0xB410; - p += 2; - - // mov r4, index - _ASSERTE(GetSectionIndex() <= 0x7F); - *(WORD *)(p + 0) = 0x2400 | (BYTE)GetSectionIndex(); - p += 2; - - // push r4 - *(WORD *)(p + 0) = 0xB410; - p += 2; - - // mov r4, [module] - MovRegImm(p, 4); - if (pImage != NULL) - pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_THUMB_MOV32); - p += 8; - - // ldr r4, [r4] - *(WORD *)p = 0x6824; - p += 2; - - // push r4 - *(WORD *)(p + 0) = 0xB410; - p += 2; - - // mov r4, [helper] - MovRegImm(p, 4); - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), pImage->GetImportTable()->GetHelperImport(GetReadyToRunHelper()), 0, IMAGE_REL_BASED_THUMB_MOV32); - p += 8; - - // ldr r4, [r4] - *(WORD *)p = 0x6824; - p += 2; - - // bx r4 - *(WORD *)p = 0x4720; - p += 2; - } - else - { - if (IsLazyHelper()) - { - // mov r1, [helper] - MovRegImm(p, 1); - if (pImage != NULL) - pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_THUMB_MOV32); - p += 8; - - // ldr r1, [r1] - *(WORD *)p = 0x6809; - p += 2; - } - - // mov r12, [helper] - MovRegImm(p, 12); - if (pImage != NULL) - pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(GetReadyToRunHelper()), 0, IMAGE_REL_BASED_THUMB_MOV32); - p += 8; - - // ldr r12, [r12] - *(DWORD *)p = 0xC000F8DC; - p += 4; - - // bx r12 - *(WORD *)p = 0x4760; - p += 2; - } -#elif defined(TARGET_ARM64) - if (IsDelayLoadHelper()) - { - // x11 contains indirection cell - // Do nothing x11 contains our first param - - // movz x9, #index - DWORD index = GetSectionIndex(); - _ASSERTE(index <= 0x7F); - *(DWORD*)p = 0xd2800009 | (index << 5); - p += 4; - - // move Module* -> x10 - // ldr x10, [PC+0x14] - *(DWORD*)p = 0x580000AA; - p += 4; - - //ldr x10, [x10] - *(DWORD*)p = 0xf940014A; - p += 4; - } - else - if (IsLazyHelper()) - { - // Move Module* -> x1 - // ldr x1, [PC+0x14] - *(DWORD*)p = 0x580000A1; - p += 4; - - // ldr x1, [x1] - *(DWORD*)p = 0xf9400021; - p += 4; - } - - // branch to helper - // ldr x12, [PC+0x14] - *(DWORD*)p = 0x580000AC; - p += 4; - - // ldr x12, [x12] - *(DWORD *)p = 0xf940018c; - p += 4; - - // br x12 - *(DWORD *)p = 0xd61f0180; - p += 4; - - // [Module*] - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_PTR); - p += 8; - - // [helper] - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), pImage->GetImportTable()->GetHelperImport(GetReadyToRunHelper()), 0, IMAGE_REL_BASED_PTR); - p += 8; -#else - PORTABILITY_ASSERT("ZapIndirectHelperThunk::SaveWorker"); -#endif - - _ASSERTE((DWORD)(p - buffer) <= sizeof(buffer)); - - if (pZapWriter != NULL) - pZapWriter->Write(&buffer, (int)(p - buffer)); - - return (DWORD)(p - buffer); -} - -void ZapImportTable::PlaceIndirectHelperThunk(ZapNode * pImport) -{ - ZapIndirectHelperThunk * pThunk = (ZapIndirectHelperThunk *)pImport; - - if (pThunk->IsDelayLoadMethodCallHelper()) - m_pImage->m_pLazyMethodCallHelperSection->Place(pThunk); - else - m_pImage->m_pLazyHelperSection->Place(pThunk); - - if (pThunk->IsDelayLoadHelper() || pThunk->IsLazyHelper()) - GetPlacedHelperImport(READYTORUN_HELPER_Module); - - GetPlacedHelperImport(pThunk->GetReadyToRunHelper()); -} - -ZapNode * ZapImportTable::GetIndirectHelperThunk(ReadyToRunHelper helperNum, PVOID pArg) -{ - ZapNode * pImport = GetImport((void *)helperNum, pArg); -#if defined(TARGET_ARM) - pImport = m_pImage->GetInnerPtr(pImport, THUMB_CODE); -#endif - return pImport; -} - -ZapNode * ZapImportTable::GetPlacedIndirectHelperThunk(ReadyToRunHelper helperNum, PVOID pArg) -{ - ZapNode * pImport = GetImport((void *)helperNum, pArg); - if (!pImport->IsPlaced()) - PlaceIndirectHelperThunk(pImport); -#if defined(TARGET_ARM) - pImport = m_pImage->GetInnerPtr(pImport, THUMB_CODE); -#endif - return pImport; -} - -class ZapHelperImport : public ZapImport -{ -public: - virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature) - { - *pfIsEager = TRUE; - *pfNeedsSignature = TRUE; - return ZapImportSectionType_Handle; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_Helper; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - // Encode should be unreachable for ready-to-run cells - _ASSERTE(false); - } -}; - -ZapImport * ZapImportTable::GetHelperImport(ReadyToRunHelper helperNum) -{ - ZapImport * pImport = GetImport((void *)helperNum); - - if (!pImport->HasBlob()) - { - SigBuilder sigBuilder; - - sigBuilder.AppendByte(ENCODE_READYTORUN_HELPER); - sigBuilder.AppendData(helperNum); - - pImport->SetBlob(GetBlob(&sigBuilder)); - } - - return pImport; -} - -ZapImport * ZapImportTable::GetPlacedHelperImport(ReadyToRunHelper helperNum) -{ - ZapImport * pImport = GetHelperImport(helperNum); - if (!pImport->IsPlaced()) - PlaceImport(pImport); - return pImport; -} - -#endif // FEATURE_READYTORUN_COMPILER diff --git a/src/coreclr/zap/zapimport.h b/src/coreclr/zap/zapimport.h deleted file mode 100644 index e1d33286a4d11e..00000000000000 --- a/src/coreclr/zap/zapimport.h +++ /dev/null @@ -1,553 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapImport.h -// - -// -// Import is soft bound references to elements outside the current module -// -// ====================================================================================== - -#ifndef __ZAPIMPORT_H__ -#define __ZAPIMPORT_H__ - -class ZapImportTable; -class ZapGCRefMapTable; -class NibbleWriter; - -//--------------------------------------------------------------------------------------- -// -// ZapImport is the import cell itself -// -// Every import cell is uniquely identified by its ZapNodeType and two handles -// (the second handle is optional and is often NULL) -// -// Actual implementations inherits from this abstract base class. -// -class ZapImport : public ZapNode -{ - COUNT_T m_index; - DWORD m_offset; - - PVOID m_handle; - PVOID m_handle2; - - ZapBlob * m_pBlob; - -public: - void SetHandle(PVOID handle) - { - _ASSERTE(m_handle == NULL); - m_handle = handle; - } - - void SetHandle2(PVOID handle2) - { - _ASSERTE(m_handle2 == NULL); - m_handle2 = handle2; - } - - PVOID GetHandle() - { - return m_handle; - } - - PVOID GetHandle2() - { - return m_handle2; - } - - void SetBlob(ZapBlob * pBlob) - { - _ASSERTE(m_pBlob == NULL); - m_pBlob = pBlob; - } - - ZapBlob * GetBlob() - { - _ASSERTE(m_pBlob != NULL); - return m_pBlob; - } - - BOOL HasBlob() - { - return m_pBlob != NULL; - } - - virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature) - { - *pfIsEager = FALSE; - *pfNeedsSignature = TRUE; - return ZapImportSectionType_Handle; - } - - // All subtypes have to override - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) = 0; - - virtual DWORD GetSize() - { - return TARGET_POINTER_SIZE; - } - - virtual UINT GetAlignment() - { - return TARGET_POINTER_SIZE; - } - - virtual void Save(ZapWriter * pZapWriter); - - // - // Offset of the fixup cell within its section - // - - void SetSectionIndexAndOffset(COUNT_T index, DWORD offset) - { - m_index = index; - m_offset = offset; - } - - DWORD GetSectionIndex() - { - return m_index; - } - - DWORD GetOffset() - { - return m_offset; - } -}; - -//--------------------------------------------------------------------------------------- -// -// ZapGenericSignature is signature of generic dictionary entry. -// -class ZapGenericSignature : public ZapBlob -{ -public: - ZapGenericSignature(SIZE_T cbSize) - : ZapBlob(cbSize) - { - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_GenericSignature; - } -}; - -//--------------------------------------------------------------------------------------- -// -// ZapImportTable is the main class that keeps track of all ZapImports. -// -// There is a single instance of it per image. -// -class ZapImportTable -{ - // - // Hashtable key of the import - // The same key is used for both ZapImport and ZapImportBlob - // - struct ImportKey - { - FORCEINLINE ImportKey(PVOID handle, ZapNodeType type) - : m_handle(handle), m_handle2(NULL), m_type(type) - { - } - - FORCEINLINE ImportKey(PVOID handle, PVOID handle2, ZapNodeType type) - : m_handle(handle), m_handle2(handle2), m_type(type) - { - } - - PVOID m_handle; - PVOID m_handle2; - ZapNodeType m_type; - }; - - // - // Hashtable of ZapImports - // - class ImportTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef ImportKey key_t; - - static FORCEINLINE key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return ImportKey(e->GetHandle(), e->GetHandle2(), e->GetType()); - } - static FORCEINLINE BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return (k1.m_handle == k2.m_handle) && (k1.m_handle2 == k2.m_handle2) && (k1.m_type == k2.m_type); - } - static FORCEINLINE count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(size_t)k.m_handle ^ ((count_t)(size_t)k.m_handle2 << 1) ^ k.m_type; - } - - static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } - }; - - typedef SHash< ImportTraits > ImportTable; - - // - // Hashtable of module indices - // - struct ModuleReferenceEntry - { - CORINFO_MODULE_HANDLE m_module; - DWORD m_index; - }; - - class ModuleReferenceTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef CORINFO_MODULE_HANDLE key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e->m_module; - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return (k1 == k2); - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(size_t)k; - } - - static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } - }; - - typedef SHash< ModuleReferenceTraits > ModuleReferenceTable; - - // - // Helpers for inserting actual implementations of ZapImports into hashtable - // - template < typename impl, ZapNodeType type > - ZapImport * GetImport(PVOID handle) - { - ZapImport * pImport = m_imports.Lookup(ImportKey(handle, type)); - - if (pImport != NULL) - { - return pImport; - } - - pImport = new (m_pImage->GetHeap()) impl(); - _ASSERTE(pImport->GetType() == type); - pImport->SetHandle(handle); - m_imports.Add(pImport); - return pImport; - } - - template < typename impl, ZapNodeType type > - ZapImport * GetImport(PVOID handle, PVOID handle2) - { - ZapImport * pImport = m_imports.Lookup(ImportKey(handle, handle2, type)); - - if (pImport != NULL) - { - return pImport; - } - - pImport = new (m_pImage->GetHeap()) impl(); - _ASSERTE(pImport->GetType() == type); - pImport->SetHandle(handle); - pImport->SetHandle2(handle2); - m_imports.Add(pImport); - return pImport; - } - - template < typename impl, ZapNodeType type > - ZapImport * GetImportForSignature(PVOID handle, SigBuilder * pSigBuilder) - { - ZapBlob * pBlob = GetBlob(pSigBuilder); - - ZapImport * pImport = m_imports.Lookup(ImportKey(handle, pBlob, type)); - - if (pImport != NULL) - { - return pImport; - } - - pImport = new (m_pImage->GetHeap()) impl(); - _ASSERTE(pImport->GetType() == type); - pImport->SetHandle(handle); - pImport->SetHandle2(pBlob); - pImport->SetBlob(pBlob); - m_imports.Add(pImport); - return pImport; - } - - ZapImport * GetExistingImport(ZapNodeType type, PVOID handle) - { - return m_imports.Lookup(ImportKey(handle, type)); - } - - ModuleReferenceEntry * GetModuleReference(CORINFO_MODULE_HANDLE handle); - - static DWORD EncodeModuleHelper(LPVOID referencingModule, CORINFO_MODULE_HANDLE referencedModule); - - ImportTable m_imports; // Interned ZapImport * - SHash< NoRemoveSHashTraits < ZapBlob::SHashTraits > > m_blobs; // Interned ZapBlos for signatures and fixups - - ModuleReferenceTable m_moduleReferences; - - SHash< NoRemoveSHashTraits < ZapBlob::SHashTraits > > m_genericSignatures; - - DWORD m_nImportSectionSizes[ZapImportSectionType_Total]; - COUNT_T m_nImportSectionIndices[ZapImportSectionType_Total]; - - ZapImage * m_pImage; - -public: - ZapImportTable(ZapImage * pImage) - : m_pImage(pImage) - { - // Everything else is zero initialized by the allocator - } - - void Preallocate(COUNT_T cbILImage) - { - PREALLOCATE_HASHTABLE(ZapImportTable::m_imports, 0.0030, cbILImage); - PREALLOCATE_HASHTABLE(ZapImportTable::m_blobs, 0.0025, cbILImage); - - PREALLOCATE_HASHTABLE_NOT_NEEDED(ZapImportTable::m_moduleReferences, cbILImage); - } - - // - // Helpers for encoding import blobs - // - - void EncodeModule(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_MODULE_HANDLE module, SigBuilder * pSigBuilder); - void EncodeClass(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_CLASS_HANDLE handle, SigBuilder * pSigBuilder); - void EncodeClassInContext(CORINFO_MODULE_HANDLE context, CORINFO_CLASS_HANDLE handle, SigBuilder * pSigBuilder); - void EncodeField(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, SigBuilder * pSigBuilder, - CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL, BOOL fEncodeUsingResolvedTokenSpecStreams = FALSE); - void EncodeMethod(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, SigBuilder * pSigBuilder, - CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken = NULL, - BOOL fEncodeUsingResolvedTokenSpecStreams = FALSE); - - // Encode module if the reference is within current version bubble. If not, return a suitable module within current version bubble. - CORINFO_MODULE_HANDLE TryEncodeModule(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_MODULE_HANDLE module, SigBuilder * pSigBuilder); - - ICorDynamicInfo * GetJitInfo() - { - return m_pImage->GetJitInfo(); - } - - ICorCompileInfo * GetCompileInfo() - { - return m_pImage->GetCompileInfo(); - } - - ZapImage * GetImage() - { - return m_pImage; - } - - // Returns index of module in the import table for encoding module fixups in EE datastructures. - DWORD GetIndexOfModule(CORINFO_MODULE_HANDLE handle) - { - ZapImportTable::ModuleReferenceEntry * pModuleReference = GetModuleReference(handle); - _ASSERTE(pModuleReference != NULL); - return pModuleReference->m_index; - } - - // Get the import blob for given signature - ZapBlob * GetBlob(SigBuilder * pSigBuilder, BOOL fEager = FALSE); - - // Place give import blob - void PlaceBlob(ZapBlob * pBlob, BOOL fEager = FALSE); - - // Encodes the import blob and places it into the image - ZapBlob * PlaceImportBlob(ZapImport * pImport, BOOL fEager = FALSE); - - // Places import cell into the image. - // This also encoded and places all the import blobs if they are not placed yet. - void PlaceImport(ZapImport * pImport); - - // Encodes list of fixups and places it into the image. - // This also places all the import cells if they are not placed yet. - ZapFixupInfo * PlaceFixups(ZapImport ** pImports); - void PlaceFixups(ZapImport ** pImports, NibbleWriter& writer); - - ZapGenericSignature * GetGenericSignature(PVOID signature, BOOL fMethod); - - // - // The actual implementations of import cells - // - ZapImport * GetFunctionEntryImport(CORINFO_METHOD_HANDLE handle); - ZapImport * GetModuleHandleImport(CORINFO_MODULE_HANDLE handle); - ZapImport * GetClassHandleImport(CORINFO_CLASS_HANDLE handle, PVOID pUniqueId = NULL); - ZapImport * GetMethodHandleImport(CORINFO_METHOD_HANDLE handle); - ZapImport * GetFieldHandleImport(CORINFO_FIELD_HANDLE handle); - ZapImport * GetStringHandleImport(CORINFO_MODULE_HANDLE tokenScope, mdString metaTok); - ZapImport * GetStaticFieldAddressImport(CORINFO_FIELD_HANDLE handle); - ZapImport * GetClassDomainIdImport(CORINFO_CLASS_HANDLE handle); - ZapImport * GetModuleDomainIdImport(CORINFO_MODULE_HANDLE handleToModule, CORINFO_CLASS_HANDLE handleToClass); - ZapImport * GetSyncLockImport(CORINFO_CLASS_HANDLE handle); - ZapImport * GetIndirectPInvokeTargetImport(CORINFO_METHOD_HANDLE handle); - ZapImport * GetPInvokeTargetImport(CORINFO_METHOD_HANDLE handle); - ZapImport * GetProfilingHandleImport(CORINFO_METHOD_HANDLE handle); - ZapImport * GetVarArgImport(CORINFO_MODULE_HANDLE handle, mdToken sigOrMemberRefOrDef); - ZapImport * GetActiveDependencyImport(CORINFO_MODULE_HANDLE moduleFrom, CORINFO_MODULE_HANDLE moduleTo); - - ZapImport * GetExistingClassHandleImport(CORINFO_CLASS_HANDLE handle); - ZapImport * GetExistingMethodHandleImport(CORINFO_METHOD_HANDLE handle); - ZapImport * GetExistingFieldHandleImport(CORINFO_FIELD_HANDLE handle); - - ZapImport * GetVirtualImportThunk(CORINFO_METHOD_HANDLE handle, int slot); - void PlaceVirtualImportThunk(ZapImport * pImportThunk); - - ZapImport * GetExternalMethodThunk(CORINFO_METHOD_HANDLE handle); - ZapImport * GetExternalMethodCell(CORINFO_METHOD_HANDLE handle); - ZapImport * GetStubDispatchCell(CORINFO_CLASS_HANDLE typeHnd, CORINFO_METHOD_HANDLE methHnd); - - // - // Ready-to-run imports - // - ZapImport * GetClassImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_RESOLVED_TOKEN * pResolvedToken); - ZapImport * GetMethodImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken = NULL); - ZapImport * GetFieldImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken); - - ZapImport * GetCheckTypeLayoutImport(CORINFO_CLASS_HANDLE handle); - ZapImport * GetCheckFieldOffsetImport(CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, DWORD offset); - - ZapImport * GetStubDispatchCell(CORINFO_RESOLVED_TOKEN * pResolvedToken); - ZapImport * GetExternalMethodCell(CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken); - - ZapImport * GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_CLASS_HANDLE handle); - ZapImport * GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_CLASS_HANDLE delegateType = NULL); - ZapImport * GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken); - - ZapImport * GetDictionaryLookupCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE containingMethod, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_LOOKUP_KIND * pLookup); - -#ifdef FEATURE_READYTORUN_COMPILER - ZapNode * GetPlacedIndirectHelperThunk(ReadyToRunHelper helperNum, PVOID pArg = NULL); - ZapNode * GetIndirectHelperThunk(ReadyToRunHelper helperNum, PVOID pArg = NULL); - void PlaceIndirectHelperThunk(ZapNode * pImport); - - ZapImport * GetPlacedHelperImport(ReadyToRunHelper helperNum); - ZapImport * GetHelperImport(ReadyToRunHelper helperNum); -#endif -}; - -// -// CORCOMPILE_CODE_IMPORT_SECTION -// -class ZapImportSectionsTable : public ZapNode -{ - struct ImportSection - { - ZapVirtualSection * m_pSection; - ZapNode * m_pSignatures; - ZapNode * m_pAuxiliaryData; - USHORT m_Flags; - BYTE m_Type; - BYTE m_EntrySize; - }; - - SArray m_ImportSectionsTable; - -public: - ZapImportSectionsTable(ZapImage * pImage) - { - } - - COUNT_T Append(BYTE Type, USHORT Flags, BYTE EntrySize, ZapVirtualSection * pSection, ZapNode * pSignatures = NULL, ZapNode * pAuxiliaryData = NULL); - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual DWORD GetSize(); - - virtual ZapNodeType GetType() - { - return ZapNodeType_ImportSectionsTable; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -// -// ZapImportSectionSignatures contains an array of signature RVAs for given import section. -// -class ZapImportSectionSignatures : public ZapNode -{ - ZapVirtualSection * m_pImportSection; - ZapGCRefMapTable * m_pGCRefMapTable; - - DWORD m_dwIndex; - - ZapImage * m_pImage; - -public: - ZapImportSectionSignatures(ZapImage * pImage, ZapVirtualSection * pImportSection, ZapVirtualSection * pGCSection = NULL); - ~ZapImportSectionSignatures(); - - void PlaceExternalMethodThunk(ZapImport * pImport); - void PlaceExternalMethodCell(ZapImport * pImport); - void PlaceStubDispatchCell(ZapImport * pImport); - void PlaceDynamicHelperCell(ZapImport * pImport); - - virtual DWORD GetSize(); - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_ImportSectionSignatures; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -#include "gcrefmap.h" - -class ZapGCRefMapTable : public ZapNode -{ - ZapImage * m_pImage; - GCRefMapBuilder m_GCRefMapBuilder; - COUNT_T m_nCount; - -public: - ZapGCRefMapTable(ZapImage * pImage) - : m_pImage(pImage) - { - } - - void Append(CORINFO_METHOD_HANDLE handle, bool isDispatchCell = false); - - virtual DWORD GetSize(); - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_GCRefMapTable; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -#endif // __ZAPIMPORT_H__ diff --git a/src/coreclr/zap/zapinfo.cpp b/src/coreclr/zap/zapinfo.cpp deleted file mode 100644 index b1066dcf807345..00000000000000 --- a/src/coreclr/zap/zapinfo.cpp +++ /dev/null @@ -1,4326 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapInfo.cpp -// - -// -// JIT-EE interface for zapping -// -// ====================================================================================== - -#include "common.h" - -#include "zapcode.h" -#include "zapimport.h" -#include "zapwrapper.h" -#include "zapinnerptr.h" -#include "zapmetadata.h" - -#ifdef FEATURE_READYTORUN_COMPILER -#include "zapreadytorun.h" -#endif - -ZapInfo::ZapInfo(ZapImage * pImage, mdMethodDef md, CORINFO_METHOD_HANDLE handle, CORINFO_MODULE_HANDLE module, unsigned methodProfilingDataFlags) - : m_pImage(pImage), - m_currentMethodToken(md), - m_currentMethodHandle(handle), - m_currentMethodModule(module), - m_currentMethodProfilingDataFlags(methodProfilingDataFlags), - - m_pNativeVarInfo(NULL), - m_iNativeVarInfo(0), - m_pOffsetMapping(NULL), - m_iOffsetMapping(0), - m_pGCInfo(NULL), - m_cbGCInfo(0), - m_pCode(NULL), - m_pColdCode(NULL), - m_pROData(NULL), -#ifdef FEATURE_EH_FUNCLETS - // Unwind info of the main method body. It will get merged with GC info. - m_pMainUnwindInfo(NULL), - m_cbMainUnwindInfo(0), - - m_pUnwindInfo(NULL), - m_pUnwindInfoFragments(NULL), -#if defined(TARGET_AMD64) - m_pChainedColdUnwindInfo(NULL), -#endif -#endif // FEATURE_EH_FUNCLETS - m_pExceptionInfo(NULL), - m_pProfileData(NULL), - m_pProfilingHandle(NULL), - - m_ClassLoadTable(pImage), - m_MethodLoadTable(pImage) -{ - m_zapper = m_pImage->m_zapper; - - m_pEEJitInfo = m_zapper->m_pEEJitInfo; - m_pEEJitInfo->setOverride(this, handle); - - m_pEECompileInfo = m_zapper->m_pEECompileInfo; -} - -ZapInfo::~ZapInfo() -{ - m_pEEJitInfo->setOverride(NULL, NULL); - - delete [] m_pNativeVarInfo; - delete [] m_pOffsetMapping; - - delete [] m_pGCInfo; -#ifdef FEATURE_EH_FUNCLETS - delete [] m_pMainUnwindInfo; -#endif - if (m_pgoResults != nullptr) - { - ProfileDataResults* current = m_pgoResults; - while (current != nullptr) - { - ProfileDataResults* next = current->m_next; - delete current; - current = next; - } - } -} - -#ifdef ALLOW_SXS_JIT_NGEN -// The AltJit failed and we're going to retry. Forget everything the JIT told us and prepare to JIT again. -void ZapInfo::ResetForJitRetry() -{ - delete [] m_pNativeVarInfo; - m_pNativeVarInfo = NULL; - - m_iNativeVarInfo = 0; - - delete [] m_pOffsetMapping; - m_pOffsetMapping = NULL; - - m_iOffsetMapping = 0; - - delete [] m_pGCInfo; - m_pGCInfo = NULL; - - m_cbGCInfo = 0; - -#ifdef FEATURE_EH_FUNCLETS - delete [] m_pMainUnwindInfo; - m_pMainUnwindInfo = NULL; - - m_cbMainUnwindInfo = 0; -#endif // FEATURE_EH_FUNCLETS - - // The rest of these pointers are in the ZapWriter's ZapHeap, and will go away when the ZapWriter - // goes away. That's ok for altjit fallback; we'll use extra memory until the ZapWriter goes away, - // but we won't write anything to the image. We just zero out the pointers and constants, and we're good. - - m_pCode = NULL; - m_pColdCode = NULL; - m_pROData = NULL; - -#ifdef FEATURE_EH_FUNCLETS - m_pUnwindInfoFragments = NULL; - m_pUnwindInfo = NULL; -#if defined(TARGET_AMD64) - m_pChainedColdUnwindInfo = NULL; -#endif -#endif // FEATURE_EH_FUNCLETS - - m_pExceptionInfo = NULL; - m_pProfileData = NULL; - m_pProfilingHandle = NULL; - - m_ImportSet.RemoveAll(); - m_Imports.Clear(); - m_CodeRelocations.Clear(); -} -#endif // ALLOW_SXS_JIT_NGEN - -void ZapInfo::InitMethodName() -{ - const char* szClsName; - const char* szMethodName = m_pEEJitInfo->getMethodName( - m_currentMethodHandle, - &szClsName); - - m_currentMethodName.SetUTF8(szClsName); - m_currentMethodName.AppendUTF8(NAMESPACE_SEPARATOR_STR); - m_currentMethodName.AppendUTF8(szMethodName); -} - -CORJIT_FLAGS ZapInfo::ComputeJitFlags(CORINFO_METHOD_HANDLE handle) -{ - CORJIT_FLAGS jitFlags = m_zapper->m_pOpt->m_compilerFlags; - - CORJIT_FLAGS flags; - IfFailThrow(m_pEECompileInfo->GetBaseJitFlags(handle, &flags)); - jitFlags.Add(flags); - - // COMPlus_JitFramed specifies the default fpo setting for jitted and NGened code. - // You can override the behavior for NGened code using COMPlus_NGenFramed. - static ConfigDWORD g_NGenFramed; - DWORD dwNGenFramed = g_NGenFramed.val(CLRConfig::UNSUPPORTED_NGenFramed); - if (dwNGenFramed == 0) - { - // NGened code should enable fpo - jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_FRAMED); - } - else if (dwNGenFramed == 1) - { - // NGened code should disable fpo - jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_FRAMED); - } - - jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION); - - if (m_pImage->m_profileDataSections[MethodBlockCounts].pData && - !m_zapper->m_pOpt->m_ignoreProfileData) - { - jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_BBOPT); - } - - // - // By default we always enable Hot/Cold procedure splitting - // - jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT); - - if (m_zapper->m_pOpt->m_noProcedureSplitting) - jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT); - - // If the method is specified for min-opts then turn everything off - if (jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_MIN_OPT)) - { - jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR); - jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_BBOPT); - jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT); - } - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_READYTORUN); - jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_PINVOKE_HELPERS); - } -#endif // FEATURE_READYTORUN_COMPILER - -#ifdef ARM_SOFTFP - jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_SOFTFP_ABI); -#endif - - return jitFlags; -} - -ZapDebugInfo * ZapInfo::EmitDebugInfo() -{ - if (m_iNativeVarInfo == 0 && m_iOffsetMapping == 0) - { - return NULL; - } - - // We create a temporary buffer which is conservatily estimated to be - // bigger than we need. We then copy the used portion into the ngen image. - - StackSBuffer debugInfoBuffer; - m_pEECompileInfo->CompressDebugInfo( - m_pOffsetMapping, m_iOffsetMapping, - m_pNativeVarInfo, m_iNativeVarInfo, - &debugInfoBuffer); - - if (IsReadyToRunCompilation()) - return ZapBlob::NewBlob(m_pImage, &debugInfoBuffer[0], debugInfoBuffer.GetSize()); - - return m_pImage->m_pDebugInfoTable->GetDebugInfo(&debugInfoBuffer[0], debugInfoBuffer.GetSize()); -} - -ZapGCInfo * ZapInfo::EmitGCInfo() -{ - _ASSERTE(m_pGCInfo != NULL); - -#ifdef FEATURE_EH_FUNCLETS - return m_pImage->m_pGCInfoTable->GetGCInfo(m_pGCInfo, m_cbGCInfo, m_pMainUnwindInfo, m_cbMainUnwindInfo); -#else - return m_pImage->m_pGCInfoTable->GetGCInfo(m_pGCInfo, m_cbGCInfo); -#endif // FEATURE_EH_FUNCLETS -} - -ZapImport ** ZapInfo::EmitFixupList() -{ - ZapImport ** pFixupList = NULL; - - if (m_Imports.GetCount() != 0) - { - pFixupList = new (m_pImage->GetHeap()) ZapImport * [m_Imports.GetCount() + 1]; - memcpy(pFixupList, &(m_Imports[0]), m_Imports.GetCount() * sizeof(ZapImport *)); - } - - return pFixupList; -} - -// Used by qsort -int __cdecl ZapInfo::CompareCodeRelocation(const void * a_, const void * b_) -{ - ZapInfo::CodeRelocation * a = (ZapInfo::CodeRelocation *)a_; - ZapInfo::CodeRelocation * b = (ZapInfo::CodeRelocation *)b_; - - if (a->m_pNode != b->m_pNode) - { - return (a->m_pNode > b->m_pNode) ? 1 : -1; - } - - return a->m_offset - b->m_offset; -} - -void ZapInfo::EmitCodeRelocations() -{ - if (m_CodeRelocations.IsEmpty()) - return; - - qsort(&m_CodeRelocations[0], m_CodeRelocations.GetCount(), sizeof(CodeRelocation), CompareCodeRelocation); - - COUNT_T startIndex = 0; - while (startIndex < m_CodeRelocations.GetCount()) - { - ZapBlobWithRelocs * pNode = m_CodeRelocations[startIndex].m_pNode; - - COUNT_T endIndex = startIndex + 1; - for ( ; endIndex < m_CodeRelocations.GetCount(); endIndex++) - { - if (m_CodeRelocations[endIndex].m_pNode != pNode) - break; - } - - ZapReloc * pRelocs = (ZapReloc *) - new (m_pImage->GetHeap()) BYTE[sizeof(ZapReloc) * (endIndex - startIndex) + sizeof(ZapRelocationType)]; - - for (COUNT_T i = 0; i < endIndex - startIndex; i++) - pRelocs[i] = m_CodeRelocations[startIndex + i]; - - // Set sentinel - static_assert_no_msg(offsetof(ZapReloc, m_type) == 0); - *(ZapRelocationType *)(pRelocs + (endIndex - startIndex)) = IMAGE_REL_INVALID; - - pNode->SetRelocs(pRelocs); - - startIndex = endIndex; - } -} - -void ZapInfo::ProcessReferences() -{ - COUNT_T count = m_CodeRelocations.GetCount(); - for (COUNT_T i = 0; i < count; i++) - { - CORINFO_METHOD_HANDLE hMethod = NULL; - CORINFO_CLASS_HANDLE hClass = NULL; - bool fMaybeConditionalImport = false; - - ZapNode * pTarget = m_CodeRelocations[i].m_pTargetNode; - - ZapNodeType type = pTarget->GetType(); - if (type == ZapNodeType_InnerPtr) - { - pTarget = ((ZapInnerPtr *)pTarget)->GetBase(); - type = pTarget->GetType(); - } - - switch (type) - { - case ZapNodeType_MethodEntryPoint: - hMethod = ((ZapMethodEntryPoint*)pTarget)->GetHandle(); - - if (m_pImage->m_pPreloader->DoesMethodNeedRestoringBeforePrestubIsRun(hMethod)) - { - methodMustBeLoadedBeforeCodeIsRun(hMethod); - } - break; - - case ZapNodeType_Import_MethodHandle: - case ZapNodeType_Import_FunctionEntry: - case ZapNodeType_Import_IndirectPInvokeTarget: - case ZapNodeType_Import_PInvokeTarget: - hMethod = (CORINFO_METHOD_HANDLE)(((ZapImport *)pTarget)->GetHandle()); - fMaybeConditionalImport = true; - break; - case ZapNodeType_Import_ClassHandle: - case ZapNodeType_Import_ClassDomainId: - case ZapNodeType_Import_SyncLock: - hClass = (CORINFO_CLASS_HANDLE)((ZapImport *)pTarget)->GetHandle(); - fMaybeConditionalImport = true; - break; - case ZapNodeType_Import_FieldHandle: - case ZapNodeType_Import_StaticFieldAddress: - hClass = m_pEEJitInfo->getFieldClass((CORINFO_FIELD_HANDLE)(((ZapImport *)pTarget)->GetHandle())); - fMaybeConditionalImport = true; - break; - case ZapNodeType_Import_StringHandle: - case ZapNodeType_Import_ModuleHandle: - case ZapNodeType_Import_ModuleDomainId: - case ZapNodeType_Import_VarArg: - fMaybeConditionalImport = true; - break; - - case ZapNodeType_MethodHandle: - hMethod = (CORINFO_METHOD_HANDLE)(((ZapWrapper *)pTarget)->GetHandle()); - break; - - case ZapNodeType_ExternalMethodThunk: - case ZapNodeType_ExternalMethodCell: - hMethod = (CORINFO_METHOD_HANDLE)((ZapImport*)pTarget)->GetHandle(); - break; - - default: - break; - } - - if (fMaybeConditionalImport) - { - const ImportEntry * pExistingEntry = m_ImportSet.LookupPtr((ZapImport *)pTarget); - if (pExistingEntry != NULL && pExistingEntry->fConditional) - { - const_cast(pExistingEntry)->fConditional = false; - m_Imports.Append((ZapImport *)pTarget); - - // 'handle' does not have to be added to CORCOMPILE_LOAD_TABLE since we adding - // it to CORCOMPILE_HANDLE_TABLE - if (hMethod != NULL) - m_MethodLoadTable.Load(hMethod, TRUE); - else - if (hClass != NULL) - m_ClassLoadTable.Load(hClass, TRUE); - } - } - - if (hMethod != NULL) - { - m_pImage->m_pPreloader->MethodReferencedByCompiledCode(hMethod); - } - } -} - -// Compile a method using the JIT or Module compiler, and emit fixups - -void ZapInfo::CompileMethod() -{ - PRECONDITION(m_zapper->m_pJitCompiler != NULL); - - InitMethodName(); - - if (m_zapper->m_pOpt->m_verbose) - { - // The evaluation of m_currentMethodName.GetUnicode() is expensive - // only do it when we are truely logging - m_zapper->Info(W("Compiling method %s\n"), m_currentMethodName.GetUnicode()); - } - - if (GetCompileInfo()->IsUnmanagedCallersOnlyMethod(m_currentMethodHandle)) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Methods with UnmanagedCallersOnlyAttribute not implemented\n")); - ThrowHR(E_NOTIMPL); - } - - if (GetCompileInfo()->IsUnmanagedCallConvMethod(m_currentMethodHandle)) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Methods with UnmanagedCallConvAttribute not implemented\n")); - ThrowHR(E_NOTIMPL); - } - - m_currentMethodInfo = CORINFO_METHOD_INFO(); - if (!getMethodInfo(m_currentMethodHandle, &m_currentMethodInfo)) - { - return; - } - - // Method does not have IL (e.g. an abstract method) - if (m_currentMethodInfo.ILCodeSize == 0) - return; - - // If we are doing partial ngen, only compile methods with profile data - if (!CurrentMethodHasProfileData() && m_zapper->m_pOpt->m_fPartialNGen) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Info(W("Skipped because of no profile data\n")); - return; - } - - // During ngen we look for a hint attribute on the method that indicates - // the method should be preprocessed for early - // preparation. This normally happens automatically, but for methods that - // are prepared explicitly at runtime the needed - // information is missing from the ngen image, causing costly overheads - // at runtime. When the author of the method knows about - // this they can add the hint and reduce the perf cost at runtime. - m_pImage->m_pPreloader->PrePrepareMethodIfNecessary(m_currentMethodHandle); - - // Retrieve method attributes from EEJitInfo - the ZapInfo's version updates - // some of the flags related to hardware intrinsics but we don't want that. - DWORD methodAttribs = m_pEEJitInfo->getMethodAttribs(m_currentMethodHandle); - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation() && (methodAttribs & CORINFO_FLG_AGGRESSIVE_OPT)) - { - // Skip methods marked with MethodImplOptions.AggressiveOptimization, they will be jitted instead. In the future, - // consider letting the JIT determine whether aggressively optimized code can/should be pregenerated for the method - // instead of this check. - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Info(W("Skipped because of aggressive optimization flag\n")); - return; - } -#endif - -#if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM64) - if (methodAttribs & CORINFO_FLG_JIT_INTRINSIC) - { - // Skip generating hardware intrinsic method bodies. - // - // We don't know what the implementation should do (whether it can do the actual intrinsic thing, or whether - // it should throw a PlatformNotSupportedException). - - const char* namespaceName; - getMethodNameFromMetadata(m_currentMethodHandle, nullptr, &namespaceName, nullptr); - if (strcmp(namespaceName, "System.Runtime.Intrinsics.X86") == 0 - || strcmp(namespaceName, "System.Runtime.Intrinsics.Arm") == 0 - || strcmp(namespaceName, "System.Runtime.Intrinsics") == 0) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Info(W("Skipped due to being a hardware intrinsic\n")); - return; - } - } -#endif - - m_jitFlags = ComputeJitFlags(m_currentMethodHandle); - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - // READYTORUN: FUTURE: Producedure spliting - m_jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT); - } -#endif - - if (m_pImage->m_stats) - { - m_pImage->m_stats->m_methods++; - m_pImage->m_stats->m_ilCodeSize += m_currentMethodInfo.ILCodeSize; - } - - CorJitResult res = CORJIT_SKIPPED; // FAILED() returns true for this value - - uint8_t *pCode; - uint32_t cCode; - bool doNormalCompile = true; - -#ifdef ALLOW_SXS_JIT_NGEN - - // Only retry the JIT compilation when we have a different JIT to run - // Often we see both COMPlus_AltJIT and COMPlus_AltJitNgen set - // which results in both JIT compilers set to the same altjit - // - doNormalCompile = (m_zapper->m_alternateJit != m_zapper->m_pJitCompiler); - - // Compile this method using the AltJitNgen compiler - // - if (m_zapper->m_alternateJit) - { - m_jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_ALT_JIT); - res = m_zapper->m_alternateJit->compileMethod( this, - &m_currentMethodInfo, - CORJIT_FLAGS::CORJIT_FLAG_CALL_GETJITFLAGS, - &pCode, - &cCode); - - // The above compileMethod call will typically return CORJIT_SKIPPED - if (doNormalCompile && FAILED(res)) - { - // We will fall back to the "main" JIT on failure. - ResetForJitRetry(); - } - } - m_jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_ALT_JIT); - -#endif // ALLOW_SXS_JIT_NGEN - - // Compile this method using the normal JIT compiler - // - if (doNormalCompile && FAILED(res)) - { - ICorJitCompiler * pCompiler = m_zapper->m_pJitCompiler; - res = pCompiler->compileMethod(this, - &m_currentMethodInfo, - CORJIT_FLAGS::CORJIT_FLAG_CALL_GETJITFLAGS, - &pCode, - &cCode); - if (FAILED(res)) - { - ThrowExceptionForJitResult(res); - } - } - - MethodCompileComplete(m_currentMethodInfo.ftn); - -#ifdef TARGET_X86 - // The x86 JIT over estimates the code size. Trim the blob size down to - // the actual size. - // We can do this only for non-split code. Adjusting the code size for split - // methods would hose offsets in GC info. - if (m_pColdCode == NULL) - { - m_pCode->AdjustBlobSize(cCode); - } -#endif - - PublishCompiledMethod(); -} - -#ifndef FEATURE_FULL_NGEN -class MethodCodeComparer -{ - static BOOL NodeEquals(ZapNode * k1, ZapNode * k2) - { - return k1 == k2; - } - - static BOOL BlobEquals(ZapBlob * k1, ZapBlob * k2) - { - if (k1 == NULL && k2 == NULL) - return TRUE; - if (k1 == NULL || k2 == NULL) - return FALSE; - - if (k1->GetBlobSize() != k2->GetBlobSize()) - return FALSE; - if (memcmp(k1->GetData(), k2->GetData(), k1->GetBlobSize()) != 0) - return FALSE; - - return TRUE; - } - - typedef ZapNode * EquivalentNodes[4][2]; - - static BOOL EquivalentNode(ZapNode * k1, ZapNode * k2, EquivalentNodes & equivalentNodes) - { - if (k1 == k2) - return TRUE; - - for (unsigned int i = 0; i < _countof(equivalentNodes); i++) - { - if (k1 == equivalentNodes[i][0] && k2 == equivalentNodes[i][1]) - return TRUE; - } - - return FALSE; - } - - static BOOL BlobWithRelocsEquals(ZapBlobWithRelocs * k1, ZapBlobWithRelocs * k2, EquivalentNodes & equivalentNodes) - { - if (k1 == NULL && k2 == NULL) - return TRUE; - if (k1 == NULL || k2 == NULL) - return FALSE; - - if (k1->GetBlobSize() != k2->GetBlobSize()) - return FALSE; - if (memcmp(k1->GetData(), k2->GetData(), k1->GetBlobSize()) != 0) - return FALSE; - - ZapReloc * pRelocs1 = k1->GetRelocs(); - ZapReloc * pRelocs2 = k2->GetRelocs(); - - if (pRelocs1 == NULL && pRelocs2 == NULL) - return TRUE; - if (pRelocs1 == NULL || pRelocs2 == NULL) - return FALSE; - - while (pRelocs1->m_type != IMAGE_REL_INVALID || pRelocs2->m_type != IMAGE_REL_INVALID) - { - if (pRelocs1->m_type != pRelocs2->m_type || pRelocs1->m_offset != pRelocs2->m_offset) - return FALSE; - - if (!EquivalentNode(pRelocs1->m_pTargetNode, pRelocs2->m_pTargetNode, equivalentNodes)) - return FALSE; - - pRelocs1++; pRelocs2++; - } - - return TRUE; - } - - static BOOL UnwindInfoEquals(ZapUnwindInfo * k1, ZapUnwindInfo * k2, EquivalentNodes & equivalentNodes) - { - if (k1 == NULL && k2 == NULL) - return TRUE; - if (k1 == NULL || k2 == NULL) - return FALSE; - - return (k1->GetStartOffset() == k2->GetStartOffset()) && - (k1->GetEndOffset() == k2->GetEndOffset()) && - (k1->GetUnwindData() == k2->GetUnwindData()) && - EquivalentNode(k1->GetCode(), k2->GetCode(), equivalentNodes); - } - - static BOOL UnwindInfoFragmentsEquals(ZapUnwindInfo * k1, ZapUnwindInfo * k2, EquivalentNodes & equivalentNodes) - { - if (k1 == NULL && k2 == NULL) - return TRUE; - if (k1 == NULL || k2 == NULL) - return FALSE; - - while (k1 != NULL || k2 != NULL) - { - if (!UnwindInfoEquals(k1, k2, equivalentNodes)) - return FALSE; - - k1 = k1->GetNextFragment(); k2 = k2->GetNextFragment(); - } - - return TRUE; - } - - static BOOL FixupListEquals(ZapImport ** k1, ZapImport ** k2) - { - if (k1 == NULL && k2 == NULL) - return TRUE; - if (k1 == NULL || k2 == NULL) - return FALSE; - - while (*k1 != NULL || *k2 != NULL) - { - if (*k1 != *k2) - return FALSE; - k1++; k2++; - } - - return TRUE; - } - -public: - static BOOL MethodCodeEquals(ZapMethodHeader * k1, ZapMethodHeader * k2) - { - LIMITED_METHOD_CONTRACT; - - EquivalentNodes equivalentNodes = - { - { k1->m_pCode, k2->m_pCode }, - { k1->m_pColdCode, k2->m_pColdCode }, - { k1->m_pROData, k2->m_pROData }, - { k1->m_pProfileData, k2->m_pProfileData } - }; - - if (!BlobWithRelocsEquals(k1->m_pCode, k2->m_pCode, equivalentNodes)) - return FALSE; - - if (!BlobWithRelocsEquals(k1->m_pColdCode, k2->m_pColdCode, equivalentNodes)) - return FALSE; - - if (!UnwindInfoEquals(k1->m_pUnwindInfo, k2->m_pUnwindInfo, equivalentNodes)) - return FALSE; - - if (!UnwindInfoEquals(k1->m_pColdUnwindInfo, k2->m_pColdUnwindInfo, equivalentNodes)) - return FALSE; - -#ifdef FEATURE_EH_FUNCLETS - if (!UnwindInfoFragmentsEquals(k1->m_pUnwindInfoFragments, k2->m_pUnwindInfoFragments, equivalentNodes)) - return FALSE; -#endif - - if (!BlobWithRelocsEquals(k1->m_pROData, k2->m_pROData, equivalentNodes)) - return FALSE; - - if (!BlobWithRelocsEquals(k1->m_pProfileData, k2->m_pProfileData, equivalentNodes)) - return FALSE; - - if (!NodeEquals(k1->m_pGCInfo, k2->m_pGCInfo)) // interned - return FALSE; - - if (!NodeEquals(k1->m_pDebugInfo, k2->m_pDebugInfo)) // interned - return FALSE; - - if (!FixupListEquals(k1->m_pFixupList, k2->m_pFixupList)) - return FALSE; - - if (!BlobEquals(k1->m_pExceptionInfo, k2->m_pExceptionInfo)) - return FALSE; - - return TRUE; - } -}; - -extern BOOL CanDeduplicateCode(CORINFO_METHOD_HANDLE method, CORINFO_METHOD_HANDLE duplicateMethod); - -BOOL ZapImage::MethodCodeTraits::Equals(key_t k1, key_t k2) -{ - if (!MethodCodeComparer::MethodCodeEquals(k1, k2)) - return FALSE; - - // Check additional VM conditions that has to be satisfied for deduplication - if (!CanDeduplicateCode(k1->GetHandle(), k2->GetHandle())) - return FALSE; - - return TRUE; -} - -COUNT_T ZapImage::MethodCodeTraits::Hash(key_t k) -{ - COUNT_T hash = ZapBlob::SHashTraits::Hash(ZapBlob::SHashTraits::GetKey(k->m_pCode)); - - ZapReloc * pRelocs = k->m_pCode->GetRelocs(); - if (pRelocs != NULL) - { - while (pRelocs->m_type != IMAGE_REL_INVALID) - { - ZapNode * pTarget = pRelocs->m_pTargetNode; - ZapNodeType type = pTarget->GetType(); - - if (type == ZapNodeType_InnerPtr) - { - pTarget = ((ZapInnerPtr *)pTarget)->GetBase(); - type = pTarget->GetType(); - } - - // The IL stubs code often differs by just a method call or class handle. Include - // these in the hash code. - switch (type) - { - case ZapNodeType_MethodEntryPoint: - case ZapNodeType_ExternalMethodThunk: - case ZapNodeType_ClassHandle: - case ZapNodeType_Import_ClassHandle: - case ZapNodeType_MethodHandle: - case ZapNodeType_Import_MethodHandle: - hash = ((hash << 5) + hash) ^ (COUNT_T)((SIZE_T)pTarget); - break; - default: - break; - } - - pRelocs++; - } - } - - return hash; -} -#endif - -void ZapInfo::PublishCompiledMethod() -{ - EmitCodeRelocations(); - - // Go through all references in the code, make sure that we have fixups for them, - // and ensure that they will be otherwise present in the image if necessary - ProcessReferences(); - - // See if there are load fixups to emit. - m_ClassLoadTable.EmitLoadFixups(m_currentMethodHandle, this); - - if (!IsReadyToRunCompilation()) - m_MethodLoadTable.EmitLoadFixups(m_currentMethodHandle, this); - - ZapMethodHeader * pMethod = new (m_pImage->GetHeap()) ZapMethodHeader(); - - pMethod->m_handle = m_currentMethodHandle; - pMethod->m_classHandle = getMethodClass(m_currentMethodHandle); - - pMethod->m_pCode = m_pCode; - pMethod->m_pColdCode = m_pColdCode; - pMethod->m_pROData = m_pROData; - - pMethod->m_pProfileData = m_pProfileData; - - pMethod->m_pExceptionInfo = m_pExceptionInfo; - - pMethod->m_pFixupList = EmitFixupList(); - - pMethod->m_pDebugInfo = EmitDebugInfo(); - pMethod->m_pGCInfo = EmitGCInfo(); - -#ifdef FEATURE_EH_FUNCLETS - pMethod->m_pUnwindInfoFragments = m_pUnwindInfoFragments; - - // Set the combined GCInfo + UnwindInfo blob - m_pUnwindInfo->SetUnwindData(pMethod->m_pGCInfo); - -#if defined(TARGET_AMD64) - if (m_pChainedColdUnwindInfo != NULL) - { - // Chain the cold unwind info with the hot unwind info - m_pChainedColdUnwindInfo->SetUnwindData(m_pUnwindInfo); - } -#endif // TARGET_AMD64 - -#endif // FEATURE_EH_FUNCLETS - -#ifndef FEATURE_FULL_NGEN - // - // Method code deduplication - // - // For now, the only methods eligible for de-duplication are IL stubs - // - if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) - { - ZapMethodHeader * pDuplicateMethod = m_pImage->m_CodeDeduplicator.Lookup(pMethod); - if (pDuplicateMethod != NULL) - { - m_pImage->m_pPreloader->NoteDeduplicatedCode(pMethod->m_handle, pDuplicateMethod->m_handle); - return; - } - - m_pImage->m_CodeDeduplicator.Add(pMethod); - } -#endif - - // Remember the gc info for IL stubs associated with hot methods so they can be packed well. - // Stubs that have no metadata token cannot be tracked by IBC data. - if (m_currentMethodProfilingDataFlags & (1 << ReadMethodCode)) - { - if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) - m_pImage->m_PrioritizedGCInfo.Append(pMethod->m_pGCInfo); - } - - pMethod->m_ProfilingDataFlags = m_currentMethodProfilingDataFlags; - - COUNT_T methodCompilationOrder = m_pImage->m_MethodCompilationOrder.GetCount(); - pMethod->m_compilationOrder = methodCompilationOrder; - - // We need to remember the first index into m_MethodCompilationOrder where we saw a method from this class - m_pImage->InitializeClassLayoutOrder(pMethod->m_classHandle, methodCompilationOrder); - - m_pImage->m_CompiledMethods.Add(pMethod); - m_pImage->m_MethodCompilationOrder.Append(pMethod); -} - -void ZapInfo::getGSCookie(GSCookie * pCookieVal, GSCookie ** ppCookieVal) -{ - *pCookieVal = 0; - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - *ppCookieVal = (GSCookie *)m_pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_GSCookie); - return; - } -#endif - - *ppCookieVal = (GSCookie *)m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable, - offsetof(CORCOMPILE_EE_INFO_TABLE, gsCookie)); -} - -uint32_t ZapInfo::getJitFlags(CORJIT_FLAGS* jitFlags, uint32_t sizeInBytes) -{ - _ASSERTE(jitFlags != NULL); - _ASSERTE(sizeInBytes >= sizeof(m_jitFlags)); - - *jitFlags = m_jitFlags; - return sizeof(m_jitFlags); -} - -bool ZapInfo::runWithErrorTrap(void (*function)(void*), void* param) -{ - return m_pEEJitInfo->runWithErrorTrap(function, param); -} - -HRESULT ZapInfo::allocPgoInstrumentationBySchema(CORINFO_METHOD_HANDLE ftnHnd, - PgoInstrumentationSchema* pSchema, - uint32_t countSchemaItems, - uint8_t** pInstrumentationData) -{ - HRESULT hr; - - *pInstrumentationData = nullptr; - if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) - { - return E_NOTIMPL; - } - - // Only allocation of PGO data for the current method is supported. - if (m_currentMethodHandle != ftnHnd) - { - return E_NOTIMPL; - } - - // @TODO: support generic methods from other assemblies - if (m_currentMethodModule != m_pImage->m_hModule) - { - return E_NOTIMPL; - } - - - mdMethodDef md = m_currentMethodToken; - - if (IsNilToken(md)) - { - // This must be the non-System.Object instantiation of a generic type/method. - IfFailRet(m_zapper->m_pEECompileInfo->GetMethodDef(m_currentMethodHandle, &md)); - } -#ifdef _DEBUG - else - { - mdMethodDef mdTemp; - IfFailRet(m_zapper->m_pEECompileInfo->GetMethodDef(m_currentMethodHandle, &mdTemp)); - _ASSERTE(md == mdTemp); - } -#endif - if (IsNilToken(md)) - { - return E_FAIL; - } - - // Validate that each schema item is only used for a basic block count - for (UINT32 iSchema = 0; iSchema < countSchemaItems; iSchema++) - { - if (pSchema[iSchema].InstrumentationKind != PgoInstrumentationKind::BasicBlockIntCount) - return E_NOTIMPL; - if (pSchema[iSchema].Count != 1) - return E_NOTIMPL; - } - - // If the JIT retries the compilation (especially during JIT stress), it can - // try to allocate the profiling data multiple times. We will just keep track - // of the latest copy in this case. - // _ASSERTE(m_pProfileData == NULL); - - DWORD totalSize = (DWORD) (countSchemaItems * sizeof(ICorJitInfo::BlockCounts)) + sizeof(CORBBTPROF_METHOD_HEADER); - m_pProfileData = ZapBlobWithRelocs::NewAlignedBlob(m_pImage, NULL, totalSize, sizeof(DWORD)); - CORBBTPROF_METHOD_HEADER * profileData = (CORBBTPROF_METHOD_HEADER *) m_pProfileData->GetData(); - profileData->size = totalSize; - profileData->cDetail = 0; - profileData->method.token = md; - profileData->method.ILSize = m_currentMethodInfo.ILCodeSize; - profileData->method.cBlock = countSchemaItems; - - ICorJitInfo::BlockCounts* blockCounts = (ICorJitInfo::BlockCounts *)(&profileData->method.block[0]); - *pInstrumentationData = (BYTE*)blockCounts; - - for (UINT32 iSchema = 0; iSchema < countSchemaItems; iSchema++) - { - // Update schema have correct offsets - pSchema[iSchema].Offset = (BYTE*)&blockCounts[iSchema].ExecutionCount - (BYTE*)blockCounts; - // Insert IL Offsets into block data to match schema - blockCounts[iSchema].ILOffset = pSchema[iSchema].ILOffset; - } - - return S_OK; -} - -HRESULT ZapInfo::getPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, - PgoInstrumentationSchema **pSchema, // pointer to the schema table which describes the instrumentation results (pointer will not remain valid after jit completes) - uint32_t * pCountSchemaItems, // pointer to the count schema items - uint8_t ** pInstrumentationData, // pointer to the actual instrumentation data (pointer will not remain valid after jit completes) - PgoSource* pPgoSource) -{ - _ASSERTE(pCountSchemaItems != nullptr); - _ASSERTE(pInstrumentationData != nullptr); - _ASSERTE(pSchema != nullptr); - - HRESULT hr; - - // Initialize outputs in case we return E_FAIL - *pCountSchemaItems = 0; - *pSchema = nullptr; - *pInstrumentationData = nullptr; - *pPgoSource = PgoSource::Unknown; - - int32_t numRuns = 0; - - // For generic instantiations whose IL is in another module, - // the profile data is in that module - // @TODO: Fetch the profile data from the other module. - if ((m_currentMethodModule != m_pImage->m_hModule) || - m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) - { - return E_FAIL; - } - - ZapImage::ProfileDataSection * DataSection_MethodBlockCounts = & m_pImage->m_profileDataSections[MethodBlockCounts]; - - if (!DataSection_MethodBlockCounts->pData) - { - return E_FAIL; - } - - mdMethodDef md; - IfFailRet(m_zapper->m_pEECompileInfo->GetMethodDef(ftnHnd, &md)); - - if (IsNilToken(md)) - { - return E_FAIL; - } - - ProfileDataResults* pgoResults = m_pgoResults; - while (pgoResults != nullptr) - { - if (pgoResults->m_ftn == ftnHnd) - break; - pgoResults = pgoResults->m_next; - } - - if (pgoResults == nullptr) - { - const ZapImage::ProfileDataHashEntry * foundEntry = m_pImage->profileDataHashTable.LookupPtr(md); - - if (foundEntry == NULL) - { - return E_FAIL; - } - - // The md must match. - _ASSERTE(foundEntry->md == md); - - if (foundEntry->pos == 0) - { - // We might not have profile data and instead only have CompileStatus and flags - assert(foundEntry->size == 0); - return E_FAIL; - } - - // - // - // We found the md. Let's retrieve the profile data. - // - _ASSERTE(foundEntry->size >= sizeof(CORBBTPROF_METHOD_HEADER)); // The size must at least this - - ProfileReader profileReader(DataSection_MethodBlockCounts->pData, DataSection_MethodBlockCounts->dataSize); - - // Locate the method in interest. - SEEK(foundEntry->pos); - CORBBTPROF_METHOD_HEADER * profileData; - READ_SIZE(profileData, CORBBTPROF_METHOD_HEADER, foundEntry->size); - _ASSERTE(profileData->method.token == foundEntry->md); // We should be looking at the right method - _ASSERTE(profileData->size == foundEntry->size); // and the cached size must match - - // Find method's IL size - // - unsigned ilSize = m_currentMethodInfo.ILCodeSize; - - if (ftnHnd != m_currentMethodHandle) - { - CORINFO_METHOD_INFO methodInfo; - if (!getMethodInfo(ftnHnd, &methodInfo)) - { - return E_FAIL; - } - ilSize = methodInfo.ILCodeSize; - } - - // If the ILSize is non-zero the the ILCodeSize also must match - // - if ((profileData->method.ILSize != 0) && (profileData->method.ILSize != ilSize)) - { - // IL code for this method does not match the IL code for the method when it was profiled - // in such cases we tell the JIT to discard the profile data by returning E_FAIL - // - return E_FAIL; - } - - pgoResults = new ProfileDataResults(ftnHnd); - pgoResults->m_next = m_pgoResults; - m_pgoResults = pgoResults; - - pgoResults->pInstrumentationData = (BYTE*)&profileData->method.block[0]; - - ICorJitInfo::BlockCounts *blockCounts = (ICorJitInfo::BlockCounts *) &profileData->method.block[0]; - - PgoInstrumentationSchema numRunsSchema = {}; - numRunsSchema.Count = 1; - numRunsSchema.Other = m_pImage->m_profileDataNumRuns; - numRunsSchema.InstrumentationKind = ICorJitInfo::PgoInstrumentationKind::NumRuns; - pgoResults->m_schema.Append(numRunsSchema); - for (UINT32 iSchema = 0; iSchema < profileData->method.cBlock; iSchema++) - { - PgoInstrumentationSchema blockCountSchema = {}; - blockCountSchema.Count = 1; - blockCountSchema.InstrumentationKind = ICorJitInfo::PgoInstrumentationKind::BasicBlockIntCount; - blockCountSchema.ILOffset = blockCounts[iSchema].ILOffset; - blockCountSchema.Offset = (BYTE *)&blockCounts[iSchema].ExecutionCount - (BYTE*)blockCounts; - pgoResults->m_schema.Append(blockCountSchema); - } - pgoResults->m_hr = S_OK; - } - - *pCountSchemaItems = pgoResults->m_schema.GetCount(); - *pSchema = pgoResults->m_schema.GetElements(); - *pInstrumentationData = pgoResults->pInstrumentationData; - *pPgoSource = PgoSource::IBC; - - return pgoResults->m_hr; -} - -void ZapInfo::allocMem(AllocMemArgs *pArgs) -{ - bool optForSize = m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SIZE_OPT); - - UINT align = DEFAULT_CODE_ALIGN; - - if ((pArgs->flag & CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN) && !IsReadyToRunCompilation()) align = max(align, 16); - - m_pCode = ZapCodeBlob::NewAlignedBlob(m_pImage, NULL, pArgs->hotCodeSize, align); - pArgs->hotCodeBlock = m_pCode->GetData(); - pArgs->hotCodeBlockRW = m_pCode->GetData(); - - if (pArgs->coldCodeSize != 0) - { - align = sizeof(DWORD); - - m_pColdCode = ZapCodeBlob::NewAlignedBlob(m_pImage, NULL, pArgs->coldCodeSize, align); - pArgs->coldCodeBlock = m_pColdCode->GetData(); - pArgs->coldCodeBlockRW = m_pColdCode->GetData(); - } - - // - // Allocate data - // - - if (pArgs->roDataSize > 0) - { - if (pArgs->flag & CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN) - { - align = 16; - } - else if (optForSize || (pArgs->roDataSize < 8)) - { - align = TARGET_POINTER_SIZE; - } - else - { - align = 8; - } - m_pROData = ZapBlobWithRelocs::NewAlignedBlob(m_pImage, NULL, pArgs->roDataSize, align); - pArgs->roDataBlock = m_pROData->GetData(); - pArgs->roDataBlockRW = m_pROData->GetData(); - } - - if (m_pImage->m_stats) - { - m_pImage->m_stats->m_nativeCodeSize += pArgs->hotCodeSize; - m_pImage->m_stats->m_nativeColdCodeSize += pArgs->coldCodeSize; - m_pImage->m_stats->m_nativeRODataSize += pArgs->roDataSize; - - BOOL haveProfileData = CurrentMethodHasProfileData(); - - if (haveProfileData) - { - m_pImage->m_stats->m_nativeCodeSizeInProfiledMethods += pArgs->hotCodeSize; - m_pImage->m_stats->m_nativeColdCodeSizeInProfiledMethods += pArgs->coldCodeSize; - } - - if (pArgs->coldCodeSize) - { - m_pImage->m_stats->m_NumHotColdAllocations++; - - m_pImage->m_stats->m_nativeCodeSizeInSplitMethods += pArgs->hotCodeSize; - m_pImage->m_stats->m_nativeColdCodeSizeInSplitMethods += pArgs->coldCodeSize; - - if (haveProfileData) - { - m_pImage->m_stats->m_nativeCodeSizeInSplitProfiledMethods += pArgs->hotCodeSize; - m_pImage->m_stats->m_nativeColdCodeSizeInSplitProfiledMethods += pArgs->coldCodeSize; - } - } - else - { - m_pImage->m_stats->m_NumHotAllocations++; - } - } -} - -void * ZapInfo::allocGCInfo(size_t size) -{ - _ASSERTE(m_pGCInfo == NULL); - -#ifdef HOST_64BIT - if (size & 0xFFFFFFFF80000000LL) - { - IfFailThrow(CORJIT_OUTOFMEM); - } -#endif // HOST_64BIT - - m_pGCInfo = new BYTE[size]; - m_cbGCInfo = size; - - return m_pGCInfo; -} - -void ZapInfo::setEHcount(unsigned cEH) -{ - // - // Must call after header has been allocated - // - - if (cEH == 0) - { - _ASSERTE(!"Should not be called"); - return; - } - - ULONG size = (sizeof(CORCOMPILE_EXCEPTION_CLAUSE) * cEH); - - _ASSERTE(m_pExceptionInfo == NULL); - m_pExceptionInfo = ZapBlob::NewAlignedBlob(m_pImage, NULL, size, sizeof(DWORD)); -} - -void ZapInfo::setEHinfo(unsigned EHnumber, - const CORINFO_EH_CLAUSE *clause) -{ - // - // Must call after EH info has been allocated - // - - _ASSERTE(m_pExceptionInfo != NULL); - - CORCOMPILE_EXCEPTION_CLAUSE *ehClauseArray = (CORCOMPILE_EXCEPTION_CLAUSE *)m_pExceptionInfo->GetData(); - CORCOMPILE_EXCEPTION_CLAUSE *ilClause = &ehClauseArray[EHnumber]; - - ilClause->TryStartPC = clause->TryOffset; - ilClause->TryEndPC = clause->TryLength; - ilClause->HandlerStartPC= clause->HandlerOffset; - ilClause->HandlerEndPC = clause->HandlerLength; - ilClause->Flags = (CorExceptionFlag) clause->Flags; - - if (clause->Flags & CORINFO_EH_CLAUSE_FILTER) - { - ilClause->FilterOffset = clause->FilterOffset; - } - else - { - ilClause->ClassToken = clause->ClassToken; - - if (ilClause->ClassToken != 0) - { - CORINFO_RESOLVED_TOKEN resolvedToken = { 0 }; - resolvedToken.tokenContext = MAKE_METHODCONTEXT(m_currentMethodInfo.ftn); - resolvedToken.tokenScope = m_currentMethodInfo.scope; - resolvedToken.token = ilClause->ClassToken; - resolvedToken.tokenType = CORINFO_TOKENKIND_Class; - - resolveToken(&resolvedToken); - - if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) - { - // IL stub tokens are 'private' and do not resolve correctly in their parent module's metadata. - - // Currently, the only place we are using a token here is for a COM-to-CLR exception-to-HRESULT - // mapping catch clause. We want this catch clause to catch all exceptions, so we override the - // token to be mdTypeRefNil, which used by the EH system to mean catch(...) -#ifdef _DEBUG - // The proper way to do this, should we ever want to support arbitrary types here, is to "pre- - // resolve" the token and store the TypeHandle in the clause. But this requires additional - // infrastructure to ensure the TypeHandle is saved and fixed-up properly. For now, we will - // simply assert that the original type was System.Object. - - CORINFO_CLASS_HANDLE systemObjectHandle = getBuiltinClass(CLASSID_SYSTEM_OBJECT); - _ASSERTE(systemObjectHandle == resolvedToken.hClass); -#endif // _DEBUG - ilClause->ClassToken = mdTypeRefNil; - } - else - { - // For all clause types add fixup to ensure the types are loaded before the code of the method - // containing the catch blocks is executed. This ensures that a failure to load the types would - // not happen when the exception handling is in progress and it is looking for a catch handler. - // At that point, we could only fail fast. - classMustBeLoadedBeforeCodeIsRun(resolvedToken.hClass); - } - } - } - - // - // @TODO: this does not support DynamicMethods - // -} - -int ZapInfo::canHandleException(struct _EXCEPTION_POINTERS *pExceptionPointers) -{ - return (EXCEPTION_EXECUTE_HANDLER); -} - -int ZapInfo::doAssert(const char* szFile, int iLine, const char* szExpr) -{ - -#if defined(_DEBUG) - return(_DbgBreakCheck(szFile, iLine, szExpr)); -#else - return(true); // break into debugger -#endif - -} -void ZapInfo::reportFatalError(CorJitResult result) -{ - m_zapper->Info(W("Jit reported error 0x%x while compiling %s\n"), (int)result, - m_currentMethodName.GetUnicode()); -} - -// Reserve memory for the method/funclet's unwind information -// Note that this must be called before allocMem, it should be -// called once for the main method, once for every funclet region, and -// once for every non-funclet cold region for which we will call -// allocUnwindinfo. -// -// For prejitted code we need to count how many funclet regions -// we have so that we can allocate and sort a contiguous .rdata block. -// -void ZapInfo::reserveUnwindInfo(bool isFunclet, bool isColdCode, uint32_t unwindSize) -{ - // Nothing to do -} - - -// -// Allocate and initialize the .xdata and .pdata for this method or -// funclet region and get the block of memory needed for the machine-specific -// unwind information (the info for crawling the stack frame). -// Note that allocMem must be called first. -// -// The pHotCode parameter points at the first byte of the code of the method. -// The startOffset and endOffset are the region (main or funclet) that -// we are to allocate and create .xdata and .pdata for. -// The pUnwindBlock is copied and contains the .xdata unwind info. -// -// Parameters: -// -// pHotCode main method code buffer, always filled in -// pColdCode cold code buffer, only filled in if this is cold code, -// null otherwise -// startOffset start of code block, relative to appropriate code buffer -// (e.g. pColdCode if cold, pHotCode if hot). -// endOffset end of code block, relative to appropriate code buffer -// unwindSize size of unwind info pointed to by pUnwindBlock -// pUnwindBlock pointer to unwind info -// funcKind type of funclet (main method code, handler, filter) -// -void ZapInfo::allocUnwindInfo ( - uint8_t * pHotCode, /* IN */ - uint8_t * pColdCode, /* IN */ - uint32_t startOffset, /* IN */ - uint32_t endOffset, /* IN */ - uint32_t unwindSize, /* IN */ - uint8_t * pUnwindBlock, /* IN */ - CorJitFuncKind funcKind /* IN */ - ) -{ -#ifdef FEATURE_EH_FUNCLETS - _ASSERTE(pHotCode == m_pCode->GetData()); - _ASSERTE(pColdCode == NULL || pColdCode == m_pColdCode->GetData()); - - ZapNode * pCode = (pColdCode != NULL) ? m_pColdCode : m_pCode; - - ZapUnwindInfo * pUnwindInfo = new (m_pImage->GetHeap()) ZapUnwindInfo(pCode, startOffset, endOffset); - - // Prepend the new unwind info to the linked list of all fragments - pUnwindInfo->SetNextFragment(m_pUnwindInfoFragments); - m_pUnwindInfoFragments = pUnwindInfo; - - if (funcKind == CORJIT_FUNC_ROOT && pColdCode == NULL && startOffset == 0) - { - // - // Main method unwind data - // - - _ASSERTE(m_pMainUnwindInfo == NULL); - - m_pMainUnwindInfo = new BYTE[unwindSize]; - m_cbMainUnwindInfo = unwindSize; - - memcpy(m_pMainUnwindInfo, pUnwindBlock, unwindSize); - - // UnwindData Will be set to the combined GCInfo + UnwindInfo blob later as the compiled method is published - - _ASSERTE(m_pUnwindInfo == NULL); - m_pUnwindInfo = pUnwindInfo; - } -#if defined(TARGET_AMD64) - else - if (funcKind == CORJIT_FUNC_ROOT && pColdCode != NULL) - { - // - // Chained cold code unwind data - // - - _ASSERTE(unwindSize == 0); - - // UnwindData Will be chained to the parent unwind info later as the compiled method is published - - _ASSERTE(m_pChainedColdUnwindInfo == NULL); - m_pChainedColdUnwindInfo = pUnwindInfo; - } -#endif - else - { - - // - // Normal unwind data - // - - ZapUnwindData * pUnwindData = m_pImage->m_pUnwindDataTable->GetUnwindData(pUnwindBlock, unwindSize, funcKind == CORJIT_FUNC_FILTER); - pUnwindInfo->SetUnwindData(pUnwindData); - } -#endif // FEATURE_EH_FUNCLETS -} - -bool ZapInfo::logMsg(unsigned level, const char *fmt, va_list args) -{ - if (HasSvcLogger()) - { - if (level <= LL_INFO10) - { - StackSString ss; - ss.VPrintf(fmt,args); - GetSvcLogger()->Log(ss.GetUnicode(), LogLevel_Success); - return TRUE; - } - } - -#ifdef LOGGING - if (LoggingOn(LF_JIT, level)) - { - LogSpewValist(LF_JIT, level, (char*) fmt, args); - return TRUE; - } -#endif // LOGGING - - return FALSE; -} - -// -// ICorDynamicInfo -// - -uint32_t ZapInfo::getThreadTLSIndex(void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - *ppIndirection = NULL; - return (uint32_t)-1; -} - -const void * ZapInfo::getInlinedCallFrameVptr(void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - *ppIndirection = m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable, - offsetof(CORCOMPILE_EE_INFO_TABLE, inlinedCallFrameVptr)); - return NULL; -} - -int32_t * ZapInfo::getAddrOfCaptureThreadGlobal(void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - *ppIndirection = NULL; - if (IsReadyToRunCompilation()) - { - *ppIndirection = m_pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_IndirectTrapThreads); - } - else - { - *ppIndirection = m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable, - offsetof(CORCOMPILE_EE_INFO_TABLE, addrOfCaptureThreadGlobal)); - } - - return NULL; -} - -// Get slow lazy string literal helper to use (CORINFO_HELP_STRCNS*). -// Returns CORINFO_HELP_UNDEF if lazy string literal helper cannot be used. -CorInfoHelpFunc ZapInfo::getLazyStringLiteralHelper(CORINFO_MODULE_HANDLE handle) -{ - if (handle == m_pImage->m_hModule) - return CORINFO_HELP_STRCNS_CURRENT_MODULE; - - return CORINFO_HELP_STRCNS; -} - -CORINFO_MODULE_HANDLE ZapInfo::embedModuleHandle(CORINFO_MODULE_HANDLE handle, - void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - if (IsReadyToRunCompilation()) - { - _ASSERTE(!"embedModuleHandle"); - ThrowHR(E_NOTIMPL); - } - - BOOL fHardbound = m_pImage->m_pPreloader->CanEmbedModuleHandle(handle); - if (fHardbound) - { - if (handle == m_pImage->m_hModule) - { - // If the handle is the module we are currently ngening, we will - // assume that Module is the very first thing in the preload section - *ppIndirection = NULL; - return (CORINFO_MODULE_HANDLE)m_pImage->m_pPreloadSections[CORCOMPILE_SECTION_MODULE]; - } - - *ppIndirection = m_pImage->GetImportTable()->GetModuleHandleImport(handle); - } - else - { - ZapImport * pImport = m_pImage->GetImportTable()->GetModuleHandleImport(handle); - AppendConditionalImport(pImport); - - *ppIndirection = pImport; - } - return NULL; -} - -// -// The following functions indicate whether a handle can be directly embedded into -// the code being compiled, or if it needs to be accessed with a (fixable) indirection. -// Embeddable handles are those that will be persisted in the zap image. -// -// These functions are gradually being all moved across to ceeload.cpp and compile.cpp. -// - -CORINFO_CLASS_HANDLE ZapInfo::embedClassHandle(CORINFO_CLASS_HANDLE handle, - void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - if (IsReadyToRunCompilation()) - { - // This is supported by crossgen2 - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: embedding class handle not supported\n")); - - ThrowHR(E_NOTIMPL); - } - - m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(handle); - - BOOL fHardbound = m_pImage->m_pPreloader->CanEmbedClassHandle(handle); - if (fHardbound) - { - CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableType(handle); - - if (moduleHandle == m_pImage->m_hModule) - { - // If the handle is the module we are currently ngening, we can - // embed it after its resolved. So use a deferred reloc - - *ppIndirection = NULL; - return CORINFO_CLASS_HANDLE(m_pImage->GetWrappers()->GetClassHandle(handle)); - } - - *ppIndirection = m_pImage->GetImportTable()->GetClassHandleImport(handle); - } - else - { - ZapImport * pImport = m_pImage->GetImportTable()->GetClassHandleImport(handle); - AppendConditionalImport(pImport); - - *ppIndirection = pImport; - } - return NULL; -} - -CORINFO_FIELD_HANDLE ZapInfo::embedFieldHandle(CORINFO_FIELD_HANDLE handle, - void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - if (IsReadyToRunCompilation()) - { - _ASSERTE(!"embedFieldHandle"); - ThrowHR(E_NOTIMPL); - } - - m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(m_pEEJitInfo->getFieldClass(handle)); - - BOOL fHardbound = m_pImage->m_pPreloader->CanEmbedFieldHandle(handle); - if (fHardbound) - { - CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableField(handle); - - if (moduleHandle == m_pImage->m_hModule) - { - // If the handle is the module we are currently ngening, we can - // embed it after its resolved. So use a deferred reloc - - *ppIndirection = NULL; - return CORINFO_FIELD_HANDLE(m_pImage->GetWrappers()->GetFieldHandle(handle)); - } - } - - - ZapImport * pImport = m_pImage->GetImportTable()->GetFieldHandleImport(handle); - AppendConditionalImport(pImport); - - *ppIndirection = pImport; - return NULL; -} - -CORINFO_METHOD_HANDLE ZapInfo::embedMethodHandle(CORINFO_METHOD_HANDLE handle, - void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - if (IsReadyToRunCompilation()) - { - // READYTORUN FUTURE: Handle this case correctly - ThrowHR(E_NOTIMPL); - } - - CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(handle); - if (moduleHandle == m_pImage->m_hModule - && m_pImage->m_pPreloader->CanEmbedMethodHandle(handle, m_currentMethodHandle)) - { - // If the handle is the module we are currently ngening, we can - // embed it after its resolved. So use a deferred reloc - - *ppIndirection = NULL; - return CORINFO_METHOD_HANDLE(m_pImage->GetWrappers()->GetMethodHandle(handle)); - } - - ZapImport * pImport = m_pImage->GetImportTable()->GetMethodHandleImport(handle); - AppendConditionalImport(pImport); - - *ppIndirection = pImport; - return NULL; -} - -CORINFO_CLASS_HANDLE ZapInfo::getTokenTypeAsHandle(CORINFO_RESOLVED_TOKEN * pResolvedToken) -{ - return m_pEEJitInfo->getTokenTypeAsHandle(pResolvedToken); -} - -void ZapInfo::getLocationOfThisType(CORINFO_METHOD_HANDLE context, CORINFO_LOOKUP_KIND * pLookupKind) -{ - m_pEEJitInfo->getLocationOfThisType(context, pLookupKind); -} - -void -ZapInfo::embedGenericHandle(CORINFO_RESOLVED_TOKEN * pResolvedToken, - bool fEmbedParent, - CORINFO_GENERICHANDLE_RESULT *pResult) -{ - _ASSERTE(pResult); - - m_pEEJitInfo->embedGenericHandle( pResolvedToken, - fEmbedParent, - pResult); - - _ASSERTE(pResult->compileTimeHandle); - - if (pResult->lookup.lookupKind.needsRuntimeLookup) - { - if (!IsReadyToRunCompilation()) - embedGenericSignature(&pResult->lookup); - - if (pResult->handleType == CORINFO_HANDLETYPE_METHOD) - { - // There is no easy way to detect method referenced via generic lookups in generated code. - // Report this method reference unconditionally. - m_pImage->m_pPreloader->MethodReferencedByCompiledCode((CORINFO_METHOD_HANDLE)pResult->compileTimeHandle); - } - } - else - { - void *pIndirection = 0; - CORINFO_GENERIC_HANDLE handle = 0; - - switch (pResult->handleType) - { - case CORINFO_HANDLETYPE_CLASS: - if (IsReadyToRunCompilation()) - { - ZapImport * pImport = m_pImage->GetImportTable()->GetClassImport(ENCODE_TYPE_HANDLE, pResolvedToken); - AppendConditionalImport(pImport); - pIndirection = pImport; - handle = NULL; - } - else - { - CORINFO_CLASS_HANDLE clsHnd = (CORINFO_CLASS_HANDLE) pResult->compileTimeHandle; - handle = CORINFO_GENERIC_HANDLE(embedClassHandle(clsHnd, &pIndirection)); - } - break; - - case CORINFO_HANDLETYPE_METHOD: - if (IsReadyToRunCompilation()) - { - ZapImport * pImport = m_pImage->GetImportTable()->GetMethodImport(ENCODE_METHOD_HANDLE, (CORINFO_METHOD_HANDLE)pResult->compileTimeHandle, pResolvedToken); - AppendConditionalImport(pImport); - pIndirection = pImport; - handle = NULL; - } - else - { - CORINFO_METHOD_HANDLE methHnd = (CORINFO_METHOD_HANDLE) pResult->compileTimeHandle; - handle = CORINFO_GENERIC_HANDLE(embedMethodHandle(methHnd, &pIndirection)); - } - break; - - case CORINFO_HANDLETYPE_FIELD: - if (IsReadyToRunCompilation()) - { - ZapImport * pImport = m_pImage->GetImportTable()->GetFieldImport(ENCODE_FIELD_HANDLE, (CORINFO_FIELD_HANDLE)pResult->compileTimeHandle, pResolvedToken); - AppendConditionalImport(pImport); - pIndirection = pImport; - handle = NULL; - } - else - { - CORINFO_FIELD_HANDLE fldHnd = (CORINFO_FIELD_HANDLE) pResult->compileTimeHandle; - handle = CORINFO_GENERIC_HANDLE(embedFieldHandle(fldHnd, &pIndirection)); - } - break; - - default: - ThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_TOKEN_TYPE); - } - - if (handle) - { - pResult->lookup.constLookup.accessType = IAT_VALUE; - pResult->lookup.constLookup.handle = CORINFO_GENERIC_HANDLE(handle); - } - else - { - pResult->lookup.constLookup.accessType = IAT_PVALUE; - pResult->lookup.constLookup.addr = pIndirection; - } - } -} - -void ZapInfo::embedGenericSignature(CORINFO_LOOKUP * pLookup) -{ - _ASSERTE(pLookup->lookupKind.needsRuntimeLookup); - - if (IsReadyToRunCompilation()) - { - UNREACHABLE_MSG("We should never get here for the ReadyToRun compilation."); - ThrowHR(E_NOTIMPL); - } - - if (pLookup->runtimeLookup.signature != NULL) - { - pLookup->runtimeLookup.signature = m_pImage->GetImportTable()->GetGenericSignature( - pLookup->runtimeLookup.signature, pLookup->lookupKind.runtimeLookupKind == CORINFO_LOOKUP_METHODPARAM); - } -} - -bool ZapInfo::getTailCallHelpers( - CORINFO_RESOLVED_TOKEN* callToken, - CORINFO_SIG_INFO* sig, - CORINFO_GET_TAILCALL_HELPERS_FLAGS flags, - CORINFO_TAILCALL_HELPERS* pResult) -{ - ThrowHR(E_NOTIMPL); - return false; -} - -bool ZapInfo::convertPInvokeCalliToCall( - CORINFO_RESOLVED_TOKEN * pResolvedToken, - bool fMustConvert) -{ - return false; -} - -#ifdef FEATURE_READYTORUN_COMPILER -ReadyToRunHelper MapReadyToRunHelper(CorInfoHelpFunc func, bool * pfOptimizeForSize) -{ - switch (func) - { -#define OPTIMIZEFORSIZE *pfOptimizeForSize = true; -#define HELPER(readyToRunHelper, corInfoHelpFunc, flags) \ - case corInfoHelpFunc: flags return readyToRunHelper; -#include "readytorunhelpers.h" - - case CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE: - return READYTORUN_HELPER_GetRuntimeTypeHandle; - - case CORINFO_HELP_STRCNS_CURRENT_MODULE: - *pfOptimizeForSize = true; - return READYTORUN_HELPER_GetString; - - default: - return READYTORUN_HELPER_Invalid; - } -} -#endif // FEATURE_READYTORUN_COMPILER - -void * ZapInfo::getHelperFtn (CorInfoHelpFunc ftnNum, void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - *ppIndirection = NULL; - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - bool fOptimizeForSize = false; - ReadyToRunHelper helperNum = MapReadyToRunHelper(ftnNum, &fOptimizeForSize); - - if (helperNum == READYTORUN_HELPER_Invalid) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: JIT helper not supported: %S\n"), m_pEEJitInfo->getHelperName(ftnNum)); - ThrowHR(E_NOTIMPL); - } - - if (fOptimizeForSize) - { - *ppIndirection = NULL; - return m_pImage->GetImportTable()->GetIndirectHelperThunk(helperNum); - } - else - { - *ppIndirection = m_pImage->GetImportTable()->GetHelperImport(helperNum); - return NULL; - } - } -#endif - - DWORD dwHelper = ftnNum; - - switch (ftnNum) - { - case CORINFO_HELP_PROF_FCN_ENTER: - *ppIndirection = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexEnterAddr * TARGET_POINTER_SIZE); - return NULL; - case CORINFO_HELP_PROF_FCN_LEAVE: - *ppIndirection = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexLeaveAddr * TARGET_POINTER_SIZE); - return NULL; - case CORINFO_HELP_PROF_FCN_TAILCALL: - *ppIndirection = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexTailcallAddr * TARGET_POINTER_SIZE); - return NULL; -#ifdef TARGET_AMD64 - case CORINFO_HELP_STOP_FOR_GC: - // Force all calls in ngen images for this helper to use an indirect call. - // We cannot use a jump stub to reach this helper because - // the RAX register can contain a return value. - dwHelper |= CORCOMPILE_HELPER_PTR; - break; -#endif - default: - break; - } - - if (m_pImage->m_pHelperThunks[ftnNum] == NULL) - { - ZapNode * pHelperThunk; - if (ftnNum == CORINFO_HELP_STRCNS_CURRENT_MODULE) - { - pHelperThunk = new (m_pImage->GetHeap()) ZapLazyHelperThunk(CORINFO_HELP_STRCNS); - } - else - { - pHelperThunk = new (m_pImage->GetHeap()) ZapHelperThunk(dwHelper); - } -#if defined(TARGET_ARM) - if ((dwHelper & CORCOMPILE_HELPER_PTR) == 0) - pHelperThunk = m_pImage->GetInnerPtr(pHelperThunk, THUMB_CODE); -#endif - m_pImage->m_pHelperThunks[ftnNum] = pHelperThunk; - } - - void * ptr = m_pImage->m_pHelperThunks[ftnNum]; - - if (dwHelper & CORCOMPILE_HELPER_PTR) - { - *ppIndirection = ptr; - return NULL; - } - - return ptr; -} - -ULONG ZapInfo::GetNumFixups() -{ - return m_Imports.GetCount(); -} - -void ZapInfo::AppendConditionalImport(ZapImport * pImport) -{ - if (m_ImportSet.LookupPtr(pImport) != NULL) - return; - - ImportEntry entry; - entry.pImport = pImport; - entry.fConditional = true; - m_ImportSet.Add(entry); -} - -void ZapInfo::AppendImport(ZapImport * pImport) -{ - const ImportEntry * pExistingEntry = m_ImportSet.LookupPtr(pImport); - if (pExistingEntry != NULL) - { - if (!pExistingEntry->fConditional) - return; - const_cast(pExistingEntry)->fConditional = false; - } - else - { - ImportEntry entry; - entry.pImport = pImport; - entry.fConditional = false; - m_ImportSet.Add(entry); - } - - m_Imports.Append(pImport); -} - -// -// This function indicates whether a method entry point be directly embedded into -// the code being compiled, or if we can use a (fixable) cross module thunk. -// If we can't use either of these then we return NULL and we will use an -// (fixable) indirection cell to perform the call. -// -PVOID ZapInfo::embedDirectCall(CORINFO_METHOD_HANDLE ftn, - CORINFO_ACCESS_FLAGS accessFlags, - BOOL fAllowThunk) -{ - if (!m_pImage->m_pPreloader->CanEmbedFunctionEntryPoint(ftn, m_currentMethodHandle, accessFlags)) - { - return NULL; - } - - ZapNode * pEntryPointOrThunkToEmbed = NULL; - - // - // If it's in the same module then we can call it directly - // - CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(ftn); - if (moduleHandle == m_pImage->m_hModule - && m_pImage->m_pPreloader->CanEmbedMethodHandle(ftn, m_currentMethodHandle)) - { - pEntryPointOrThunkToEmbed = m_pImage->m_pMethodEntryPoints->GetMethodEntryPoint(ftn, accessFlags); - } - else // otherwise we are calling into an external module - { - if (!fAllowThunk) - { - return NULL; - } - - pEntryPointOrThunkToEmbed = m_pImage->GetImportTable()->GetExternalMethodThunk(ftn); - } - -#ifdef TARGET_ARM - pEntryPointOrThunkToEmbed = m_pImage->GetInnerPtr(pEntryPointOrThunkToEmbed, THUMB_CODE); -#endif - - return pEntryPointOrThunkToEmbed; -} - -bool ZapInfo::notifyInstructionSetUsage(CORINFO_InstructionSet instructionSet, bool supportEnabled) -{ - return m_pEEJitInfo->notifyInstructionSetUsage(instructionSet, supportEnabled); -} - -void ZapInfo::getFunctionEntryPoint( - CORINFO_METHOD_HANDLE ftn, /* IN */ - CORINFO_CONST_LOOKUP * pResult, /* OUT */ - CORINFO_ACCESS_FLAGS accessFlags/*=CORINFO_ACCESS_ANY*/) -{ - if (IsReadyToRunCompilation()) - { - // READYTORUN: FUTURE: JIT still calls this for tail. and jmp instructions - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Method entrypoint cannot be encoded\n")); - ThrowHR(E_NOTIMPL); - } - - // Must deal with methods that are methodImpl'd within their own type. - ftn = mapMethodDeclToMethodImpl(ftn); - - m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(ftn); - - void * entryPointOrThunkToEmbed = embedDirectCall(ftn, accessFlags, TRUE); - if (entryPointOrThunkToEmbed != NULL) - { - pResult->accessType = IAT_VALUE; - pResult->addr = entryPointOrThunkToEmbed; - } - else - { - ZapImport * pImport = m_pImage->GetImportTable()->GetFunctionEntryImport(ftn); - AppendConditionalImport(pImport); - - // Tell the JIT to use an indirections - pResult->accessType = IAT_PVALUE; - pResult->addr = pImport; - } -} - -void ZapInfo::getFunctionFixedEntryPoint(CORINFO_METHOD_HANDLE ftn, - CORINFO_CONST_LOOKUP * pResult) -{ - _ASSERTE(pResult); - - m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(ftn); - - // We can only embed entrypoints from the module being NGened since we do not support mapping of external - // import thunks to MethodDesc. It should be ok since the delegate targets are typically from the same module. - void * entryPointToEmbed = embedDirectCall(ftn, CORINFO_ACCESS_ANY, FALSE); - - if (entryPointToEmbed != NULL) - { - pResult->accessType = IAT_VALUE; - pResult->addr = entryPointToEmbed; - } - else - { - ZapImport * pImport = m_pImage->GetImportTable()->GetFunctionEntryImport(ftn); - AppendConditionalImport(pImport); - - pResult->accessType = IAT_PVALUE; - pResult->addr = pImport; - } -} - -void * ZapInfo::getMethodSync(CORINFO_METHOD_HANDLE ftn, - void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - CORINFO_CLASS_HANDLE classHandle = getMethodClass(ftn); - - ZapImport * pImport = m_pImage->GetImportTable()->GetSyncLockImport(classHandle); - AppendConditionalImport(pImport); - - *ppIndirection = pImport; - return NULL; -} - -void * ZapInfo::getAddressOfPInvokeFixup(CORINFO_METHOD_HANDLE method,void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - *ppIndirection = NULL; - - m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(method); - - if (!IsReadyToRunCompilation()) - { - CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(method); - if (moduleHandle == m_pImage->m_hModule - && m_pImage->m_pPreloader->CanEmbedMethodHandle(method, m_currentMethodHandle)) - { - return PVOID(m_pImage->GetWrappers()->GetAddrOfPInvokeFixup(method)); - } - } - - // - // The indirect P/Invoke target enables the traditional semantics of - // resolving the P/Invoke target at the callsite. Providing a non-indirect - // fixup indicates the P/Invoke target will be resolved when the enclosing - // function is compiled. This subtle semantic difference is chosen for - // scenarios when resolution of the target must occur under a specific GC mode. - // - - void *fixup = NULL; - ZapImport *pImport = NULL; - if (m_pImage->m_pPreloader->ShouldSuppressGCTransition(method)) - { - pImport = m_pImage->GetImportTable()->GetPInvokeTargetImport(method); - fixup = pImport; - } - else - { - pImport = m_pImage->GetImportTable()->GetIndirectPInvokeTargetImport(method); - *ppIndirection = pImport; - } - - _ASSERTE(pImport != NULL); - AppendConditionalImport(pImport); - - return fixup; -} - -void ZapInfo::getAddressOfPInvokeTarget(CORINFO_METHOD_HANDLE method, CORINFO_CONST_LOOKUP *pLookup) -{ - _ASSERTE(pLookup != NULL); - - void * pIndirection; - void * pResult = getAddressOfPInvokeFixup(method, &pIndirection); - if (pResult != NULL) - { - pLookup->accessType = IAT_PVALUE; - pLookup->addr = pResult; - return; - } - - _ASSERTE(pIndirection != NULL); - pLookup->accessType = IAT_PPVALUE; - pLookup->addr = pIndirection; -} - -CORINFO_JUST_MY_CODE_HANDLE ZapInfo::getJustMyCodeHandle( - CORINFO_METHOD_HANDLE method, - CORINFO_JUST_MY_CODE_HANDLE **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - if (IsReadyToRunCompilation()) - { - *ppIndirection = NULL; - return NULL; - } - - *ppIndirection = (CORINFO_JUST_MY_CODE_HANDLE *)m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable, - offsetof(CORCOMPILE_EE_INFO_TABLE, addrOfJMCFlag)); - return NULL; -} - -ZapImport * ZapInfo::GetProfilingHandleImport() -{ - if (m_pProfilingHandle == NULL) - { - ZapImport * pImport = m_pImage->GetImportTable()->GetProfilingHandleImport(m_currentMethodHandle); - AppendImport(pImport); - - m_pProfilingHandle = pImport; - } - - return m_pProfilingHandle; -} - -void ZapInfo::GetProfilingHandle(bool *pbHookFunction, - void **pProfilerHandle, - bool *pbIndirectedHandles) -{ - // - // Return the location within the fixup table - // - // Profiling handle is opaque token. It does not have to be aligned thus we can not store it in the same location as token. - // - *pProfilerHandle = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexClientData * TARGET_POINTER_SIZE); - - // All functions get hooked in ngen /Profile - *pbHookFunction = TRUE; - - // - // This is the NGEN case, where we always do indirection on the handle so we can fix it up at load time. - // - *pbIndirectedHandles = TRUE; -} - -// -// This strips the CORINFO_FLG_JIT_INTRINSIC flag from some of the named intrinsic methods. -// -DWORD FilterNamedIntrinsicMethodAttribs(ZapInfo* pZapInfo, DWORD attribs, CORINFO_METHOD_HANDLE ftn, ICorDynamicInfo* pJitInfo) -{ - if (attribs & CORINFO_FLG_JIT_INTRINSIC) - { - // Figure out which intrinsic we are dealing with. - const char* namespaceName; - const char* className; - const char* enclosingClassName; - const char* methodName = pJitInfo->getMethodNameFromMetadata(ftn, &className, &namespaceName, &enclosingClassName); - - // Is this the get_IsSupported method that checks whether intrinsic is supported? - bool fIsGetIsSupportedMethod = strcmp(methodName, "get_IsSupported") == 0; - bool fIsPlatformHWIntrinsic = false; - bool fIsHWIntrinsic = false; - bool fTreatAsRegularMethodCall = false; - -#if defined(TARGET_X86) || defined(TARGET_AMD64) - fIsPlatformHWIntrinsic = strcmp(namespaceName, "System.Runtime.Intrinsics.X86") == 0; -#elif defined(TARGET_ARM64) - fIsPlatformHWIntrinsic = strcmp(namespaceName, "System.Runtime.Intrinsics.Arm") == 0; -#endif - - fIsHWIntrinsic = fIsPlatformHWIntrinsic || (strcmp(namespaceName, "System.Runtime.Intrinsics") == 0); - - // By default, we want to treat the get_IsSupported method for platform specific HWIntrinsic ISAs as - // method calls. This will be modified as needed below based on what ISAs are considered baseline. - // - // We also want to treat the non-platform specific hardware intrinsics as regular method calls. This - // is because they often change the code they emit based on what ISAs are supported by the compiler, - // but we don't know what the target machine will support. - // - // Additionally, we make sure none of the hardware intrinsic method bodies get pregenerated in crossgen - // (see ZapInfo::CompileMethod) but get JITted instead. The JITted method will have the correct - // answer for the CPU the code is running on. - - fTreatAsRegularMethodCall = fIsGetIsSupportedMethod && fIsPlatformHWIntrinsic; - -#if defined(TARGET_ARM64) - // On Arm64 AdvSimd ISA is required by CoreCLR, so we can expand Vector64 and Vector128 generic methods (e.g. Vector64.get_Zero) - // as well as Vector64 and Vector128 methods (e.g. Vector128.CreateScalarUnsafe). - fTreatAsRegularMethodCall |= !fIsPlatformHWIntrinsic && fIsHWIntrinsic - && (strncmp(className, "Vector64", _countof("Vector64") - 1) != 0) - && (strncmp(className, "Vector128", _countof("Vector128") - 1) != 0); - -#elif defined(TARGET_X86) || defined(TARGET_AMD64) - // The following methods should be safe to expand unconditionally, since JIT either - // 1) does not generate code for them (e.g. for Vector128.AsByte() or get_Count) or - // 2) uses instructions that belong to Sse or Sse2 (these are required baseline ISAs). - static const char* vector128MethodsSafeToExpand[] = { "As", "AsByte", "AsDouble", "AsInt16", "AsInt32", "AsInt64", "AsSByte", - "AsSingle", "AsUInt16", "AsUInt32", "AsUInt64", "Create", "CreateScalarUnsafe", "ToScalar", "get_Count", "get_Zero" }; - - if (!fIsPlatformHWIntrinsic && fIsHWIntrinsic) - { - fTreatAsRegularMethodCall = true; - - if (strncmp(className, "Vector128", _countof("Vector128") - 1) == 0) - { - for (size_t i = 0; i < _countof(vector128MethodsSafeToExpand); i++) - { - if (strcmp(methodName, vector128MethodsSafeToExpand[i]) == 0) - { - fTreatAsRegularMethodCall = false; - break; - } - } - } - } -#else - fTreatAsRegularMethodCall |= !fIsPlatformHWIntrinsic && fIsHWIntrinsic; -#endif - - if (fIsPlatformHWIntrinsic) - { - // Simplify the comparison logic by grabbing the name of the ISA - const char* isaName = (enclosingClassName == nullptr) ? className : enclosingClassName; - - bool fIsPlatformRequiredISA = false; - bool fIsPlatformSubArchitecture = false; - -#if defined(TARGET_X86) || defined(TARGET_AMD64) - fIsPlatformRequiredISA = (strcmp(isaName, "X86Base") == 0) || (strcmp(isaName, "Sse") == 0) || (strcmp(isaName, "Sse2") == 0); - fIsPlatformSubArchitecture = strcmp(className, "X64") == 0; -#elif defined(TARGET_ARM64) - fIsPlatformRequiredISA = (strcmp(isaName, "ArmBase") == 0) || (strcmp(isaName, "AdvSimd") == 0); - fIsPlatformSubArchitecture = strcmp(className, "Arm64") == 0; -#endif - - if (fIsPlatformRequiredISA) - { - if ((enclosingClassName == nullptr) || fIsPlatformSubArchitecture) - { - // If the ISA is required by CoreCLR for the platform, we can expand unconditionally - fTreatAsRegularMethodCall = false; - } - } -#if defined(TARGET_X86) || defined(TARGET_AMD64) - else if ((strcmp(isaName, "Avx") == 0) || (strcmp(isaName, "Fma") == 0) || (strcmp(isaName, "Avx2") == 0) - || (strcmp(isaName, "Bmi1") == 0) || (strcmp(isaName, "Bmi2") == 0) || (strcmp(isaName, "Lzcnt") == 0)) - { - if ((enclosingClassName == nullptr) || fIsPlatformSubArchitecture) - { - // If it is the get_IsSupported method for an ISA which is intentionally not enabled - // for crossgen, we want to expand unconditionally. This will force those code - // paths to be treated as dead code and dropped from the compilation. - // See Zapper::InitializeCompilerFlags - // - // For all of the other intrinsics in an ISA which requires the VEX encoding - // we need to treat them as regular method calls. This is done because RyuJIT - // doesn't currently support emitting both VEX and non-VEX encoded instructions - // for a single method. - fTreatAsRegularMethodCall = !fIsGetIsSupportedMethod; - } - } -#endif // defined(TARGET_X86) || defined(TARGET_AMD64) -#ifdef TARGET_X86 - else if (fIsPlatformSubArchitecture) - { - // For ISAs not handled explicitly above, the IsSupported check will always - // be treated as a regular method call. If we are evaulating a method in the X64 - // namespace, we know it will never be supported on x86, so we can allow the code - // to be treated as dead. We treat all non-IsSupported methods as regular method - // calls so they throw PNSE if used withoug the IsSupported check. - fTreatAsRegularMethodCall = !fIsGetIsSupportedMethod; - } -#endif // TARGET_X86 - } -#if defined(TARGET_X86) || defined(TARGET_AMD64) - else if (strcmp(namespaceName, "System") == 0) - { - if (strcmp(className, "Math") == 0 || strcmp(className, "MathF") == 0) - { - // These are normally handled via the SSE4.1 instructions ROUNDSS/ROUNDSD. - // However, we don't know the ISAs the target machine supports so we should - // fallback to the method call implementation instead. - fTreatAsRegularMethodCall = strcmp(methodName, "Round") == 0 || strcmp(methodName, "Ceiling") == 0 || - strcmp(methodName, "Floor") == 0; - } - } - else if (strcmp(namespaceName, "System.Numerics") == 0) - { - if ((strcmp(className, "Vector3") == 0) || (strcmp(className, "Vector4") == 0)) - { - // Vector3 and Vector4 have constructors which take a smaller Vector and create bolt on - // a larger vector. This uses insertps instruction when compiled with SSE4.1 instruction support - // which must not be generated inline in R2R images that actually support an SSE2 only mode. - if (strcmp(methodName, ".ctor") == 0) - { - CORINFO_SIG_INFO sig; - pZapInfo->getMethodSig(ftn, &sig, NULL); - CORINFO_CLASS_HANDLE argClass; - if ((CorInfoType)pZapInfo->getArgType(&sig, sig.args, &argClass) == CORINFO_TYPE_VALUECLASS) - { - fTreatAsRegularMethodCall = TRUE; - } - } - else if (strcmp(methodName, "Dot") == 0) - { - // The dot product operations uses the dpps instruction when compiled with SSE4.1 instruction - // support. This must not be generated inline in R2R images that actually support an SSE2 only mode. - fTreatAsRegularMethodCall = TRUE; - } - } - else if ((strcmp(className, "Vector2") == 0) || (strcmp(className, "Vector") == 0) || (strcmp(className, "Vector`1") == 0)) - { - if (strcmp(methodName, "Dot") == 0) - { - // The dot product operations uses the dpps instruction when compiled with SSE4.1 instruction - // support. This must not be generated inline in R2R images that actually support an SSE2 only mode. - fTreatAsRegularMethodCall = TRUE; - } - } - } -#endif // defined(TARGET_X86) || defined(TARGET_AMD64) - - if (fTreatAsRegularMethodCall) - { - // Treat as a regular method call (into a JITted method). - attribs = (attribs & ~CORINFO_FLG_JIT_INTRINSIC) | CORINFO_FLG_DONT_INLINE; - } - } - - return attribs; -} - -//return a callable stub that will do the virtual or interface call - - -void ZapInfo::getCallInfo(CORINFO_RESOLVED_TOKEN * pResolvedToken, - CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken, - CORINFO_METHOD_HANDLE callerHandle, - CORINFO_CALLINFO_FLAGS flags, - CORINFO_CALL_INFO *pResult) -{ - void * pTarget = NULL; - - _ASSERTE(pResult); - - if ((flags & CORINFO_CALLINFO_CALLVIRT) == 0 && pConstrainedResolvedToken != nullptr) - { - // Defer constrained call / ldftn instructions used for static virtual methods - // to runtime resolution. - ThrowHR(E_NOTIMPL); - } - - // Fill in the kind of the virtual call. - // We set kindOnly=true since we don't want the EE to actually give us - // a call stub - instead we want to generate an indirection ourselves. - m_pEEJitInfo->getCallInfo(pResolvedToken, - pConstrainedResolvedToken, - callerHandle, - /* REVISIT_TODO - * Addition of this flag. - */ - (CORINFO_CALLINFO_FLAGS)(flags | CORINFO_CALLINFO_KINDONLY), - pResult); - - pResult->methodFlags = FilterNamedIntrinsicMethodAttribs(this, pResult->methodFlags, pResult->hMethod, m_pEEJitInfo); - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - if (pResult->sig.isVarArg()) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: VarArg methods not supported\n")); - ThrowHR(E_NOTIMPL); - } - - if (pResult->accessAllowed != CORINFO_ACCESS_ALLOWED) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Runtime method access checks not supported\n")); - ThrowHR(E_NOTIMPL); - } - } -#endif - -#ifdef TARGET_X86 - if (GetCompileInfo()->IsUnmanagedCallersOnlyMethod(pResult->hMethod)) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: References to methods with UnmanagedCallersOnlyAttribute not implemented\n")); - ThrowHR(E_NOTIMPL); - } -#endif // TARGET_X86 - - if (flags & CORINFO_CALLINFO_KINDONLY) - return; - - if (IsReadyToRunCompilation()) - { - if (pResult->thisTransform == CORINFO_BOX_THIS) - { - // READYTORUN: FUTURE: Optionally create boxing stub at runtime - // We couldn't resolve the constrained call into a valuetype instance method and we're asking the JIT - // to box and do a virtual dispatch. If we were to allow the boxing to happen now, it could break future code - // when the user adds a method to the valuetype that makes it possible to avoid boxing (if there is state - // mutation in the method). - - // We allow this at least for primitives and enums because we control them - // and we know there's no state mutation. - CorInfoType constrainedType = getTypeForPrimitiveValueClass(pConstrainedResolvedToken->hClass); - if (constrainedType == CORINFO_TYPE_UNDEF) - ThrowHR(E_NOTIMPL); - } - } - - // OK, if the EE said we're not doing a stub dispatch then just return the kind to - // the caller. No other kinds of virtual calls have extra information attached. - switch (pResult->kind) - { - case CORINFO_VIRTUALCALL_STUB: - { - if (pResult->stubLookup.lookupKind.needsRuntimeLookup) - { - if (!IsReadyToRunCompilation()) - embedGenericSignature(&pResult->stubLookup); - return; - } - - if (IsReadyToRunCompilation()) - { - ZapImport * pImport = m_pImage->GetImportTable()->GetStubDispatchCell(pResolvedToken); - - pResult->stubLookup.constLookup.accessType = IAT_PVALUE; - pResult->stubLookup.constLookup.addr = pImport; - } - else - { - - CORINFO_CLASS_HANDLE calleeOwner = pResolvedToken->hClass; - CORINFO_METHOD_HANDLE callee = pResolvedToken->hMethod; - _ASSERTE(callee == pResult->hMethod); - - // - // Create the indirection cell - // - pTarget = m_pImage->GetImportTable()->GetStubDispatchCell(calleeOwner, callee); - - pResult->stubLookup.constLookup.accessType = IAT_PVALUE; - pResult->stubLookup.constLookup.addr = pTarget; - } - } - break; - - - case CORINFO_CALL_CODE_POINTER: - _ASSERTE(pResult->codePointerLookup.lookupKind.needsRuntimeLookup); - if (!IsReadyToRunCompilation()) - embedGenericSignature(&pResult->codePointerLookup); - - // There is no easy way to detect method referenced via generic lookups in generated code. - // Report this method reference unconditionally. - m_pImage->m_pPreloader->MethodReferencedByCompiledCode(pResult->hMethod); - return; - - case CORINFO_CALL: - if (IsReadyToRunCompilation()) - { - // Constrained token is not interesting with this transforms - if (pResult->thisTransform != CORINFO_NO_THIS_TRANSFORM) - pConstrainedResolvedToken = NULL; - - ZapImport * pImport; - - if (flags & CORINFO_CALLINFO_LDFTN) - { - pImport = m_pImage->GetImportTable()->GetMethodImport(ENCODE_METHOD_ENTRY, pResult->hMethod, pResolvedToken, pConstrainedResolvedToken); - - AppendConditionalImport(pImport); - } - else - { - if (pResult->methodFlags & CORINFO_FLG_INTRINSIC) - { - bool unused; - CorInfoIntrinsics intrinsic = getIntrinsicID(pResult->hMethod, &unused); - if ((intrinsic == CORINFO_INTRINSIC_StubHelpers_GetStubContext) - || (intrinsic == CORINFO_INTRINSIC_StubHelpers_GetStubContextAddr) - ) - { - // These intrinsics are always expanded directly in the jit and do not correspond to external methods - return; - } - } - pImport = m_pImage->GetImportTable()->GetExternalMethodCell(pResult->hMethod, pResolvedToken, pConstrainedResolvedToken); - } - - // READYTORUN: FUTURE: Direct calls if possible - pResult->codePointerLookup.constLookup.accessType = IAT_PVALUE; - pResult->codePointerLookup.constLookup.addr = pImport; - } - break; - - case CORINFO_VIRTUALCALL_VTABLE: - // Only calls within the CoreLib version bubble support fragile NI codegen with vtable based calls, for better performance (because - // CoreLib and the runtime will always be updated together anyways - this is a special case) - break; - - case CORINFO_VIRTUALCALL_LDVIRTFTN: -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation() && !pResult->exactContextNeedsRuntimeLookup) - { - ZapImport * pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(ENCODE_VIRTUAL_ENTRY, pResult->hMethod, pResolvedToken); - - pResult->codePointerLookup.constLookup.accessType = IAT_PVALUE; - pResult->codePointerLookup.constLookup.addr = pImport; - - _ASSERTE(!pResult->sig.hasTypeArg()); - } -#endif - - // Include the declaring instantiation of virtual generic methods in the NGen image. - m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(pResult->hMethod); - break; - - default: - _ASSERTE(!"Unknown call type"); - break; - } - - if (IsReadyToRunCompilation() && pResult->sig.hasTypeArg()) - { - if (pResult->exactContextNeedsRuntimeLookup) - { - // Nothing to do... The generic handle lookup gets embedded in to the codegen - // during the jitting of the call. - // (Note: The generic lookup in R2R is performed by a call to a helper at runtime, not by - // codegen emitted at crossgen time) - } - else - { - ZapImport * pImport; - if (((SIZE_T)pResult->contextHandle & CORINFO_CONTEXTFLAGS_MASK) == CORINFO_CONTEXTFLAGS_METHOD) - { - CORINFO_METHOD_HANDLE exactMethodHandle = (CORINFO_METHOD_HANDLE)((SIZE_T)pResult->contextHandle & ~CORINFO_CONTEXTFLAGS_MASK); - - pImport = m_pImage->GetImportTable()->GetMethodImport(ENCODE_METHOD_DICTIONARY, exactMethodHandle, - pResolvedToken, pConstrainedResolvedToken); - } - else - { - pImport = m_pImage->GetImportTable()->GetClassImport(ENCODE_TYPE_DICTIONARY, - (pConstrainedResolvedToken != NULL) ? pConstrainedResolvedToken : pResolvedToken); - } - - pResult->instParamLookup.accessType = IAT_PVALUE; - pResult->instParamLookup.addr = pImport; - - AppendConditionalImport(pImport); - } - } -} - -bool ZapInfo::canAccessFamily(CORINFO_METHOD_HANDLE hCaller, - CORINFO_CLASS_HANDLE hInstanceType) -{ - return m_pEEJitInfo->canAccessFamily(hCaller, hInstanceType); -} - -bool ZapInfo::isRIDClassDomainID (CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->isRIDClassDomainID(cls); -} - -unsigned ZapInfo::getClassDomainID (CORINFO_CLASS_HANDLE cls, void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(cls); - - if (!m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE)) - { - if (isRIDClassDomainID(cls)) - { - // Token is invariant to loading order, so we can go ahead and use it - - // Ensure that 'cls' gets added to CORCOMPILE_LOAD_TABLE, unless - // someone else adds some other type of fixup for 'cls'. - m_ClassLoadTable.Load(cls, FALSE); - - return m_pEEJitInfo->getClassDomainID(cls, ppIndirection); - } - - if (m_pImage->m_pPreloader->CanEmbedClassID(cls)) - { - // Ensure that 'cls' gets added to CORCOMPILE_LOAD_TABLE, unless - // someone else adds some other type of fixup for 'cls'. - m_ClassLoadTable.Load(cls, FALSE); - return m_pEEJitInfo->getClassDomainID(cls, ppIndirection); - } - } - - // We will have to insert a fixup - ZapImport * pImport = m_pImage->GetImportTable()->GetClassDomainIdImport(cls); - AppendConditionalImport(pImport); - - *ppIndirection = pImport; - return NULL; -} - -void * ZapInfo::getFieldAddress(CORINFO_FIELD_HANDLE field, void **ppIndirection) -{ - if (IsReadyToRunCompilation()) - { - void * pAddress = m_pEEJitInfo->getFieldAddress(field, ppIndirection); - - return m_pImage->m_pILMetaData->GetRVAField(pAddress); - } - - _ASSERTE(ppIndirection != NULL); - - CORINFO_CLASS_HANDLE hClass = m_pEEJitInfo->getFieldClass(field); - - m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(hClass); - - ZapImport * pImport = m_pImage->GetImportTable()->GetStaticFieldAddressImport(field); - AppendConditionalImport(pImport); - - // Field address is not aligned thus we can not store it in the same location as token. - *ppIndirection = m_pImage->GetInnerPtr(pImport, TARGET_POINTER_SIZE); - - return NULL; -} - -CORINFO_CLASS_HANDLE ZapInfo::getStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, bool* pIsSpeculative) -{ - if (pIsSpeculative != NULL) - { - *pIsSpeculative = true; - } - - return NULL; -} - -uint32_t ZapInfo::getFieldThreadLocalStoreID(CORINFO_FIELD_HANDLE field, - void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - *ppIndirection = m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable, - offsetof(CORCOMPILE_EE_INFO_TABLE, rvaStaticTlsIndex)); - return NULL; -} - -CORINFO_VARARGS_HANDLE ZapInfo::getVarArgsHandle(CORINFO_SIG_INFO *sig, - void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - // Zapper does not support embedding these as they are created dynamically - - if (sig->scope != m_pImage->m_hModule || sig->token == mdTokenNil) - { - _ASSERTE(!"Don't have enough info to be able to create a sig token."); - - *ppIndirection = NULL; - return NULL; - } - - // @perf: If the sig cookie construction code actually will restore the value types in - // the sig, we should call LoadClass on all of those types to avoid redundant - // restore cookies. - - ZapImport * pImport = m_pImage->GetImportTable()->GetVarArgImport(sig->scope, sig->token); - AppendConditionalImport(pImport); - - *ppIndirection = pImport; - return NULL; -} - -bool ZapInfo::canGetVarArgsHandle(CORINFO_SIG_INFO *sig) -{ - // Zapper does not support embedding these as they are created dynamically - if (sig->scope != m_pImage->m_hModule || sig->token == mdTokenNil) - { - return false; - } - - return true; -} - -void ZapInfo::setOverride(ICorDynamicInfo *pOverride, CORINFO_METHOD_HANDLE currentMethod) -{ - UNREACHABLE(); -} - -void ZapInfo::addActiveDependency(CORINFO_MODULE_HANDLE moduleFrom, CORINFO_MODULE_HANDLE moduleTo) -{ - if (IsReadyToRunCompilation()) - return; - - _ASSERT(moduleFrom != moduleTo); - - if (m_pImage->m_pPreloader->CanSkipDependencyActivation(m_currentMethodHandle, moduleFrom, moduleTo)) - { - // No need to add dependency fixup since we will have an unconditional dependency - // already - } - else if (!GetCompileInfo()->IsInCurrentVersionBubble(moduleTo)) - { - } - else - { - ZapImport * pImport = m_pImage->GetImportTable()->GetActiveDependencyImport(moduleFrom, moduleTo); - AppendImport(pImport); - - CORINFO_DEPENDENCY dep; - dep.moduleFrom = moduleFrom; - dep.moduleTo = moduleTo; - } -} - - -InfoAccessType - ZapInfo::constructStringLiteral(CORINFO_MODULE_HANDLE tokenScope, - unsigned metaTok, void **ppValue) -{ - if (m_pEECompileInfo->IsEmptyString(metaTok, tokenScope)) - { - return emptyStringLiteral(ppValue); - } - - ZapImport * pImport = m_pImage->GetImportTable()->GetStringHandleImport(tokenScope, metaTok); - AppendConditionalImport(pImport); - - *ppValue = pImport; - - return IAT_PPVALUE; -} - -InfoAccessType ZapInfo::emptyStringLiteral(void **ppValue) -{ -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - ZapImport * pImport = m_pImage->GetImportTable()->GetStringHandleImport(m_pImage->m_hModule, mdtString); - *ppValue = pImport; - return IAT_PPVALUE; - } -#endif - - *ppValue = m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable, - offsetof(CORCOMPILE_EE_INFO_TABLE, emptyString)); - - return IAT_PPVALUE; -} - -void ZapInfo::recordCallSite(uint32_t instrOffset, CORINFO_SIG_INFO *callSig, CORINFO_METHOD_HANDLE methodHandle) -{ - return; -} - -void ZapInfo::recordRelocation(void *location, void *locationRW, void *target, - uint16_t fRelocType, uint16_t slotNum, int32_t addlDelta) -{ - // Factor slotNum into the location address - switch (fRelocType) - { - case IMAGE_REL_BASED_ABSOLUTE: - case IMAGE_REL_BASED_PTR: -#if defined(TARGET_X86) || defined(TARGET_AMD64) - case IMAGE_REL_BASED_REL32: -#endif // TARGET_X86 || TARGET_AMD64 - location = (PBYTE)location + slotNum; - break; - -#if defined(TARGET_ARM) - case IMAGE_REL_BASED_THUMB_MOV32: - case IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL: - case IMAGE_REL_BASED_THUMB_BRANCH24: - -# ifdef _DEBUG - { - CORJIT_FLAGS jitFlags = m_zapper->m_pOpt->m_compilerFlags; - - if (jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_RELATIVE_CODE_RELOCS)) - { - _ASSERTE(fRelocType == IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL - || fRelocType == IMAGE_REL_BASED_THUMB_BRANCH24); - } - else - { - _ASSERTE(fRelocType == IMAGE_REL_BASED_THUMB_MOV32 - || fRelocType == IMAGE_REL_BASED_THUMB_BRANCH24); - } - } -# endif // _DEBUG - break; -#endif - -#if defined(TARGET_ARM64) - case IMAGE_REL_ARM64_BRANCH26: - case IMAGE_REL_ARM64_PAGEBASE_REL21: - case IMAGE_REL_ARM64_PAGEOFFSET_12A: - break; -#endif - - default: - _ASSERTE(!"Unknown reloc type"); - break; - } - - ZapBlobWithRelocs * knownNodes[] = - { - m_pCode, - m_pColdCode, - m_pROData, - m_pProfileData - }; - - // - // The location of the relocation reported by the JIT has to fall into one of the code or data blobs - // - - CodeRelocation r; - - ZapBlobWithRelocs * pSrcNode = NULL; - for (size_t i = 0; i < _countof(knownNodes); i++) - { - ZapBlobWithRelocs * pNode = knownNodes[i]; - if (pNode == NULL) - continue; - - if (pNode->GetData() <= location && location < pNode->GetData() + pNode->GetSize()) - { - pSrcNode = pNode; - break; - } - } - PREFIX_ASSUME(pSrcNode != NULL); - r.m_pNode = pSrcNode; - r.m_offset = (DWORD)((PBYTE)location - (PBYTE)pSrcNode->GetData()); - - // - // The target of the relocation reported by the JIT can be one of: - // - Inner pointer into into one of the code or data blobs. We can detect this case by searching - // through the blobs. - // - Hardbound target. We can detect this case by searching through all hardbound assemblies. - // - Otherwise, it has to be ZapNode *. - // - - ZapNode * pTargetNode = NULL; - INT32 targetOffset = 0; - for (size_t i = 0; i < _countof(knownNodes); i++) - { - ZapBlobWithRelocs * pNode = knownNodes[i]; - if (pNode == NULL) - continue; - - if (pNode->GetData() <= target && target < pNode->GetData() + pNode->GetSize()) - { - pTargetNode = pNode; - targetOffset = (INT32)((PBYTE)target - (PBYTE)pNode->GetData()); - break; - } - } - - if (pTargetNode != NULL) - { - r.m_pTargetNode = pTargetNode; - } - else - { - // Must be ZapNode otherwise - pTargetNode = (ZapNode *)target; - _ASSERTE(pTargetNode->GetType() != ZapNodeType_Unknown); - r.m_pTargetNode = pTargetNode; - } - - r.m_type = (ZapRelocationType)fRelocType; - - switch (fRelocType) - { - case IMAGE_REL_BASED_ABSOLUTE: - *(UNALIGNED DWORD *)location = (DWORD)targetOffset; - break; - - case IMAGE_REL_BASED_PTR: - *(UNALIGNED TARGET_POINTER_TYPE *)location = (TARGET_POINTER_TYPE)targetOffset; - break; - -#if defined(TARGET_X86) || defined(TARGET_AMD64) - case IMAGE_REL_BASED_REL32: - *(UNALIGNED INT32 *)location = targetOffset + addlDelta; - break; -#endif // TARGET_X86 || TARGET_AMD64 - -#if defined(TARGET_ARM) - case IMAGE_REL_BASED_THUMB_MOV32: - case IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL: - PutThumb2Mov32((UINT16 *)location, targetOffset); - break; - - case IMAGE_REL_BASED_THUMB_BRANCH24: - if (!FitsInThumb2BlRel24(targetOffset)) - ThrowHR(COR_E_OVERFLOW); - PutThumb2BlRel24((UINT16 *)location, targetOffset); - break; -#endif - -#if defined(TARGET_ARM64) - case IMAGE_REL_ARM64_BRANCH26: - if (!FitsInRel28(targetOffset)) - ThrowHR(COR_E_OVERFLOW); - PutArm64Rel28((UINT32 *)location, targetOffset); - break; - case IMAGE_REL_ARM64_PAGEBASE_REL21: - if (!FitsInRel21(targetOffset)) - ThrowHR(COR_E_OVERFLOW); - PutArm64Rel21((UINT32 *)location, targetOffset); - break; - - case IMAGE_REL_ARM64_PAGEOFFSET_12A: - if (!FitsInRel12(targetOffset)) - ThrowHR(COR_E_OVERFLOW); - PutArm64Rel12((UINT32 *)location, targetOffset); - break; -#endif - - default: - _ASSERTE(!"Unknown reloc type"); - break; - } - - if (m_CodeRelocations.IsEmpty()) - { - SIZE_T totalCodeSize = m_pCode->GetSize() + ((m_pColdCode != NULL) ? m_pColdCode->GetSize() : 0); - - // Prealocate relocations (assume that every other pointer may need relocation) - COUNT_T nEstimatedRelocations = (COUNT_T)(totalCodeSize / (2 * TARGET_POINTER_SIZE)); - if (nEstimatedRelocations > 1) - m_CodeRelocations.Preallocate(nEstimatedRelocations); - } - - m_CodeRelocations.Append(r); -} - -WORD ZapInfo::getRelocTypeHint(void * target) -{ -#ifdef TARGET_AMD64 - // There should be no external pointers - return IMAGE_REL_BASED_REL32; -#elif defined(TARGET_ARM) - // Use full 32-bit branch targets when retrying compilation on ARM - if (m_zapper->m_pOpt->m_fNGenLastRetry) - return (WORD)-1; - return IMAGE_REL_BASED_THUMB_BRANCH24; -#elif defined(TARGET_ARM64) - return IMAGE_REL_ARM64_BRANCH26; -#else - // No hints - return (WORD)-1; -#endif -} - -uint32_t ZapInfo::getExpectedTargetArchitecture() -{ - return IMAGE_FILE_MACHINE_NATIVE; -} - -CORINFO_METHOD_HANDLE ZapInfo::GetDelegateCtor(CORINFO_METHOD_HANDLE methHnd, - CORINFO_CLASS_HANDLE clsHnd, - CORINFO_METHOD_HANDLE targetMethodHnd, - DelegateCtorArgs * pCtorData) -{ - // For ReadyToRun, this optimization is done via ZapInfo::getReadyToRunDelegateCtorHelper - if (IsReadyToRunCompilation()) - return methHnd; - - // forward the call to the standard GetDelegateCtor - CORINFO_METHOD_HANDLE delegateCtor = m_pEEJitInfo->GetDelegateCtor(methHnd, clsHnd, targetMethodHnd, pCtorData); - if (delegateCtor != methHnd) - { - if (pCtorData->pArg4) - { - // cannot optimize any wrapper delegate, give up - delegateCtor = methHnd; - } - else if (pCtorData->pArg3) - { - pCtorData->pArg3 = m_pImage->GetWrappers()->GetStub(pCtorData->pArg3); - } - } - return delegateCtor; -} - -void ZapInfo::MethodCompileComplete( - CORINFO_METHOD_HANDLE methHnd) -{ - m_pEEJitInfo->MethodCompileComplete(methHnd); -} - - -// -// ICorStaticInfo -// - -void ZapInfo::getEEInfo(CORINFO_EE_INFO *pEEInfoOut) -{ - m_pEEJitInfo->getEEInfo(pEEInfoOut); -} - -const char16_t * ZapInfo::getJitTimeLogFilename() -{ - return m_pEEJitInfo->getJitTimeLogFilename(); -} - -// -// ICorArgInfo -// - -CORINFO_ARG_LIST_HANDLE ZapInfo::getArgNext(CORINFO_ARG_LIST_HANDLE args) -{ - return m_pEEJitInfo->getArgNext(args); -} - -CorInfoTypeWithMod ZapInfo::getArgType(CORINFO_SIG_INFO* sig, - CORINFO_ARG_LIST_HANDLE args, - CORINFO_CLASS_HANDLE *vcTypeRet) -{ - return m_pEEJitInfo->getArgType(sig, args, vcTypeRet); -} - -CORINFO_CLASS_HANDLE ZapInfo::getArgClass(CORINFO_SIG_INFO* sig, - CORINFO_ARG_LIST_HANDLE args) -{ - return m_pEEJitInfo->getArgClass(sig, args); -} - -CorInfoHFAElemType ZapInfo::getHFAType(CORINFO_CLASS_HANDLE hClass) -{ - return m_pEEJitInfo->getHFAType(hClass); -} - -// -// ICorDebugInfo -// - -void ZapInfo::getBoundaries(CORINFO_METHOD_HANDLE ftn, unsigned int *cILOffsets, - uint32_t **pILOffsets, ICorDebugInfo::BoundaryTypes *implicitBoundaries) -{ - m_pEEJitInfo->getBoundaries(ftn, cILOffsets, pILOffsets, - implicitBoundaries); -} - -void ZapInfo::setBoundaries(CORINFO_METHOD_HANDLE ftn, ULONG32 cMap, - ICorDebugInfo::OffsetMapping *pMap) -{ - _ASSERTE(ftn == m_currentMethodHandle); - - if (cMap == 0) - return; - - m_pOffsetMapping = pMap; - m_iOffsetMapping = cMap; - return; -} - -void ZapInfo::getVars(CORINFO_METHOD_HANDLE ftn, - ULONG32 *cVars, - ICorDebugInfo::ILVarInfo **vars, - bool *extendOthers) -{ - m_pEEJitInfo->getVars(ftn, cVars, vars, extendOthers); -} - -void ZapInfo::setVars(CORINFO_METHOD_HANDLE ftn, - ULONG32 cVars, - ICorDebugInfo::NativeVarInfo * vars) -{ - _ASSERTE(ftn == m_currentMethodHandle); - - if (cVars == 0) - return; - - m_pNativeVarInfo = vars; - m_iNativeVarInfo = cVars; - - return; -} - -void ZapInfo::setPatchpointInfo(PatchpointInfo* patchpointInfo) -{ - // No patchpoint info when prejitting - UNREACHABLE(); -} - -PatchpointInfo* ZapInfo::getOSRInfo(unsigned * ilOffset) -{ - // No patchpoint info when prejitting - UNREACHABLE(); -} - -void * ZapInfo::allocateArray(size_t cBytes) -{ - return new BYTE[cBytes]; -} - -void ZapInfo::freeArray(void *array) -{ - delete [] ((BYTE*) array); -} - -// -// ICorFieldInfo -// - -const char* ZapInfo::getFieldName(CORINFO_FIELD_HANDLE ftn, const char **moduleName) -{ - return m_pEEJitInfo->getFieldName(ftn, moduleName); -} - -CORINFO_CLASS_HANDLE ZapInfo::getFieldClass(CORINFO_FIELD_HANDLE field) -{ - return m_pEEJitInfo->getFieldClass(field); -} - -CorInfoType ZapInfo::getFieldType(CORINFO_FIELD_HANDLE field, - CORINFO_CLASS_HANDLE *structType, - CORINFO_CLASS_HANDLE memberParent) - -{ - return m_pEEJitInfo->getFieldType(field, structType, memberParent); -} - -unsigned ZapInfo::getFieldOffset(CORINFO_FIELD_HANDLE field) -{ - return m_pEEJitInfo->getFieldOffset(field); -} - -void ZapInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken, - CORINFO_METHOD_HANDLE callerHandle, - CORINFO_ACCESS_FLAGS flags, - CORINFO_FIELD_INFO *pResult) -{ - m_pEEJitInfo->getFieldInfo(pResolvedToken, callerHandle, flags, pResult); - -#ifdef FEATURE_READYTORUN_COMPILER - CORINFO_EE_INFO eeInfo; - m_pEEJitInfo->getEEInfo(&eeInfo); - - if (IsReadyToRunCompilation()) - { - if (pResult->accessAllowed != CORINFO_ACCESS_ALLOWED) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Runtime field access checks not supported\n")); - ThrowHR(E_NOTIMPL); - } - - switch (pResult->fieldAccessor) - { - case CORINFO_FIELD_INSTANCE: - { - DWORD dwBaseOffset = (DWORD)-1; - CORCOMPILE_FIXUP_BLOB_KIND fixupKind = m_pImage->GetCompileInfo()->GetFieldBaseOffset(pResolvedToken->hClass, &dwBaseOffset); - - switch (fixupKind) - { - case ENCODE_FIELD_OFFSET: - { - ZapImport * pImport = m_pImage->GetImportTable()->GetFieldImport(ENCODE_FIELD_OFFSET, pResolvedToken->hField, pResolvedToken); - - if (pResult->offset > eeInfo.maxUncheckedOffsetForNullObject / 2) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Cross-module instance fields with large offsets not supported\n")); - ThrowHR(E_NOTIMPL); - } - pResult->offset = 0; - - pResult->fieldAccessor = CORINFO_FIELD_INSTANCE_WITH_BASE; - - pResult->fieldLookup.accessType = IAT_PVALUE; - pResult->fieldLookup.addr = pImport; - - AppendImport(pImport); - } - break; - - case ENCODE_CHECK_FIELD_OFFSET: - { - ZapImport * pImport = m_pImage->GetImportTable()->GetCheckFieldOffsetImport(pResolvedToken->hField, pResolvedToken, pResult->offset); - AppendImport(pImport); - } - break; - - case ENCODE_FIELD_BASE_OFFSET: - { - ZapImport * pImport = m_pImage->GetImportTable()->GetClassImport(ENCODE_FIELD_BASE_OFFSET, pResolvedToken); - - if (pResult->offset > eeInfo.maxUncheckedOffsetForNullObject / 2) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Large objects crossing module boundaries not supported\n")); - ThrowHR(E_NOTIMPL); - } - _ASSERTE(pResult->offset >= dwBaseOffset); - pResult->offset -= dwBaseOffset; - - pResult->fieldAccessor = CORINFO_FIELD_INSTANCE_WITH_BASE; - - pResult->fieldLookup.accessType = IAT_PVALUE; - pResult->fieldLookup.addr = pImport; - - AppendImport(pImport); - } - break; - - case ENCODE_NONE: - break; - - default: - UNREACHABLE_MSG("Unexpected field base fixup"); - } - } - break; - - case CORINFO_FIELD_INSTANCE_HELPER: - case CORINFO_FIELD_INSTANCE_ADDR_HELPER: - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Special instance fields not supported\n")); - ThrowHR(E_NOTIMPL); - break; - - case CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER: - { - if (m_pImage->GetCompileInfo()->IsInCurrentVersionBubble(m_pEEJitInfo->getClassModule(pResolvedToken->hClass))) - { - CORCOMPILE_FIXUP_BLOB_KIND kind; - - switch (pResult->helper) - { - case CORINFO_HELP_GETSHARED_GCSTATIC_BASE: - case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR: - case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS: - kind = ENCODE_STATIC_BASE_GC_HELPER; - break; - case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE: - case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR: - case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS: - kind = ENCODE_STATIC_BASE_NONGC_HELPER; - break; - case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE: - case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR: - case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS: - kind = ENCODE_THREAD_STATIC_BASE_GC_HELPER; - break; - case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE: - case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR: - case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS: - kind = ENCODE_THREAD_STATIC_BASE_NONGC_HELPER; - break; - default: - UNREACHABLE_MSG("Unexpected static helper"); - } - - ZapImport * pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(kind, pResolvedToken->hClass); - - pResult->fieldLookup.accessType = IAT_PVALUE; - pResult->fieldLookup.addr = pImport; - - pResult->helper = CORINFO_HELP_READYTORUN_STATIC_BASE; - } - else - { - ZapImport * pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(ENCODE_FIELD_ADDRESS, pResolvedToken->hField, pResolvedToken); - - pResult->fieldLookup.accessType = IAT_PVALUE; - pResult->fieldLookup.addr = pImport; - - pResult->helper = CORINFO_HELP_READYTORUN_STATIC_BASE; - - pResult->offset = 0; - pResult->fieldFlags &= ~CORINFO_FLG_FIELD_STATIC_IN_HEAP; // The dynamic helper takes care of the unboxing - } - } - break; - - case CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER: - { - // Nothing to do... The generic handle lookup gets embedded in to the codegen - // during the jitting of the field lookup. - // (Note: The generic lookup in R2R is performed by a call to a helper at runtime, not by - // codegen emitted at crossgen time) - // TODO: replace the call to the generic lookup helper and the call to the static helper function - // with a single call to a R2R cell that performs: - // 1) Generic handle lookup - // 2) Computes the statics base address - // 3) Generates a stub for subsequent lookups that includes dictionary access - // (For perf reasons) - } - break; - - case CORINFO_FIELD_STATIC_RVA_ADDRESS: // RVA field at given address - if (m_pEEJitInfo->getClassModule(pResolvedToken->hClass) != m_pImage->m_hModule) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Cross-module RVA static fields not supported\n")); - ThrowHR(E_NOTIMPL); - } - break; - - case CORINFO_FIELD_STATIC_ADDRESS: // field at given address - case CORINFO_FIELD_STATIC_ADDR_HELPER: // static field accessed using address-of helper (argument is FieldDesc *) - case CORINFO_FIELD_STATIC_TLS: - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Rare kinds of static fields not supported\n")); - ThrowHR(E_NOTIMPL); - break; - - case CORINFO_FIELD_INTRINSIC_ZERO: - case CORINFO_FIELD_INTRINSIC_EMPTY_STRING: - case CORINFO_FIELD_INTRINSIC_ISLITTLEENDIAN: - break; - - default: - UNREACHABLE_MSG("Unexpected field acccess type"); - } - } -#endif // FEATURE_READYTORUN_COMPILER -} - -bool ZapInfo::isFieldStatic(CORINFO_FIELD_HANDLE fldHnd) -{ - return m_pEEJitInfo->isFieldStatic(fldHnd); -} - -// -// ICorClassInfo -// - -CorInfoType ZapInfo::asCorInfoType(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->asCorInfoType(cls); -} - -const char* ZapInfo::getClassName(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getClassName(cls); -} - -const char* ZapInfo::getClassNameFromMetadata(CORINFO_CLASS_HANDLE cls, const char** namespaceName) -{ - return m_pEEJitInfo->getClassNameFromMetadata(cls, namespaceName); -} - -CORINFO_CLASS_HANDLE ZapInfo::getTypeInstantiationArgument(CORINFO_CLASS_HANDLE cls, unsigned index) -{ - return m_pEEJitInfo->getTypeInstantiationArgument(cls, index); -} - -const char* ZapInfo::getHelperName(CorInfoHelpFunc func) -{ - return m_pEEJitInfo->getHelperName(func); -} - -int ZapInfo::appendClassName(__deref_inout_ecount(*pnBufLen) char16_t** ppBuf, int* pnBufLen, - CORINFO_CLASS_HANDLE cls, - bool fNamespace, - bool fFullInst, - bool fAssembly) -{ - return m_pEEJitInfo->appendClassName(ppBuf,pnBufLen,cls,fNamespace,fFullInst,fAssembly); -} - -bool ZapInfo::isValueClass(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->isValueClass(cls); -} - -CorInfoInlineTypeCheck ZapInfo::canInlineTypeCheck (CORINFO_CLASS_HANDLE cls, CorInfoInlineTypeCheckSource source) -{ - return m_pEEJitInfo->canInlineTypeCheck(cls, source); -} - -uint32_t ZapInfo::getClassAttribs(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getClassAttribs(cls); -} - -bool ZapInfo::isStructRequiringStackAllocRetBuf(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->isStructRequiringStackAllocRetBuf(cls); -} - -CorInfoInitClassResult ZapInfo::initClass( - CORINFO_FIELD_HANDLE field, - CORINFO_METHOD_HANDLE method, - CORINFO_CONTEXT_HANDLE context) -{ - return m_pEEJitInfo->initClass(field, method, context); -} - -void ZapInfo::classMustBeLoadedBeforeCodeIsRun(CORINFO_CLASS_HANDLE cls) -{ - // This adds an entry to the table of fixups. The table gets iterated later - // to add entries to the delayed fixup list for the code being generated. - m_ClassLoadTable.Load(cls, FALSE); -} - -CORINFO_METHOD_HANDLE ZapInfo::mapMethodDeclToMethodImpl(CORINFO_METHOD_HANDLE methHnd) -{ - return (CORINFO_METHOD_HANDLE)m_pEEJitInfo->mapMethodDeclToMethodImpl(methHnd); -} - -void ZapInfo::methodMustBeLoadedBeforeCodeIsRun(CORINFO_METHOD_HANDLE meth) -{ - // This adds an entry to the table of fixups. The table gets iterated later - // to add entries to the delayed fixup list for the code being generated. - m_MethodLoadTable.Load(meth, FALSE); -} - -CORINFO_CLASS_HANDLE ZapInfo::getBuiltinClass(CorInfoClassId classId) -{ - return m_pEEJitInfo->getBuiltinClass(classId); -} - -CorInfoType ZapInfo::getTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getTypeForPrimitiveValueClass(cls); -} - -CorInfoType ZapInfo::getTypeForPrimitiveNumericClass(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getTypeForPrimitiveNumericClass(cls); -} - -bool ZapInfo::canCast(CORINFO_CLASS_HANDLE child, - CORINFO_CLASS_HANDLE parent) -{ - return m_pEEJitInfo->canCast(child, parent); -} - -bool ZapInfo::areTypesEquivalent(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) -{ - return m_pEEJitInfo->areTypesEquivalent(cls1, cls2); -} - -TypeCompareState ZapInfo::compareTypesForCast(CORINFO_CLASS_HANDLE fromClass, CORINFO_CLASS_HANDLE toClass) -{ - return m_pEEJitInfo->compareTypesForCast(fromClass, toClass); -} - -TypeCompareState ZapInfo::compareTypesForEquality(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) -{ - return m_pEEJitInfo->compareTypesForEquality(cls1, cls2); -} - -CORINFO_CLASS_HANDLE ZapInfo::mergeClasses( - CORINFO_CLASS_HANDLE cls1, - CORINFO_CLASS_HANDLE cls2) -{ - return m_pEEJitInfo->mergeClasses(cls1, cls2); -} - -bool ZapInfo::isMoreSpecificType( - CORINFO_CLASS_HANDLE cls1, - CORINFO_CLASS_HANDLE cls2) -{ - return m_pEEJitInfo->isMoreSpecificType(cls1, cls2); -} - -CORINFO_CLASS_HANDLE ZapInfo::getParentType ( - CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getParentType(cls); -} - -CorInfoType ZapInfo::getChildType ( - CORINFO_CLASS_HANDLE clsHnd, - CORINFO_CLASS_HANDLE *clsRet) -{ - return m_pEEJitInfo->getChildType(clsHnd, clsRet); -} - -bool ZapInfo::satisfiesClassConstraints( - CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->satisfiesClassConstraints(cls); -} - -bool ZapInfo::isSDArray(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->isSDArray(cls); -} - -unsigned ZapInfo::getArrayRank(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getArrayRank(cls); -} - -void * ZapInfo::getArrayInitializationData(CORINFO_FIELD_HANDLE field, uint32_t size) -{ - if (m_pEEJitInfo->getClassModule(m_pEEJitInfo->getFieldClass(field)) != m_pImage->m_hModule) - return NULL; - - void * arrayData = m_pEEJitInfo->getArrayInitializationData(field, size); - if (!arrayData) - return NULL; - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - return m_pImage->m_pILMetaData->GetRVAField(arrayData); -#endif - - return (void *) m_pImage->GetWrappers()->GetGenericHandle(CORINFO_GENERIC_HANDLE(arrayData)); -} - -CorInfoIsAccessAllowedResult ZapInfo::canAccessClass( CORINFO_RESOLVED_TOKEN * pResolvedToken, - CORINFO_METHOD_HANDLE callerHandle, - CORINFO_HELPER_DESC *throwHelper) -{ - CorInfoIsAccessAllowedResult ret = m_pEEJitInfo->canAccessClass(pResolvedToken, callerHandle, throwHelper); - -#ifdef FEATURE_READYTORUN_COMPILER - if (ret != CORINFO_ACCESS_ALLOWED) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Runtime access checks not supported\n")); - ThrowHR(E_NOTIMPL); - } -#endif - - return ret; -} - - -CORINFO_MODULE_HANDLE ZapInfo::getClassModule(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getClassModule(cls); -} - -CORINFO_ASSEMBLY_HANDLE ZapInfo::getModuleAssembly(CORINFO_MODULE_HANDLE mod) -{ - return m_pEEJitInfo->getModuleAssembly(mod); -} - -const char* ZapInfo::getAssemblyName(CORINFO_ASSEMBLY_HANDLE assem) -{ - return m_pEEJitInfo->getAssemblyName(assem); -} - -void* ZapInfo::LongLifetimeMalloc(size_t sz) -{ - return m_pEEJitInfo->LongLifetimeMalloc(sz); -} - -void ZapInfo::LongLifetimeFree(void* obj) -{ - return m_pEEJitInfo->LongLifetimeFree(obj); -} - -size_t ZapInfo::getClassModuleIdForStatics(CORINFO_CLASS_HANDLE cls, CORINFO_MODULE_HANDLE *pModule, void **ppIndirection) -{ - if (IsReadyToRunCompilation()) - { - _ASSERTE(!"getClassModuleIdForStatics"); - ThrowHR(E_NOTIMPL); - } - - _ASSERTE(ppIndirection != NULL); - _ASSERTE(pModule == NULL); - CORINFO_MODULE_HANDLE module; - size_t moduleId = m_pEEJitInfo->getClassModuleIdForStatics(cls, &module, ppIndirection); - CORINFO_MODULE_HANDLE pzmModule = m_pImage->m_pPreloader->GetPreferredZapModuleForClassHandle(cls); - - if (module == pzmModule) - { - // Use the module for the moduleid lookup if we have to do so. This causes us to have fewer fixups than - // if the fixups were exclusively based on the moduleforstatics lookup - cls = NULL; - - - if (module == m_pImage->m_hModule) - { - // If the handle is the module we are currently ngening, we use - // an indirection to the slot where the module pointer gets - // stored when the module gets reloaded. - - *ppIndirection = PVOID(m_pImage->GetWrappers()->GetModuleIDHandle(module)); - return NULL; - } - - // Fall through to regular import - } - else - { - // Use the class for the moduleid lookup. This causes us to generate a fixup for the ModuleForStatics explicitly. - module = NULL; - } - - ZapImport * pImport = m_pImage->GetImportTable()->GetModuleDomainIdImport(module, cls); - AppendConditionalImport(pImport); - - *ppIndirection = pImport; - return NULL; -} - -unsigned ZapInfo::getClassSize(CORINFO_CLASS_HANDLE cls) -{ - DWORD size = m_pEEJitInfo->getClassSize(cls); - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - if (m_pEECompileInfo->NeedsTypeLayoutCheck(cls)) - { - ZapImport * pImport = m_pImage->GetImportTable()->GetCheckTypeLayoutImport(cls); - AppendImport(pImport); - - m_ClassLoadTable.Load(cls, TRUE); - } - } -#endif - - return size; -} - -unsigned ZapInfo::getHeapClassSize(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getHeapClassSize(cls); -} - -bool ZapInfo::canAllocateOnStack(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->canAllocateOnStack(cls); -} - -unsigned ZapInfo::getClassAlignmentRequirement(CORINFO_CLASS_HANDLE cls, bool fDoubleAlignHint) -{ - return m_pEEJitInfo->getClassAlignmentRequirement(cls, fDoubleAlignHint); -} - -CORINFO_FIELD_HANDLE ZapInfo::getFieldInClass(CORINFO_CLASS_HANDLE clsHnd, INT num) -{ - return m_pEEJitInfo->getFieldInClass(clsHnd,num); -} - -mdMethodDef ZapInfo::getMethodDefFromMethod(CORINFO_METHOD_HANDLE hMethod) -{ - return m_pEEJitInfo->getMethodDefFromMethod(hMethod); -} - -bool ZapInfo::checkMethodModifier(CORINFO_METHOD_HANDLE hMethod, LPCSTR modifier, bool fOptional) -{ - return m_pEEJitInfo->checkMethodModifier(hMethod, modifier, fOptional); -} - -unsigned ZapInfo::getClassGClayout(CORINFO_CLASS_HANDLE cls, BYTE *gcPtrs) -{ - return m_pEEJitInfo->getClassGClayout(cls, gcPtrs); -} - -// returns the enregister info for a struct based on type of fields, alignment, etc.. -bool ZapInfo::getSystemVAmd64PassStructInRegisterDescriptor( - /*IN*/ CORINFO_CLASS_HANDLE _structHnd, - /*OUT*/ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr) -{ - return m_pEEJitInfo->getSystemVAmd64PassStructInRegisterDescriptor(_structHnd, structPassInRegDescPtr); -} - -unsigned ZapInfo::getClassNumInstanceFields(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getClassNumInstanceFields(cls); -} - -CorInfoHelpFunc ZapInfo::getNewHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, bool * pHasSideEffects) -{ - if (!IsReadyToRunCompilation()) - { - classMustBeLoadedBeforeCodeIsRun(pResolvedToken->hClass); - } - - CorInfoHelpFunc helper = m_pEEJitInfo->getNewHelper(pResolvedToken, callerHandle, pHasSideEffects); - - return IsReadyToRunCompilation() ? CORINFO_HELP_NEWFAST : helper; -} - -CorInfoHelpFunc ZapInfo::getSharedCCtorHelper(CORINFO_CLASS_HANDLE clsHnd) -{ - return m_pEEJitInfo->getSharedCCtorHelper(clsHnd); -} - -CORINFO_CLASS_HANDLE ZapInfo::getTypeForBox(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getTypeForBox(cls); -} - -CorInfoHelpFunc ZapInfo::getBoxHelper(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getBoxHelper(cls); -} - -CorInfoHelpFunc ZapInfo::getUnBoxHelper(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getUnBoxHelper(cls); -} - -CorInfoHelpFunc ZapInfo::getCastingHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fThrowing) -{ - if (IsReadyToRunCompilation()) - return (fThrowing ? CORINFO_HELP_CHKCASTANY : CORINFO_HELP_ISINSTANCEOFANY); - - return m_pEEJitInfo->getCastingHelper(pResolvedToken, fThrowing); -} - -CorInfoHelpFunc ZapInfo::getNewArrHelper(CORINFO_CLASS_HANDLE arrayCls) -{ - if (IsReadyToRunCompilation()) - return CORINFO_HELP_NEWARR_1_DIRECT; - - return m_pEEJitInfo->getNewArrHelper(arrayCls); -} - -bool ZapInfo::getReadyToRunHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken, - CORINFO_LOOKUP_KIND * pGenericLookupKind, - CorInfoHelpFunc id, - CORINFO_CONST_LOOKUP * pLookup) -{ -#ifdef FEATURE_READYTORUN_COMPILER - _ASSERTE(IsReadyToRunCompilation()); - - ZapImport * pImport = NULL; - - bool ignoredSideEffects = false; - switch (id) - { - case CORINFO_HELP_READYTORUN_NEW: - // Call CEEInfo::getNewHelper to validate the request (e.g., check for abstract class). - m_pEEJitInfo->getNewHelper(pResolvedToken, m_currentMethodHandle, &ignoredSideEffects); - - if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0) - return false; // Requires runtime lookup. - pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(ENCODE_NEW_HELPER, pResolvedToken->hClass); - break; - - case CORINFO_HELP_READYTORUN_NEWARR_1: - if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0) - return false; // Requires runtime lookup. - pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(ENCODE_NEW_ARRAY_HELPER, pResolvedToken->hClass); - break; - - case CORINFO_HELP_READYTORUN_ISINSTANCEOF: - if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0) - return false; // Requires runtime lookup. - pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(ENCODE_ISINSTANCEOF_HELPER, pResolvedToken->hClass); - break; - - case CORINFO_HELP_READYTORUN_CHKCAST: - if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0) - return false; // Requires runtime lookup. - pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(ENCODE_CHKCAST_HELPER, pResolvedToken->hClass); - break; - - case CORINFO_HELP_READYTORUN_STATIC_BASE: - if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0) - return false; // Requires runtime lookup. - if (m_pImage->GetCompileInfo()->IsInCurrentVersionBubble(m_pEEJitInfo->getClassModule(pResolvedToken->hClass))) - { - pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(ENCODE_CCTOR_TRIGGER, pResolvedToken->hClass); - } - else - { - // READYTORUN: FUTURE: Cross-module static cctor triggers - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Cross-module static cctor triggers not supported\n")); - ThrowHR(E_NOTIMPL); - } - break; - - case CORINFO_HELP_READYTORUN_GENERIC_HANDLE: - _ASSERTE(pGenericLookupKind != NULL && pGenericLookupKind->needsRuntimeLookup); - if (pGenericLookupKind->runtimeLookupKind == CORINFO_LOOKUP_METHODPARAM) - { - pImport = m_pImage->GetImportTable()->GetDictionaryLookupCell( - ENCODE_DICTIONARY_LOOKUP_METHOD, m_currentMethodHandle, pResolvedToken, pGenericLookupKind); - } - else if (pGenericLookupKind->runtimeLookupKind == CORINFO_LOOKUP_THISOBJ) - { - pImport = m_pImage->GetImportTable()->GetDictionaryLookupCell( - ENCODE_DICTIONARY_LOOKUP_THISOBJ, m_currentMethodHandle, pResolvedToken, pGenericLookupKind); - } - else - { - _ASSERTE(pGenericLookupKind->runtimeLookupKind == CORINFO_LOOKUP_CLASSPARAM); - pImport = m_pImage->GetImportTable()->GetDictionaryLookupCell( - ENCODE_DICTIONARY_LOOKUP_TYPE, m_currentMethodHandle, pResolvedToken, pGenericLookupKind); - } - break; - - default: - _ASSERTE(false); - ThrowHR(E_NOTIMPL); - } - - pLookup->accessType = IAT_PVALUE; - pLookup->addr = pImport; - return true; -#else - return false; -#endif -} - -void ZapInfo::getReadyToRunDelegateCtorHelper( - CORINFO_RESOLVED_TOKEN * pTargetMethod, - CORINFO_CLASS_HANDLE delegateType, - CORINFO_LOOKUP * pLookup - ) -{ -#ifdef FEATURE_READYTORUN_COMPILER - _ASSERTE(IsReadyToRunCompilation()); - pLookup->lookupKind.needsRuntimeLookup = false; - pLookup->constLookup.accessType = IAT_PVALUE; - pLookup->constLookup.addr = m_pImage->GetImportTable()->GetDynamicHelperCell( - (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_DELEGATE_CTOR), pTargetMethod->hMethod, pTargetMethod, delegateType); -#endif -} - - -// -// ICorModuleInfo -// - -//----------------------------------------------------------------------------- -void ZapInfo::resolveToken(CORINFO_RESOLVED_TOKEN * pResolvedToken) -{ - m_pEEJitInfo->resolveToken(pResolvedToken); -} - -//----------------------------------------------------------------------------- -bool ZapInfo::tryResolveToken(CORINFO_RESOLVED_TOKEN * pResolvedToken) -{ - return m_pEEJitInfo->tryResolveToken(pResolvedToken); -} - -//----------------------------------------------------------------------------- -void ZapInfo::findSig(CORINFO_MODULE_HANDLE tokenScope, - unsigned sigTOK, - CORINFO_CONTEXT_HANDLE tokenContext, - CORINFO_SIG_INFO *sig) -{ - m_pEEJitInfo->findSig(tokenScope, sigTOK, tokenContext, sig); -} - -void ZapInfo::findCallSiteSig(CORINFO_MODULE_HANDLE tokenScope, - unsigned methTOK, - CORINFO_CONTEXT_HANDLE tokenContext, CORINFO_SIG_INFO *sig) -{ - m_pEEJitInfo->findCallSiteSig(tokenScope, methTOK, tokenContext, sig); -} - -size_t ZapInfo::findNameOfToken(CORINFO_MODULE_HANDLE tokenScope, - unsigned token, - __out_ecount (FQNameCapacity) char * szFQName, - size_t FQNameCapacity) -{ - return m_pEEJitInfo->findNameOfToken(tokenScope, token, szFQName, FQNameCapacity); -} - -bool ZapInfo::isValidToken ( - CORINFO_MODULE_HANDLE tokenScope, - unsigned token) -{ - return m_pEEJitInfo->isValidToken(tokenScope, token); -} - -bool ZapInfo::isValidStringRef ( - CORINFO_MODULE_HANDLE tokenScope, - unsigned token) -{ - return m_pEEJitInfo->isValidStringRef(tokenScope, token); -} - -const char16_t* ZapInfo::getStringLiteral ( - CORINFO_MODULE_HANDLE tokenScope, - unsigned token, - int* length) -{ - return m_pEEJitInfo->getStringLiteral(tokenScope, token, length); -} - -// -// ICorMethodInfo -// - -const char* ZapInfo::getMethodName(CORINFO_METHOD_HANDLE ftn, const char **moduleName) -{ - return m_pEEJitInfo->getMethodName(ftn, moduleName); -} - -const char* ZapInfo::getMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftn, const char **className, const char** namespaceName, const char **enclosingClassName) -{ - return m_pEEJitInfo->getMethodNameFromMetadata(ftn, className, namespaceName, enclosingClassName); -} - -unsigned ZapInfo::getMethodHash(CORINFO_METHOD_HANDLE ftn) -{ - return m_pEEJitInfo->getMethodHash(ftn); -} - -bool ZapInfo::isJitIntrinsic(CORINFO_METHOD_HANDLE ftn) -{ - return m_pEEJitInfo->isJitIntrinsic(ftn); -} - -uint32_t ZapInfo::getMethodAttribs(CORINFO_METHOD_HANDLE ftn) -{ - DWORD result = m_pEEJitInfo->getMethodAttribs(ftn); - return FilterNamedIntrinsicMethodAttribs(this, result, ftn, m_pEEJitInfo); -} - -void ZapInfo::setMethodAttribs(CORINFO_METHOD_HANDLE ftn, CorInfoMethodRuntimeFlags attribs) -{ - m_pEEJitInfo->setMethodAttribs(ftn, attribs); -} - -void ZapInfo::getMethodSig(CORINFO_METHOD_HANDLE ftn, CORINFO_SIG_INFO *sig,CORINFO_CLASS_HANDLE memberParent) -{ - m_pEEJitInfo->getMethodSig(ftn, sig, memberParent); -} - -bool ZapInfo::getMethodInfo(CORINFO_METHOD_HANDLE ftn,CORINFO_METHOD_INFO* info) -{ - bool result = m_pImage->m_pPreloader->GetMethodInfo(m_currentMethodToken, ftn, info); - info->regionKind = m_pImage->GetCurrentRegionKind(); - return result; -} - -CorInfoInline ZapInfo::canInline(CORINFO_METHOD_HANDLE caller, - CORINFO_METHOD_HANDLE callee, - uint32_t* pRestrictions) -{ - return m_pEEJitInfo->canInline(caller, callee, pRestrictions); - -} - -void ZapInfo::reportInliningDecision (CORINFO_METHOD_HANDLE inlinerHnd, - CORINFO_METHOD_HANDLE inlineeHnd, - CorInfoInline inlineResult, - const char * reason) -{ - if (!dontInline(inlineResult) && inlineeHnd != NULL) - { - // We deliberately report m_currentMethodHandle (not inlinerHnd) as inliner, because - // if m_currentMethodHandle != inlinerHnd, it simply means that inlinerHnd is intermediate link - // in inlining into m_currentMethodHandle, and we have no interest to track those intermediate links now. - m_pImage->m_pPreloader->ReportInlining(m_currentMethodHandle, inlineeHnd); - } - return m_pEEJitInfo->reportInliningDecision(inlinerHnd, inlineeHnd, inlineResult, reason); -} - -bool ZapInfo::canTailCall(CORINFO_METHOD_HANDLE caller, - CORINFO_METHOD_HANDLE declaredCallee, - CORINFO_METHOD_HANDLE exactCallee, - bool fIsTailPrefix) -{ -#ifdef FEATURE_READYTORUN_COMPILER - // READYTORUN: FUTURE: Delay load fixups for tailcalls - if (IsReadyToRunCompilation()) - { - if (fIsTailPrefix) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Explicit tailcalls not supported\n")); - ThrowHR(E_NOTIMPL); - } - - return false; - } -#endif - - return m_pEEJitInfo->canTailCall(caller, declaredCallee, exactCallee, fIsTailPrefix); -} - -void ZapInfo::reportTailCallDecision(CORINFO_METHOD_HANDLE callerHnd, - CORINFO_METHOD_HANDLE calleeHnd, - bool fIsTailPrefix, - CorInfoTailCall tailCallResult, - const char * reason) -{ - return m_pEEJitInfo->reportTailCallDecision(callerHnd, calleeHnd, fIsTailPrefix, tailCallResult, reason); -} - -void ZapInfo::getEHinfo(CORINFO_METHOD_HANDLE ftn, - unsigned EHnumber, CORINFO_EH_CLAUSE* clause) -{ - m_pEEJitInfo->getEHinfo(ftn, EHnumber, clause); -} - -CORINFO_CLASS_HANDLE ZapInfo::getMethodClass(CORINFO_METHOD_HANDLE method) -{ - return m_pEEJitInfo->getMethodClass(method); -} - -CORINFO_MODULE_HANDLE ZapInfo::getMethodModule(CORINFO_METHOD_HANDLE method) -{ - return m_pEEJitInfo->getMethodModule(method); -} - -void ZapInfo::getMethodVTableOffset(CORINFO_METHOD_HANDLE method, - unsigned * pOffsetOfIndirection, - unsigned * pOffsetAfterIndirection, - bool * isRelative) -{ - m_pEEJitInfo->getMethodVTableOffset(method, pOffsetOfIndirection, pOffsetAfterIndirection, isRelative); -} - -bool ZapInfo::resolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO * info) -{ - bool result = m_pEEJitInfo->resolveVirtualMethod(info); - if (result) - { - // First, cons up a suitable resolved token. - CORINFO_RESOLVED_TOKEN derivedResolvedToken = {}; - info->resolvedTokenDevirtualizedMethod = derivedResolvedToken; - - info->resolvedTokenDevirtualizedMethod.tokenScope = getMethodModule(info->devirtualizedMethod); - info->resolvedTokenDevirtualizedMethod.tokenContext = MAKE_METHODCONTEXT(info->devirtualizedMethod); - info->resolvedTokenDevirtualizedMethod.token = getMethodDefFromMethod(info->devirtualizedMethod); - info->resolvedTokenDevirtualizedMethod.tokenType = CORINFO_TOKENKIND_DevirtualizedMethod; - info->resolvedTokenDevirtualizedMethod.hClass = (CORINFO_CLASS_HANDLE)((size_t)info->exactContext & ~CORINFO_CONTEXTFLAGS_MASK);; - info->resolvedTokenDevirtualizedMethod.hMethod = info->devirtualizedMethod; - - // Then, if the method is on a valuetype, cons up a unboxed method resolution stub - info->resolvedTokenDevirtualizedUnboxedMethod = derivedResolvedToken; - bool unused; - CORINFO_METHOD_HANDLE unboxedMethod = getUnboxedEntry(info->devirtualizedMethod, &unused); - if (unboxedMethod != NULL) - { - info->resolvedTokenDevirtualizedUnboxedMethod.tokenScope = getMethodModule(unboxedMethod); - info->resolvedTokenDevirtualizedUnboxedMethod.tokenContext = MAKE_METHODCONTEXT(unboxedMethod); - info->resolvedTokenDevirtualizedUnboxedMethod.token = getMethodDefFromMethod(unboxedMethod); - info->resolvedTokenDevirtualizedUnboxedMethod.tokenType = CORINFO_TOKENKIND_DevirtualizedMethod; - info->resolvedTokenDevirtualizedUnboxedMethod.hClass = (CORINFO_CLASS_HANDLE)((size_t)info->exactContext & ~CORINFO_CONTEXTFLAGS_MASK);; - info->resolvedTokenDevirtualizedUnboxedMethod.hMethod = unboxedMethod; - } - } - - return result; -} - -CORINFO_METHOD_HANDLE ZapInfo::getUnboxedEntry( - CORINFO_METHOD_HANDLE ftn, - bool* requiresInstMethodTableArg) -{ - return m_pEEJitInfo->getUnboxedEntry(ftn, requiresInstMethodTableArg); -} - -CORINFO_CLASS_HANDLE ZapInfo::getDefaultComparerClass( - CORINFO_CLASS_HANDLE elemType) -{ - return m_pEEJitInfo->getDefaultComparerClass(elemType); -} - -CORINFO_CLASS_HANDLE ZapInfo::getDefaultEqualityComparerClass( - CORINFO_CLASS_HANDLE elemType) -{ - return m_pEEJitInfo->getDefaultEqualityComparerClass(elemType); -} - -void ZapInfo::expandRawHandleIntrinsic( - CORINFO_RESOLVED_TOKEN * pResolvedToken, - CORINFO_GENERICHANDLE_RESULT * pResult) -{ - m_pEEJitInfo->expandRawHandleIntrinsic(pResolvedToken, pResult); -} - -CorInfoIntrinsics ZapInfo::getIntrinsicID(CORINFO_METHOD_HANDLE method, - bool * pMustExpand) -{ - return m_pEEJitInfo->getIntrinsicID(method, pMustExpand); -} - -bool ZapInfo::isIntrinsicType(CORINFO_CLASS_HANDLE classHnd) -{ - return m_pEEJitInfo->isIntrinsicType(classHnd); -} - -CorInfoCallConvExtension ZapInfo::getUnmanagedCallConv(CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig, bool* pSuppressGCTransition) -{ - return m_pEEJitInfo->getUnmanagedCallConv(method, sig, pSuppressGCTransition); -} - -bool ZapInfo::pInvokeMarshalingRequired(CORINFO_METHOD_HANDLE method, - CORINFO_SIG_INFO* sig) -{ -#if defined(TARGET_X86) && defined(TARGET_UNIX) - // FUTURE ReadyToRun: x86 pinvoke stubs on Unix platforms - if (IsReadyToRunCompilation()) - return TRUE; -#endif - - if (IsReadyToRunCompilation() && method != NULL && !m_pImage->GetCompileInfo()->IsInCurrentVersionBubble(m_pEEJitInfo->getMethodModule(method))) - { - // FUTURE: ZapSig::EncodeMethod does not yet handle cross module references for ReadyToRun - // See zapsig.cpp around line 1217. - // Once this is implemented, we'll be able to inline pinvokes of extern methods declared in other modules (Ex: PresentationCore.dll) - return TRUE; - } - - return m_pEEJitInfo->pInvokeMarshalingRequired(method, sig); -} - -LPVOID ZapInfo::GetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig, - void ** ppIndirection) -{ - return getVarArgsHandle(szMetaSig, ppIndirection); -} - -bool ZapInfo::canGetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig) -{ - return canGetVarArgsHandle(szMetaSig); -} - -bool ZapInfo::satisfiesMethodConstraints( - CORINFO_CLASS_HANDLE parent, - CORINFO_METHOD_HANDLE method) -{ - return m_pEEJitInfo->satisfiesMethodConstraints(parent, method); -} - - -bool ZapInfo::isCompatibleDelegate( - CORINFO_CLASS_HANDLE objCls, - CORINFO_CLASS_HANDLE methodParentCls, - CORINFO_METHOD_HANDLE method, - CORINFO_CLASS_HANDLE delegateCls, - bool* pfIsOpenDelegate) -{ - return m_pEEJitInfo->isCompatibleDelegate(objCls, methodParentCls, method, delegateCls, pfIsOpenDelegate); -} - -// -// ICorErrorInfo -// - -HRESULT ZapInfo::GetErrorHRESULT(struct _EXCEPTION_POINTERS *pExceptionPointers) -{ - return m_pEEJitInfo->GetErrorHRESULT(pExceptionPointers); -} - -uint32_t ZapInfo::GetErrorMessage(__in_ecount(bufferLength) char16_t* buffer, uint32_t bufferLength) -{ - return m_pEEJitInfo->GetErrorMessage(buffer, bufferLength); -} - -int ZapInfo::FilterException(struct _EXCEPTION_POINTERS *pExceptionPointers) -{ - // Continue unwinding if fatal error was hit. - if (FAILED(g_hrFatalError)) - return EXCEPTION_CONTINUE_SEARCH; - - return m_pEEJitInfo->FilterException(pExceptionPointers); -} - -void ZapInfo::HandleException(struct _EXCEPTION_POINTERS *pExceptionPointers) -{ - m_pEEJitInfo->HandleException(pExceptionPointers); -} - -void ZapInfo::ThrowExceptionForJitResult(HRESULT result) -{ - m_pEEJitInfo->ThrowExceptionForJitResult(result); -} -void ZapInfo::ThrowExceptionForHelper(const CORINFO_HELPER_DESC * throwHelper) -{ - m_pEEJitInfo->ThrowExceptionForHelper(throwHelper); -} - -template<> void LoadTable::EmitLoadFixups(CORINFO_METHOD_HANDLE currentMethodHandle, ZapInfo * pZapInfo) -{ - // - // Find all of our un-fixed entries, and emit a restore fixup for each of them. - // Note that we don't need a restore fixups for prerestored classes. - // - - InlineSArray unfixed; - - for (LoadEntryHashTable::Iterator i = m_entries.Begin(), end = m_entries.End(); i != end; i++) - { - if (i->order == -1 - || m_pModule->m_pPreloader->CanPrerestoreEmbedClassHandle(i->handle) - // @TODO: Skip transitive closure of currentMethodHandle (parents, instantiations, etc.) - || m_pModule->GetJitInfo()->getMethodClass(currentMethodHandle) == i->handle) - continue; - - unfixed.Append(*i); - } - - // - // Now clear the table. - // - - m_entries.RemoveAll(); - - if (unfixed.IsEmpty()) - return; - - // Save the fixups in the order they got emited for determinism - qsort(&unfixed[0], unfixed.GetCount(), sizeof(LoadEntry), LoadEntryCmp); - - for(COUNT_T j = 0; j < unfixed.GetCount(); j++) - { - CORINFO_CLASS_HANDLE handle = unfixed[j].handle; - m_pModule->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(handle); - ZapImport * pImport = m_pModule->GetImportTable()->GetClassHandleImport(handle); - pZapInfo->AppendImport(pImport); - } -} - - -template<> void LoadTable::EmitLoadFixups(CORINFO_METHOD_HANDLE currentMethodHandle, ZapInfo * pZapInfo) -{ - // - // Find all of our un-fixed entries, and emit a restore fixup for each of them. - // Note that we don't need a restore fixups for prerestored methods. - // - - InlineSArray unfixed; - - for (LoadEntryHashTable::Iterator i = m_entries.Begin(), end = m_entries.End(); i != end; i++) - { - if (i->order == -1 - || m_pModule->m_pPreloader->CanPrerestoreEmbedMethodHandle(i->handle) - || currentMethodHandle == i->handle) - continue; - - unfixed.Append(*i); - } - - // - // Now clear the table. - // - - m_entries.RemoveAll(); - - if (unfixed.IsEmpty()) - return; - - // Save the fixups in the order they got emited for determinism - qsort(&unfixed[0], unfixed.GetCount(), sizeof(LoadEntry), LoadEntryCmp); - - for(COUNT_T j = 0; j < unfixed.GetCount(); j++) - { - CORINFO_METHOD_HANDLE handle = unfixed[j].handle; - m_pModule->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(handle); - ZapImport * pImport = m_pModule->GetImportTable()->GetMethodHandleImport(handle); - pZapInfo->AppendImport(pImport); - } -} - -BOOL ZapInfo::CurrentMethodHasProfileData() -{ - WRAPPER_NO_CONTRACT; - UINT32 size; - ICorJitInfo::PgoInstrumentationSchema * pSchema; - BYTE* pData; - ICorJitInfo::PgoSource pgoSource; - return SUCCEEDED(getPgoInstrumentationResults(m_currentMethodHandle, &pSchema, &size, &pData, &pgoSource)); -} - diff --git a/src/coreclr/zap/zapinfo.h b/src/coreclr/zap/zapinfo.h deleted file mode 100644 index 2731bdc8954d10..00000000000000 --- a/src/coreclr/zap/zapinfo.h +++ /dev/null @@ -1,288 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapInfo.h -// - -// -// JIT-EE interface for zapping -// -// ====================================================================================== - -#ifndef __ZAPINFO_H__ -#define __ZAPINFO_H__ - -#include "zapcode.h" - -class ZapInfo; -struct InlineContext; - -// The compiled code often implicitly needs fixups for various subtle reasons. -// We only emit explict fixups while compiling the method, while collecting -// implicit fixups in the LoadTable. At the end of compiling, we expect -// many of the LoadTable entries to be subsumed by the explicit entries -// and will not need to be emitted. -// This is also used to detect duplicate explicit fixups for the same type. - -template -class LoadTable -{ -private: - ZapImage *m_pModule; - - struct LoadEntry - { - HandleType handle; - int order; // -1 = fixed - }; - - static int __cdecl LoadEntryCmp(const void* a_, const void* b_) - { - return ((LoadEntry*)a_)->order - ((LoadEntry*)b_)->order; - } - - class LoadEntryTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef typename NoRemoveSHashTraits >::count_t count_t; - typedef typename NoRemoveSHashTraits >::element_t element_t; - typedef HandleType key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e.handle; - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return k1 == k2; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(size_t)k; - } - - static const element_t Null() { LIMITED_METHOD_CONTRACT; LoadEntry e; e.handle = NULL; e.order = 0; return e; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return (e.handle == NULL); } - }; - - typedef SHash LoadEntryHashTable; - - LoadEntryHashTable m_entries; - -public: - LoadTable(ZapImage *pModule) - : m_pModule(pModule) - { - } - - // fixed=TRUE if the caller can guarantee that type will be fixed up because - // of some implicit fixup. In this case, we track 'handle' only to avoid - // duplicates and will not actually emit an explicit fixup for 'handle' - // - // fixed=FALSE if the caller needs an explicit fixup. We will emit an - // explicit fixup for 'handle' if there are no other implicit fixups. - - void Load(HandleType handle, BOOL fixed) - { - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - } - CONTRACTL_END; - - const LoadEntry *result = m_entries.LookupPtr(handle); - - if (result != NULL) - { - if (fixed) - ((LoadEntry*)result)->order = -1; - return; - } - - LoadEntry newEntry; - - newEntry.handle = handle; - newEntry.order = fixed ? -1 : m_entries.GetCount(); - - m_entries.Add(newEntry); - } - - void EmitLoadFixups(CORINFO_METHOD_HANDLE currentMethodHandle, ZapInfo * pZapInfo); -}; - -// Declare some specializations of EmitLoadFixups(). -template<> void LoadTable::EmitLoadFixups(CORINFO_METHOD_HANDLE currentMethodHandle, ZapInfo * pZapInfo); -template<> void LoadTable::EmitLoadFixups(CORINFO_METHOD_HANDLE currentMethodHandle, ZapInfo * pZapInfo); - - -class ZapInfo - : public ICorJitInfo -{ - friend class ZapImage; - - // Owning ZapImage - ZapImage * m_pImage; - - Zapper * m_zapper; - ICorDynamicInfo * m_pEEJitInfo; - ICorCompileInfo * m_pEECompileInfo; - - // Current method being compiled; it is non-nil only for - // method defs whose IL is in this module and (for generic code) - // have instantiation. It is also nil for IL_STUBs. - mdMethodDef m_currentMethodToken; - CORINFO_METHOD_HANDLE m_currentMethodHandle; - CORINFO_METHOD_INFO m_currentMethodInfo; - - // m_currentMethodModule==m_hModule except for generic types/methods - // defined in another assembly but instantiated in the current assembly. - CORINFO_MODULE_HANDLE m_currentMethodModule; - - unsigned m_currentMethodProfilingDataFlags; - - // Debug information reported by the JIT compiler for the current method - ICorDebugInfo::NativeVarInfo *m_pNativeVarInfo; - ULONG32 m_iNativeVarInfo; - ICorDebugInfo::OffsetMapping *m_pOffsetMapping; - ULONG32 m_iOffsetMapping; - - BYTE * m_pGCInfo; - SIZE_T m_cbGCInfo; - - - ZapBlobWithRelocs * m_pCode; - ZapBlobWithRelocs * m_pColdCode; - ZapBlobWithRelocs * m_pROData; - -#ifdef FEATURE_EH_FUNCLETS - // Unwind info of the main method body. It will get merged with GC info. - BYTE * m_pMainUnwindInfo; - ULONG m_cbMainUnwindInfo; - - ZapUnwindInfo * m_pUnwindInfo; - ZapUnwindInfo * m_pUnwindInfoFragments; -#if defined(TARGET_AMD64) - ZapUnwindInfo * m_pChainedColdUnwindInfo; -#endif -#endif // FEATURE_EH_FUNCLETS - - ZapExceptionInfo * m_pExceptionInfo; - - ZapBlobWithRelocs * m_pProfileData; - - ZapImport * m_pProfilingHandle; - - struct CodeRelocation : ZapReloc - { - ZapBlobWithRelocs * m_pNode; - }; - - SArray m_CodeRelocations; - - static int __cdecl CompareCodeRelocation(const void * a, const void * b); - - struct ImportEntry - { - ZapImport * pImport; - bool fConditional; // Conditional imports are emitted only if they are actually referenced by the code. - }; - - class ImportTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef ZapImport * key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e.pImport; - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return k1 == k2; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(size_t)k; - } - - static const element_t Null() { LIMITED_METHOD_CONTRACT; ImportEntry e; e.pImport = NULL; return e; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e.pImport == NULL; } - }; - - SHash m_ImportSet; - SArray m_Imports; - - InlineSString<128> m_currentMethodName; - - // Cache to reduce the number of entries in CORCOMPILE_LOAD_TABLE if it - // is implied by some other fixup type - LoadTable m_ClassLoadTable; - LoadTable m_MethodLoadTable; - - CORJIT_FLAGS m_jitFlags; - - void InitMethodName(); - - CORJIT_FLAGS ComputeJitFlags(CORINFO_METHOD_HANDLE handle); - - ZapDebugInfo * EmitDebugInfo(); - ZapGCInfo * EmitGCInfo(); - ZapImport ** EmitFixupList(); - - void PublishCompiledMethod(); - - void EmitCodeRelocations(); - - void ProcessReferences(); - - BOOL CurrentMethodHasProfileData(); - - void embedGenericSignature(CORINFO_LOOKUP * pLookup); - - PVOID embedDirectCall(CORINFO_METHOD_HANDLE ftn, - CORINFO_ACCESS_FLAGS accessFlags, - BOOL fAllowThunk); - - struct ProfileDataResults - { - ProfileDataResults(CORINFO_METHOD_HANDLE ftn) : m_ftn(ftn) {} - ProfileDataResults* m_next = nullptr; - CORINFO_METHOD_HANDLE m_ftn; - SArray m_schema; - BYTE *pInstrumentationData = nullptr; - HRESULT m_hr = E_FAIL; - }; - ProfileDataResults *m_pgoResults = nullptr; - -public: - ZapInfo(ZapImage * pImage, mdMethodDef md, CORINFO_METHOD_HANDLE handle, CORINFO_MODULE_HANDLE module, unsigned methodProfilingDataFlags); - ~ZapInfo(); - -#ifdef ALLOW_SXS_JIT_NGEN - void ResetForJitRetry(); -#endif // ALLOW_SXS_JIT_NGEN - - void CompileMethod(); - - void AppendImport(ZapImport * pImport); - void AppendConditionalImport(ZapImport * pImport); - - ULONG GetNumFixups(); - - // ICorJitInfo -#include "icorjitinfoimpl_generated.h" - - int canHandleException(struct _EXCEPTION_POINTERS *pExceptionPointers); - void * getAddressOfPInvokeFixup(CORINFO_METHOD_HANDLE method, - void **ppIndirection); - ZapImport * GetProfilingHandleImport(); -}; - -#endif // __ZAPINFO_H__ diff --git a/src/coreclr/zap/zapinnerptr.cpp b/src/coreclr/zap/zapinnerptr.cpp deleted file mode 100644 index ec8baec4fa8852..00000000000000 --- a/src/coreclr/zap/zapinnerptr.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapInnerPtr.h -// - -// -// ZapNode that points into middle of other ZapNode -// -// ====================================================================================== - -#include "common.h" - -#include "zapinnerptr.h" - -ZapNode * ZapInnerPtrTable::Get(ZapNode * pBase, SSIZE_T offset) -{ - // Nothing to do if the offset is zero - if (offset == 0) - return pBase; - - // Flatten the hiearchy of inner ptrs. Inner ptrs pointing to other inner ptrs - // would not work well during the Resolve phase - while (pBase->GetType() == ZapNodeType_InnerPtr) - { - ZapInnerPtr * pWrapper = (ZapInnerPtr *)pBase; - - offset += pWrapper->GetOffset(); - pBase = pWrapper->GetBase(); - } - - ZapInnerPtr * pInnerPtr = m_entries.Lookup(InnerPtrKey(pBase, offset)); - - if (pInnerPtr != NULL) - return pInnerPtr; - - switch (offset) - { - case 1: - pInnerPtr = new (m_pWriter->GetHeap()) InnerPtrConst<1>(pBase); - break; - case 2: - pInnerPtr = new (m_pWriter->GetHeap()) InnerPtrConst<2>(pBase); - break; - case 4: - pInnerPtr = new (m_pWriter->GetHeap()) InnerPtrConst<4>(pBase); - break; - case 8: - pInnerPtr = new (m_pWriter->GetHeap()) InnerPtrConst<8>(pBase); - break; - default: - pInnerPtr = new (m_pWriter->GetHeap()) InnerPtrVar(pBase, offset); - break; - } - - m_entries.Add(pInnerPtr); - return pInnerPtr; -} - -void ZapInnerPtrTable::Resolve() -{ - for (InnerPtrTable::Iterator i = m_entries.Begin(), end = m_entries.End(); i != end; i++) - { - (*i)->Resolve(); - } -} diff --git a/src/coreclr/zap/zapinnerptr.h b/src/coreclr/zap/zapinnerptr.h deleted file mode 100644 index 7c3ef0aa6c8c14..00000000000000 --- a/src/coreclr/zap/zapinnerptr.h +++ /dev/null @@ -1,143 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapInnerPtr.h -// - -// -// ZapNode that points into middle of other ZapNode. It is used to create -// pointers into datastructures that are not convenient to split into smaller zap nodes. -// -// ====================================================================================== - -#ifndef __ZAPINNERPTR_H__ -#define __ZAPINNERPTR_H__ - -class ZapInnerPtr : public ZapNode -{ - ZapNode * m_pBase; - -public: - ZapInnerPtr(ZapNode * pBase) - : m_pBase(pBase) - { - } - - ZapNode * GetBase() - { - return m_pBase; - } - - virtual int GetOffset() = 0; - - void Resolve() - { - if (m_pBase->IsPlaced()) - { - SetRVA(m_pBase->GetRVA() + GetOffset()); - } - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_InnerPtr; - } -}; - -class ZapInnerPtrTable -{ - // Create more space efficient nodes for a few common constant offsets - template - class InnerPtrConst : public ZapInnerPtr - { - public: - InnerPtrConst(ZapNode * pBase) - : ZapInnerPtr(pBase) - { - } - - virtual int GetOffset() - { - return offset; - } - }; - - // The generic node for arbitrary offsets - class InnerPtrVar : public ZapInnerPtr - { - int m_offset; - - public: - InnerPtrVar(ZapNode * pBase, SSIZE_T offset) - : ZapInnerPtr(pBase), m_offset((int)offset) - { - if (offset != (int)offset) - ThrowHR(COR_E_OVERFLOW); - } - - virtual int GetOffset() - { - return m_offset; - } - }; - - struct InnerPtrKey - { - InnerPtrKey(ZapNode * pBase, SSIZE_T offset) - : m_pBase(pBase), m_offset(offset) - { - } - - ZapNode * m_pBase; - SSIZE_T m_offset; - }; - - class InnerPtrTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef const InnerPtrKey key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return InnerPtrKey(e->GetBase(), e->GetOffset()); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return (k1.m_pBase == k2.m_pBase) && (k1.m_offset == k2.m_offset); - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(size_t)k.m_pBase ^ (count_t)k.m_offset; - } - - static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } - }; - - typedef SHash< InnerPtrTraits > InnerPtrTable; - - InnerPtrTable m_entries; - ZapWriter * m_pWriter; - -public: - ZapInnerPtrTable(ZapWriter * pWriter) - : m_pWriter(pWriter) - { - } - - void Preallocate(COUNT_T cbILImage) - { - PREALLOCATE_HASHTABLE_NOT_NEEDED(ZapInnerPtrTable::m_entries, cbILImage); - } - - // Returns ZapNode that points at given offset in base ZapNode - ZapNode * Get(ZapNode * pBase, SSIZE_T offset); - - // Assign offsets to the inner-ptr ZapNodes - void Resolve(); -}; - -#endif // __ZAPINNERPTR_H__ diff --git a/src/coreclr/zap/zaplog.h b/src/coreclr/zap/zaplog.h deleted file mode 100644 index a9f5e2e27798e4..00000000000000 --- a/src/coreclr/zap/zaplog.h +++ /dev/null @@ -1,43 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - - -/* - * Hook IfFailThrow calls to do some logging when exceptions are thrown. - * - */ - -#ifndef __ZAPLOG_H__ -#define __ZAPLOG_H__ - -#undef IfFailThrow -#define IfFailThrow(x) \ - do { \ - HRESULT hrMacro = x; \ - if (FAILED(hrMacro)) { \ - /* don't embed file names in retail to save space and avoid IP */ \ - /* a findstr /n will allow you to locate it in a pinch */ \ - ThrowAndLog(hrMacro, INDEBUG_COMMA(#x) INDEBUG_COMMA(__FILE__) __LINE__); \ - } \ - } while(FALSE) - -inline void ThrowAndLog(HRESULT hr, INDEBUG_COMMA(__in_z const char * szMsg) INDEBUG_COMMA(__in_z const char * szFile) int lineNum) -{ - WRAPPER_NO_CONTRACT; - - // Log failures when StressLog is on - static ConfigDWORD g_iStressLog; - BOOL bLog = g_iStressLog.val(CLRConfig::UNSUPPORTED_StressLog); - if (bLog) - { -#ifdef _DEBUG - GetSvcLogger()->Printf("IfFailThrow about to throw in file %s line %d, msg = %s, hr: 0x%X\n", szFile, lineNum, szMsg, hr); -#else - GetSvcLogger()->Printf("IfFailThrow about to throw on line %d. hr: 0x%X\n", lineNum, hr); -#endif - } - - ThrowHR(hr); -} - -#endif // __ZAPLOG_H__ diff --git a/src/coreclr/zap/zapmetadata.cpp b/src/coreclr/zap/zapmetadata.cpp deleted file mode 100644 index 2e7c3dc570e1b2..00000000000000 --- a/src/coreclr/zap/zapmetadata.cpp +++ /dev/null @@ -1,362 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapMetadata.cpp -// - -// -// Metadata zapping -// -// ====================================================================================== - -#include "common.h" - -#include "zapmetadata.h" - -//----------------------------------------------------------------------------- -// -// ZapMetaData is the barebone ZapNode to save metadata scope -// - -void ZapMetaData::SetMetaData(IUnknown * pEmit) -{ - _ASSERTE(m_pEmit == NULL); - _ASSERTE(pEmit != NULL); - - IfFailThrow(pEmit->QueryInterface(IID_IMetaDataEmit, (void **)&m_pEmit)); -} - -DWORD ZapMetaData::GetSize() -{ - if (m_dwSize == 0) - { - IfFailThrow(m_pEmit->GetSaveSize(cssAccurate, &m_dwSize)); - _ASSERTE(m_dwSize != 0); - } - return m_dwSize; -} - -void ZapMetaData::Save(ZapWriter * pZapWriter) -{ - IfFailThrow(m_pEmit->SaveToStream(pZapWriter, 0)); -} - -//----------------------------------------------------------------------------- -// -// ZapILMetaData copies both the metadata and IL to the NGEN image. -// - -void ZapILMetaData::Save(ZapWriter * pZapWriter) -{ - IMDInternalImport * pMDImport = m_pImage->m_pMDImport; - - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumAllInit(mdtMethodDef); - - mdMethodDef md; - while (pMDImport->EnumNext(&hEnum, &md)) - { - DWORD flags; - ULONG rva; - IfFailThrow(pMDImport->GetMethodImplProps(md, &rva, &flags)); - - if (!IsMiIL(flags) || (rva == 0)) - continue; - - // Set the actual RVA of the method - const ILMethod * pILMethod = m_ILMethods.LookupPtr(md); - - IfFailThrow(m_pEmit->SetRVA(md, (pILMethod != NULL) ? pILMethod->m_pIL->GetRVA() : 0)); - } - - if (IsReadyToRunCompilation()) - { - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumAllInit(mdtFieldDef); - - mdFieldDef fd; - while (pMDImport->EnumNext(&hEnum, &fd)) - { - DWORD dwRVA = 0; - if (pMDImport->GetFieldRVA(fd, &dwRVA) == S_OK) - { - PVOID pData = NULL; - DWORD cbSize = 0; - DWORD cbAlignment = 0; - - m_pImage->m_pPreloader->GetRVAFieldData(fd, &pData, &cbSize, &cbAlignment); - - ZapRVADataNode * pRVADataNode = m_rvaData.Lookup(pData); - m_pEmit->SetRVA(fd, pRVADataNode->GetRVA()); - } - } - } - else - { - ZapImage::GetImage(pZapWriter)->m_pPreloader->SetRVAsForFields(m_pEmit); - } - - ZapMetaData::Save(pZapWriter); -} - -ZapRVADataNode * ZapILMetaData::GetRVAField(void * pData) -{ - ZapRVADataNode * pRVADataNode = m_rvaData.Lookup(pData); - - if (pRVADataNode == NULL) - { - pRVADataNode = new (m_pImage->GetHeap()) ZapRVADataNode(pData); - - m_rvaData.Add(pRVADataNode); - } - - return pRVADataNode; -} - -struct RVAField -{ - PVOID pData; - DWORD cbSize; - DWORD cbAlignment; -}; - -// Used by qsort -int __cdecl RVAFieldCmp(const void * a_, const void * b_) -{ - RVAField * a = (RVAField *)a_; - RVAField * b = (RVAField *)b_; - - if (a->pData != b->pData) - { - return (a->pData > b->pData) ? 1 : -1; - } - - return 0; -} - -void ZapILMetaData::CopyRVAFields() -{ - IMDInternalImport * pMDImport = m_pImage->m_pMDImport; - - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumAllInit(mdtFieldDef); - - SArray fields; - - mdFieldDef fd; - while (pMDImport->EnumNext(&hEnum, &fd)) - { - DWORD dwRVA = 0; - if (pMDImport->GetFieldRVA(fd, &dwRVA) == S_OK) - { - RVAField field; - m_pImage->m_pPreloader->GetRVAFieldData(fd, &field.pData, &field.cbSize, &field.cbAlignment); - fields.Append(field); - } - } - - if (fields.GetCount() == 0) - return; - - // Managed C++ binaries depend on the order of RVA fields - qsort(&fields[0], fields.GetCount(), sizeof(RVAField), RVAFieldCmp); - -#ifdef _DEBUG - for (COUNT_T i = 0; i < fields.GetCount(); i++) - { - // Make sure no RVA field node has been placed during compilation. This would mess up the ordering - // and can potentially break the Managed C++ scenarios. - _ASSERTE(!GetRVAField(fields[i].pData)->IsPlaced()); - } -#endif - - for (COUNT_T i = 0; i < fields.GetCount(); i++) - { - RVAField field = fields[i]; - - ZapRVADataNode * pRVADataNode = GetRVAField(field.pData); - - // Handle overlapping fields by reusing blobs based on the address, and just updating size and alignment. - pRVADataNode->UpdateSizeAndAlignment(field.cbSize, field.cbAlignment); - - if (!pRVADataNode->IsPlaced()) - m_pImage->m_pReadOnlyDataSection->Place(pRVADataNode); - } -} - -void ZapILMetaData::CopyIL() -{ - // The IL is emited into NGen image in the following priority order: - // 1. Public inlineable method (may be needed by JIT inliner) - // 2. Generic method (may be needed to compile non-NGened instantiations) - // 3. Other potentially warm instances (private inlineable methods, methods that failed to NGen) - // 4. Everything else (should be touched in rare scenarios like reflection or profiling only) - - SArray priorityLists[CORCOMPILE_ILREGION_COUNT]; - - IMDInternalImport * pMDImport = m_pImage->m_pMDImport; - - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumAllInit(mdtMethodDef); - - // - // Build the list for each priority in first pass, and then place - // the IL blobs in each list. The two passes are needed because of - // interning of IL blobs (one IL blob can be on multiple lists). - // - - mdMethodDef md; - while (pMDImport->EnumNext(&hEnum, &md)) - { - const ILMethod * pILMethod = m_ILMethods.LookupPtr(md); - - if (pILMethod == NULL) - continue; - - CorCompileILRegion region = m_pImage->m_pPreloader->GetILRegion(md); - _ASSERTE(region < CORCOMPILE_ILREGION_COUNT); - - // Preallocate space to avoid wasting too much time by reallocations - if (priorityLists[region].IsEmpty()) - priorityLists[region].Preallocate(m_ILMethods.GetCount() / 16); - - priorityLists[region].Append(pILMethod->m_pIL); - } - - for (int iList = 0; iList < CORCOMPILE_ILREGION_COUNT; iList++) - { - SArray & priorityList = priorityLists[iList]; - - // Use just one section for IL for now. Once the touches of IL for method preparation are fixed change it to: - // ZapVirtualSection * pSection = (iList == CORCOMPILE_ILREGION_COLD) ? m_pImage->m_pColdILSection : m_pImage->m_pILSection; - - ZapVirtualSection * pSection = m_pImage->m_pILSection; - - COUNT_T nBlobs = priorityList.GetCount(); - for (COUNT_T iBlob = 0; iBlob < nBlobs; iBlob++) - { - ZapBlob * pIL = priorityList[iBlob]; - if (!pIL->IsPlaced()) - pSection->Place(pIL); - } - } -} - -void ZapILMetaData::CopyMetaData() -{ - // - // Copy metadata from IL image and open it so we can update IL rva's - // - - COUNT_T cMeta; - const void *pMeta = m_pImage->m_ModuleDecoder.GetMetadata(&cMeta); - - IMetaDataDispenserEx * pMetaDataDispenser = m_pImage->m_zapper->m_pMetaDataDispenser; - - // - // Transfer the metadata version string from IL image to native image - // - LPCSTR pRuntimeVersionString; - IfFailThrow(GetImageRuntimeVersionString((PVOID)pMeta, &pRuntimeVersionString)); - - SString ssRuntimeVersion; - ssRuntimeVersion.SetUTF8(pRuntimeVersionString); - - BSTRHolder strVersion(SysAllocString(ssRuntimeVersion.GetUnicode())); - - VARIANT versionOption; - V_VT(&versionOption) = VT_BSTR; - V_BSTR(&versionOption) = strVersion; - IfFailThrow(pMetaDataDispenser->SetOption(MetaDataRuntimeVersion, &versionOption)); - - // Preserve local refs. - VARIANT preserveLocalRefsOption; - V_VT(&preserveLocalRefsOption) = VT_UI4; - V_UI4(&preserveLocalRefsOption) = MDPreserveLocalTypeRef | MDPreserveLocalMemberRef; - IfFailThrow(pMetaDataDispenser->SetOption(MetaDataPreserveLocalRefs, &preserveLocalRefsOption)); - - // ofNoTransform - Get the raw metadata for WinRT, not the adapter view - HRESULT hr = pMetaDataDispenser->OpenScopeOnMemory(pMeta, cMeta, - ofWrite | ofNoTransform, - IID_IMetaDataEmit, - (IUnknown **) &m_pEmit); - if (hr == CLDB_E_BADUPDATEMODE) - { - // This must be incrementally-updated metadata. It needs to be opened - // specially. - VARIANT incOption; - V_VT(&incOption) = VT_UI4; - V_UI4(&incOption) = MDUpdateIncremental; - IfFailThrow(pMetaDataDispenser->SetOption(MetaDataSetUpdate, &incOption)); - - hr = pMetaDataDispenser->OpenScopeOnMemory(pMeta, cMeta, - ofWrite | ofNoTransform, - IID_IMetaDataEmit, - (IUnknown **) &m_pEmit); - } - - // Check the result of OpenScopeOnMemory() - IfFailThrow(hr); - - if (!IsReadyToRunCompilation()) - { - // Communicate the profile data to the meta data emitter so it can hot/cold split it - NonVMComHolder pIMetaDataCorProfileData; - IfFailThrow(m_pEmit->QueryInterface(IID_IMetaDataCorProfileData, - (void**)&pIMetaDataCorProfileData)); - - // unless we're producing an instrumented version - the IBC logging for meta data doesn't - // work for the hot/cold split version. - if (m_pImage->m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR)) - IfFailThrow(pIMetaDataCorProfileData->SetCorProfileData(NULL)); - else - IfFailThrow(pIMetaDataCorProfileData->SetCorProfileData(m_pImage->GetProfileData())); - } - - // If we are ngening with the tuning option, the IBC data that is - // generated gets reordered and may be inconsistent with the - // metadata in the original IL image. Let's just skip that case. - if (!m_pImage->m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR)) - { - // Communicate the reordering option for saving - NonVMComHolder pIMDInternalMetadataReorderingOptions; - IfFailThrow(m_pEmit->QueryInterface(IID_IMDInternalMetadataReorderingOptions, - (void**)&pIMDInternalMetadataReorderingOptions)); - IfFailThrow(pIMDInternalMetadataReorderingOptions->SetMetaDataReorderingOptions(ReArrangeStringPool)); - } -} - -// Emit IL for a method def into the ngen image -void ZapILMetaData::EmitMethodIL(mdMethodDef md) -{ - DWORD flags; - ULONG rva; - IfFailThrow(m_pImage->m_pMDImport->GetMethodImplProps(md, &rva, &flags)); - - if (!IsMiIL(flags) || (rva == 0)) - return; - - if (!m_pImage->m_ModuleDecoder.CheckILMethod(rva)) - IfFailThrow(COR_E_BADIMAGEFORMAT); // BFA_BAD_IL_RANGE - - PVOID pMethod = (PVOID)m_pImage->m_ModuleDecoder.GetRvaData(rva); - - SIZE_T cMethod = PEDecoder::ComputeILMethodSize((TADDR)pMethod); - - // - // Emit copy of IL method in native image. - // - ZapBlob * pIL = m_blobs.Lookup(ZapBlob::SHashKey(pMethod, cMethod)); - - if (pIL == NULL) - { - pIL = new (m_pImage->GetHeap()) ILBlob(pMethod, cMethod); - - m_blobs.Add(pIL); - } - - ILMethod ilMethod; - ilMethod.m_md = md; - ilMethod.m_pIL = pIL; - m_ILMethods.Add(ilMethod); -} diff --git a/src/coreclr/zap/zapmetadata.h b/src/coreclr/zap/zapmetadata.h deleted file mode 100644 index c23774cffb1f19..00000000000000 --- a/src/coreclr/zap/zapmetadata.h +++ /dev/null @@ -1,221 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapMetadata.h -// - -// -// Metadata zapping -// -// ====================================================================================== - -#ifndef __ZAPMETADATA_H__ -#define __ZAPMETADATA_H__ - -//----------------------------------------------------------------------------- -// -// ZapMetaData is the barebone ZapNode to save metadata scope -// - -class ZapMetaData : public ZapNode -{ - DWORD m_dwSize; - -protected: - IMetaDataEmit * m_pEmit; - -public: - ZapMetaData() - { - } - - ~ZapMetaData() - { - SAFERELEASE(m_pEmit); - } - - void SetMetaData(IUnknown * pEmit); - - virtual DWORD GetSize(); - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_MetaData; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -//----------------------------------------------------------------------------- -// -// Helper node to copy RVA data to from IL to the NGEN image. -// - -class ZapRVADataNode : public ZapNode -{ - PVOID m_pData; - DWORD m_dwSize; - DWORD m_dwAlignment; - -public: - ZapRVADataNode(PVOID pData) - { - m_pData = pData; - m_dwSize = 0; - m_dwAlignment = 1; - } - - void UpdateSizeAndAlignment(DWORD dwSize, DWORD dwAlignment) - { - if (dwSize > m_dwSize) - m_dwSize = dwSize; - - if (dwAlignment > m_dwAlignment) - m_dwAlignment = dwAlignment; - } - - PVOID GetData() - { - return m_pData; - } - - virtual DWORD GetSize() - { - return m_dwSize; - } - - virtual UINT GetAlignment() - { - return m_dwAlignment; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_RVAFieldData; - } - - virtual void Save(ZapWriter * pZapWriter) - { - pZapWriter->Write(m_pData, m_dwSize); - } -}; - - -//----------------------------------------------------------------------------- -// -// ZapILMetaData copies both the metadata and IL to the NGEN image. -// - -class ZapILMetaData : public ZapMetaData -{ - ZapImage * m_pImage; - - class ILBlob : public ZapBlobPtr - { - public: - ILBlob(PVOID pData, SIZE_T cbSize) - : ZapBlobPtr(pData, cbSize) - { - } - - virtual UINT GetAlignment() - { - // The tiny header does not have any alignment requirements - return ((COR_ILMETHOD_TINY *)GetData())->IsTiny() ? sizeof(BYTE) : sizeof(DWORD); - } - }; - - // Hashtable with all IL method blobs. If two methods have same IL code - // we store it just once. - SHash< NoRemoveSHashTraits < ZapBlob::SHashTraits > > m_blobs; - - struct ILMethod - { - mdMethodDef m_md; - ZapBlob * m_pIL; - }; - - class ILMethodTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef const mdMethodDef key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e.m_md; - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return k1 == k2; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return k; - } - - static const element_t Null() { LIMITED_METHOD_CONTRACT; ILMethod e; e.m_md = 0; e.m_pIL = NULL; return e; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e.m_md == 0; } - }; - - SHash< ILMethodTraits > m_ILMethods; - -public: - ZapILMetaData(ZapImage * pImage) - : m_pImage(pImage) - { - } - - void Preallocate(COUNT_T cbILImage) - { - PREALLOCATE_HASHTABLE(ZapILMetaData::m_blobs, 0.0040, cbILImage); - PREALLOCATE_HASHTABLE(ZapILMetaData::m_ILMethods, 0.0044, cbILImage); - } - - void EmitMethodIL(mdMethodDef md); - - void CopyIL(); - void CopyMetaData(); - void CopyRVAFields(); - - virtual void Save(ZapWriter * pZapWriter); - - ZapRVADataNode * GetRVAField(void * pData); - -private: - class RVADataTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef PVOID key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e->GetData(); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return k1 == k2; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(SIZE_T)k; - } - - static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } - }; - - SHash< RVADataTraits > m_rvaData; -}; - -#endif // __ZAPMETADATA_H__ diff --git a/src/coreclr/zap/zapnodetype.h b/src/coreclr/zap/zapnodetype.h deleted file mode 100644 index 6f73833eb84101..00000000000000 --- a/src/coreclr/zap/zapnodetype.h +++ /dev/null @@ -1,117 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapNoteType.h -// - -// -// Enum for ZapNode types -// -// ====================================================================================== - -#ifndef __ZAPNODETYPE_H__ -#define __ZAPNODETYPE_H__ - -enum ZapNodeType { - -// System types - - ZapNodeType_Unknown, - - ZapNodeType_PhysicalSection, - ZapNodeType_VirtualSection, - ZapNodeType_Blob, - ZapNodeType_InnerPtr, - - ZapNodeType_Relocs, - -// Headers - - ZapNodeType_CorHeader, - ZapNodeType_NativeHeader, - ZapNodeType_VersionInfo, - ZapNodeType_Dependencies, - ZapNodeType_CodeManagerEntry, - ZapNodeType_MetaData, - ZapNodeType_DebugDirectory, - ZapNodeType_Win32Resources, - -// PlaceHolders - - ZapNodeType_MethodEntryPoint, - ZapNodeType_ClassHandle, - ZapNodeType_MethodHandle, - ZapNodeType_FieldHandle, - ZapNodeType_AddrOfPInvokeFixup, - ZapNodeType_GenericHandle, - ZapNodeType_ModuleIDHandle, - -// Code references - - ZapNodeType_MethodHeader, - ZapNodeType_CodeManagerMap, - ZapNodeType_UnwindInfo, - ZapNodeType_UnwindData, - ZapNodeType_UnwindDataAndGCInfo, - ZapNodeType_FilterFuncletUnwindData, - - ZapNodeType_ProfileData, - ZapNodeType_VirtualSectionsTable, - - ZapNodeType_DebugInfoTable, - ZapNodeType_DebugInfoLabelledEntry, - - ZapNodeType_HelperThunk, - ZapNodeType_LazyHelperThunk, - ZapNodeType_IndirectHelperThunk, - - ZapNodeType_ExceptionInfoTable, - ZapNodeType_UnwindInfoLookupTable, - ZapNodeType_ColdCodeMap, - -// Wrappers - - ZapNodeType_Stub, - -// Imports - - ZapNodeType_ExternalMethodThunk, - ZapNodeType_VirtualMethodThunk, - - ZapNodeType_ExternalMethodCell, - ZapNodeType_StubDispatchCell, - ZapNodeType_DynamicHelperCell, - - ZapNodeType_Import_FunctionEntry, - ZapNodeType_Import_ModuleHandle, - ZapNodeType_Import_ClassHandle, - ZapNodeType_Import_MethodHandle, - ZapNodeType_Import_FieldHandle, - ZapNodeType_Import_IndirectPInvokeTarget, - ZapNodeType_Import_PInvokeTarget, - ZapNodeType_Import_StringHandle, - ZapNodeType_Import_StaticFieldAddress, - ZapNodeType_Import_ClassDomainId, - ZapNodeType_Import_ModuleDomainId, - ZapNodeType_Import_SyncLock, - ZapNodeType_Import_ProfilingHandle, - ZapNodeType_Import_VarArg, - ZapNodeType_Import_ActiveDependency, - ZapNodeType_Import_Helper, - - ZapNodeType_GenericSignature, - - ZapNodeType_ImportTable, - - ZapNodeType_ImportSectionsTable, - ZapNodeType_ImportSectionSignatures, - - ZapNodeType_GCRefMapTable, - - ZapNodeType_RVAFieldData, - ZapNodeType_EntryPointsTable, - - ZapNodeType_StoredStructure, // The ZapNodeTypes of the legacy stored structures start here -}; - -#endif // __ZAPNODETYPE_H__ diff --git a/src/coreclr/zap/zapper.cpp b/src/coreclr/zap/zapper.cpp deleted file mode 100644 index c0d65d34c46498..00000000000000 --- a/src/coreclr/zap/zapper.cpp +++ /dev/null @@ -1,1699 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - - -#include "common.h" - -#include "coregen.h" - -#pragma warning(push) -#pragma warning(disable: 4995) -#include "shlwapi.h" -#pragma warning(pop) - -extern const WCHAR g_pwBaseLibrary[]; -extern bool g_fAllowNativeImages; -bool g_fNGenMissingDependenciesOk; - -#ifdef FEATURE_READYTORUN_COMPILER -bool g_fReadyToRunCompilation; -bool g_fLargeVersionBubble; -#endif - -/* --------------------------------------------------------------------------- * - * Public entry points for ngen - * --------------------------------------------------------------------------- */ -// For side by side issues, it's best to use the exported API calls to generate a -// Zapper Object instead of creating one on your own. - - -STDAPI NGenWorker(LPCWSTR pwzFilename, DWORD dwFlags, LPCWSTR pwzPlatformAssembliesPaths, LPCWSTR pwzTrustedPlatformAssemblies, LPCWSTR pwzPlatformResourceRoots, LPCWSTR pwzAppPaths, LPCWSTR pwzOutputFilename=NULL, SIZE_T customBaseAddress=0, ICorSvcLogger *pLogger = NULL, LPCWSTR pwszCLRJITPath = nullptr) -{ - HRESULT hr = S_OK; - - BEGIN_ENTRYPOINT_NOTHROW; - - Zapper* zap = NULL; - - EX_TRY - { - NGenOptions ngo = {0}; - ngo.dwSize = sizeof(NGenOptions); - - // V1 - - ngo.fDebug = false; - ngo.fDebugOpt = false; - ngo.fProf = false; - ngo.fSilent = (dwFlags & NGENWORKER_FLAGS_SILENT) != 0; - ngo.lpszExecutableFileName = pwzFilename; - - // V2 (Whidbey) - - ngo.fInstrument = !!(dwFlags & NGENWORKER_FLAGS_TUNING); - ngo.fWholeProgram = false; - ngo.fProfInfo = false; - - ngo.lpszRepositoryDir = NULL; - ngo.repositoryFlags = RepositoryDefault; - - ngo.dtRequested = DT_NIL; - ngo.lpszDebugDir = NULL; - - ngo.fNoInstall = false; - - ngo.fEmitFixups = false; - ngo.fFatHeaders = false; - - ngo.fVerbose = (dwFlags & NGENWORKER_FLAGS_VERBOSE) != 0; - ngo.uStats = false; - - ngo.fNgenLastRetry = false; - - zap = Zapper::NewZapper(&ngo); - - if (pwzOutputFilename) - zap->SetOutputFilename(pwzOutputFilename); - - zap->SetCustomBaseAddress(customBaseAddress); - - if (pwzPlatformAssembliesPaths != nullptr) - zap->SetPlatformAssembliesPaths(pwzPlatformAssembliesPaths); - - if (pwzTrustedPlatformAssemblies != nullptr) - zap->SetTrustedPlatformAssemblies(pwzTrustedPlatformAssemblies); - - if (pwzPlatformResourceRoots != nullptr) - zap->SetPlatformResourceRoots(pwzPlatformResourceRoots); - - if (pwzAppPaths != nullptr) - zap->SetAppPaths(pwzAppPaths); - -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) - if (pwszCLRJITPath != nullptr) - zap->SetCLRJITPath(pwszCLRJITPath); -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) - - g_fNGenMissingDependenciesOk = !!(dwFlags & NGENWORKER_FLAGS_MISSINGDEPENDENCIESOK); - -#ifdef FEATURE_READYTORUN_COMPILER - g_fReadyToRunCompilation = !!(dwFlags & NGENWORKER_FLAGS_READYTORUN); - g_fLargeVersionBubble = !!(dwFlags & NGENWORKER_FLAGS_LARGEVERSIONBUBBLE); -#endif - - if (pLogger != NULL) - { - GetSvcLogger()->SetSvcLogger(pLogger); - } - - hr = zap->Compile(pwzFilename); - } - EX_CATCH_HRESULT(hr); - - END_ENTRYPOINT_NOTHROW; - - return hr; -} - -STDAPI CreatePDBWorker(LPCWSTR pwzAssemblyPath, LPCWSTR pwzPlatformAssembliesPaths, LPCWSTR pwzTrustedPlatformAssemblies, LPCWSTR pwzPlatformResourceRoots, LPCWSTR pwzAppPaths, LPCWSTR pwzAppNiPaths, LPCWSTR pwzPdbPath, BOOL fGeneratePDBLinesInfo, LPCWSTR pwzManagedPdbSearchPath, LPCWSTR pwzDiasymreaderPath) -{ - HRESULT hr = S_OK; - - BEGIN_ENTRYPOINT_NOTHROW; - - EX_TRY - { - GetCompileInfo()->SetIsGeneratingNgenPDB(TRUE); - - NGenOptions ngo = {0}; - ngo.dwSize = sizeof(NGenOptions); - - NewHolder zap(Zapper::NewZapper(&ngo)); - -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) - zap->SetDontLoadJit(); -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) - - if (pwzPlatformAssembliesPaths != nullptr) - zap->SetPlatformAssembliesPaths(pwzPlatformAssembliesPaths); - - if (pwzTrustedPlatformAssemblies != nullptr) - zap->SetTrustedPlatformAssemblies(pwzTrustedPlatformAssemblies); - - if (pwzPlatformResourceRoots != nullptr) - zap->SetPlatformResourceRoots(pwzPlatformResourceRoots); - - if (pwzAppPaths != nullptr) - zap->SetAppPaths(pwzAppPaths); - - if (pwzAppNiPaths != nullptr) - zap->SetAppNiPaths(pwzAppNiPaths); - -#if !defined(NO_NGENPDB) - if (pwzDiasymreaderPath != nullptr) - zap->SetDiasymreaderPath(pwzDiasymreaderPath); -#endif // !defined(NO_NGENPDB) - - BSTRHolder strAssemblyPath(::SysAllocString(pwzAssemblyPath)); - BSTRHolder strPdbPath(::SysAllocString(pwzPdbPath)); - BSTRHolder strManagedPdbSearchPath(::SysAllocString(pwzManagedPdbSearchPath)); - - // Zapper::CreatePdb is shared code for both desktop NGEN PDBs and coreclr - // crossgen PDBs. - zap->CreatePdb( - strAssemblyPath, - - // On desktop with fusion AND on the phone, the various binders always expect - // the native image to be specified here. - strAssemblyPath, - - strPdbPath, - fGeneratePDBLinesInfo, - strManagedPdbSearchPath); - } - EX_CATCH_HRESULT(hr); - - END_ENTRYPOINT_NOTHROW; - - return hr; -} - - -/* --------------------------------------------------------------------------- * - * Options class - * --------------------------------------------------------------------------- */ - -ZapperOptions::ZapperOptions() : - m_repositoryDir(NULL), - m_repositoryFlags(RepositoryDefault), - m_autodebug(false), - m_onlyOneMethod(0), - m_silent(true), - m_verbose(false), - m_ignoreErrors(true), - m_statOptions(0), - m_ngenProfileImage(false), - m_ignoreProfileData(false), - m_noProcedureSplitting(false), - m_fHasAnyProfileData(false), - m_fPartialNGen(false), - m_fPartialNGenSet(false), - m_fNGenLastRetry(false), - m_compilerFlags() -{ - SetCompilerFlags(); - - m_zapSet = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_ZapSet); - if (m_zapSet != NULL && wcslen(m_zapSet) > 3) - { - delete [] m_zapSet; - m_zapSet = NULL; - } - - if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_DisableIBC)) - { - m_ignoreProfileData = true; - } - - if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_NoProcedureSplitting)) - { - m_noProcedureSplitting = true; - } - - DWORD partialNGen = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_PartialNGen); - if (partialNGen != (DWORD)(-1)) - { - m_fPartialNGenSet = true; - m_fPartialNGen = partialNGen != 0; - } - -#ifdef _DEBUG - m_onlyOneMethod = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_NGenOnlyOneMethod); -#endif -} - -ZapperOptions::~ZapperOptions() -{ - if (m_zapSet != NULL) - delete [] m_zapSet; - - if (m_repositoryDir != NULL) - delete [] m_repositoryDir; -} - -void ZapperOptions::SetCompilerFlags(void) -{ - m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_RELOC); - m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PREJIT); - -#if defined(TARGET_ARM) -# if defined(TARGET_UNIX) - m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_RELATIVE_CODE_RELOCS); -# endif // defined(TARGET_UNIX) -#endif // defined(TARGET_ARM) -} - -/* --------------------------------------------------------------------------- * - * Zapper class - * --------------------------------------------------------------------------- */ - -Zapper::Zapper(NGenOptions *pOptions, bool fromDllHost) -{ - ZapperOptions *zo = new ZapperOptions(); - - // We can version NGenOptions by looking at the dwSize variable - - NGenOptions currentVersionOptions; - memcpy(¤tVersionOptions, pOptions, pOptions->dwSize); - - if (pOptions->dwSize < sizeof(currentVersionOptions)) - { - // Clear out the memory. This is redundant with the explicit - // initializations below, but is meant to be a backup. - - ZeroMemory(PBYTE(¤tVersionOptions) + pOptions->dwSize, - sizeof(currentVersionOptions) - pOptions->dwSize); - - // Initialize all the fields added in the current version - - currentVersionOptions.fInstrument = false; - currentVersionOptions.fWholeProgram = false; - currentVersionOptions.fProfInfo = false; - - currentVersionOptions.dtRequested = DT_NIL; - currentVersionOptions.lpszDebugDir = NULL; - - currentVersionOptions.lpszRepositoryDir = NULL; - currentVersionOptions.repositoryFlags = RepositoryDefault; - - currentVersionOptions.fNoInstall = false; - - currentVersionOptions.fEmitFixups = false; - currentVersionOptions.fFatHeaders = false; - - currentVersionOptions.fVerbose = false; - currentVersionOptions.uStats = 0; - - currentVersionOptions.fNgenLastRetry = false; - - currentVersionOptions.fAutoNGen = false; - - currentVersionOptions.fRepositoryOnly = false; - } - - pOptions = ¤tVersionOptions; - - zo->m_compilerFlags.Reset(); - zo->SetCompilerFlags(); - zo->m_autodebug = true; - - if (pOptions->fDebug) - { - zo->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); - zo->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE); - zo->m_autodebug = false; - } - - if (pOptions->fProf) - { - zo->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE); - } - - - if (pOptions->fInstrument) - zo->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR); - - zo->m_verbose = pOptions->fVerbose; - zo->m_statOptions = pOptions->uStats; - - zo->m_silent = pOptions->fSilent; - - if (pOptions->lpszExecutableFileName != NULL) - { - m_exeName.Set(pOptions->lpszExecutableFileName); - } - - if (pOptions->fNgenLastRetry) - { - zo->m_fNGenLastRetry = true; - - // - // Things that we turn off when this is the last retry for ngen - // - zo->m_ignoreProfileData = true; // ignore any IBC profile data - -#ifdef TARGET_ARM - // - // On ARM, we retry compilation for large images when we hit overflow of IMAGE_REL_BASED_THUMB_BRANCH24 relocations. - // Disable procedure spliting for retry because of it depends on IMAGE_REL_BASED_THUMB_BRANCH24 relocations. - // See related code in code:ZapInfo::getRelocTypeHint - // - zo->m_noProcedureSplitting = true; -#endif - } - - zo->m_fAutoNGen = pOptions->fAutoNGen; - - zo->m_fRepositoryOnly = pOptions->fRepositoryOnly; - - m_fromDllHost = fromDllHost; - - Init(zo, true); -} - - -Zapper::Zapper(ZapperOptions *pOptions) -{ - Init(pOptions); -} - -void Zapper::Init(ZapperOptions *pOptions, bool fFreeZapperOptions) -{ - m_pEEJitInfo = NULL; - m_pEECompileInfo = NULL; - m_pJitCompiler = NULL; - m_pMetaDataDispenser = NULL; - m_hJitLib = NULL; -#ifdef TARGET_AMD64 - m_hJitLegacy = NULL; -#endif - - m_pOpt = pOptions; - - m_pDomain = NULL; - m_hAssembly = NULL; - m_pAssemblyImport = NULL; - m_failed = FALSE; - m_currentRegionKind = CORINFO_REGION_NONE; - - m_pAssemblyEmit = NULL; - m_fFreeZapperOptions = fFreeZapperOptions; - - m_customBaseAddress = 0; - -#ifdef LOGGING - InitializeLogging(); -#endif - - HRESULT hr; - - // - // Get metadata dispenser interface - // - - IfFailThrow(MetaDataGetDispenser(CLSID_CorMetaDataDispenser, - IID_IMetaDataDispenserEx, (void **)&m_pMetaDataDispenser)); - - // - // Make sure we don't duplicate assembly refs and file refs - // - - VARIANT opt; - hr = m_pMetaDataDispenser->GetOption(MetaDataCheckDuplicatesFor, &opt); - _ASSERTE(SUCCEEDED(hr)); - - _ASSERTE(V_VT(&opt) == VT_UI4); - V_UI4(&opt) |= MDDupAssemblyRef | MDDupFile; - - hr = m_pMetaDataDispenser->SetOption(MetaDataCheckDuplicatesFor, &opt); - _ASSERTE(SUCCEEDED(hr)); - - -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) - m_fDontLoadJit = false; -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) -} - -// LoadAndInitializeJITForNgen: load the JIT dll into the process, and initialize it (call the UtilCode initialization function, -// check the JIT-EE interface GUID, etc.). (This is similar to LoadAndInitializeJIT.) -// -// Parameters: -// -// pwzJitName - The filename of the JIT .dll file to load. E.g., "altjit.dll". -// phJit - On return, *phJit is the Windows module handle of the loaded JIT dll. It will be NULL if the load failed. -// ppICorJitCompiler - On return, *ppICorJitCompiler is the ICorJitCompiler* returned by the JIT's getJit() entrypoint. -// It is NULL if the JIT returns a NULL interface pointer, or if the JIT-EE interface GUID is mismatched. -// -// Note that both *phJit and *ppICorJitCompiler will be non-NULL on success. On failure, an exception is thrown. -void Zapper::LoadAndInitializeJITForNgen(LPCWSTR pwzJitName, OUT HINSTANCE* phJit, OUT ICorJitCompiler** ppICorJitCompiler) -{ - _ASSERTE(phJit != NULL); - _ASSERTE(ppICorJitCompiler != NULL); - - *phJit = NULL; - *ppICorJitCompiler = NULL; - - HRESULT hr = E_FAIL; - - // Note: FEATURE_MERGE_JIT_AND_ENGINE is defined for the Desktop crossgen compilation as well. - // - PathString CoreClrFolder; - -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) - if (m_fDontLoadJit) - { - return; - } - - if (m_CLRJITPath.GetCount() > 0) - { - // If we have been asked to load a specific JIT binary, load it. - CoreClrFolder.Set(m_CLRJITPath); - hr = S_OK; - } - else -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) - { - hr = GetClrModuleDirectory(CoreClrFolder); - if (SUCCEEDED(hr)) - { - CoreClrFolder.Append(pwzJitName); - } - } - - if (SUCCEEDED(hr)) - { - *phJit = ::WszLoadLibrary(CoreClrFolder); - if (*phJit == NULL) - { - hr = HRESULT_FROM_GetLastError(); - } - else - { - hr = S_OK; - } - } - - if (FAILED(hr)) - { - Error(W("Unable to load Jit Compiler: %s, hr=0x%08x\r\n"), pwzJitName, hr); - ThrowLastError(); - } - - typedef void (__stdcall* pJitStartup)(ICorJitHost* host); - pJitStartup jitStartupFn = (pJitStartup)GetProcAddress(*phJit, "jitStartup"); - if (jitStartupFn != nullptr) - { - jitStartupFn(m_pEECompileInfo->GetJitHost()); - } - - //get the appropriate compiler interface - typedef ICorJitCompiler* (__stdcall* pGetJitFn)(); - pGetJitFn getJitFn = (pGetJitFn) GetProcAddress(*phJit, "getJit"); - if (getJitFn == NULL) - { - Error(W("Unable to load main Jit function: %s\r\n"), pwzJitName); - ThrowLastError(); - } - - ICorJitCompiler* pICorJitCompiler = (*getJitFn)(); - if (pICorJitCompiler == NULL) - { - Error(W("Unable to initialize Jit Compiler: %s\r\n"), pwzJitName); - ThrowLastError(); - } - - // Check the JIT version identifier. - - GUID versionId; - memset(&versionId, 0, sizeof(GUID)); - pICorJitCompiler->getVersionIdentifier(&versionId); - - if (memcmp(&versionId, &JITEEVersionIdentifier, sizeof(GUID)) != 0) - { - // Mismatched version ID. Fail the load. - Error(W("Jit Compiler has wrong version identifier\r\n")); - ThrowHR(E_FAIL); - } - - // The JIT has loaded and passed the version identifier test, so publish the JIT interface to the caller. - *ppICorJitCompiler = pICorJitCompiler; -} - -void Zapper::InitEE(BOOL fForceDebug, BOOL fForceProfile, BOOL fForceInstrument) -{ - if (m_pEECompileInfo != NULL) - return; - -#if defined(FEATURE_COMINTEROP) - // - // Initialize COM - // - - if (!m_fromDllHost) - { - CoInitializeEx(NULL, COINIT_MULTITHREADED); - } - -#endif // FEATURE_COMINTEROP - - // - // Get EE compiler interface and initialize the EE - // - - m_pEECompileInfo = GetCompileInfo(); - - if (m_pOpt->m_statOptions) - IfFailThrow(m_pEECompileInfo->SetVerboseLevel (CORCOMPILE_STATS)); - - if (m_pOpt->m_verbose) - IfFailThrow(m_pEECompileInfo->SetVerboseLevel (CORCOMPILE_VERBOSE)); - - IfFailThrow(m_pEECompileInfo->Startup(fForceDebug, fForceProfile, fForceInstrument)); - - m_pEEJitInfo = GetZapJitInfo(); - - // - // Get JIT interface - // - -#ifdef FEATURE_MERGE_JIT_AND_ENGINE - jitStartup(m_pEECompileInfo->GetJitHost()); - m_pJitCompiler = getJit(); - - if (m_pJitCompiler == NULL) - { - Error(W("Unable to initialize Jit Compiler\r\n")); - ThrowLastError(); - } -#else - - LPCWSTR pwzJitName = nullptr; - - // Try to obtain a name for the jit library from the env. variable - IfFailThrow(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_JitName, const_cast(&pwzJitName))); - if (pwzJitName == nullptr) - { - pwzJitName = CorCompileGetRuntimeDllName(CROSSGEN_COMPILER_INFO); - } - - LoadAndInitializeJITForNgen(pwzJitName, &m_hJitLib, &m_pJitCompiler); - -#endif // FEATURE_MERGE_JIT_AND_ENGINE - -#ifdef ALLOW_SXS_JIT_NGEN - - // Do not load altjit unless COMPlus_AltJitNgen is set. - LPWSTR altJit; - HRESULT hr = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_AltJitNgen, &altJit); - if (FAILED(hr)) - { - Error(W("Unable to load alternative Jit Compiler\r\n")); - ThrowHR(hr); - } - - m_hAltJITCompiler = NULL; - m_alternateJit = NULL; - - if (altJit != NULL) - { - // Allow a second jit to be loaded into the system. - // - LPCWSTR altName; - hr = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_AltJitName, (LPWSTR*)&altName); - if (FAILED(hr)) - { - Error(W("Unable to load alternative Jit Compiler\r\n")); - ThrowHR(hr); - } - - if (altName == NULL) - { - #ifdef TARGET_WINDOWS -#ifdef TARGET_X86 - altName = MAKEDLLNAME_W(W("clrjit_win_x86_x86")); -#elif defined(TARGET_AMD64) - altName = MAKEDLLNAME_W(W("clrjit_win_x64_x64")); -#elif defined(TARGET_ARM) - altName = MAKEDLLNAME_W(W("clrjit_win_arm_arm")); -#elif defined(TARGET_ARM64) - altName = MAKEDLLNAME_W(W("clrjit_win_arm64_arm64")); -#endif -#else // TARGET_WINDOWS -#ifdef TARGET_X86 - altName = MAKEDLLNAME_W(W("clrjit_unix_x86_x86")); -#elif defined(TARGET_AMD64) - altName = MAKEDLLNAME_W(W("clrjit_unix_x64_x64")); -#elif defined(TARGET_ARM) - altName = MAKEDLLNAME_W(W("clrjit_unix_arm_arm")); -#elif defined(TARGET_ARM64) - altName = MAKEDLLNAME_W(W("clrjit_unix_arm64_arm64")); -#endif -#endif // TARGET_WINDOWS - } - - LoadAndInitializeJITForNgen(altName, &m_hAltJITCompiler, &m_alternateJit); - } -#endif // ALLOW_SXS_JIT_NGEN -} - -Zapper::~Zapper() -{ - DestroyDomain(); - - if (m_pMetaDataDispenser != NULL) - m_pMetaDataDispenser->Release(); - - if (m_fFreeZapperOptions) - { - if (m_pOpt != NULL) - delete m_pOpt; - m_pOpt = NULL; - } - - if (m_pEECompileInfo != NULL) - { -#ifndef FEATURE_MERGE_JIT_AND_ENGINE -#ifdef TARGET_AMD64 - if (m_hJitLegacy != NULL) - { - _ASSERTE(m_hJitLib != NULL); - _ASSERTE(m_pJitCompiler != NULL); - - FreeLibrary(m_hJitLegacy); - } -#endif - if (m_hJitLib != NULL) - FreeLibrary(m_hJitLib); -#endif - -#ifdef ALLOW_SXS_JIT_NGEN - if (m_hAltJITCompiler != NULL) - FreeLibrary(m_hAltJITCompiler); -#endif - -#ifdef FEATURE_COMINTEROP - if (!m_fromDllHost) - { - CoUninitialize(); - } -#endif // FEATURE_COMINTEROP - } -} - -void Zapper::DestroyDomain() -{ - CleanupAssembly(); - - // - // Shut down JIT compiler. - // - - if (m_pJitCompiler != NULL) - { - m_pJitCompiler->ProcessShutdownWork(NULL); - } - - // - // Get rid of domain. - // - - if (m_pDomain != NULL) - { - m_pEECompileInfo->DestroyDomain(m_pDomain); - m_pDomain = NULL; - } -} - -void Zapper::CleanupAssembly() -{ - if (m_pAssemblyEmit != NULL) - { - m_pAssemblyEmit->Release(); - m_pAssemblyEmit = NULL; - } - - if (m_pAssemblyImport != NULL) - { - m_pAssemblyImport->Release(); - m_pAssemblyImport = NULL; - } -} - - -//********************************************************************** -// Copy of vm\i386\cgenCpu.h -// @TODO : clean this up. There has to be a way of sharing this code - -//********************************************************************** -// To be used with GetSpecificCpuInfo() -#ifdef TARGET_X86 - -#define CPU_X86_FAMILY(cpuType) (((cpuType) & 0x0F00) >> 8) -#define CPU_X86_MODEL(cpuType) (((cpuType) & 0x00F0) >> 4) -// Stepping is masked out by GetSpecificCpuInfo() -// #define CPU_X86_STEPPING(cpuType) (((cpuType) & 0x000F) ) - -#define CPU_X86_USE_CMOV(cpuFeat) (((cpuFeat) & 0x00008001) == 0x00008001) -#define CPU_X86_USE_SSE2(cpuFeat) (((cpuFeat) & 0x04000000) == 0x04000000) - -// Values for CPU_X86_FAMILY(cpuType) -#define CPU_X86_486 4 -#define CPU_X86_PENTIUM 5 -#define CPU_X86_PENTIUM_PRO 6 -#define CPU_X86_PENTIUM_4 0xF - -// Values for CPU_X86_MODEL(cpuType) for CPU_X86_PENTIUM_PRO -#define CPU_X86_MODEL_PENTIUM_PRO_BANIAS 9 // Pentium M (Mobile PPro with P4 feautres) - -#endif - - -BOOL Zapper::IsAssembly(LPCWSTR path) -{ - HandleHolder hFile = WszCreateFile(path, - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); - - if (hFile == INVALID_HANDLE_VALUE) - return FALSE; - - IMAGE_DOS_HEADER dos; - - DWORD count; - if (!ReadFile(hFile, &dos, sizeof(dos), &count, NULL) - || count != sizeof(dos)) - return FALSE; - - if (dos.e_magic != IMAGE_DOS_SIGNATURE || dos.e_lfanew == 0) - return FALSE; - - if( SetFilePointer(hFile, dos.e_lfanew, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) - return FALSE; - - IMAGE_NT_HEADERS nt; - if (!ReadFile(hFile, &nt, sizeof(nt), &count, NULL) - || count != sizeof(nt)) - return FALSE; - - if (nt.Signature != IMAGE_NT_SIGNATURE) - return FALSE; - - IMAGE_DATA_DIRECTORY* pDataDirectory = NULL; - - // We accept pe32 or pe64 file formats - - if (nt.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) - { - if (nt.FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER32)) - return FALSE; - - IMAGE_NT_HEADERS32* pNTHeader32 = (IMAGE_NT_HEADERS32*) &nt.OptionalHeader; - pDataDirectory = &pNTHeader32->OptionalHeader.DataDirectory[0]; - } - else if (nt.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) - { - if (nt.FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER64)) - return FALSE; - - IMAGE_NT_HEADERS64* pNTHeader64 = (IMAGE_NT_HEADERS64*) &nt.OptionalHeader; - pDataDirectory = &pNTHeader64->OptionalHeader.DataDirectory[0]; - } - else - return FALSE; - - if ((pDataDirectory[IMAGE_DIRECTORY_ENTRY_COMHEADER].VirtualAddress == 0) || - (pDataDirectory[IMAGE_DIRECTORY_ENTRY_COMHEADER].Size < sizeof(IMAGE_COR20_HEADER))) - { - return FALSE; - } - - return TRUE; -} - -void Zapper::SetContextInfo(LPCWSTR assemblyName) -{ - // A special case: If we're compiling CoreLib, ignore m_exeName and don't set any context. - // There can only be one CoreLib in the runtime, independent of any context. If we don't - // check for CoreLib, and isExe == true, then CompilationDomain::SetContextInfo will call - // into CoreLib and cause the resulting System.Private.CoreLib.ni.dll to be slightly different (checked - // build only). - if (assemblyName != NULL && _wcsnicmp(assemblyName, CoreLibName_W, CoreLibNameLen) == 0 && (wcslen(assemblyName) == CoreLibNameLen || assemblyName[CoreLibNameLen] == W(','))) - { - return; - } - - // Determine whether the root is an exe or a dll - - StackSString s(m_exeName); - - //These locals seem necessary for gcc do resolve the overload correctly - SString literalExe(SString::Literal, W(".exe")); - SString literalDll(SString::Literal, W(".dll")); - BOOL isExe = (s.GetCount() > 4) && s.MatchCaseInsensitive(s.End() - 4, literalExe); - BOOL isDll = (s.GetCount() > 4) && s.MatchCaseInsensitive(s.End() - 4, literalDll); - - DWORD attributes = WszGetFileAttributes(m_exeName); - if (attributes != INVALID_FILE_ATTRIBUTES) - { - if (isExe) - { - // If it's an exe, set it as the config - m_pDomain->SetContextInfo(m_exeName, TRUE); - } - else if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) - { - // If it's a directory, set it as the default app base - m_pDomain->SetContextInfo(m_exeName, FALSE); - } - else if (isDll) - { - // If it's a dll, then set a default app base of the directory containing the dll - SString::Iterator i = s.End(); - if (s.FindBack(i, W("\\"))) - { - s.Truncate(i); - m_pDomain->SetContextInfo(s.GetUnicode(), FALSE); - } - } - } -} - -void Zapper::CreateDependenciesLookupDomainInCurrentDomain() -{ - SetContextInfo(); -} - - -void ZapperSetBindingPaths(ICorCompilationDomain *pDomain, SString &trustedPlatformAssemblies, SString &platformResourceRoots, SString &appPaths, SString &appNiPaths); - -void Zapper::CreateCompilationDomain() -{ - - BOOL fForceDebug = FALSE; - if (!m_pOpt->m_autodebug) - fForceDebug = m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); - - BOOL fForceProfile = m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE); - BOOL fForceInstrument = m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR); - - InitEE(fForceDebug, fForceProfile, fForceInstrument); - - // Make a compilation domain for the assembly. Note that this will - // collect the assembly dependencies for use in the version info, as - // well as isolating the compilation code. - - IfFailThrow(m_pEECompileInfo->CreateDomain(&m_pDomain, - CreateAssemblyEmitter(), - fForceDebug, - fForceProfile, - fForceInstrument)); - - // we support only TPA binding on CoreCLR - - if (!m_trustedPlatformAssemblies.IsEmpty()) - { - // TPA-based binding - // Add the trusted paths and apppath to the binding list - ZapperSetBindingPaths(m_pDomain, m_trustedPlatformAssemblies, m_platformResourceRoots, m_appPaths, m_appNiPaths); - } -} - -void Zapper::CreateDependenciesLookupDomain() -{ - CreateCompilationDomain(); - CreateDependenciesLookupDomainInCurrentDomain(); -} - -void Zapper::CreatePdb(BSTR pAssemblyPathOrName, BSTR pNativeImagePath, BSTR pPdbPath, BOOL pdbLines, BSTR pManagedPdbSearchPath) -{ -#ifdef CROSSGEN_COMPILE - CreateCompilationDomain(); -#endif - - EX_TRY - { - CORINFO_ASSEMBLY_HANDLE hAssembly = NULL; - - IfFailThrow(m_pEECompileInfo->LoadAssemblyByPath( - pAssemblyPathOrName, - - // fExplicitBindToNativeImage: On the phone, a path to the NI is specified - // explicitly (even with .ni. in the name). All other callers specify a path to - // the IL, and the NI is inferred, so this is normally FALSE in those other - // cases. - TRUE, - - &hAssembly)); - - - // Ensure all modules belonging to this assembly get loaded. The CreatePdb() call - // below will iterate through them via the ModuleIterator to generate PDB files for each - // one, and the ModuleIterator assumes they've been loaded. - IMDInternalImport * pMDImport = m_pEECompileInfo->GetAssemblyMetaDataImport(hAssembly); - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumAllInit(mdtFile); - mdFile tkFile; - while (pMDImport->EnumNext(&hEnum, &tkFile)) - { - LPCSTR szName; - DWORD flags; - IfFailThrow(pMDImport->GetFileProps(tkFile, &szName, NULL, NULL, &flags)); - - if (!IsFfContainsMetaData(flags)) - continue; - - CORINFO_MODULE_HANDLE hModule; - IfFailThrow(m_pEECompileInfo->LoadAssemblyModule(hAssembly, - tkFile, &hModule)); - } - - LPCWSTR pDiasymreaderPath = nullptr; -#if !defined(NO_NGENPDB) - if (m_DiasymreaderPath.GetCount() > 0) - { - pDiasymreaderPath = m_DiasymreaderPath.GetUnicode(); - } -#endif //!defined(NO_NGENPDB) - - IfFailThrow(::CreatePdb(hAssembly, pNativeImagePath, pPdbPath, pdbLines, pManagedPdbSearchPath, pDiasymreaderPath)); - } - EX_CATCH - { - // Print the error message - - Error(W("Error generating PDB for '%s': "), pNativeImagePath); - PrintErrorMessage(CORZAP_LOGLEVEL_ERROR, GET_EXCEPTION()); - Error(W("\n")); - EX_RETHROW; - } - EX_END_CATCH(RethrowTerminalExceptions); -} - -void Zapper::ComputeDependencies(LPCWSTR pAssemblyName, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig) -{ -} - - -// -// Compile a module by name -// - -HRESULT Zapper::Compile(LPCWSTR string, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig) -{ - HRESULT hr = S_OK; - - bool fCoreLib = false; - LPCWSTR fileName = PathFindFileName(string); - if (fileName != NULL && SString::_wcsicmp(fileName, g_pwBaseLibrary) == 0) - { - fCoreLib = true; - } - - - if (fCoreLib) - { - // - // Disallow use of native image to force a new native image generation for CoreLib - // - g_fAllowNativeImages = false; - } - - // the errors in CreateCompilationDomain are fatal - propogate them up - CreateCompilationDomain(); - - EX_TRY - { - CompileInCurrentDomain(string, pNativeImageSig); - } - EX_CATCH - { - // Print the error message - - Error(W("Error compiling %s: "), string); - PrintErrorMessage(CORZAP_LOGLEVEL_ERROR, GET_EXCEPTION()); - Error(W("\n")); - - hr = GET_EXCEPTION()->GetHR(); - } - EX_END_CATCH(SwallowAllExceptions); - - // the errors in DestroyDomain are fatal - propogate them up - DestroyDomain(); - - return hr; -} - -void Zapper::DontUseProfileData() -{ - // Call this before calling Compile() - - m_pOpt->m_ignoreProfileData = true; -} - -bool Zapper::HasProfileData() -{ - // Only valid after calling Compile() - return m_pOpt->m_fHasAnyProfileData; -} - -// Helper function for Zapper::Compile(LPCWSTR string) -// - -void Zapper::CompileInCurrentDomain(__in LPCWSTR string, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig) -{ - STATIC_CONTRACT_ENTRY_POINT; - - BEGIN_ENTRYPOINT_VOIDRET; - - - - // - // Load the assembly. - // - // "string" may be a path or assembly display name. - // To decide, we see if it is the name of a valid file. - // - - _ASSERTE(m_hAssembly == NULL); - - //without fusion, this has to be a file name - { - IfFailThrow(m_pEECompileInfo->LoadAssemblyByPath(string, FALSE /* fExplicitBindToNativeImage */, &m_hAssembly)); - } - - - // - // Compile the assembly - // - CompileAssembly(pNativeImageSig); - - goto Exit; // Avoid warning about unreferenced label - -Exit: - END_ENTRYPOINT_VOIDRET; - - return; -} - - -//------------------------------------------------------------------------------ - -// Is this is a valid file-system file name? - -bool StringHasLegalFileNameChars(LPCWSTR assemblyName) -{ - if (wcschr(assemblyName, ':') || wcschr(assemblyName, '/') || wcschr(assemblyName, '\\') || - wcschr(assemblyName, '*') || wcschr(assemblyName, '?') || wcschr(assemblyName, '"') || - wcschr(assemblyName, '<') || wcschr(assemblyName, '>') || wcschr(assemblyName, '|')) - return false; - - return true; -} - -IMetaDataAssemblyEmit * Zapper::CreateAssemblyEmitter() -{ - _ASSERTE(!m_pAssemblyEmit); - - // - // Make a manifest emitter for the zapped assembly. - // - - // Hardwire the metadata version to be the current runtime version so that the ngen image - // does not change when the directory runtime is installed in different directory (e.g. v2.0.x86chk vs. v2.0.80826). - BSTRHolder strVersion(SysAllocString(CLR_METADATA_VERSION_L)); - VARIANT versionOption; - V_VT(&versionOption) = VT_BSTR; - V_BSTR(&versionOption) = strVersion; - IfFailThrow(m_pMetaDataDispenser->SetOption(MetaDataRuntimeVersion, &versionOption)); - - IfFailThrow(m_pMetaDataDispenser->DefineScope(CLSID_CorMetaDataRuntime, - 0, IID_IMetaDataAssemblyEmit, - (IUnknown **) &m_pAssemblyEmit)); - - return m_pAssemblyEmit; -} - -void Zapper::InitializeCompilerFlags(CORCOMPILE_VERSION_INFO * pVersionInfo) -{ - m_pOpt->m_compilerFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); - m_pOpt->m_compilerFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE); - m_pOpt->m_compilerFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE); - m_pOpt->m_compilerFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROF_NO_PINVOKE_INLINE); - - // We track debug info all the time in the ngen image - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); - - if (pVersionInfo->wCodegenFlags & CORCOMPILE_CODEGEN_DEBUGGING) - { - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE); - } - - if (pVersionInfo->wCodegenFlags & CORCOMPILE_CODEGEN_PROFILING) - { - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE); - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROF_NO_PINVOKE_INLINE); - m_pOpt->m_ngenProfileImage = true; - } - - if (pVersionInfo->wCodegenFlags & CORCOMPILE_CODEGEN_PROF_INSTRUMENTING) - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR); - - // Set CORJIT_FLAG_MIN_OPT only if COMPlus_JitMinOpts == 1 - static ConfigDWORD g_jitMinOpts; - if (g_jitMinOpts.val(CLRConfig::UNSUPPORTED_JITMinOpts) == 1) - { - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_MIN_OPT); - } - -#if defined(TARGET_X86) - - // @TODO: This is a copy of SetCpuInfo() in vm\codeman.cpp. Unify the implementaion - - switch (CPU_X86_FAMILY(pVersionInfo->cpuInfo.dwCPUType)) - { - case CPU_X86_PENTIUM_4: - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_TARGET_P4); - break; - - default: - break; - } - - if (CPU_X86_USE_CMOV(pVersionInfo->cpuInfo.dwFeatures)) - { - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_CMOV); - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_FCOMI); - } - -#endif // TARGET_X86 - -#if defined(TARGET_X86) || defined(TARGET_AMD64) - // .NET Core requires SSE2. - m_pOpt->m_compilerFlags.Set(InstructionSet_X86Base); - m_pOpt->m_compilerFlags.Set(InstructionSet_SSE); - m_pOpt->m_compilerFlags.Set(InstructionSet_SSE2); -#endif -#if defined(TARGET_ARM64) - m_pOpt->m_compilerFlags.Set(InstructionSet_ArmBase); - m_pOpt->m_compilerFlags.Set(InstructionSet_AdvSimd); -#endif - -#if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM64) - // If we're crossgenning CoreLib, allow generating non-VEX intrinsics. The generated code might - // not actually be supported by the processor at runtime so we compensate for it by - // not letting the get_IsSupported method to be intrinsically expanded in crossgen - // (see special handling around CORINFO_FLG_JIT_INTRINSIC in ZapInfo). - // That way the actual support checks will always be jitted. - // We only do this for CoreLib because forgetting to wrap intrinsics under IsSupported - // checks can lead to illegal instruction traps (instead of a nice managed exception). - if (m_pEECompileInfo->GetAssemblyModule(m_hAssembly) == m_pEECompileInfo->GetLoaderModuleForCoreLib()) - { - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_FEATURE_SIMD); - -#if defined(TARGET_X86) || defined(TARGET_AMD64) - m_pOpt->m_compilerFlags.Set(InstructionSet_AES); - m_pOpt->m_compilerFlags.Set(InstructionSet_PCLMULQDQ); - m_pOpt->m_compilerFlags.Set(InstructionSet_SSE3); - m_pOpt->m_compilerFlags.Set(InstructionSet_SSSE3); - m_pOpt->m_compilerFlags.Set(InstructionSet_SSE41); - m_pOpt->m_compilerFlags.Set(InstructionSet_SSE42); - m_pOpt->m_compilerFlags.Set(InstructionSet_POPCNT); - // Leaving out InstructionSet_AVX, InstructionSet_FMA, InstructionSet_AVX2, - // InstructionSet_BMI1, InstructionSet_BMI2 on purpose - these require VEX encodings - // and the JIT doesn't support generating code for methods with mixed encodings. - // Also leaving out InstructionSet_LZCNT because BSR from InstructionSet_X86Base - // is used as a fallback in CoreLib and doesn't require an IsSupported check. -#endif // defined(TARGET_X86) || defined(TARGET_AMD64) - } -#endif // defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM64) - m_pOpt->m_compilerFlags.Set64BitInstructionSetVariants(); - m_pOpt->m_compilerFlags.EnsureValidInstructionSetSupport(); - - if ( m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO) - && m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE) - && m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE)) - { - // - // We've decided not to support debugging + optimizations disabled + profiling to - // cut down on the testing matrix, under the assertion that the combination isn't - // particularly common or useful. (It's still supported in normal jit mode though.) - // - - Error(W("The CLR doesn't support precompiled code when using both debugging and profiling") - W(" instrumentation.\n")); - ThrowHR(E_NOTIMPL); - } -} - -void Zapper::DefineOutputAssembly(SString& strAssemblyName, ULONG * pHashAlgId) -{ - mdAssembly tkAssembly; - IfFailThrow(m_pAssemblyImport->GetAssemblyFromScope(&tkAssembly)); - - AssemblyMetaDataInternal internalMetadata; - - const void *pbPublicKey; - ULONG cbPublicKey; - ULONG hashAlgId; - LPCSTR szAssemblyName; - DWORD flags; - - IfFailThrow(m_pAssemblyImport->GetAssemblyProps(tkAssembly, &pbPublicKey, &cbPublicKey, - &hashAlgId, &szAssemblyName, &internalMetadata, &flags)); - - strAssemblyName.SetUTF8(szAssemblyName); - - ASSEMBLYMETADATA metadata; - SString strLocale; - - metadata.usMajorVersion = internalMetadata.usMajorVersion; - metadata.usMinorVersion = internalMetadata.usMinorVersion; - metadata.usBuildNumber = internalMetadata.usBuildNumber; - metadata.usRevisionNumber = internalMetadata.usRevisionNumber; - if (internalMetadata.szLocale) - { - strLocale.SetUTF8(internalMetadata.szLocale); - metadata.szLocale = (LPWSTR)strLocale.GetUnicode(); - metadata.cbLocale = strLocale.GetCount() + 1; - } - else - { - metadata.szLocale = NULL; - metadata.cbLocale = 0; - } - metadata.rProcessor = NULL; - metadata.ulProcessor = 0; - metadata.rOS = NULL; - metadata.ulOS = 0; - - LPCWSTR wszAssemblyName = strAssemblyName.GetUnicode(); - - // If assembly name (and hence fileName) has invalid characters, - // GenerateFile() will fail later on. - // StringHasLegalFileNameChars is a ngen restriction. - - if (!StringHasLegalFileNameChars(wszAssemblyName)) - { - Error(W("Error: Assembly name \"%s\" contains illegal (unsupported) file name characters.\n"), wszAssemblyName); - ThrowHR(HRESULT_FROM_WIN32(ERROR_INVALID_NAME)); - } - -#ifndef TARGET_UNIX - // - // We always need a hash since our assembly module is separate from the manifest. - // Use MD5 by default. - // - - if (hashAlgId == 0) - hashAlgId = CALG_MD5; -#endif - - mdAssembly tkEmitAssembly; - IfFailThrow(m_pAssemblyEmit->DefineAssembly(pbPublicKey, cbPublicKey, hashAlgId, - wszAssemblyName, &metadata, - flags, &tkEmitAssembly)); - - *pHashAlgId = hashAlgId; -} - -// -// This is the main worker function (at the assembly level). -// -// Zapper::CompileInCurrentDomain() ends up calling this function. - -void Zapper::CompileAssembly(CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig) -{ - _ASSERTE(m_pDomain != NULL); // This must be set up by this time. - _ASSERTE(m_hAssembly != NULL); - - CORINFO_MODULE_HANDLE hAssemblyModule = m_pEECompileInfo->GetAssemblyModule(m_hAssembly); - - CORCOMPILE_VERSION_INFO versionInfo; - - IfFailThrow(m_pEECompileInfo->GetAssemblyVersionInfo(m_hAssembly, - &versionInfo)); - - InitializeCompilerFlags(&versionInfo); - - // - // Set up the output path. - // - - // - // If we don't have fusion, we just create the file right at the target. No need to do an install. - // - { - SString strAssemblyPath = GetOutputFileName(); - - if (strAssemblyPath.IsEmpty()) - { - m_pEECompileInfo->GetModuleFileName(hAssemblyModule, strAssemblyPath); - } - - const WCHAR * assemblyPath = strAssemblyPath.GetUnicode(); - const WCHAR * pathend = wcsrchr( assemblyPath, DIRECTORY_SEPARATOR_CHAR_W ); - if( pathend ) - { - m_outputPath.Set(assemblyPath, COUNT_T(pathend - assemblyPath)); - } - else - { - m_outputPath.Set(W(".") DIRECTORY_SEPARATOR_STR_W); - } - } - - // - // Get the manifest metadata. - // - - m_pAssemblyImport = m_pEECompileInfo->GetAssemblyMetaDataImport(m_hAssembly); - - // - // Copy the relevant assembly info to the zap manifest - // - - SString strAssemblyName; - ULONG hashAlgId; - DefineOutputAssembly(strAssemblyName, &hashAlgId); - - SString strNativeImagePath; - SString strNativeImageTempPath; - HANDLE hFile = INVALID_HANDLE_VALUE; - StackSArray hFiles; - - { - // - // Compile the manifest module (if manifest is not stand-alone). - // - - NewHolder pAssemblyModule; - - pAssemblyModule = CompileModule(hAssemblyModule, m_pAssemblyEmit); - - // - // The loader (currently) requires all modules of an ngen-ed multi-module - // assembly to be ngen-ed. - // - - - // - // Record the version info - // - - pAssemblyModule->SetVersionInfo(&versionInfo); - - // - // Record Dependencies - // - - if (!IsReadyToRunCompilation()) - { - CORCOMPILE_DEPENDENCY *pDependencies; - DWORD cDependencies; - IfFailThrow(m_pDomain->GetDependencies(&pDependencies, &cDependencies)); - - pAssemblyModule->SetDependencies(pDependencies, cDependencies); - } - - // Write the main assembly module - strNativeImagePath = GetOutputFileName(); - - if (strNativeImagePath.IsEmpty()) - { - strNativeImagePath.Set(m_outputPath, SL(DIRECTORY_SEPARATOR_STR_W), strAssemblyName, - pAssemblyModule->m_ModuleDecoder.IsDll() ? SL(W(".ni.dll")) : SL(W(".ni.exe"))); - } - - pAssemblyModule->SetPdbFileName(SString(strAssemblyName, SL(W(".ni.pdb")))); - - strNativeImageTempPath = strNativeImagePath; - strNativeImageTempPath.Append(W(".tmp")); - - hFile = pAssemblyModule->SaveImage(strNativeImageTempPath.GetUnicode(), strNativeImagePath.GetUnicode(), pNativeImageSig); - } - - // Throw away the assembly if we have hit fatal error during compilation - if (FAILED(g_hrFatalError)) - ThrowHR(g_hrFatalError); - - - // Close the file - CloseHandle(hFile); - for (SArray::Iterator i = hFiles.Begin(); i != hFiles.End(); ++i) - { - CloseHandle(*i); - } - - if (!WszMoveFileEx(strNativeImageTempPath.GetUnicode(), strNativeImagePath.GetUnicode(), MOVEFILE_REPLACE_EXISTING)) - { - ThrowLastError(); - } - - if (!m_pOpt->m_silent) - { - GetSvcLogger()->Printf(W("Native image %s generated successfully.\n"), strNativeImagePath.GetUnicode()); - } - -} - - -ZapImage * Zapper::CompileModule(CORINFO_MODULE_HANDLE hModule, - IMetaDataAssemblyEmit *pAssemblyEmit) -{ - NewHolder module; - - BYTE * pMemory = new BYTE[sizeof(ZapImage)]; - ZeroMemory(pMemory, sizeof(ZapImage)); - - module = new (pMemory) ZapImage(this); - - // Finish initializing the ZapImage object - // any calls that could throw an exception are done in ZapImage::Initialize() - // - module->ZapWriter::Initialize(); - - // - // Set target - // - - IfFailThrow(m_pEECompileInfo->SetCompilationTarget(m_hAssembly, hModule)); - - // - // Open input file - // - - Info(W("Opening input file\n")); - - module->Open(hModule, pAssemblyEmit); - - // - // input module. - // - - Info(W("Preloading input file %s\n"), module->m_pModuleFileName); - - module->Preload(); - - // - // Compile input module - // - - Info(W("Compiling input file %s\n"), module->m_pModuleFileName); - - module->Compile(); - - if (!IsReadyToRunCompilation()) - { - // - // Link preloaded module. - // - - Info(W("Linking preloaded input file %s\n"), module->m_pModuleFileName); - - module->LinkPreload(); - } - return module.Extract(); -} - - -void Zapper::Success(LPCWSTR format, ...) -{ - va_list args; - va_start(args, format); - - Print(CORZAP_LOGLEVEL_SUCCESS, format, args); - - va_end(args); -} - -void Zapper::Error(LPCWSTR format, ...) -{ - // Preserve last error so we can still do ThrowLastError() after printing the message - DWORD err = GetLastError(); - - va_list args; - va_start(args, format); - - Print(CORZAP_LOGLEVEL_ERROR, format, args); - - va_end(args); - - SetLastError(err); -} - -void Zapper::Warning(LPCWSTR format, ...) -{ - // Preserve last error so we can still do ThrowLastError() after printing the message - DWORD err = GetLastError(); - - va_list args; - va_start(args, format); - - Print(CORZAP_LOGLEVEL_WARNING, format, args); - - va_end(args); - - SetLastError(err); -} - -void Zapper::Info(LPCWSTR format, ...) -{ - va_list args; - va_start(args, format); - - Print(CORZAP_LOGLEVEL_INFO, format, args); - - va_end(args); -} - -void Zapper::Print(CorZapLogLevel level, LPCWSTR format, ...) -{ - va_list args; - va_start(args, format); - - Print(level, format, args); - - va_end(args); -} - -void Zapper::Print(CorZapLogLevel level, LPCWSTR format, va_list args) -{ - const int BUFF_SIZE = 1024; - WCHAR output[BUFF_SIZE]; - - switch (level) - { - case CORZAP_LOGLEVEL_INFO: - if (!m_pOpt->m_verbose) - return; - break; - - case CORZAP_LOGLEVEL_ERROR: - case CORZAP_LOGLEVEL_WARNING: - break; - - case CORZAP_LOGLEVEL_SUCCESS: - if (m_pOpt->m_silent) - return; - break; - } - - CorSvcLogLevel logLevel = (CorSvcLogLevel)0; - switch (level) - { - case CORZAP_LOGLEVEL_INFO: - logLevel = LogLevel_Info; - break; - - case CORZAP_LOGLEVEL_ERROR: - logLevel = LogLevel_Error; - break; - - case CORZAP_LOGLEVEL_WARNING: - logLevel = LogLevel_Warning; - break; - - case CORZAP_LOGLEVEL_SUCCESS: - logLevel = LogLevel_Success; - break; - } - - _vsnwprintf_s(output, BUFF_SIZE, BUFF_SIZE - 1, format, args); - output[BUFF_SIZE-1] = 0; - - GetSvcLogger()->Log(output, logLevel); -} - -void Zapper::PrintErrorMessage(CorZapLogLevel level, Exception *ex) -{ - StackSString message; - ex->GetMessage(message); - Print(level, W("%s"), message.GetUnicode()); -} - -void Zapper::PrintErrorMessage(CorZapLogLevel level, HRESULT hr) -{ - StackSString message; - GetHRMsg(hr, message); - Print(level, W("%s"), message.GetUnicode()); -} - -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) -void Zapper::SetCLRJITPath(LPCWSTR pwszCLRJITPath) -{ - m_CLRJITPath.Set(pwszCLRJITPath); -} - -void Zapper::SetDontLoadJit() -{ - m_fDontLoadJit = true; -} -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) - -#if !defined(NO_NGENPDB) -void Zapper::SetDiasymreaderPath(LPCWSTR pwzDiasymreaderPath) -{ - m_DiasymreaderPath.Set(pwzDiasymreaderPath); -} -#endif // !defined(NO_NGENPDB) - - -void Zapper::SetPlatformAssembliesPaths(LPCWSTR pwzPlatformAssembliesPaths) -{ - m_platformAssembliesPaths.Set(pwzPlatformAssembliesPaths); -} - -void Zapper::SetTrustedPlatformAssemblies(LPCWSTR pwzTrustedPlatformAssemblies) -{ - m_trustedPlatformAssemblies.Set(pwzTrustedPlatformAssemblies); -} - -void Zapper::SetPlatformResourceRoots(LPCWSTR pwzPlatformResourceRoots) -{ - m_platformResourceRoots.Set(pwzPlatformResourceRoots); -} - -void Zapper::SetAppPaths(LPCWSTR pwzAppPaths) -{ - m_appPaths.Set(pwzAppPaths); -} - -void Zapper::SetAppNiPaths(LPCWSTR pwzAppNiPaths) -{ - m_appNiPaths.Set(pwzAppNiPaths); -} - -void Zapper::SetOutputFilename(LPCWSTR pwzOutputFilename) -{ - m_outputFilename.Set(pwzOutputFilename); -} - - -SString Zapper::GetOutputFileName() -{ - return m_outputFilename; -} - - -void Zapper::SetCustomBaseAddress(SIZE_T baseAddress) -{ - m_customBaseAddress = baseAddress; -} - -SIZE_T Zapper::GetCustomBaseAddress() -{ - return m_customBaseAddress; -} diff --git a/src/coreclr/zap/zapperstats.cpp b/src/coreclr/zap/zapperstats.cpp deleted file mode 100644 index 9379cd39239968..00000000000000 --- a/src/coreclr/zap/zapperstats.cpp +++ /dev/null @@ -1,246 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/* - - */ - - -#include "common.h" - -namespace -{ -// some helper functions -// - -template < typename T > -void init_array( T * arr, size_t size ) -{ - ::ZeroMemory( arr, size * sizeof( T ) ); -} - - -// locals -// - -const char * const fixupNames[] = -{ - "Class Handle", - "Field Handle", - "Method Handle", - "Function Call/Pointer", - "Sync", - "Pinvoke", - "Profiling Handle", - "Interface Table", - "Module Handle", - "Module Domain ID", - "Class Domain ID", - "Field Address", - "Varargs Handle", - "String", - "Init Class", - "Load Class", - "Stub Dispatch", - "Active Dependency" -}; - -const char * const callReasons[] = -{ - "Unknown", - "Exotic (Not IL or ECall)", - "PInvoke", - "Has Generic Instantiation", - "No code generated yet", - "Method has fixups", - "Prestub may produce stub", - "Remoting interception", - "Contains Cer root", - "Restore method (Generics)", - "Restore first call", - "Restore value type", - "Restore", - "Can't patch", - "Profiling", - "Other loader module", -}; - -static_assert_no_msg((sizeof(callReasons)/sizeof(callReasons[0])) == CORINFO_INDIRECT_CALL_COUNT); - -} - -ZapperStats::ZapperStats() - : m_methods( 0 ) - , m_failedMethods( 0 ) - , m_failedILStubs( 0 ) - , m_ilCodeSize( 0 ) - , m_nativeCodeSize( 0 ) - , m_nativeColdCodeSize( 0 ) - , m_nativeRODataSize( 0 ) - , m_gcInfoSize( 0 ) -#ifdef FEATURE_EH_FUNCLETS - , m_unwindInfoSize( 0 ) -#endif // FEATURE_EH_FUNCLETS - , m_NumHotAllocations( 0 ) - , m_NumHotColdAllocations( 0 ) - , m_NumMediumHeaders( 0 ) - , m_nativeCodeSizeInSplitMethods( 0 ) - , m_nativeColdCodeSizeInSplitMethods( 0 ) - , m_nativeCodeSizeInSplitProfiledMethods( 0 ) - , m_nativeColdCodeSizeInSplitProfiledMethods( 0 ) - , m_nativeCodeSizeInProfiledMethods( 0 ) - , m_nativeColdCodeSizeInProfiledMethods( 0 ) - , m_totalHotCodeSize( 0 ) - , m_totalUnprofiledCodeSize( 0 ) - , m_totalColdCodeSize( 0 ) - , m_totalCodeSizeInProfiledMethods( 0 ) - , m_totalColdCodeSizeInProfiledMethods( 0 ) - , m_inputFileSize( 0 ) - , m_outputFileSize( 0 ) - , m_metadataSize( 0 ) - , m_preloadImageSize( 0 ) - , m_hotCodeMgrSize( 0 ) - , m_unprofiledCodeMgrSize( 0 ) - , m_coldCodeMgrSize( 0 ) - , m_eeInfoTableSize( 0 ) - , m_helperTableSize( 0 ) - , m_dynamicInfoTableSize( 0 ) - , m_dynamicInfoDelayListSize( 0 ) - , m_debuggingTableSize( 0 ) - , m_headerSectionSize( 0 ) - , m_codeSectionSize( 0 ) - , m_coldCodeSectionSize( 0 ) - , m_exceptionSectionSize( 0 ) - , m_readOnlyDataSectionSize( 0 ) - , m_relocSectionSize( 0 ) - , m_ILMetadataSize( 0 ) - , m_externalMethodThunkSize( 0 ) - , m_externalMethodDataSize( 0 ) - , m_prestubMethods( 0 ) - , m_directMethods( 0 ) -{ - init_array( m_indirectMethodReasons, CORINFO_INDIRECT_CALL_COUNT ); -} - -#ifdef _PREFAST_ -#pragma warning(push) -#pragma warning(disable:21000) // Suppress PREFast warning about overly large function -#endif -void ZapperStats::PrintStats() -{ - if (m_outputFileSize > 0) { - - GetSvcLogger()->Printf( "-------------------------------------------------------\n"); - GetSvcLogger()->Printf( "Input file size: %8d\n", m_inputFileSize); - GetSvcLogger()->Printf( "Output file size: %8d\n", m_outputFileSize); - GetSvcLogger()->Printf( "Input file size/Output file size ratio:\t%8.2fx\n", double( m_outputFileSize ) / m_inputFileSize); - GetSvcLogger()->Printf( "\n"); - GetSvcLogger()->Printf( "Metadata: %8d\t%8.2f%%\n", m_metadataSize, (double)m_metadataSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "Debugging maps: %8d\t%8.2f%%\n", m_debuggingTableSize, (double)m_debuggingTableSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "Hot Code manager: %8d\t%8.2f%%\n", m_hotCodeMgrSize, (double)m_hotCodeMgrSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "Unprofiled Code manager: %8d\t%8.2f%%\n", m_unprofiledCodeMgrSize, (double)m_unprofiledCodeMgrSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "Cold Code manager: %8d\t%8.2f%%\n", m_coldCodeMgrSize, (double)m_coldCodeMgrSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "GC info: %8d\t%8.2f%%\n", m_headerSectionSize, (double)m_headerSectionSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "Native code & r/o data: %8d\t%8.2f%%\n", m_codeSectionSize, (double)m_codeSectionSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "Cold code: %8d\t%8.2f%%\n", m_coldCodeSectionSize, (double)m_coldCodeSectionSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "Exception tables: %8d\t%8.2f%%\n", m_exceptionSectionSize, (double)m_exceptionSectionSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "Relocs: %8d\t%8.2f%%\n", m_relocSectionSize, (double)m_relocSectionSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "IL metadata: %8d\t%8.2f%%\n", m_ILMetadataSize, (double)m_ILMetadataSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "External Method Thunks: %8d\t%8.2f%%\n", m_externalMethodThunkSize, (double)m_externalMethodThunkSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "External Method Data: %8d\t%8.2f%%\n", m_externalMethodDataSize, (double)m_externalMethodDataSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "Image of EE structures: %8d\t%8.2f%%\n", m_preloadImageSize, (double)m_preloadImageSize/m_outputFileSize*100); - - unsigned totalIndirections = - m_dynamicInfoDelayListSize + - m_eeInfoTableSize + - m_helperTableSize + - m_dynamicInfoTableSize; - - GetSvcLogger()->Printf( "Indirections: %8d\t%8.2f%%\n", - totalIndirections, (double)totalIndirections/m_outputFileSize*100); - GetSvcLogger()->Printf( " ----- Breakdown of Indirections ----\n"); - - GetSvcLogger()->Printf( " Delay load lists: %8d\t%8.2f%%\n", - m_dynamicInfoDelayListSize, (double)m_dynamicInfoDelayListSize/totalIndirections*100); - GetSvcLogger()->Printf( " Tables: %8d\t%8.2f%%\n", - m_dynamicInfoTableSize, (double)m_dynamicInfoTableSize/totalIndirections*100); - GetSvcLogger()->Printf( " EE Values: %8d\t%8.2f%%\n", - m_eeInfoTableSize, (double)m_eeInfoTableSize/totalIndirections*100); - GetSvcLogger()->Printf( " Helper functions: %8d\t%8.2f%%\n", - m_helperTableSize, (double)m_helperTableSize/totalIndirections*100); - } - - GetSvcLogger()->Printf( " Direct method descs:\t%5d/%5d %8.2f%%\n", - m_directMethods, m_prestubMethods+m_directMethods, - (double)m_directMethods/(m_directMethods+m_prestubMethods)*100); - GetSvcLogger()->Printf( " Indirect method descs:\t%5d/%5d %8.2f%%\n", - m_prestubMethods, m_prestubMethods+m_directMethods, - (double)m_prestubMethods/(m_directMethods+m_prestubMethods)*100); - - for (int i=0; i < CORINFO_INDIRECT_CALL_COUNT; i++) - GetSvcLogger()->Printf( " %-30s %5d %8.2f%%\n", - callReasons[i], - m_indirectMethodReasons[i], - double(m_indirectMethodReasons[i])/(m_directMethods+m_prestubMethods)*100); - - GetSvcLogger()->Printf( "-------------------------------------------------------\n"); - GetSvcLogger()->Printf( "Total Methods: \t\t\t\t%8d\n", m_methods); - GetSvcLogger()->Printf( "Total Hot Only: \t\t\t%8d\n", m_NumHotAllocations); - GetSvcLogger()->Printf( "Total Split (Hot/Cold): \t\t%8d\n", m_NumHotColdAllocations); - GetSvcLogger()->Printf( "Total Medium Headers: \t\t\t%8d\n", m_NumMediumHeaders); - GetSvcLogger()->Printf( "Split Methods: Hot Code \t\t%8d\n", m_nativeCodeSizeInSplitMethods); - GetSvcLogger()->Printf( "Split Methods: Cold Code \t\t%8d\n", m_nativeColdCodeSizeInSplitMethods); - GetSvcLogger()->Printf( "Split Profiled Methods: Hot Code \t%8d\n", m_nativeCodeSizeInSplitProfiledMethods); - GetSvcLogger()->Printf( "Split Profiled Methods: Cold Code \t%8d\n", m_nativeColdCodeSizeInSplitProfiledMethods); - GetSvcLogger()->Printf( "Profiled Methods: Hot Code \t\t%8d\n", m_nativeCodeSizeInProfiledMethods); - GetSvcLogger()->Printf( "Profiled Methods: Cold Code \t\t%8d\n", m_nativeColdCodeSizeInProfiledMethods); - GetSvcLogger()->Printf( "Profiled Methods: Total Hot Code+Headers %7d\n", m_totalCodeSizeInProfiledMethods); - GetSvcLogger()->Printf( "Profiled Methods: Total Cold Code+Headers %6d\n", m_totalColdCodeSizeInProfiledMethods); - GetSvcLogger()->Printf( "All Methods: Total Hot+Unprofiled Code \t\t%8d\n", m_nativeCodeSize); - GetSvcLogger()->Printf( "All Methods: Total Cold Code \t\t%8d\n", m_nativeColdCodeSize); - GetSvcLogger()->Printf( "All Methods: Total Hot Code+Headers \t%8d\n", m_totalHotCodeSize); - GetSvcLogger()->Printf( "All Methods: Total Unprofiled Code+Headers \t%8d\n", m_totalUnprofiledCodeSize); - GetSvcLogger()->Printf( "All Methods: Total Cold Code+Headers \t%8d\n", m_totalColdCodeSize); - - GetSvcLogger()->Printf( "-------------------------------------------------------\n"); - GetSvcLogger()->Printf( "Total IL Code: %8d\n", m_ilCodeSize); - GetSvcLogger()->Printf( "Total Native Code: %8d\n", m_nativeCodeSize + m_nativeColdCodeSize); - GetSvcLogger()->Printf( "Total Code+Headers: %8d\n", m_totalHotCodeSize + m_totalUnprofiledCodeSize + m_totalColdCodeSize); - - GetSvcLogger()->Printf( "Total Native RO Data: %8d\n", m_nativeRODataSize); - GetSvcLogger()->Printf( "Total Native GC Info: %8d\n", m_gcInfoSize); - size_t nativeTotal = m_nativeCodeSize + m_nativeRODataSize + m_gcInfoSize; -#ifdef FEATURE_EH_FUNCLETS - GetSvcLogger()->Printf( "Total Native UnwindInfo:%8d\n", m_unwindInfoSize); - nativeTotal += m_unwindInfoSize; -#endif // FEATURE_EH_FUNCLETS - GetSvcLogger()->Printf( "Total Native Total : %8d\n", nativeTotal); - - if (m_methods > 0) { - GetSvcLogger()->Printf( "\n"); - GetSvcLogger()->Printf( "Average IL Code: %8.2f\n", double(m_ilCodeSize) / m_methods); - GetSvcLogger()->Printf( "Average NativeCode: %8.2f\n", double(m_nativeCodeSize) / m_methods); - GetSvcLogger()->Printf( "Average Native RO Data: %8.2f\n", double(m_nativeRODataSize) / m_methods); - GetSvcLogger()->Printf( "Average Native GC Info: %8.2f\n", double(m_gcInfoSize) / m_methods); -#ifdef FEATURE_EH_FUNCLETS - GetSvcLogger()->Printf( "Average Native UnwindInfo: %8.2f\n", double(m_unwindInfoSize) / m_methods); -#endif // FEATURE_EH_FUNCLETS - GetSvcLogger()->Printf( "Average Native: %8.2f\n", double(nativeTotal) / m_methods); - GetSvcLogger()->Printf( "\n"); - GetSvcLogger()->Printf( "NativeGC / Native: %8.2f\n", double(m_gcInfoSize) / nativeTotal); - GetSvcLogger()->Printf( "Native / IL: %8.2f\n", double(nativeTotal) / m_ilCodeSize); - } - - if (m_failedMethods > 0) - GetSvcLogger()->Printf( "Methods which did not compile: %d\n", m_failedMethods); - if (m_failedILStubs > 0) - GetSvcLogger()->Printf( "IL STUBS which did not compile: %d\n", m_failedILStubs); -} -#ifdef _PREFAST_ -#pragma warning(pop) -#endif - -char const * GetCallReasonString( CorInfoIndirectCallReason reason ) -{ - return callReasons[ reason ]; -} diff --git a/src/coreclr/zap/zapperstats.h b/src/coreclr/zap/zapperstats.h deleted file mode 100644 index 585b1bdd0e28a4..00000000000000 --- a/src/coreclr/zap/zapperstats.h +++ /dev/null @@ -1,91 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/* - - */ - - -#ifndef ZAPPER_STATS_H_0170123740208327 -#define ZAPPER_STATS_H_0170123740208327 - -#include "sarray.h" -#include "sstring.h" -#include "corcompile.h" -#include "arraylist.h" -#include "log.h" -#include "shash.h" -#include "utilcode.h" - - -// forward declarations -class ZapperOptions; - -class ZapperStats -{ - public: - - unsigned m_methods; // Total number of methods - unsigned m_failedMethods; // Methods which failed to compile correctly - unsigned m_failedILStubs; // ILSTUB methods which failed to compile correctly - - ULONG m_ilCodeSize; - ULONG m_nativeCodeSize; // Really just the Hot Code Size + Unprofiled size - ULONG m_nativeColdCodeSize; - ULONG m_nativeRODataSize; - ULONG m_gcInfoSize; -#ifdef FEATURE_EH_FUNCLETS - ULONG m_unwindInfoSize; -#endif // FEATURE_EH_FUNCLETS - - ULONG m_NumHotAllocations; - ULONG m_NumHotColdAllocations; - ULONG m_NumMediumHeaders; - - ULONG m_nativeCodeSizeInSplitMethods; - ULONG m_nativeColdCodeSizeInSplitMethods; - ULONG m_nativeCodeSizeInSplitProfiledMethods; - ULONG m_nativeColdCodeSizeInSplitProfiledMethods; - ULONG m_nativeCodeSizeInProfiledMethods; - ULONG m_nativeColdCodeSizeInProfiledMethods; - ULONG m_totalHotCodeSize; - ULONG m_totalUnprofiledCodeSize; - ULONG m_totalColdCodeSize; - ULONG m_totalCodeSizeInProfiledMethods; - ULONG m_totalColdCodeSizeInProfiledMethods; - - unsigned m_inputFileSize; - unsigned m_outputFileSize; - unsigned m_metadataSize; - unsigned m_preloadImageSize; - unsigned m_hotCodeMgrSize; - unsigned m_unprofiledCodeMgrSize; - unsigned m_coldCodeMgrSize; - unsigned m_eeInfoTableSize; - unsigned m_helperTableSize; - unsigned m_dynamicInfoTableSize; - unsigned m_dynamicInfoDelayListSize; - unsigned m_debuggingTableSize; - unsigned m_headerSectionSize; - unsigned m_codeSectionSize; - unsigned m_coldCodeSectionSize; - unsigned m_exceptionSectionSize; - unsigned m_readOnlyDataSectionSize; - unsigned m_relocSectionSize; - unsigned m_ILMetadataSize; - unsigned m_virtualImportThunkSize; - unsigned m_externalMethodThunkSize; - unsigned m_externalMethodDataSize; - - unsigned m_prestubMethods; - unsigned m_directMethods; - unsigned m_indirectMethodReasons[CORINFO_INDIRECT_CALL_COUNT]; - - ZapperStats(); - void PrintStats(); -}; - -char const * GetCallReasonString( CorInfoIndirectCallReason reason ); - -#endif // ZAPPER_STATS_H_0170123740208327 - diff --git a/src/coreclr/zap/zapreadytorun.cpp b/src/coreclr/zap/zapreadytorun.cpp deleted file mode 100644 index e5e0a236e44319..00000000000000 --- a/src/coreclr/zap/zapreadytorun.cpp +++ /dev/null @@ -1,874 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapReadyToRun.cpp -// - -// -// Zapping of ready-to-run specific structures -// -// ====================================================================================== - -#include "common.h" - -#include "zapreadytorun.h" - -#include "zapimport.h" - -#include "nativeformatwriter.h" - -#include "nibblestream.h" - -#include "../vm/typehashingalgorithms.h" -#include "../vm/nativeformatreader.h" - -using namespace NativeFormat; - -void ZapReadyToRunHeader::Save(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - READYTORUN_HEADER readyToRunHeader; - - ZeroMemory(&readyToRunHeader, sizeof(readyToRunHeader)); - - readyToRunHeader.Signature = READYTORUN_SIGNATURE; - readyToRunHeader.MajorVersion = READYTORUN_MAJOR_VERSION; - readyToRunHeader.MinorVersion = READYTORUN_MINOR_VERSION; - - if (pImage->m_ModuleDecoder.IsPlatformNeutral()) - readyToRunHeader.CoreHeader.Flags |= READYTORUN_FLAG_PLATFORM_NEUTRAL_SOURCE; - - // If all types loaded succesfully, set a flag to skip type loading sanity checks at runtime - if (pImage->GetCompileInfo()->AreAllClassesFullyLoaded(pImage->GetModuleHandle())) - readyToRunHeader.CoreHeader.Flags |= READYTORUN_FLAG_SKIP_TYPE_VALIDATION; - - if (pImage->GetZapperOptions()->m_fPartialNGen) - readyToRunHeader.CoreHeader.Flags |= READYTORUN_FLAG_PARTIAL; - - readyToRunHeader.CoreHeader.NumberOfSections = m_Sections.GetCount(); - - pZapWriter->Write(&readyToRunHeader, sizeof(readyToRunHeader)); - - qsort(&m_Sections[0], m_Sections.GetCount(), sizeof(Section), SectionCmp); - - for(COUNT_T i = 0; i < m_Sections.GetCount(); i++) - { - READYTORUN_SECTION section; - section.Type = m_Sections[i].type; - ZapWriter::SetDirectoryData(§ion.Section, m_Sections[i].pSection); - pZapWriter->Write(§ion, sizeof(section)); - } -} - -class BlobVertex : public NativeFormat::Vertex -{ - int m_cbSize; - -public: - BlobVertex(int cbSize) - : m_cbSize(cbSize) - { - } - - void * GetData() - { - return this + 1; - } - - int GetSize() - { - return m_cbSize; - } - - virtual void Save(NativeWriter * pWriter) - { - byte * pData = (byte *)GetData(); - for (int i = 0; i < m_cbSize; i++) - pWriter->WriteByte(pData[i]); - } -}; - -class BlobVertexKey -{ - PVOID _pData; - int _cbSize; - -public: - BlobVertexKey(PVOID pData, int cbSize) - : _pData(pData), _cbSize(cbSize) - { - } - - void * GetData() - { - return _pData; - } - - int GetSize() - { - return _cbSize; - } -}; - -class BlobVertexSHashTraits : public DefaultSHashTraits -{ -public: - typedef BlobVertexKey key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return key_t(e->GetData(), e->GetSize()); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - if (k1.GetSize() != k2.GetSize()) - return FALSE; - return memcmp(k1.GetData(), k2.GetData(), k1.GetSize()) == 0; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - count_t hash = 5381 + (count_t)(k.GetSize() << 7); - - PBYTE pbData = (PBYTE)k.GetData(); - PBYTE pbDataEnd = pbData + k.GetSize(); - - for (/**/ ; pbData < pbDataEnd; pbData++) - { - hash = ((hash << 5) + hash) ^ *pbData; - } - return hash; - } -}; - - -class EntryPointVertex : public NativeFormat::Vertex -{ - DWORD m_methodIndex; - BlobVertex * m_pFixups; - -public: - EntryPointVertex(DWORD methodIndex, BlobVertex * pFixups) - : m_methodIndex(methodIndex), m_pFixups(pFixups) - { - } - - virtual void Save(NativeWriter * pWriter) - { - if (m_pFixups != NULL) - { - int existingOffset = pWriter->GetCurrentOffset(m_pFixups); - if (existingOffset != -1) - { - pWriter->WriteUnsigned((m_methodIndex << 2) | 3); - pWriter->WriteUnsigned(pWriter->GetCurrentOffset() - existingOffset); - } - else - { - pWriter->WriteUnsigned((m_methodIndex << 2) | 1); - pWriter->SetCurrentOffset(m_pFixups); - m_pFixups->Save(pWriter); - } - } - else - { - pWriter->WriteUnsigned(m_methodIndex << 1); - } - } -}; - -class EntryPointWithBlobVertex : public EntryPointVertex -{ - BlobVertex * m_pBlob; - -public: - EntryPointWithBlobVertex(DWORD methodIndex, BlobVertex * pFixups, BlobVertex * pBlob) - : EntryPointVertex(methodIndex, pFixups), m_pBlob(pBlob) - { - } - - virtual void Save(NativeWriter * pWriter) - { - m_pBlob->Save(pWriter); - EntryPointVertex::Save(pWriter); - } -}; - -void ZapImage::OutputEntrypointsTableForReadyToRun() -{ - BeginRegion(CORINFO_REGION_COLD); - - NativeWriter arrayWriter; - NativeWriter hashtableWriter; - - NativeSection * pArraySection = arrayWriter.NewSection(); - NativeSection * pHashtableSection = hashtableWriter.NewSection(); - - VertexArray vertexArray(pArraySection); - pArraySection->Place(&vertexArray); - VertexHashtable vertexHashtable; - pHashtableSection->Place(&vertexHashtable); - - bool fEmpty = true; - - SHash< NoRemoveSHashTraits < BlobVertexSHashTraits > > fixupBlobs; - - COUNT_T nCount = m_MethodCompilationOrder.GetCount(); - for (COUNT_T i = 0; i < nCount; i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - - - BlobVertex * pFixupBlob = NULL; - - if (pMethod->m_pFixupList != NULL) - { - NibbleWriter writer; - m_pImportTable->PlaceFixups(pMethod->m_pFixupList, writer); - - DWORD cbBlob; - PVOID pBlob = writer.GetBlob(&cbBlob); - - pFixupBlob = fixupBlobs.Lookup(BlobVertexKey(pBlob, cbBlob)); - if (pFixupBlob == NULL) - { - void * pMemory = new (GetHeap()) BYTE[sizeof(BlobVertex) + cbBlob]; - pFixupBlob = new (pMemory) BlobVertex(cbBlob); - memcpy(pFixupBlob->GetData(), pBlob, cbBlob); - - fixupBlobs.Add(pFixupBlob); - } - } - - CORINFO_SIG_INFO sig; - GetJitInfo()->getMethodSig(pMethod->GetHandle(), &sig); - - mdMethodDef token = GetJitInfo()->getMethodDefFromMethod(pMethod->GetHandle()); - int rid = RidFromToken(token); - - if (sig.sigInst.classInstCount > 0 || sig.sigInst.methInstCount > 0) - { - _ASSERTE(rid != 0); - - CORINFO_MODULE_HANDLE module = GetJitInfo()->getClassModule(pMethod->GetClassHandle()); - _ASSERTE(GetCompileInfo()->IsInCurrentVersionBubble(module)); - SigBuilder sigBuilder; - CORINFO_RESOLVED_TOKEN resolvedToken = {}; - resolvedToken.tokenScope = module; - resolvedToken.token = token; - resolvedToken.hClass = pMethod->GetClassHandle(); - resolvedToken.hMethod = pMethod->GetHandle(); - GetCompileInfo()->EncodeMethod(module, pMethod->GetHandle(), &sigBuilder, m_pImportTable, EncodeModuleHelper, &resolvedToken); - - DWORD cbBlob; - PVOID pBlob = sigBuilder.GetSignature(&cbBlob); - void * pMemory = new (GetHeap()) BYTE[sizeof(BlobVertex) + cbBlob]; - BlobVertex * pSigBlob = new (pMemory) BlobVertex(cbBlob); - memcpy(pSigBlob->GetData(), pBlob, cbBlob); - - int dwHash = GetCompileInfo()->GetVersionResilientMethodHashCode(pMethod->GetHandle()); - vertexHashtable.Append(dwHash, pHashtableSection->Place(new (GetHeap()) EntryPointWithBlobVertex(pMethod->GetMethodIndex(), pFixupBlob, pSigBlob))); - } - else - { - int rid = RidFromToken(token); - if (rid != 0) - { - vertexArray.Set(rid - 1, new (GetHeap()) EntryPointVertex(pMethod->GetMethodIndex(), pFixupBlob)); - } - else - { - // This is a p/invoke stub, get the list of methods associated with the stub, and put this code in that set of rids - void *targetMethodEnum; - BOOL isStubWithTargetMethods = GetCompileInfo()->EnumMethodsForStub(pMethod->GetHandle(), &targetMethodEnum); - _ASSERTE(isStubWithTargetMethods); - - CORINFO_METHOD_HANDLE hTargetMethod; - while (GetCompileInfo()->EnumNextMethodForStub(targetMethodEnum, &hTargetMethod)) - { - mdMethodDef token = GetJitInfo()->getMethodDefFromMethod(hTargetMethod); - int rid = RidFromToken(token); - _ASSERTE(rid != 0); - vertexArray.Set(rid - 1, new (GetHeap()) EntryPointVertex(pMethod->GetMethodIndex(), pFixupBlob)); - } - - GetCompileInfo()->EnumCloseForStubEnumerator(targetMethodEnum); - } - } - - fEmpty = false; - } - - if (fEmpty) - return; - - vertexArray.ExpandLayout(); - - vector& arrayBlob = arrayWriter.Save(); - ZapNode * pArrayBlob = ZapBlob::NewBlob(this, &arrayBlob[0], arrayBlob.size()); - m_pCodeMethodDescsSection->Place(pArrayBlob); - - vector& hashtableBlob = hashtableWriter.Save(); - ZapNode * pHashtableBlob = ZapBlob::NewBlob(this, &hashtableBlob[0], hashtableBlob.size()); - m_pCodeMethodDescsSection->Place(pHashtableBlob); - - ZapReadyToRunHeader * pReadyToRunHeader = GetReadyToRunHeader(); - pReadyToRunHeader->RegisterSection(ReadyToRunSectionType::MethodDefEntryPoints, pArrayBlob); - pReadyToRunHeader->RegisterSection(ReadyToRunSectionType::InstanceMethodEntryPoints, pHashtableBlob); - pReadyToRunHeader->RegisterSection(ReadyToRunSectionType::RuntimeFunctions, m_pRuntimeFunctionSection); - - if (m_pLazyMethodCallHelperSection->GetNodeCount() != 0) - pReadyToRunHeader->RegisterSection(ReadyToRunSectionType::DelayLoadMethodCallThunks, m_pLazyMethodCallHelperSection); - - if (m_pExceptionInfoLookupTable->GetSize() != 0) - pReadyToRunHeader->RegisterSection(ReadyToRunSectionType::ExceptionInfo, m_pExceptionInfoLookupTable); - - EndRegion(CORINFO_REGION_COLD); -} - -class DebugInfoVertex : public NativeFormat::Vertex -{ - BlobVertex * m_pDebugInfo; - -public: - DebugInfoVertex(BlobVertex * pDebugInfo) - : m_pDebugInfo(pDebugInfo) - { - } - - virtual void Save(NativeWriter * pWriter) - { - int existingOffset = pWriter->GetCurrentOffset(m_pDebugInfo); - if (existingOffset != -1) - { - _ASSERTE(pWriter->GetCurrentOffset() > existingOffset); - pWriter->WriteUnsigned(pWriter->GetCurrentOffset() - existingOffset); - } - else - { - pWriter->WriteUnsigned(0); - pWriter->SetCurrentOffset(m_pDebugInfo); - m_pDebugInfo->Save(pWriter); - } - } -}; -// At ngen time Zapper::CompileModule PlaceFixups called from -// code:ZapSig.GetSignatureForTypeHandle -// -/*static*/ DWORD ZapImage::EncodeModuleHelper(LPVOID compileContext, - CORINFO_MODULE_HANDLE referencedModule) -{ - _ASSERTE(!IsReadyToRunCompilation() || IsLargeVersionBubbleEnabled()); - ZapImportTable * pTable = (ZapImportTable *)compileContext; - return pTable->GetIndexOfModule(referencedModule); -} - -void ZapImage::OutputDebugInfoForReadyToRun() -{ - NativeWriter writer; - - NativeSection * pSection = writer.NewSection(); - - VertexArray vertexArray(pSection); - pSection->Place(&vertexArray); - - bool fEmpty = true; - - SHash< NoRemoveSHashTraits < BlobVertexSHashTraits > > debugInfoBlobs; - - COUNT_T nCount = m_MethodCompilationOrder.GetCount(); - for (COUNT_T i = 0; i < nCount; i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - - ZapBlob * pDebugInfo = pMethod->GetDebugInfo(); - if (pDebugInfo == NULL) - continue; - - DWORD cbBlob = pDebugInfo->GetBlobSize(); - PVOID pBlob = pDebugInfo->GetData(); - - BlobVertex * pDebugInfoBlob = debugInfoBlobs.Lookup(BlobVertexKey(pBlob, cbBlob)); - if (pDebugInfoBlob == NULL) - { - void * pMemory = new (GetHeap()) BYTE[sizeof(BlobVertex) + cbBlob]; - pDebugInfoBlob = new (pMemory) BlobVertex(cbBlob); - memcpy(pDebugInfoBlob->GetData(), pBlob, cbBlob); - - debugInfoBlobs.Add(pDebugInfoBlob); - } - - vertexArray.Set(pMethod->GetMethodIndex(), new (GetHeap()) DebugInfoVertex(pDebugInfoBlob)); - - fEmpty = false; - } - - if (fEmpty) - return; - - vertexArray.ExpandLayout(); - - vector& blob = writer.Save(); - - ZapNode * pBlob = ZapBlob::NewBlob(this, &blob[0], blob.size()); - m_pDebugSection->Place(pBlob); - - GetReadyToRunHeader()->RegisterSection(ReadyToRunSectionType::DebugInfo, pBlob); -} - -void ZapImage::OutputInliningTableForReadyToRun() -{ - SBuffer serializedInlineTrackingBuffer; - m_pPreloader->GetSerializedInlineTrackingMap(&serializedInlineTrackingBuffer); - ZapNode * pBlob = ZapBlob::NewAlignedBlob(this, (PVOID)(const BYTE*) serializedInlineTrackingBuffer, serializedInlineTrackingBuffer.GetSize(), 4); - m_pDebugSection->Place(pBlob); - GetReadyToRunHeader()->RegisterSection(ReadyToRunSectionType::InliningInfo, pBlob); -} - -void ZapImage::OutputProfileDataForReadyToRun() -{ - if (m_pInstrumentSection != nullptr) - { - GetReadyToRunHeader()->RegisterSection(ReadyToRunSectionType::ProfileDataInfo, m_pInstrumentSection); - } -} - -void ZapImage::OutputManifestMetadataForReadyToRun() -{ - if (m_pMetaDataSection != nullptr) - { - GetReadyToRunHeader()->RegisterSection(ReadyToRunSectionType::ManifestMetadata, m_pMetaDataSection); - } -} - -void ZapImage::OutputTypesTableForReadyToRun(IMDInternalImport * pMDImport) -{ - NativeWriter writer; - VertexHashtable typesHashtable; - - NativeSection * pSection = writer.NewSection(); - pSection->Place(&typesHashtable); - - // Note on duplicate types with same name: there is not need to perform that check when building - // the hashtable. If such types were encountered, the R2R compilation would fail before reaching here. - - // Save the TypeDefs to the hashtable - { - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumAllInit(mdtTypeDef); - - mdToken mdTypeToken; - while (pMDImport->EnumNext(&hEnum, &mdTypeToken)) - { - mdTypeDef mdCurrentToken = mdTypeToken; - DWORD dwHash = GetCompileInfo()->GetVersionResilientTypeHashCode(GetModuleHandle(), mdTypeToken); - - typesHashtable.Append(dwHash, pSection->Place(new UnsignedConstant(RidFromToken(mdTypeToken) << 1))); - } - } - - // Save the ExportedTypes to the hashtable - { - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumInit(mdtExportedType, mdTokenNil); - - mdToken mdTypeToken; - while (pMDImport->EnumNext(&hEnum, &mdTypeToken)) - { - DWORD dwHash = GetCompileInfo()->GetVersionResilientTypeHashCode(GetModuleHandle(), mdTypeToken); - - typesHashtable.Append(dwHash, pSection->Place(new UnsignedConstant((RidFromToken(mdTypeToken) << 1) | 1))); - } - } - - vector& blob = writer.Save(); - - ZapNode * pBlob = ZapBlob::NewBlob(this, &blob[0], blob.size()); - _ASSERTE(m_pAvailableTypesSection); - m_pAvailableTypesSection->Place(pBlob); - - GetReadyToRunHeader()->RegisterSection(ReadyToRunSectionType::AvailableTypes, pBlob); -} - -template -HRESULT EnumerateAllCustomAttributes(IMDInternalImport *pMDImport, Tlambda lambda) -{ - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumAllInit(mdtCustomAttribute); - - HRESULT hr = S_OK; - - mdCustomAttribute tkCustomAttribute; - while (pMDImport->EnumNext(&hEnum, &tkCustomAttribute)) - { - LPCUTF8 szNamespace; - LPCUTF8 szName; - - hr = pMDImport->GetNameOfCustomAttribute(tkCustomAttribute, &szNamespace, &szName); - if (FAILED(hr)) - return hr; - - if (szNamespace == NULL) - continue; - - if (szName == NULL) - continue; - - // System.Runtime.CompilerServices.NullableAttribute is NEVER added to the table (There are *many* of these, and they provide no useful value to the runtime) - if ((strcmp(szNamespace, "System.Runtime.CompilerServices") == 0) && (strcmp(szName, "NullableAttribute") == 0)) - continue; - - bool addToTable = false; - // Other than Nullable attribute, all attributes under System.Runtime are added to the table - if (strncmp(szNamespace, "System.Runtime.", strlen("System.Runtime.")) == 0) - { - addToTable = true; - } - else if (strcmp(szNamespace, "Windows.Foundation.Metadata") == 0) - { - // Windows.Foundation.Metadata attributes are a similar construct to compilerservices attributes. Add them to the table - addToTable = true; - } - else if (strcmp(szNamespace, "System") == 0) - { - // Some historical well known attributes were placed in the System namespace. Special case them - if (strcmp(szName, "ParamArrayAttribute") == 0) - addToTable = true; - else if (strcmp(szName, "ThreadStaticAttribute") == 0) - addToTable = true; - } - else if (strcmp(szNamespace, "System.Reflection") == 0) - { - // Historical attribute in the System.Reflection namespace - if (strcmp(szName, "DefaultMemberAttribute") == 0) - addToTable = true; - } - - if (!addToTable) - continue; - - mdToken tkParent; - hr = pMDImport->GetParentToken(tkCustomAttribute, &tkParent); - if (FAILED(hr)) - return hr; - - hr = lambda(szNamespace, szName, tkParent); - if (FAILED(hr)) - return hr; - } - - return hr; -} - -static inline uint32_t RotateLeft(const uint32_t x, int k) { - return (x << k) | (x >> (32 - k)); -} - -uint32_t Xoshiro128StarStar(uint32_t s[]) { - const uint32_t result = RotateLeft(s[1] * 5, 7) * 9; - const uint32_t t = s[1] << 9; - - s[2] ^= s[0]; - s[3] ^= s[1]; - s[1] ^= s[2]; - s[0] ^= s[3]; - - s[2] ^= t; - s[3] = RotateLeft(s[3], 11); - - return result; -} - -HRESULT ZapImage::ComputeAttributePresenceTable(IMDInternalImport * pMDImport, SArray *table) -{ - int countOfEntries = 0; - HRESULT hr = EnumerateAllCustomAttributes(pMDImport, [&countOfEntries](LPCUTF8 szNamespace, LPCUTF8 szName, mdToken tkParent) - { - countOfEntries++; - return S_OK; - }); - if (FAILED(hr)) - return hr; - - if (countOfEntries == 0) - { - table->Clear(); - _ASSERTE(table->IsEmpty()); - return S_OK; - } - - // Buckets have 8 entries - UINT minTableBucketCount = (countOfEntries / 8) + 1; - UINT bucketCount = 1; - - // Bucket count must be power of two - while (bucketCount < minTableBucketCount) - bucketCount *= 2; - - // Resize the array. - bool tryAgainWithBiggerTable = false; - int countOfRetries = 0; - do - { - tryAgainWithBiggerTable = false; - UINT actualSizeOfTable = bucketCount * 8; // Buckets have 8 entries in them - UINT16* pTable = table->OpenRawBuffer(actualSizeOfTable); - memset(pTable, 0, sizeof(UINT16) * actualSizeOfTable); - table->CloseRawBuffer(); - - uint32_t state[4] = {729055690, 833774698, 218408041, 493449127}; // 4 randomly generated numbers to initialize random number state - - // Attempt to fill table - - hr = EnumerateAllCustomAttributes(pMDImport, [&](LPCUTF8 szNamespace, LPCUTF8 szName, mdToken tkParent) - { - StackSString name(SString::Utf8); - name.AppendUTF8(szNamespace); - name.AppendUTF8(NAMESPACE_SEPARATOR_STR); - name.AppendUTF8(szName); - - StackScratchBuffer buff; - const char* pDebugNameUTF8 = name.GetUTF8(buff); - size_t len = strlen(pDebugNameUTF8); - - // This hashing algorithm MUST match exactly the logic in NativeCuckooFilter - DWORD hashOfAttribute = ComputeNameHashCode(pDebugNameUTF8); - UINT32 hash = CombineTwoValuesIntoHash(hashOfAttribute, tkParent); - UINT16 fingerprint = (UINT16)(hash >> 16); - if (fingerprint == 0) - fingerprint = 1; - - UINT bucketAIndex = hash % bucketCount; - UINT bucketBIndex = (bucketAIndex ^ (NativeFormat::NativeCuckooFilter::ComputeFingerprintHash(fingerprint) % bucketCount)); - - _ASSERTE(bucketAIndex == (bucketBIndex ^ (NativeFormat::NativeCuckooFilter::ComputeFingerprintHash(fingerprint) % bucketCount))); - - if (Xoshiro128StarStar(state) & 1) // Randomly choose which bucket to attempt to fill first - { - UINT temp = bucketAIndex; - bucketAIndex = bucketBIndex; - bucketBIndex = temp; - } - - auto hasEntryInBucket = [&table](UINT bucketIndex, UINT16 fprint) - { - for (int i = 0; i < 8; i++) - { - if ((*table)[(bucketIndex * 8) + i] == fprint) - return true; - } - return false; - }; - - auto isEmptyEntryInBucket = [&table](UINT bucketIndex) - { - for (int i = 0; i < 8; i++) - { - if ((*table)[(bucketIndex * 8) + i] == 0) - return true; - } - return false; - }; - - auto fillEmptyEntryInBucket = [&table](UINT bucketIndex, UINT16 fprint) - { - for (int i = 0; i < 8; i++) - { - if ((*table)[(bucketIndex * 8) + i] == 0) - { - (*table)[(bucketIndex * 8) + i] = fprint; - return; - } - } - _ASSERTE(!"Not possible to reach here"); - return; - }; - - // Scan for pre-existing fingerprint entry in buckets - if (hasEntryInBucket(bucketAIndex, fingerprint) || hasEntryInBucket(bucketBIndex, fingerprint)) - return S_OK; - - // Determine if there is space in a bucket to add a new entry - if (isEmptyEntryInBucket(bucketAIndex)) - { - fillEmptyEntryInBucket(bucketAIndex, fingerprint); - return S_OK; - } - if (isEmptyEntryInBucket(bucketBIndex)) - { - fillEmptyEntryInBucket(bucketBIndex, fingerprint); - return S_OK; - } - - int MaxNumKicks = 256; - // Note, that bucketAIndex itself was chosen randomly above. - for (int n = 0; n < MaxNumKicks; n++) - { - // Randomly swap an entry in bucket bucketAIndex with fingerprint - UINT entryIndexInBucket = Xoshiro128StarStar(state) & 0x7; - UINT16 temp = fingerprint; - fingerprint = (*table)[(bucketAIndex * 8) + entryIndexInBucket]; - (*table)[(bucketAIndex * 8) + entryIndexInBucket] = temp; - - // Find other bucket - bucketAIndex = bucketAIndex ^ (NativeFormat::NativeCuckooFilter::ComputeFingerprintHash(fingerprint) % bucketCount); - if (isEmptyEntryInBucket(bucketAIndex)) - { - fillEmptyEntryInBucket(bucketAIndex, fingerprint); - return S_OK; - } - } - - tryAgainWithBiggerTable = true; - return E_FAIL; - }); - - if (tryAgainWithBiggerTable) - { - // bucket entry kicking path requires bucket counts to be power of two in size due to use of xor to retrieve second hash - bucketCount *= 2; - } - } while(tryAgainWithBiggerTable && ((countOfRetries++) < 2)); - - if (tryAgainWithBiggerTable) - { - return E_FAIL; - } - - return S_OK; -} - -void ZapImage::OutputAttributePresenceFilter(IMDInternalImport * pMDImport) -{ - // Core library attributes are checked FAR more often than other dlls - // attributes, so produce a highly efficient table for determining if they are - // present. Other assemblies *MAY* benefit from this feature, but it doesn't show - // as useful at this time. - - if (m_hModule != m_zapper->m_pEECompileInfo->GetLoaderModuleForCoreLib()) - return; - - SArray table; - if (SUCCEEDED(ComputeAttributePresenceTable(pMDImport, &table))) - { - UINT16* pRawTable = table.OpenRawBuffer(table.GetCount()); - ZapNode * pBlob = ZapBlob::NewBlob(this, pRawTable, table.GetCount() * sizeof(UINT16)); - table.CloseRawBuffer(); - - _ASSERTE(m_pAttributePresenceSection); - m_pAttributePresenceSection->Place(pBlob); - GetReadyToRunHeader()->RegisterSection(ReadyToRunSectionType::AttributePresence, pBlob); - } -} - -// -// Verify that data structures and flags shared between NGen and ReadyToRun are in sync -// - -// -// READYTORUN_IMPORT_SECTION -// -static_assert_no_msg(sizeof(READYTORUN_IMPORT_SECTION) == sizeof(CORCOMPILE_IMPORT_SECTION)); - -static_assert_no_msg((int)READYTORUN_IMPORT_SECTION_TYPE_UNKNOWN == (int)CORCOMPILE_IMPORT_TYPE_UNKNOWN); - -static_assert_no_msg((int)READYTORUN_IMPORT_SECTION_FLAGS_EAGER == (int)CORCOMPILE_IMPORT_FLAGS_EAGER); - -// -// READYTORUN_METHOD_SIG -// -static_assert_no_msg((int)READYTORUN_METHOD_SIG_UnboxingStub == (int)ENCODE_METHOD_SIG_UnboxingStub); -static_assert_no_msg((int)READYTORUN_METHOD_SIG_InstantiatingStub == (int)ENCODE_METHOD_SIG_InstantiatingStub); -static_assert_no_msg((int)READYTORUN_METHOD_SIG_MethodInstantiation == (int)ENCODE_METHOD_SIG_MethodInstantiation); -static_assert_no_msg((int)READYTORUN_METHOD_SIG_SlotInsteadOfToken == (int)ENCODE_METHOD_SIG_SlotInsteadOfToken); -static_assert_no_msg((int)READYTORUN_METHOD_SIG_MemberRefToken == (int)ENCODE_METHOD_SIG_MemberRefToken); -static_assert_no_msg((int)READYTORUN_METHOD_SIG_Constrained == (int)ENCODE_METHOD_SIG_Constrained); -static_assert_no_msg((int)READYTORUN_METHOD_SIG_OwnerType == (int)ENCODE_METHOD_SIG_OwnerType); -static_assert_no_msg((int)READYTORUN_METHOD_SIG_UpdateContext == (int)ENCODE_METHOD_SIG_UpdateContext); - -// -// READYTORUN_FIELD_SIG -// -static_assert_no_msg((int)READYTORUN_FIELD_SIG_IndexInsteadOfToken == (int)ENCODE_FIELD_SIG_IndexInsteadOfToken); -static_assert_no_msg((int)READYTORUN_FIELD_SIG_MemberRefToken == (int)ENCODE_FIELD_SIG_MemberRefToken); -static_assert_no_msg((int)READYTORUN_FIELD_SIG_OwnerType == (int)ENCODE_FIELD_SIG_OwnerType); - -// -// READYTORUN_FIXUP -// -static_assert_no_msg((int)READYTORUN_FIXUP_ThisObjDictionaryLookup == (int)ENCODE_DICTIONARY_LOOKUP_THISOBJ); -static_assert_no_msg((int)READYTORUN_FIXUP_TypeDictionaryLookup == (int)ENCODE_DICTIONARY_LOOKUP_TYPE); -static_assert_no_msg((int)READYTORUN_FIXUP_MethodDictionaryLookup == (int)ENCODE_DICTIONARY_LOOKUP_METHOD); - -static_assert_no_msg((int)READYTORUN_FIXUP_TypeHandle == (int)ENCODE_TYPE_HANDLE); -static_assert_no_msg((int)READYTORUN_FIXUP_MethodHandle == (int)ENCODE_METHOD_HANDLE); -static_assert_no_msg((int)READYTORUN_FIXUP_FieldHandle == (int)ENCODE_FIELD_HANDLE); - -static_assert_no_msg((int)READYTORUN_FIXUP_MethodEntry == (int)ENCODE_METHOD_ENTRY); -static_assert_no_msg((int)READYTORUN_FIXUP_MethodEntry_DefToken == (int)ENCODE_METHOD_ENTRY_DEF_TOKEN); -static_assert_no_msg((int)READYTORUN_FIXUP_MethodEntry_RefToken == (int)ENCODE_METHOD_ENTRY_REF_TOKEN); - -static_assert_no_msg((int)READYTORUN_FIXUP_VirtualEntry == (int)ENCODE_VIRTUAL_ENTRY); -static_assert_no_msg((int)READYTORUN_FIXUP_VirtualEntry_DefToken == (int)ENCODE_VIRTUAL_ENTRY_DEF_TOKEN); -static_assert_no_msg((int)READYTORUN_FIXUP_VirtualEntry_RefToken == (int)ENCODE_VIRTUAL_ENTRY_REF_TOKEN); -static_assert_no_msg((int)READYTORUN_FIXUP_VirtualEntry_Slot == (int)ENCODE_VIRTUAL_ENTRY_SLOT); - -static_assert_no_msg((int)READYTORUN_FIXUP_Helper == (int)ENCODE_READYTORUN_HELPER); -static_assert_no_msg((int)READYTORUN_FIXUP_StringHandle == (int)ENCODE_STRING_HANDLE); - -static_assert_no_msg((int)READYTORUN_FIXUP_NewObject == (int)ENCODE_NEW_HELPER); -static_assert_no_msg((int)READYTORUN_FIXUP_NewArray == (int)ENCODE_NEW_ARRAY_HELPER); - -static_assert_no_msg((int)READYTORUN_FIXUP_IsInstanceOf == (int)ENCODE_ISINSTANCEOF_HELPER); -static_assert_no_msg((int)READYTORUN_FIXUP_ChkCast == (int)ENCODE_CHKCAST_HELPER); - -static_assert_no_msg((int)READYTORUN_FIXUP_FieldAddress == (int)ENCODE_FIELD_ADDRESS); -static_assert_no_msg((int)READYTORUN_FIXUP_CctorTrigger == (int)ENCODE_CCTOR_TRIGGER); - -static_assert_no_msg((int)READYTORUN_FIXUP_StaticBaseNonGC == (int)ENCODE_STATIC_BASE_NONGC_HELPER); -static_assert_no_msg((int)READYTORUN_FIXUP_StaticBaseGC == (int)ENCODE_STATIC_BASE_GC_HELPER); -static_assert_no_msg((int)READYTORUN_FIXUP_ThreadStaticBaseNonGC == (int)ENCODE_THREAD_STATIC_BASE_NONGC_HELPER); -static_assert_no_msg((int)READYTORUN_FIXUP_ThreadStaticBaseGC == (int)ENCODE_THREAD_STATIC_BASE_GC_HELPER); - -static_assert_no_msg((int)READYTORUN_FIXUP_FieldBaseOffset == (int)ENCODE_FIELD_BASE_OFFSET); -static_assert_no_msg((int)READYTORUN_FIXUP_FieldOffset == (int)ENCODE_FIELD_OFFSET); - -static_assert_no_msg((int)READYTORUN_FIXUP_TypeDictionary == (int)ENCODE_TYPE_DICTIONARY); -static_assert_no_msg((int)READYTORUN_FIXUP_MethodDictionary == (int)ENCODE_METHOD_DICTIONARY); - -static_assert_no_msg((int)READYTORUN_FIXUP_Check_TypeLayout == (int)ENCODE_CHECK_TYPE_LAYOUT); -static_assert_no_msg((int)READYTORUN_FIXUP_Check_FieldOffset == (int)ENCODE_CHECK_FIELD_OFFSET); - -static_assert_no_msg((int)READYTORUN_FIXUP_DelegateCtor == (int)ENCODE_DELEGATE_CTOR); - -static_assert_no_msg((int)READYTORUN_FIXUP_DeclaringTypeHandle == (int)ENCODE_DECLARINGTYPE_HANDLE); - -static_assert_no_msg((int)READYTORUN_FIXUP_IndirectPInvokeTarget == (int)ENCODE_INDIRECT_PINVOKE_TARGET); -static_assert_no_msg((int)READYTORUN_FIXUP_PInvokeTarget == (int)ENCODE_PINVOKE_TARGET); - -static_assert_no_msg((int)READYTORUN_FIXUP_Check_InstructionSetSupport== (int)ENCODE_CHECK_INSTRUCTION_SET_SUPPORT); - -static_assert_no_msg((int)READYTORUN_FIXUP_Verify_FieldOffset == (int)ENCODE_VERIFY_FIELD_OFFSET); -static_assert_no_msg((int)READYTORUN_FIXUP_Verify_TypeLayout == (int)ENCODE_VERIFY_TYPE_LAYOUT); - -static_assert_no_msg((int)READYTORUN_FIXUP_Check_VirtualFunctionOverride == (int)ENCODE_CHECK_VIRTUAL_FUNCTION_OVERRIDE); -static_assert_no_msg((int)READYTORUN_FIXUP_Verify_VirtualFunctionOverride == (int)ENCODE_VERIFY_VIRTUAL_FUNCTION_OVERRIDE); - -// -// READYTORUN_EXCEPTION -// -static_assert_no_msg(sizeof(READYTORUN_EXCEPTION_LOOKUP_TABLE_ENTRY) == sizeof(CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY)); -static_assert_no_msg(sizeof(READYTORUN_EXCEPTION_CLAUSE) == sizeof(CORCOMPILE_EXCEPTION_CLAUSE)); - -// -// ReadyToRunHFAElemType -// -static_assert_no_msg((int)READYTORUN_HFA_ELEMTYPE_None == (int)CORINFO_HFA_ELEM_NONE); -static_assert_no_msg((int)READYTORUN_HFA_ELEMTYPE_Float32 == (int)CORINFO_HFA_ELEM_FLOAT); -static_assert_no_msg((int)READYTORUN_HFA_ELEMTYPE_Float64 == (int)CORINFO_HFA_ELEM_DOUBLE); -static_assert_no_msg((int)READYTORUN_HFA_ELEMTYPE_Vector64 == (int)CORINFO_HFA_ELEM_VECTOR64); -static_assert_no_msg((int)READYTORUN_HFA_ELEMTYPE_Vector128 == (int)CORINFO_HFA_ELEM_VECTOR128); - diff --git a/src/coreclr/zap/zapreadytorun.h b/src/coreclr/zap/zapreadytorun.h deleted file mode 100644 index 66fe3adb391aef..00000000000000 --- a/src/coreclr/zap/zapreadytorun.h +++ /dev/null @@ -1,65 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapReadyToRun.h -// - -// -// Zapping of ready-to-run specific structures -// -// ====================================================================================== - -#ifndef __ZAPREADYTORUN_H__ -#define __ZAPREADYTORUN_H__ - -#include "readytorun.h" - -class ZapReadyToRunHeader : public ZapNode -{ - struct Section - { - ReadyToRunSectionType type; - ZapNode * pSection; - }; - - SArray
m_Sections; - - static int __cdecl SectionCmp(const void* a_, const void* b_) - { - return (uint32_t)((Section*)a_)->type - (uint32_t)((Section*)b_)->type; - } - -public: - ZapReadyToRunHeader(ZapImage * pImage) - { - } - - void RegisterSection(ReadyToRunSectionType type, ZapNode * pSection) - { - Section section; - section.type = type; - section.pSection = pSection; - m_Sections.Append(section); - } - - virtual DWORD GetSize() - { - return sizeof(READYTORUN_HEADER) + sizeof(READYTORUN_SECTION) * m_Sections.GetCount(); - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_NativeHeader; - } - - virtual void Save(ZapWriter * pZapWriter); - - DWORD EncodeModuleHelper(LPVOID compileContext, CORINFO_MODULE_HANDLE referencedModule); -}; - -#endif // __ZAPREADYTORUN_H__ diff --git a/src/coreclr/zap/zaprelocs.cpp b/src/coreclr/zap/zaprelocs.cpp deleted file mode 100644 index 028a30e0154bf5..00000000000000 --- a/src/coreclr/zap/zaprelocs.cpp +++ /dev/null @@ -1,427 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapRelocs.cpp -// - -// -// Zapping of relocations -// -// ====================================================================================== - -#include "common.h" - -#include "zaprelocs.h" - -#ifdef REDHAWK -void PDB_NoticeReloc(ZapRelocationType type, DWORD rvaReloc, ZapNode * pTarget, int targetOffset); -#endif - -void ZapBaseRelocs::WriteReloc(PVOID pSrc, int offset, ZapNode * pTarget, int targetOffset, ZapRelocationType type) -{ - _ASSERTE(pTarget != NULL); - - PBYTE pLocation = (PBYTE)pSrc + offset; - DWORD rva = m_pImage->GetCurrentRVA() + offset; - TADDR pActualTarget = (TADDR)m_pImage->GetBaseAddress() + pTarget->GetRVA() + targetOffset; - -#ifdef REDHAWK - PDB_NoticeReloc(type, rva, pTarget, targetOffset); -#endif - - switch (type) - { - case IMAGE_REL_BASED_ABSOLUTE: - *(UNALIGNED DWORD *)pLocation = pTarget->GetRVA() + targetOffset; - // IMAGE_REL_BASED_ABSOLUTE does not need base reloc entry - return; - - case IMAGE_REL_BASED_ABSOLUTE_TAGGED: - _ASSERTE(targetOffset == 0); - *(UNALIGNED DWORD *)pLocation = (DWORD)CORCOMPILE_TAG_TOKEN(pTarget->GetRVA()); - // IMAGE_REL_BASED_ABSOLUTE_TAGGED does not need base reloc entry - return; - - case IMAGE_REL_BASED_PTR: -#ifdef TARGET_ARM - // Misaligned relocs disable ASLR on ARM. We should never ever emit them. - _ASSERTE(IS_ALIGNED(rva, TARGET_POINTER_SIZE)); -#endif - *(UNALIGNED TARGET_POINTER_TYPE *)pLocation = (TARGET_POINTER_TYPE)pActualTarget; - break; - - case IMAGE_REL_BASED_RELPTR: - { - TADDR pSite = (TADDR)m_pImage->GetBaseAddress() + rva; - *(UNALIGNED TADDR *)pLocation = (INT32)(pActualTarget - pSite); - } - // neither IMAGE_REL_BASED_RELPTR nor IMAGE_REL_BASED_MD_METHODENTRY need base reloc entry - return; - - case IMAGE_REL_BASED_RELPTR32: - { - TADDR pSite = (TADDR)m_pImage->GetBaseAddress() + rva; - *(UNALIGNED INT32 *)pLocation = (INT32)(pActualTarget - pSite); - } - // IMAGE_REL_BASED_RELPTR32 does not need base reloc entry - return; - -#if defined(TARGET_X86) || defined(TARGET_AMD64) - case IMAGE_REL_BASED_REL32: - { - TADDR pSite = (TADDR)m_pImage->GetBaseAddress() + rva; - *(UNALIGNED INT32 *)pLocation = (INT32)(pActualTarget - (pSite + sizeof(INT32))); - } - // IMAGE_REL_BASED_REL32 does not need base reloc entry - return; -#endif // TARGET_X86 || TARGET_AMD64 - -#if defined(TARGET_ARM) - case IMAGE_REL_BASED_THUMB_MOV32: - { - PutThumb2Mov32((UINT16 *)pLocation, (UINT32)pActualTarget); - break; - } - - case IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL: - { - TADDR pSite = (TADDR)m_pImage->GetBaseAddress() + rva; - - // For details about how the value is calculated, see - // description of IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL - const UINT32 offsetCorrection = 12; - - UINT32 imm32 = UINT32(pActualTarget - (pSite + offsetCorrection)); - - PutThumb2Mov32((UINT16 *)pLocation, imm32); - - // IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL does not need base reloc entry - return; - } - - case IMAGE_REL_BASED_THUMB_BRANCH24: - { - TADDR pSite = (TADDR)m_pImage->GetBaseAddress() + rva; - - // Kind of a workaround: make this reloc work both for calls (which have the thumb bit set), - // and for relative jumps used for hot/cold splitting (which don't). - pActualTarget &= ~THUMB_CODE; - - // Calculate the reloffset without the ThumbBit set so that it can be correctly encoded. - _ASSERTE(!(pActualTarget & THUMB_CODE));// we expect pActualTarget not to have the thumb bit set - _ASSERTE(!(pSite & THUMB_CODE)); // we expect pSite not to have the thumb bit set - INT32 relOffset = (INT32)(pActualTarget - (pSite + sizeof(INT32))); - if (!FitsInThumb2BlRel24(relOffset)) - { - // Retry the compilation with IMAGE_REL_BASED_THUMB_BRANCH24 relocations disabled - // (See code:ZapInfo::getRelocTypeHint) - ThrowHR(COR_E_OVERFLOW); - } - PutThumb2BlRel24((UINT16 *)pLocation, relOffset); - } - // IMAGE_REL_BASED_THUMB_BRANCH24 does not need base reloc entry - return; -#endif // defined(TARGET_ARM) -#if defined(TARGET_ARM64) - case IMAGE_REL_ARM64_BRANCH26: - { - TADDR pSite = (TADDR)m_pImage->GetBaseAddress() + rva; - - INT32 relOffset = (INT32)(pActualTarget - pSite); - if (!FitsInRel28(relOffset)) - { - ThrowHR(COR_E_OVERFLOW); - } - PutArm64Rel28((UINT32 *)pLocation,relOffset); - } - return; - - case IMAGE_REL_ARM64_PAGEBASE_REL21: - { - TADDR pSitePage = ((TADDR)m_pImage->GetBaseAddress() + rva) & 0xFFFFFFFFFFFFF000LL; - TADDR pActualTargetPage = pActualTarget & 0xFFFFFFFFFFFFF000LL; - - INT64 relPage = (INT64)(pActualTargetPage - pSitePage); - INT32 imm21 = (INT32)(relPage >> 12) & 0x1FFFFF; - PutArm64Rel21((UINT32 *)pLocation, imm21); - } - return; - - case IMAGE_REL_ARM64_PAGEOFFSET_12A: - { - INT32 imm12 = (INT32)(pActualTarget & 0xFFFLL); - PutArm64Rel12((UINT32 *)pLocation, imm12); - } - return; -#endif - - default: - _ASSERTE(!"Unknown relocation type"); - break; - } - - DWORD page = AlignDown(rva, RELOCATION_PAGE_SIZE); - - if (page != m_page) - { - FlushWriter(); - - m_page = page; - m_pageIndex = m_SerializedRelocs.GetCount(); - - // Reserve space for IMAGE_BASE_RELOCATION - for (size_t iSpace = 0; iSpace < sizeof(IMAGE_BASE_RELOCATION) / sizeof(USHORT); iSpace++) - m_SerializedRelocs.Append(0); - } - - m_SerializedRelocs.Append((USHORT)(AlignmentTrim(rva, RELOCATION_PAGE_SIZE) | (type << 12))); -} - -void ZapBaseRelocs::FlushWriter() -{ - if (m_page != 0) - { - // The blocks has to be 4-byte aligned - if (m_SerializedRelocs.GetCount() & 1) - m_SerializedRelocs.Append(0); - - IMAGE_BASE_RELOCATION * pBaseRelocation = (IMAGE_BASE_RELOCATION *)&(m_SerializedRelocs[m_pageIndex]); - pBaseRelocation->VirtualAddress = m_page; - pBaseRelocation->SizeOfBlock = (m_SerializedRelocs.GetCount() - m_pageIndex) * sizeof(USHORT); - - m_page = 0; - } -} - -void ZapBaseRelocs::Save(ZapWriter * pZapWriter) -{ - FlushWriter(); - - pZapWriter->SetWritingRelocs(); - - // Write the relocs as blob - pZapWriter->Write(&m_SerializedRelocs[0], m_SerializedRelocs.GetCount() * sizeof(USHORT)); -} - -////////////////////////////////////////////////////////////////////////////// -// -// ZapBlobWithRelocs -// - -int _cdecl CmpZapRelocs(const void *p1, const void *p2) -{ - LIMITED_METHOD_CONTRACT; - - const ZapReloc *relocTemp1 = (ZapReloc *)p1; - const ZapReloc *relocTemp2 = (ZapReloc *)p2; - if (relocTemp1->m_offset < relocTemp2->m_offset) - return -1; - else if (relocTemp1->m_offset > relocTemp2->m_offset) - return 1; - else - return 0; -} - -void ZapBlobWithRelocs::Save(ZapWriter * pZapWriter) -{ - if (m_pRelocs != NULL) - { - - // pre-pass to figure out if we need to sort - // if the offsets are not in ascending order AND the offsets within this - // array ending up describing locations in different pages, the relocation - // writer generates bad relocation info (e.g. multiple entries for the same page) - // that is no longer accepted by the OS loader - // Also, having relocs in ascending order allows a more compact representation. - - ZapReloc *pReloc = m_pRelocs; - - // we need to check only for more than one reloc entry - if (pReloc->m_type != IMAGE_REL_INVALID && pReloc[1].m_type != IMAGE_REL_INVALID) - { - bool isSorted = true; - DWORD lastOffset = pReloc->m_offset; - DWORD cReloc = 1; - - // we start with the second entry (the first entry is already consumed) - while (pReloc[cReloc].m_type != IMAGE_REL_INVALID) - { - // we cannot abort the loop here because we need to count the entries - // to properly sort the relocs!!! - if (pReloc[cReloc].m_offset < lastOffset) - isSorted = false; - lastOffset = pReloc[cReloc].m_offset; - cReloc++; - } - if (!isSorted) - { - qsort(pReloc, cReloc, sizeof(ZapReloc), CmpZapRelocs); - } - } - - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - PBYTE pData = GetData(); - - for (pReloc = m_pRelocs; pReloc->m_type != IMAGE_REL_INVALID; pReloc++) - { - PBYTE pLocation = pData + pReloc->m_offset; - int targetOffset = 0; - - // Decode the offset - switch (pReloc->m_type) - { - case IMAGE_REL_BASED_ABSOLUTE: - targetOffset = *(UNALIGNED DWORD *)pLocation; - break; - - case IMAGE_REL_BASED_ABSOLUTE_TAGGED: - targetOffset = 0; - break; - - case IMAGE_REL_BASED_PTR: - targetOffset = (int)*(UNALIGNED TADDR *)pLocation; - break; - case IMAGE_REL_BASED_RELPTR: - targetOffset = (int)*(UNALIGNED TADDR *)pLocation; - break; - - case IMAGE_REL_BASED_RELPTR32: - targetOffset = (int)*(UNALIGNED INT32 *)pLocation; - break; - -#if defined(TARGET_X86) || defined(TARGET_AMD64) - case IMAGE_REL_BASED_REL32: - targetOffset = *(UNALIGNED INT32 *)pLocation; - break; -#endif // TARGET_X86 || TARGET_AMD64 - -#if defined(TARGET_ARM) - case IMAGE_REL_BASED_THUMB_MOV32: - case IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL: - targetOffset = (int)GetThumb2Mov32((UINT16 *)pLocation); - break; - - case IMAGE_REL_BASED_THUMB_BRANCH24: - targetOffset = GetThumb2BlRel24((UINT16 *)pLocation); - break; -#endif // defined(TARGET_ARM) - -#if defined(TARGET_ARM64) - case IMAGE_REL_ARM64_BRANCH26: - targetOffset = (int)GetArm64Rel28((UINT32*)pLocation); - break; - - case IMAGE_REL_ARM64_PAGEBASE_REL21: - targetOffset = (int)GetArm64Rel21((UINT32*)pLocation); - break; - - case IMAGE_REL_ARM64_PAGEOFFSET_12A: - targetOffset = (int)GetArm64Rel12((UINT32*)pLocation); - break; - -#endif // defined(TARGET_ARM64) - - default: - _ASSERTE(!"Unknown reloc type"); - break; - } - - pImage->WriteReloc(pData, pReloc->m_offset, - pReloc->m_pTargetNode, targetOffset, pReloc->m_type); - } - } - - ZapBlob::Save(pZapWriter); -} - -COUNT_T ZapBlobWithRelocs::GetCountOfStraddlerRelocations(DWORD dwPos) -{ - if (m_pRelocs == NULL) - return 0; - - // Straddlers can exist only if the node is crossing page boundary - if (AlignDown(dwPos, RELOCATION_PAGE_SIZE) == AlignDown(dwPos + GetSize() - 1, RELOCATION_PAGE_SIZE)) - return 0; - - COUNT_T nStraddlers = 0; - - for (ZapReloc * pReloc = m_pRelocs; pReloc->m_type != IMAGE_REL_INVALID; pReloc++) - { - if (pReloc->m_type == IMAGE_REL_BASED_PTR) - { - if (AlignmentTrim(dwPos + pReloc->m_offset, RELOCATION_PAGE_SIZE) > RELOCATION_PAGE_SIZE - TARGET_POINTER_SIZE) - nStraddlers++; - } - } - - return nStraddlers; -} - -ZapBlobWithRelocs * ZapBlobWithRelocs::NewBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize) -{ - S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapBlobWithRelocs)) + S_SIZE_T(cbSize); - if(cbAllocSize.IsOverflow()) - ThrowHR(COR_E_OVERFLOW); - - void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize.Value()]; - - ZapBlobWithRelocs * pZapBlobWithRelocs = new (pMemory) ZapBlobWithRelocs(cbSize); - - if (pData != NULL) - memcpy((void*)(pZapBlobWithRelocs + 1), pData, cbSize); - - return pZapBlobWithRelocs; -} - -template -class ZapAlignedBlobWithRelocsConst : public ZapBlobWithRelocs -{ -protected: - ZapAlignedBlobWithRelocsConst(SIZE_T cbSize) - : ZapBlobWithRelocs(cbSize) - { - } - -public: - virtual UINT GetAlignment() - { - return alignment; - } - - static ZapBlobWithRelocs * NewBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize) - { - S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapAlignedBlobWithRelocsConst)) + S_SIZE_T(cbSize); - if(cbAllocSize.IsOverflow()) - ThrowHR(COR_E_OVERFLOW); - - void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize.Value()]; - - ZapAlignedBlobWithRelocsConst * pZapBlob = new (pMemory) ZapAlignedBlobWithRelocsConst(cbSize); - - if (pData != NULL) - memcpy((void*)(pZapBlob + 1), pData, cbSize); - - return pZapBlob; - } -}; - -ZapBlobWithRelocs * ZapBlobWithRelocs::NewAlignedBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, SIZE_T cbAlignment) -{ - switch (cbAlignment) - { - case 1: - return ZapBlobWithRelocs::NewBlob(pWriter, pData, cbSize); - case 2: - return ZapAlignedBlobWithRelocsConst<2>::NewBlob(pWriter, pData, cbSize); - case 4: - return ZapAlignedBlobWithRelocsConst<4>::NewBlob(pWriter, pData, cbSize); - case 8: - return ZapAlignedBlobWithRelocsConst<8>::NewBlob(pWriter, pData, cbSize); - case 16: - return ZapAlignedBlobWithRelocsConst<16>::NewBlob(pWriter, pData, cbSize); - - default: - _ASSERTE(!"Requested alignment not supported"); - return NULL; - } -} diff --git a/src/coreclr/zap/zaprelocs.h b/src/coreclr/zap/zaprelocs.h deleted file mode 100644 index 9b06450e8c8f1d..00000000000000 --- a/src/coreclr/zap/zaprelocs.h +++ /dev/null @@ -1,128 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapRelocs.h -// - -// -// Zapping of relocations -// -// ====================================================================================== - -#ifndef __ZAPRELOCS_H__ -#define __ZAPRELOCS_H__ - -typedef BYTE ZapRelocationType; // IMAGE_REL_XXX enum - -// Special NGEN-specific relocation type for fixups (absolute RVA in the middle 30 bits) -#define IMAGE_REL_BASED_ABSOLUTE_TAGGED 0x7E - -// Special NGEN-specific relocation type for relative pointer (used to make NGen relocation section smaller) -#define IMAGE_REL_BASED_RELPTR 0x7D -#define IMAGE_REL_BASED_RELPTR32 0x7C - -// Invalid reloc marker (used to mark end of the reloc array) -#define IMAGE_REL_INVALID 0xFF - -// IMAGE_REL_BASED_PTR is architecture specific reloc of virtual address -#ifdef TARGET_64BIT -#define IMAGE_REL_BASED_PTR IMAGE_REL_BASED_DIR64 -#else -#define IMAGE_REL_BASED_PTR IMAGE_REL_BASED_HIGHLOW -#endif - -// Size of base relocs relocation page -#define RELOCATION_PAGE_SIZE 0x1000 - -// -// The ZapNode for regular PE base relocs -// - -class ZapBaseRelocs : public ZapNode -{ - ZapImage * m_pImage; - - // The page currently being written - DWORD m_page; - COUNT_T m_pageIndex; - - // Reloc writer output - SArray m_SerializedRelocs; - - void FlushWriter(); - -public: - ZapBaseRelocs(ZapImage * pImage) - : m_pImage(pImage) - { - // Everything is zero initialized by the allocator - } - - void WriteReloc(PVOID pSrc, int offset, ZapNode * pTarget, int targetOffset, ZapRelocationType type); - - virtual DWORD GetSize() - { - return m_SerializedRelocs.GetCount() * sizeof(USHORT); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_Relocs; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -// -// -// Blob with associated relocations. Used for compiled code. -// - -struct ZapReloc -{ - ZapRelocationType m_type; - DWORD m_offset; - ZapNode * m_pTargetNode; -}; - -class ZapBlobWithRelocs : public ZapBlob -{ - ZapReloc * m_pRelocs; - -protected: - ZapBlobWithRelocs(SIZE_T cbSize) - : ZapBlob(cbSize) - { - } - -public: - void SetRelocs(ZapReloc * pRelocs) - { - _ASSERTE(m_pRelocs == NULL); - _ASSERTE(pRelocs != NULL); - m_pRelocs = pRelocs; - } - - ZapReloc * GetRelocs() - { - return m_pRelocs; - } - - virtual PBYTE GetData() - { - return (PBYTE)(this + 1); - } - - virtual void Save(ZapWriter * pZapWriter); - - // Returns number of straddler relocs, assuming RVA of the node is dwPos - COUNT_T GetCountOfStraddlerRelocations(DWORD dwPos); - - // Create new zap blob node. The node *does* own copy of the memory. - static ZapBlobWithRelocs * NewBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize); - - // Create new aligned zap blob node. - static ZapBlobWithRelocs * NewAlignedBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, SIZE_T cbAlignment); -}; - -#endif // __ZAPRELOCS_H__ diff --git a/src/coreclr/zap/zapwrapper.cpp b/src/coreclr/zap/zapwrapper.cpp deleted file mode 100644 index b9dc87c8a0afdd..00000000000000 --- a/src/coreclr/zap/zapwrapper.cpp +++ /dev/null @@ -1,200 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapWrapper.cpp -// - -// -// ZapNode that wraps EE datastructure for zapping -// -// ====================================================================================== - -#include "common.h" - -#include "zapwrapper.h" - -void ZapWrapperTable::Resolve() -{ - for (WrapperTable::Iterator i = m_entries.Begin(), end = m_entries.End(); i != end; i++) - { - (*i)->Resolve(m_pImage); - } -} - -// ====================================================================================== -// Actual placeholders - -class ZapMethodHandle : public ZapWrapper -{ -public: - virtual void Resolve(ZapImage * pImage) - { - SetRVA(pImage->m_pPreloader->MapMethodHandle(CORINFO_METHOD_HANDLE(GetHandle()))); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_MethodHandle; - } -}; - -ZapNode * ZapWrapperTable::GetMethodHandle(CORINFO_METHOD_HANDLE handle) -{ - return GetPlaceHolder(handle); -} - -class ZapClassHandle : public ZapWrapper -{ -public: - virtual void Resolve(ZapImage * pImage) - { - SetRVA(pImage->m_pPreloader->MapClassHandle(CORINFO_CLASS_HANDLE(GetHandle()))); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_ClassHandle; - } -}; - -ZapNode * ZapWrapperTable::GetClassHandle(CORINFO_CLASS_HANDLE handle) -{ - return GetPlaceHolder(handle); -} - -class ZapFieldHandle : public ZapWrapper -{ -public: - virtual void Resolve(ZapImage * pImage) - { - SetRVA(pImage->m_pPreloader->MapFieldHandle(CORINFO_FIELD_HANDLE(GetHandle()))); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_FieldHandle; - } -}; - -ZapNode * ZapWrapperTable::GetFieldHandle(CORINFO_FIELD_HANDLE handle) -{ - return GetPlaceHolder(handle); -} - -class ZapAddrOfPInvokeFixup : public ZapWrapper -{ -public: - virtual void Resolve(ZapImage * pImage) - { - SetRVA(pImage->m_pPreloader->MapAddressOfPInvokeFixup(CORINFO_METHOD_HANDLE((BYTE *)GetHandle() - 1))); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_AddrOfPInvokeFixup; - } -}; - -ZapNode * ZapWrapperTable::GetAddrOfPInvokeFixup(CORINFO_METHOD_HANDLE handle) -{ - // Disambiguate the normal method handle and address of P/Invoke fixup by adding 1 - return GetPlaceHolder((BYTE *)handle + 1); -} - -class ZapGenericHandle : public ZapWrapper -{ -public: - virtual void Resolve(ZapImage * pImage) - { - SetRVA(pImage->m_pPreloader->MapGenericHandle(CORINFO_GENERIC_HANDLE(GetHandle()))); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_GenericHandle; - } -}; - -ZapNode * ZapWrapperTable::GetGenericHandle(CORINFO_GENERIC_HANDLE handle) -{ - return GetPlaceHolder(handle); -} - -class ZapModuleIDHandle : public ZapWrapper -{ -public: - virtual void Resolve(ZapImage * pImage) - { - SetRVA(pImage->m_pPreloader->MapModuleIDHandle(CORINFO_MODULE_HANDLE(GetHandle()))); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_ModuleIDHandle; - } -}; - -ZapNode * ZapWrapperTable::GetModuleIDHandle(CORINFO_MODULE_HANDLE handle) -{ - return GetPlaceHolder(handle); -} - -class ZapStub : public ZapWrapper -{ - DWORD m_dwStubSize; - -public: - ZapStub(PVOID pStubData, DWORD dwStubSize) - : ZapWrapper(pStubData), m_dwStubSize(dwStubSize) - { - } - - virtual DWORD GetSize() - { - return m_dwStubSize; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_Stub; - } - - virtual UINT GetAlignment() - { - return DEFAULT_CODE_ALIGN; - } - - virtual void Save(ZapWriter * pZapWriter) - { - DWORD dwSize = GetSize(); - PVOID pStub = GetHandle(); - - SBuffer stubClone(dwSize); - - ICorCompileInfo *pCompileInfo = ZapImage::GetImage(pZapWriter)->GetCompileInfo(); - IfFailThrow(pCompileInfo->GetStubClone(pStub, - const_cast(static_cast(stubClone)), dwSize)); - - pZapWriter->Write(const_cast(static_cast(stubClone)), dwSize); - } -}; - -ZapNode * ZapWrapperTable::GetStub(void * pStub) -{ - DWORD dwStubSize = 0; - void * pStubData = m_pImage->GetCompileInfo()->GetStubSize(pStub, &dwStubSize); - _ASSERTE(pStubData < pStub && pStub < (BYTE*)pStubData + dwStubSize); - - ZapStub * pZapStub = (ZapStub *)m_entries.Lookup(pStubData); - if (pZapStub == NULL) - { - // did not find the delegate stub, need to emit the stub in the native image - pZapStub = new (m_pImage->GetHeap()) ZapStub(pStubData, dwStubSize); - - m_entries.Add(pZapStub); - } - - // Return inner ptr for the entrypoint - _ASSERTE(pZapStub->GetType() == ZapNodeType_Stub); - return m_pImage->GetInnerPtr(pZapStub, (PBYTE)pStub - (PBYTE)pStubData); -} diff --git a/src/coreclr/zap/zapwrapper.h b/src/coreclr/zap/zapwrapper.h deleted file mode 100644 index ea914da749710c..00000000000000 --- a/src/coreclr/zap/zapwrapper.h +++ /dev/null @@ -1,141 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapWrapper.h -// - -// -// ZapNode that wraps EE datastructure for zapping -// -// ====================================================================================== - -#ifndef __ZAPWRAPPER_H__ -#define __ZAPWRAPPER_H__ - -// -// When generating compiled code for IL, the compiler will need to embed -// handles, which are pointers to various data structures. The data -// structures may either not exist, or we may not have some information -// we need for optimal code gen. -// -// In such cases, we use placeholders. Compiled code embed pointers -// to placeholders, which then have rich information about the -// referenced data structure. -// -// Once information is finally available for the exact code required, -// ZapWrapper::Resolve makes the place holder to point to the intended target. -// - -class ZapWrapper : public ZapNode -{ - PVOID m_handle; - -public: - ZapWrapper(PVOID handle) - : m_handle(handle) - { - } - - ZapWrapper() - { - } - - void SetHandle(PVOID handle) - { - _ASSERTE(m_handle == NULL); - _ASSERTE(handle != NULL); - m_handle = handle; - } - - PVOID GetHandle() - { - return m_handle; - } - - virtual ZapNode * GetBase() - { - return this; - } - - virtual void Resolve(ZapImage * pImage) - { - } -}; - -class ZapWrapperTable -{ - class WrapperTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef PVOID key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e->GetHandle(); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return k1 == k2; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(size_t)k; - } - - static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } - }; - - typedef SHash< WrapperTraits > WrapperTable; - - WrapperTable m_entries; - ZapImage * m_pImage; - - // - // Helper for inserting actual implementations of placeholders into hashtable - // - template < typename impl, ZapNodeType type > - ZapNode * GetPlaceHolder(PVOID handle) - { - ZapWrapper * pPlaceHolder = m_entries.Lookup(handle); - - if (pPlaceHolder != NULL) - { - _ASSERTE(pPlaceHolder->GetType() == type); - return pPlaceHolder; - } - - pPlaceHolder = new (m_pImage->GetHeap()) impl(); - _ASSERTE(pPlaceHolder->GetType() == type); - pPlaceHolder->SetHandle(handle); - m_entries.Add(pPlaceHolder); - return pPlaceHolder; - } - -public: - ZapWrapperTable(ZapImage * pImage) - : m_pImage(pImage) - { - } - - void Preallocate(COUNT_T cbILImage) - { - PREALLOCATE_HASHTABLE(ZapWrapperTable::m_entries, 0.0013, cbILImage); - } - - ZapNode * GetMethodHandle(CORINFO_METHOD_HANDLE handle); - ZapNode * GetClassHandle(CORINFO_CLASS_HANDLE handle); - ZapNode * GetFieldHandle(CORINFO_FIELD_HANDLE handle); - ZapNode * GetAddrOfPInvokeFixup(CORINFO_METHOD_HANDLE handle); - ZapNode * GetGenericHandle(CORINFO_GENERIC_HANDLE handle); - ZapNode * GetModuleIDHandle(CORINFO_MODULE_HANDLE handle); - - ZapNode * GetStub(void * pStub); - - void Resolve(); -}; - -#endif // __ZAPWRAPPER_H__ diff --git a/src/coreclr/zap/zapwriter.cpp b/src/coreclr/zap/zapwriter.cpp deleted file mode 100644 index 4642c2af698abe..00000000000000 --- a/src/coreclr/zap/zapwriter.cpp +++ /dev/null @@ -1,697 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapWriter.cpp -// - -// -// Infrastructure for writing PE files. (Not NGEN specific) -// -// ====================================================================================== - -#include "common.h" - -//--------------------------------------------------------------------------------------- -// ZapNode - -void * operator new(size_t size, ZapHeap * pHeap) -{ - return ((LoaderHeap*)pHeap)->AllocMem(S_SIZE_T(size)); -} - -void * operator new[](size_t size, ZapHeap * pHeap) -{ - return ((LoaderHeap*)pHeap)->AllocMem(S_SIZE_T(size)); -} - -//--------------------------------------------------------------------------------------- -// ZapWriter - -ZapWriter::ZapWriter() -{ -} - -ZapWriter::~ZapWriter() -{ - for (COUNT_T iPhysicalSection = 0; iPhysicalSection < m_Sections.GetCount(); iPhysicalSection++) - { - ZapPhysicalSection * pPhysicalSection = m_Sections[iPhysicalSection]; - pPhysicalSection->~ZapPhysicalSection(); - } - delete (LoaderHeap*)m_pHeap; -} - -void ZapWriter::Initialize() -{ - const DWORD dwReserveSize = 0x1000000; - const DWORD dwCommitSize = 0x10000; - - m_pHeap = reinterpret_cast(new LoaderHeap(dwReserveSize, dwCommitSize)); - - m_isDll = true; - - // Default file alignment - m_FileAlignment = 0x200; -} - -#if defined(TARGET_UNIX) && defined(TARGET_64BIT) -#define SECTION_ALIGNMENT m_FileAlignment -#define PAL_MAX_PAGE_SIZE 0x10000 -#else -#define SECTION_ALIGNMENT 0x1000 -#define PAL_MAX_PAGE_SIZE 0 -#endif - -void ZapWriter::Save(IStream * pStream) -{ - INDEBUG(m_fSaving = TRUE;) - - InitializeWriter(pStream); - - _ASSERTE(m_Sections.GetCount() > 0); - - ZapPhysicalSection * pLastPhysicalSection = m_Sections[m_Sections.GetCount() - 1]; - - ULARGE_INTEGER estimatedFileSize; - estimatedFileSize.QuadPart = pLastPhysicalSection->m_dwFilePos + pLastPhysicalSection->m_dwSizeOfRawData; - - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_NGenSimulateDiskFull) != 0) - { - ThrowHR(HRESULT_FROM_WIN32(ERROR_DISK_FULL)); - } - - // Set the file size upfront to reduce disk fragmentation - IfFailThrow(pStream->SetSize(estimatedFileSize)); - - LARGE_INTEGER zero; - zero.QuadPart = 0; - - // Write the content of all sections - IfFailThrow(pStream->Seek(zero, STREAM_SEEK_SET, NULL)); - SaveContent(); - FlushWriter(); - - // Finally write the NT headers - IfFailThrow(pStream->Seek(zero, STREAM_SEEK_SET, NULL)); - SaveHeaders(); - FlushWriter(); -} - -DWORD ZapNode::ComputeRVA(ZapWriter * pZapWriter, DWORD dwPos) -{ - dwPos = AlignUp(dwPos, GetAlignment()); - - SetRVA(dwPos); - - dwPos += GetSize(); - - return dwPos; -} - -void ZapWriter::ComputeRVAs() -{ - DWORD dwHeaderSize = GetSizeOfNTHeaders(); - - DWORD dwPos = dwHeaderSize; - DWORD dwFilePos = dwHeaderSize; - - for (COUNT_T iPhysicalSection = 0; iPhysicalSection < m_Sections.GetCount(); iPhysicalSection++) - { - ZapPhysicalSection * pPhysicalSection = m_Sections[iPhysicalSection]; - - DWORD dwAlignedFilePos = AlignUp(dwFilePos, m_FileAlignment); - dwFilePos = dwAlignedFilePos; - - pPhysicalSection->m_dwFilePos = dwFilePos; - - dwPos = AlignUp(dwPos, SECTION_ALIGNMENT) + PAL_MAX_PAGE_SIZE; - pPhysicalSection->SetRVA(dwPos); - - DWORD dwEndOfRawData = dwPos; - -#ifdef REDHAWK - printf("Physical Section \"%s\" {\n", pPhysicalSection->m_pszName); -#endif // REDHAWK - - for (COUNT_T iVirtualSection = 0; iVirtualSection < pPhysicalSection->m_Sections.GetCount(); iVirtualSection++) - { - ZapVirtualSection * pVirtualSection = pPhysicalSection->m_Sections[iVirtualSection]; - - // Do not bother with empty virtual sections - if (pVirtualSection->m_Nodes.GetCount() == 0) - continue; - - dwPos = AlignUp(dwPos, pVirtualSection->m_dwAlignment); - pVirtualSection->SetRVA(dwPos); - - for (COUNT_T iNode = 0; iNode < pVirtualSection->m_Nodes.GetCount(); iNode++) - { - ZapNode * pNode = pVirtualSection->m_Nodes[iNode]; - - DWORD dwNextPos = pNode->ComputeRVA(this, dwPos); - _ASSERTE(dwNextPos >= dwPos); - - if (dwNextPos < dwPos || dwNextPos > ZAPWRITER_MAX_SIZE) - ThrowHR(COR_E_OVERFLOW); - - dwPos = dwNextPos; - } - - pVirtualSection->m_dwSize = dwPos - pVirtualSection->GetRVA(); - - if (iVirtualSection < pPhysicalSection->m_Sections.GetCount() - pPhysicalSection->m_nBssSections) - dwEndOfRawData = dwPos; -#ifdef REDHAWK - if (pVirtualSection->m_dwSize > 0) - { - printf(" %08x (%6u bytes): %s\n", pVirtualSection->GetRVA(), pVirtualSection->m_dwSize, pVirtualSection->m_pszTag); - } -#endif // REDHAWK - } - - pPhysicalSection->m_dwSize = dwPos - pPhysicalSection->GetRVA(); - - pPhysicalSection->m_dwSizeOfRawData = dwEndOfRawData - pPhysicalSection->GetRVA(); - - dwFilePos += pPhysicalSection->m_dwSizeOfRawData; - -#ifdef REDHAWK - printf(" %08x: end\n", dwPos); - printf("}\n"); -#endif // REDHAWK - } -} - -void ZapWriter::SaveContent() -{ - DWORD dwHeaderSize = GetSizeOfNTHeaders(); - - WritePad(dwHeaderSize); - - DWORD dwPos = dwHeaderSize; - DWORD dwFilePos = dwHeaderSize; - - for (COUNT_T iPhysicalSection = 0; iPhysicalSection < m_Sections.GetCount(); iPhysicalSection++) - { - ZapPhysicalSection * pPhysicalSection = m_Sections[iPhysicalSection]; - DWORD dwAlignedFilePos = AlignUp(dwFilePos, m_FileAlignment); - WritePad(dwAlignedFilePos - dwFilePos); - dwFilePos = dwAlignedFilePos; - - dwPos = AlignUp(dwPos, SECTION_ALIGNMENT) + PAL_MAX_PAGE_SIZE; - - if (m_fWritingRelocs) - { - pPhysicalSection->m_RVA = dwPos; - pPhysicalSection->m_dwFilePos = dwFilePos; - } - _ASSERTE(pPhysicalSection->GetRVA() == dwPos); - _ASSERTE(pPhysicalSection->m_dwFilePos == dwFilePos); - _ASSERTE(m_dwWriterFilePos == dwFilePos); - - for (COUNT_T iVirtualSection = 0; iVirtualSection < pPhysicalSection->m_Sections.GetCount() - pPhysicalSection->m_nBssSections; iVirtualSection++) - { - ZapVirtualSection * pVirtualSection = pPhysicalSection->m_Sections[iVirtualSection]; - - // Do not bother with empty virtual sections - if (pVirtualSection->m_Nodes.GetCount() == 0) - continue; - - if (m_fWritingRelocs) - { - pVirtualSection->m_RVA = dwPos; - - _ASSERTE(pVirtualSection->m_Nodes.GetCount() == 1); - pVirtualSection->m_Nodes[0]->m_RVA = dwPos; - } - - DWORD dwVirtualSectionPos = pVirtualSection->GetRVA(); - if (dwVirtualSectionPos != dwPos) - WritePad(dwVirtualSectionPos - dwPos); - dwPos = dwVirtualSectionPos; - - for (COUNT_T iNode = 0; iNode < pVirtualSection->m_Nodes.GetCount(); iNode++) - { - ZapNode * pNode = pVirtualSection->m_Nodes[iNode]; - - DWORD dwNodePos = pNode->GetRVA(); - if (dwNodePos != dwPos) - WritePad(dwNodePos - dwPos, pVirtualSection->m_defaultFill); - dwPos = dwNodePos; - - m_dwCurrentRVA = dwPos; - pNode->Save(this); - -#ifdef _DEBUG - if (dwPos + pNode->GetSize() != m_dwCurrentRVA) - { - _ASSERTE(!"Mismatch between ZapNode::GetSize() and ZapNode::Save() implementations"); - pNode->GetSize(); - pNode->Save(this); - } -#endif - - dwPos = m_dwCurrentRVA; - } - - DWORD dwVirtualSectionSize = dwPos - pVirtualSection->GetRVA(); - if (m_fWritingRelocs) - { - pVirtualSection->m_dwSize = dwVirtualSectionSize; - } - _ASSERTE(pVirtualSection->m_dwSize == dwVirtualSectionSize); - } - - DWORD dwPhysicalSectionSize = dwPos - pPhysicalSection->GetRVA(); - if (m_fWritingRelocs) - { - pPhysicalSection->m_dwSize = dwPhysicalSectionSize; - pPhysicalSection->m_dwSizeOfRawData = dwPhysicalSectionSize; - } - _ASSERTE(pPhysicalSection->m_dwSizeOfRawData == dwPhysicalSectionSize); - - dwPos = pPhysicalSection->GetRVA() + pPhysicalSection->m_dwSize; - - dwFilePos += pPhysicalSection->m_dwSizeOfRawData; - } - - WritePad(AlignmentPad(dwFilePos, m_FileAlignment)); -} - -//--------------------------------------------------------------------------------------- -// -// ZapVirtualSection -// -#ifdef REDHAWK -UINT32 ZapVirtualSection::FillInNodeOffsetMap(MapSHash * pMap) -{ - UINT32 dataSize = 0; - for (int i = 0; i < m_Nodes.GetCount(); i++) - { - ZapNode* pNode = m_Nodes[i]; - pMap->Add(pNode, dataSize); - dataSize += pNode->GetSize(); - } - - return dataSize; -} -#endif // REDHAWK - -//--------------------------------------------------------------------------------------- -// Simple buffered writer - -#define WRITE_BUFFER_SIZE 0x10000 - -void ZapWriter::InitializeWriter(IStream * pStream) -{ - m_pBuffer = new (GetHeap()) BYTE[WRITE_BUFFER_SIZE]; - m_nBufferPos = 0; - - m_pStream = pStream; - - INDEBUG(m_dwWriterFilePos = 0;) -} - -void ZapWriter::FlushWriter() -{ - if (m_nBufferPos > 0) - { - ULONG cbWritten; - IfFailThrow(m_pStream->Write(m_pBuffer, m_nBufferPos, &cbWritten)); - _ASSERTE(cbWritten == m_nBufferPos); - - m_nBufferPos = 0; - } -} - -void ZapWriter::Write(PVOID p, DWORD dwSize) -{ - m_dwCurrentRVA += dwSize; - INDEBUG(m_dwWriterFilePos += dwSize;) - - if (m_dwCurrentRVA >= ZAPWRITER_MAX_SIZE) - ThrowHR(COR_E_OVERFLOW); - - DWORD cbAvailable = min(dwSize, WRITE_BUFFER_SIZE - m_nBufferPos); - - memcpy(m_pBuffer + m_nBufferPos, p, cbAvailable); - p = (PBYTE)p + cbAvailable; - dwSize -= cbAvailable; - - m_nBufferPos += cbAvailable; - - if (m_nBufferPos < WRITE_BUFFER_SIZE) - return; - - FlushWriter(); - - if (dwSize == 0) - return; - - cbAvailable = AlignDown(dwSize, WRITE_BUFFER_SIZE); - - if (cbAvailable > 0) - { - ULONG cbWritten; - IfFailThrow(m_pStream->Write(p, cbAvailable, &cbWritten)); - _ASSERTE(cbWritten == cbAvailable); - - p = (PBYTE)p + cbAvailable; - dwSize -= cbAvailable; - } - - _ASSERTE(m_nBufferPos == 0); - memcpy(m_pBuffer, p, dwSize); - m_nBufferPos = dwSize; -} - -void ZapWriter::WritePad(DWORD dwSize, BYTE fill) -{ - m_dwCurrentRVA += dwSize; - INDEBUG(m_dwWriterFilePos += dwSize;) - - if (m_dwCurrentRVA >= ZAPWRITER_MAX_SIZE) - ThrowHR(COR_E_OVERFLOW); - - DWORD cbAvailable = min(dwSize, WRITE_BUFFER_SIZE - m_nBufferPos); - - memset(m_pBuffer + m_nBufferPos, fill, cbAvailable); - dwSize -= cbAvailable; - - m_nBufferPos += cbAvailable; - - if (m_nBufferPos < WRITE_BUFFER_SIZE) - return; - - FlushWriter(); - - if (dwSize == 0) - return; - - memset(m_pBuffer, fill, min(WRITE_BUFFER_SIZE, dwSize)); - - while (dwSize >= WRITE_BUFFER_SIZE) - { - ULONG cbWritten; - cbAvailable = min(WRITE_BUFFER_SIZE, dwSize); - IfFailThrow(m_pStream->Write(m_pBuffer, cbAvailable, &cbWritten)); - _ASSERTE(cbWritten == cbAvailable); - - dwSize -= cbAvailable; - } - - m_nBufferPos = dwSize; -} - -STDMETHODIMP ZapWriter::Write(void const *pv, ULONG cb, ULONG *pcbWritten) -{ - HRESULT hr = S_OK; - - EX_TRY - { - Write((PVOID)pv, cb); - - if (pcbWritten != 0) - *pcbWritten = cb; - } - EX_CATCH_HRESULT(hr) - - return hr; -} - -//--------------------------------------------------------------------------------------- -// NT Headers - -void ZapWriter::SaveHeaders() -{ - SaveDosHeader(); - SaveSignature(); - SaveFileHeader(); - SaveOptionalHeader(); - SaveSections(); -} - -void ZapWriter::SaveDosHeader() -{ - IMAGE_DOS_HEADER header; - - ZeroMemory(&header, sizeof(header)); - - header.e_magic = VAL16(IMAGE_DOS_SIGNATURE); - header.e_lfanew = VAL32(sizeof(IMAGE_DOS_HEADER)); - - // Legacy tools depend on e_lfarlc to be 0x40 - header.e_lfarlc = VAL16(0x40); - - // We put the PE Signature at 0x80 so that we are the same offset for IL Images - - header.e_lfanew = VAL32(sizeof(IMAGE_DOS_HEADER) + 0x40); - Write(&header, sizeof(header)); - - // Write out padding to get to offset 0x80 - WritePad(0x40); -} - -void ZapWriter::SaveSignature() -{ - ULONG Signature = VAL32(IMAGE_NT_SIGNATURE); - Write(&Signature, sizeof(Signature)); -} - -void ZapWriter::SaveFileHeader() -{ - IMAGE_FILE_HEADER fileHeader; - ZeroMemory(&fileHeader, sizeof(fileHeader)); - - fileHeader.Machine = VAL16(GetMachine()); - fileHeader.TimeDateStamp = VAL32(m_dwTimeDateStamp); - fileHeader.SizeOfOptionalHeader = Is64Bit() ? VAL16(sizeof(IMAGE_OPTIONAL_HEADER64)) : VAL16(sizeof(IMAGE_OPTIONAL_HEADER32)); - - // Count the number of non-empty physical sections - int nSections = 0; - for (COUNT_T iPhysicalSection = 0; iPhysicalSection < m_Sections.GetCount(); iPhysicalSection++) - { - if (m_Sections[iPhysicalSection]->m_dwSize != 0) - nSections++; - } - fileHeader.NumberOfSections = VAL16(nSections); - - fileHeader.Characteristics = VAL16(IMAGE_FILE_EXECUTABLE_IMAGE | - (Is64Bit() ? 0 : IMAGE_FILE_32BIT_MACHINE) | - (m_isDll ? IMAGE_FILE_DLL : 0) | - (Is64Bit() ? IMAGE_FILE_LARGE_ADDRESS_AWARE : 0) ); - - Write(&fileHeader, sizeof(fileHeader)); -} - -void ZapWriter::SaveOptionalHeader() -{ - // Write the correct flavor of the optional header - union - { - IMAGE_OPTIONAL_HEADER32 header32; - IMAGE_OPTIONAL_HEADER64 header64; - } - optionalHeader; - - ZeroMemory(&optionalHeader, sizeof(optionalHeader)); - - PIMAGE_OPTIONAL_HEADER pHeader = (PIMAGE_OPTIONAL_HEADER)&optionalHeader; - - // Common fields between 32-bit and 64-bit - - // Linker version should be consistent with current VC level - pHeader->MajorLinkerVersion = 11; - - pHeader->SectionAlignment = VAL32(SECTION_ALIGNMENT); - pHeader->FileAlignment = VAL32(m_FileAlignment); - - // Win2k = 5.0 for 32-bit images, Win2003 = 5.2 for 64-bit images - pHeader->MajorOperatingSystemVersion = VAL16(5); - pHeader->MinorOperatingSystemVersion = Is64Bit() ? VAL16(2) : VAL16(0); - - pHeader->MajorSubsystemVersion = pHeader->MajorOperatingSystemVersion; - pHeader->MinorSubsystemVersion = pHeader->MinorOperatingSystemVersion; - -#ifdef REDHAWK - pHeader->AddressOfEntryPoint = m_entryPointRVA; -#endif - - ZapPhysicalSection * pLastPhysicalSection = m_Sections[m_Sections.GetCount() - 1]; - pHeader->SizeOfImage = VAL32(AlignUp(pLastPhysicalSection->GetRVA() + pLastPhysicalSection->m_dwSize, SECTION_ALIGNMENT)); - - pHeader->SizeOfHeaders = VAL32(AlignUp(GetSizeOfNTHeaders(), m_FileAlignment)); - - pHeader->Subsystem = VAL16(m_Subsystem); - pHeader->DllCharacteristics = VAL16(m_DllCharacteristics); - - - // Different fields between 32-bit and 64-bit - - PIMAGE_DATA_DIRECTORY pDataDirectory; - - if (Is64Bit()) - { - PIMAGE_OPTIONAL_HEADER64 pHeader64 = (PIMAGE_OPTIONAL_HEADER64)pHeader; - - pHeader64->Magic = VAL16(IMAGE_NT_OPTIONAL_HDR64_MAGIC); - - pHeader64->ImageBase = VAL64(m_BaseAddress); - pHeader64->NumberOfRvaAndSizes = VAL32(IMAGE_NUMBEROF_DIRECTORY_ENTRIES); - - pHeader64->SizeOfStackReserve = VAL64(m_SizeOfStackReserve); - pHeader64->SizeOfStackCommit = VAL64(m_SizeOfStackCommit); - - pDataDirectory = pHeader64->DataDirectory; - } - else - { - PIMAGE_OPTIONAL_HEADER32 pHeader32 = (PIMAGE_OPTIONAL_HEADER32)pHeader; - - pHeader32->Magic = VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC); - - pHeader32->ImageBase = VAL32((ULONG)m_BaseAddress); - pHeader32->NumberOfRvaAndSizes = VAL32(IMAGE_NUMBEROF_DIRECTORY_ENTRIES); - - pHeader32->SizeOfStackReserve = VAL32((ULONG)m_SizeOfStackReserve); - pHeader32->SizeOfStackCommit = VAL32((ULONG)m_SizeOfStackCommit); - - pDataDirectory = pHeader32->DataDirectory; - } - - for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) - { - SetDirectoryData(&pDataDirectory[i], m_DirectoryEntries[i]); - } - - Write(&optionalHeader, Is64Bit() ? sizeof(IMAGE_OPTIONAL_HEADER64) : sizeof(IMAGE_OPTIONAL_HEADER32)); -} - -void ZapWriter::SaveSections() -{ - for (COUNT_T iPhysicalSection = 0; iPhysicalSection < m_Sections.GetCount(); iPhysicalSection++) - { - ZapPhysicalSection * pPhysicalSection = m_Sections[iPhysicalSection]; - - // Do not save empty sections - if (pPhysicalSection->m_dwSize == 0) - continue; - - IMAGE_SECTION_HEADER header; - ZeroMemory(&header, sizeof(header)); - - SIZE_T cbName = strlen(pPhysicalSection->m_pszName); - _ASSERTE(cbName <= sizeof(header.Name)); - memcpy(header.Name, pPhysicalSection->m_pszName, min(sizeof(header.Name), cbName)); - - header.Misc.VirtualSize = VAL32(pPhysicalSection->m_dwSize); - header.VirtualAddress = VAL32(pPhysicalSection->GetRVA()); - - header.SizeOfRawData = VAL32(AlignUp(pPhysicalSection->m_dwSizeOfRawData, m_FileAlignment)); - - if (header.SizeOfRawData != 0) - header.PointerToRawData = VAL32(pPhysicalSection->m_dwFilePos); - - header.Characteristics = VAL32(pPhysicalSection->m_dwCharacteristics); - - Write(&header, sizeof(header)); - } -} - -DWORD ZapWriter::GetSizeOfNTHeaders() -{ - return sizeof(IMAGE_DOS_HEADER) + 0x40 + /* Padding for DOS Header */ - sizeof(ULONG) + - sizeof(IMAGE_FILE_HEADER) + - (Is64Bit() ? sizeof(IMAGE_OPTIONAL_HEADER64) : sizeof(IMAGE_OPTIONAL_HEADER32)) + - (m_Sections.GetCount() * sizeof(IMAGE_SECTION_HEADER)); -} - -void ZapWriter::SetDirectoryData(IMAGE_DATA_DIRECTORY * pDir, ZapNode * pZapNode) -{ - DWORD size = (pZapNode != NULL) ? pZapNode->GetSize() : 0; - - if (size != 0) - { - pDir->VirtualAddress = pZapNode->GetRVA(); - pDir->Size = size; - } - else - { - pDir->VirtualAddress = 0; - pDir->Size = 0; - } -} - -//--------------------------------------------------------------------------------------- -// ZapBlob - -ZapBlob * ZapBlob::NewBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize) -{ - S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapBlob)) + S_SIZE_T(cbSize); - if(cbAllocSize.IsOverflow()) - ThrowHR(COR_E_OVERFLOW); - - void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize.Value()]; - - ZapBlob * pZapBlob = new (pMemory) ZapBlob(cbSize); - - if (pData != NULL) - memcpy((void*)(pZapBlob + 1), pData, cbSize); - - return pZapBlob; -} - -template -class ZapAlignedBlobConst : public ZapBlob -{ -protected: - ZapAlignedBlobConst(SIZE_T cbSize) - : ZapBlob(cbSize) - { - } - -public: - virtual UINT GetAlignment() - { - return alignment; - } - - static ZapBlob * NewBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize) - { - S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapAlignedBlobConst)) + S_SIZE_T(cbSize); - if(cbAllocSize.IsOverflow()) - ThrowHR(COR_E_OVERFLOW); - - void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize.Value()]; - - ZapAlignedBlobConst * pZapBlob = new (pMemory) ZapAlignedBlobConst(cbSize); - - if (pData != NULL) - memcpy((void *)(pZapBlob + 1), pData, cbSize); - - return pZapBlob; - } -}; - -ZapBlob * ZapBlob::NewAlignedBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, SIZE_T cbAlignment) -{ - switch (cbAlignment) - { - case 4: - return ZapAlignedBlobConst<4>::NewBlob(pWriter, pData, cbSize); - case 8: - return ZapAlignedBlobConst<8>::NewBlob(pWriter, pData, cbSize); - case 16: - return ZapAlignedBlobConst<16>::NewBlob(pWriter, pData, cbSize); - - default: - _ASSERTE(!"Requested alignment not supported"); - return NULL; - } -} - -void ZapBlob::Save(ZapWriter * pZapWriter) -{ - pZapWriter->Write(GetData(), GetSize()); -} diff --git a/src/coreclr/zap/zapwriter.h b/src/coreclr/zap/zapwriter.h deleted file mode 100644 index 295a38ade3958a..00000000000000 --- a/src/coreclr/zap/zapwriter.h +++ /dev/null @@ -1,752 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapWriter.h -// - -// -// Infrastructure for writing PE files. (Not NGEN specific) -// -// ====================================================================================== - - - -#ifndef __ZAPWRITER_H__ -#define __ZAPWRITER_H__ - -#include "zapnodetype.h" - -class ZapWriter; -class ZapHeap; - -// This is maximum size of anything in the image written by ZapWriter. Used for overflow checking. -#define ZAPWRITER_MAX_SIZE 0x3FFFFFFF - -// All ZapNodes should be allocated from ZapHeap returned by ZapWriter::GetHeap() -void *operator new(size_t size, ZapHeap * pZapHeap); -void *operator new[](size_t size, ZapHeap * pZapHeap); - -// -// ZapHeap does not support deallocation. Empty operators delete avoids deallocating memory -// if the constructor fails -// -inline void operator delete(void *, ZapHeap * pZapHeap) -{ - // Memory allocated by ZapHeap is never freed -} -inline void operator delete[](void *, ZapHeap * pZapHeap) -{ - // Memory allocated by ZapHeap is never freed -} - - -//------------------------------------------------------------------------------------------------------ -// ZapNode is the basic building block of the native image. Every ZapNode must know how to persist itself. -// -// The basic contract for a ZapNode is that it understands its allocations requirements (size and alignment), -// and knows how to save itself (given a ZapWriter). At some point a ZapNode is given a location in the -// executable (an RVA), which it is responsible remembering. -// -// See file:../../doc/BookOfTheRuntime/NGEN/NGENDesign.doc for an overview. -// -class ZapNode -{ - friend class ZapWriter; - - DWORD m_RVA; - -public: - void SetRVA(DWORD dwRVA) - { - _ASSERTE(m_RVA == 0 || m_RVA == (DWORD)-1); - m_RVA = dwRVA; - } - - ZapNode() - { - // All ZapNodes are expected to be allocate from ZapWriter::GetHeap() that returns zero filled memory -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wuninitialized" -#endif - _ASSERTE(m_RVA == 0); -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - } - - // This constructor should be used to allocate temporary ZapNodes on the stack only - ZapNode(DWORD rva) - : m_RVA(rva) - { - } - - virtual ~ZapNode() - { - } - - // Returns the size of the node in the image. All nodes that are written into the image should override this method. - virtual DWORD GetSize() - { -#if defined(_MSC_VER) //UNREACHABLE doesn't work in GCC, when the method has a non-void return - UNREACHABLE(); -#else - _ASSERTE(!"Unreachable"); - return 0; -#endif - } - - // Alignment for this node. - virtual UINT GetAlignment() - { - return 1; - } - - // Returns the type of the ZapNode. All nodes should override this method. - virtual ZapNodeType GetType() - { - return ZapNodeType_Unknown; - } - - // Assign RVA to this node. dwPos is current RVA, returns updated current RVA. - virtual DWORD ComputeRVA(ZapWriter * pZapWriter, DWORD dwPos); - - // All nodes that are written into the image should override this method. The implementation should write exactly GetSize() bytes - // using ZapWriter::Write method - virtual void Save(ZapWriter * pZapWriter) - { - UNREACHABLE(); - } - - // Returns the RVA of the node. Valid only after ComputeRVA phase - DWORD GetRVA() - { - _ASSERTE(m_RVA != 0 && m_RVA != (DWORD)-1); - return m_RVA; - } - - // Returns whether the node was placed into a virtual section - BOOL IsPlaced() - { - return m_RVA != 0; - } -}; - -//--------------------------------------------------------------------------------------- -// Virtual section of PE image. -class ZapVirtualSection : public ZapNode -{ - friend class ZapWriter; - - DWORD m_dwAlignment; - - SArray m_Nodes; - - // State initialized once the section is placed - DWORD m_dwSize; - - DWORD m_dwSectionType; - - BYTE m_defaultFill; - - ZapVirtualSection(DWORD dwAlignment) - : m_dwAlignment(dwAlignment) - { - } - -public: - virtual DWORD GetSize() - { - return m_dwSize; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_VirtualSection; - } - - DWORD GetSectionType() - { - return m_dwSectionType; - } - - void SetSectionType(DWORD dwSectionType) - { - _ASSERTE((dwSectionType & IBCTypeReservedFlag) != 0 || !"IBCType flag is not specified"); - _ASSERTE((dwSectionType & RangeTypeReservedFlag) != 0 || !"RangeType flag is not specified"); - _ASSERTE((dwSectionType & VirtualSectionTypeReservedFlag) != 0 || !"VirtualSectionType flag is not specified"); - _ASSERTE((dwSectionType & VirtualSectionTypeReservedFlag) < CORCOMPILE_SECTION_TYPE_COUNT || !"Invalid VirtualSectionType flag"); - m_dwSectionType = dwSectionType; - } - - void SetDefaultFill(BYTE fill) - { - m_defaultFill = fill; - } - - void Place(ZapNode * pNode) - { - _ASSERTE(!pNode->IsPlaced()); - m_Nodes.Append(pNode); - pNode->SetRVA((DWORD)-1); - } - - COUNT_T GetNodeCount() - { - return m_Nodes.GetCount(); - } - - ZapNode * GetNode(COUNT_T iNode) - { - return m_Nodes[iNode]; - } -}; - -//--------------------------------------------------------------------------------------- -// The named physical section of the PE Image. It contains one or more virtual sections. -class ZapPhysicalSection : public ZapNode -{ - friend class ZapWriter; - - SArray m_Sections; - - LPCSTR m_pszName; - DWORD m_dwCharacteristics; - - // Number of zero filled sections (zero filled sections are always last in m_Sections array) - COUNT_T m_nBssSections; - - // State initialized once the section is placed - DWORD m_dwSize; - DWORD m_dwFilePos; - DWORD m_dwSizeOfRawData; - - ZapPhysicalSection(LPCSTR pszName, DWORD dwCharacteristics) - : m_pszName(pszName), - m_dwCharacteristics(dwCharacteristics) - { - } - -public: - ~ZapPhysicalSection() - { - for (COUNT_T iVirtualSection = 0; iVirtualSection < m_Sections.GetCount(); iVirtualSection++) - { - ZapVirtualSection * pVirtualSection = m_Sections[iVirtualSection]; - pVirtualSection->~ZapVirtualSection(); - } - } - - virtual DWORD GetSize() - { - return m_dwSize; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_PhysicalSection; - } - - DWORD GetFilePos() - { - _ASSERTE(m_dwFilePos != 0); - return m_dwFilePos; - } - - COUNT_T GetVirtualSectionCount() - { - return m_Sections.GetCount(); - } - - ZapVirtualSection * GetVirtualSection(COUNT_T iSection) - { - return m_Sections[iSection]; - } - -}; - -//--------------------------------------------------------------------------------------- -// -// The ZapWriter -// -// Notice that ZapWriter implements IStream that can be passed to APIs that write to stream -// -// The main API in a ZapWriter is (not suprisingly) the code:ZapWriter.Write method. -// -// Relocations are handled by a higher level object, code:ZapImage, which knows about all the sections of a -// ngen image and how to do relections. Every ZapWriter has an associated ZapImage which you get to by -// calling code:ZapImage.GetImage. -// -class ZapWriter : public IStream -{ - ZapHeap * m_pHeap; - - SArray m_Sections; - - ZapNode * m_DirectoryEntries[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; - DWORD m_dwTimeDateStamp; - ULONGLONG m_BaseAddress; - ULONGLONG m_SizeOfStackReserve; - ULONGLONG m_SizeOfStackCommit; - USHORT m_Subsystem; - USHORT m_DllCharacteristics; - BOOL m_isDll; - DWORD m_FileAlignment; - - // Current state of the writer for debug checks - INDEBUG(BOOL m_fSaving;) - - DWORD m_dwCurrentRVA; - BOOL m_fWritingRelocs; // Set to true once we start reloc sections at the end of the file - - void SaveContent(); - - DWORD GetSizeOfNTHeaders(); - void SaveHeaders(); - - // Simple buffered writer - void InitializeWriter(IStream * pStream); - - IStream * m_pStream; - PBYTE m_pBuffer; - ULONG m_nBufferPos; - INDEBUG(DWORD m_dwWriterFilePos;) - - // - // NT Headers - // - - BOOL Is64Bit() - { -#ifdef TARGET_64BIT - return TRUE; -#else // !TARGET_64BIT - return FALSE; -#endif // !TARGET_64BIT - } - - USHORT GetMachine() - { - return IMAGE_FILE_MACHINE_NATIVE_NI; - } - - void SaveDosHeader(); - void SaveSignature(); - void SaveFileHeader(); - void SaveOptionalHeader(); - void SaveSections(); - - // IStream support - the only actually implemented method is IStream::Write - - // IUnknown methods - STDMETHODIMP_(ULONG) AddRef() - { - return 1; - } - - STDMETHODIMP_(ULONG) Release() - { - return 1; - } - - STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv) - { - HRESULT hr = S_OK; - if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IStream)) { - *ppv = static_cast(this); - } - else { - *ppv = NULL; - hr = E_NOINTERFACE; - } - return hr; - } - - // ISequentialStream methods: - STDMETHODIMP Read(void *pv, ULONG cb, ULONG *pcbRead) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Write(void const *pv, ULONG cb, ULONG *pcbWritten); - - // IStream methods: - STDMETHODIMP Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) - { - // IMetaDataEmit::SaveToStream calls Seek(0) but ignores the returned error - //_ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP SetSize(ULARGE_INTEGER libNewSize) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Commit(DWORD grfCommitFlags) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Revert() - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Stat(STATSTG *pstatstg, DWORD grfStatFlag) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Clone(IStream **ppIStream) - { - _ASSERTE(false); - return E_NOTIMPL; - } - -public: - ZapWriter(); - ~ZapWriter(); - - void Initialize(); - - // Create new section in the PE file. The sections will be saved in the order they are created. - ZapPhysicalSection * NewPhysicalSection(LPCSTR pszName, DWORD dwCharacteristics) - { - _ASSERTE(!IsSaving()); - ZapPhysicalSection * pSection = new (GetHeap()) ZapPhysicalSection(pszName, dwCharacteristics); - m_Sections.Append(pSection); - return pSection; - } - - // Create new virtual section within the physical section. The sections will be saved in the order they are created. - // The default virtual section alignment is 16. - ZapVirtualSection * NewVirtualSection(ZapPhysicalSection * pPhysicalSection, DWORD dwAlignment = 16, ZapVirtualSection * pInsertAfter = NULL) - { - _ASSERTE(!IsSaving()); - ZapVirtualSection * pSection = new (GetHeap()) ZapVirtualSection(dwAlignment); - if (pInsertAfter != NULL) - { - // pInsertAfter is workaround to get decent layout with the current scheme of virtual sections. It should not be necessary - // once we have better layout algorithms in place. - for (COUNT_T iSection = 0; iSection < pPhysicalSection->m_Sections.GetCount(); iSection++) - { - if (pPhysicalSection->m_Sections[iSection] == pInsertAfter) - { - pPhysicalSection->m_Sections.Insert(pPhysicalSection->m_Sections+(iSection+1)); - pPhysicalSection->m_Sections[iSection+1] = pSection; - return pSection; - } - } - _ASSERTE(false); - } - - pPhysicalSection->m_Sections.Append(pSection); - return pSection; - } - - void MarkBssSection(ZapPhysicalSection * pPhysicalSection, ZapVirtualSection * pSection) - { - _ASSERTE(!IsSaving()); - _ASSERTE(pPhysicalSection->m_Sections[pPhysicalSection->m_Sections.GetCount() - 1] == pSection); - pPhysicalSection->m_nBssSections++; - } - - void Append(ZapVirtualSection * pVirtualSection, ZapNode * pNode) - { - _ASSERTE(!IsSaving()); - pVirtualSection->m_Nodes.Append(pNode); - } - - // Set the directory entry in the image to match the given ZapNode - void SetDirectoryEntry(DWORD entry, ZapNode * pNode) - { - _ASSERTE(!IsSaving()); - _ASSERTE(entry < IMAGE_NUMBEROF_DIRECTORY_ENTRIES); - _ASSERTE(m_DirectoryEntries[entry] == NULL); - m_DirectoryEntries[entry] = pNode; - } - - // Set the timedate stamp of the image - void SetTimeDateStamp(DWORD dwTimeDateStamp) - { - _ASSERTE(!IsSaving()); - m_dwTimeDateStamp = dwTimeDateStamp; - } - - // Set the base address of the image - void SetBaseAddress(ULONGLONG baseAddress) - { - _ASSERTE(!IsSaving()); - m_BaseAddress = baseAddress; - } - - ULONGLONG GetBaseAddress() - { - _ASSERTE(m_BaseAddress != 0); - return m_BaseAddress; - } - - void SetSizeOfStackReserve(ULONGLONG sizeOfStackReserve) - { - _ASSERTE(!IsSaving()); - m_SizeOfStackReserve = sizeOfStackReserve; - } - - void SetSizeOfStackCommit(ULONGLONG sizeOfStackCommit) - { - _ASSERTE(!IsSaving()); - m_SizeOfStackCommit = sizeOfStackCommit; - } - - void SetSubsystem(USHORT subsystem) - { - _ASSERTE(!IsSaving()); - m_Subsystem = subsystem; - } - - void SetDllCharacteristics(USHORT dllCharacteristics) - { - _ASSERTE(!IsSaving()); - m_DllCharacteristics = dllCharacteristics; - } - - void SetIsDll(BOOL isDLL) - { - m_isDll = isDLL; - } - - void SetFileAlignment(DWORD fileAlignment) - { - m_FileAlignment = fileAlignment; - } - - // Compute RVAs for everything in the file - void ComputeRVAs(); - - // Save the content into stream - void Save(IStream * pStream); - - // Get the heap. The lifetime of this heap is same as the lifetime of the ZapWriter. All ZapNodes should - // be allocated from this heap. - ZapHeap * GetHeap() - { - return m_pHeap; - } - - COUNT_T GetPhysicalSectionCount() - { - return m_Sections.GetCount(); - } - - ZapPhysicalSection * GetPhysicalSection(COUNT_T iSection) - { - return m_Sections[iSection]; - } - -#ifdef _DEBUG - // Certain methods can be called only during the save phase - BOOL IsSaving() - { - return m_fSaving; - } -#endif - - DWORD GetCurrentRVA() - { - _ASSERTE(IsSaving()); - return m_dwCurrentRVA; - } - - - // This is the main entrypoint used to write the image. Every implementation of ZapNode::Save will call this method. - void Write(PVOID p, DWORD dwSize); - - // Writes padding - void WritePad(DWORD size, BYTE fill = 0); - - // Flush any buffered data - void FlushWriter(); - - BOOL IsWritingRelocs() - { - return m_fWritingRelocs; - } - - void SetWritingRelocs() - { - m_fWritingRelocs = TRUE; - } - - // Convenience helper to initialize IMAGE_DATA_DIRECTORY - static void SetDirectoryData(IMAGE_DATA_DIRECTORY * pDir, ZapNode * pZapNode); -}; - -//--------------------------------------------------------------------------------------- -// ZapBlob -// -// Generic node for unstructured sequence of bytes. -// Includes SHash support (ZapBlob::SHashTraits) -// -class ZapBlob : public ZapNode -{ - DWORD m_cbSize; - -protected: - ZapBlob(SIZE_T cbSize) - : m_cbSize((DWORD)cbSize) - { - if (cbSize > ZAPWRITER_MAX_SIZE) - ThrowHR(COR_E_OVERFLOW); - } - -public: - class SHashKey - { - PBYTE m_pData; - SIZE_T m_cbSize; - - public: - SHashKey(PVOID pData, SIZE_T cbSize) - : m_pData((PBYTE)pData), m_cbSize(cbSize) - { - } - - PBYTE GetData() const - { - return m_pData; - } - - SIZE_T GetBlobSize() const - { - return m_cbSize; - } - }; - - class SHashTraits : public DefaultSHashTraits - { - public: - typedef const ZapBlob::SHashKey key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return key_t(e->GetData(), e->GetBlobSize()); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - if (k1.GetBlobSize() != k2.GetBlobSize()) - return FALSE; - return memcmp(k1.GetData(), k2.GetData(), k1.GetBlobSize()) == 0; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - count_t hash = 5381 + (count_t)(k.GetBlobSize() << 7); - - PBYTE pbData = k.GetData(); - PBYTE pbDataEnd = pbData + k.GetBlobSize(); - - for (/**/ ; pbData < pbDataEnd; pbData++) - { - hash = ((hash << 5) + hash) ^ *pbData; - } - return hash; - } - }; - - virtual PBYTE GetData() - { - return (PBYTE)(this + 1); - } - - // Used to shrink the size of the blob - void AdjustBlobSize(SIZE_T cbSize) - { - _ASSERTE(cbSize <= m_cbSize); - _ASSERTE(cbSize != 0); - m_cbSize = (DWORD)cbSize; - } - - // Raw size of the blob - DWORD GetBlobSize() - { - return m_cbSize; - } - - virtual DWORD GetSize() - { - return m_cbSize; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_Blob; - } - - virtual void Save(ZapWriter * pZapWriter); - - // Create new zap blob node. The node *does* own copy of the memory. - static ZapBlob * NewBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize); - - // Create new aligned zap blob node. - static ZapBlob * NewAlignedBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, SIZE_T cbAlignment); -}; - -class ZapBlobPtr : public ZapBlob -{ - PBYTE m_pData; - -public: - ZapBlobPtr(PVOID pData, SIZE_T cbSize) - : ZapBlob(cbSize), m_pData((PBYTE)pData) - { - } - - virtual PBYTE GetData() - { - return m_pData; - } -}; - -class ZapDummyNode : public ZapNode -{ - DWORD m_cbSize; - -public: - ZapDummyNode(DWORD cbSize) - : m_cbSize(cbSize) - { - } - - virtual DWORD GetSize() - { - return m_cbSize; - } -}; - -#endif // __ZAPWRITER_H__ From 9370dc6a44aecaf44c0c95c63dba628198c0e6e3 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 17 Aug 2021 15:24:37 -0700 Subject: [PATCH 3/9] Delete v3binder_crossgen target --- src/coreclr/binder/CMakeLists.txt | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/coreclr/binder/CMakeLists.txt b/src/coreclr/binder/CMakeLists.txt index f04c647f88f4b6..537791412fd84a 100644 --- a/src/coreclr/binder/CMakeLists.txt +++ b/src/coreclr/binder/CMakeLists.txt @@ -61,21 +61,11 @@ set(BINDER_HEADERS inc/contextentry.hpp ) -set(BINDER_CROSSGEN_SOURCES - ${BINDER_COMMON_SOURCES} -) - -set(BINDER_CROSSGEN_HEADERS - ${BINDER_COMMON_HEADERS} -) - if (CLR_CMAKE_TARGET_WIN32) list(APPEND BINDER_SOURCES ${BINDER_HEADERS}) - list(APPEND BINDER_CROSSGEN_SOURCES ${BINDER_CROSSGEN_HEADERS}) endif(CLR_CMAKE_TARGET_WIN32) convert_to_absolute_path(BINDER_SOURCES ${BINDER_SOURCES}) -convert_to_absolute_path(BINDER_CROSSGEN_SOURCES ${BINDER_CROSSGEN_SOURCES}) add_library_clr(v3binder_obj OBJECT @@ -84,11 +74,3 @@ add_library_clr(v3binder_obj add_dependencies(v3binder_obj eventing_headers) add_library(v3binder INTERFACE) target_sources(v3binder INTERFACE $) - -add_library_clr(v3binder_crossgen - STATIC - ${BINDER_CROSSGEN_SOURCES} -) -add_dependencies(v3binder_crossgen eventing_headers) -set_target_properties(v3binder_crossgen PROPERTIES CROSSGEN_COMPONENT TRUE) - From bbaee26cb3213b70c029d5ae65cd776bb7200f17 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 17 Aug 2021 15:25:17 -0700 Subject: [PATCH 4/9] Delete mdcompiler_crossgen target --- src/coreclr/md/compiler/CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/coreclr/md/compiler/CMakeLists.txt b/src/coreclr/md/compiler/CMakeLists.txt index a2d3a5776c0b49..3ef387534a476d 100644 --- a/src/coreclr/md/compiler/CMakeLists.txt +++ b/src/coreclr/md/compiler/CMakeLists.txt @@ -76,10 +76,6 @@ add_library_clr(mdcompiler-dbi ${MDCOMPILER_SOURCES}) set_target_properties(mdcompiler-dbi PROPERTIES DBI_COMPONENT TRUE) target_precompile_headers(mdcompiler-dbi PRIVATE stdafx.h) -add_library_clr(mdcompiler_crossgen ${MDCOMPILER_SOURCES}) -set_target_properties(mdcompiler_crossgen PROPERTIES CROSSGEN_COMPONENT TRUE) -target_precompile_headers(mdcompiler_crossgen PRIVATE stdafx.h) - add_library_clr(mdcompiler_ppdb ${MDCOMPILER_SOURCES}) target_compile_definitions(mdcompiler_ppdb PRIVATE FEATURE_METADATA_EMIT_ALL FEATURE_METADATA_EMIT_PORTABLE_PDB) target_precompile_headers(mdcompiler_ppdb PRIVATE stdafx.h) From 2a8770dc2f6bd168e1b51a72705115cf0b7c7e86 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 17 Aug 2021 15:25:49 -0700 Subject: [PATCH 5/9] Delete mdhotdata_crossgen target --- src/coreclr/md/hotdata/CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/coreclr/md/hotdata/CMakeLists.txt b/src/coreclr/md/hotdata/CMakeLists.txt index 7f8ba752c4bf5e..37bdc0bc58807a 100644 --- a/src/coreclr/md/hotdata/CMakeLists.txt +++ b/src/coreclr/md/hotdata/CMakeLists.txt @@ -38,10 +38,6 @@ target_precompile_headers(mdhotdata_full_obj PRIVATE external.h) add_library(mdhotdata_full INTERFACE) target_sources(mdhotdata_full INTERFACE $) -add_library_clr(mdhotdata_crossgen ${MDHOTDATA_SOURCES}) -set_target_properties(mdhotdata_crossgen PROPERTIES CROSSGEN_COMPONENT TRUE) -target_precompile_headers(mdhotdata_crossgen PRIVATE external.h) - if(CLR_CMAKE_HOST_WIN32) add_library_clr(mdhotdata-staticcrt ${MDHOTDATA_SOURCES}) target_precompile_headers(mdhotdata-staticcrt PRIVATE external.h) From 66a44f8b516fc9af0e55fa212272fea78227be18 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 17 Aug 2021 15:26:34 -0700 Subject: [PATCH 6/9] Delete gcinfo_crossgen target --- src/coreclr/gcinfo/CMakeLists.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/coreclr/gcinfo/CMakeLists.txt b/src/coreclr/gcinfo/CMakeLists.txt index bfddaee4b700af..96319fd98b4252 100644 --- a/src/coreclr/gcinfo/CMakeLists.txt +++ b/src/coreclr/gcinfo/CMakeLists.txt @@ -32,13 +32,6 @@ add_library_clr(gcinfo_obj add_library(gcinfo INTERFACE) target_sources(gcinfo INTERFACE $) -add_library_clr(gcinfo_crossgen - STATIC - ${GCINFO_SOURCES} -) - -set_target_properties(gcinfo_crossgen PROPERTIES CROSSGEN_COMPONENT TRUE) - install (FILES gcinfoencoder.cpp DESTINATION gcinfo) From cd25bf89226e67268e7945e18317232c43e1622d Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 17 Aug 2021 15:27:52 -0700 Subject: [PATCH 7/9] Delete crossgen target for crossgen1 and the folder as well. --- src/coreclr/tools/crossgen/CMakeLists.txt | 83 -- src/coreclr/tools/crossgen/Native.rc | 6 - src/coreclr/tools/crossgen/compare.bat | 168 ---- src/coreclr/tools/crossgen/crossgen.cpp | 949 ---------------------- 4 files changed, 1206 deletions(-) delete mode 100644 src/coreclr/tools/crossgen/CMakeLists.txt delete mode 100644 src/coreclr/tools/crossgen/Native.rc delete mode 100644 src/coreclr/tools/crossgen/compare.bat delete mode 100644 src/coreclr/tools/crossgen/crossgen.cpp diff --git a/src/coreclr/tools/crossgen/CMakeLists.txt b/src/coreclr/tools/crossgen/CMakeLists.txt deleted file mode 100644 index 6b998ebb9e1ad1..00000000000000 --- a/src/coreclr/tools/crossgen/CMakeLists.txt +++ /dev/null @@ -1,83 +0,0 @@ -project(crossgen) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) -include_directories(../util) -include_directories(../../pal/prebuilt/corerror) - -set(crossgen_SOURCES crossgen.cpp ../util/consoleargs.cpp) -if(CLR_CMAKE_TARGET_WIN32) - list(APPEND crossgen_SOURCES ../util/consoleargs.h) - set(crossgen_RESOURCES Native.rc) -endif() - -if(CLR_CMAKE_HOST_WIN32) - add_definitions(-D_CRT_NON_CONFORMING_WCSTOK) -endif() - -if(CLR_CMAKE_HOST_UNIX) - add_definitions(-DNO_NGENPDB) -endif(CLR_CMAKE_HOST_UNIX) - -add_definitions(-DFX_VER_INTERNALNAME_STR=crossgen.exe) - -add_executable_clr(crossgen - ${crossgen_SOURCES} - ${crossgen_RESOURCES} -) -set_target_properties(crossgen PROPERTIES CROSSGEN_COMPONENT TRUE) - -if(FEATURE_MERGE_JIT_AND_ENGINE) - set(CLRJIT_CROSSGEN clrjit_crossgen) -endif(FEATURE_MERGE_JIT_AND_ENGINE) - -if(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD OR CLR_CMAKE_HOST_SUNOS) - # The following linked options can be inserted into the linker libraries list to - # ensure proper resolving of circular references between a subset of the libraries. - set(START_LIBRARY_GROUP -Wl,--start-group) - set(END_LIBRARY_GROUP -Wl,--end-group) -endif(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD OR CLR_CMAKE_HOST_SUNOS) - -target_link_libraries(crossgen - ${START_LIBRARY_GROUP} # Start group of libraries that have circular references - cee_crossgen - v3binder_crossgen - mdcompiler_crossgen - mdruntime_crossgen - mdruntimerw_crossgen - mdhotdata_crossgen - ${END_LIBRARY_GROUP} # End group of libraries that have circular references - corguids - ${CLRJIT_CROSSGEN} - gcinfo_crossgen - corzap_crossgen - corelib_crossgen - utilcode_crossgen -) - -if(CLR_CMAKE_HOST_UNIX) - target_link_libraries(crossgen - mscorrc - palrt - coreclrpal - ) -else() - target_link_libraries(crossgen - advapi32 - ole32 - oleaut32 - uuid - user32 - version - shlwapi - bcrypt - ${STATIC_MT_CRT_LIB} - ${STATIC_MT_VCRT_LIB} - ) - -endif(CLR_CMAKE_HOST_UNIX) - -add_subdirectory(../../zap ../../zap) -add_subdirectory(../../vm/crossgen ../../vm/crossgen) - -# add the install targets -install_clr(TARGETS crossgen DESTINATIONS . sharedFramework COMPONENT runtime) diff --git a/src/coreclr/tools/crossgen/Native.rc b/src/coreclr/tools/crossgen/Native.rc deleted file mode 100644 index c90ad0d19ccf89..00000000000000 --- a/src/coreclr/tools/crossgen/Native.rc +++ /dev/null @@ -1,6 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#define FX_VER_FILEDESCRIPTION_STR "Microsoft Common Language Runtime native cross compiler\0" - -#include "..\..\dlls\mscorrc\mscorrc.rc" diff --git a/src/coreclr/tools/crossgen/compare.bat b/src/coreclr/tools/crossgen/compare.bat deleted file mode 100644 index 436876a02a76c1..00000000000000 --- a/src/coreclr/tools/crossgen/compare.bat +++ /dev/null @@ -1,168 +0,0 @@ -::mscorlib -::System -::System.Core -::System.Xml -::System.Configuration -::System.Drawing -::System.Data -::System.Windows.Forms -::System.Runtime.Remoting -::System.Serviceprocess -::System.Management -::Accessibility -::Microsoft.VisualBasic -::System.DirectoryServices -::System.Transactions -::System.Web.Services -::CustomMarshalers -::System.Configuration.Install -::System.Xaml -::WindowsBase -::System.Net.Http -::System.Xml.Linq -::System.Runtime.WindowsRuntime -::System.Runtime.WindowsRuntime.UI.Xaml -::System.Runtime.Serialization -::System.ServiceModel -::PresentationCore -::PresentationFramework -::System.EnterpriseServices -::System.Collections.Concurrent -::System.Collections -::System.ComponentModel.Annotations -::System.ComponentModel -::System.ComponentModel.EventBasedAsync -::System.Diagnostics.Contracts -::System.Diagnostics.Debug -::System.Diagnostics.Tools -::System.Diagnostics.Tracing -::System.Dynamic.Runtime -::System.Globalization -::System.IO -::System.Linq -::System.Linq.Expressions -::System.Linq.Parallel -::System.Linq.Queryable -::System.Net.Http.Rtc -::System.Net.NetworkInformation -::System.Net.Primitives -::System.Net.Requests -::System.ObjectModel -::System.Reflection -::System.Reflection.Emit -::System.Reflection.Emit.ILGeneration -::System.Reflection.Emit.Lightweight -::System.Reflection.Extensions -::System.Reflection.Primitives -::System.Resources.ResourceManager -::System.Runtime -::System.Runtime.Extensions -::System.Runtime.InteropServices -::System.Runtime.InteropServices.WindowsRuntime -::System.Runtime.Numerics -::System.Runtime.Serialization.Json -::System.Runtime.Serialization.Primitives -::System.Runtime.Serialization.Xml -::System.Security.Principal -::System.ServiceModel.Duplex -::System.ServiceModel.Http -::System.ServiceModel.NetTcp -::System.ServiceModel.Primitives -::System.ServiceModel.Security -::System.Text.Encoding -::System.Text.Encoding.Extensions -::System.Text.RegularExpressions -::System.Threading -::System.Threading.Tasks -::System.Threading.Tasks.Parallel -::System.Windows -::System.Xml.ReaderWriter -::System.Xml.XDocument -::System.Xml.XmlSerializer -::END_OF_LIST - -@echo off - -rem -rem This script compares ngen and crossgen output for framework assemblies -rem - -SETLOCAL ENABLEDELAYEDEXPANSION - -set BITNESS= -IF /I "%_BuildArch%" == "amd64" set BITNESS=64 -set FRAMEWORKDIR=%SYSTEMROOT%\Microsoft.NET\Framework%BITNESS%\%COMPlus_Version% -IF "%BITNESS%" == "" set BITNESS=32 - -set NATIVEIMAGEPATH=%FRAMEWORKDIR%\assembly\NativeImages_%COMPlus_Version%_%BITNESS% - -rem rmdir /S /Q %NATIVEIMAGEPATH% -rem %FRAMEWORKDIR%\ngen install mscorlib -rem %FRAMEWORKDIR%\ngen update - -%FRAMEWORKDIR%\gacutil /if %_NTTREE%\System.Runtime.WindowsRuntime.dll -%FRAMEWORKDIR%\gacutil /if %_NTTREE%\System.Runtime.WindowsRuntime.UI.Xaml.dll - -set ILIMAGEPATH=%_NTTREE%\il -rmdir /S /Q %ILIMAGEPATH% -if not exist %ILIMAGEPATH% mkdir %ILIMAGEPATH% - -rem Collect all files from the GAC into ILIMAGEPATH directory to guaranteed that we get the exact same IL images -rem between ngen and crossgen. It is important on non-x86 builds because of non-x86 layouts pull files from x86 build. -forfiles /P %FRAMEWORKDIR%\assembly\GAC_%BITNESS% /M *.dll /S /C "cmd /c copy @path %ILIMAGEPATH%\@file > nul" -forfiles /P %FRAMEWORKDIR%\assembly\GAC_MSIL /M *.dll /S /C "cmd /c copy @path %ILIMAGEPATH%\@file > nul" -rem clr.dll and clrjit.dll are required for timestamps -copy %FRAMEWORKDIR%\clr.dll %ILIMAGEPATH%\clr.dll >nul -copy %FRAMEWORKDIR%\clrjit.dll %ILIMAGEPATH%\clrjit.dll >nul - -set CROSSGENIMAGEPATH=%_NTTREE%\ni -rmdir /S /Q %CROSSGENIMAGEPATH% -if not exist %CROSSGENIMAGEPATH% mkdir %CROSSGENIMAGEPATH% - -set SELF=%~fd0 -set FAILED= - -for /f "eol=; usebackq tokens=1,2,3* delims=,:" %%I in ("%SELF%") DO ( - if "%%I"=="END_OF_LIST" goto LDone - call :ProcessFile %%I - if "!FAILED!"=="1" goto LFailed -) - -:LDone -echo DONE -exit /B 0 - -:LFailed -echo FAILED -exit /B 1 - -:ProcessFile - -set FILEPATH= -call :ProbeFile %ILIMAGEPATH%\%1.dll - -if "%FILEPATH%" == "" ( echo File not found: %1 & goto LError ) - -echo. -echo ========= COMPILE and COMPARE %1 ========== -echo ngen install /nodependencies %FILEPATH% -ngen install /nodependencies %FILEPATH% -echo. -echo %_NTTREE%\crossgen /platform_assemblies_paths %ILIMAGEPATH%;%CROSSGENIMAGEPATH% /in %FILEPATH% /out %CROSSGENIMAGEPATH%\%1.ni.dll -%_NTTREE%\crossgen /platform_assemblies_paths %ILIMAGEPATH%;%CROSSGENIMAGEPATH% /in %FILEPATH% /out %CROSSGENIMAGEPATH%\%1.ni.dll -IF NOT "%ERRORLEVEL%"=="0" set FAILED=1 -echo. -forfiles /P %NATIVEIMAGEPATH% /M %1.ni.dll /S /C "cmd /c echo Compare: @path & fc /B @path %CROSSGENIMAGEPATH%\%1.ni.dll > %CROSSGENIMAGEPATH%\diff.txt & IF NOT ERRORLEVEL 1 del %CROSSGENIMAGEPATH%\diff.txt" -IF not exist %CROSSGENIMAGEPATH%\diff.txt goto LExit -echo ----- DIFFERENT ----- -:LError -set FAILED=1 -goto LExit - -:ProbeFile -if NOT "%FILEPATH%" == "" goto LExit -if NOT exist "%1" goto LExit -set FILEPATH=%1 -goto LExit - -:LExit diff --git a/src/coreclr/tools/crossgen/crossgen.cpp b/src/coreclr/tools/crossgen/crossgen.cpp deleted file mode 100644 index 61faeb761a6bb6..00000000000000 --- a/src/coreclr/tools/crossgen/crossgen.cpp +++ /dev/null @@ -1,949 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// -// TO DO: we currently use raw printf() for output. Maybe we need to pick up something like ngen's Output() handling -// to handle multiple code pages, etc, better. - -#include -#include -#include - -#include -#include -#include - -#include "palclr.h" - -#include -#include "ex.h" - -#include "coregen.h" -#include "consoleargs.h" - -// Return values from wmain() in case of error -enum ReturnValues -{ - FAILURE_RESULT = 1, - CLR_INIT_ERROR = -2, - ASSEMBLY_NOT_FOUND = -3, - INVALID_ARGUMENTS = -4 -}; - -#define NumItems(s) (sizeof(s) / sizeof(s[0])) - -STDAPI CreatePDBWorker(LPCWSTR pwzAssemblyPath, LPCWSTR pwzPlatformAssembliesPaths, LPCWSTR pwzTrustedPlatformAssemblies, LPCWSTR pwzPlatformResourceRoots, LPCWSTR pwzAppPaths, LPCWSTR pwzAppNiPaths, LPCWSTR pwzPdbPath, BOOL fGeneratePDBLinesInfo, LPCWSTR pwzManagedPdbSearchPath, LPCWSTR pwzDiasymreaderPath); -STDAPI NGenWorker(LPCWSTR pwzFilename, DWORD dwFlags, LPCWSTR pwzPlatformAssembliesPaths, LPCWSTR pwzTrustedPlatformAssemblies, LPCWSTR pwzPlatformResourceRoots, LPCWSTR pwzAppPaths, LPCWSTR pwzOutputFilename=NULL, SIZE_T customBaseAddress=0, ICorSvcLogger *pLogger = NULL, LPCWSTR pwszCLRJITPath = nullptr); -void SetSvcLogger(ICorSvcLogger *pCorSvcLogger); -void SetCoreLibPath(LPCWSTR wzSystemDirectory); - -/* --------------------------------------------------------------------------- * - * Console stuff - * --------------------------------------------------------------------------- */ - -void Output(LPCWSTR str) -{ - wprintf(W("%s"), str); -} - -void Outputf(LPCWSTR szFormat, ...) -{ - va_list args; - va_start(args, szFormat); - vfwprintf(stdout, szFormat, args); - va_end(args); -} - -void OutputErr(LPCWSTR str) -{ - fwprintf(stderr, W("%s"), str); -} - -void OutputErrf(LPCWSTR szFormat, ...) -{ - va_list args; - va_start(args, szFormat); - vfwprintf(stderr, szFormat, args); - va_end(args); -} - -void ErrorHR(HRESULT hr) -{ - OutputErrf(W("Error: failed to initialize CoreCLR: 0x%08x\n"), hr); -} - -void ErrorWin32(DWORD err) -{ - ErrorHR(HRESULT_FROM_WIN32(err)); -} - -// Some error messages are useless to callers, so make them generic, except in debug builds, where we want as much -// information as possible. - -#ifdef _DEBUG -#define ERROR_HR(msg,hr) Outputf(msg, hr) -#define ERROR_WIN32(msg,err) Outputf(msg, err) -#else // _DEBUG -#define ERROR_HR(msg,hr) ErrorHR(hr) -#define ERROR_WIN32(msg,err) ErrorWin32(err) -#endif // _DEBUG - - -void PrintLogoHelper() -{ - Output(W("Microsoft (R) CoreCLR Native Image ")); - Outputf(W("Generator - Version %S\n"), CLR_PRODUCT_VERSION); - Outputf(W("%S\n"), VER_LEGALCOPYRIGHT_LOGO_STR); - Output(W("\n")); -} - -void PrintUsageHelper() -{ - // Always print the logo when we print the usage, even if they've specified /nologo and we've parsed that already. - PrintLogoHelper(); - - Output( - W("Usage: crossgen [args] \n") - W("\n") - W(" /? or /help - Display this screen\n") - W(" /nologo - Prevents displaying the logo\n") - W(" /nowarnings - Prevents displaying warning messages\n") - W(" /silent - Do not display completion message\n") - W(" /verbose - Display verbose information\n") - W(" @response.rsp - Process command line arguments from specified\n") - W(" response file\n") - W(" /in - Specifies input filename (optional)\n") - W(" /out - Specifies output filename (optional)\n") - W(" /r - Specifies a trusted platform assembly reference\n") - W(" - Cannot be used with /p\n") - W(" /p - List of paths containing target platform assemblies\n") - // If /p, we will use it to build the TPA list and thus, - // TPA list cannot be explicitly specified. - W(" - Cannot be used with /r\n") - - W(" /Platform_Resource_Roots \n") - W(" - List of paths containing localized assembly directories\n") - W(" /App_Paths \n") - W(" - List of paths containing user-application assemblies and resources\n") -#ifndef NO_NGENPDB - W(" /App_Ni_Paths \n") - W(" - List of paths containing user-application native images\n") - W(" - Must be used with /CreatePDB switch\n") -#endif // NO_NGENPDB - W(" /MissingDependenciesOK\n") - W(" - Specifies that crossgen should attempt not to fail\n") - W(" if a dependency is missing.\n") -#if 0 - W(" /Tuning - Generate an instrumented image to collect\n") - W(" scenario traces, which can be used with ibcmerge.exe\n") -#endif -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) - W(" /JITPath \n") - W(" - Specifies the absolute file path to JIT compiler to be used.\n") -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) -#ifdef FEATURE_READYTORUN_COMPILER - W(" /ReadyToRun - Generate images resilient to the runtime and\n") - W(" dependency versions\n") - W(" /LargeVersionBubble - Generate image with a version bubble including all\n") - W(" input assemblies\n") - -#endif -#ifdef FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION - W(" /BaseAddress - Specifies base address to use for compilation.\n") -#endif -#ifndef NO_NGENPDB - W(" Debugging Parameters\n") - W(" /CreatePDB [/lines [] ]\n") - W(" When specifying /CreatePDB, the native image should be created\n") - W(" first, and should be the path to the NI.\n") - W(" /DiasymreaderPath \n") - W(" - Specifies the absolute file path to diasymreader.dll to be used.\n") -#elif defined(FEATURE_PERFMAP) - W(" Debugging Parameters\n") - W(" /CreatePerfMap \n") - W(" When specifying /CreatePerfMap, the native image should be created\n") - W(" first, and should be the path to the NI.\n") -#endif - ); -} - -class CrossgenLogger : public ICorSvcLogger -{ -public: - STDMETHODIMP_(ULONG) AddRef() {return E_NOTIMPL;} - STDMETHODIMP_(ULONG) Release() {return E_NOTIMPL;} - STDMETHODIMP QueryInterface(REFIID riid,void ** ppv) - { - if (ppv==0) - return E_POINTER; - - *ppv = NULL; - - if (IsEqualIID(riid, IID_ICorSvcLogger) || IsEqualIID(riid, IID_IUnknown)) - { - *ppv = this; - return S_OK; - } - else - { - return E_NOINTERFACE; - } - } - - HRESULT STDMETHODCALLTYPE Log( - /*[in] */CorSvcLogLevel logLevel, - /*[in] */BSTR message - ) - { - if (logLevel == LogLevel_Error) - OutputErr(message); - else if(logLevel != LogLevel_Warning || m_bEnableWarningLogging) - Output(message); - return S_OK; - } - - void SetWarningLogging(bool value) - { - m_bEnableWarningLogging = value; - } - - CrossgenLogger() : m_bEnableWarningLogging(true) { } - -private: - bool m_bEnableWarningLogging; -}; - -CrossgenLogger g_CrossgenLogger; - -// -// Tests whether szArg, the currently indexed argv matches the specified parameter name, szTestParamName. -// Specify szTestParamName without a switch. This method handles testing for - and / switches. -// -bool MatchParameter(LPCWSTR szArg, LPCWSTR szTestParamName) -{ - if (wcslen(szArg) == 0) - { - return false; - } - - if (szArg[0] != W('/') && szArg[0] != W('-')) - { - return false; - } - - return !_wcsicmp(szArg + 1, szTestParamName) || !_wcsicmp(szArg + 1, szTestParamName); -} - -// -// Returns true if pwzString ends with the string in pwzCandidate -// Ignores case -// -bool StringEndsWith(LPCWSTR pwzString, LPCWSTR pwzCandidate) -{ - size_t stringLength = wcslen(pwzString); - size_t candidateLength = wcslen(pwzCandidate); - - if (candidateLength > stringLength || stringLength == 0 || candidateLength == 0) - { - return false; - } - - LPCWSTR pwzStringEnd = pwzString + stringLength - candidateLength; - - return !_wcsicmp(pwzStringEnd, pwzCandidate); -} - -// -// When using the Phone binding model (TrustedPlatformAssemblies), automatically -// detect which path CoreLib.[ni.]dll lies in. -// -bool ComputeCoreLibPathFromTrustedPlatformAssemblies(SString& pwzCoreLibPath, LPCWSTR pwzTrustedPlatformAssemblies) -{ - LPWSTR wszTrustedPathCopy = new WCHAR[wcslen(pwzTrustedPlatformAssemblies) + 1]; - wcscpy_s(wszTrustedPathCopy, wcslen(pwzTrustedPlatformAssemblies) + 1, pwzTrustedPlatformAssemblies); - WCHAR *context; - LPWSTR wszSingleTrustedPath = wcstok_s(wszTrustedPathCopy, PATH_SEPARATOR_STR_W, &context); - - while (wszSingleTrustedPath != NULL) - { - size_t pathLength = wcslen(wszSingleTrustedPath); - // Strip off enclosing quotes, if present - if (wszSingleTrustedPath[0] == W('\"') && wszSingleTrustedPath[pathLength-1] == W('\"')) - { - wszSingleTrustedPath[pathLength-1] = '\0'; - wszSingleTrustedPath++; - } - - if (StringEndsWith(wszSingleTrustedPath, DIRECTORY_SEPARATOR_STR_W CoreLibName_IL_W) || - StringEndsWith(wszSingleTrustedPath, DIRECTORY_SEPARATOR_STR_W CoreLibName_NI_W)) - { - pwzCoreLibPath.Set(wszSingleTrustedPath); - SString::Iterator pwzSeparator = pwzCoreLibPath.End(); - bool retval = true; - - if (!SUCCEEDED(CopySystemDirectory(pwzCoreLibPath, pwzCoreLibPath))) - { - retval = false; - } - - delete [] wszTrustedPathCopy; - return retval; - } - - wszSingleTrustedPath = wcstok_s(NULL, PATH_SEPARATOR_STR_W, &context); - } - delete [] wszTrustedPathCopy; - - return false; -} - -// Given a path terminated with "\\" and a search mask, this function will add -// the enumerated files, corresponding to the search mask, from the path into -// the refTPAList. -void PopulateTPAList(SString path, LPCWSTR pwszMask, SString &refTPAList, bool fCreatePDB) -{ - _ASSERTE(path.GetCount() > 0); - ClrDirectoryEnumerator folderEnumerator(path.GetUnicode(), pwszMask); - - while (folderEnumerator.Next()) - { - // Got a valid enumeration handle and the data about the first file. - DWORD dwAttributes = folderEnumerator.GetFileAttributes(); - if ((!(dwAttributes & FILE_ATTRIBUTE_DIRECTORY)) && (!(dwAttributes & FILE_ATTRIBUTE_DEVICE))) - { - bool fAddDelimiter = (refTPAList.GetCount() > 0)?true:false; - bool fAddFileToTPAList = true; - LPCWSTR pwszFilename = folderEnumerator.GetFileName(); - - // No NIs are supported when creating NI images (other than NI of System.Private.CoreLib.dll). - if (!fCreatePDB) - { - // Only CoreLib's ni.dll should be in the TPAList for the compilation of non-CoreLib assemblies. - if (StringEndsWith((LPWSTR)pwszFilename, W(".ni.dll"))) - { - fAddFileToTPAList = false; - } - } - - if (fAddFileToTPAList) - { - if (fAddDelimiter) - { - // Add the path delimiter if we already have entries in the TPAList - refTPAList.Append(PATH_SEPARATOR_CHAR_W); - } - // Add the path to the TPAList - refTPAList.Append(path); - refTPAList.Append(pwszFilename); - } - } - } - } - -// Given a semi-colon delimited set of absolute folder paths (pwzPlatformAssembliesPaths), this function -// will enumerate all EXE/DLL modules in those folders and add them to the TPAList buffer (refTPAList). -void ComputeTPAListFromPlatformAssembliesPath(LPCWSTR pwzPlatformAssembliesPaths, SString &refTPAList, bool fCreatePDB) -{ - // We should have a valid pointer to the paths - _ASSERTE(pwzPlatformAssembliesPaths != NULL); - - SString ssPlatformAssembliesPath(pwzPlatformAssembliesPaths); - - // Platform Assemblies Path List is semi-colon delimited - if(ssPlatformAssembliesPath.GetCount() > 0) - { - SString::CIterator start = ssPlatformAssembliesPath.Begin(); - SString::CIterator itr = ssPlatformAssembliesPath.Begin(); - SString::CIterator end = ssPlatformAssembliesPath.End(); - SString qualifiedPath; - - while (itr != end) - { - start = itr; - BOOL found = ssPlatformAssembliesPath.Find(itr, PATH_SEPARATOR_CHAR_W); - if (!found) - { - itr = end; - } - - SString qualifiedPath(ssPlatformAssembliesPath,start,itr); - - if (found) - { - itr++; - } - - unsigned len = qualifiedPath.GetCount(); - - if (len > 0) - { - if (qualifiedPath[len-1]!=DIRECTORY_SEPARATOR_CHAR_W) - { - qualifiedPath.Append(DIRECTORY_SEPARATOR_CHAR_W); - } - - // Enumerate the EXE/DLL modules within this path and add them to the TPAList - EX_TRY - { - PopulateTPAList(qualifiedPath, W("*.exe"), refTPAList, fCreatePDB); - PopulateTPAList(qualifiedPath, W("*.dll"), refTPAList, fCreatePDB); - } - EX_CATCH - { - Outputf(W("Warning: Error enumerating files under %s.\n"), qualifiedPath.GetUnicode()); - } - EX_END_CATCH(SwallowAllExceptions); - } - } - } -} - -int _cdecl wmain(int argc, __in_ecount(argc) WCHAR **argv) -{ - ///////////////////////////////////////////////////////////////////////// - // - // Parse the arguments - // - bool fDisplayLogo = true; - DWORD dwFlags = 0; - LPCWSTR pwzFilename = NULL; - LPCWSTR pwzPlatformResourceRoots = nullptr; - LPCWSTR pwzTrustedPlatformAssemblies = nullptr; - LPCWSTR pwzAppPaths = nullptr; - LPCWSTR pwzAppNiPaths = nullptr; - LPCWSTR pwzPlatformAssembliesPaths = nullptr; - StackSString wzDirectoryToStorePDB; - bool fCreatePDB = false; - bool fGeneratePDBLinesInfo = false; - LPWSTR pwzSearchPathForManagedPDB = NULL; - LPCWSTR pwzOutputFilename = NULL; - LPCWSTR pwzPublicKeys = nullptr; - bool fLargeVersionBubbleSwitch = false; - SIZE_T baseAddress = 0; - -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) - LPCWSTR pwszCLRJITPath = nullptr; -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) - - LPCWSTR pwzDiasymreaderPath = nullptr; - - HRESULT hr; - -#ifndef TARGET_UNIX - // This is required to properly display Unicode characters - _setmode(_fileno(stdout), _O_U8TEXT); -#endif - - // Skip this executable path - argv++; - argc--; - - ConsoleArgs consoleArgs; - int argc2; - LPWSTR *argv2; - - SString ssTrustedPlatformAssemblies; - - if (argc == 0) - { - PrintUsageHelper(); - exit(INVALID_ARGUMENTS); - } - - if (!consoleArgs.ExpandResponseFiles(argc, argv, &argc2, &argv2)) - { - if (consoleArgs.ErrorMessage() != nullptr) - { - wprintf(consoleArgs.ErrorMessage()); - exit(FAILURE_RESULT); - } - } - - argc = argc2; - argv = argv2; - - // By default, Crossgen will generate readytorun images unless /FragileNonVersionable switch is specified - dwFlags |= NGENWORKER_FLAGS_READYTORUN; - - while (argc > 0) - { - if (MatchParameter(*argv, W("?")) - || MatchParameter(*argv, W("help"))) - { - PrintUsageHelper(); - exit(INVALID_ARGUMENTS); - } - else if (MatchParameter(*argv, W("nologo"))) - { - fDisplayLogo = false; - } - else if (MatchParameter(*argv, W("silent"))) - { - dwFlags |= NGENWORKER_FLAGS_SILENT; - } - else if (MatchParameter(*argv, W("verbose"))) - { - dwFlags |= NGENWORKER_FLAGS_VERBOSE; - } - else if (MatchParameter(*argv, W("nowarnings"))) - { - dwFlags |= NGENWORKER_FLAGS_SUPPRESS_WARNINGS; - } - else if (MatchParameter(*argv, W("Tuning"))) - { - dwFlags |= NGENWORKER_FLAGS_TUNING; - } - else if (MatchParameter(*argv, W("MissingDependenciesOK"))) - { - dwFlags |= NGENWORKER_FLAGS_MISSINGDEPENDENCIESOK; - } -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) - else if (MatchParameter(*argv, W("JITPath")) && (argc > 1)) - { - pwszCLRJITPath = argv[1]; - - // skip JIT Path - argv++; - argc--; - } -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) -#ifdef FEATURE_READYTORUN_COMPILER - else if (MatchParameter(*argv, W("ReadyToRun"))) - { - dwFlags |= NGENWORKER_FLAGS_READYTORUN; - } - else if (MatchParameter(*argv, W("FragileNonVersionable"))) - { - dwFlags &= ~NGENWORKER_FLAGS_READYTORUN; - } - else if (MatchParameter(*argv, W("LargeVersionBubble"))) - { - dwFlags |= NGENWORKER_FLAGS_LARGEVERSIONBUBBLE; - fLargeVersionBubbleSwitch = true; - } -#endif -#ifdef FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION - else if (MatchParameter(*argv, W("BaseAddress"))) - { - if (baseAddress != 0) - { - OutputErr(W("Cannot specify multiple base addresses.\n")); - exit(INVALID_ARGUMENTS); - } - baseAddress = (SIZE_T) _wcstoui64(argv[1], NULL, 0); - argv++; - argc--; - } -#endif - else if (MatchParameter(*argv, W("out"))) - { - if (pwzOutputFilename != NULL) - { - OutputErr(W("Cannot specify multiple output files.\n")); - exit(INVALID_ARGUMENTS); - } - pwzOutputFilename = argv[1]; - argv++; - argc--; - } - else if (MatchParameter(*argv, W("in"))) - { - if (pwzFilename != NULL) - { - OutputErr(W("Cannot specify multiple input files.\n")); - exit(INVALID_ARGUMENTS); - } - pwzFilename = argv[1]; - argv++; - argc--; - } - else if (MatchParameter(*argv, W("r")) && (argc > 1)) - { - if (!ssTrustedPlatformAssemblies.IsEmpty()) - { - // Add the path delimiter if we already have entries in the TPAList - ssTrustedPlatformAssemblies.Append(PATH_SEPARATOR_CHAR_W); - } - ssTrustedPlatformAssemblies.Append(argv[1]); - - // skip path list - argv++; - argc--; - } - else if (MatchParameter(*argv, W("Platform_Resource_Roots")) && (argc > 1)) - { - pwzPlatformResourceRoots = argv[1]; - - // skip path list - argv++; - argc--; - } - else if (MatchParameter(*argv, W("App_Paths")) && (argc > 1)) - { - pwzAppPaths = argv[1]; - - // skip User app path - argv++; - argc--; - } -#ifndef NO_NGENPDB - else if (MatchParameter(*argv, W("App_Ni_Paths")) && (argc > 1)) - { - pwzAppNiPaths = argv[1]; - - // skip User app path - argv++; - argc--; - } -#endif // NO_NGENPDB - // Note: Leaving "Platform_Assemblies_Paths" for backwards compatibility reasons. - else if ((MatchParameter(*argv, W("Platform_Assemblies_Paths")) || MatchParameter(*argv, W("p"))) && (argc > 1)) - { - pwzPlatformAssembliesPaths = argv[1]; - - // skip path list - argv++; - argc--; - } -#ifndef NO_NGENPDB - else if (MatchParameter(*argv, W("CreatePDB")) && (argc > 1)) - { - // syntax: /CreatePDB [/lines [] ] - - // Parse: /CreatePDB - fCreatePDB = true; - argv++; - argc--; - - // Clear any extra flags - using /CreatePDB fails if any of these are set. - dwFlags = dwFlags & ~NGENWORKER_FLAGS_READYTORUN; - - // Parse: - wzDirectoryToStorePDB.Set(argv[0]); - argv++; - argc--; - - // Ensure output dir ends in a backslash, or else diasymreader has issues - if (wzDirectoryToStorePDB[wzDirectoryToStorePDB.GetCount()-1] != DIRECTORY_SEPARATOR_CHAR_W) - { - wzDirectoryToStorePDB.Append(DIRECTORY_SEPARATOR_STR_W); - } - - if (argc == 0) - { - OutputErr(W("The /CreatePDB switch requires and .\n")); - exit(FAILURE_RESULT); - } - - // [/lines [] ] - if (MatchParameter(*argv, W("lines")) && (argc > 1)) - { - // Parse: /lines - fGeneratePDBLinesInfo = true; - argv++; - argc--; - - if (argc == 0) - { - OutputErr(W("The /CreatePDB switch requires and .\n")); - exit(FAILURE_RESULT); - } - - if (argc > 1) - { - // Parse: - pwzSearchPathForManagedPDB = argv[0]; - argv++; - argc--; - } - } - - // Undo last arg iteration, since we do it for all cases at the bottom of - // the loop - argv--; - argc++; - } - else if (MatchParameter(*argv, W("DiasymreaderPath")) && (argc > 1)) - { - pwzDiasymreaderPath = argv[1]; - - // skip diasymreader Path - argv++; - argc--; - } -#endif // NO_NGENPDB -#ifdef FEATURE_PERFMAP - else if (MatchParameter(*argv, W("CreatePerfMap")) && (argc > 1)) - { - // syntax: /CreatePerfMap - - // Parse: /CreatePerfMap - // NOTE: We use the same underlying PDB logic. - fCreatePDB = true; - argv++; - argc--; - - // Clear the /ready to run flag - /CreatePerfmap does not work with any other flags. - dwFlags = dwFlags & ~NGENWORKER_FLAGS_READYTORUN; - - // Parse: - wzDirectoryToStorePDB.Set(argv[0]); - argv++; - argc--; - - // Ensure output dir ends in a backslash - if (wzDirectoryToStorePDB[wcslen(wzDirectoryToStorePDB)-1] != DIRECTORY_SEPARATOR_CHAR_W) - { - wzDirectoryToStorePDB.Append(DIRECTORY_SEPARATOR_STR_W); - } - - if (argc == 0) - { - OutputErr(W("The /CreatePerfMap switch requires and .\n")); - exit(FAILURE_RESULT); - } - - // Undo last arg iteration, since we do it for all cases at the bottom of - // the loop - argv--; - argc++; - } -#endif // FEATURE_PERFMAP - else - { - if (argc == 1) - { -#if !defined(TARGET_UNIX) - // When not running on Mac or Linux, which can have forward-slash pathnames, we know - // a command switch here means an invalid argument. - if (*argv[0] == W('-') || *argv[0] == W('/')) - { - OutputErrf(W("Invalid parameter: %s\n"), *argv); - exit(INVALID_ARGUMENTS); - } -#endif //!TARGET_UNIX - // The last thing on the command line is an assembly name or path, and - // because we got this far is not an argument like /nologo. Because this - // code works on Mac, with forward-slash pathnames, we can't assume - // anything with a forward slash is an argument. So we just always - // assume the last thing on the command line must be an assembly name. - - if (pwzFilename != NULL) - { - OutputErr(W("Cannot use /In and specify an input file as the last argument.\n")); - exit(INVALID_ARGUMENTS); - } - - pwzFilename = *argv; - break; - } - else - { - OutputErrf(W("Invalid parameter: %s\n"), *argv); - exit(INVALID_ARGUMENTS); - } - } - - argv++; - argc--; - } - - if (pwzFilename == NULL) - { - OutputErr(W("You must specify an assembly to compile\n")); - exit(INVALID_ARGUMENTS); - } - - if (fCreatePDB && (dwFlags != 0)) - { - OutputErr(W("The /CreatePDB switch cannot be used with other switches, except /lines and the various path switches.\n")); - exit(FAILURE_RESULT); - } - - if (pwzAppNiPaths != nullptr && !fCreatePDB) - { - OutputErr(W("The /App_Ni_Paths switch can only be used with the /CreatePDB switch.\n")); - exit(FAILURE_RESULT); - } - -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) - if (pwszCLRJITPath != nullptr && fCreatePDB) - { - OutputErr(W("The /JITPath switch can not be used with the /CreatePDB switch.\n")); - exit(FAILURE_RESULT); - } -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) - -#if !defined(NO_NGENPDB) - if (pwzDiasymreaderPath != nullptr && !fCreatePDB) - { - OutputErr(W("The /DiasymreaderPath switch can only be used with the /CreatePDB switch.\n")); - exit(FAILURE_RESULT); - } -#endif // !defined(NO_NGENPDB) - - if (!ssTrustedPlatformAssemblies.IsEmpty()) - { - pwzTrustedPlatformAssemblies = (WCHAR *)ssTrustedPlatformAssemblies.GetUnicode(); - } - - if ((pwzTrustedPlatformAssemblies != nullptr) && (pwzPlatformAssembliesPaths != nullptr)) - { - OutputErr(W("The /r and /p switches cannot be both specified.\n")); - exit(FAILURE_RESULT); - } - - // All argument processing has happened by now. The only messages that should appear before here are errors - // related to argument parsing, such as the Usage message. Afterwards, other messages can appear. - - ///////////////////////////////////////////////////////////////////////// - // - // Start processing - // - - if (fDisplayLogo) - { - PrintLogoHelper(); - } - - PathString wzTrustedPathRoot; - - SString ssTPAList; - - if (fCreatePDB) - { - // While creating PDB, assembly binder gives preference to files in TPA. - // This can create difficulties if the input file is not in TPA. - // To avoid this issue, put the input file as the first item in TPA. - ssTPAList.Append(pwzFilename); - } - - if(pwzPlatformAssembliesPaths != nullptr) - { - // /p command line switch has been specified. - _ASSERTE(pwzTrustedPlatformAssemblies == nullptr); - - // Formulate the TPAList from /p - ComputeTPAListFromPlatformAssembliesPath(pwzPlatformAssembliesPaths, ssTPAList, fCreatePDB); - pwzTrustedPlatformAssemblies = (WCHAR *)ssTPAList.GetUnicode(); - pwzPlatformAssembliesPaths = NULL; - } - - if (pwzTrustedPlatformAssemblies != nullptr) - { - if (ComputeCoreLibPathFromTrustedPlatformAssemblies(wzTrustedPathRoot, pwzTrustedPlatformAssemblies)) - { - pwzPlatformAssembliesPaths = wzTrustedPathRoot.GetUnicode(); - SetCoreLibPath(pwzPlatformAssembliesPaths); - } - } - - if (pwzPlatformAssembliesPaths == NULL) - { - if (!WszGetModuleFileName(NULL, wzTrustedPathRoot)) - { - ERROR_WIN32(W("Error: GetModuleFileName failed (%d)\n"), GetLastError()); - exit(CLR_INIT_ERROR); - } - - if (SUCCEEDED(CopySystemDirectory(wzTrustedPathRoot, wzTrustedPathRoot))) - { - pwzPlatformAssembliesPaths = wzTrustedPathRoot.GetUnicode(); - } - else - { - ERROR_HR(W("Error: wcsrchr returned NULL; GetModuleFileName must have given us something bad\n"), E_UNEXPECTED); - exit(CLR_INIT_ERROR); - } - - - } - - // Verbose mode will always print warnings - if ((dwFlags & NGENWORKER_FLAGS_VERBOSE) != 0) - dwFlags &= ~NGENWORKER_FLAGS_SUPPRESS_WARNINGS; - - g_CrossgenLogger.SetWarningLogging((dwFlags & NGENWORKER_FLAGS_SUPPRESS_WARNINGS) == 0); - - // Initialize the logger - SetSvcLogger(&g_CrossgenLogger); - - //Step - Compile the assembly - - if (fCreatePDB) - { - hr = CreatePDBWorker( - pwzFilename, - pwzPlatformAssembliesPaths, - pwzTrustedPlatformAssemblies, - pwzPlatformResourceRoots, - pwzAppPaths, - pwzAppNiPaths, - wzDirectoryToStorePDB, - fGeneratePDBLinesInfo, - pwzSearchPathForManagedPDB, - pwzDiasymreaderPath); - - } - else - { - hr = NGenWorker(pwzFilename, dwFlags, - pwzPlatformAssembliesPaths, - pwzTrustedPlatformAssemblies, - pwzPlatformResourceRoots, - pwzAppPaths, - pwzOutputFilename, - baseAddress -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) - , - NULL, // ICorSvcLogger - pwszCLRJITPath -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) - ); - } - - - if (FAILED(hr)) - { - if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) - { - OutputErrf(W("Error: file \"%s\" or one of its dependencies was not found\n"), pwzFilename); - exit(ASSEMBLY_NOT_FOUND); - } - else - { - OutputErrf(W("Error: compilation failed for \"%s\" (0x%08x)\n"), pwzFilename, hr); - exit(hr); - } - } - - return 0; -} - -#ifdef TARGET_UNIX -int main(int argc, char *argv[]) -{ - if (0 != PAL_Initialize(argc, argv)) - { - return FAILURE_RESULT; - } - - WCHAR **wargv = new WCHAR*[argc]; - for (int i = 0; i < argc; i++) - { - size_t len = strlen(argv[i]) + 1; - wargv[i] = new WCHAR[len]; - WszMultiByteToWideChar(CP_ACP, 0, argv[i], -1, wargv[i], len); - } - - int ret = wmain(argc, wargv); - - for (int i = 0; i < argc; i++) - { - delete[] wargv[i]; - } - delete[] wargv; - - return ret; -} -#endif // TARGET_UNIX From 4647832dacdc5a22df8c46c0be9fe15f5eb79cef Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 17 Aug 2021 15:37:06 -0700 Subject: [PATCH 8/9] Delete compile definitions that are only applicable for crossgen1. Code references have not been removed. The following defines are now never defined and all blocks guarded by them can be considered dead code: - [ ] CROSSGEN_COMPILE - [ ] FEATURE_NATIVE_IMAGE_GENERATION - [ ] FEATURE_READYTORUN_COMPILER (outside of the coreclr/jit directory) --- src/coreclr/clrdefinitions.cmake | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/src/coreclr/clrdefinitions.cmake b/src/coreclr/clrdefinitions.cmake index 257a9c377e3bac..9bac60864e413c 100644 --- a/src/coreclr/clrdefinitions.cmake +++ b/src/coreclr/clrdefinitions.cmake @@ -1,10 +1,6 @@ include(${CMAKE_CURRENT_LIST_DIR}/clrfeatures.cmake) add_compile_definitions($<$>:DACCESS_COMPILE>) -add_compile_definitions($<$>:CROSSGEN_COMPILE>) -add_compile_definitions($<$>:CROSS_COMPILE>) -add_compile_definitions($<$>:FEATURE_NATIVE_IMAGE_GENERATION>) -add_compile_definitions($<$>:SELF_NO_HOST>) if (CLR_CMAKE_TARGET_ARCH_ARM64) if (CLR_CMAKE_TARGET_UNIX) @@ -58,11 +54,11 @@ if(CLR_CMAKE_HOST_WIN32) endif(CLR_CMAKE_HOST_WIN32) if (NOT (CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_UNIX)) - add_compile_definitions($<$>>:EnC_SUPPORTED>) + add_compile_definitions(EnC_SUPPORTED) endif() if(CLR_CMAKE_TARGET_ARCH_AMD64 OR (CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_WIN32)) if(CLR_CMAKE_TARGET_WIN32) - add_compile_definitions($<$>>:FEATURE_ENC_SUPPORTED>) + add_compile_definitions(FEATURE_ENC_SUPPORTED) endif(CLR_CMAKE_TARGET_WIN32) endif(CLR_CMAKE_TARGET_ARCH_AMD64 OR (CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_WIN32)) @@ -85,7 +81,7 @@ if(CLR_CMAKE_TARGET_UNIX OR NOT CLR_CMAKE_TARGET_ARCH_I386) add_definitions(-DFEATURE_INSTANTIATINGSTUB_AS_IL) endif() -add_compile_definitions($<$>>:FEATURE_CODE_VERSIONING>) +add_compile_definitions(FEATURE_CODE_VERSIONING) add_definitions(-DFEATURE_COLLECTIBLE_TYPES) if(CLR_CMAKE_TARGET_WIN32) @@ -103,7 +99,7 @@ if(FEATURE_DBGIPC) endif(FEATURE_DBGIPC) add_definitions(-DFEATURE_DEFAULT_INTERFACES) if(FEATURE_EVENT_TRACE) - add_compile_definitions($<$>>:FEATURE_EVENT_TRACE>) + add_compile_definitions(FEATURE_EVENT_TRACE) add_definitions(-DFEATURE_PERFTRACING) else(FEATURE_EVENT_TRACE) add_custom_target(eventing_headers) # add a dummy target to avoid checking for FEATURE_EVENT_TRACE in multiple places @@ -132,7 +128,7 @@ if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ add_definitions(-DFEATURE_INTEROP_DEBUGGING) endif (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM64)) if(FEATURE_INTERPRETER) - add_compile_definitions($<$>>:FEATURE_INTERPRETER>) + add_compile_definitions(FEATURE_INTERPRETER) endif(FEATURE_INTERPRETER) add_definitions(-DFEATURE_ISYM_READER) if (CLR_CMAKE_TARGET_LINUX OR CLR_CMAKE_TARGET_WIN32) @@ -143,7 +139,7 @@ add_definitions(-DFEATURE_MANAGED_ETW_CHANNELS) if(FEATURE_MERGE_JIT_AND_ENGINE) add_compile_definitions($<$>>:FEATURE_MERGE_JIT_AND_ENGINE>) endif(FEATURE_MERGE_JIT_AND_ENGINE) -add_compile_definitions($<$>>:FEATURE_MULTICOREJIT>) +add_compile_definitions(FEATURE_MULTICOREJIT) if(CLR_CMAKE_TARGET_UNIX) add_definitions(-DFEATURE_PAL_ANSI) endif(CLR_CMAKE_TARGET_UNIX) @@ -151,12 +147,10 @@ if(CLR_CMAKE_TARGET_LINUX AND CLR_CMAKE_HOST_LINUX) add_definitions(-DFEATURE_PERFMAP) endif(CLR_CMAKE_TARGET_LINUX AND CLR_CMAKE_HOST_LINUX) if(CLR_CMAKE_TARGET_FREEBSD) - add_compile_definitions($<$>>:FEATURE_PERFMAP>) + add_compile_definitions(FEATURE_PERFMAP) endif(CLR_CMAKE_TARGET_FREEBSD) if(FEATURE_PREJIT) add_definitions(-DFEATURE_PREJIT) -else() - add_compile_definitions($<$>:FEATURE_PREJIT>) endif(FEATURE_PREJIT) if(FEATURE_COMWRAPPERS) @@ -167,14 +161,13 @@ if(FEATURE_OBJCMARSHAL) add_compile_definitions(FEATURE_OBJCMARSHAL) endif() -add_compile_definitions($<$>>,$>>>:FEATURE_PROFAPI_ATTACH_DETACH>) +add_compile_definitions($<$>>:FEATURE_PROFAPI_ATTACH_DETACH>) add_definitions(-DFEATURE_READYTORUN) -add_compile_definitions($<$>:FEATURE_READYTORUN_COMPILER>) set(FEATURE_READYTORUN 1) -add_compile_definitions($<$>>:FEATURE_REJIT>) +add_compile_definitions(FEATURE_REJIT) if (CLR_CMAKE_HOST_UNIX AND CLR_CMAKE_TARGET_UNIX) add_definitions(-DFEATURE_REMOTE_PROC_MEM) @@ -191,11 +184,11 @@ if (FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION) endif(FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION) add_definitions(-DFEATURE_SVR_GC) add_definitions(-DFEATURE_SYMDIFF) -add_compile_definitions($<$>>:FEATURE_TIERED_COMPILATION>) +add_compile_definitions(FEATURE_TIERED_COMPILATION) if (CLR_CMAKE_TARGET_ARCH_AMD64) - add_compile_definitions($<$>>:FEATURE_ON_STACK_REPLACEMENT>) + add_compile_definitions(FEATURE_ON_STACK_REPLACEMENT) endif (CLR_CMAKE_TARGET_ARCH_AMD64) -add_compile_definitions($<$>>:FEATURE_PGO>) +add_compile_definitions(FEATURE_PGO) if (CLR_CMAKE_TARGET_WIN32) add_definitions(-DFEATURE_TYPEEQUIVALENCE) endif(CLR_CMAKE_TARGET_WIN32) From e27286574abd0dd5f0869ea117da415844d40041 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 17 Aug 2021 16:36:57 -0700 Subject: [PATCH 9/9] Remove FEATURE_PREJIT and FEATURE_NGEN_RELOCS_OPTIMIZATIONS as they are dead code. --- src/coreclr/clrdefinitions.cmake | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/coreclr/clrdefinitions.cmake b/src/coreclr/clrdefinitions.cmake index 9bac60864e413c..be2335b5910d57 100644 --- a/src/coreclr/clrdefinitions.cmake +++ b/src/coreclr/clrdefinitions.cmake @@ -149,9 +149,6 @@ endif(CLR_CMAKE_TARGET_LINUX AND CLR_CMAKE_HOST_LINUX) if(CLR_CMAKE_TARGET_FREEBSD) add_compile_definitions(FEATURE_PERFMAP) endif(CLR_CMAKE_TARGET_FREEBSD) -if(FEATURE_PREJIT) - add_definitions(-DFEATURE_PREJIT) -endif(FEATURE_PREJIT) if(FEATURE_COMWRAPPERS) add_compile_definitions(FEATURE_COMWRAPPERS) @@ -176,9 +173,6 @@ endif (CLR_CMAKE_HOST_UNIX AND CLR_CMAKE_TARGET_UNIX) if (CLR_CMAKE_TARGET_UNIX OR CLR_CMAKE_TARGET_ARCH_ARM64) add_definitions(-DFEATURE_STUBS_AS_IL) endif () -if (FEATURE_NGEN_RELOCS_OPTIMIZATIONS) - add_definitions(-DFEATURE_NGEN_RELOCS_OPTIMIZATIONS) -endif(FEATURE_NGEN_RELOCS_OPTIMIZATIONS) if (FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION) add_definitions(-DFEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION) endif(FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION)