Minor refactoring of TSymbolTable.

Used pointers for precision-stack entries as well to avoid unnecessarily re-allocating PrecisionStackLevel whenever the vector needs to resize.

Added a scoped class to properly restore symbol-table level after each compile.

R=kbr@chromium.org

Review URL: https://codereview.appspot.com/12583047
diff --git a/src/compiler/Compiler.cpp b/src/compiler/Compiler.cpp
index 1f5eb16..37b5ab2 100644
--- a/src/compiler/Compiler.cpp
+++ b/src/compiler/Compiler.cpp
@@ -30,19 +30,32 @@
 namespace {
 class TScopedPoolAllocator {
 public:
-    TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
-        : mAllocator(allocator), mPushPopAllocator(pushPop) {
-        if (mPushPopAllocator) mAllocator->push();
+    TScopedPoolAllocator(TPoolAllocator* allocator) : mAllocator(allocator) {
+        mAllocator->push();
         SetGlobalPoolAllocator(mAllocator);
     }
     ~TScopedPoolAllocator() {
         SetGlobalPoolAllocator(NULL);
-        if (mPushPopAllocator) mAllocator->pop();
+        mAllocator->pop();
     }
 
 private:
     TPoolAllocator* mAllocator;
-    bool mPushPopAllocator;
+};
+
+class TScopedSymbolTableLevel {
+public:
+    TScopedSymbolTableLevel(TSymbolTable* table) : mTable(table) {
+        ASSERT(mTable->atBuiltInLevel());
+        mTable->push();
+    }
+    ~TScopedSymbolTableLevel() {
+        while (!mTable->atBuiltInLevel())
+            mTable->pop();
+    }
+
+private:
+    TSymbolTable* mTable;
 };
 }  // namespace
 
@@ -83,7 +96,8 @@
         resources.MaxFragmentUniformVectors;
     maxExpressionComplexity = resources.MaxExpressionComplexity;
     maxCallStackDepth = resources.MaxCallStackDepth;
-    TScopedPoolAllocator scopedAlloc(&allocator, false);
+
+    SetGlobalPoolAllocator(&allocator);
 
     // Generate built-in symbol table.
     if (!InitBuiltInSymbolTable(resources))
@@ -103,7 +117,7 @@
                         size_t numStrings,
                         int compileOptions)
 {
-    TScopedPoolAllocator scopedAlloc(&allocator, true);
+    TScopedPoolAllocator scopedAlloc(&allocator);
     clearResults();
 
     if (numStrings == 0)
@@ -131,11 +145,7 @@
 
     // We preserve symbols at the built-in level from compile-to-compile.
     // Start pushing the user-defined symbols at global level.
-    symbolTable.push();
-    if (!symbolTable.atGlobalLevel()) {
-        infoSink.info.prefix(EPrefixInternalError);
-        infoSink.info << "Wrong symbol table level";
-    }
+    TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable);
 
     // Parse shader.
     bool success =
@@ -206,10 +216,6 @@
 
     // Cleanup memory.
     intermediate.remove(parseContext.treeRoot);
-    // Ensure symbol table is returned to the built-in level,
-    // throwing away all but the built-ins.
-    while (!symbolTable.atBuiltInLevel())
-        symbolTable.pop();
 
     return success;
 }
diff --git a/src/compiler/SymbolTable.cpp b/src/compiler/SymbolTable.cpp
index f9daad4..1132386 100644
--- a/src/compiler/SymbolTable.cpp
+++ b/src/compiler/SymbolTable.cpp
@@ -246,3 +246,9 @@
 
     return 0;
 }
+
+TSymbolTable::~TSymbolTable()
+{
+    while (table.size() > 0)
+        pop();
+}
diff --git a/src/compiler/SymbolTable.h b/src/compiler/SymbolTable.h
index 7fa2c9c..d4849d2 100644
--- a/src/compiler/SymbolTable.h
+++ b/src/compiler/SymbolTable.h
@@ -42,7 +42,7 @@
 class TSymbol {    
 public:
     POOL_ALLOCATOR_NEW_DELETE();
-    TSymbol(const TString *n) :  name(n) { }
+    TSymbol(const TString* n) :  uniqueId(0), name(n) { }
     virtual ~TSymbol() { /* don't delete name, it's from the pool */ }
 
     const TString& getName() const { return *name; }
@@ -57,8 +57,8 @@
 private:
     DISALLOW_COPY_AND_ASSIGN(TSymbol);
 
+    int uniqueId;      // For real comparing during code generation
     const TString *name;
-    unsigned int uniqueId;      // For real comparing during code generation
     TString extension;
 };
 
