Jelajahi Sumber

Compiler performance enhancements

Brian Fiete 3 tahun lalu
induk
melakukan
d623c21495

+ 9 - 0
BeefySysLib/Common.cpp

@@ -66,6 +66,12 @@ String Beefy::ToUpper(const StringImpl& theString)
 	return aString;
 }
 
+void Beefy::MakeUpper(StringImpl& theString)
+{	
+	for (int i = 0; i < (int)theString.length(); ++i)
+		theString[i] = toupper(theString[i]);	
+}
+
 UTF16String Beefy::ToUpper(const UTF16String& theString)
 {
 	UTF16String aString = theString;
@@ -1282,3 +1288,6 @@ void Beefy::BFFatalError(const char* message, const char* file, int line)
 	BFFatalError(String(message), String(file), line);
 }
 
+void MakeUpper(const StringImpl& theString)
+{
+}

+ 1 - 0
BeefySysLib/Common.h

@@ -199,6 +199,7 @@ void OutputDebugStrF(const char* fmt ...);
 UTF16String ToWString(const StringImpl& theString);
 String ToString(const UTF16String& theString);
 String ToUpper(const StringImpl& theString);
+void MakeUpper(StringImpl& theString);
 UTF16String ToUpper(const UTF16String& theString);
 UTF16String ToLower(const UTF16String& theString);
 String ToLower(const StringImpl& theString);

+ 23 - 2
BeefySysLib/util/BumpAllocator.h

@@ -255,11 +255,11 @@ class BumpAllocator : public BumpAllocatorT<0x2000>
 
 };
 
-template <typename T>
+template <typename T, int ALLOC_SIZE = 0x2000>
 class AllocatorBump
 {
 public:
-	BumpAllocator* mAlloc;
+	BumpAllocatorT<ALLOC_SIZE>* mAlloc;
 
 	AllocatorBump()
 	{
@@ -286,6 +286,27 @@ public:
 	}
 };
 
+template <int ALLOC_SIZE = 0x2000>
+class RawAllocatorBump
+{
+public:
+	BumpAllocatorT<ALLOC_SIZE>* mAlloc;
+
+	RawAllocatorBump()
+	{
+		mAlloc = NULL;
+	}
+		
+	void* rawAllocate(intptr size)
+	{
+		return mAlloc->AllocBytes(size, 16);
+	}
+
+	void rawDeallocate(void* ptr)
+	{
+
+	}
+};
 
 NS_BF_END
 

+ 5 - 5
BeefySysLib/util/Dictionary.h

@@ -1,6 +1,6 @@
 #pragma once
 
-#include "../Common.h"
+#include "Array.h"
 #include <unordered_map>
 
 #define NEW_DICTIONAY
@@ -9,8 +9,8 @@ NS_BF_BEGIN;
 
 #ifdef NEW_DICTIONAY
 
-template <typename TKey, typename TValue>
-class Dictionary
+template <typename TKey, typename TValue, typename TAlloc = AllocatorCLib<TKey> >
+class Dictionary : public TAlloc
 {
 public:
 	typedef int int_cosize;
@@ -411,7 +411,7 @@ public:
 
 	void AllocData(intptr size, Entry*& outEntries, int_cosize*& outBuckets)
 	{
-		uint8* data = new uint8[size * (sizeof(Entry) + sizeof(int_cosize))];
+		uint8* data = (uint8*)this->rawAllocate(size * (sizeof(Entry) + sizeof(int_cosize)));
 		outEntries = (Entry*)data;
 		outBuckets = (int_cosize*)(data + size * sizeof(Entry));
 	}
@@ -436,7 +436,7 @@ public:
 			}
 		}
 
-		delete [] mEntries;
+		this->rawDeallocate(mEntries);
 	}
 
 	Dictionary& operator=(const Dictionary& rhs)

+ 263 - 84
BeefySysLib/util/MultiHashSet.h

@@ -37,15 +37,50 @@ public:
 	struct Entry
 	{
 		T mValue;
-		Entry* mNext;
-		int mHash;
+		int mNext;
+		int mHashCode;
 	};
 
-	struct Iterator
+	struct EntryRef
 	{
 	public:
 		MultiHashSet* mSet;
-		Entry* mCurEntry;
+		int mIndex;
+
+	public:
+		EntryRef()
+		{
+			mSet = NULL;
+			mIndex = -1;
+		}
+
+		EntryRef(MultiHashSet* set, int index)
+		{
+			mSet = set;
+			mIndex = index;
+		}
+
+		Entry* operator*()
+		{
+			return &this->mSet->mEntries[this->mIndex];
+		}
+
+		Entry* operator->()
+		{
+			return &this->mSet->mEntries[this->mIndex];
+		}
+
+		operator bool() const
+		{
+			return this->mIndex != -1;
+		}
+	};
+
+	struct Iterator
+	{
+	public:		
+		MultiHashSet* mSet;
+		int mCurEntry;
 		int mCurBucket;
 
 	public:
@@ -53,15 +88,15 @@ public:
 		{
 			this->mSet = set;
 			this->mCurBucket = 0;
-			this->mCurEntry = NULL;
+			this->mCurEntry = -1;
 		}
 
 		Iterator& operator++()
 		{
-			if (this->mCurEntry != NULL)
+			if (this->mCurEntry != -1)
 			{
-				this->mCurEntry = this->mCurEntry->mNext;
-				if (this->mCurEntry != NULL)
+				this->mCurEntry = this->mSet->mEntries[this->mCurEntry].mNext;
+				if (this->mCurEntry != -1)
 					return *this;
 				this->mCurBucket++;
 			}
@@ -75,7 +110,7 @@ public:
 			while (this->mCurBucket < mSet->mHashSize)
 			{
 				this->mCurEntry = this->mSet->mHashHeads[mCurBucket];
-				if (this->mCurEntry != NULL)
+				if (this->mCurEntry != -1)
 					return *this;
 				this->mCurBucket++;
 			}
@@ -83,43 +118,135 @@ public:
 			return *this; // At end
 		}
 
-		bool operator!=(const Iterator& itr) const
+		T operator*()
 		{
-			return ((itr.mCurEntry != this->mCurEntry) || (itr.mCurBucket != this->mCurBucket));
+			return this->mSet->mEntries[this->mCurEntry].mValue;
 		}
 
-		T operator*()
+		T operator->()
 		{
-			return this->mCurEntry->mValue;
+			return this->mSet->mEntries[this->mCurEntry].mValue;
 		}
 
-		operator bool() const
+		bool operator!=(const Iterator& itr) const
 		{
-			return this->mCurEntry != NULL;
+			return ((itr.mCurEntry != this->mCurEntry) || (itr.mCurBucket != this->mCurBucket));
 		}
 
+		operator bool() const
+		{
+			return this->mCurEntry != -1;
+		}
+		
 		void MoveToNextHashMatch()
 		{
-			int wantHash = this->mCurEntry->mHash;
+			int wantHash = this->mSet->mEntries[this->mCurEntry].mHashCode;
 			do 
 			{
-				this->mCurEntry = this->mCurEntry->mNext;
+				this->mCurEntry = this->mSet->mEntries[this->mCurEntry].mNext;
 			} 
-			while ((this->mCurEntry != NULL) && (this->mCurEntry->mHash != wantHash));
+			while ((this->mCurEntry != -1) && (this->mSet->mEntries[this->mCurEntry].mHashCode != wantHash));
 		}
 	};
 
-public:
-	Entry** mHashHeads;
+protected:
+
+	int GetPrimeish(int min)
+	{
+		// This is a minimal effort to help address-aligned dataa
+		return (min | 1);
+	}
+
+	int ExpandSize(int oldSize)
+	{
+		int newSize = 2 * oldSize;
+
+		// Allow the hashtables to grow to maximum possible size (~2G elements) before encoutering capacity overflow.
+		// Note that this check works even when mAllocSize overflowed thanks to the (uint) cast
+		/*if ((uint)newSize > MaxPrimeArrayLength && MaxPrimeArrayLength > oldSize)
+		{
+		Contract.Assert( MaxPrimeArrayLength == GetPrime(MaxPrimeArrayLength), "Invalid MaxPrimeArrayLength");
+		return MaxPrimeArrayLength;
+		}*/
+
+		return GetPrimeish(newSize);
+	}
+
+	void ResizeEntries()
+	{
+		ResizeEntries(ExpandSize(mCount));
+	}
+
+	void ResizeEntries(int newSize)
+	{
+		BF_ASSERT(newSize >= mAllocSize);
+		Entry* newEntries = (Entry*)TFuncs::Allocate(sizeof(Entry) * newSize, alignof(Entry));
+		
+		for (int i = 0; i < mCount; i++)
+		{
+			auto& newEntry = newEntries[i];
+			auto& oldEntry = mEntries[i];
+			newEntry.mHashCode = oldEntry.mHashCode;
+			newEntry.mNext = oldEntry.mNext;
+			new (&newEntry.mValue) T(std::move(*(T*)&oldEntry.mValue));
+		}
+		for (int i = mCount; i < newSize; i++)
+		{
+			newEntries[i].mHashCode = -1;
+		}
+		
+		TFuncs::Deallocate(mEntries);
+		
+		mEntries = newEntries;
+		mAllocSize = (int)newSize;
+	}
+
+	void FreeIdx(int entryIdx)
+	{
+		this->mEntries[entryIdx].mNext = this->mFreeList;
+		this->mFreeList = entryIdx;
+		this->mFreeCount++;
+	}
+
+	int AllocEntry()
+	{
+		int index;
+		if (this->mFreeCount > 0)
+		{
+			index = this->mFreeList;
+			this->mFreeList = this->mEntries[index].mNext;
+			this->mFreeCount--;
+		}
+		else
+		{
+			if (this->mCount == this->mAllocSize)
+				ResizeEntries();
+			index = mCount;
+			this->mCount++;
+		}
+		return index;
+	}
+
+public:	
+	int* mHashHeads;
+	int mAllocSize;
+	Entry* mEntries;
+	int mFreeList;
+	int mFreeCount;
+	
 	static const int cDefaultHashSize = 17;
 	int mHashSize;
 	int mCount;
 	
 	MultiHashSet()
-	{
+	{		
 		this->mHashHeads = NULL;
 		this->mHashSize = cDefaultHashSize;
+		this->mEntries = NULL;
+		this->mAllocSize = 0;
 		this->mCount = 0;
+		this->mFreeList = -1;
+		this->mFreeCount = 0;
 	}
 
 	~MultiHashSet()
@@ -127,71 +254,118 @@ public:
 		this->Clear();
 	}
 
