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=crbug.com/181691
R=kbr@chromium.org

Review URL: https://codereview.appspot.com/11679046

Conflicts:
	src/compiler/ConstantUnion.h
	src/compiler/ShaderLang.cpp
	src/compiler/Types.h
	src/compiler/ValidateLimitations.cpp
diff --git a/src/compiler/Common.h b/src/compiler/Common.h
index 532486a..46f9440 100644
--- a/src/compiler/Common.h
+++ b/src/compiler/Common.h
@@ -24,14 +24,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 *) { }
 
 //
@@ -42,7 +42,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/compiler/Compiler.cpp b/src/compiler/Compiler.cpp
index 529c30a..768f32c 100644
--- a/src/compiler/Compiler.cpp
+++ b/src/compiler/Compiler.cpp
@@ -127,7 +127,7 @@
                                shaderType, shaderSpec, compileOptions, true,
                                sourcePath, infoSink);
     parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh;
-    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/compiler/ConstantUnion.h b/src/compiler/ConstantUnion.h
index 217e2b2..5fdba61 100644
--- a/src/compiler/ConstantUnion.h
+++ b/src/compiler/ConstantUnion.h
@@ -11,13 +11,13 @@
 
 class ConstantUnion {
 public:
+    POOL_ALLOCATOR_NEW_DELETE();
     ConstantUnion()
     {
         iConst = 0;
         type = EbtVoid;
     }
 
-    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
     void setIConst(int i) {iConst = i; type = EbtInt; }
     void setUConst(unsigned int u) { uConst = u; type = EbtUInt; }
     void setFConst(float f) {fConst = f; type = EbtFloat; }
diff --git a/src/compiler/InitializeDll.cpp b/src/compiler/InitializeDll.cpp
index 8763cfe..6c7f27f 100644
--- a/src/compiler/InitializeDll.cpp
+++ b/src/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/compiler/InitializeDll.h b/src/compiler/InitializeDll.h
index 857238e..43070cc 100644
--- a/src/compiler/InitializeDll.h
+++ b/src/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/compiler/InitializeGlobals.h b/src/compiler/InitializeGlobals.h
index 842a452..0715941 100644
--- a/src/compiler/InitializeGlobals.h
+++ b/src/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/compiler/InitializeParseContext.cpp b/src/compiler/InitializeParseContext.cpp
index 1f40cf5..dfab027 100644
--- a/src/compiler/InitializeParseContext.cpp
+++ b/src/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/compiler/InitializeParseContext.h b/src/compiler/InitializeParseContext.h
index aa53b73..bffbab8 100644
--- a/src/compiler/InitializeParseContext.h
+++ b/src/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/compiler/PoolAlloc.cpp b/src/compiler/PoolAlloc.cpp
index 3f0f5a6..eb99356 100644
--- a/src/compiler/PoolAlloc.cpp
+++ b/src/compiler/PoolAlloc.cpp
@@ -17,55 +17,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/compiler/PoolAlloc.h b/src/compiler/PoolAlloc.h
index a8a59c6..edd249c 100644
--- a/src/compiler/PoolAlloc.h
+++ b/src/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/compiler/ShaderLang.cpp b/src/compiler/ShaderLang.cpp
index 48dc0a0..1551dad 100644
--- a/src/compiler/ShaderLang.cpp
+++ b/src/compiler/ShaderLang.cpp
@@ -99,9 +99,7 @@
 //
 int ShFinalize()
 {
-    if (!DetachProcess())
-        return 0;
-
+    DetachProcess();
     return 1;
 }
 
@@ -149,9 +147,6 @@
                              ShShaderOutput output,
                              const ShBuiltInResources* resources)
 {
-    if (!InitThread())
-        return 0;
-
     TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output));
     TCompiler* compiler = base->getAsCompiler();
     if (compiler == 0)
