| 2838 | |
| 2839 | template <typename T> |
| 2840 | bool Insert(T* findType, LookupContext* ctx, BfResolvedTypeSet::EntryRef* entryPtr) |
| 2841 | { |
| 2842 | CheckRehash(); |
| 2843 | |
| 2844 | int tryCount = 0; |
| 2845 | ctx->mFailed = false; |
| 2846 | |
| 2847 | BfHashFlags hashFlags = BfHashFlag_AllowRef; |
| 2848 | if ((ctx->mResolveFlags & (BfResolveTypeRefFlag_AllowGenericParamConstValue | BfResolveTypeRefFlag_AllowImplicitConstExpr)) != 0) |
| 2849 | { |
| 2850 | ctx->mResolveFlags = (BfResolveTypeRefFlags)(ctx->mResolveFlags & ~(BfResolveTypeRefFlag_AllowGenericParamConstValue | BfResolveTypeRefFlag_AllowImplicitConstExpr)); |
| 2851 | hashFlags = (BfHashFlags)(hashFlags | BfHashFlag_AllowGenericParamConstValue); |
| 2852 | } |
| 2853 | |
| 2854 | int hashVal = Hash(findType, ctx, hashFlags); |
| 2855 | if ((ctx->mFailed) || (ctx->mHadVar)) |
| 2856 | { |
| 2857 | return false; |
| 2858 | } |
| 2859 | |
| 2860 | while (true) |
| 2861 | { |
| 2862 | int startAllocSize = mAllocSize; |
| 2863 | int bucket = (hashVal & 0x7FFFFFFF) % mHashSize; |
| 2864 | auto startEntryIdx = mHashHeads[bucket]; |
| 2865 | auto checkEntryIdx = startEntryIdx; |
| 2866 | bool needsRerun = false; |
| 2867 | |
| 2868 | while (checkEntryIdx != -1) |
| 2869 | { |
| 2870 | auto checkEntry = &mEntries[checkEntryIdx]; |
| 2871 | |
| 2872 | // checkEntry->mType can be NULL if we're in the process of filling it in (and this Insert is from an element type) |
| 2873 | // OR if the type resolution failed after node insertion |
| 2874 | if ((checkEntry->mValue != NULL) && (hashVal == checkEntry->mHashCode) && (Equals(checkEntry->mValue, findType, ctx))) |
| 2875 | { |
| 2876 | *entryPtr = EntryRef(this, checkEntryIdx); |
| 2877 | return false; |
| 2878 | } |
| 2879 | |
| 2880 | if ((mAllocSize != startAllocSize) || (startEntryIdx != mHashHeads[bucket])) |
| 2881 | { |
| 2882 | // It's possible for Equals to add types, buckets could be invalid or a new type could |
| 2883 | // have been inserted at the start of our bucket |
| 2884 | needsRerun = true; |
| 2885 | break; |
| 2886 | } |
| 2887 | |
| 2888 | checkEntryIdx = checkEntry->mNext; |
| 2889 | |
| 2890 | tryCount++; |
| 2891 | // If this fires off, this may indicate that our hashes are equivalent but Equals fails |
| 2892 | if (tryCount >= 10) |
| 2893 | { |
| 2894 | NOP; |
| 2895 | } |
| 2896 | BF_ASSERT(tryCount < 10); |
| 2897 | } |
no test coverage detected