+	void EnsureFreeCount(int wantFreeCount)
+	{
+		int freeCount = mFreeCount + (mAllocSize - mCount);
+		if (freeCount >= wantFreeCount)
+			return;
+		ResizeEntries(BF_MAX(ExpandSize(mCount), mAllocSize + wantFreeCount - freeCount));
+	}
+
+	int GetCount() const
+	{
+		return mCount - mFreeCount;
+	}
+
+	int size() const
+	{
+		return mCount - mFreeCount;
+	}
+
+	EntryRef AddRaw(int hash)
+	{
+		if (this->mHashHeads == NULL)
+		{
+			this->mHashHeads = (int*)TFuncs::Allocate(sizeof(int) * mHashSize, alignof(int));
+			memset(this->mHashHeads, -1, sizeof(int) * mHashSize);
+		}
+
+		int index = AllocEntry();		
+		int hashIdx = (hash & 0x7FFFFFFF) % this->mHashSize;
+		int headEntry = this->mHashHeads[hashIdx];
+
+		Entry* newEntry = &mEntries[index];
+		newEntry->mValue = T();
+		newEntry->mNext = headEntry;
+		newEntry->mHashCode = hash;
+
+		mHashHeads[hashIdx] = index;
+
+		return EntryRef(this, index);
+	}
+
 	void Add(T value)
 	{
 		if (this->mHashHeads == NULL)
-			this->mHashHeads = (Entry**)TFuncs::AllocateZero(sizeof(Entry*) * mHashSize, alignof(Entry*));
+		{			
+			this->mHashHeads = (int*)TFuncs::Allocate(sizeof(int) * mHashSize, alignof(int));
+			memset(this->mHashHeads, -1, sizeof(int) * mHashSize);
+		}
 
+		int index = AllocEntry();
 		int hash = TFuncs::GetHash(value);
 		int hashIdx = (hash & 0x7FFFFFFF) % this->mHashSize;
-		Entry* headEntry = this->mHashHeads[hashIdx];
+		int headEntry = this->mHashHeads[hashIdx];
 
-		Entry* newEntry = (Entry*)TFuncs::Allocate(sizeof(Entry), alignof(Entry));
+		Entry* newEntry = &mEntries[index];
 		newEntry->mValue = value;
 		newEntry->mNext = headEntry;
-		newEntry->mHash = hash;
-		mCount++;
+		newEntry->mHashCode = hash;		
 
-		mHashHeads[hashIdx] = newEntry;
+		mHashHeads[hashIdx] = index;		
 	}
 
 	void AddAfter(T value, Entry* afterEntry)
 	{
 		int hash = TFuncs::GetHash(value);
 		int hashIdx = (hash & 0x7FFFFFFF) % this->mHashSize;
-		BF_ASSERT(hash == afterEntry->mHash);
+		BF_ASSERT(hash == afterEntry->mHashCode);
 		
-		Entry* newEntry = (Entry*)TFuncs::Allocate(sizeof(Entry), alignof(Entry));
+		int index = AllocEntry();
+		Entry* newEntry = &mEntries[index];
 		newEntry->mValue = value;
 		newEntry->mNext = afterEntry->mNext;
-		newEntry->mHash = hash;
-		mCount++;
+		newEntry->mHashCode = hash;		
 
-		afterEntry->mNext = newEntry;
+		afterEntry->mNext = index;
 	}
 
 	void Rehash(int newHashSize)
 	{
-		auto newHashHeads = (Entry**)TFuncs::AllocateZero(sizeof(Entry*) * newHashSize, alignof(Entry*));
-
-		SizedArray<Entry*, 32> entryList;
-
-		for (int hashIdx = 0; hashIdx < mHashSize; hashIdx++)
+		auto newHashHeads = (int*)TFuncs::Allocate(sizeof(int) * newHashSize, alignof(int));
+		memset(newHashHeads, -1, sizeof(int) * newHashSize);
+		
+		if (mHashHeads != NULL)
 		{
-			Entry* checkEntry = mHashHeads[hashIdx];
-			if (checkEntry != NULL)
+			SizedArray<int, 1024> entryList;
+			for (int hashIdx = 0; hashIdx < mHashSize; hashIdx++)
 			{
-				// We want to keep elements with equal hashes in their insert order so we need to 
-				// iterate through the linked list in reverse
-				entryList.Clear();
-				
-				while (checkEntry != NULL)
-				{
-					entryList.Add(checkEntry);
-					checkEntry = checkEntry->mNext;
-				}
-				
-				for (int i = (int)entryList.mSize - 1; i >= 0; i--)
+				int checkEntryIdx = mHashHeads[hashIdx];
+				if (checkEntryIdx != -1)
 				{
-					auto checkEntry = entryList[i];					
-					int newHashIdx = (checkEntry->mHash & 0x7FFFFFFF) % newHashSize;
-					checkEntry->mNext = newHashHeads[newHashIdx];
-					newHashHeads[newHashIdx] = checkEntry;
+					// We want to keep elements with equal hashes in their insert order so we need to 
+					// iterate through the linked list in reverse
+					entryList.Clear();
+
+					while (checkEntryIdx != -1)
+					{
+						entryList.Add(checkEntryIdx);
+						checkEntryIdx = mEntries[checkEntryIdx].mNext;
+					}
+
+					for (int i = (int)entryList.mSize - 1; i >= 0; i--)
+					{
+						int checkEntryIdx = entryList[i];
+						auto checkEntry = &mEntries[checkEntryIdx];
+						int newHashIdx = (checkEntry->mHashCode & 0x7FFFFFFF) % newHashSize;
+						checkEntry->mNext = newHashHeads[newHashIdx];
+						newHashHeads[newHashIdx] = checkEntryIdx;
+					}
 				}
 			}
-		}
 
-		TFuncs::Deallocate(mHashHeads);
+			TFuncs::Deallocate(mHashHeads);
+		}
 		mHashHeads = newHashHeads;
 		mHashSize = newHashSize;
 	}
@@ -215,16 +389,17 @@ public:
 
 		int hash = TFuncs::GetHash(key);
 		int hashIdx = (hash & 0x7FFFFFFF) % this->mHashSize;
-		Entry* checkEntry = this->mHashHeads[hashIdx];
-		while (checkEntry != NULL)
+		int checkEntryIdx = this->mHashHeads[hashIdx];
+		while (checkEntryIdx != -1)
 		{
-			if ((checkEntry->mHash == hash) && (TFuncs::Matches(key, checkEntry->mValue)))
+			Entry* checkEntry = &mEntries[checkEntryIdx];
+			if ((checkEntry->mHashCode == hash) && (TFuncs::Matches(key, checkEntry->mValue)))
 			{
 				if (val != NULL)
 					*val = checkEntry->mValue;
 				return true;
 			}
-			checkEntry = checkEntry->mNext;
+			checkEntryIdx = checkEntry->mNext;
 		}
 		return false;
 	}
@@ -239,17 +414,18 @@ public:
 
 		int hash = TFuncs::GetHash(key);
 		int hashIdx = (hash & 0x7FFFFFFF) % this->mHashSize;
-		Entry* checkEntry = this->mHashHeads[hashIdx];
-		while (checkEntry != NULL)
+		int checkEntryIdx = this->mHashHeads[hashIdx];		
+		while (checkEntryIdx != -1)
 		{
-			if ((checkEntry->mHash == hash) && (TFuncs::Matches(key, checkEntry->mValue)))
+			auto checkEntry = &this->mEntries[checkEntryIdx];
+			if ((checkEntry->mHashCode == hash) && (TFuncs::Matches(key, checkEntry->mValue)))
 			{
 				Iterator itr(this);
-				itr.mCurEntry = checkEntry;
+				itr.mCurEntry = checkEntryIdx;
 				itr.mCurBucket = hashIdx;				
 				return itr;
 			}
-			checkEntry = checkEntry->mNext;
+			checkEntryIdx = checkEntry->mNext;			
 		}
 
 		return end();
@@ -266,19 +442,19 @@ public:
 		int hash = TFuncs::GetHash(key);
 		int hashIdx = (hash & 0x7FFFFFFF) % this->mHashSize;
 
-		Entry** srcCheckEntryPtr = &this->mHashHeads[hashIdx];
-		Entry* checkEntry = *srcCheckEntryPtr;
-		while (checkEntry != NULL)
+		int* srcCheckEntryPtr = &this->mHashHeads[hashIdx];
+		int checkEntryIdx = *srcCheckEntryPtr;
+		while (checkEntryIdx != -1)
 		{
-			if ((checkEntry->mHash == hash) && (TFuncs::Matches(key, checkEntry->mValue)))
-			{
-				this->mCount--;
+			auto checkEntry = &mEntries[checkEntryIdx];
+			if ((checkEntry->mHashCode == hash) && (TFuncs::Matches(key, checkEntry->mValue)))
+			{				
 				*srcCheckEntryPtr = checkEntry->mNext;
-				TFuncs::Deallocate(checkEntry);
+				FreeIdx(checkEntryIdx);
 				return true;
 			}
 			srcCheckEntryPtr = &checkEntry->mNext;
-			checkEntry = checkEntry->mNext;
+			checkEntryIdx = checkEntry->mNext;
 		}
 		return false;
 	}
@@ -290,29 +466,30 @@ public:
 
 		bool found = false;
 
-		auto entry = itr.mCurEntry;		
-		int hashIdx = (entry->mHash & 0x7FFFFFFF) % this->mHashSize;
+		auto entryIdx = itr.mCurEntry;		
+		auto entry = &mEntries[entryIdx];
+		int hashIdx = (entry->mHashCode & 0x7FFFFFFF) % this->mHashSize;
 		
-		Entry** srcCheckEntryPtr = &this->mHashHeads[hashIdx];
-		Entry* checkEntry = *srcCheckEntryPtr;
-		while (checkEntry != NULL)
+		int* srcCheckEntryPtr = &this->mHashHeads[hashIdx];
+		int checkEntryIdx = *srcCheckEntryPtr;
+		while (checkEntryIdx != -1)
 		{
-			if (checkEntry == itr.mCurEntry)
+			auto checkEntry = &mEntries[checkEntryIdx];
+			if (checkEntryIdx == itr.mCurEntry)
 			{
-				this->mCount--;
 				*srcCheckEntryPtr = checkEntry->mNext;
 				found = true;
 			}
 			srcCheckEntryPtr = &checkEntry->mNext;
-			checkEntry = checkEntry->mNext;
+			checkEntryIdx = checkEntry->mNext;
 		}
 
 		BF_ASSERT(found);
-		TFuncs::Deallocate(entry);
+		FreeIdx(entryIdx);
 
 		return next;
 	}
-
+	
 	void Clear()
 	{
 		if (!TFuncs::DeallocateAll())
@@ -323,13 +500,15 @@ public:
 			{
 				auto entry = itr.mCurEntry;
 				++itr;
-				TFuncs::Deallocate(entry);
+				FreeIdx(entry);
 			}			
 			TFuncs::Deallocate(this->mHashHeads);
+			TFuncs::Deallocate(this->mEntries);
 		}
 		
 		this->mHashSize = cDefaultHashSize;
 		this->mHashHeads = NULL;
+		this->mEntries = NULL;
 		this->mCount = 0;
 	}
 

+ 5 - 0
BeefySysLib/util/String.cpp

@@ -283,6 +283,11 @@ void StringImpl::Reference(const StringView& strView)
 	Reference(strView.mPtr, strView.mLength);
 }
 