@@ -190,9 +185,6 @@
     size_t numStrings,
     int compileOptions)
 {
-    if (!InitThread())
-        return 0;
-
     if (handle == 0)
         return 0;
 
diff --git a/src/compiler/SymbolTable.h b/src/compiler/SymbolTable.h
index 9e9beb5..7fa2c9c 100644
--- a/src/compiler/SymbolTable.h
+++ b/src/compiler/SymbolTable.h
@@ -41,9 +41,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; }
@@ -193,7 +194,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/compiler/Types.h b/src/compiler/Types.h
index c71a053..facb578 100644
--- a/src/compiler/Types.h
+++ b/src/compiler/Types.h
@@ -19,7 +19,7 @@
 class TField
 {
 public:
-    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator);
+    POOL_ALLOCATOR_NEW_DELETE();
     TField(TType* type, TString* name, const TSourceLoc& line) : mType(type), mName(name), mLine(line) {}
 
     // TODO(alokp): We should only return const type.
@@ -40,7 +40,7 @@
 typedef TVector<TField*> TFieldList;
 inline TFieldList* NewPoolTFieldList()
 {
-    void* memory = GlobalPoolAllocator.allocate(sizeof(TFieldList));
+    void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList));
     return new(memory) TFieldList;
 }
 
@@ -82,7 +82,7 @@
 class TStructure : public TFieldListCollection
 {
 public:
-    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator);
+    POOL_ALLOCATOR_NEW_DELETE();
     TStructure(const TString* name, TFieldList* fields)
         : TFieldListCollection(name, fields),
           mDeepestNesting(0) {
@@ -106,7 +106,7 @@
 class TInterfaceBlock : public TFieldListCollection
 {
 public:
-    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator);
+    POOL_ALLOCATOR_NEW_DELETE();
     TInterfaceBlock(const TString* name, TFieldList* fields, const TString* instanceName, int arraySize, const TLayoutQualifier& layoutQualifier)
         : TFieldListCollection(name, fields),
           mInstanceName(instanceName),
@@ -138,7 +138,7 @@
 class TType
 {
 public:
-    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
+    POOL_ALLOCATOR_NEW_DELETE();
     TType() {}
     TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int ps = 1, int ss = 1, bool a = false) :
             type(t), precision(p), qualifier(q), primarySize(ps), secondarySize(ss), array(a), layoutQualifier(TLayoutQualifier::create()), arraySize(0),
diff --git a/src/compiler/ValidateLimitations.cpp b/src/compiler/ValidateLimitations.cpp
index 164c187..8a34f2b 100644
--- a/src/compiler/ValidateLimitations.cpp
+++ b/src/compiler/ValidateLimitations.cpp
@@ -439,8 +439,8 @@
         return true;
 
     bool valid = true;
-    TSymbolTable& symbolTable = GlobalParseContext->symbolTable;
-    TSymbol* symbol = symbolTable.find(node->getName(), GlobalParseContext->shaderVersion);
+    TSymbolTable& symbolTable = GetGlobalParseContext()->symbolTable;
+    TSymbol* symbol = symbolTable.find(node->getName(), GetGlobalParseContext()->shaderVersion);
     ASSERT(symbol && symbol->isFunction());
     TFunction* function = static_cast<TFunction*>(symbol);
     for (ParamIndex::const_iterator i = pIndex.begin();
diff --git a/src/compiler/intermediate.h b/src/compiler/intermediate.h
index 17571bd..efc3a6e 100644
--- a/src/compiler/intermediate.h
+++ b/src/compiler/intermediate.h
@@ -216,8 +216,7 @@
 //
 class TIntermNode {
 public:
-    POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
-
+    POOL_ALLOCATOR_NEW_DELETE();
     TIntermNode() {
         // TODO: Move this to TSourceLoc constructor
         // after getting rid of TPublicType.
@@ -555,8 +554,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/compiler/localintermediate.h b/src/compiler/localintermediate.h
index db35250..74020cb 100644
--- a/src/compiler/localintermediate.h
+++ b/src/compiler/localintermediate.h
@@ -21,9 +21,9 @@
 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&, const TSourceLoc&);
     TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
     TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);