diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2018-09-14 14:16:28 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-09-14 14:16:28 -0400 |
| commit | 3c505c22673701339d35eb2151f01c16eb3c78c3 (patch) | |
| tree | ff21543fcc846c693cbb6aba43a4e8ae9918f600 | |
| parent | e1c934972509f4bbd2c05affe565f91e7a1e6c16 (diff) | |
Improvements around IR representation and memory usage (#635)
* * Remove dispose from IRInst
* Use MemoryArena instead of MemoryPool
* Make all IRInst not require Dtor - by having ref counted array store ptrs that need freeing
* Increase block size - typically compilation is 2Mb of IR space(!)
* Fix issues around StringRepresentation::equal because null has special meaning.
* Don't bother to construct as String to compare StringRepresentation, just used UnownedStringSlice.
* Added fromLiteral support to UnownedStringSlice and use instead of strlen version.
* Use more conventional way to test StringRepresentation against a String.
* Fix gcc/clang template problem with cast.
| -rw-r--r-- | source/core/slang-memory-arena.cpp | 10 | ||||
| -rw-r--r-- | source/core/slang-memory-arena.h | 106 | ||||
| -rw-r--r-- | source/core/slang-string.h | 177 | ||||
| -rw-r--r-- | source/core/smart-pointer.h | 19 | ||||
| -rw-r--r-- | source/slang/emit.cpp | 16 | ||||
| -rw-r--r-- | source/slang/ir-insts.h | 47 | ||||
| -rw-r--r-- | source/slang/ir-legalize-types.cpp | 2 | ||||
| -rw-r--r-- | source/slang/ir.cpp | 23 | ||||
| -rw-r--r-- | source/slang/ir.h | 73 | ||||
| -rw-r--r-- | source/slang/lower-to-ir.cpp | 14 | ||||
| -rw-r--r-- | source/slang/memory_pool.cpp | 52 | ||||
| -rw-r--r-- | source/slang/memory_pool.h | 19 | ||||
| -rw-r--r-- | source/slang/slang.vcxproj | 2 | ||||
| -rw-r--r-- | source/slang/slang.vcxproj.filters | 8 |
14 files changed, 288 insertions, 280 deletions
diff --git a/source/core/slang-memory-arena.cpp b/source/core/slang-memory-arena.cpp index 4d8b2ed2a..a0a89155c 100644 --- a/source/core/slang-memory-arena.cpp +++ b/source/core/slang-memory-arena.cpp @@ -222,6 +222,16 @@ MemoryArena::Block* MemoryArena::_newBlock(size_t allocSize, size_t alignment) return block; } +void* MemoryArena::_allocateAlignedFromNewBlockAndZero(size_t sizeInBytes, size_t alignment) +{ + void* mem = _allocateAlignedFromNewBlock(sizeInBytes, alignment); + if (mem) + { + ::memset(mem, 0, sizeInBytes); + } + return mem; +} + void* MemoryArena::_allocateAlignedFromNewBlock(size_t size, size_t alignment) { // Make sure init has been called (or has been set up in parameterized constructor) diff --git a/source/core/slang-memory-arena.h b/source/core/slang-memory-arena.h index 1c59ee7d7..54b380b32 100644 --- a/source/core/slang-memory-arena.h +++ b/source/core/slang-memory-arena.h @@ -46,7 +46,7 @@ public: typedef MemoryArena ThisType; /** The minimum alignment of the backing memory allocator. - NOTE! That this should not be greater than the alignment of the underlying allocator. + NOTE! That this should not be greater than the alignment of the underlying allocator, and should never be less than sizeof(void*). */ static const size_t kMinAlignment = sizeof(void*); /** Determines if an allocation is consistent with an allocation from this arena. @@ -60,7 +60,7 @@ public: /** Initialize the arena with specified block size and alignment If the arena has been previously initialized will free and deallocate all memory */ - void init(size_t blockSize, size_t blockAlignment = kMinAlignment); + void init(size_t blockSizeInBytes, size_t blockAlignment = kMinAlignment); /** Allocate some memory of at least size bytes without having any specific alignment. @@ -72,6 +72,11 @@ public: @return The allocation. Can be nullptr if backing allocator was not able to request required memory */ void* allocate(size_t sizeInBytes); + /** Same as allocate, but zeros memory before returning + @param size The size of the allocation requested (in bytes and must be > 0). + @return The allocation. Can be nullptr if backing allocator was not able to request required memory */ + void* allocateAndZero(size_t sizeInBytes); + /** Allocate some aligned memory of at least size bytes @param size Size of allocation wanted (must be > 0). @param alignment Alignment of allocation - must be a power of 2. @@ -100,15 +105,15 @@ public: /// Allocate an array of a specified type. NOTE Constructor of T is NOT executed. template <typename T> - T* allocateArray(size_t size); + T* allocateArray(size_t numElems); /// Allocate an array of a specified type, and copy array passed into it. template <typename T> - T* allocateAndCopyArray(const T* src, size_t size); + T* allocateAndCopyArray(const T* src, size_t numElems); /// Allocate an array of a specified type, and zero it. template <typename T> - T* allocateAndZeroArray(size_t size); + T* allocateAndZeroArray(size_t numElems); /** Deallocates all allocated memory. That backing memory will generally not be released so subsequent allocation will be fast, and from the same memory. Note though that 'oversize' blocks @@ -160,13 +165,14 @@ protected: /// Create a new block with regular block alignment Block* _newNormalBlock(); /// Allocates a new block with allocSize and alignment - Block* _newBlock(size_t allocSize, size_t alignment); + Block* _newBlock(size_t allocSizeInBytes, size_t alignment); - void* _allocateAlignedFromNewBlock(size_t size, size_t alignment); + void* _allocateAlignedFromNewBlock(size_t sizeInBytes, size_t alignment); + void* _allocateAlignedFromNewBlockAndZero(size_t sizeInBytes, size_t alignment); /// Find block that contains data/size that is _NOT_ current (ie not first block in m_usedBlocks) - const Block* _findNonCurrent(const void* data, size_t size) const; - const Block* _findInBlocks(const Block* block, const void* data, size_t size) const; + const Block* _findNonCurrent(const void* data, size_t sizeInBytes) const; + const Block* _findInBlocks(const Block* block, const void* data, size_t sizeInBytes) const; size_t _calcBlocksUsedMemory(const Block* block) const; size_t _calcBlocksAllocatedMemory(const Block* block) const; @@ -192,7 +198,7 @@ protected: }; // -------------------------------------------------------------------------- -inline bool MemoryArena::isValid(const void* data, size_t size) const +SLANG_FORCE_INLINE bool MemoryArena::isValid(const void* data, size_t size) const { assert(size); uint8_t* ptr = (uint8_t*)data; @@ -200,12 +206,12 @@ inline bool MemoryArena::isValid(const void* data, size_t size) const } // -------------------------------------------------------------------------- -SLANG_FORCE_INLINE void* MemoryArena::allocateUnaligned(size_t size) +SLANG_FORCE_INLINE void* MemoryArena::allocateUnaligned(size_t sizeInBytes) { - assert(size > 0); + assert(sizeInBytes > 0); // Align with the minimum alignment uint8_t* mem = m_current; - uint8_t* end = mem + size; + uint8_t* end = mem + sizeInBytes; if (end <= m_end) { m_current = end; @@ -213,33 +219,54 @@ SLANG_FORCE_INLINE void* MemoryArena::allocateUnaligned(size_t size) } else { - return _allocateAlignedFromNewBlock(size, kMinAlignment); + return _allocateAlignedFromNewBlock(sizeInBytes, kMinAlignment); } } // -------------------------------------------------------------------------- -SLANG_FORCE_INLINE void* MemoryArena::allocate(size_t size) +SLANG_FORCE_INLINE void* MemoryArena::allocate(size_t sizeInBytes) { - assert(size > 0); + assert(sizeInBytes > 0); // Align with the minimum alignment const size_t alignMask = kMinAlignment - 1; uint8_t* mem = (uint8_t*)((size_t(m_current) + alignMask) & ~alignMask); - if (mem + size <= m_end) + if (mem + sizeInBytes <= m_end) { - m_current = mem + size; + m_current = mem + sizeInBytes; return mem; } else { - return _allocateAlignedFromNewBlock(size, kMinAlignment); + return _allocateAlignedFromNewBlock(sizeInBytes, kMinAlignment); } } // -------------------------------------------------------------------------- -inline void* MemoryArena::allocateAligned(size_t size, size_t alignment) +SLANG_FORCE_INLINE void* MemoryArena::allocateAndZero(size_t sizeInBytes) { - assert(size > 0); + // Implement without calling ::allocate, because in most common case we don't need to test for null. + assert(sizeInBytes > 0); + // Align with the minimum alignment + const size_t alignMask = kMinAlignment - 1; + uint8_t* mem = (uint8_t*)((size_t(m_current) + alignMask) & ~alignMask); + uint8_t* end = mem + sizeInBytes; + if ( end <= m_end) + { + ::memset(mem, 0, sizeInBytes); + m_current = end; + return mem; + } + else + { + return _allocateAlignedFromNewBlockAndZero(sizeInBytes, kMinAlignment); + } +} + +// -------------------------------------------------------------------------- +SLANG_FORCE_INLINE void* MemoryArena::allocateAligned(size_t sizeInBytes, size_t alignment) +{ + assert(sizeInBytes > 0); // Alignment must be a power of 2 assert(((alignment - 1) & alignment) == 0); @@ -247,19 +274,19 @@ inline void* MemoryArena::allocateAligned(size_t size, size_t alignment) const size_t alignMask = alignment - 1; uint8_t* memory = (uint8_t*)((size_t(m_current) + alignMask) & ~alignMask); - if (memory + size <= m_end) + if (memory + sizeInBytes <= m_end) { - m_current = memory + size; + m_current = memory + sizeInBytes; return memory; } else { - return _allocateAlignedFromNewBlock(size, alignment); + return _allocateAlignedFromNewBlock(sizeInBytes, alignment); } } // -------------------------------------------------------------------------- -inline const char* MemoryArena::allocateString(const char* str) +SLANG_FORCE_INLINE const char* MemoryArena::allocateString(const char* str) { size_t size = ::strlen(str); if (size == 0) @@ -272,43 +299,42 @@ inline const char* MemoryArena::allocateString(const char* str) } // -------------------------------------------------------------------------- -inline const char* MemoryArena::allocateString(const char* chars, size_t charsCount) +inline const char* MemoryArena::allocateString(const char* chars, size_t numChars) { - if (charsCount == 0) + if (numChars == 0) { return ""; } - char* dst = (char*)allocateUnaligned(charsCount + 1); - ::memcpy(dst, chars, charsCount); + char* dst = (char*)allocateUnaligned(numChars + 1); + ::memcpy(dst, chars, numChars); // Add null-terminating zero - dst[charsCount] = 0; + dst[numChars] = 0; return dst; } // -------------------------------------------------------------------------- template <typename T> -inline T* MemoryArena::allocate() +SLANG_FORCE_INLINE T* MemoryArena::allocate() { return reinterpret_cast<T*>(allocateAligned(sizeof(T), SLANG_ALIGN_OF(T))); } // -------------------------------------------------------------------------- template <typename T> -inline T* MemoryArena::allocateArray(size_t count) +SLANG_FORCE_INLINE T* MemoryArena::allocateArray(size_t numElems) { - return (count > 0) ? reinterpret_cast<T*>(allocateAligned(sizeof(T) * count, SLANG_ALIGN_OF(T))) : nullptr; + return (numElems > 0) ? reinterpret_cast<T*>(allocateAligned(sizeof(T) * numElems, SLANG_ALIGN_OF(T))) : nullptr; } // -------------------------------------------------------------------------- template <typename T> -inline T* MemoryArena::allocateAndCopyArray(const T* arr, size_t size) +SLANG_FORCE_INLINE T* MemoryArena::allocateAndCopyArray(const T* arr, size_t numElems) { SLANG_COMPILE_TIME_ASSERT(std::is_pod<T>::value); - - if (size > 0) + if (numElems > 0) { - const size_t totalSize = sizeof(T) * size; + const size_t totalSize = sizeof(T) * numElems; void* ptr = allocateAligned(totalSize, SLANG_ALIGN_OF(T)); ::memcpy(ptr, arr, totalSize); return reinterpret_cast<T*>(ptr); @@ -318,11 +344,11 @@ inline T* MemoryArena::allocateAndCopyArray(const T* arr, size_t size) // --------------------------------------------------------------------------- template <typename T> -inline T* MemoryArena::allocateAndZeroArray(size_t size) +SLANG_FORCE_INLINE T* MemoryArena::allocateAndZeroArray(size_t numElems) { - if (size > 0) + if (numElems > 0) { - const size_t totalSize = sizeof(T) * size; + const size_t totalSize = sizeof(T) * numElems; void* ptr = allocateAligned(totalSize, SLANG_ALIGN_OF(T)); ::memset(ptr, 0, totalSize); return reinterpret_cast<T*>(ptr); diff --git a/source/core/slang-string.h b/source/core/slang-string.h index a67597360..2609b37ab 100644 --- a/source/core/slang-string.h +++ b/source/core/slang-string.h @@ -62,84 +62,15 @@ namespace Slang return (((unsigned char)ch) & 0xC0) == 0x80; } - // A `StringRepresentation` provides the backing storage for - // all reference-counted string-related types. - class StringRepresentation : public RefObject - { - public: - UInt length; - UInt capacity; - - UInt getLength() - { - return length; - } - - char* getData() - { - return (char*) (this + 1); - } - - static StringRepresentation* createWithCapacityAndLength(UInt capacity, UInt length) - { - SLANG_ASSERT(capacity >= length); - void* allocation = operator new(sizeof(StringRepresentation) + capacity + 1); - StringRepresentation* obj = new(allocation) StringRepresentation(); - obj->capacity = capacity; - obj->length = length; - obj->getData()[length] = 0; - return obj; - } - - static StringRepresentation* createWithCapacity(UInt capacity) - { - return createWithCapacityAndLength(capacity, 0); - } - - static StringRepresentation* createWithLength(UInt length) - { - return createWithCapacityAndLength(length, length); - } - - StringRepresentation* cloneWithCapacity(UInt newCapacity) - { - StringRepresentation* newObj = createWithCapacityAndLength(newCapacity, length); - memcpy(getData(), newObj->getData(), length + 1); - return newObj; - } - - StringRepresentation* clone() - { - return cloneWithCapacity(length); - } - - StringRepresentation* ensureCapacity(UInt required) - { - if (capacity >= required) return this; - - UInt newCapacity = capacity; - if (!newCapacity) newCapacity = 16; // TODO: figure out good value for minimum capacity - - while (newCapacity < required) - { - newCapacity = 2 * newCapacity; - } - - return cloneWithCapacity(newCapacity); - } - }; - - class String; - struct UnownedStringSlice { public: UnownedStringSlice() : beginData(nullptr) - , endData(0) + , endData(nullptr) {} - explicit UnownedStringSlice(char const* a): + explicit UnownedStringSlice(char const* a) : beginData(a), endData(a + strlen(a)) {} @@ -147,6 +78,10 @@ namespace Slang : beginData(b) , endData(e) {} + UnownedStringSlice(char const* b, size_t len) + : beginData(b) + , endData(b + len) + {} char const* begin() const { @@ -202,11 +137,104 @@ namespace Slang bool endsWith(UnownedStringSlice const& other) const; bool endsWith(char const* str) const; + template <size_t SIZE> + SLANG_FORCE_INLINE static UnownedStringSlice fromLiteral(const char (&in)[SIZE]) { return UnownedStringSlice(in, SIZE - 1); } + private: char const* beginData; char const* endData; }; + // A `StringRepresentation` provides the backing storage for + // all reference-counted string-related types. + class StringRepresentation : public RefObject + { + public: + UInt length; + UInt capacity; + + SLANG_FORCE_INLINE UInt getLength() const + { + return length; + } + + SLANG_FORCE_INLINE char* getData() + { + return (char*) (this + 1); + } + SLANG_FORCE_INLINE const char* getData() const + { + return (const char*)(this + 1); + } + + static const char* getData(const StringRepresentation* stringRep) + { + return stringRep ? stringRep->getData() : ""; + } + + static UnownedStringSlice asSlice(const StringRepresentation* rep) + { + return rep ? UnownedStringSlice(rep->getData(), rep->getLength()) : UnownedStringSlice(); + } + + static bool equal(const StringRepresentation* a, const StringRepresentation* b) + { + return (a == b) || asSlice(a) == asSlice(b); + } + + static StringRepresentation* createWithCapacityAndLength(UInt capacity, UInt length) + { + SLANG_ASSERT(capacity >= length); + void* allocation = operator new(sizeof(StringRepresentation) + capacity + 1); + StringRepresentation* obj = new(allocation) StringRepresentation(); + obj->capacity = capacity; + obj->length = length; + obj->getData()[length] = 0; + return obj; + } + + static StringRepresentation* createWithCapacity(UInt capacity) + { + return createWithCapacityAndLength(capacity, 0); + } + + static StringRepresentation* createWithLength(UInt length) + { + return createWithCapacityAndLength(length, length); + } + + StringRepresentation* cloneWithCapacity(UInt newCapacity) + { + StringRepresentation* newObj = createWithCapacityAndLength(newCapacity, length); + memcpy(getData(), newObj->getData(), length + 1); + return newObj; + } + + StringRepresentation* clone() + { + return cloneWithCapacity(length); + } + + StringRepresentation* ensureCapacity(UInt required) + { + if (capacity >= required) return this; + + UInt newCapacity = capacity; + if (!newCapacity) newCapacity = 16; // TODO: figure out good value for minimum capacity + + while (newCapacity < required) + { + newCapacity = 2 * newCapacity; + } + + return cloneWithCapacity(newCapacity); + } + }; + + class String; + + + struct UnownedTerminatedStringSlice : public UnownedStringSlice { public: @@ -300,11 +328,12 @@ namespace Slang RefPtr<StringRepresentation> buffer; - String(StringRepresentation* buffer) + public: + + explicit String(StringRepresentation* buffer) : buffer(buffer) {} - public: static String FromWString(const wchar_t * wstr); static String FromWString(const wchar_t * wstr, const wchar_t * wend); static String FromWChar(const wchar_t ch); @@ -313,6 +342,8 @@ namespace Slang { } + SLANG_FORCE_INLINE StringRepresentation* getStringRepresentation() const { return buffer; } + const char * begin() const { return getData(); diff --git a/source/core/smart-pointer.h b/source/core/smart-pointer.h index f45618050..abd7763ee 100644 --- a/source/core/smart-pointer.h +++ b/source/core/smart-pointer.h @@ -61,6 +61,18 @@ namespace Slang { return referenceCount; } + + // Use instead of dynamic_cast as it allows for replacement without using Rtti in the future + template<typename T> + SLANG_FORCE_INLINE const T* dynamicCast() const + { + return dynamic_cast<const T*>(this); + } + template<typename T> + SLANG_FORCE_INLINE T* dynamicCast() + { + return dynamic_cast<T*>(this); + } }; inline void addReference(RefObject* obj) @@ -78,7 +90,7 @@ namespace Slang struct RefPtr { RefPtr() - : pointer(0) + : pointer(nullptr) {} RefPtr(T* p) @@ -96,7 +108,7 @@ namespace Slang RefPtr(RefPtr<T>&& p) : pointer(p.pointer) { - p.pointer = 0; + p.pointer = nullptr; } template <typename U> @@ -170,8 +182,7 @@ namespace Slang template<typename U> RefPtr<U> As() const { - RefPtr<U> result(dynamic_cast<U*>(pointer)); - return result; + return RefPtr<U>(pointer->template dynamicCast<U>()); } ~RefPtr() diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 1d121d69b..2d774d8d8 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -1389,7 +1389,7 @@ struct EmitVisitor bool isTargetIntrinsicModifierApplicable( IRTargetIntrinsicDecoration* decoration) { - auto targetName = decoration->targetName; + auto targetName = String(decoration->targetName); // If no target name was specified, then the modifier implicitly // applies to all targets. @@ -2133,7 +2133,7 @@ struct EmitVisitor // then use that name instead. if(auto intrinsicDecoration = findTargetIntrinsicDecoration(context, inst)) { - return intrinsicDecoration->definition; + return String(intrinsicDecoration->definition); } // If we have a name hint on the instruction, then we will try to use that @@ -2945,7 +2945,7 @@ struct EmitVisitor args++; argCount--; - auto name = targetIntrinsic->definition; + auto name = String(targetIntrinsic->definition); if(isOrdinaryName(name)) @@ -3845,11 +3845,11 @@ struct EmitVisitor if(auto layoutDecoration = inst->findDecoration<IRLayoutDecoration>()) { auto layout = layoutDecoration->layout; - if(auto varLayout = layout.As<VarLayout>()) + if(auto varLayout = layout->dynamicCast<VarLayout>()) { emitIRSemantics(ctx, varLayout); } - else if (auto entryPointLayout = layout.As<EntryPointLayout>()) + else if (auto entryPointLayout = layout->dynamicCast<EntryPointLayout>()) { emitIRSemantics(ctx, entryPointLayout->resultLayout); } @@ -3864,7 +3864,7 @@ struct EmitVisitor if (!decoration) return nullptr; - return (VarLayout*) decoration->layout.Ptr(); + return (VarLayout*) decoration->layout; } void emitIRLayoutSemantics( @@ -4757,7 +4757,7 @@ struct EmitVisitor { if( auto layoutDecoration = func->findDecoration<IRLayoutDecoration>() ) { - return layoutDecoration->layout.As<EntryPointLayout>(); + return layoutDecoration->layout->dynamicCast<EntryPointLayout>(); } return nullptr; } @@ -4766,7 +4766,7 @@ struct EmitVisitor { if (auto layoutDecoration = func->findDecoration<IRLayoutDecoration>()) { - if (auto entryPointLayout = layoutDecoration->layout.As<EntryPointLayout>()) + if (auto entryPointLayout = layoutDecoration->layout->dynamicCast<EntryPointLayout>()) { return entryPointLayout; } diff --git a/source/slang/ir-insts.h b/source/slang/ir-insts.h index e7ca08c6d..644036e89 100644 --- a/source/slang/ir-insts.h +++ b/source/slang/ir-insts.h @@ -32,12 +32,7 @@ struct IRLayoutDecoration : IRDecoration { enum { kDecorationOp = kIRDecorationOp_Layout }; - RefPtr<Layout> layout; - virtual void dispose() override - { - IRDecoration::dispose(); - layout = nullptr; - } + Layout* layout; }; enum IRLoopControl @@ -56,12 +51,7 @@ struct IRLoopControlDecoration : IRDecoration struct IRTargetSpecificDecoration : IRDecoration { // TODO: have a more structured representation of target specifiers - String targetName; - virtual void dispose()override - { - IRDecoration::dispose(); - targetName = String(); - } + StringRepresentation* targetName; }; struct IRTargetDecoration : IRTargetSpecificDecoration @@ -73,12 +63,7 @@ struct IRTargetIntrinsicDecoration : IRTargetSpecificDecoration { enum { kDecorationOp = kIRDecorationOp_TargetIntrinsic }; - String definition; - virtual void dispose()override - { - IRTargetSpecificDecoration::dispose(); - definition = String(); - } + StringRepresentation* definition; }; struct IRGLSLOuterArrayDecoration : IRDecoration @@ -138,12 +123,7 @@ struct IRNameHintDecoration : IRDecoration // declaration. struct IRDeclRef : IRInst { - DeclRef<Decl> declRef; - virtual void dispose() override - { - IRInst::dispose(); - declRef = decltype(declRef)(); - } + Decl* declRef; }; // An instruction that specializes another IR value @@ -838,17 +818,32 @@ struct IRBuilder { SLANG_ASSERT(getModule()); auto decorationSize = sizeof(T); - auto decoration = (T*)getModule()->memoryPool.allocZero(decorationSize); + auto decoration = (T*)getModule()->memoryArena.allocateAndZero(decorationSize); + + // TODO: Do we need to run ctor after zeroing? new(decoration)T(); decoration->op = op; decoration->next = value->firstDecoration; value->firstDecoration = decoration; - getModule()->irObjectsToFree.Add(decoration); return decoration; } + template <typename T> + T* addRefObjectToFree(T* ptr) + { + getModule()->addRefObjectToFree(ptr); + return ptr; + } + StringRepresentation* addStringToFree(const String& string) + { + StringRepresentation* stringRep = string.getStringRepresentation(); + getModule()->addRefObjectToFree(stringRep); + return stringRep; + } + + template<typename T> T* addDecoration(IRInst* value) { diff --git a/source/slang/ir-legalize-types.cpp b/source/slang/ir-legalize-types.cpp index 9136ad671..931ceb85a 100644 --- a/source/slang/ir-legalize-types.cpp +++ b/source/slang/ir-legalize-types.cpp @@ -844,7 +844,7 @@ static LegalVal legalizeInst( RefPtr<VarLayout> findVarLayout(IRInst* value) { if (auto layoutDecoration = value->findDecoration<IRLayoutDecoration>()) - return layoutDecoration->layout.As<VarLayout>(); + return layoutDecoration->layout->dynamicCast<VarLayout>(); return nullptr; } diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp index 83735d6df..6b2939987 100644 --- a/source/slang/ir.cpp +++ b/source/slang/ir.cpp @@ -763,7 +763,7 @@ namespace Slang // Create an IR instruction/value and initialize it. // - // In this case `argCount` and `args` represnt the + // In this case `argCount` and `args` represent the // arguments *after* the type (which is a mandatory // argument for all instructions). template<typename T> @@ -791,9 +791,10 @@ namespace Slang } SLANG_ASSERT(module); - T* inst = (T*)module->memoryPool.allocZero(size); - new(inst)T(); + T* inst = (T*)module->memoryArena.allocateAndZero(size); + // TODO: Do we need to run ctor after zeroing? + new(inst)T(); inst->operandCount = (uint32_t)(fixedArgCount + varArgCount); @@ -833,7 +834,6 @@ namespace Slang operand++; } } - module->irObjectsToFree.Add(inst); return inst; } @@ -2285,7 +2285,7 @@ namespace Slang IRLayoutDecoration* IRBuilder::addLayoutDecoration(IRInst* inst, Layout* layout) { auto decoration = addDecoration<IRLayoutDecoration>(inst); - decoration->layout = layout; + decoration->layout = addRefObjectToFree(layout); return decoration; } @@ -2534,7 +2534,7 @@ namespace Slang dump(context, "\n"); dumpIndent(context); dump(context, "[target("); - dump(context, decoration->targetName.Buffer()); + dump(context, StringRepresentation::getData(decoration->targetName)); dump(context, ")]"); } break; @@ -2910,11 +2910,6 @@ namespace Slang ff->debugValidate(); } - void IRInst::dispose() - { - IRObject::dispose(); - } - // Insert this instruction into the same basic block // as `other`, right before it. void IRInst::insertBefore(IRInst* other) @@ -4223,7 +4218,7 @@ namespace Slang continue; auto decoration = (IRTargetIntrinsicDecoration*) dd; - if(decoration->targetName == targetName) + if(String(decoration->targetName) == targetName) return decoration; } @@ -4469,7 +4464,7 @@ namespace Slang if(!decoration) continue; - if(decoration->definition != "EmitVertex()") + if(StringRepresentation::asSlice(decoration->definition) != UnownedStringSlice::fromLiteral("EmitVertex()")) { continue; } @@ -5425,7 +5420,7 @@ namespace Slang continue; auto decoration = (IRTargetDecoration*) dd; - if(decoration->targetName == targetName) + if(String(decoration->targetName) == targetName) return TargetSpecializationLevel::specializedForTarget; result = TargetSpecializationLevel::specializedForOtherTarget; diff --git a/source/slang/ir.h b/source/slang/ir.h index 4c601ce5d..a7f2cb4fb 100644 --- a/source/slang/ir.h +++ b/source/slang/ir.h @@ -10,7 +10,9 @@ #include "../core/basic.h" #include "source-loc.h" -#include "memory_pool.h" + +#include "../core/slang-memory-arena.h" + #include "type-system-shared.h" namespace Slang { @@ -128,18 +130,9 @@ enum IRDecorationOp : uint16_t kIRDecorationOp_NameHint, }; -// represents an object allocated in an IR memory pool +// represents an object allocated in an IR memory arena struct IRObject { - bool isDestroyed = false; - virtual void dispose() - { - isDestroyed = true; - } - virtual ~IRObject() - { - isDestroyed = true; - } }; // A "decoration" that gets applied to an instruction. @@ -247,9 +240,6 @@ struct IRInst : public IRObject // that this value will now have no uses. void replaceUsesWith(IRInst* other); - // Clean up any non-pool resources used by this instruction - virtual void dispose() override; - // Insert this instruction into the same basic block // as `other`, right before/after it. void insertBefore(IRInst* other); @@ -332,8 +322,8 @@ struct IRInstListBase - IRInst* first = 0; - IRInst* last = 0; + IRInst* first = nullptr; + IRInst* last = nullptr; IRInst* getFirst() { return first; } IRInst* getLast() { return last; } @@ -991,23 +981,50 @@ struct IRModuleInst : IRParentInst struct IRModule : RefObject { - // The compilation session in use. - Session* session; - MemoryPool memoryPool; - List<IRObject*> irObjectsToFree; // list of ir objects to run destructor upon destruction + enum + { + kMemoryArenaBlockSize = 16 * 1024, ///< Use 16k block size for memory arena + }; - IRModuleInst* moduleInst; - IRModuleInst* getModuleInst() { return moduleInst; } + SLANG_FORCE_INLINE Session* getSession() const { return session; } + SLANG_FORCE_INLINE IRModuleInst* getModuleInst() const { return moduleInst; } - IRInstListBase getGlobalInsts() { return getModuleInst()->getChildren(); } + IRInstListBase getGlobalInsts() const { return getModuleInst()->getChildren(); } - ~IRModule() + void addRefObjectToFree(RefObject* obj) + { + if (obj) + { + obj->addReference(); + m_refObjectsToFree.Add(obj); + } + } + + /// Ctor + IRModule(): + memoryArena(kMemoryArenaBlockSize) { - for (auto val : irObjectsToFree) - if (!val->isDestroyed) - val->dispose(); - irObjectsToFree = List<IRObject*>(); } + + ~IRModule() + { + // Release all ref objects + for (RefObject* ptr: m_refObjectsToFree) + { + ptr->releaseReference(); + } + // Clear any memory too + m_refObjectsToFree = List<RefObject*>(); + } + + MemoryArena memoryArena; + + // The compilation session in use. + Session* session; + IRModuleInst* moduleInst; + + protected: + List<RefObject*> m_refObjectsToFree; }; void printSlangIRAssembly(StringBuilder& builder, IRModule* module); diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp index 280b89fb8..d57872fc9 100644 --- a/source/slang/lower-to-ir.cpp +++ b/source/slang/lower-to-ir.cpp @@ -4549,19 +4549,21 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> IRInst* irInst, Decl* decl) { + auto builder = getBuilder(); + for (auto targetMod : decl->GetModifiersOfType<TargetIntrinsicModifier>()) { - auto decoration = getBuilder()->addDecoration<IRTargetIntrinsicDecoration>(irInst); - decoration->targetName = targetMod->targetToken.Content; - + auto decoration = builder->addDecoration<IRTargetIntrinsicDecoration>(irInst); + decoration->targetName = builder->addStringToFree(targetMod->targetToken.Content); + auto definitionToken = targetMod->definitionToken; if (definitionToken.type == TokenType::StringLiteral) { - decoration->definition = getStringLiteralTokenValue(definitionToken); + decoration->definition = builder->addStringToFree(getStringLiteralTokenValue(definitionToken)); } else { - decoration->definition = definitionToken.Content; + decoration->definition = builder->addStringToFree(definitionToken.Content); } } } @@ -4900,7 +4902,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> // target, and we need to reflect that at the IR level. auto decoration = getBuilder()->addDecoration<IRTargetDecoration>(irFunc); - decoration->targetName = targetMod->targetToken.Content; + decoration->targetName = getBuilder()->addStringToFree(targetMod->targetToken.Content); } // If this declaration was marked as having a target-specific lowering diff --git a/source/slang/memory_pool.cpp b/source/slang/memory_pool.cpp deleted file mode 100644 index 884c9cfe4..000000000 --- a/source/slang/memory_pool.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "memory_pool.h" - -namespace Slang -{ - const size_t kPoolSegmentSize = 4 << 20; // use 4MB segments - - struct MemoryPoolSegment - { - unsigned char* data = nullptr; - size_t allocPtr = 0; - MemoryPoolSegment* nextSegment = nullptr; - }; - - MemoryPool::~MemoryPool() - { - while (curSegment) - { - auto nxtSegment = curSegment->nextSegment; - free(curSegment->data); - delete curSegment; - curSegment = nxtSegment; - } - } - - void newSegment(MemoryPool* pool) - { - auto seg = new MemoryPoolSegment(); - seg->nextSegment = pool->curSegment; - seg->data = (unsigned char*)malloc(kPoolSegmentSize); - pool->curSegment = seg; - } - - void * MemoryPool::alloc(size_t size) - { - assert(size < kPoolSegmentSize); - // ensure there is a segment available - if (!curSegment) - newSegment(this); - if (curSegment->allocPtr + size > kPoolSegmentSize) - newSegment(this); - // alloc memory from current segment - void* rs = curSegment->data + curSegment->allocPtr; - curSegment->allocPtr += size; - return rs; - } - void * MemoryPool::allocZero(size_t size) - { - auto rs = alloc(size); - memset(rs, 0, size); - return rs; - } -} diff --git a/source/slang/memory_pool.h b/source/slang/memory_pool.h deleted file mode 100644 index ee3ee1aa3..000000000 --- a/source/slang/memory_pool.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SLANG_MEMORY_POOL_H -#define SLANG_MEMORY_POOL_H - -#include "../core/basic.h" - -namespace Slang -{ - struct MemoryPoolSegment; - - struct MemoryPool : public RefObject - { - MemoryPoolSegment* curSegment = nullptr; - ~MemoryPool(); - void* alloc(size_t size); - void* allocZero(size_t size); - }; -} - -#endif
\ No newline at end of file diff --git a/source/slang/slang.vcxproj b/source/slang/slang.vcxproj index 284907018..eeaf7410a 100644 --- a/source/slang/slang.vcxproj +++ b/source/slang/slang.vcxproj @@ -195,7 +195,6 @@ <ClInclude Include="lookup.h" /> <ClInclude Include="lower-to-ir.h" /> <ClInclude Include="mangle.h" /> - <ClInclude Include="memory_pool.h" /> <ClInclude Include="modifier-defs.h" /> <ClInclude Include="name.h" /> <ClInclude Include="object-meta-begin.h" /> @@ -241,7 +240,6 @@ <ClCompile Include="lookup.cpp" /> <ClCompile Include="lower-to-ir.cpp" /> <ClCompile Include="mangle.cpp" /> - <ClCompile Include="memory_pool.cpp" /> <ClCompile Include="name.cpp" /> <ClCompile Include="options.cpp" /> <ClCompile Include="parameter-binding.cpp" /> diff --git a/source/slang/slang.vcxproj.filters b/source/slang/slang.vcxproj.filters index f12163f27..e2b17530e 100644 --- a/source/slang/slang.vcxproj.filters +++ b/source/slang/slang.vcxproj.filters @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <Filter Include="Header Files"> @@ -84,9 +84,6 @@ <ClInclude Include="mangle.h"> <Filter>Header Files</Filter> </ClInclude> - <ClInclude Include="memory_pool.h"> - <Filter>Header Files</Filter> - </ClInclude> <ClInclude Include="modifier-defs.h"> <Filter>Header Files</Filter> </ClInclude> @@ -218,9 +215,6 @@ <ClCompile Include="mangle.cpp"> <Filter>Source Files</Filter> </ClCompile> - <ClCompile Include="memory_pool.cpp"> - <Filter>Source Files</Filter> - </ClCompile> <ClCompile Include="name.cpp"> <Filter>Source Files</Filter> </ClCompile> |