+void StringImpl::Reference(const StringImpl& str)
+{
+	Reference(str.GetPtr(), str.mLength);
+}
+
 String StringImpl::CreateReference(const StringView& strView)
 {
 	String str;

+ 1 - 0
BeefySysLib/util/String.h

@@ -919,6 +919,7 @@ public:
 	void Reference(const char* str);
 	void Reference(const char* str, intptr length);
 	void Reference(const StringView& strView);
+	void Reference(const StringImpl& str);
 	static String CreateReference(const StringView& strView);
 	void Reserve(intptr newSize);
 

+ 58 - 41
IDEHelper/Compiler/BfCompiler.cpp

@@ -2312,15 +2312,16 @@ void BfCompiler::UpdateDependencyMap(bool deleteUnusued, bool& didWork)
 				{
 					extern BfModule* gLastCreatedModule;
 						
+#ifdef _DEBUG
 					for (auto itr = depType->mDependencyMap.begin(); itr != depType->mDependencyMap.end(); ++itr)
 					{
 						auto dependentType = itr->mKey;							
-							
 						if (dependentType->IsIncomplete())
 						{								
 							BF_ASSERT(dependentType->IsDeleting() || dependentType->IsOnDemand() || !dependentType->HasBeenReferenced() || !madeFullPass || dependentType->IsSpecializedByAutoCompleteMethod());
 						}
 					}
+#endif
 					
 					depType->mDependencyMap.mFlagsUnion = BfDependencyMap::DependencyFlag_None;
 
@@ -3196,15 +3197,19 @@ void BfCompiler::UpdateRevisedTypes()
 			break;
 
 		// Partials combiner				
-		auto outerTypeDefEntry = mSystem->mTypeDefs.mHashHeads[bucketIdx];
-		while (outerTypeDefEntry != NULL)
+		auto outerTypeDefEntryIdx = mSystem->mTypeDefs.mHashHeads[bucketIdx];
+		while (outerTypeDefEntryIdx != -1)
 		{
+			// Make sure we can fit a composite without reallocating
+			mSystem->mTypeDefs.EnsureFreeCount(1);
+
+			auto outerTypeDefEntry = &mSystem->mTypeDefs.mEntries[outerTypeDefEntryIdx];
 			auto outerTypeDef = outerTypeDefEntry->mValue;
 
 			if (outerTypeDef->mDefState == BfTypeDef::DefState_Deleted)
 			{
 				hadChanges = true;
-				outerTypeDefEntry = outerTypeDefEntry->mNext;
+				outerTypeDefEntryIdx = mSystem->mTypeDefs.mEntries[outerTypeDefEntryIdx].mNext;
 				continue;
 			}
 
@@ -3228,14 +3233,14 @@ void BfCompiler::UpdateRevisedTypes()
 				// Initialize mPartialUsed flags
 				if (!hadPartials)
 				{
-					auto checkTypeDefEntry = mSystem->mTypeDefs.mHashHeads[bucketIdx];
-					while (checkTypeDefEntry != NULL)
+					auto checkTypeDefEntryIdx = mSystem->mTypeDefs.mHashHeads[bucketIdx];
+					while (checkTypeDefEntryIdx != -1)
 					{	
 						// This clears the mPartialUsed flag for the whole bucket
- 						auto checkTypeDef = checkTypeDefEntry->mValue;
+ 						auto checkTypeDef = mSystem->mTypeDefs.mEntries[checkTypeDefEntryIdx].mValue;
 						if ((checkTypeDef->mIsPartial) || (checkTypeDef->mIsCombinedPartial))
 							checkTypeDef->mPartialUsed = false;
-						checkTypeDefEntry = checkTypeDefEntry->mNext;
+						checkTypeDefEntryIdx = mSystem->mTypeDefs.mEntries[checkTypeDefEntryIdx].mNext;
 					}
 					hadPartials = true;
 				}
@@ -3246,11 +3251,12 @@ void BfCompiler::UpdateRevisedTypes()
 			if ((outerTypeDef->mTypeCode == BfTypeCode_Extension) && (!outerTypeDef->mPartialUsed))
 			{								
 				// Find root type, and we assume the composite type follows this
-				auto checkTypeDefEntry = mSystem->mTypeDefs.mHashHeads[bucketIdx];
-				while (checkTypeDefEntry != NULL)
-				{						
+				auto checkTypeDefEntryIdx = mSystem->mTypeDefs.mHashHeads[bucketIdx];
+				while (checkTypeDefEntryIdx != -1)
+				{	
+					auto checkTypeDefEntry = &mSystem->mTypeDefs.mEntries[checkTypeDefEntryIdx];
 					auto checkTypeDef = checkTypeDefEntry->mValue;
-					if ((checkTypeDefEntry->mHash != outerTypeDefEntry->mHash) ||
+					if ((checkTypeDefEntry->mHashCode != outerTypeDefEntry->mHashCode) ||
 						(checkTypeDef->mIsCombinedPartial) ||
 						(checkTypeDef->mTypeCode == BfTypeCode_Extension) ||
 						(checkTypeDef->mDefState == BfTypeDef::DefState_Deleted) ||
@@ -3259,7 +3265,7 @@ void BfCompiler::UpdateRevisedTypes()
 						(checkTypeDef->mGenericParamDefs.size() != outerTypeDef->mGenericParamDefs.size()) ||
 						(!outerTypeDef->mProject->ContainsReference(checkTypeDef->mProject)))
 					{
-						checkTypeDefEntry = checkTypeDefEntry->mNext;
+						checkTypeDefEntryIdx = checkTypeDefEntry->mNext;
 						continue;
 					}
 
@@ -3274,7 +3280,7 @@ void BfCompiler::UpdateRevisedTypes()
 						compositeProject = rootTypeDef->mProject;
 					}
 					
-					checkTypeDefEntry = checkTypeDefEntry->mNext;
+					checkTypeDefEntryIdx = checkTypeDefEntry->mNext;
 
 					if (compositeTypeDef != NULL)
 					{
@@ -3297,18 +3303,19 @@ void BfCompiler::UpdateRevisedTypes()
 				compositeProject = rootTypeDef->mProject;
 				
 				// Find composite type, there is no explicit position for this
-				auto checkTypeDefEntry = mSystem->mTypeDefs.mHashHeads[bucketIdx];
-				while (checkTypeDefEntry != NULL)
+				auto checkTypeDefEntryIdx = mSystem->mTypeDefs.mHashHeads[bucketIdx];
+				while (checkTypeDefEntryIdx != -1)
 				{						
+					auto checkTypeDefEntry = &mSystem->mTypeDefs.mEntries[checkTypeDefEntryIdx];
 					auto checkTypeDef = checkTypeDefEntry->mValue;
 
-					if ((checkTypeDefEntry->mHash != outerTypeDefEntry->mHash) ||						
+					if ((checkTypeDefEntry->mHashCode != outerTypeDefEntry->mHashCode) ||						
 						(checkTypeDef->mPartialUsed) ||
 						(checkTypeDef->mDefState == BfTypeDef::DefState_Deleted) ||
 						(!checkTypeDef->NameEquals(outerTypeDef)) ||
 						(checkTypeDef->mGenericParamDefs.size() != outerTypeDef->mGenericParamDefs.size()))
 					{
-						checkTypeDefEntry = checkTypeDefEntry->mNext;
+						checkTypeDefEntryIdx = checkTypeDefEntry->mNext;
 						continue;
 					}
 
@@ -3339,13 +3346,13 @@ void BfCompiler::UpdateRevisedTypes()
 							}
  						}
 
-						checkTypeDefEntry = checkTypeDefEntry->mNext;
+						checkTypeDefEntryIdx = checkTypeDefEntry->mNext;
 						continue;
 					}
 
 					if (!rootTypeDef->mProject->ContainsReference(checkTypeDef->mProject))
 					{
-						checkTypeDefEntry = checkTypeDefEntry->mNext;
+						checkTypeDefEntryIdx = checkTypeDefEntry->mNext;
 						continue;
 					}
 
@@ -3362,7 +3369,7 @@ void BfCompiler::UpdateRevisedTypes()
 						if (compositeTypeDef->mDefState != BfTypeDef::DefState_Deleted)
 							compositeTypeDef->mDefState = BfTypeDef::DefState_Defined;
 					}
-					checkTypeDefEntry = checkTypeDefEntry->mNext;
+					checkTypeDefEntryIdx = checkTypeDefEntry->mNext;
 				}
 			}
 
@@ -3375,12 +3382,16 @@ void BfCompiler::UpdateRevisedTypes()
 
 				if (compositeTypeDef == NULL)
 				{
-					if ((rootTypeDef->mIsExplicitPartial) || (rootTypeDefEntry->mNext == NULL) || 
-						(!rootTypeDefEntry->mNext->mValue->mIsCombinedPartial) ||
-						(rootTypeDefEntry->mNext->mValue->mTypeCode != rootTypeDef->mTypeCode) ||
-						(rootTypeDefEntry->mNext->mValue->mIsFunction != rootTypeDef->mIsFunction) ||
-						(rootTypeDefEntry->mNext->mValue->mIsDelegate != rootTypeDef->mIsDelegate) ||
-						(rootTypeDefEntry->mNext->mValue->mGenericParamDefs.size() != rootTypeDef->mGenericParamDefs.size()))
+					BfTypeDefMap::Entry* nextEntry = NULL;
+					if (rootTypeDefEntry->mNext != -1)
+						nextEntry = &mSystem->mTypeDefs.mEntries[rootTypeDefEntry->mNext];
+
+					if ((rootTypeDef->mIsExplicitPartial) || (nextEntry == NULL) ||
+						(!nextEntry->mValue->mIsCombinedPartial) ||
+						(nextEntry->mValue->mTypeCode != rootTypeDef->mTypeCode) ||
+						(nextEntry->mValue->mIsFunction != rootTypeDef->mIsFunction) ||
+						(nextEntry->mValue->mIsDelegate != rootTypeDef->mIsDelegate) ||
+						(nextEntry->mValue->mGenericParamDefs.size() != rootTypeDef->mGenericParamDefs.size()))
 					{
 						compositeTypeDef = new BfTypeDef();
 						compositeTypeDef->mSystem = rootTypeDef->mSystem;
@@ -3418,8 +3429,8 @@ void BfCompiler::UpdateRevisedTypes()
 					}
 					else
 					{
-						BF_ASSERT(rootTypeDefEntry->mNext->mValue->NameEquals(rootTypeDef));
-						compositeTypeDef = rootTypeDefEntry->mNext->mValue;
+						BF_ASSERT(nextEntry->mValue->NameEquals(rootTypeDef));
+						compositeTypeDef = nextEntry->mValue;
 						if (rootTypeDef != NULL)
 						{
 							BF_ASSERT(rootTypeDef->mFullNameEx == compositeTypeDef->mFullNameEx);
@@ -3448,9 +3459,10 @@ void BfCompiler::UpdateRevisedTypes()
 				// Collect the partials
 				BfSizedVector<BfTypeDef*, 8> typeParts;
 				typeParts.push_back(rootTypeDef);
-				auto checkTypeDefEntry = mSystem->mTypeDefs.mHashHeads[bucketIdx];				
-				while (checkTypeDefEntry != NULL)
+				auto checkTypeDefEntryIdx = mSystem->mTypeDefs.mHashHeads[bucketIdx];				
+				while (checkTypeDefEntryIdx != -1)
 				{
+					auto checkTypeDefEntry = &mSystem->mTypeDefs.mEntries[checkTypeDefEntryIdx];
 					auto checkTypeDef = checkTypeDefEntry->mValue;
 
 					bool isValidProject = checkTypeDef->mProject->ContainsReference(compositeProject);
@@ -3464,7 +3476,7 @@ void BfCompiler::UpdateRevisedTypes()
 							(checkTypeDef->mGenericParamDefs.size() != rootTypeDef->mGenericParamDefs.size()) ||
 							(!isValidProject))
 						{
-							checkTypeDefEntry = checkTypeDefEntry->mNext;
+							checkTypeDefEntryIdx = checkTypeDefEntry->mNext;
 							continue;
 						}
 					}
@@ -3498,7 +3510,7 @@ void BfCompiler::UpdateRevisedTypes()
 							partialsHadChanges = true;
 					}
 
-					checkTypeDefEntry = checkTypeDefEntry->mNext;
+					checkTypeDefEntryIdx = checkTypeDefEntry->mNext;
 				}
 				// Set this down here, because the InjectNewRevision will clear this flag
 				rootTypeDef->mIsPartial = true;
@@ -3631,7 +3643,7 @@ void BfCompiler::UpdateRevisedTypes()
 				}
 			}			
 
-			outerTypeDefEntry = outerTypeDefEntry->mNext;
+			outerTypeDefEntryIdx = outerTypeDefEntry->mNext;
 		}
 
 		// Handle unused partials, apply any new revisions, process pending deletes
@@ -3641,11 +3653,16 @@ void BfCompiler::UpdateRevisedTypes()
 			BfTypeDef* checkMasterTypeDef = NULL;
 			BfTypeDef* deletedCombinedPartial = NULL;
 
-			outerTypeDefEntry = mSystem->mTypeDefs.mHashHeads[bucketIdx];
-			while (outerTypeDefEntry != NULL)
+			outerTypeDefEntryIdx = mSystem->mTypeDefs.mHashHeads[bucketIdx];
+			while (outerTypeDefEntryIdx != -1)
 			{
+				auto outerTypeDefEntry = &mSystem->mTypeDefs.mEntries[outerTypeDefEntryIdx];
 				auto outerTypeDef = outerTypeDefEntry->mValue;
-				auto nextTypeDefEntry = outerTypeDefEntry->mNext;
+				auto nextTypeDefEntryIdx = outerTypeDefEntry->mNext;
+
+				BfTypeDefMap::Entry* nextTypeDefEntry = NULL;
+				if (nextTypeDefEntryIdx != -1)
+					nextTypeDefEntry = &mSystem->mTypeDefs.mEntries[nextTypeDefEntryIdx];
 
 				if ((outerTypeDef->mIsPartial) && (!outerTypeDef->mIsExplicitPartial) && (outerTypeDef->mTypeCode != BfTypeCode_Extension) &&
 					(nextTypeDefEntry != NULL) && (!nextTypeDefEntry->mValue->mPartialUsed))
@@ -3695,7 +3712,7 @@ void BfCompiler::UpdateRevisedTypes()
 					}					
 				}
 
-				outerTypeDefEntry = nextTypeDefEntry;				
+				outerTypeDefEntryIdx = nextTypeDefEntryIdx;
 			}
 		}
 	}
@@ -5616,7 +5633,7 @@ void BfCompiler::PopulateReified()
 		BfLogSysM("PopulateReified iteration start\n");
 
 		Array<BfType*> typeList;
-		typeList.Reserve(context->mResolvedTypes.mCount);
+		typeList.Reserve(context->mResolvedTypes.GetCount());
 		for (auto type : context->mResolvedTypes)
 			typeList.Add(type);
 
@@ -6155,7 +6172,7 @@ void BfCompiler::HotResolve_AddActiveMethod(const StringImpl& methodName)
 {
 	BfLogSysM("HotResolve_AddActiveMethod %s\n", methodName.c_str());
 
-	String mangledName;
+	StringT<512> mangledName;
 	int hotCompileIdx = 0;
 	
 	int tabIdx = (int)methodName.IndexOf('\t');
@@ -7730,7 +7747,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
 	}	
 
 	UpdateCompletion();
-	mStats.mTotalTypes = mContext->mResolvedTypes.mCount;
+	mStats.mTotalTypes = mContext->mResolvedTypes.GetCount();
 
 	String compileInfo;
 	if (mIsResolveOnly)

+ 19 - 14
IDEHelper/Compiler/BfContext.cpp

