diff --git a/src/coreclr/inc/bitvector.h b/src/coreclr/inc/bitvector.h deleted file mode 100644 index b957bdadc5a53e..00000000000000 --- a/src/coreclr/inc/bitvector.h +++ /dev/null @@ -1,463 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - - -/***************************************************************************/ -/* BitVector.h */ -/***************************************************************************/ -// Routines to support a growable bitvector -/***************************************************************************/ - -#ifndef BITVECTOR_H -#define BITVECTOR_H 1 - - -#ifndef LIMITED_METHOD_CONTRACT -#define LIMITED_METHOD_CONTRACT -#define UNDEF_LIMITED_METHOD_CONTRACT -#endif - -#ifndef WRAPPER_NO_CONTRACT -#define WRAPPER_NO_CONTRACT -#define UNDEF_WRAPPER_NO_CONTRACT -#endif - -#ifndef SUPPORTS_DAC -#define SUPPORTS_DAC -#define UNDEF_SUPPORTS_DAC -#endif - -#ifndef _ASSERTE -#define _ASSERTE(x) -#define UNDEF_ASSERTE -#endif - -#ifndef FEATURE_NATIVEAOT -#define USE_BITVECTOR 1 -#endif -#if USE_BITVECTOR - -/* The bitvector class is meant to be a drop in replacement for an integer - (that is you use it like an integer), however it grows as needed. - - Features: - plug compatible with normal integers; - grows as needed - Optimized for the small case when the vector fits in machine word - Uses one machine word if vector fits in machine word (minus a bit) - - Some caveates: - You should use mutator operators &=, |= ... instead of the - non-mutators whenever possible to avoid creating a temps - - Specifically did NOT supply automatic coercions to - and from short types so that the programmer is aware of - when code was being injected on their behalf. The upshot of this - is that you have to use the BitVector() toUnsigned() to convert -*/ - -/***************************************************************************/ - -class BitVector { - // Set this to be unsigned char to do testing, should be UINT_PTR for real life - - typedef UINT_PTR ChunkType; // The size of integer type that the machine can operate on directly -// typedef BYTE ChunkType; // Use for testing - - // Maximum number of bits in our bitvector -#define MAX_PTRARG_OFS 1024 - - enum { - IS_BIG = 1, // The low bit is used to discrimate m_val and m_vals - CHUNK_BITS = sizeof(ChunkType)*8, // The number of bits that we can manipuate as a chunk - SMALL_BITS = CHUNK_BITS - 1, // The number of bits we can fit in the small representation -// SMALL_BITS = 5, // TESTING ONLY: The number of bits we can fit in the small representation - VALS_COUNT = MAX_PTRARG_OFS / CHUNK_BITS, // The number of ChunkType elements in the Vals array - }; - -public: - BitVector() - { - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - m_val = 0; - } - - BOOL isBig() const - { - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - return ((m_val & IS_BIG) != 0); - } - - void toBig() - { - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - if (!isBig()) - { - doBigInit(smallBits()); - } - } - - explicit BitVector(ChunkType arg) - { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - if (arg > MaxVal) - { - doBigInit(arg); - } - else - { - m_val = ChunkType(arg << 1); - } - } - - BitVector(ChunkType arg, UINT shift) - { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - if ((arg > MaxVal) || (shift >= SMALL_BITS) || (arg > (MaxVal >> shift))) - { - doBigInit(arg); - doBigLeftShiftAssign(shift); - } - else - { - m_val = ChunkType(arg << (shift+1)); - } - } - -#define CONSTRUCT_ptrArgTP(arg,shift) BitVector((arg), (shift)) - - BitVector(const BitVector& arg) - { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - if (arg.isBig()) - { - doBigInit(arg); - } - else - { - m_val = arg.m_val; - } - } - - void operator <<=(unsigned shift) - { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - if ((m_val == 0) || (shift == 0)) // Zero is a special case, don't need to do anything - return; - - if (isBig() || (shift >= SMALL_BITS) || (m_val > (MaxVal >> (shift-1)))) - { - doBigLeftShiftAssign(shift); - } - else - { - m_val <<= shift; - } - } - - void operator >>=(unsigned shift) - { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - if (isBig()) - { - doBigRightShiftAssign(shift); - } - else - { - m_val >>= shift; - m_val &= ~IS_BIG; // clear the isBig bit if it got set - } - } - - void operator |=(const BitVector& arg) - { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - if (((m_val | arg.m_val) & IS_BIG) != 0) - { - doBigOrAssign(arg); - } - else - { - m_val |= arg.m_val; - } - } - - // Note that this is set difference, not subtration - void operator -=(const BitVector& arg) - { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - if (((m_val | arg.m_val) & IS_BIG) != 0) - { - doBigDiffAssign(arg); - } - else - { - m_val &= ~arg.m_val; - } - } - - void operator &=(const BitVector& arg) - { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - if (((m_val | arg.m_val) & IS_BIG) != 0) - { - doBigAndAssign(arg); - } - else - { - m_val &= arg.m_val; - } - } - - friend void setDiff(BitVector& target, const BitVector& arg) - { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - target -= arg; - } - - friend BOOL intersect(const BitVector& arg1, const BitVector& arg2) - { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - if (((arg1.m_val | arg2.m_val) & IS_BIG) != 0) - { - return arg1.doBigIntersect(arg2); - } - else - { - return ((arg1.m_val & arg2.m_val) != 0); - } - } - - BOOL operator ==(const BitVector& arg) const - { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - if ((m_val | arg.m_val) & IS_BIG) - { - return doBigEquals(arg); - } - else - { - return m_val == arg.m_val; - } - } - - BOOL operator !=(const BitVector& arg) const - { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - return !(*this == arg); - } - - friend ChunkType toUnsigned(const BitVector& arg) - { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - if (arg.isBig()) - { - return arg.m_vals.m_chunks[0]; // Note truncation - } - else - { - return arg.smallBits(); - } - } - - // Note that we require the invariant that zero is always stored in the - // small form so that this works bitvector is zero iff (m_val == 0) - friend BOOL isZero(const BitVector& arg) - { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - return arg.m_val == 0; - } - - /* currently only used in asserts */ - BitVector operator &(const BitVector& arg) const - { - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - BitVector ret = *this; - ret &= arg; - return ret; - } - - int NumBits() const; - -private: - - static const ChunkType MaxVal = ((ChunkType)1 << SMALL_BITS) - 1; // Maximum value that can be stored in m_val - - // This is the structure that we use when the bit vector overflows. - // It is a simple vector. - struct Vals { - unsigned m_encodedLength; // An encoding of the current length of the 'm_chunks' array - ChunkType m_chunks[VALS_COUNT]; - - BOOL isBig() const - { - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - return ((m_encodedLength & IS_BIG) != 0); - } - - unsigned GetLength() const - { - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - if (isBig()) - { - unsigned length = (m_encodedLength >> 1); - _ASSERTE(length > 0); - return length; - } - else - { - return 0; - } - } - - void SetLength(unsigned length) - { - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - _ASSERTE(length > 0); - _ASSERTE(length <= VALS_COUNT); - - m_encodedLength = (ChunkType) (length << 1); - m_encodedLength |= (ChunkType) IS_BIG; - } - }; - - // - // This is the instance data for the bitvector - // - // We discrimininate on this - union { - ChunkType m_val; // if m_val bit 0 is false, then bits 1-N are the bit vector - Vals m_vals; // if m_val bit 1 is true, then use Vals - }; - - - ChunkType smallBits() const - { - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - _ASSERTE(!isBig()); - return (m_val >> 1); - } - -#ifdef STRIKE - void doBigInit(ChunkType arg) {} -#else - void doBigInit(ChunkType arg); -#endif - void doBigInit(const BitVector& arg); - void doBigLeftShiftAssign(unsigned arg); - void doBigRightShiftAssign(unsigned arg); - void doBigDiffAssign(const BitVector&); - void doBigAndAssign(const BitVector&); - void doBigOrAssign(const BitVector& arg); - BOOL doBigEquals(const BitVector&) const; - BOOL doBigIntersect(const BitVector&) const; -}; - -typedef BitVector ptrArgTP; - -#else // !USE_BITVECTOR - -typedef uint64_t ptrArgTP; - - // Maximum number of bits in our bitvector -#define MAX_PTRARG_OFS (sizeof(ptrArgTP) * 8) - -#define CONSTRUCT_ptrArgTP(arg,shift) (((ptrArgTP) (arg)) << (shift)) - -inline BOOL isZero(const ptrArgTP& arg) -{ - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - return (arg == 0); -} - -inline ptrArgTP toUnsigned(const ptrArgTP& arg) -{ - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - return arg; -} - -inline void setDiff(ptrArgTP& target, const ptrArgTP& arg) -{ - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - target &= ~arg; -} - -inline BOOL intersect(const ptrArgTP arg1, const ptrArgTP arg2) -{ - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - return ((arg1 & arg2) != 0); -} - -#endif // !USE_BITVECTOR - -#ifdef UNDEF_LIMITED_METHOD_CONTRACT -#undef LIMITED_METHOD_CONTRACT -#undef UNDEF_LIMITED_METHOD_CONTRACT -#endif - -#ifdef UNDEF_WRAPPER_NO_CONTRACT -#undef WRAPPER_NO_CONTRACT -#undef UNDEF_WRAPPER_NO_CONTRACT -#endif - -#ifdef UNDEF_SUPPORTS_DAC -#undef SUPPORTS_DAC -#undef UNDEF_SUPPORTS_DAC -#endif - -#ifdef UNDEF_ASSERTE -#undef _ASSERTE -#undef UNDEF_ASSERTE -#endif - -#endif // BITVECTOR_H diff --git a/src/coreclr/inc/eetwain.h b/src/coreclr/inc/eetwain.h index 32801bd23c540c..e229ae1fe29d38 100644 --- a/src/coreclr/inc/eetwain.h +++ b/src/coreclr/inc/eetwain.h @@ -28,7 +28,6 @@ #include "regdisp.h" #include "corjit.h" // For NativeVarInfo #include "stackwalktypes.h" -#include "bitvector.h" #include "gcinfotypes.h" #if !defined(TARGET_X86) diff --git a/src/coreclr/inc/gc_unwind_x86.h b/src/coreclr/inc/gc_unwind_x86.h index e5be6b2e4aa43f..2430254e40ea61 100644 --- a/src/coreclr/inc/gc_unwind_x86.h +++ b/src/coreclr/inc/gc_unwind_x86.h @@ -26,10 +26,6 @@ enum regNum REGI_NA = REGI_COUNT }; -/***************************************************************************** - Register masks - */ - enum RegMask { RM_EAX = 0x01, @@ -47,6 +43,276 @@ enum RegMask RM_CALLEE_TRASHED = (RM_ALL & ~RM_CALLEE_SAVED), }; +#define CONSTRUCT_ptrArgTP(arg,shift) ptrArgTP((arg), (shift)) + +// Bit vector structure that can hold MAX_PTRARG_OFS bits and efficiently +// handle small vectors. +class ptrArgTP +{ + typedef UINT_PTR ChunkType; // The size of integer type that the machine can operate on directly + + enum + { + IS_BIG = 1, // The low bit is used to discrimate m_val and m_vals + CHUNK_BITS = sizeof(ChunkType)*8, // The number of bits that we can manipuate as a chunk + SMALL_BITS = CHUNK_BITS - 1, // The number of bits we can fit in the small representation + VALS_COUNT = MAX_PTRARG_OFS / CHUNK_BITS, // The number of ChunkType elements in the Vals array + }; + + static const ChunkType MaxVal = ((ChunkType)1 << SMALL_BITS) - 1; // Maximum value that can be stored in m_val + + struct Vals + { + unsigned m_encodedLength; // An encoding of the current length of the 'm_chunks' array + ChunkType m_chunks[VALS_COUNT]; + + bool isBig() const + { + return ((m_encodedLength & IS_BIG) != 0); + } + + unsigned GetLength() const + { + if (isBig()) + { + unsigned length = (m_encodedLength >> 1); + _ASSERTE(length > 0); + return length; + } + else + { + return 0; + } + } + + void SetLength(unsigned length) + { + _ASSERTE(length > 0); + _ASSERTE(length <= VALS_COUNT); + + m_encodedLength = (ChunkType) (length << 1); + m_encodedLength |= (ChunkType) IS_BIG; + } + }; + + union + { + ChunkType m_val; // if m_val bit 0 is false, then bits 1-N are the bit vector + Vals m_vals; // if m_val bit 1 is true, then use Vals + }; + + bool isBig() const + { + LIMITED_METHOD_DAC_CONTRACT; + + return ((m_val & IS_BIG) != 0); + } + + void toBig() + { + LIMITED_METHOD_DAC_CONTRACT; + + if (!isBig()) + { + doBigInit(smallBits()); + } + } + + ChunkType smallBits() const + { + LIMITED_METHOD_DAC_CONTRACT; + + _ASSERTE(!isBig()); + return (m_val >> 1); + } + + void doBigInit(ChunkType arg); + void doBigInit(const ptrArgTP& arg); + void doBigLeftShiftAssign(unsigned arg); + void doBigRightShiftAssign(unsigned arg); + void doBigDiffAssign(const ptrArgTP&); + void doBigAndAssign(const ptrArgTP&); + void doBigOrAssign(const ptrArgTP& arg); + bool doBigEquals(const ptrArgTP&) const; + bool doBigIntersect(const ptrArgTP&) const; + +public: + ptrArgTP() + { + LIMITED_METHOD_DAC_CONTRACT; + + m_val = 0; + } + + explicit ptrArgTP(ChunkType arg) + { + LIMITED_METHOD_DAC_CONTRACT; + + if (arg > MaxVal) + { + doBigInit(arg); + } + else + { + m_val = ChunkType(arg << 1); + } + } + + ptrArgTP(ChunkType arg, UINT shift) + { + LIMITED_METHOD_DAC_CONTRACT; + + if ((arg > MaxVal) || (shift >= SMALL_BITS) || (arg > (MaxVal >> shift))) + { + doBigInit(arg); + doBigLeftShiftAssign(shift); + } + else + { + m_val = ChunkType(arg << (shift+1)); + } + } + + ptrArgTP operator &(const ptrArgTP& arg) const + { + LIMITED_METHOD_DAC_CONTRACT; + + ptrArgTP ret = *this; + ret &= arg; + return ret; + } + + bool operator ==(const ptrArgTP& arg) const + { + LIMITED_METHOD_DAC_CONTRACT; + + if ((m_val | arg.m_val) & IS_BIG) + { + return doBigEquals(arg); + } + else + { + return m_val == arg.m_val; + } + } + + bool operator !=(const ptrArgTP& arg) const + { + LIMITED_METHOD_DAC_CONTRACT; + + return !(*this == arg); + } + + void operator <<=(unsigned shift) + { + LIMITED_METHOD_DAC_CONTRACT; + + if ((m_val == 0) || (shift == 0)) // Zero is a special case, don't need to do anything + return; + + if (isBig() || (shift >= SMALL_BITS) || (m_val > (MaxVal >> (shift-1)))) + { + doBigLeftShiftAssign(shift); + } + else + { + m_val <<= shift; + } + } + + void operator >>=(unsigned shift) + { + LIMITED_METHOD_DAC_CONTRACT; + + if (isBig()) + { + doBigRightShiftAssign(shift); + } + else + { + m_val >>= shift; + m_val &= ~IS_BIG; // clear the isBig bit if it got set + } + } + + void operator |=(const ptrArgTP& arg) + { + LIMITED_METHOD_DAC_CONTRACT; + + if (((m_val | arg.m_val) & IS_BIG) != 0) + { + doBigOrAssign(arg); + } + else + { + m_val |= arg.m_val; + } + } + + void operator &=(const ptrArgTP& arg) + { + LIMITED_METHOD_DAC_CONTRACT; + + if (((m_val | arg.m_val) & IS_BIG) != 0) + { + doBigAndAssign(arg); + } + else + { + m_val &= arg.m_val; + } + } + + friend bool isZero(const ptrArgTP& arg) + { + LIMITED_METHOD_DAC_CONTRACT; + + return arg.m_val == 0; + } + + friend bool intersect(const ptrArgTP& arg1, const ptrArgTP& arg2) + { + LIMITED_METHOD_DAC_CONTRACT; + + if (((arg1.m_val | arg2.m_val) & IS_BIG) != 0) + { + return arg1.doBigIntersect(arg2); + } + else + { + return ((arg1.m_val & arg2.m_val) != 0); + } + } + + friend void setDiff(ptrArgTP& target, const ptrArgTP& arg) + { + LIMITED_METHOD_DAC_CONTRACT; + + if (((target.m_val | arg.m_val) & IS_BIG) != 0) + { + target.doBigDiffAssign(arg); + } + else + { + target.m_val &= ~arg.m_val; + } + } + + friend ChunkType toUnsigned(const ptrArgTP& arg) + { + LIMITED_METHOD_DAC_CONTRACT; + + if (arg.isBig()) + { + return arg.m_vals.m_chunks[0]; // Note truncation + } + else + { + return arg.smallBits(); + } + } +}; + /***************************************************************************** * * Helper to extract basic info from a method info block. diff --git a/src/coreclr/inc/gcinfotypes.h b/src/coreclr/inc/gcinfotypes.h index ef33fc275fe282..f3cf31ffdc320e 100644 --- a/src/coreclr/inc/gcinfotypes.h +++ b/src/coreclr/inc/gcinfotypes.h @@ -350,7 +350,8 @@ inline const char *ReturnKindToString(ReturnKind returnKind) #ifdef TARGET_X86 #include // For memcmp() -#include "bitvector.h" // for ptrArgTP + +#define MAX_PTRARG_OFS 1024 #ifndef FASTCALL #define FASTCALL __fastcall diff --git a/src/coreclr/utilcode/CMakeLists.txt b/src/coreclr/utilcode/CMakeLists.txt index ec543e707d7185..06282d39189e56 100644 --- a/src/coreclr/utilcode/CMakeLists.txt +++ b/src/coreclr/utilcode/CMakeLists.txt @@ -23,7 +23,6 @@ set(UTILCODE_COMMON_SOURCES check.cpp log.cpp arraylist.cpp - bitvector.cpp comex.cpp guidfromname.cpp memorypool.cpp diff --git a/src/coreclr/utilcode/bitvector.cpp b/src/coreclr/utilcode/bitvector.cpp deleted file mode 100644 index b4c53aa96ed0f3..00000000000000 --- a/src/coreclr/utilcode/bitvector.cpp +++ /dev/null @@ -1,405 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/***************************************************************************/ -/* BitVector.cpp */ -/***************************************************************************/ -// Routines to support a growable bitvector -/***************************************************************************/ - -#include "stdafx.h" -#include - -#include "utilcode.h" - -#include "bitvector.h" - -#if USE_BITVECTOR - -int BitVector::NumBits() const -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - SUPPORTS_DAC; - } CONTRACTL_END; - - int count = 0; - ChunkType hiChunk; - - if (isBig()) - { - unsigned maxNonZero = 0; - for (unsigned i=1; (i < m_vals.GetLength()); i++) - { - if (m_vals.m_chunks[i] != 0) - { - maxNonZero = i; - } - } - count = (maxNonZero * CHUNK_BITS) - 1; - hiChunk = m_vals.m_chunks[maxNonZero]; - } - else - { - hiChunk = m_val; - } - - while (hiChunk > 0) - { - hiChunk <<= 1; - count++; - } - - _ASSERTE(count >= 0); - return count; -} - -void BitVector::doBigInit(ChunkType arg) -{ - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - m_vals.m_chunks[0] = arg; - m_vals.SetLength(1); -} - -void BitVector::doBigInit(const BitVector& arg) -{ - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - if (arg.isBig()) - { - memcpy(m_vals.m_chunks, arg.m_vals.m_chunks, (sizeof(ChunkType) * arg.m_vals.GetLength())); - m_vals.SetLength(arg.m_vals.GetLength()); - } - else - { - m_val = arg.m_val; - } -} - -void BitVector::doBigLeftShiftAssign(unsigned shift) -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - SUPPORTS_DAC; - } CONTRACTL_END; - - if ((m_val == 0) || (shift == 0)) // Zero is a special case, don't need to do anything - return; - - unsigned numWords = shift / CHUNK_BITS; - unsigned numBits = shift % CHUNK_BITS; - - // - // Change to Big representation - // - toBig(); - - int from = m_vals.GetLength()-1; - int to = from + numWords; - unsigned newlen = to + 1; - - ChunkType topBits = 0; - if (numBits > 0) - { - topBits = m_vals.m_chunks[from] >> (CHUNK_BITS - numBits); - } - - if (topBits != 0 || numWords != 0) - { - if (topBits != 0) - { - m_vals.m_chunks[newlen] = topBits; - newlen++; - } - m_vals.SetLength(newlen); - } - - while (to >= 0) - { - m_vals.m_chunks[to] = (from >= 0) ? (m_vals.m_chunks[from] << numBits) : 0; - from--; - - if ((from >= 0) && (numBits > 0)) - { - m_vals.m_chunks[to] |= m_vals.m_chunks[from] >> (CHUNK_BITS - numBits); - } - to--; - } - - // Convert back to small format if necessary - if ((newlen == 1) && (m_vals.m_chunks[0] <= MaxVal)) - { - m_val = ChunkType(m_vals.m_chunks[0] << 1); - } -} - -void BitVector::doBigRightShiftAssign(unsigned shift) -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - SUPPORTS_DAC; - } CONTRACTL_END; - - if ((m_val == 0) || (shift == 0)) // Zero is a special case, don't need to do anything - return; - - unsigned numWords = shift / CHUNK_BITS; - unsigned numBits = shift % CHUNK_BITS; - - // - // Change to Big representation - // - toBig(); - - unsigned from = numWords; - unsigned to = 0; - unsigned len = m_vals.GetLength(); - unsigned newlen = len - numWords; - - if (from >= len) - { - // we always encode zero in short form - m_val = 0; - } - else - { - m_vals.m_chunks[to] = (m_vals.m_chunks[from] >> numBits); - from++; - - while (from < len) - { - if (numBits > 0) - { - m_vals.m_chunks[to] |= m_vals.m_chunks[from] << (CHUNK_BITS - numBits); - } - to++; - - m_vals.m_chunks[to] = (m_vals.m_chunks[from] >> numBits); - from++; - } - - if ((newlen > 1) && (m_vals.m_chunks[newlen-1] == 0)) - { - newlen--; - } - - m_vals.SetLength(newlen); - - // Convert back to small format if necessary - if ((newlen == 1) && (m_vals.m_chunks[0] <= MaxVal)) - { - m_val = ChunkType(m_vals.m_chunks[0] << 1); - } - } -} - -void BitVector::doBigAndAssign(const BitVector& arg) -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - SUPPORTS_DAC; - } CONTRACTL_END; - - // - // Change to Big representation - // - toBig(); - - if (arg.isBig()) - { - bool isZero = true; // until proven otherwise - unsigned myLen = m_vals.GetLength(); - unsigned argLen = arg.m_vals.GetLength(); - - if (myLen > argLen) - { - // shrink our length to match argLen - m_vals.SetLength(argLen); - myLen = argLen; - } - - for (unsigned i = 0; (i < myLen); i++) - { - ChunkType curChunk = m_vals.m_chunks[i] & arg.m_vals.m_chunks[i]; - m_vals.m_chunks[i] = curChunk; - if (curChunk != 0) - isZero = false; - } - - if (isZero) - { - // we always encode zero in short form - m_val = 0; - } - } - else - { - m_val = (m_vals.m_chunks[0] << 1) & arg.m_val; - } -} - -void BitVector::doBigOrAssign(const BitVector& arg) -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - SUPPORTS_DAC; - } CONTRACTL_END; - - // - // Change to Big representation - // - toBig(); - - if (arg.isBig()) - { - unsigned myLen = m_vals.GetLength(); - unsigned argLen = arg.m_vals.GetLength(); - - if (myLen < argLen) - { - // expand our length to match argLen and zero init - memset(m_vals.m_chunks + myLen, 0, sizeof(ChunkType) * (argLen - myLen)); - m_vals.SetLength(argLen); - myLen = argLen; - } - - for(unsigned i = 0; ((i < myLen) && (i < argLen)); i++) - { - m_vals.m_chunks[i] |= arg.m_vals.m_chunks[i]; - } - } - else - { - m_vals.m_chunks[0] |= arg.smallBits(); - } -} - -void BitVector::doBigDiffAssign(const BitVector& arg) -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - SUPPORTS_DAC; - } CONTRACTL_END; - - // - // Change to Big representation - // - toBig(); - - unsigned myLen = m_vals.GetLength(); - unsigned argLen = arg.m_vals.GetLength(); - bool isZero = true; // until proven otherwise - - for (unsigned i = 0; (i < myLen); i++) - { - ChunkType nextChunk = m_vals.m_chunks[i]; - if (i < argLen) - { - nextChunk &= ~arg.m_vals.m_chunks[i]; - m_vals.m_chunks[i] = nextChunk; - } - else if (i == 0) - { - nextChunk &= ~arg.smallBits(); - m_vals.m_chunks[i] = nextChunk; - } - - if (nextChunk != 0) - isZero = false; - } - - if (isZero) - { - // we always encode zero in short form - m_val = 0; - } -} - -BOOL BitVector::doBigEquals(const BitVector& arg) const -{ - CONTRACT(BOOL) - { - NOTHROW; - GC_NOTRIGGER; - SUPPORTS_DAC; - } - CONTRACT_END; - - unsigned myLen = m_vals.GetLength(); - unsigned argLen = arg.m_vals.GetLength(); - unsigned maxLen = (myLen >= argLen) ? myLen : argLen; - - for (unsigned i=0; (i < maxLen); i++) - { - ChunkType myVal = 0; - ChunkType argVal = 0; - - if (i < myLen) - myVal = m_vals.m_chunks[i]; - - if (i < argLen) - argVal = arg.m_vals.m_chunks[i]; - - if (i == 0) - { - if (myLen == 0) - myVal = smallBits(); - if (argLen == 0) - argVal = arg.smallBits(); - } - - if (myVal != argVal) - RETURN false; - } - RETURN true; -} - -BOOL BitVector::doBigIntersect(const BitVector& arg) const -{ - CONTRACT(BOOL) - { - NOTHROW; - GC_NOTRIGGER; - SUPPORTS_DAC; - } - CONTRACT_END; - - unsigned myLen = m_vals.GetLength(); - unsigned argLen = arg.m_vals.GetLength(); - unsigned minLen = (myLen <= argLen) ? myLen : argLen; - - for (unsigned i=0; (i <= minLen); i++) - { - ChunkType myVal = 0; - ChunkType argVal = 0; - - if (i < myLen) - myVal = m_vals.m_chunks[i]; - - if (i < argLen) - argVal = arg.m_vals.m_chunks[i]; - - if (i == 0) - { - if (myLen == 0) - myVal = smallBits(); - if (argLen == 0) - argVal = arg.smallBits(); - } - - if ((myVal & argVal) != 0) - RETURN true; - } - RETURN false; -} - -#endif // USE_BITVECTOR diff --git a/src/coreclr/vm/gc_unwind_x86.inl b/src/coreclr/vm/gc_unwind_x86.inl index 33604336d28c52..c3383574354cfe 100644 --- a/src/coreclr/vm/gc_unwind_x86.inl +++ b/src/coreclr/vm/gc_unwind_x86.inl @@ -3824,3 +3824,318 @@ bool EnumGcRefsX86(PREGDISPLAY pContext, return true; } + +void ptrArgTP::doBigInit(ChunkType arg) +{ + LIMITED_METHOD_DAC_CONTRACT; + + m_vals.m_chunks[0] = arg; + m_vals.SetLength(1); +} + +void ptrArgTP::doBigInit(const ptrArgTP& arg) +{ + LIMITED_METHOD_DAC_CONTRACT; + + if (arg.isBig()) + { + memcpy(m_vals.m_chunks, arg.m_vals.m_chunks, (sizeof(ChunkType) * arg.m_vals.GetLength())); + m_vals.SetLength(arg.m_vals.GetLength()); + } + else + { + m_val = arg.m_val; + } +} + +void ptrArgTP::doBigLeftShiftAssign(unsigned shift) +{ + LIMITED_METHOD_DAC_CONTRACT; + + if ((m_val == 0) || (shift == 0)) // Zero is a special case, don't need to do anything + return; + + unsigned numWords = shift / CHUNK_BITS; + unsigned numBits = shift % CHUNK_BITS; + + // + // Change to Big representation + // + toBig(); + + int from = m_vals.GetLength()-1; + int to = from + numWords; + unsigned newlen = to + 1; + + ChunkType topBits = 0; + if (numBits > 0) + { + topBits = m_vals.m_chunks[from] >> (CHUNK_BITS - numBits); + } + + if (topBits != 0 || numWords != 0) + { + if (topBits != 0) + { + m_vals.m_chunks[newlen] = topBits; + newlen++; + } + m_vals.SetLength(newlen); + } + + while (to >= 0) + { + m_vals.m_chunks[to] = (from >= 0) ? (m_vals.m_chunks[from] << numBits) : 0; + from--; + + if ((from >= 0) && (numBits > 0)) + { + m_vals.m_chunks[to] |= m_vals.m_chunks[from] >> (CHUNK_BITS - numBits); + } + to--; + } + + // Convert back to small format if necessary + if ((newlen == 1) && (m_vals.m_chunks[0] <= MaxVal)) + { + m_val = ChunkType(m_vals.m_chunks[0] << 1); + } +} + +void ptrArgTP::doBigRightShiftAssign(unsigned shift) +{ + LIMITED_METHOD_DAC_CONTRACT; + + if ((m_val == 0) || (shift == 0)) // Zero is a special case, don't need to do anything + return; + + unsigned numWords = shift / CHUNK_BITS; + unsigned numBits = shift % CHUNK_BITS; + + // + // Change to Big representation + // + toBig(); + + unsigned from = numWords; + unsigned to = 0; + unsigned len = m_vals.GetLength(); + unsigned newlen = len - numWords; + + if (from >= len) + { + // we always encode zero in short form + m_val = 0; + } + else + { + m_vals.m_chunks[to] = (m_vals.m_chunks[from] >> numBits); + from++; + + while (from < len) + { + if (numBits > 0) + { + m_vals.m_chunks[to] |= m_vals.m_chunks[from] << (CHUNK_BITS - numBits); + } + to++; + + m_vals.m_chunks[to] = (m_vals.m_chunks[from] >> numBits); + from++; + } + + if ((newlen > 1) && (m_vals.m_chunks[newlen-1] == 0)) + { + newlen--; + } + + m_vals.SetLength(newlen); + + // Convert back to small format if necessary + if ((newlen == 1) && (m_vals.m_chunks[0] <= MaxVal)) + { + m_val = ChunkType(m_vals.m_chunks[0] << 1); + } + } +} + +void ptrArgTP::doBigAndAssign(const ptrArgTP& arg) +{ + LIMITED_METHOD_DAC_CONTRACT; + + // + // Change to Big representation + // + toBig(); + + if (arg.isBig()) + { + bool isZero = true; // until proven otherwise + unsigned myLen = m_vals.GetLength(); + unsigned argLen = arg.m_vals.GetLength(); + + if (myLen > argLen) + { + // shrink our length to match argLen + m_vals.SetLength(argLen); + myLen = argLen; + } + + for (unsigned i = 0; (i < myLen); i++) + { + ChunkType curChunk = m_vals.m_chunks[i] & arg.m_vals.m_chunks[i]; + m_vals.m_chunks[i] = curChunk; + if (curChunk != 0) + isZero = false; + } + + if (isZero) + { + // we always encode zero in short form + m_val = 0; + } + } + else + { + m_val = (m_vals.m_chunks[0] << 1) & arg.m_val; + } +} + +void ptrArgTP::doBigOrAssign(const ptrArgTP& arg) +{ + LIMITED_METHOD_DAC_CONTRACT; + + // + // Change to Big representation + // + toBig(); + + if (arg.isBig()) + { + unsigned myLen = m_vals.GetLength(); + unsigned argLen = arg.m_vals.GetLength(); + + if (myLen < argLen) + { + // expand our length to match argLen and zero init + memset(m_vals.m_chunks + myLen, 0, sizeof(ChunkType) * (argLen - myLen)); + m_vals.SetLength(argLen); + myLen = argLen; + } + + for(unsigned i = 0; ((i < myLen) && (i < argLen)); i++) + { + m_vals.m_chunks[i] |= arg.m_vals.m_chunks[i]; + } + } + else + { + m_vals.m_chunks[0] |= arg.smallBits(); + } +} + +void ptrArgTP::doBigDiffAssign(const ptrArgTP& arg) +{ + LIMITED_METHOD_DAC_CONTRACT; + + // + // Change to Big representation + // + toBig(); + + unsigned myLen = m_vals.GetLength(); + unsigned argLen = arg.m_vals.GetLength(); + bool isZero = true; // until proven otherwise + + for (unsigned i = 0; (i < myLen); i++) + { + ChunkType nextChunk = m_vals.m_chunks[i]; + if (i < argLen) + { + nextChunk &= ~arg.m_vals.m_chunks[i]; + m_vals.m_chunks[i] = nextChunk; + } + else if (i == 0) + { + nextChunk &= ~arg.smallBits(); + m_vals.m_chunks[i] = nextChunk; + } + + if (nextChunk != 0) + isZero = false; + } + + if (isZero) + { + // we always encode zero in short form + m_val = 0; + } +} + +bool ptrArgTP::doBigEquals(const ptrArgTP& arg) const +{ + LIMITED_METHOD_DAC_CONTRACT; + + unsigned myLen = m_vals.GetLength(); + unsigned argLen = arg.m_vals.GetLength(); + unsigned maxLen = (myLen >= argLen) ? myLen : argLen; + + for (unsigned i=0; (i < maxLen); i++) + { + ChunkType myVal = 0; + ChunkType argVal = 0; + + if (i < myLen) + myVal = m_vals.m_chunks[i]; + + if (i < argLen) + argVal = arg.m_vals.m_chunks[i]; + + if (i == 0) + { + if (myLen == 0) + myVal = smallBits(); + if (argLen == 0) + argVal = arg.smallBits(); + } + + if (myVal != argVal) + return false; + } + + return true; +} + +bool ptrArgTP::doBigIntersect(const ptrArgTP& arg) const +{ + LIMITED_METHOD_DAC_CONTRACT; + + unsigned myLen = m_vals.GetLength(); + unsigned argLen = arg.m_vals.GetLength(); + unsigned minLen = (myLen <= argLen) ? myLen : argLen; + + for (unsigned i=0; (i <= minLen); i++) + { + ChunkType myVal = 0; + ChunkType argVal = 0; + + if (i < myLen) + myVal = m_vals.m_chunks[i]; + + if (i < argLen) + argVal = arg.m_vals.m_chunks[i]; + + if (i == 0) + { + if (myLen == 0) + myVal = smallBits(); + if (argLen == 0) + argVal = arg.smallBits(); + } + + if ((myVal & argVal) != 0) + return true; + } + + return false; +}