From a5ea9c63f72c0ecf5937a8b33a2e18160c79814a Mon Sep 17 00:00:00 2001
From: John Kessenich <cepheus@frii.com>
Date: Tue, 13 Aug 2013 00:58:49 +0000
Subject: [PATCH] Dynamically allocate symbol table containers, so timing of
 clean up can be more easily controlled WRT memory pool cleanup.

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@22681 e7fa87d3-cd2b-0410-9028-fcbf551c1848
---
 BuildLinux.sh                             |  5 ++-
 glslang/MachineIndependent/ShaderLang.cpp | 55 ++++++++++++-----------
 glslang/MachineIndependent/SymbolTable.h  | 38 ++++++++--------
 3 files changed, 51 insertions(+), 47 deletions(-)

diff --git a/BuildLinux.sh b/BuildLinux.sh
index fb7644380..ac85720d3 100755
--- a/BuildLinux.sh
+++ b/BuildLinux.sh
@@ -1,12 +1,13 @@
 #! /bin/bash
 
-rm -f StandAlone/StandAlone
+rm -f StandAlone/glsangValidator
+rm -f glslang/MachineIndependent/lib/libglslang.so
 
 # build the StandAlone app and all it's dependencies
 make -C StandAlone
 
 # so we can find the shared library
-LD_LIBRARY_PATH=`pwd`/glslang/MachineIndependent/lib:${LD_LIBRARY_PATH}
+LD_LIBRARY_PATH=`pwd`/glslang/MachineIndependent/lib
 export LD_LIBRARY_PATH
 
 # run using test data
diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp
index 7bdae0968..0d1c9ccfe 100644
--- a/glslang/MachineIndependent/ShaderLang.cpp
+++ b/glslang/MachineIndependent/ShaderLang.cpp
@@ -109,8 +109,6 @@ bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profil
     parseContext.scanContext = &scanContext;
     parseContext.ppContext = &ppContext;
     
-    assert(symbolTable.isEmpty() || symbolTable.atSharedBuiltInLevel());
-       
     //
     // Parse the built-ins.  This should only happen once per
     // language symbol table when no 'resources' are passed in.
@@ -140,29 +138,29 @@ bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profil
 //
 // To call for per-stage initialization, with the common table already complete.
 //
-void InitializeSymbolTable(TBuiltIns& builtIns, int version, EProfile profile, EShLanguage language, TInfoSink& infoSink, TSymbolTable* commonTable, TSymbolTable* symbolTables)
+void InitializeSymbolTable(TBuiltIns& builtIns, int version, EProfile profile, EShLanguage language, TInfoSink& infoSink, TSymbolTable** commonTable, TSymbolTable** symbolTables)
 {
     int commonIndex = EPcGeneral;
     if (profile == EEsProfile && language == EShLangFragment)
         commonIndex = EPcFragment;
 
-    symbolTables[language].adoptLevels(commonTable[commonIndex]);
-    InitializeSymbolTable(builtIns.getStageString(language), version, profile, language, infoSink, symbolTables[language]);
-    IdentifyBuiltIns(version, profile, language, symbolTables[language]);
+    (*symbolTables[language]).adoptLevels(*commonTable[commonIndex]);
+    InitializeSymbolTable(builtIns.getStageString(language), version, profile, language, infoSink, *symbolTables[language]);
+    IdentifyBuiltIns(version, profile, language, *symbolTables[language]);
     if (profile == EEsProfile)
-        symbolTables[language].setNoBuiltInRedeclarations();
+        (*symbolTables[language]).setNoBuiltInRedeclarations();
 }
 