@@ -207,7 +207,8 @@ void BfContext::AssignModule(BfType* type)
 		}
 		else
 		{
-			String moduleName = GenerateModuleName(typeInst);
+			StringT<256> moduleName;
+			GenerateModuleName(typeInst, moduleName);
 			module = new BfModule(this, moduleName);
 			module->mIsReified = typeInst->mIsReified;			
 			module->mProject = project;
@@ -1936,7 +1937,7 @@ void BfContext::UpdateAfterDeletingTypes()
 		auto itr = mResolvedTypes.begin();
 		while (itr != mResolvedTypes.end())
 		{
-			auto type = itr.mCurEntry->mValue;
+			auto type = mResolvedTypes.mEntries[itr.mCurEntry].mValue;
 
 			bool doDelete = false;
 			//BfLogSysM("Removing entry\n");
@@ -2659,7 +2660,7 @@ void BfContext::VerifyTypeLookups(BfTypeInstance* typeInst)
 	}
 }
 
-void BfContext::GenerateModuleName_TypeInst(BfTypeInstance* typeInst, String& name)
+void BfContext::GenerateModuleName_TypeInst(BfTypeInstance* typeInst, StringImpl& name)
 {
 	auto resolveModule = typeInst->mIsReified ? mScratchModule : mUnreifiedModule;
 	auto outerType = resolveModule->GetOuterType(typeInst);
@@ -2708,7 +2709,7 @@ void BfContext::GenerateModuleName_TypeInst(BfTypeInstance* typeInst, String& na
 	}
 }
 
-void BfContext::GenerateModuleName_Type(BfType* type, String& name)
+void BfContext::GenerateModuleName_Type(BfType* type, StringImpl& name)
 {
 	if ((!name.empty()) && (name[name.length() - 1] != '_'))
 		name += '_';
@@ -2817,9 +2818,8 @@ void BfContext::GenerateModuleName_Type(BfType* type, String& name)
 	}	
 }
 
-String BfContext::GenerateModuleName(BfTypeInstance* typeInst)
-{	
-	String name;	
+void BfContext::GenerateModuleName(BfTypeInstance* typeInst, StringImpl& name)
+{		
 	GenerateModuleName_Type(typeInst, name);
 
 	int maxChars = 80;
@@ -2834,16 +2834,21 @@ String BfContext::GenerateModuleName(BfTypeInstance* typeInst)
 		if (c == '@')
 			name[i] = '_';
 	}
-
-	String tryName = name;
+	
 	for (int i = 2; true; i++)
 	{
-		if (!mUsedModuleNames.Contains(ToUpper(tryName)))
-			return tryName;
-		tryName = name + StrFormat("_%d", i);
+		StringT<256> upperName = name;
+		MakeUpper(upperName);
+		if (!mUsedModuleNames.Contains(upperName))
+			return;
+		if (i > 2)
+		{
+			int lastUnderscore = (int)name.LastIndexOf('_');
+			if (lastUnderscore != -1)
+				name.RemoveToEnd(lastUnderscore);
+		}
+		name += StrFormat("_%d", i);
 	}
-
-	return name;
 }
 
 bool BfContext::IsSentinelMethod(BfMethodInstance* methodInstance)

+ 3 - 3
IDEHelper/Compiler/BfContext.h

@@ -448,9 +448,9 @@ public:
 	void DeleteType(BfType* type, bool deferDepRebuilds = false);
 	void UpdateAfterDeletingTypes();
 	void VerifyTypeLookups(BfTypeInstance* typeInst);		
-	void GenerateModuleName_TypeInst(BfTypeInstance* typeInst, String& name);
-	void GenerateModuleName_Type(BfType* type, String& name);
-	String GenerateModuleName(BfTypeInstance* typeInst);
+	void GenerateModuleName_TypeInst(BfTypeInstance* typeInst, StringImpl& name);
+	void GenerateModuleName_Type(BfType* type, StringImpl& name);
+	void GenerateModuleName(BfTypeInstance* typeInst, StringImpl& name);
 	bool IsSentinelMethod(BfMethodInstance* methodInstance);
 	void SaveDeletingType(BfType* type);		
 	BfType* FindType(const StringImpl& typeName);

+ 2 - 2
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -12700,7 +12700,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
 	
 	auto _GetInvokeMethodName = [&]()
 	{
-		String methodName = "Invoke$";
+		StringT<512> methodName = "Invoke$";
 		methodName += mModule->mCurMethodInstance->mMethodDef->mName;
 		
 		int prevSepPos = (int)methodName.LastIndexOf('$');
@@ -12734,7 +12734,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
 		methodName += '$';
 		methodName += BfTypeUtils::HashEncode64(hashVal.mLow);
 
-		String mangledName;
+		StringT<512> mangledName;
 		BfMangler::MangleMethodName(mangledName, mModule->mCompiler->GetMangleKind(), mModule->mCurTypeInstance, methodName);
 		return mangledName;
 	};

+ 13 - 11
IDEHelper/Compiler/BfIRBuilder.cpp

@@ -277,7 +277,7 @@ BfIRBlock::BfIRBlock()
 
 BfIRConstHolder::BfIRConstHolder(BfModule* module)
 {
-	mModule = module;
+	mModule = module;	
 }
 
 BfIRConstHolder::~BfIRConstHolder()