@@ -194,7 +194,6 @@
     typedef const tLevel::value_type tLevelPair;
     typedef std::pair<tLevel::iterator, bool> tInsertResult;
 
-    POOL_ALLOCATOR_NEW_DELETE();
     TSymbolTableLevel() { }
     ~TSymbolTableLevel();
 
@@ -205,8 +204,7 @@
         //
         // returning true means symbol was added to the table
         //
-        tInsertResult result;
-        result = level.insert(tLevelPair(name, &symbol));
+        tInsertResult result = level.insert(tLevelPair(name, &symbol));
 
         return result.second;
     }
@@ -253,11 +251,7 @@
         //
     }
 
-    ~TSymbolTable()
-    {
-        while (table.size() > 0)
-            pop();
-    }
+    ~TSymbolTable();
 
     //
     // When the symbol table is initialized with the built-ins, there should
@@ -270,13 +264,15 @@
     void push()
     {
         table.push_back(new TSymbolTableLevel);
-        precisionStack.push_back( PrecisionStackLevel() );
+        precisionStack.push_back(new PrecisionStackLevel);
     }
 
     void pop()
-    { 
-        delete table[currentLevel()]; 
-        table.pop_back(); 
+    {
+        delete table.back();
+        table.pop_back();
+
+        delete precisionStack.back();
         precisionStack.pop_back();
     }
 
@@ -333,8 +329,9 @@
     void relateToExtension(ESymbolLevel level, const char* name, const TString& ext) {
         table[level]->relateToExtension(name, ext);
     }
+    void dump(TInfoSink &infoSink) const;
 
-    bool setDefaultPrecision( const TPublicType& type, TPrecision prec ){
+    bool setDefaultPrecision(const TPublicType& type, TPrecision prec) {
         if (IsSampler(type.type))
             return true;  // Skip sampler types for the time being
         if (type.type != EbtFloat && type.type != EbtInt)
@@ -342,7 +339,7 @@
         if (type.isAggregate())
             return false; // Not allowed to set for aggregate types
         int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
-        precisionStack[indexOfLastElement][type.type] = prec; // Uses map operator [], overwrites the current value
+        (*precisionStack[indexOfLastElement])[type.type] = prec; // Uses map operator [], overwrites the current value
         return true;
     }
 
@@ -350,16 +347,19 @@
     TPrecision getDefaultPrecision( TBasicType type){
 
         // unsigned integers use the same precision as signed
-        if (type == EbtUInt) type = EbtInt;
+        if (type == EbtUInt)
+            type = EbtInt;
 
-        if( type != EbtFloat && type != EbtInt ) return EbpUndefined;
+        if (type != EbtFloat && type != EbtInt)
+            return EbpUndefined;
+
         int level = static_cast<int>(precisionStack.size()) - 1;
-        assert( level >= 0); // Just to be safe. Should not happen.
+        assert(level >= 0); // Just to be safe. Should not happen.
         PrecisionStackLevel::iterator it;
         TPrecision prec = EbpUndefined; // If we dont find anything we return this. Should we error check this?
-        while( level >= 0 ){
-            it = precisionStack[level].find( type );
-            if( it != precisionStack[level].end() ){
+        while (level >= 0) {
+            it = precisionStack[level]->find(type);
+            if (it != precisionStack[level]->end()) {
                 prec = (*it).second;
                 break;
             }
@@ -368,12 +368,12 @@
         return prec;
     }
 
-protected:
+private:
     ESymbolLevel currentLevel() const { return static_cast<ESymbolLevel>(table.size() - 1); }
 
     std::vector<TSymbolTableLevel*> table;
-    typedef std::map< TBasicType, TPrecision > PrecisionStackLevel;
-    std::vector< PrecisionStackLevel > precisionStack;
+    typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
+    std::vector< PrecisionStackLevel*> precisionStack;
 };
 
 #endif // _SYMBOL_TABLE_INCLUDED_