-bool GenerateBuiltInSymbolTable(TInfoSink& infoSink, TSymbolTable* commonTable,  TSymbolTable* symbolTables, int version, EProfile profile)
+bool GenerateBuiltInSymbolTable(TInfoSink& infoSink, TSymbolTable** commonTable,  TSymbolTable** symbolTables, int version, EProfile profile)
 {
     TBuiltIns builtIns;
     
 	builtIns.initialize(version, profile);
 
     // do the common table
-    InitializeSymbolTable(builtIns.getCommonString(), version, profile, EShLangVertex, infoSink, commonTable[EPcGeneral]);
+    InitializeSymbolTable(builtIns.getCommonString(), version, profile, EShLangVertex, infoSink, *commonTable[EPcGeneral]);
     if (profile == EEsProfile)
-        InitializeSymbolTable(builtIns.getCommonString(), version, profile, EShLangFragment, infoSink, commonTable[EPcFragment]);
+        InitializeSymbolTable(builtIns.getCommonString(), version, profile, EShLangFragment, infoSink, *commonTable[EPcFragment]);
 
     // do the per-stage tables
     InitializeSymbolTable(builtIns, version, profile, EShLangVertex, infoSink, commonTable, symbolTables);
@@ -222,9 +220,15 @@ void SetupBuiltinSymbolTable(int version, EProfile profile)
     TPoolAllocator* builtInPoolAllocator = new TPoolAllocator();
     SetThreadPoolAllocator(*builtInPoolAllocator);
 
+    // Dynamically allocate the symbol tables so we can control when they are deallocated WRT the pool.
+    TSymbolTable* commonTable[EPcCount];
+    TSymbolTable* stageTables[EShLangCount];
+    for (int precClass = 0; precClass < EPcCount; ++precClass)
+        commonTable[precClass] = new TSymbolTable;
+    for (int stage = 0; stage < EShLangCount; ++stage)
+        stageTables[stage] = new TSymbolTable;
+
     // Generate the local symbol tables using the new pool
-    TSymbolTable commonTable[2];
-    TSymbolTable stageTables[EShLangCount];
     GenerateBuiltInSymbolTable(infoSink, commonTable, stageTables, version, profile);
 
     // Switch to the process-global pool
@@ -232,23 +236,23 @@ void SetupBuiltinSymbolTable(int version, EProfile profile)
 
     // Copy the local symbol tables from the new pool to the global tables using the process-global pool
     for (int precClass = 0; precClass < EPcCount; ++precClass) {
-        if (! commonTable[precClass].isEmpty()) {
+        if (! commonTable[precClass]->isEmpty()) {
             CommonSymbolTable[versionIndex][profile][precClass] = new TSymbolTable;
-            CommonSymbolTable[versionIndex][profile][precClass]->copyTable(commonTable[precClass]);
+            CommonSymbolTable[versionIndex][profile][precClass]->copyTable(*commonTable[precClass]);
         }
     }
     for (int stage = 0; stage < EShLangCount; ++stage) {
-        if (! stageTables[stage].isEmpty()) {
+        if (! stageTables[stage]->isEmpty()) {
             SharedSymbolTables[versionIndex][profile][stage] = new TSymbolTable;
-            SharedSymbolTables[versionIndex][profile][stage]->copyTable(stageTables[stage]);
+            SharedSymbolTables[versionIndex][profile][stage]->copyTable(*stageTables[stage]);
         }    
     }
 
-    // Explicitly clean up the local tables before deleting the pool they used and before releasing the lock.
+    // Clean up the local tables before deleting the pool they used.
     for (int precClass = 0; precClass < EPcCount; ++precClass)
-        commonTable[precClass].~TSymbolTable();
+        delete commonTable[precClass];
     for (int stage = 0; stage < EShLangCount; ++stage)
-        stageTables[stage].~TSymbolTable();
+        delete stageTables[stage];
 
     delete builtInPoolAllocator;
     SetThreadPoolAllocator(savedGPA);
@@ -458,7 +462,10 @@ int ShCompile(
     TSymbolTable* cachedTable = SharedSymbolTables[MapVersionToIndex(version)]
                                                   [profile]
                                                   [compiler->getLanguage()];
-    TSymbolTable symbolTable;
+    
+    // Dynamically allocate the symbol table so we can control when it is deallocated WRT the pool.
+    TSymbolTable* symbolTableMemory = new TSymbolTable;
+    TSymbolTable& symbolTable = *symbolTableMemory;
     if (cachedTable)
         symbolTable.adoptLevels(*cachedTable);
     
@@ -531,12 +538,8 @@ int ShCompile(
 
     intermediate.remove(parseContext.treeRoot);
 
-    //
-    // Ensure symbol table is returned to the built-in level,
-    // throwing away all but the built-ins.
-    //
-    while (! symbolTable.atSharedBuiltInLevel())
-        symbolTable.pop(0);
+    // Clean up the symbol table before deallocating the pool memory it used.
+    delete symbolTableMemory;
 
     //
     // Throw away all the temporary memory used by the compilation process.
diff --git a/glslang/MachineIndependent/SymbolTable.h b/glslang/MachineIndependent/SymbolTable.h
index 4bfae1851..d80721394 100644
--- a/glslang/MachineIndependent/SymbolTable.h
+++ b/glslang/MachineIndependent/SymbolTable.h
@@ -373,19 +373,13 @@ public:
     }
     ~TSymbolTable()
     {
+        // this can be called explicitly; safest to code it so it can be called multiple times
+
         // don't deallocate levels passed in from elsewhere
         while (table.size() > adoptedLevels)
             pop(0);
     }
 
-    //
-    // While level adopting is generic, the methods below enact a the following
-    // convention for levels:
-    //   0: common built-ins shared across all stages, all compiles, only one copy for all symbol tables
-    //   1: per-stage built-ins, shared across all compiles, but a different copy per stage
-    //   2: built-ins specific to a compile, like resources that are context-dependent
-    //   3: user-shader globals
-    //
     void adoptLevels(TSymbolTable& symTable)
     {
         for (unsigned int level = 0; level < symTable.table.size(); ++level) {
@@ -395,11 +389,21 @@ public:
         uniqueId = symTable.uniqueId;
         noBuiltInRedeclarations = symTable.noBuiltInRedeclarations;
     }
+
+    //
+    // While level adopting is generic, the methods below enact a the following
+    // convention for levels:
+    //   0: common built-ins shared across all stages, all compiles, only one copy for all symbol tables
+    //   1: per-stage built-ins, shared across all compiles, but a different copy per stage
+    //   2: built-ins specific to a compile, like resources that are context-dependent
+    //   3: user-shader globals
+    //
+protected:
+    static const int globalLevel = 3;
+public:
     bool isEmpty() { return table.size() == 0; }
-    bool atBuiltInLevel() { return atSharedBuiltInLevel() || atDynamicBuiltInLevel(); }
-    bool atSharedBuiltInLevel() { return table.size() <= 2; }
-    bool atDynamicBuiltInLevel() { return table.size() == 3; }
-    bool atGlobalLevel() { return table.size() <= 4; }
+    bool atBuiltInLevel() { return table.size() <= globalLevel; }      // exclude user globals
+    bool atGlobalLevel()  { return table.size() <= globalLevel + 1; }  // include user globals
 
     void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; }
     
@@ -411,7 +415,7 @@ public:
     void pop(TPrecisionQualifier *p)
     {
         table[currentLevel()]->getPreviousDefaultPrecisions(p);
-        delete table[currentLevel()];
+        delete table.back();
         table.pop_back();
     }
 
@@ -453,12 +457,8 @@ public:
 
     void relateToOperator(const char* name, TOperator op)
     {
-        for (unsigned int level = 0; level < table.size(); ++level) {
-            if (atSharedBuiltInLevel())
-                table[level]->relateToOperator(name, op);
-            else
-                break;
-        }
+        for (unsigned int level = 0; level < table.size(); ++level)
+            table[level]->relateToOperator(name, op);
     }
 
     int getMaxSymbolId() { return uniqueId; }
-- 
GitLab