@@ -2573,7 +2573,7 @@ BfIRMDNode BfIRBuilder::CreateNamespaceScope(BfType* type, BfIRMDNode fileDIScop
 
 		if (!typeInstance->IsBoxed())
 		{
-			BfAtomComposite curNamespace;
+			BfAtomCompositeT<16> curNamespace;
 			if (typeInstance->IsArray())
 			{
 				auto arrayType = (BfArrayType*)typeInstance;
@@ -2958,7 +2958,7 @@ void BfIRBuilder::CreateTypeDeclaration(BfType* type, bool forceDbgDefine)
 					diForwardDecl = DbgCreateReplaceableCompositeType(llvm::dwarf::DW_TAG_structure_type,
 						typeName, curDIScope, fileDIScope, 0, (int64)0 * 8, (int64)0 * 8, flags);
 					auto derivedFrom = DbgGetTypeInst(mModule->mContext->mBfObjectType);
-					llvm::SmallVector<BfIRMDNode, 8> diFieldTypes;					
+					SizedArray<BfIRMDNode, 8> diFieldTypes;					
 					auto inheritanceType = DbgCreateInheritance(diForwardDecl, derivedFrom, 0, llvm::DINode::FlagPublic);
 					diFieldTypes.push_back(inheritanceType);
 					DbgMakePermanent(diForwardDecl, derivedFrom, diFieldTypes);
@@ -3081,7 +3081,7 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
 	
 	//BF_ASSERT(WantsDbgDefinition(type));
 	
-	llvm::SmallVector<BfIRMDNode, 8> diFieldTypes;
+	SizedArray<BfIRMDNode, 256> diFieldTypes;
 
 	int packing = 0;
 	bool isUnion = false;
@@ -3448,8 +3448,8 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
 			}
 
 			String methodName = methodDef->mName;
-			llvm::SmallVector<BfIRMDNode, 1> genericArgs;
-			llvm::SmallVector<BfIRValue, 1> genericConstValueArgs;
+			SizedArray<BfIRMDNode, 1> genericArgs;
+			SizedArray<BfIRValue, 1> genericConstValueArgs;
 			auto diFunction = DbgCreateMethod(funcScope, methodName, mangledName, fileDIScope,
 				defLine + 1, diFuncType, false, false,
 				(methodInstance->mVirtualTableIdx != -1) ? 1 : 0,
@@ -3602,13 +3602,13 @@ void BfIRBuilder::CreateTypeDefinition_Data(BfModule* populateModule, BfTypeInst
 	bool isGlobalContainer = typeDef->IsGlobalsContainer();
 
 	auto diForwardDecl = DbgGetTypeInst(typeInstance);
-	llvm::SmallVector<BfIRType, 8> irFieldTypes;
+	SizedArray<BfIRType, 256> irFieldTypes;
 	if ((!typeInstance->IsTypedPrimitive()) && (typeInstance->mBaseType != NULL))
 	{
 		irFieldTypes.push_back(MapTypeInst(typeInstance->mBaseType, BfIRPopulateType_Eventually_Full));
 	}
 
-	llvm::SmallVector<BfIRMDNode, 8> diFieldTypes;
+	SizedArray<BfIRMDNode, 256> diFieldTypes;
 
 	int packing = 0;
 	bool isUnion = false;
@@ -3625,7 +3625,7 @@ void BfIRBuilder::CreateTypeDefinition_Data(BfModule* populateModule, BfTypeInst
 
 		if (!elementType->IsValuelessType())
 		{
-			irFieldTypes.push_back(MapType(elementType, elementType->IsValueType() ? BfIRPopulateType_Eventually_Full : BfIRPopulateType_Declaration));
+			irFieldTypes.Add(MapType(elementType, elementType->IsValueType() ? BfIRPopulateType_Eventually_Full : BfIRPopulateType_Declaration));
 		}
 	}
 	else
@@ -5293,7 +5293,9 @@ BfIRFunction BfIRBuilder::CreateFunction(BfIRFunctionType funcType, BfIRLinkageT
 
 	BfIRFunction retVal = WriteCmd(BfIRCmd_CreateFunction, funcType, (uint8)linkageType, name);	
 	NEW_CMD_INSERTED_IRVALUE;	
-	mFunctionMap[name] = retVal;
+
+	StringView nameSV = StringView(AllocStr(name), name.mLength);
+	mFunctionMap[nameSV] = retVal;
 
 	//BfLogSys(mModule->mSystem, "BfIRBuilder::CreateFunction: %d %s Module:%p\n", retVal.mId, name.c_str(), mModule);
 
@@ -5926,7 +5928,7 @@ BfIRMDNode BfIRBuilder::DbgCreateSubroutineType(BfMethodInstance* methodInstance
 	auto methodDef = methodInstance->mMethodDef;
 	auto typeInstance = methodInstance->GetOwner();
 
-	llvm::SmallVector<BfIRMDNode, 8> diParams;
+	SizedArray<BfIRMDNode, 32> diParams;
 	diParams.push_back(DbgGetType(methodInstance->mReturnType));
 
 	BfType* thisType = NULL;

+ 1 - 1
IDEHelper/Compiler/BfIRBuilder.h

@@ -1019,7 +1019,7 @@ public:
 	bool mHasDebugInfo;
 	bool mHasDebugLineInfo;
 	Dictionary<BfMethodRef, BfIRFunctionType> mMethodTypeMap;
-	Dictionary<String, BfIRFunction> mFunctionMap;	
+	Dictionary<StringView, BfIRFunction> mFunctionMap;
 	Dictionary<BfType*, BfIRPopulateType> mTypeMap;
 	Dictionary<int, BfIRValue> mConstMemMap;
 	Array<BfTypeInstance*> mDITemporaryTypes;	

+ 59 - 30
IDEHelper/Compiler/BfModule.cpp

@@ -213,7 +213,12 @@ BfMethodState::~BfMethodState()
 	}
 	
 	for (auto local : mLocals)
-		delete local;
+	{
+		if (local->mIsBumpAlloc)
+			local->~BfLocalVariable();
+		else
+			delete local;
+	}
 
 	for (auto& kv : mLambdaCache)
 		delete kv.mValue;
@@ -856,7 +861,11 @@ BfModule::BfModule(BfContext* context, const StringImpl& moduleName)
 	mContext = context;
 	mModuleName = moduleName;
 	if (!moduleName.empty())
-		mContext->mUsedModuleNames.Add(ToUpper(moduleName));
+	{
+		StringT<256> upperModuleName = moduleName;
+		MakeUpper(upperModuleName);
+		mContext->mUsedModuleNames.Add(upperModuleName);
+	}
 	mAddedToCount = false;
 
 	mParentModule = NULL;
@@ -1912,7 +1921,10 @@ void BfModule::RestoreScoreState_LocalVariables()
 			mCurMethodState->mLocalVarSet.Remove(BfLocalVarEntry(localVar));
 		}
 
-		delete localVar;
+		if (localVar->mIsBumpAlloc)
+			localVar->~BfLocalVariable();
+		else
+			delete localVar;
 	}
 }
 
@@ -4029,7 +4041,7 @@ void BfModule::CreateStaticField(BfFieldInstance* fieldInstance, bool isThreadLo
 	else			
 	{
 		BfLogSysM("Creating static field Module:%p Type:%p\n", this, fieldType);
-		StringT<128> staticVarName;
+		StringT<4096> staticVarName;
 		BfMangler::Mangle(staticVarName, mCompiler->GetMangleKind(), fieldInstance);
 		if ((!fieldType->IsValuelessType()) && (!staticVarName.StartsWith("#")))
 		{
@@ -5300,7 +5312,7 @@ BfIRValue BfModule::CreateClassVDataExtGlobal(BfTypeInstance* declTypeInst, BfTy
 
 	PopulateType(declTypeInst, BfPopulateType_DataAndMethods);
 	PopulateType(implTypeInst, BfPopulateType_DataAndMethods);
-	StringT<128> classVDataName;
+	StringT<512> classVDataName;
 	BfMangler::MangleStaticFieldName(classVDataName, mCompiler->GetMangleKind(), implTypeInst, "bf_hs_replace_VDataExt");
 	if (declTypeInst != implTypeInst)
 	{
@@ -5385,7 +5397,7 @@ BfIRValue BfModule::CreateTypeDataRef(BfType* type)
 	auto typeTypeInst = typeTypeDef->ToTypeInstance();
 	auto typeInstance = type->ToTypeInstance();
 
-	StringT<128> typeDataName;
+	StringT<4096> typeDataName;
 	if (typeInstance != NULL)
 	{
 		BfMangler::MangleStaticFieldName(typeDataName, mCompiler->GetMangleKind(), typeInstance, "sBfTypeData");
@@ -5739,7 +5751,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 	FixConstValueParams(mContext->mBfObjectType, typeValueParams);
 	BfIRValue objectData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(mContext->mBfObjectType, BfIRPopulateType_Full), typeValueParams);
 
-	StringT<128> typeDataName;
+	StringT<512> typeDataName;
 	if ((typeInstance != NULL) && (!typeInstance->IsTypeAlias()))
 	{
 		BfMangler::MangleStaticFieldName(typeDataName, mCompiler->GetMangleKind(), typeInstance, "sBfTypeData");
@@ -5981,7 +5993,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 		PopulateType(typeInstance, BfPopulateType_DataAndMethods);
 	
 	BfTypeDef* typeDef = typeInstance->mTypeDef;
-	StringT<128> mangledName;
+	StringT<512> mangledName;
 	BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), typeInstance, typeInstance->mModule);
 	
 	if (!mIsComptimeModule)
@@ -6018,7 +6030,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 	if (typeInstance->mSlotNum >= 0)
 	{
 		// For interfaces we ONLY emit the slot num				
-		StringT<128> slotVarName;
+		StringT<512> slotVarName;
 		BfMangler::MangleStaticFieldName(slotVarName, mCompiler->GetMangleKind(), typeInstance, "sBfSlotOfs");
 		auto intType = GetPrimitiveType(BfTypeCode_Int32);
 		auto slotNumVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapType(intType), true, BfIRLinkageType_External,
@@ -6485,7 +6497,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 			BfIRValue ifaceMethodExtVar;
 			if ((!ifaceMethodExtData.IsEmpty()) && (!mIsComptimeModule))
 			{
-				StringT<128> classVDataName;
+				StringT<512> classVDataName;
 				BfMangler::MangleStaticFieldName(classVDataName, mCompiler->GetMangleKind(), typeInstance, "bf_hs_replace_IFaceExt");
 				auto arrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->GetPrimitiveType(BfTypeCode_NullPtr), (int)ifaceMethodExtData.size());
 				ifaceMethodExtVar = mBfIRBuilder->CreateGlobalVariable(arrayType, true,
@@ -8542,7 +8554,7 @@ BfGenericParamType* BfModule::GetGenericParamType(BfGenericParamKind paramKind,
 
 	BfResolvedTypeSet::LookupContext lookupCtx;
 	lookupCtx.mModule = this;
-	BfResolvedTypeSet::Entry* typeEntry = NULL;
+	BfResolvedTypeSet::EntryRef typeEntry;
 	auto inserted = mContext->mResolvedTypes.Insert(genericParamType, &lookupCtx, &typeEntry);
 	BF_ASSERT(inserted);
 	typeEntry->mValue = genericParamType;
@@ -10690,7 +10702,7 @@ BfIRValue BfModule::CreateFunctionFrom(BfMethodInstance* methodInstance, bool tr
 	}
 
 	auto methodDef = methodInstance->mMethodDef;
-	StringT<128> methodName;
+	StringT<4096> methodName;
 	BfMangler::Mangle(methodName, mCompiler->GetMangleKind(), methodInstance);
 	if (isInlined != methodInstance->mAlwaysInline)
 	{
@@ -13983,7 +13995,7 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
 						
 						if ((!mBfIRBuilder->mIgnoreWrites) && (methodInstance->mDeclModule != NULL))
 						{
-							StringT<128> mangledName;
+							StringT<512> mangledName;
 							BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), methodInstance);
 							bool isIntrinsic = false;
 							SetupIRFunction(methodInstance, mangledName, false, &isIntrinsic);
@@ -14479,7 +14491,7 @@ BfIRValue BfModule::GetInterfaceSlotNum(BfTypeInstance* ifaceType)
 		// This is necessary to reify the interface type
 		PopulateType(ifaceType);		
 		
-		StringT<128> slotVarName;
+		StringT<512> slotVarName;
 		BfMangler::MangleStaticFieldName(slotVarName, mCompiler->GetMangleKind(), ifaceType, "sBfSlotOfs");
 		BfType* intType = GetPrimitiveType(BfTypeCode_Int32);				
 		BfIRValue value;
@@ -14670,7 +14682,7 @@ BfTypedValue BfModule::ReferenceStaticField(BfFieldInstance* fieldInstance)
 	}
 	else
 	{				
-		StringT<128> staticVarName;
+		StringT<512> staticVarName;
 		BfMangler::Mangle(staticVarName, mCompiler->GetMangleKind(), fieldInstance);
 
 		auto typeType = fieldInstance->GetResolvedType();
@@ -15018,6 +15030,12 @@ void BfModule::DoAddLocalVariable(BfLocalVariable* localVar)
 		localVar->mName.Remove(0);
 	}
 
+	if (mCurMethodState->mLocals.mAllocSize == 0)
+	{
+		mCurMethodState->mLocals.Reserve(16);
+		mCurMethodState->mLocalVarSet.Reserve(16);
+	}
+
 	localVar->mLocalVarIdx = (int)mCurMethodState->mLocals.size();
 	mCurMethodState->mLocals.push_back(localVar);
 
@@ -15712,7 +15730,7 @@ void BfModule::EmitDeferredScopeCalls(bool useSrcPositions, BfScopeData* scopeDa
 				}
 			}
 
-			std::unordered_set<BfDeferredCallEntry*> handledSet;
+			HashSet<BfDeferredCallEntry*> handledSet;
 			BfDeferredCallEntry* deferredCallEntry = checkScope->mDeferredCallEntries.mHead;
 			while (deferredCallEntry != NULL)
 			{
@@ -15732,13 +15750,14 @@ void BfModule::EmitDeferredScopeCalls(bool useSrcPositions, BfScopeData* scopeDa
 
 				if (deferredCallEntry->mDeferredBlock != NULL)
 				{
-					auto itr = handledSet.insert(deferredCallEntry);
-					if (!itr.second)
+					BfDeferredCallEntry** entryPtr = NULL;
+					if (!handledSet.TryAdd(deferredCallEntry, &entryPtr))
 					{
 						// Already handled, can happen if we defer again within the block
 						deferredCallEntry = deferredCallEntry->mNext;
-						continue;
+						continue;					
 					}
+
 					auto prevHead = checkScope->mDeferredCallEntries.mHead;
 					EmitDeferredCall(*deferredCallEntry, true);
 					if (prevHead != checkScope->mDeferredCallEntries.mHead)
@@ -16993,7 +17012,7 @@ BfIRValue BfModule::CreateDllImportGlobalVar(BfMethodInstance* methodInstance, b
 		return BfIRValue();
 	}
 
-	String name = "bf_hs_preserve@";
+	StringT<512> name = "bf_hs_preserve@";
 	BfMangler::Mangle(name, mCompiler->GetMangleKind(), methodInstance);
 	name += "__imp";
 	
@@ -18446,14 +18465,17 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp
 	if ((!mIsComptimeModule) && (argIdx == methodInstance->GetStructRetIdx()))
 		argIdx++;
 
+	auto rootMethodState = mCurMethodState->GetRootMethodState();
+
 	if (!methodDef->mIsStatic)
 	{
 		BfTypeCode loweredTypeCode = BfTypeCode_None;
 		BfTypeCode loweredTypeCode2 = BfTypeCode_None;
 
-		BfLocalVariable* paramVar = new BfLocalVariable();
+		BfLocalVariable* paramVar = rootMethodState->mBumpAlloc.Alloc<BfLocalVariable>();
+		paramVar->mIsBumpAlloc = true;
 		paramVar->mResolvedType = thisType;
-		paramVar->mName = "this";
+		paramVar->mName.Reference("this");
 		if (!thisType->IsValuelessType())
 			paramVar->mValue = mBfIRBuilder->GetArgument(argIdx);
 		else
@@ -18525,7 +18547,8 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp
 	{		
 		// We already issues a type error for this param if we had one in declaration processing
 		SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true);
-		BfLocalVariable* paramVar = new BfLocalVariable();
+		BfLocalVariable* paramVar = rootMethodState->mBumpAlloc.Alloc<BfLocalVariable>();
+		paramVar->mIsBumpAlloc = true;
 
 		BfTypeCode loweredTypeCode = BfTypeCode_None;
 		BfTypeCode loweredTypeCode2 = BfTypeCode_None;
@@ -18542,7 +18565,8 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp
 		PopulateType(resolvedType, BfPopulateType_Declaration);
 		paramVar->mResolvedType = resolvedType;
 		int namePrefixCount = 0;
-		paramVar->mName = methodInstance->GetParamName(paramIdx, namePrefixCount);
+		methodInstance->GetParamName(paramIdx, paramVar->mName, namePrefixCount);
+
 		paramVar->mNamePrefixCount = (uint8)namePrefixCount;
 		paramVar->mNameNode = methodInstance->GetParamNameNode(paramIdx);
 		if (!isParamSkipped)
@@ -18774,7 +18798,12 @@ void BfModule::ProcessMethod_ProcessDeferredLocals(int startIdx)
 		mCurMethodState->mLocalMethods.Clear();
 
 		for (auto& local : mCurMethodState->mLocals)
-			delete local;
+		{
+			if (local->mIsBumpAlloc)
+				local->~BfLocalVariable();
+			else
+				delete local;
+		}
 		mCurMethodState->mLocals.Clear();
 		mCurMethodState->mLocalVarSet.Clear();
 	};
@@ -19225,7 +19254,7 @@ void BfModule::EmitGCMarkMembers()
 
 						if ((fieldDef->mIsStatic) && (!fieldDef->mIsConst))
 						{
-							StringT<128> staticVarName;
+							StringT<512> staticVarName;
 							BfMangler::Mangle(staticVarName, mCompiler->GetMangleKind(), &fieldInst);
 							if (staticVarName.StartsWith('#'))
 								continue;
@@ -19582,7 +19611,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
 		return;				
 	}
 
-	StringT<128> mangledName;
+	StringT<512> mangledName;
 	BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), mCurMethodInstance);
 	if (!methodInstance->mIRFunction)
 	{						
@@ -21509,7 +21538,7 @@ String BfModule::GetLocalMethodName(const StringImpl& baseName, BfAstNode* ancho
 	{
 		for (auto methodGenericArg : rootMethodState->mMethodInstance->mMethodInfoEx->mMethodGenericArguments)
 		{
-			StringT<128> genericTypeName;
+			StringT<512> genericTypeName;
 			BfMangler::Mangle(genericTypeName, mCompiler->GetMangleKind(), methodGenericArg);
 			hashCtx.MixinStr(genericTypeName);
 		}
@@ -23688,7 +23717,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
 		}		
 	}
 
-	StringT<128> mangledName;
+	StringT<4096> mangledName;
 	BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), mCurMethodInstance);
 
 	for (int paramIdx = 0; paramIdx < methodInstance->GetParamCount(); paramIdx++)
@@ -24155,7 +24184,7 @@ void BfModule::UniqueSlotVirtualMethod(BfMethodInstance* methodInstance)
 			if (implBaseType != NULL)
 				vTableStart = implBaseType->mVirtualMethodTableSize;
 
-			StringT<128> mangledName;
+			StringT<512> mangledName;
 			BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), methodInstance);
 			for (int checkIdxOfs = 0; checkIdxOfs < (int)typeInstance->mHotTypeData->mVTableEntries.size(); checkIdxOfs++)
 			{

+ 5 - 6
IDEHelper/Compiler/BfModule.h

@@ -188,6 +188,7 @@ public:
 	bool mUsedImplicitly; // Passed implicitly to a local method, capture by ref if we can	
 	bool mNotCaptured;
 	bool mIsConst;
+	bool mIsBumpAlloc;
 	BfLocalVariable* mShadowedLocal;
 
 public:
@@ -219,6 +220,7 @@ public:
 		mUsedImplicitly = false;
 		mNotCaptured = false;
 		mIsConst = false;
+		mIsBumpAlloc = false;
 		mShadowedLocal = NULL;
 	}
 
@@ -1053,8 +1055,7 @@ public:
 	bool mAllowUinitReads;
 	bool mDisableReturns;
 	bool mCancelledDeferredCall;	
-	bool mNoObjectAccessChecks;
-	bool mHadIgnoredError;
+	bool mNoObjectAccessChecks;		
 	int mCurLocalVarId; // Can also refer to a label
 	int mCurAccessId; // For checking to see if a block reads from or writes to a local
 
@@ -1062,9 +1063,7 @@ public:
 	BfMethodState()
 	{
 		mLocals.mAlloc = &mBumpAlloc;
-		mLocals.Reserve(8);
-		mLocalVarSet.mAlloc = &mBumpAlloc;
-		mLocalVarSet.Reserve(8);
+		mLocalVarSet.mAlloc = &mBumpAlloc;		
 		
 		mMethodInstance = NULL;		
 		mPrevMethodState = NULL;
@@ -1093,7 +1092,7 @@ public:
 		mAllowUinitReads = false;
 		mDisableReturns = false;
 		mCancelledDeferredCall = false;
-		mNoObjectAccessChecks = false;
+		mNoObjectAccessChecks = false;		
 		mInDeferredBlock = false;		
 		mDeferredLocalAssignData = NULL;
 		mCurLocalVarId = 0;

+ 38 - 38
IDEHelper/Compiler/BfModuleTypeUtils.cpp

@@ -851,8 +851,8 @@ void BfModule::CheckMemberNames(BfTypeInstance* typeInst)
 	struct MemberRef
 	{
 		BfMemberDef* mMemberDef;
-		String mName;
-		String mKindName;
+		StringView mName;
+		StringView mKindName;
 		BfTypeInstance* mTypeInst;
 		BfAstNode* mNameNode;
 		BfProtection mProtection;
@@ -920,13 +920,13 @@ void BfModule::CheckMemberNames(BfTypeInstance* typeInst)
 		checkType = checkType->mBaseType;
 	}
 
-	Dictionary<String, MemberRef> memberMap;
+	Dictionary<StringView, MemberRef> memberMap;
 	memberMap.Reserve(memberList.size());
 
 	for (int i = (int)memberList.size() - 1; i >= 0; i--)
 	{
 		MemberRef& memberRef = memberList[i];
-		if (memberRef.mName.empty())
+		if (memberRef.mName.IsEmpty())
 			continue;
 		if ((memberRef.mTypeInst == typeInst) && (!memberRef.mIsOverride))
 		{
@@ -944,7 +944,7 @@ void BfModule::CheckMemberNames(BfTypeInstance* typeInst)
 				{
 					if ((prevMemberRef->mProtection != BfProtection_Private) && (memberRef.mNameNode != NULL))
 					{
-						error = Warn(BfWarning_CS0108_MemberHidesInherited, StrFormat("%s hides inherited member '%s'. Use the 'new' keyword if hiding was intentional.", prevMemberRef->mKindName.c_str(), memberRef.mName.c_str()), memberRef.mNameNode, true);
+						error = Warn(BfWarning_CS0108_MemberHidesInherited, StrFormat("%s hides inherited member '%s'. Use the 'new' keyword if hiding was intentional.", String(prevMemberRef->mKindName).c_str(), String(memberRef.mName).c_str()), memberRef.mNameNode, true);
 						showPrevious = true;
 					}
 				}
@@ -995,7 +995,7 @@ void BfModule::CheckMemberNames(BfTypeInstance* typeInst)
 					}
 
 					if (secondMemberRef->mNameNode != NULL)
-						error = Fail(StrFormat("A %s named '%s' has already been declared.", secondMemberRef->mKindName.c_str(), memberRef.mName.c_str()), secondMemberRef->mNameNode, true);
+						error = Fail(StrFormat("A %s named '%s' has already been declared.", String(secondMemberRef->mKindName).c_str(), String(memberRef.mName).c_str()), secondMemberRef->mNameNode, true);
 					showPrevious = true;
 					typeInst->mHasDeclError = true;
 				}
@@ -3185,7 +3185,7 @@ void BfModule::DoPopulateType_InitSearches(BfTypeInstance* typeInstance)
 					{
 						String checkNamespaceStr;
 						typeRef->ToString(checkNamespaceStr);
-						BfAtomComposite checkNamespace;
+						BfAtomCompositeT<16> checkNamespace;
 						if (mSystem->ParseAtomComposite(checkNamespaceStr, checkNamespace))
 						{
 							if (mSystem->ContainsNamespace(checkNamespace, typeDef->mProject))
@@ -7263,7 +7263,7 @@ BfMethodRefType* BfModule::CreateMethodRefType(BfMethodInstance* methodInstance,
 
 	BfResolvedTypeSet::LookupContext lookupCtx;
 	lookupCtx.mModule = this;
-	BfResolvedTypeSet::Entry* typeEntry = NULL;
+	BfResolvedTypeSet::EntryRef typeEntry;
 	auto inserted = mContext->mResolvedTypes.Insert(methodRefType, &lookupCtx, &typeEntry);
 	if (typeEntry->mValue == NULL)
 	{	
@@ -7992,7 +7992,7 @@ BfTypeDef* BfModule::GetCombinedPartialTypeDef(BfTypeDef* typeDef)
 	BF_ASSERT(!typeDef->mIsExplicitPartial);
 	if (!typeDef->mIsPartial)
 		return typeDef;
-	auto result = mSystem->FindTypeDef(typeDef->mFullName.ToString(), (int)typeDef->mGenericParamDefs.size());
+	auto result = mSystem->FindTypeDef(typeDef->mFullName, (int)typeDef->mGenericParamDefs.size(), NULL, {}, NULL, BfFindTypeDefFlag_None);
 	return result;
 }
 
@@ -8780,10 +8780,10 @@ BfType* BfModule::ResolveType(BfType* lookupType, BfPopulateType populateType, B
 	BfResolvedTypeSet::LookupContext lookupCtx;
 	lookupCtx.mModule = this;	
 	lookupCtx.mResolveFlags = resolveFlags;
-	BfResolvedTypeSet::Entry* resolvedEntry = NULL;
+	BfResolvedTypeSet::EntryRef resolvedEntry;
 	bool inserted = mContext->mResolvedTypes.Insert(lookupType, &lookupCtx, &resolvedEntry);	
 
-	if (resolvedEntry == NULL)
+	if (!resolvedEntry)
 		return NULL;
 
 	if (!inserted)
@@ -9667,7 +9667,7 @@ BfTypeDef* BfModule::FindTypeDef(const BfAtomComposite& findName, int numGeneric
 
 			if (!checkNamespace.IsEmpty())
 			{
-				BfAtomComposite atomComposite;
+				BfAtomCompositeT<16> atomComposite;
 				if (mSystem->ParseAtomComposite(checkNamespace, atomComposite))
 					namespaceSearch.Add(atomComposite);
 			}
@@ -9693,7 +9693,7 @@ BfTypeDef* BfModule::FindTypeDef(const BfAtomComposite& findName, int numGeneric
 	}
 
 	BfTypeLookupEntry typeLookupEntry;
-	typeLookupEntry.mName = findName;
+	typeLookupEntry.mName.Reference(findName);
 	typeLookupEntry.mNumGenericParams = numGenericArgs;
 	typeLookupEntry.mUseTypeDef = useTypeDef;
 
@@ -9918,7 +9918,7 @@ bool BfModule::ValidateTypeWildcard(BfAstNode* typeRef, bool isAttributeRef)
 			StringT<128> leftNameStr;
 
 			BfType* leftType = NULL;
-			BfAtomComposite leftComposite;
+			BfAtomCompositeT<16> leftComposite;
 
 			qualifiedTypeRef->mLeft->ToString(leftNameStr);
 			if (!mSystem->ParseAtomComposite(leftNameStr, leftComposite))
@@ -9982,11 +9982,11 @@ bool BfModule::ValidateTypeWildcard(BfAstNode* typeRef, bool isAttributeRef)
 	if (!_ToString(typeRef, true))
 		return false;
 
-	BfAtomComposite composite;
+	BfAtomCompositeT<16> composite;
 	if (!mSystem->ParseAtomComposite(name, composite))
 		return false;
 
-	BfAtomComposite compositeEx;	
+	BfAtomCompositeT<16> compositeEx;
 	if (!mSystem->ParseAtomComposite(nameEx, compositeEx))
 		return false;
 	
@@ -10939,13 +10939,13 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 	lookupCtx.mRootTypeRef = typeRef;
 	lookupCtx.mRootTypeDef = typeDef;
 	lookupCtx.mModule = this;
-	BfResolvedTypeSet::Entry* resolvedEntry = NULL;
+	BfResolvedTypeSet::EntryRef resolvedEntry;
 	if (auto delegateTypeRef = BfNodeDynCastExact<BfDelegateTypeRef>(typeRef))
 		GetDelegateTypeRefAttributes(delegateTypeRef, lookupCtx.mCallingConvention);	
 
 	auto inserted = mContext->mResolvedTypes.Insert(typeRef, &lookupCtx, &resolvedEntry);	
 
-	if (resolvedEntry == NULL)
+	if (!resolvedEntry)
 	{
 		if (lookupCtx.mHadVar)
 			return ResolveTypeResult(typeRef, GetPrimitiveType(BfTypeCode_Var), populateType, resolveFlags);
@@ -10984,7 +10984,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 			BfPrimitiveType* primType = new BfPrimitiveType();
 			primType->mTypeDef = typeDef;
 			resolvedEntry->mValue = primType;
-			BF_ASSERT(BfResolvedTypeSet::Hash(primType, &lookupCtx, false) == resolvedEntry->mHash);
+			BF_ASSERT(BfResolvedTypeSet::Hash(primType, &lookupCtx, false) == resolvedEntry->mHashCode);
 			populateModule->InitType(primType, populateType);
 			return ResolveTypeResult(typeRef, primType, populateType, resolveFlags);
 		}
@@ -11045,7 +11045,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 				resolvedEntry->mValue = genericTypeInst;
 				populateModule->InitType(genericTypeInst, populateType);
 #ifdef _DEBUG
-				if (BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx) != resolvedEntry->mHash)
+				if (BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx) != resolvedEntry->mHashCode)
 				{
 					int refHash = BfResolvedTypeSet::Hash(typeRef, &lookupCtx);
 					int typeHash = BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx);
@@ -11088,14 +11088,14 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 
 		populateModule->InitType(typeInst, populateType);
 		
-		if (BfResolvedTypeSet::Hash(typeInst, &lookupCtx) != resolvedEntry->mHash)
+		if (BfResolvedTypeSet::Hash(typeInst, &lookupCtx) != resolvedEntry->mHashCode)
 		{
 			int refHash = BfResolvedTypeSet::Hash(typeRef, &lookupCtx);
 			int typeHash = BfResolvedTypeSet::Hash(typeInst, &lookupCtx);
 			BF_ASSERT(refHash == typeHash);
 		}
 		{
-			BF_ASSERT(BfResolvedTypeSet::Hash(typeInst, &lookupCtx) == resolvedEntry->mHash);
+			BF_ASSERT(BfResolvedTypeSet::Hash(typeInst, &lookupCtx) == resolvedEntry->mHashCode);
 		}		
 		return ResolveTypeResult(typeRef, typeInst, populateType, resolveFlags);
 	}	
@@ -11141,7 +11141,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 					arrayType->mElementCountSource = typedVal.mType;
 					resolvedEntry->mValue = arrayType;
 
-					BF_ASSERT(BfResolvedTypeSet::Hash(arrayType, &lookupCtx) == resolvedEntry->mHash);
+					BF_ASSERT(BfResolvedTypeSet::Hash(arrayType, &lookupCtx) == resolvedEntry->mHashCode);
 					populateModule->InitType(arrayType, populateType);
 					return ResolveTypeResult(typeRef, arrayType, populateType, resolveFlags);
 				}
@@ -11175,7 +11175,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 			arrayType->mGenericDepth = elementType->GetGenericDepth() + 1;
 			resolvedEntry->mValue = arrayType;
 
-			BF_ASSERT(BfResolvedTypeSet::Hash(arrayType, &lookupCtx) == resolvedEntry->mHash);
+			BF_ASSERT(BfResolvedTypeSet::Hash(arrayType, &lookupCtx) == resolvedEntry->mHashCode);
 			populateModule->InitType(arrayType, populateType);
 			return ResolveTypeResult(typeRef, arrayType, populateType, resolveFlags);
 		}
@@ -11190,7 +11190,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 
 		CheckUnspecializedGenericType(arrayType, populateType);
 
-		BF_ASSERT(BfResolvedTypeSet::Hash(arrayType, &lookupCtx) == resolvedEntry->mHash);
+		BF_ASSERT(BfResolvedTypeSet::Hash(arrayType, &lookupCtx) == resolvedEntry->mHashCode);
 		populateModule->InitType(arrayType, populateType);
 		return ResolveTypeResult(typeRef, arrayType, populateType, resolveFlags);
 	}
@@ -11388,22 +11388,22 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 		populateModule->InitType(genericTypeInst, populateType);
 
 #ifdef _DEBUG
-		if (BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx) != resolvedEntry->mHash)
+		if (BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx) != resolvedEntry->mHashCode)
 		{
 			int refHash = BfResolvedTypeSet::Hash(typeRef, &lookupCtx);
 			int typeHash = BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx);
 			BF_ASSERT(refHash == typeHash);
-			BF_ASSERT(refHash == resolvedEntry->mHash);
+			BF_ASSERT(refHash == resolvedEntry->mHashCode);
 		}
 		if (!BfResolvedTypeSet::Equals(genericTypeInst, typeRef, &lookupCtx))
 		{
 			BF_ASSERT(BfResolvedTypeSet::Equals(genericTypeInst, typeRef, &lookupCtx));
 		}
 
-		BfLogSysM("Generic type %p typeHash: %8X\n", genericTypeInst, resolvedEntry->mHash);
+		BfLogSysM("Generic type %p typeHash: %8X\n", genericTypeInst, resolvedEntry->mHashCode);
 #endif
 
-		BF_ASSERT(BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx) == resolvedEntry->mHash);		
+		BF_ASSERT(BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx) == resolvedEntry->mHashCode);		
 		return ResolveTypeResult(typeRef, genericTypeInst, populateType, resolveFlags);
 	}
 	else if (auto tupleTypeRef = BfNodeDynCast<BfTupleTypeRef>(typeRef))
