diff --git a/src/coreclr/interpreter/compiler.cpp b/src/coreclr/interpreter/compiler.cpp index 26cd08599b9c3e..2be041ca9dcee6 100644 --- a/src/coreclr/interpreter/compiler.cpp +++ b/src/coreclr/interpreter/compiler.cpp @@ -89,6 +89,23 @@ class InterpIAllocator : public IAllocator } }; + +void* MemPoolAllocator::Alloc(size_t sz) const { return m_compiler->AllocMemPool(sz); } +void MemPoolAllocator::Free(void* ptr) const { /* no-op */ } + +void* MallocAllocator::Alloc(size_t sz) const +{ + void* mem = malloc(sz); + if (mem == nullptr) + NOMEM(); + return mem; +} +void MallocAllocator::Free(void* ptr) const +{ + free(ptr); +} + + size_t GetGenericLookupOffset(const CORINFO_RUNTIME_LOOKUP *pLookup, uint32_t index) { if (pLookup->indirections == CORINFO_USEHELPER) @@ -716,7 +733,7 @@ uint32_t InterpCompiler::ConvertOffset(int32_t offset) return offset * sizeof(int32_t) + sizeof(void*); } -int32_t* InterpCompiler::EmitCodeIns(int32_t *ip, InterpInst *ins, TArray *relocs) +int32_t* InterpCompiler::EmitCodeIns(int32_t *ip, InterpInst *ins, TArray *relocs) { ins->nativeOffset = (int32_t)(ip - m_pMethodCode); @@ -838,10 +855,16 @@ int32_t* InterpCompiler::EmitCodeIns(int32_t *ip, InterpInst *ins, TArray *relocs) +void InterpCompiler::PatchRelocations(TArray *relocs) { int32_t size = relocs->GetSize(); @@ -880,7 +903,7 @@ void InterpCompiler::PatchRelocations(TArray *relocs) } } -int32_t *InterpCompiler::EmitBBCode(int32_t *ip, InterpBasicBlock *bb, TArray *relocs) +int32_t *InterpCompiler::EmitBBCode(int32_t *ip, InterpBasicBlock *bb, TArray *relocs) { m_pCBB = bb; m_pCBB->nativeOffset = (int32_t)(ip - m_pMethodCode); @@ -903,12 +926,13 @@ int32_t *InterpCompiler::EmitBBCode(int32_t *ip, InterpBasicBlock *bb, TArray relocs; + TArray relocs(GetMemPoolAllocator()); int32_t codeSize = ComputeCodeSize(); m_pMethodCode = (int32_t*)AllocMethodData(codeSize * sizeof(int32_t)); // These will eventually be freed by the VM, and they use the delete [] operator for the deletion. m_pILToNativeMap = new ICorDebugInfo::OffsetMapping[m_ILCodeSize]; + ICorDebugInfo::NativeVarInfo* eeVars = NULL; if (m_numILVars > 0) { @@ -998,6 +1022,13 @@ class InterpGcSlotAllocator uint32_t startOffset; uint32_t endOffset; + bool OverlapsOrAdjacentTo(uint32_t startOther, uint32_t endOther) const + { + assert (startOther < endOther); + + return !(endOffset < startOther || startOffset > endOther); + } + void MergeWith(uint32_t startOther, uint32_t endOther) { // This can only be called with overlapping or adjacent ranges @@ -1014,38 +1045,81 @@ class InterpGcSlotAllocator } }; - ConservativeRange** m_conservativeRanges = nullptr; - - ConservativeRange* FindAndRemoveOverlappingOrAdjacentRange(uint32_t offsetBytes, uint32_t start, uint32_t end) + struct ConservativeRanges { - uint32_t slotIndex = offsetBytes / sizeof(void *); - ConservativeRange* prev = nullptr; - ConservativeRange* range = m_conservativeRanges[slotIndex]; - while (range) + ConservativeRanges(InterpCompiler* pCompiler) : m_liveRanges(pCompiler->GetMemPoolAllocator()) { - if (!(end < range->startOffset || start > range->endOffset)) + } + + TArray m_liveRanges; + + void InsertRange(InterpCompiler* pCompiler, uint32_t start, uint32_t end) + { +#ifdef DEBUG + bool m_verbose = pCompiler->m_verbose; +#endif + + ConservativeRange newRange(start, end); + + if (m_liveRanges.GetSize() != 0) { - // Overlapping or adjacent ranges - if (prev) - prev->next = range->next; - else - m_conservativeRanges[slotIndex] = range->next; - range->next = nullptr; - return range; + // Find the first range which has a start offset greater or equal to the new ranges start offset + + int32_t hiBound = m_liveRanges.GetSize(); + int32_t loBound = 0; + while (loBound < hiBound) + { + int32_t mid = (loBound + hiBound) / 2; + ConservativeRange existingRange = m_liveRanges.Get(mid); + if (existingRange.startOffset >= start) + { + hiBound = mid; + } + else + { + loBound = mid + 1; + } + } + int32_t iFirstRangeWithGreaterStartOffset = hiBound; + + // The range before the first range which is greater, may overlap with the new range, so subtract 1 if possible + int32_t iFirstInterestingRange = iFirstRangeWithGreaterStartOffset > 0 ? iFirstRangeWithGreaterStartOffset - 1: 0; + + for (int32_t i = iFirstInterestingRange; i < m_liveRanges.GetSize(); i++) + { + ConservativeRange existingRange = m_liveRanges.Get(i); + if (existingRange.OverlapsOrAdjacentTo(start, end)) + { + ConservativeRange updatedRange = existingRange; + INTERP_DUMP("Merging with existing range [%u - %u]\n", existingRange.startOffset, existingRange.endOffset); + updatedRange.MergeWith(start, end); + while ((i + 1 < m_liveRanges.GetSize()) && m_liveRanges.Get(i + 1).OverlapsOrAdjacentTo(start, end)) + { + ConservativeRange otherExistingRange = m_liveRanges.Get(i + 1); + INTERP_DUMP("Merging with existing range [%u - %u]\n", otherExistingRange.startOffset, otherExistingRange.endOffset); + updatedRange.MergeWith(otherExistingRange.startOffset, otherExistingRange.endOffset); + m_liveRanges.RemoveAt(i + 1); + } + INTERP_DUMP("Final merged range [%u - %u]\n", updatedRange.startOffset, updatedRange.endOffset); + m_liveRanges.Set(i, updatedRange); + return; + } + + if (existingRange.startOffset > start) + { + // If we reach here, the new range is disjoint from all existing ranges, and we've found the right place to insert + m_liveRanges.InsertAt(i, newRange); + return; + } + } + } - prev = range; - range = range->next; + // If we reach here, the new range is disjoint from all existing ranges, and should be added at the end of the list + m_liveRanges.Add(newRange); } - return nullptr; - } - - void InsertConservativeRange(uint32_t offsetBytes, ConservativeRange* range) - { - uint32_t slotIndex = offsetBytes / sizeof(void *); + }; - range->next = m_conservativeRanges[slotIndex]; - m_conservativeRanges[slotIndex] = range; - } + TArray m_conservativeRanges; unsigned m_slotTableSize; @@ -1065,6 +1139,7 @@ class InterpGcSlotAllocator InterpGcSlotAllocator(InterpCompiler *compiler, InterpreterGcInfoEncoder *encoder) : m_compiler(compiler) , m_encoder(encoder) + , m_conservativeRanges(compiler->GetMemPoolAllocator()) , m_slotTableSize(compiler->m_totalVarsStackSize / sizeof(void *)) #ifdef DEBUG , m_verbose(compiler->m_verbose) @@ -1076,8 +1151,7 @@ class InterpGcSlotAllocator // 0 is a valid slot id so default-initialize all the slots to 0xFFFFFFFF memset(m_slotTables[i], 0xFF, sizeof(GcSlotId) * m_slotTableSize); } - m_conservativeRanges = new (m_compiler) ConservativeRange *[m_slotTableSize]; - memset(m_conservativeRanges, 0, sizeof(ConservativeRange *) * m_slotTableSize); + m_conservativeRanges.GrowBy(m_slotTableSize); } void AllocateOrReuseGcSlot(uint32_t offsetBytes, GcSlotFlags flags) @@ -1128,51 +1202,41 @@ class InterpGcSlotAllocator startOffset, endOffset ); - - ConservativeRange* pExistingRange = FindAndRemoveOverlappingOrAdjacentRange(offsetBytes, startOffset, endOffset); - if (pExistingRange != nullptr) - { - INTERP_DUMP("Merging with existing range [%u - %u]\n", pExistingRange->startOffset, pExistingRange->endOffset); - pExistingRange->MergeWith(startOffset, endOffset); - ConservativeRange* pOtherExistingRange = FindAndRemoveOverlappingOrAdjacentRange(offsetBytes, pExistingRange->startOffset, pExistingRange->endOffset); - while (pOtherExistingRange != nullptr) - { - INTERP_DUMP("Merging with existing range [%u - %u]\n", pOtherExistingRange->startOffset, pOtherExistingRange->endOffset); - pExistingRange->MergeWith(pOtherExistingRange->startOffset, pOtherExistingRange->endOffset); - pOtherExistingRange = FindAndRemoveOverlappingOrAdjacentRange(offsetBytes, pExistingRange->startOffset, pExistingRange->endOffset); - }; - InsertConservativeRange(offsetBytes, pExistingRange); - } - else + uint32_t slotIndex = offsetBytes / sizeof(void *); + if (m_conservativeRanges.Get(slotIndex) == nullptr) { - ConservativeRange* pNewRange = new (m_compiler) ConservativeRange(startOffset, endOffset); - InsertConservativeRange(offsetBytes, pNewRange); + m_conservativeRanges.Set(slotIndex, new (m_compiler) ConservativeRanges(m_compiler)); } + m_conservativeRanges.Get(slotIndex)->InsertRange(m_compiler, startOffset, endOffset); } void ReportConservativeRangesToGCEncoder() { uint32_t maxEndOffset = m_compiler->ConvertOffset(m_compiler->m_methodCodeSize); - for (uint32_t i = 0; i < m_slotTableSize; i++) + for (uint32_t iSlot = 0; iSlot < m_slotTableSize; iSlot++) { - ConservativeRange* range = m_conservativeRanges[i]; + ConservativeRanges* ranges = m_conservativeRanges.Get(iSlot); + if (ranges == nullptr) + continue; - if (range == nullptr) + if (ranges->m_liveRanges.GetSize() == 0) continue; - GcSlotId* pSlot = LocateGcSlotTableEntry(i * sizeof(void *), GC_SLOT_INTERIOR); + GcSlotId* pSlot = LocateGcSlotTableEntry(iSlot * sizeof(void *), GC_SLOT_INTERIOR); assert(pSlot != nullptr && *pSlot != (GcSlotId)-1); - while (range) + for(int32_t iRange = 0; iRange < ranges->m_liveRanges.GetSize(); iRange++) { + ConservativeRange range = ranges->m_liveRanges.Get(iRange); + INTERP_DUMP( "Conservative range for slot %u at %u [%u - %u]\n", *pSlot, - (unsigned)(i * sizeof(void *)), - range->startOffset, - range->endOffset + 1 + (unsigned)(iSlot * sizeof(void *)), + range.startOffset, + range.endOffset + 1 ); - m_encoder->SetSlotState(range->startOffset, *pSlot, GC_SLOT_LIVE); + m_encoder->SetSlotState(range.startOffset, *pSlot, GC_SLOT_LIVE); // Conservatively assume that the lifetime of a slot extends to just past the end of what // the lifetime analysis has determined. This is due to an inaccuracy of reporting in the @@ -1187,16 +1251,15 @@ class InterpGcSlotAllocator // in the caller's stack. This would likely reduce the conservative reporting being done by // functions up the stack in the interpreter case, such that we don't have excessive conservative // reporting causing substantial pinning overhead. - uint32_t endOffset = range->endOffset + 1; + uint32_t endOffset = range.endOffset + 1; if (endOffset > maxEndOffset) { // The GcInfoEncoder should not report slots beyond the method's end endOffset = maxEndOffset; - assert(endOffset == range->endOffset); + assert(endOffset == range.endOffset); } m_encoder->SetSlotState(endOffset, *pSlot, GC_SLOT_DEAD); - range = range->next; } } } @@ -1488,9 +1551,15 @@ static void FreeInterpreterStackMap(void *key, void *value, void *userdata) InterpCompiler::InterpCompiler(COMP_HANDLE compHnd, CORINFO_METHOD_INFO* methodInfo) - : m_stackmapsByClass(FreeInterpreterStackMap) + : + #ifdef DEBUG + m_methodName(GetMallocAllocator()), + #endif + m_stackmapsByClass(FreeInterpreterStackMap) , m_pInitLocalsIns(nullptr) , m_hiddenArgumentVar(-1) + , m_leavesTable(this) + , m_dataItems(this) , m_globalVarsWithRefsStackTop(0) { m_genericLookupToDataItemIndex.Init(&m_dataItems, this); @@ -6708,7 +6777,7 @@ void InterpCompiler::PrintMethodName(CORINFO_METHOD_HANDLE method) CORINFO_SIG_INFO sig; m_compHnd->getMethodSig(method, &sig, cls); - TArray methodName = ::PrintMethodName(m_compHnd, cls, method, &sig, + TArray methodName = ::PrintMethodName(m_compHnd, cls, method, &sig, /* includeAssembly */ false, /* includeClass */ true, /* includeClassInstantiation */ true, diff --git a/src/coreclr/interpreter/compiler.h b/src/coreclr/interpreter/compiler.h index 6c7144ec3dc4d5..a2eff1b0c03d57 100644 --- a/src/coreclr/interpreter/compiler.h +++ b/src/coreclr/interpreter/compiler.h @@ -26,6 +26,15 @@ struct InterpException class InterpreterStackMap; class InterpCompiler; +class MemPoolAllocator +{ + InterpCompiler* const m_compiler; + public: + MemPoolAllocator(InterpCompiler* compiler) : m_compiler(compiler) {} + void* Alloc(size_t sz) const; + void Free(void* ptr) const; +}; + class InterpDataItemIndexMap { struct VarSizedData @@ -52,7 +61,7 @@ class InterpDataItemIndexMap }; dn_simdhash_ght_t* _hash = nullptr; - TArray *_dataItems = nullptr; // Actual data items stored here, indexed by the value in the hash table. This pointer is owned by the InterpCompiler class. + TArray *_dataItems = nullptr; // Actual data items stored here, indexed by the value in the hash table. This pointer is owned by the InterpCompiler class. InterpCompiler* _compiler = nullptr; static unsigned int HashVarSizedData(const void *voidKey) @@ -90,7 +99,7 @@ class InterpDataItemIndexMap InterpDataItemIndexMap(const InterpDataItemIndexMap&) = delete; InterpDataItemIndexMap& operator=(const InterpDataItemIndexMap&) = delete; - void Init(TArray *dataItems, InterpCompiler* compiler) + void Init(TArray *dataItems, InterpCompiler* compiler) { _compiler = compiler; _dataItems = dataItems; @@ -122,7 +131,7 @@ class InterpDataItemIndexMap int32_t GetDataItemIndexForT(const T& lookup); }; -TArray PrintMethodName(COMP_HANDLE comp, +TArray PrintMethodName(COMP_HANDLE comp, CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE methHnd, CORINFO_SIG_INFO* sig, @@ -478,8 +487,8 @@ class InterpCompiler } CORINFO_CLASS_HANDLE m_classHnd; - #ifdef DEBUG - TArray m_methodName; +#ifdef DEBUG + TArray m_methodName; #ifdef TARGET_WASM // enable verbose output on wasm temporarily bool m_verbose = true; @@ -520,13 +529,13 @@ class InterpCompiler // Table of mappings of leave instructions to the first finally call island the leave // needs to execute. - TArray m_leavesTable; + TArray m_leavesTable; // This represents a mapping from indexes to pointer sized data. During compilation, an // instruction can request an index for some data (like a MethodDesc pointer), that it // will then embed in the instruction stream. The data item table will be referenced // from the interpreter code header during execution. - TArray m_dataItems; + TArray m_dataItems; InterpDataItemIndexMap m_genericLookupToDataItemIndex; int32_t GetDataItemIndex(void* data) @@ -615,10 +624,12 @@ class InterpCompiler void* AllocMethodData(size_t numBytes); public: - // FIXME Mempool allocation currently leaks. We need to add an allocator and then + // FIXME MemPool allocation currently leaks. We need to add an allocator and then // free all memory when method is finished compilling. void* AllocMemPool(size_t numBytes); void* AllocMemPool0(size_t numBytes); + MemPoolAllocator GetMemPoolAllocator() { return MemPoolAllocator(this); } + private: void* AllocTemporary(size_t numBytes); void* AllocTemporary0(size_t numBytes); @@ -649,6 +660,9 @@ class InterpCompiler InterpBasicBlock** m_ppOffsetToBB; ICorDebugInfo::OffsetMapping* m_pILToNativeMap = NULL; +#ifdef DEBUG + int32_t* m_pNativeMapIndexToILOffset = NULL; +#endif int32_t m_ILToNativeMapSize = 0; InterpBasicBlock* AllocBB(int32_t ilOffset); @@ -723,8 +737,8 @@ class InterpCompiler void EmitBox(StackInfo* pStackInfo, const CORINFO_GENERICHANDLE_RESULT &boxType, bool argByRef); // Var Offset allocator - TArray *m_pActiveCalls; - TArray *m_pActiveVars; + TArray *m_pActiveCalls; + TArray *m_pActiveVars; TSList *m_pDeferredCalls; int32_t AllocGlobalVarOffset(int var); @@ -744,9 +758,9 @@ class InterpCompiler int32_t ComputeCodeSize(); uint32_t ConvertOffset(int32_t offset); void EmitCode(); - int32_t* EmitBBCode(int32_t *ip, InterpBasicBlock *bb, TArray *relocs); - int32_t* EmitCodeIns(int32_t *ip, InterpInst *pIns, TArray *relocs); - void PatchRelocations(TArray *relocs); + int32_t* EmitBBCode(int32_t *ip, InterpBasicBlock *bb, TArray *relocs); + int32_t* EmitCodeIns(int32_t *ip, InterpInst *pIns, TArray *relocs); + void PatchRelocations(TArray *relocs); InterpMethod* CreateInterpMethod(); void CreateBasicBlocks(CORINFO_METHOD_INFO* methodInfo); void InitializeClauseBuildingBlocks(CORINFO_METHOD_INFO* methodInfo); @@ -781,15 +795,25 @@ class InterpCompiler * Uses the compiler's AllocMemPool0, which will eventually free automatically at the end of compilation (doesn't yet). */ - inline void* operator new(size_t sz, InterpCompiler* compiler) - { +inline void* operator new(size_t sz, InterpCompiler* compiler) +{ return compiler->AllocMemPool0(sz); } - inline void* operator new[](size_t sz, InterpCompiler* compiler) - { - return compiler->AllocMemPool0(sz); - } +inline void* operator new[](size_t sz, InterpCompiler* compiler) +{ + return compiler->AllocMemPool0(sz); +} + +inline void operator delete(void* ptr, InterpCompiler* compiler) +{ + // Nothing to do, memory will be freed when the compiler is destroyed +} + +inline void operator delete[](void* ptr, InterpCompiler* compiler) +{ + // Nothing to do, memory will be freed when the compiler is destroyed +} template int32_t InterpDataItemIndexMap::GetDataItemIndexForT(const T& lookup) diff --git a/src/coreclr/interpreter/compileropt.cpp b/src/coreclr/interpreter/compileropt.cpp index 7fd51b7610f561..92018b0d6a1845 100644 --- a/src/coreclr/interpreter/compileropt.cpp +++ b/src/coreclr/interpreter/compileropt.cpp @@ -137,7 +137,7 @@ void InterpCompiler::InitializeGlobalVars() void InterpCompiler::EndActiveCall(InterpInst *call) { // Remove call from array - m_pActiveCalls->Remove(call); + m_pActiveCalls->RemoveFirstUnordered(call); // Push active call that should be resolved onto the stack if (m_pActiveCalls->GetSize()) @@ -211,7 +211,7 @@ void InterpCompiler::CompactActiveVars(int32_t *pCurrentOffset) if (m_pVars[var].alive) return; *pCurrentOffset = m_pVars[var].offset; - m_pActiveVars->RemoveAt(i); + m_pActiveVars->RemoveAtUnordered(i); i--; } } @@ -219,8 +219,8 @@ void InterpCompiler::CompactActiveVars(int32_t *pCurrentOffset) void InterpCompiler::AllocOffsets() { InterpBasicBlock *pBB; - m_pActiveVars = new TArray(); - m_pActiveCalls = new TArray(); + m_pActiveVars = new TArray(GetMemPoolAllocator()); + m_pActiveCalls = new TArray(GetMemPoolAllocator()); m_pDeferredCalls = NULL; InitializeGlobalVars(); diff --git a/src/coreclr/interpreter/datastructs.h b/src/coreclr/interpreter/datastructs.h index 3228ca7682ea30..362444a5e2f441 100644 --- a/src/coreclr/interpreter/datastructs.h +++ b/src/coreclr/interpreter/datastructs.h @@ -4,25 +4,42 @@ #ifndef _DATASTRUCTS_H_ #define _DATASTRUCTS_H_ -template +struct MallocAllocator +{ + MallocAllocator() {} + void* Alloc(size_t sz) const; + void Free(void* ptr) const; +}; + +inline MallocAllocator GetMallocAllocator() { return MallocAllocator(); } + +template class TArray { private: int32_t m_size, m_capacity; T *m_array; + Allocator const m_allocator; void Grow() { + int32_t oldCapacity = m_capacity; + if (m_capacity) m_capacity *= 2; else m_capacity = 16; - m_array = (T*)realloc(m_array, m_capacity * sizeof(T)); + T* newArray = (T*)m_allocator.Alloc(m_capacity * sizeof(T)); + memcpy(newArray, m_array, oldCapacity * sizeof(T)); + m_allocator.Free(m_array); + m_array = newArray; } void Grow(int32_t minNewCapacity) { + int32_t oldCapacity = m_capacity; + if (m_capacity) m_capacity *= 2; else @@ -30,10 +47,13 @@ class TArray m_capacity = (m_capacity > minNewCapacity) ? m_capacity : minNewCapacity; - m_array = (T*)realloc(m_array, m_capacity * sizeof(T)); + T* newArray = (T*)m_allocator.Alloc(m_capacity * sizeof(T)); + memcpy(newArray, m_array, oldCapacity * sizeof(T)); + m_allocator.Free(m_array); + m_array = newArray; } public: - TArray() + TArray(Allocator allocator) : m_allocator(allocator) { m_size = 0; m_capacity = 0; @@ -41,10 +61,11 @@ class TArray } // Implicit copies are not permitted to prevent accidental allocation of large arrays. - TArray(const TArray &other) = delete; - TArray& operator=(const TArray &other) = delete; + TArray(const TArray &other) = delete; + TArray& operator=(const TArray &other) = delete; - TArray(TArray &&other) + TArray(TArray &&other) + : m_allocator(other.m_allocator) { m_size = other.m_size; m_capacity = other.m_capacity; @@ -54,13 +75,12 @@ class TArray other.m_capacity = 0; other.m_array = NULL; } - TArray& operator=(TArray &&other) + TArray& operator=(TArray &&other) { if (this != &other) { - if (m_capacity > 0) - free(m_array); - + if (m_array != nullptr) + m_allocator.Free(m_array); m_size = other.m_size; m_capacity = other.m_capacity; m_array = other.m_array; @@ -74,8 +94,8 @@ class TArray ~TArray() { - if (m_capacity > 0) - free(m_array); + if (m_array != nullptr) + m_allocator.Free(m_array); } int32_t GetSize() const @@ -124,13 +144,19 @@ class TArray return m_array; } - T Get(int32_t index) + T Get(int32_t index) const { assert(index < m_size); return m_array[index]; } - int32_t Find(T element) + void Set(int32_t index, T value) + { + assert(index < m_size); + m_array[index] = value; + } + + int32_t Find(T element) const { for (int i = 0; i < m_size; i++) { @@ -140,24 +166,48 @@ class TArray return -1; } - // Assumes elements are unique void RemoveAt(int32_t index) + { + assert(index < m_size); + for (int32_t iCopy = index + 1; iCopy < m_size; iCopy++) + { + m_array[iCopy - 1] = m_array[iCopy]; + } + m_size--; + } + + void InsertAt(int32_t index, T newValue) + { + assert(index <= m_size); + if (m_size == m_capacity) + Grow(); + + for (int32_t iCopy = m_size; iCopy > index; iCopy--) + { + m_array[iCopy] = m_array[iCopy - 1]; + } + m_array[index] = newValue; + m_size++; + } + + // Assumes order of items in the array is unimportant, as it will reorder the array + void RemoveAtUnordered(int32_t index) { assert(index < m_size); m_size--; // Since this entry is removed, move the last entry into it if (m_size > 0 && index < m_size) m_array[index] = m_array[m_size]; - } + } - // Assumes elements are unique - void Remove(T element) + // Assumes order of items in the array is unimportant, as it will reorder the array + void RemoveFirstUnordered(T element) { for (int32_t i = 0; i < m_size; i++) { if (element == m_array[i]) { - RemoveAt(i); + RemoveAtUnordered(i); break; } } diff --git a/src/coreclr/interpreter/methodset.cpp b/src/coreclr/interpreter/methodset.cpp index 179e9c6031bc33..e4eb5b703becb5 100644 --- a/src/coreclr/interpreter/methodset.cpp +++ b/src/coreclr/interpreter/methodset.cpp @@ -155,7 +155,7 @@ bool MethodSet::contains(COMP_HANDLE comp, return false; } - TArray printer; + TArray printer(GetMallocAllocator()); MethodName* prevPattern = nullptr; for (MethodName* name = m_names; name != nullptr; name = name->m_next) diff --git a/src/coreclr/interpreter/naming.cpp b/src/coreclr/interpreter/naming.cpp index 601a134dceac8f..c73baa8ec5a643 100644 --- a/src/coreclr/interpreter/naming.cpp +++ b/src/coreclr/interpreter/naming.cpp @@ -3,11 +3,11 @@ #include "interpreter.h" -void AppendType(COMP_HANDLE comp, TArray* printer, CORINFO_CLASS_HANDLE clsHnd, bool includeInstantiation); -void AppendCorInfoType(TArray* printer, CorInfoType corInfoType); -void AppendTypeOrJitAlias(COMP_HANDLE comp, TArray* printer, CORINFO_CLASS_HANDLE clsHnd, bool includeInstantiation); +void AppendType(COMP_HANDLE comp, TArray* printer, CORINFO_CLASS_HANDLE clsHnd, bool includeInstantiation); +void AppendCorInfoType(TArray* printer, CorInfoType corInfoType); +void AppendTypeOrJitAlias(COMP_HANDLE comp, TArray* printer, CORINFO_CLASS_HANDLE clsHnd, bool includeInstantiation); -void AppendString(TArray* array, const char* str) +void AppendString(TArray* array, const char* str) { if (str != nullptr) { @@ -16,7 +16,7 @@ void AppendString(TArray* array, const char* str) } } -void AppendCorInfoTypeWithModModifiers(TArray* printer, CorInfoTypeWithMod corInfoTypeWithMod) +void AppendCorInfoTypeWithModModifiers(TArray* printer, CorInfoTypeWithMod corInfoTypeWithMod) { if ((corInfoTypeWithMod & CORINFO_TYPE_MOD_PINNED) == CORINFO_TYPE_MOD_PINNED) { @@ -28,7 +28,7 @@ void AppendCorInfoTypeWithModModifiers(TArray* printer, CorInfoTypeWithMod } } -void AppendCorInfoType(TArray* printer, CorInfoType corInfoType) +void AppendCorInfoType(TArray* printer, CorInfoType corInfoType) { static const char* preciseVarTypeMap[CORINFO_TYPE_COUNT] = { // see the definition of enum CorInfoType in file inc/corinfo.h @@ -66,7 +66,7 @@ void AppendCorInfoType(TArray* printer, CorInfoType corInfoType) printer->Append(corInfoTypeName, static_cast(strlen(corInfoTypeName))); } -void AppendTypeOrJitAlias(COMP_HANDLE comp, TArray* printer, CORINFO_CLASS_HANDLE clsHnd, bool includeInstantiation) +void AppendTypeOrJitAlias(COMP_HANDLE comp, TArray* printer, CORINFO_CLASS_HANDLE clsHnd, bool includeInstantiation) { CorInfoType typ = comp->asCorInfoType(clsHnd); if ((typ == CORINFO_TYPE_CLASS) || (typ == CORINFO_TYPE_VALUECLASS)) @@ -79,7 +79,7 @@ void AppendTypeOrJitAlias(COMP_HANDLE comp, TArray* printer, CORINFO_CLASS } } -void AppendType(COMP_HANDLE comp, TArray* printer, CORINFO_CLASS_HANDLE clsHnd, bool includeInstantiation) +void AppendType(COMP_HANDLE comp, TArray* printer, CORINFO_CLASS_HANDLE clsHnd, bool includeInstantiation) { unsigned arrayRank = comp->getArrayRank(clsHnd); if (arrayRank > 0) @@ -141,7 +141,7 @@ void AppendType(COMP_HANDLE comp, TArray* printer, CORINFO_CLASS_HANDLE cl } void AppendMethodName(COMP_HANDLE comp, - TArray* printer, + TArray* printer, CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE methHnd, CORINFO_SIG_INFO* sig, @@ -153,7 +153,7 @@ void AppendMethodName(COMP_HANDLE comp, bool includeReturnType, bool includeThisSpecifier) { - TArray result; + TArray result(GetMallocAllocator()); if (includeAssembly) { @@ -273,7 +273,7 @@ void AppendMethodName(COMP_HANDLE comp, } } -TArray PrintMethodName(COMP_HANDLE comp, +TArray PrintMethodName(COMP_HANDLE comp, CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE methHnd, CORINFO_SIG_INFO* sig, @@ -285,7 +285,7 @@ TArray PrintMethodName(COMP_HANDLE comp, bool includeReturnType, bool includeThisSpecifier) { - TArray printer; + TArray printer(GetMallocAllocator()); AppendMethodName(comp, &printer, clsHnd, methHnd, sig, includeAssembly, includeClass, includeClassInstantiation, includeMethodInstantiation,