Fixed memory leak associated with TLS. We used to allocate thread-local memory on each compile. If the compile did not happen on the same thread as ShInitialize, we leaked the thread-local memory. It turns out that there is no need to allocate any thread-local memory. This patch cleans up all the unnecessary junk around TLS. BUG=chromium:181691 Change-Id: I4b67ab23dc856d93424ae51ebf8aaf8966b732e4 Reviewed-on: https://swiftshader-review.googlesource.com/1361 Reviewed-by: Nicolas Capens <nicolascapens@google.com> Tested-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/OpenGL/compiler/Common.h b/src/OpenGL/compiler/Common.h index 27a5598..1dc5eeb 100644 --- a/src/OpenGL/compiler/Common.h +++ b/src/OpenGL/compiler/Common.h
@@ -36,14 +36,14 @@ // // Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. // -#define POOL_ALLOCATOR_NEW_DELETE(A) \ - void* operator new(size_t s) { return (A).allocate(s); } \ - void* operator new(size_t, void *_Where) { return (_Where); } \ - void operator delete(void*) { } \ - void operator delete(void *, void *) { } \ - void* operator new[](size_t s) { return (A).allocate(s); } \ - void* operator new[](size_t, void *_Where) { return (_Where); } \ - void operator delete[](void*) { } \ +#define POOL_ALLOCATOR_NEW_DELETE() \ + void* operator new(size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \ + void* operator new(size_t, void *_Where) { return (_Where); } \ + void operator delete(void*) { } \ + void operator delete(void *, void *) { } \ + void* operator new[](size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \ + void* operator new[](size_t, void *_Where) { return (_Where); } \ + void operator delete[](void*) { } \ void operator delete[](void *, void *) { } // @@ -54,7 +54,7 @@ typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream; inline TString* NewPoolTString(const char* s) { - void* memory = GlobalPoolAllocator.allocate(sizeof(TString)); + void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TString)); return new(memory) TString(s); }
diff --git a/src/OpenGL/compiler/Compiler.cpp b/src/OpenGL/compiler/Compiler.cpp index 6945869..28455cf 100644 --- a/src/OpenGL/compiler/Compiler.cpp +++ b/src/OpenGL/compiler/Compiler.cpp
@@ -92,7 +92,7 @@ TParseContext parseContext(symbolTable, extensionBehavior, intermediate, shaderType, shaderSpec, compileOptions, true, sourcePath, infoSink); - GlobalParseContext = &parseContext; + SetGlobalParseContext(&parseContext); // We preserve symbols at the built-in level from compile-to-compile. // Start pushing the user-defined symbols at global level.
diff --git a/src/OpenGL/compiler/ConstantUnion.h b/src/OpenGL/compiler/ConstantUnion.h index 6b04310..397bb75 100644 --- a/src/OpenGL/compiler/ConstantUnion.h +++ b/src/OpenGL/compiler/ConstantUnion.h
@@ -11,6 +11,7 @@ class ConstantUnion { public: + POOL_ALLOCATOR_NEW_DELETE(); ConstantUnion() { iConst = 0;
diff --git a/src/OpenGL/compiler/InitializeDll.cpp b/src/OpenGL/compiler/InitializeDll.cpp index 8763cfe..6c7f27f 100644 --- a/src/OpenGL/compiler/InitializeDll.cpp +++ b/src/OpenGL/compiler/InitializeDll.cpp
@@ -10,25 +10,8 @@ #include "compiler/InitializeParseContext.h" #include "compiler/osinclude.h" -OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX; - bool InitProcess() { - if (ThreadInitializeIndex != OS_INVALID_TLS_INDEX) { - // - // Function is re-entrant. - // - return true; - } - - ThreadInitializeIndex = OS_AllocTLSIndex(); - - if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "InitProcess(): Failed to allocate TLS area for init flag"); - return false; - } - - if (!InitializePoolIndex()) { assert(0 && "InitProcess(): Failed to initalize global pool"); return false; @@ -39,77 +22,11 @@ return false; } - return InitThread(); -} - -bool DetachProcess() -{ - bool success = true; - - if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) - return true; - - success = DetachThread(); - - if (!FreeParseContextIndex()) - success = false; - - FreePoolIndex(); - - OS_FreeTLSIndex(ThreadInitializeIndex); - ThreadInitializeIndex = OS_INVALID_TLS_INDEX; - - return success; -} - -bool InitThread() -{ - // - // This function is re-entrant - // - if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "InitThread(): Process hasn't been initalised."); - return false; - } - - if (OS_GetTLSValue(ThreadInitializeIndex) != 0) - return true; - - InitializeGlobalPools(); - - if (!InitializeGlobalParseContext()) - return false; - - if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) { - assert(0 && "InitThread(): Unable to set init flag."); - return false; - } - return true; } -bool DetachThread() +void DetachProcess() { - bool success = true; - - if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) - return true; - - // - // Function is re-entrant and this thread may not have been initalised. - // - if (OS_GetTLSValue(ThreadInitializeIndex) != 0) { - if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)0)) { - assert(0 && "DetachThread(): Unable to clear init flag."); - success = false; - } - - if (!FreeParseContext()) - success = false; - - FreeGlobalPools(); - } - - return success; + FreeParseContextIndex(); + FreePoolIndex(); } -
diff --git a/src/OpenGL/compiler/InitializeDll.h b/src/OpenGL/compiler/InitializeDll.h index 857238e..43070cc 100644 --- a/src/OpenGL/compiler/InitializeDll.h +++ b/src/OpenGL/compiler/InitializeDll.h
@@ -7,10 +7,7 @@ #define __INITIALIZEDLL_H bool InitProcess(); -bool DetachProcess(); - -bool InitThread(); -bool DetachThread(); +void DetachProcess(); #endif // __INITIALIZEDLL_H
diff --git a/src/OpenGL/compiler/InitializeGlobals.h b/src/OpenGL/compiler/InitializeGlobals.h index 842a452..0715941 100644 --- a/src/OpenGL/compiler/InitializeGlobals.h +++ b/src/OpenGL/compiler/InitializeGlobals.h
@@ -7,8 +7,6 @@ #ifndef __INITIALIZE_GLOBALS_INCLUDED_ #define __INITIALIZE_GLOBALS_INCLUDED_ -void InitializeGlobalPools(); -void FreeGlobalPools(); bool InitializePoolIndex(); void FreePoolIndex();
diff --git a/src/OpenGL/compiler/InitializeParseContext.cpp b/src/OpenGL/compiler/InitializeParseContext.cpp index 1f40cf5..dfab027 100644 --- a/src/OpenGL/compiler/InitializeParseContext.cpp +++ b/src/OpenGL/compiler/InitializeParseContext.cpp
@@ -12,85 +12,29 @@ bool InitializeParseContextIndex() { - if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) { - assert(0 && "InitializeParseContextIndex(): Parse Context already initalized"); - return false; - } + assert(GlobalParseContextIndex == OS_INVALID_TLS_INDEX); - // - // Allocate a TLS index. - // GlobalParseContextIndex = OS_AllocTLSIndex(); - - if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "InitializeParseContextIndex(): Parse Context already initalized"); - return false; - } - - return true; + return GlobalParseContextIndex != OS_INVALID_TLS_INDEX; } -bool FreeParseContextIndex() +void FreeParseContextIndex() { - OS_TLSIndex tlsiIndex = GlobalParseContextIndex; + assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); - if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "FreeParseContextIndex(): Parse Context index not initalized"); - return false; - } - + OS_FreeTLSIndex(GlobalParseContextIndex); GlobalParseContextIndex = OS_INVALID_TLS_INDEX; - - return OS_FreeTLSIndex(tlsiIndex); } -bool InitializeGlobalParseContext() +void SetGlobalParseContext(TParseContext* context) { - if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalized"); - return false; - } - - TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex)); - if (lpParseContext != 0) { - assert(0 && "InitializeParseContextIndex(): Parse Context already initalized"); - return false; - } - - TThreadParseContext *lpThreadData = new TThreadParseContext(); - if (lpThreadData == 0) { - assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context"); - return false; - } - - lpThreadData->lpGlobalParseContext = 0; - OS_SetTLSValue(GlobalParseContextIndex, lpThreadData); - - return true; + assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); + OS_SetTLSValue(GlobalParseContextIndex, context); } -bool FreeParseContext() +TParseContext* GetGlobalParseContext() { - if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "FreeParseContext(): Parse Context index not initalized"); - return false; - } - - TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex)); - if (lpParseContext) - delete lpParseContext; - - return true; -} - -TParseContextPointer& GetGlobalParseContext() -{ - // - // Minimal error checking for speed - // - - TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex)); - - return lpParseContext->lpGlobalParseContext; + assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); + return static_cast<TParseContext*>(OS_GetTLSValue(GlobalParseContextIndex)); }
diff --git a/src/OpenGL/compiler/InitializeParseContext.h b/src/OpenGL/compiler/InitializeParseContext.h index 354bfe1..4729d3c 100644 --- a/src/OpenGL/compiler/InitializeParseContext.h +++ b/src/OpenGL/compiler/InitializeParseContext.h
@@ -8,19 +8,10 @@ #define __INITIALIZE_PARSE_CONTEXT_INCLUDED_ bool InitializeParseContextIndex(); -bool FreeParseContextIndex(); - -bool InitializeGlobalParseContext(); -bool FreeParseContext(); +void FreeParseContextIndex(); struct TParseContext; -typedef TParseContext* TParseContextPointer; -extern TParseContextPointer& GetGlobalParseContext(); -#define GlobalParseContext GetGlobalParseContext() - -typedef struct TThreadParseContextRec -{ - TParseContext *lpGlobalParseContext; -} TThreadParseContext; +extern void SetGlobalParseContext(TParseContext* context); +extern TParseContext* GetGlobalParseContext(); #endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_
diff --git a/src/OpenGL/compiler/PoolAlloc.cpp b/src/OpenGL/compiler/PoolAlloc.cpp index 9cdbeaa..6ec3c40 100644 --- a/src/OpenGL/compiler/PoolAlloc.cpp +++ b/src/OpenGL/compiler/PoolAlloc.cpp
@@ -16,55 +16,32 @@ OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX; -void InitializeGlobalPools() -{ - TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex)); - if (globalPools) - return; - - TThreadGlobalPools* threadData = new TThreadGlobalPools(); - threadData->globalPoolAllocator = 0; - - OS_SetTLSValue(PoolIndex, threadData); -} - -void FreeGlobalPools() -{ - // Release the allocated memory for this thread. - TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex)); - if (!globalPools) - return; - - delete globalPools; -} - bool InitializePoolIndex() { - // Allocate a TLS index. - if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX) - return false; + assert(PoolIndex == OS_INVALID_TLS_INDEX); - return true; + PoolIndex = OS_AllocTLSIndex(); + return PoolIndex != OS_INVALID_TLS_INDEX; } void FreePoolIndex() { - // Release the TLS index. + assert(PoolIndex != OS_INVALID_TLS_INDEX); + OS_FreeTLSIndex(PoolIndex); + PoolIndex = OS_INVALID_TLS_INDEX; } -TPoolAllocator& GetGlobalPoolAllocator() +TPoolAllocator* GetGlobalPoolAllocator() { - TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex)); - - return *threadData->globalPoolAllocator; + assert(PoolIndex != OS_INVALID_TLS_INDEX); + return static_cast<TPoolAllocator*>(OS_GetTLSValue(PoolIndex)); } void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator) { - TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex)); - - threadData->globalPoolAllocator = poolAllocator; + assert(PoolIndex != OS_INVALID_TLS_INDEX); + OS_SetTLSValue(PoolIndex, poolAllocator); } //
diff --git a/src/OpenGL/compiler/PoolAlloc.h b/src/OpenGL/compiler/PoolAlloc.h index c33dfd9..b032c47 100644 --- a/src/OpenGL/compiler/PoolAlloc.h +++ b/src/OpenGL/compiler/PoolAlloc.h
@@ -219,14 +219,8 @@ // different times. But a simple use is to have a global pop // with everyone using the same global allocator. // -extern TPoolAllocator& GetGlobalPoolAllocator(); +extern TPoolAllocator* GetGlobalPoolAllocator(); extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator); -#define GlobalPoolAllocator GetGlobalPoolAllocator() - -struct TThreadGlobalPools -{ - TPoolAllocator* globalPoolAllocator; -}; // // This STL compatible allocator is intended to be used as the allocator @@ -253,7 +247,7 @@ pointer address(reference x) const { return &x; } const_pointer address(const_reference x) const { return &x; } - pool_allocator() : allocator(&GlobalPoolAllocator) { } + pool_allocator() : allocator(GetGlobalPoolAllocator()) { } pool_allocator(TPoolAllocator& a) : allocator(&a) { } pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }
diff --git a/src/OpenGL/compiler/ShaderLang.cpp b/src/OpenGL/compiler/ShaderLang.cpp index 368c068..cd4e9ad 100644 --- a/src/OpenGL/compiler/ShaderLang.cpp +++ b/src/OpenGL/compiler/ShaderLang.cpp
@@ -23,10 +23,7 @@ // int ShInitialize() { - if (!InitProcess()) - return 0; - - return 1; + return InitProcess() ? 1 : 0; } // @@ -34,9 +31,7 @@ // int ShFinalize() { - if (!DetachProcess()) - return 0; - + DetachProcess(); return 1; } @@ -69,9 +64,6 @@ ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources* resources) { - if (!InitThread()) - return 0; - TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec)); TCompiler* compiler = base->getAsCompiler(); if (compiler == 0) @@ -110,9 +102,6 @@ const int numStrings, int compileOptions) { - if (!InitThread()) - return 0; - if (handle == 0) return 0;
diff --git a/src/OpenGL/compiler/SymbolTable.h b/src/OpenGL/compiler/SymbolTable.h index 6d4355d..739b7ad 100644 --- a/src/OpenGL/compiler/SymbolTable.h +++ b/src/OpenGL/compiler/SymbolTable.h
@@ -40,9 +40,10 @@ // class TSymbol { public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + POOL_ALLOCATOR_NEW_DELETE(); TSymbol(const TString *n) : name(n) { } virtual ~TSymbol() { /* don't delete name, it's from the pool */ } + const TString& getName() const { return *name; } virtual const TString& getMangledName() const { return getName(); } virtual bool isFunction() const { return false; } @@ -179,7 +180,7 @@ typedef const tLevel::value_type tLevelPair; typedef std::pair<tLevel::iterator, bool> tInsertResult; - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + POOL_ALLOCATOR_NEW_DELETE(); TSymbolTableLevel() { } ~TSymbolTableLevel();
diff --git a/src/OpenGL/compiler/Types.h b/src/OpenGL/compiler/Types.h index ff280d6..8b6f07c 100644 --- a/src/OpenGL/compiler/Types.h +++ b/src/OpenGL/compiler/Types.h
@@ -1,314 +1,314 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef _TYPES_INCLUDED -#define _TYPES_INCLUDED - -#include "compiler/BaseTypes.h" -#include "compiler/Common.h" -#include "compiler/debug.h" - -#include <algorithm> - -class TType; -struct TPublicType; - -// -// Need to have association of line numbers to types in a list for building structs. -// -struct TTypeLine { - TType* type; - int line; -}; -typedef TVector<TTypeLine> TTypeList; - -inline TTypeList* NewPoolTTypeList() -{ - void* memory = GlobalPoolAllocator.allocate(sizeof(TTypeList)); - return new(memory) TTypeList; -} - -// -// Base class for things that have a type. -// -class TType -{ -public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) - TType() {} - TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) : - type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), - maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0) - { - } - explicit TType(const TPublicType &p); - TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) : - type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), - maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0) - { - typeName = NewPoolTString(n.c_str()); - } - - TBasicType getBasicType() const { return type; } - void setBasicType(TBasicType t) { type = t; } - - TPrecision getPrecision() const { return precision; } - void setPrecision(TPrecision p) { precision = p; } - - TQualifier getQualifier() const { return qualifier; } - void setQualifier(TQualifier q) { qualifier = q; } - - // One-dimensional size of single instance type - int getNominalSize() const { return size; } - void setNominalSize(int s) { size = s; } - // Full size of single instance of type - int getObjectSize() const - { - if(isArray()) - { - return getElementSize() * std::max(getArraySize(), getMaxArraySize()); - } - else - { - return getElementSize(); - } - } - - int getElementSize() const - { - if(getBasicType() == EbtStruct) - { - return getStructSize(); - } - else if(matrix) - { - return size * size; - } - else // Vector or scalar - { - return size; - } - } - - int elementRegisterCount() const - { - TTypeList *structure = getStruct(); - - if(structure) - { - int registerCount = 0; - - for(size_t i = 0; i < structure->size(); i++) - { - registerCount += (*structure)[i].type->totalRegisterCount(); - } - - return registerCount; - } - else if(isMatrix()) - { - return getNominalSize(); - } - else - { - return 1; - } - } - - int totalRegisterCount() const - { - if(array) - { - return arraySize * elementRegisterCount(); - } - else - { - return elementRegisterCount(); - } - } - - bool isMatrix() const { return matrix ? true : false; } - void setMatrix(bool m) { matrix = m; } - - bool isArray() const { return array ? true : false; } - int getArraySize() const { return arraySize; } - void setArraySize(int s) { array = true; arraySize = s; } - int getMaxArraySize () const { return maxArraySize; } - void setMaxArraySize (int s) { maxArraySize = s; } - void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; } - void setArrayInformationType(TType* t) { arrayInformationType = t; } - TType* getArrayInformationType() const { return arrayInformationType; } - - bool isVector() const { return size > 1 && !matrix; } - bool isScalar() const { return size == 1 && !matrix && !structure; } - bool isRegister() const { return !matrix && !structure && !array; } // Fits in a 4-element register - bool isStruct() const { return structure != 0; } - - TTypeList* getStruct() const { return structure; } - void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); } - - const TString& getTypeName() const - { - assert(typeName); - return *typeName; - } - void setTypeName(const TString& n) - { - typeName = NewPoolTString(n.c_str()); - } - - bool isField() const { return fieldName != 0; } - const TString& getFieldName() const - { - assert(fieldName); - return *fieldName; - } - void setFieldName(const TString& n) - { - fieldName = NewPoolTString(n.c_str()); - } - - TString& getMangledName() { - if (!mangled) { - mangled = NewPoolTString(""); - buildMangledName(*mangled); - *mangled += ';' ; - } - - return *mangled; - } - - bool sameElementType(const TType& right) const { - return type == right.type && - size == right.size && - matrix == right.matrix && - structure == right.structure; - } - bool operator==(const TType& right) const { - return type == right.type && - size == right.size && - matrix == right.matrix && - array == right.array && (!array || arraySize == right.arraySize) && - structure == right.structure; - // don't check the qualifier, it's not ever what's being sought after - } - bool operator!=(const TType& right) const { - return !operator==(right); - } - bool operator<(const TType& right) const { - if (type != right.type) return type < right.type; - if (size != right.size) return size < right.size; - if (matrix != right.matrix) return matrix < right.matrix; - if (array != right.array) return array < right.array; - if (arraySize != right.arraySize) return arraySize < right.arraySize; - if (structure != right.structure) return structure < right.structure; - - return false; - } - - const char* getBasicString() const { return ::getBasicString(type); } - const char* getPrecisionString() const { return ::getPrecisionString(precision); } - const char* getQualifierString() const { return ::getQualifierString(qualifier); } - TString getCompleteString() const; - - // If this type is a struct, returns the deepest struct nesting of - // any field in the struct. For example: - // struct nesting1 { - // vec4 position; - // }; - // struct nesting2 { - // nesting1 field1; - // vec4 field2; - // }; - // For type "nesting2", this method would return 2 -- the number - // of structures through which indirection must occur to reach the - // deepest field (nesting2.field1.position). - int getDeepestStructNesting() const { return deepestStructNesting; } - - bool isStructureContainingArrays() const; - -protected: - void buildMangledName(TString&); - int getStructSize() const; - void computeDeepestStructNesting(); - - TBasicType type : 6; - TPrecision precision; - TQualifier qualifier : 7; - int size : 8; // size of vector or matrix, not size of array - unsigned int matrix : 1; - unsigned int array : 1; - int arraySize; - int maxArraySize; - TType* arrayInformationType; - - TTypeList* structure; // 0 unless this is a struct - mutable int structureSize; - int deepestStructNesting; - - TString *fieldName; // for structure field names - TString *mangled; - TString *typeName; // for structure field type name -}; - -// -// This is a workaround for a problem with the yacc stack, It can't have -// types that it thinks have non-trivial constructors. It should -// just be used while recognizing the grammar, not anything else. Pointers -// could be used, but also trying to avoid lots of memory management overhead. -// -// Not as bad as it looks, there is no actual assumption that the fields -// match up or are name the same or anything like that. -// -struct TPublicType -{ - TBasicType type; - TQualifier qualifier; - TPrecision precision; - int size; // size of vector or matrix, not size of array - bool matrix; - bool array; - int arraySize; - TType* userDef; - int line; - - void setBasic(TBasicType bt, TQualifier q, int ln = 0) - { - type = bt; - qualifier = q; - precision = EbpUndefined; - size = 1; - matrix = false; - array = false; - arraySize = 0; - userDef = 0; - line = ln; - } - - void setAggregate(int s, bool m = false) - { - size = s; - matrix = m; - } - - void setArray(bool a, int s = 0) - { - array = a; - arraySize = s; - } - - bool isStructureContainingArrays() const - { - if (!userDef) - { - return false; - } - - return userDef->isStructureContainingArrays(); - } -}; - -#endif // _TYPES_INCLUDED_ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _TYPES_INCLUDED +#define _TYPES_INCLUDED + +#include "compiler/BaseTypes.h" +#include "compiler/Common.h" +#include "compiler/debug.h" + +#include <algorithm> + +class TType; +struct TPublicType; + +// +// Need to have association of line numbers to types in a list for building structs. +// +struct TTypeLine { + TType* type; + int line; +}; +typedef TVector<TTypeLine> TTypeList; + +inline TTypeList* NewPoolTTypeList() +{ + void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TTypeList)); + return new(memory) TTypeList; +} + +// +// Base class for things that have a type. +// +class TType +{ +public: + POOL_ALLOCATOR_NEW_DELETE(); + TType() {} + TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) : + type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), + maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0) + { + } + explicit TType(const TPublicType &p); + TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) : + type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), + maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0) + { + typeName = NewPoolTString(n.c_str()); + } + + TBasicType getBasicType() const { return type; } + void setBasicType(TBasicType t) { type = t; } + + TPrecision getPrecision() const { return precision; } + void setPrecision(TPrecision p) { precision = p; } + + TQualifier getQualifier() const { return qualifier; } + void setQualifier(TQualifier q) { qualifier = q; } + + // One-dimensional size of single instance type + int getNominalSize() const { return size; } + void setNominalSize(int s) { size = s; } + // Full size of single instance of type + int getObjectSize() const + { + if(isArray()) + { + return getElementSize() * std::max(getArraySize(), getMaxArraySize()); + } + else + { + return getElementSize(); + } + } + + int getElementSize() const + { + if(getBasicType() == EbtStruct) + { + return getStructSize(); + } + else if(matrix) + { + return size * size; + } + else // Vector or scalar + { + return size; + } + } + + int elementRegisterCount() const + { + TTypeList *structure = getStruct(); + + if(structure) + { + int registerCount = 0; + + for(size_t i = 0; i < structure->size(); i++) + { + registerCount += (*structure)[i].type->totalRegisterCount(); + } + + return registerCount; + } + else if(isMatrix()) + { + return getNominalSize(); + } + else + { + return 1; + } + } + + int totalRegisterCount() const + { + if(array) + { + return arraySize * elementRegisterCount(); + } + else + { + return elementRegisterCount(); + } + } + + bool isMatrix() const { return matrix ? true : false; } + void setMatrix(bool m) { matrix = m; } + + bool isArray() const { return array ? true : false; } + int getArraySize() const { return arraySize; } + void setArraySize(int s) { array = true; arraySize = s; } + int getMaxArraySize () const { return maxArraySize; } + void setMaxArraySize (int s) { maxArraySize = s; } + void clearArrayness() { array = false; arraySize = 0; maxArraySize = 0; } + void setArrayInformationType(TType* t) { arrayInformationType = t; } + TType* getArrayInformationType() const { return arrayInformationType; } + + bool isVector() const { return size > 1 && !matrix; } + bool isScalar() const { return size == 1 && !matrix && !structure; } + bool isRegister() const { return !matrix && !structure && !array; } // Fits in a 4-element register + bool isStruct() const { return structure != 0; } + + TTypeList* getStruct() const { return structure; } + void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); } + + const TString& getTypeName() const + { + assert(typeName); + return *typeName; + } + void setTypeName(const TString& n) + { + typeName = NewPoolTString(n.c_str()); + } + + bool isField() const { return fieldName != 0; } + const TString& getFieldName() const + { + assert(fieldName); + return *fieldName; + } + void setFieldName(const TString& n) + { + fieldName = NewPoolTString(n.c_str()); + } + + TString& getMangledName() { + if (!mangled) { + mangled = NewPoolTString(""); + buildMangledName(*mangled); + *mangled += ';' ; + } + + return *mangled; + } + + bool sameElementType(const TType& right) const { + return type == right.type && + size == right.size && + matrix == right.matrix && + structure == right.structure; + } + bool operator==(const TType& right) const { + return type == right.type && + size == right.size && + matrix == right.matrix && + array == right.array && (!array || arraySize == right.arraySize) && + structure == right.structure; + // don't check the qualifier, it's not ever what's being sought after + } + bool operator!=(const TType& right) const { + return !operator==(right); + } + bool operator<(const TType& right) const { + if (type != right.type) return type < right.type; + if (size != right.size) return size < right.size; + if (matrix != right.matrix) return matrix < right.matrix; + if (array != right.array) return array < right.array; + if (arraySize != right.arraySize) return arraySize < right.arraySize; + if (structure != right.structure) return structure < right.structure; + + return false; + } + + const char* getBasicString() const { return ::getBasicString(type); } + const char* getPrecisionString() const { return ::getPrecisionString(precision); } + const char* getQualifierString() const { return ::getQualifierString(qualifier); } + TString getCompleteString() const; + + // If this type is a struct, returns the deepest struct nesting of + // any field in the struct. For example: + // struct nesting1 { + // vec4 position; + // }; + // struct nesting2 { + // nesting1 field1; + // vec4 field2; + // }; + // For type "nesting2", this method would return 2 -- the number + // of structures through which indirection must occur to reach the + // deepest field (nesting2.field1.position). + int getDeepestStructNesting() const { return deepestStructNesting; } + + bool isStructureContainingArrays() const; + +protected: + void buildMangledName(TString&); + int getStructSize() const; + void computeDeepestStructNesting(); + + TBasicType type : 6; + TPrecision precision; + TQualifier qualifier : 7; + int size : 8; // size of vector or matrix, not size of array + unsigned int matrix : 1; + unsigned int array : 1; + int arraySize; + int maxArraySize; + TType* arrayInformationType; + + TTypeList* structure; // 0 unless this is a struct + mutable int structureSize; + int deepestStructNesting; + + TString *fieldName; // for structure field names + TString *mangled; + TString *typeName; // for structure field type name +}; + +// +// This is a workaround for a problem with the yacc stack, It can't have +// types that it thinks have non-trivial constructors. It should +// just be used while recognizing the grammar, not anything else. Pointers +// could be used, but also trying to avoid lots of memory management overhead. +// +// Not as bad as it looks, there is no actual assumption that the fields +// match up or are name the same or anything like that. +// +struct TPublicType +{ + TBasicType type; + TQualifier qualifier; + TPrecision precision; + int size; // size of vector or matrix, not size of array + bool matrix; + bool array; + int arraySize; + TType* userDef; + int line; + + void setBasic(TBasicType bt, TQualifier q, int ln = 0) + { + type = bt; + qualifier = q; + precision = EbpUndefined; + size = 1; + matrix = false; + array = false; + arraySize = 0; + userDef = 0; + line = ln; + } + + void setAggregate(int s, bool m = false) + { + size = s; + matrix = m; + } + + void setArray(bool a, int s = 0) + { + array = a; + arraySize = s; + } + + bool isStructureContainingArrays() const + { + if (!userDef) + { + return false; + } + + return userDef->isStructureContainingArrays(); + } +}; + +#endif // _TYPES_INCLUDED_
diff --git a/src/OpenGL/compiler/ValidateLimitations.cpp b/src/OpenGL/compiler/ValidateLimitations.cpp index 5838d0f..9219cd1 100644 --- a/src/OpenGL/compiler/ValidateLimitations.cpp +++ b/src/OpenGL/compiler/ValidateLimitations.cpp
@@ -435,7 +435,7 @@ return true; bool valid = true; - TSymbolTable& symbolTable = GlobalParseContext->symbolTable; + TSymbolTable& symbolTable = GetGlobalParseContext()->symbolTable; TSymbol* symbol = symbolTable.find(node->getName()); ASSERT(symbol && symbol->isFunction()); TFunction* function = static_cast<TFunction*>(symbol);
diff --git a/src/OpenGL/compiler/intermediate.h b/src/OpenGL/compiler/intermediate.h index fe7c363..18b889f 100644 --- a/src/OpenGL/compiler/intermediate.h +++ b/src/OpenGL/compiler/intermediate.h
@@ -196,7 +196,7 @@ // class TIntermNode { public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + POOL_ALLOCATOR_NEW_DELETE(); TIntermNode() : line(0) {} @@ -510,8 +510,7 @@ class TIntermTraverser { public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) - + POOL_ALLOCATOR_NEW_DELETE(); TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : preVisit(preVisit), inVisit(inVisit),
diff --git a/src/OpenGL/compiler/localintermediate.h b/src/OpenGL/compiler/localintermediate.h index 253548d..805744f 100644 --- a/src/OpenGL/compiler/localintermediate.h +++ b/src/OpenGL/compiler/localintermediate.h
@@ -21,7 +21,7 @@ class TInfoSink; class TIntermediate { public: - POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) + POOL_ALLOCATOR_NEW_DELETE(); TIntermediate(TInfoSink& i) : infoSink(i) { } TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);