@@ -11517,7 +11517,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 		}
 				
 		resolvedEntry->mValue = tupleType;
-		BF_ASSERT(BfResolvedTypeSet::Hash(tupleType, &lookupCtx) == resolvedEntry->mHash);
+		BF_ASSERT(BfResolvedTypeSet::Hash(tupleType, &lookupCtx) == resolvedEntry->mHashCode);
 		populateModule->InitType(tupleType, populateType);
 
 		return ResolveTypeResult(typeRef, tupleType, populateType, resolveFlags);
@@ -11548,7 +11548,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 
 		resolvedEntry->mValue = genericTypeInst;
 #ifdef _DEBUG
-		if (BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx) != resolvedEntry->mHash)
+		if (BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx) != resolvedEntry->mHashCode)
 		{
 			int refHash = BfResolvedTypeSet::Hash(typeRef, &lookupCtx);
 			int typeHash = BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx);
@@ -11575,7 +11575,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 		resolvedEntry->mValue = pointerType;
 
 		//int hashVal = mContext->mResolvedTypes.Hash(typeRef, &lookupCtx);
-		BF_ASSERT(BfResolvedTypeSet::Hash(pointerType, &lookupCtx) == resolvedEntry->mHash);
+		BF_ASSERT(BfResolvedTypeSet::Hash(pointerType, &lookupCtx) == resolvedEntry->mHashCode);
 
 		populateModule->InitType(pointerType, populateType);
 		return ResolveTypeResult(typeRef, pointerType, populateType, resolveFlags);
@@ -11604,7 +11604,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 		resolvedEntry->mValue = refType;
 		
 #ifdef _DEBUG
-		if (BfResolvedTypeSet::Hash(refType, &lookupCtx) != resolvedEntry->mHash)
+		if (BfResolvedTypeSet::Hash(refType, &lookupCtx) != resolvedEntry->mHashCode)
 		{
 			int refHash = BfResolvedTypeSet::Hash(typeRef, &lookupCtx, BfResolvedTypeSet::BfHashFlag_AllowRef);
 			int typeHash = BfResolvedTypeSet::Hash(refType, &lookupCtx);
@@ -11879,7 +11879,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 			AddDependency(paramType, delegateType, BfDependencyMap::DependencyFlag_ParamOrReturnValue);
 
 #ifdef _DEBUG
-		if (BfResolvedTypeSet::Hash(delegateType, &lookupCtx) != resolvedEntry->mHash)
+		if (BfResolvedTypeSet::Hash(delegateType, &lookupCtx) != resolvedEntry->mHashCode)
 		{
 			int refHash = BfResolvedTypeSet::Hash(typeRef, &lookupCtx);
 			int typeHash = BfResolvedTypeSet::Hash(delegateType, &lookupCtx);			
@@ -11888,7 +11888,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 		BF_ASSERT(BfResolvedTypeSet::Equals(delegateType, typeRef, &lookupCtx));
 #endif
 
-		BF_ASSERT(BfResolvedTypeSet::Hash(delegateType, &lookupCtx) == resolvedEntry->mHash);
+		BF_ASSERT(BfResolvedTypeSet::Hash(delegateType, &lookupCtx) == resolvedEntry->mHashCode);
 
 		return ResolveTypeResult(typeRef, delegateType, populateType, resolveFlags);
 	}
@@ -11896,7 +11896,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 	{
 		auto genericParamType = GetGenericParamType(genericParamTypeRef->mGenericParamKind, genericParamTypeRef->mGenericParamIdx);
 		resolvedEntry->mValue = genericParamType;
-		BF_ASSERT(BfResolvedTypeSet::Hash(genericParamType, &lookupCtx) == resolvedEntry->mHash);
+		BF_ASSERT(BfResolvedTypeSet::Hash(genericParamType, &lookupCtx) == resolvedEntry->mHashCode);
 		return ResolveTypeResult(typeRef, genericParamType, populateType, resolveFlags);
 	}
 	else if (auto retTypeTypeRef = BfNodeDynCast<BfModifiedTypeRef>(typeRef))
@@ -11908,7 +11908,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 		BF_ASSERT(retTypeType->mElementType);
 
 		resolvedEntry->mValue = retTypeType;
-		BF_ASSERT(BfResolvedTypeSet::Hash(retTypeType, &lookupCtx) == resolvedEntry->mHash);
+		BF_ASSERT(BfResolvedTypeSet::Hash(retTypeType, &lookupCtx) == resolvedEntry->mHashCode);
 
 		populateModule->InitType(retTypeType, populateType);
 		return ResolveTypeResult(typeRef, retTypeType, populateType, resolveFlags);
@@ -11952,7 +11952,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 
 		resolvedEntry->mValue = constExprType;
 #ifdef _DEBUG
-		if (BfResolvedTypeSet::Hash(constExprType, &lookupCtx) != resolvedEntry->mHash)
+		if (BfResolvedTypeSet::Hash(constExprType, &lookupCtx) != resolvedEntry->mHashCode)
 		{
 			int refHash = BfResolvedTypeSet::Hash(typeRef, &lookupCtx);
 			int typeHash = BfResolvedTypeSet::Hash(constExprType, &lookupCtx);			

+ 3 - 3
IDEHelper/Compiler/BfNamespaceVisitor.cpp

@@ -15,7 +15,7 @@ void BfNamespaceVisitor::Visit(BfUsingDirective* usingDirective)
 	}
 	
 	String usingString = usingDirective->mNamespace->ToString();
-	BfAtomComposite usingComposite;
+	BfAtomCompositeT<16> usingComposite;
 	mSystem->ParseAtomComposite(usingString, usingComposite);
 
 	if (mResolvePassData->mAutoComplete != NULL)
@@ -45,14 +45,14 @@ void BfNamespaceVisitor::Visit(BfUsingModDirective* usingDirective)
 	
 	String usingString = useNode->ToString();
 	
-	BfAtomComposite usingComposite;
+	BfAtomCompositeT<16> usingComposite;
 	if (mSystem->ParseAtomComposite(usingString, usingComposite))
 		mResolvePassData->HandleNamespaceReference(useNode, usingComposite);
 }
 
 void BfNamespaceVisitor::Visit(BfNamespaceDeclaration* namespaceDeclaration)
 {
-	BfAtomComposite prevNamespace = mNamespace;
+	BfAtomCompositeT<16> prevNamespace = mNamespace;
 	
 	if (namespaceDeclaration->mNameNode == NULL)
 		return;

+ 12 - 12
IDEHelper/Compiler/BfResolvedTypeUtils.cpp

@@ -1026,13 +1026,13 @@ void BfMethodInstance::GetParamName(int paramIdx, StringImpl& name, int& namePre
 			invokeMethodInstance->GetParamName(methodParam->mDelegateParamIdx, name, namePrefixCount);
 		return;
 	}
-	name = paramDef->mName;
+	name.Reference(paramDef->mName);
 	namePrefixCount = paramDef->mNamePrefixCount;
 }
 
 String BfMethodInstance::GetParamName(int paramIdx)
 {	
-	String paramName;
+	StringT<256> paramName;
 	int namePrefixCount = 0;
 	GetParamName(paramIdx, paramName, namePrefixCount);
 	return paramName;
@@ -1040,7 +1040,7 @@ String BfMethodInstance::GetParamName(int paramIdx)
 
 String BfMethodInstance::GetParamName(int paramIdx, int& namePrefixCount)
 {
-	String paramName;
+	StringT<256> paramName;
 	GetParamName(paramIdx, paramName, namePrefixCount);
 	return paramName;
 }
@@ -4875,9 +4875,9 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfAstNode* rhs, LookupContext* ctx)
 	return false;
 }
 
-void BfResolvedTypeSet::RemoveEntry(BfResolvedTypeSet::Entry* entry)
+void BfResolvedTypeSet::RemoveEntry(BfResolvedTypeSet::EntryRef entry)
 {
- 	int hashIdx = (entry->mHash & 0x7FFFFFFF) % mHashSize;
+ 	int hashIdx = (entry->mHashCode & 0x7FFFFFFF) % mHashSize;
 // 	if (entry->mPrev == NULL)
 // 	{
 // 		if (entry->mNext != NULL)
@@ -4896,23 +4896,23 @@ void BfResolvedTypeSet::RemoveEntry(BfResolvedTypeSet::Entry* entry)
 
 	bool found = false;
 
-	Entry** srcCheckEntryPtr = &this->mHashHeads[hashIdx];
-	Entry* checkEntry = *srcCheckEntryPtr;
-	while (checkEntry != NULL)
+	int* srcCheckEntryPtr = &this->mHashHeads[hashIdx];
+	int checkEntryIdx = *srcCheckEntryPtr;
+	while (checkEntryIdx != -1)
 	{
-		if (checkEntry == entry)
+		auto checkEntry = &mEntries[checkEntryIdx];
+		if (checkEntryIdx == entry.mIndex)
 		{
-			this->mCount--;
 			*srcCheckEntryPtr = checkEntry->mNext;
 			found = true;						
 		}
 		srcCheckEntryPtr = &checkEntry->mNext;
-		checkEntry = checkEntry->mNext;
+		checkEntryIdx = checkEntry->mNext;
 	}
 	
 	BF_ASSERT(found);
 	BF_ASSERT(entry->mValue == NULL);
-	Deallocate(entry);		
+	FreeIdx(entry.mIndex);
 }
 
 // BfResolvedTypeSet::Iterator BfResolvedTypeSet::begin()

+ 12 - 20
IDEHelper/Compiler/BfResolvedTypeUtils.h

@@ -2152,7 +2152,6 @@ public:
 	}
 };
 
-
 class BfBoxedType : public BfTypeInstance
 {
 public:
@@ -2664,14 +2663,13 @@ public:
 public:
 	BfResolvedTypeSet()
 	{
-		mHashSize = 9973;
-		mHashHeads = (Entry**)AllocateZero(sizeof(Entry*) * mHashSize, alignof(Entry*));
+		Rehash(9973);
 	}	
 
 	~BfResolvedTypeSet();
 	
 	template <typename T>
-	bool Insert(T* findType, LookupContext* ctx, BfResolvedTypeSet::Entry** entryPtr)
+	bool Insert(T* findType, LookupContext* ctx, BfResolvedTypeSet::EntryRef* entryPtr)
 	{
 		CheckRehash();
 
@@ -2691,17 +2689,19 @@ public:
 			return false;
 		}
 		int bucket = (hashVal & 0x7FFFFFFF) % mHashSize;
-		auto checkEntry = mHashHeads[bucket];
-		while (checkEntry != NULL)
-		{			
+		auto checkEntryIdx = mHashHeads[bucket];
+		while (checkEntryIdx != -1)
+		{
+			auto checkEntry = &mEntries[checkEntryIdx];
+
 			// checkEntry->mType can be NULL if we're in the process of filling it in (and this Insert is from an element type)
 			//  OR if the type resolution failed after node insertion
-			if ((checkEntry->mValue != NULL) && (hashVal == checkEntry->mHash) && (Equals(checkEntry->mValue, findType, ctx)))
+			if ((checkEntry->mValue != NULL) && (hashVal == checkEntry->mHashCode) && (Equals(checkEntry->mValue, findType, ctx)))
 			{
-				*entryPtr = checkEntry;
+				*entryPtr = EntryRef(this, checkEntryIdx);
 				return false;
 			}
-			checkEntry = checkEntry->mNext;
+			checkEntryIdx = checkEntry->mNext;
 
 			tryCount++;
 			// If this fires off, this may indicate that our hashes are equivalent but Equals fails
@@ -2715,22 +2715,14 @@ public:
 		if ((ctx->mResolveFlags & BfResolveTypeRefFlag_NoCreate) != 0)
 			return false;
 
-		mCount++;
-		Entry* entry = (Entry*)BfResolvedTypeSetFuncs::Allocate(sizeof(Entry), alignof(Entry));
-		entry->mValue = NULL;
-// 		if (mHashHeads[bucket] != NULL)
-// 			mHashHeads[bucket]->mPrev = entry;
-		entry->mNext = mHashHeads[bucket];
-		entry->mHash = hashVal;
-		mHashHeads[bucket] = entry;
-		*entryPtr = entry;
+		*entryPtr = AddRaw(hashVal);			 		
 		return true;
 	}
 	
 // 	Iterator begin();
 // 	Iterator end();
 // 	Iterator erase(Iterator& itr);
-	void RemoveEntry(Entry* entry);
+	void RemoveEntry(EntryRef entry);
 };
 
 class BfTypeUtils

+ 41 - 13
IDEHelper/Compiler/BfSystem.cpp

@@ -2504,7 +2504,7 @@ BfTypeDef* BfSystem::FindTypeDef(const BfAtomComposite& findName, int numGeneric
 
 	// This searched globals, but we were already doing that down below at the LAST step.  Right?
 	BfTypeDef* foundTypeDef = NULL;	
-	BfAtomComposite qualifiedFindName;
+	BfAtomCompositeT<16> qualifiedFindName;
 
 	int foundPri = (int)0x80000000;
 	for (int namespaceIdx = 0; namespaceIdx <= (int) namespaceSearch.size(); namespaceIdx++)
@@ -2512,14 +2512,16 @@ BfTypeDef* BfSystem::FindTypeDef(const BfAtomComposite& findName, int numGeneric
 		int curNamespacePri = 0;
 		if (namespaceIdx < (int)namespaceSearch.size())
 		{ 
-			auto& namespaceDeclaration = namespaceSearch[namespaceIdx];			
+			auto& namespaceDeclaration = namespaceSearch[namespaceIdx];
 			qualifiedFindName.Set(namespaceDeclaration, findName);
 		}
 		else
 		{			
 			qualifiedFindName = findName;
 		}
-				
+	
+		int partialStartEntryIdx = -1;
+
 		auto itr = mTypeDefs.TryGet(qualifiedFindName);		
 		while (itr)
 		{
@@ -2528,10 +2530,39 @@ BfTypeDef* BfSystem::FindTypeDef(const BfAtomComposite& findName, int numGeneric
 			if ((typeDef->mIsPartial) || 
 				((typeDef->IsGlobalsContainer()) && ((flags & BfFindTypeDefFlag_AllowGlobal) == 0)))
 			{
-				itr.MoveToNextHashMatch();
-				continue;
+				bool handled = false;
+				if (itr.mCurEntry < mTypeDefs.mPartialSkipCache.mSize)
+				{
+					auto& entry = mTypeDefs.mPartialSkipCache[itr.mCurEntry];
+					if (entry.mRevision == mTypeDefs.mRevision)
+					{
+						if (entry.mIndex == -1)
+						{
+							// No non-partial here
+							break;
+						}
+
+						itr.mCurEntry = entry.mIndex;
+						typeDef = *itr;
+						handled = true;
+					}
+				}
+
+				if (!handled)
+				{
+					if (partialStartEntryIdx == -1)
+						partialStartEntryIdx = itr.mCurEntry;
+					itr.MoveToNextHashMatch();
+					continue;
+				}
 			}
 			
+			if ((partialStartEntryIdx != -1) && ((flags & BfFindTypeDefFlag_AllowGlobal) == 0))
+			{
+				mTypeDefs.SetPartialSkipCache(partialStartEntryIdx, itr.mCurEntry);
+				partialStartEntryIdx = -1;
+			}
+
 			if ((typeDef->mFullName == qualifiedFindName) && (CheckTypeDefReference(typeDef, project)))
 			{
 				int curPri = curNamespacePri;				
@@ -2556,6 +2587,9 @@ BfTypeDef* BfSystem::FindTypeDef(const BfAtomComposite& findName, int numGeneric
 			}
 			itr.MoveToNextHashMatch();
 		}
+
+		if ((partialStartEntryIdx != -1) && ((flags & BfFindTypeDefFlag_AllowGlobal) == 0))
+			mTypeDefs.SetPartialSkipCache(partialStartEntryIdx, -1);
 	}	
 
 	// Didn't match the correct number of generic params, but let the compiler complain
@@ -2647,16 +2681,10 @@ bool BfSystem::FindTypeDef(const BfAtomComposite& findName, int numGenericArgs,
 
 BfTypeDef* BfSystem::FindTypeDef(const StringImpl& typeName, int numGenericArgs, BfProject* project, const Array<BfAtomComposite>& namespaceSearch, BfTypeDef** ambiguousTypeDef, BfFindTypeDefFlags flags)
 {
-	BfAtomComposite qualifiedFindName;
-	BfAtom* tempData[16];
-	qualifiedFindName.mAllocSize = 16;
-	qualifiedFindName.mParts = tempData;
-	
+	BfAtomCompositeT<16> qualifiedFindName;	
 	BfTypeDef* result = NULL;
 	if (ParseAtomComposite(typeName, qualifiedFindName))
-		result = FindTypeDef(qualifiedFindName, numGenericArgs, project, namespaceSearch, ambiguousTypeDef, flags);
-	if (qualifiedFindName.mParts == tempData)
-		qualifiedFindName.mParts = NULL;
+		result = FindTypeDef(qualifiedFindName, numGenericArgs, project, namespaceSearch, ambiguousTypeDef, flags);	
 	return result;
 }
 

+ 104 - 4
IDEHelper/Compiler/BfSystem.h

@@ -44,7 +44,6 @@ class BfProject;
 class BfTypeDef;
 
 struct BfTypeDefMapFuncs;
-typedef MultiHashSet<BfTypeDef*, BfTypeDefMapFuncs> BfTypeDefMap;
 typedef HashSet<BfProject*> BfProjectSet;
 
 class BfAtom
@@ -107,6 +106,33 @@ public:
 	uint32 GetAtomUpdateIdx();
 };
 
+template <const int TBufSize>
+class BfAtomCompositeT : public BfAtomComposite
+{
+public:
+	BfAtom* mInternalBuffer[TBufSize];
+
+public:
+	BfAtomCompositeT()
+	{
+		mAllocSize = (int16)TBufSize;
+		mParts = mInternalBuffer;
+	}
+
+	BfAtomCompositeT(const BfAtomComposite& rhs)
+	{
+		mAllocSize = (int16)TBufSize;
+		mParts = mInternalBuffer;
+		*this = rhs;
+	}
+
+	BfAtomCompositeT& operator=(const BfAtomComposite& rhs)
+	{
+		Set(rhs.mParts, rhs.mSize, NULL, 0);
+		return *this;
+	}
+};
+
 class BfSizedAtomComposite : public BfAtomComposite
 {
 public:
@@ -1245,6 +1271,79 @@ struct BfTypeDefMapFuncs : public MultiHashSetFuncs
 	}
 };
 
+class BfTypeDefMap : public MultiHashSet<BfTypeDef*, BfTypeDefMapFuncs>
+{
+public:
+	struct SkipEntry
+	{
+	public:
+		int mIndex;
+		int mRevision;
+
+	public:
+		SkipEntry()
+		{
+			mIndex = -1;
+			mRevision = -1;			
+		}
+
+		SkipEntry(int index, int revision)
+		{
+			mIndex = index;
+			mRevision = revision;
+		}
+	};
+
+	Array<SkipEntry> mPartialSkipCache;
+	int mRevision;
+
+public:
+	BfTypeDefMap()
+	{
+		mRevision = 1;
+	}
+
+	void Add(BfTypeDef* value)
+	{
+		MultiHashSet::Add(value);
+		mRevision++;
+	}
+
+	void AddAfter(BfTypeDef* value, Entry* afterEntry)
+	{
+		MultiHashSet::AddAfter(value, afterEntry);
+		mRevision++;
+	}
+
+	template <typename TKey>
+	bool Remove(const TKey& key)
+	{
+		bool result = MultiHashSet::Remove(key);
+		mRevision++;
+		return result;
+	}
+
+	Iterator Erase(const Iterator& itr)
+	{
+		auto result = MultiHashSet::Erase(itr);
+		mRevision++;
+		return result;
+	}
+
+	void Clear()
+	{
+		MultiHashSet::Clear();
+		mRevision++;
+	}
+
+	void SetPartialSkipCache(int partialIdx, int mapToIdx)
+	{
+		while (partialIdx >= mPartialSkipCache.mSize)
+			mPartialSkipCache.Add(SkipEntry());
+		mPartialSkipCache[partialIdx] = SkipEntry(mapToIdx, mRevision);
+	}
+};
+
 enum BfTargetType
 {
 	BfTargetType_BeefConsoleApplication,
@@ -1663,7 +1762,7 @@ public:
 	int mHighestYieldTime;
 	// The following are protected by mSystemLock - can only be accessed by the compiling thread
 	Dictionary<String, BfTypeDef*> mSystemTypeDefs;	
-	BfTypeDefMap mTypeDefs;	
+	BfTypeDefMap mTypeDefs;		
 	bool mNeedsTypesHandledByCompiler;
 	BumpAllocator mAlloc;	
 	int mAtomCreateIdx;	
@@ -1727,7 +1826,7 @@ public:
 	void ReleaseAtomComposite(const BfAtomComposite& atomComposite);	
 	void SanityCheckAtomComposite(const BfAtomComposite& atomComposite);
 	void TrackName(BfTypeDef* typeDef);
-	void UntrackName(BfTypeDef* typeDef);
+	void UntrackName(BfTypeDef* typeDef);	
 
 	bool ParseAtomComposite(const StringView& name, BfAtomComposite& composite, bool addRefs = false);
 
@@ -1747,7 +1846,8 @@ public:
 	BfTypeDef* FindTypeDef(const StringImpl& typeName, int numGenericArgs = 0, BfProject* project = NULL, const Array<BfAtomComposite>& namespaceSearch = Array<BfAtomComposite>(), BfTypeDef** ambiguousTypeDef = NULL, BfFindTypeDefFlags flags = BfFindTypeDefFlag_None);
 	BfTypeDef* FindTypeDef(const StringImpl& typeName, BfProject* project);
 	BfTypeDef* FindTypeDefEx(const StringImpl& typeName);
-	void FindFixitNamespaces(const StringImpl& typeName, int numGenericArgs, BfProject* project, std::set<String>& fixitNamespaces);	
+	void ClearTypeDefCache();
+	void FindFixitNamespaces(const StringImpl& typeName, int numGenericArgs, BfProject* project, std::set<String>& fixitNamespaces);		
 
 	void RemoveTypeDef(BfTypeDef* typeDef);
 	//BfTypeDefMap::Iterator RemoveTypeDef(BfTypeDefMap::Iterator typeDefItr);

+ 1 - 1
IDEHelper/IDEHelper.vcxproj

@@ -218,7 +218,7 @@
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>zBP_DISABLED;WIN32;NDEBUG;_WINDOWS;_USRDLL;IDEHELPER_EXPORTS;BFSYSLIB_DYNAMIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>BP_DISABLED;WIN32;NDEBUG;_WINDOWS;_USRDLL;IDEHELPER_EXPORTS;BFSYSLIB_DYNAMIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>../;../BeefySysLib/platform/win;../BeefySysLib/third_party;..\extern\llvm-project_13_0_1\llvm\include;..\extern\llvm_win64_13_0_1\include;..\extern\llvm-project_13_0_1\llvm\lib\Target;..\extern\llvm_win64_13_0_1\lib\Target\X86;..\extern\llvm-project_13_0_1\llvm\tools\clang\include;..\extern\curl\builds\libcurl-vc15-x64-release-static-zlib-static-ipv6-sspi-winssl\include</AdditionalIncludeDirectories>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <BufferSecurityCheck>false</BufferSecurityCheck>