Moved the global-pool-allocator to TCompiler so that all memory allocated by the compiler can be de-allocated. Earlier the global-pool-allocator kept accumulating memory from all compilers (symbol-table in particular). The memory was only de-allocated when gpu-process exited or ShFinalize() was called. This was a problem for Chromium which keeps the GPU process around for the browser session. Now the memory is de-allocated as soon as the compiler is deleted, which happens when a tab is closed.
BUG=58808 (crbug.com)
Review URL: http://codereview.appspot.com/3280041
git-svn-id: http://angleproject.googlecode.com/svn/trunk@489 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/Compiler.cpp b/src/compiler/Compiler.cpp
index 322595b..11acfae 100644
--- a/src/compiler/Compiler.cpp
+++ b/src/compiler/Compiler.cpp
@@ -8,10 +8,11 @@
#include "compiler/ParseHelper.h"
#include "compiler/ShHandle.h"
-static bool InitializeSymbolTable(
- const TBuiltInStrings& builtInStrings,
- ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources,
- TInfoSink& infoSink, TSymbolTable& symbolTable)
+namespace {
+bool InitializeSymbolTable(
+ const TBuiltInStrings& builtInStrings,
+ ShShaderType type, ShShaderSpec spec, const ShBuiltInResources& resources,
+ TInfoSink& infoSink, TSymbolTable& symbolTable)
{
TIntermediate intermediate(infoSink);
TExtensionBehavior extBehavior;
@@ -49,6 +50,34 @@
return true;
}
+class TScopedPoolAllocator {
+public:
+ TScopedPoolAllocator(TPoolAllocator* allocator, bool pushPop)
+ : mAllocator(allocator), mPushPopAllocator(pushPop) {
+ if (mPushPopAllocator) mAllocator->push();
+ SetGlobalPoolAllocator(mAllocator);
+ }
+ ~TScopedPoolAllocator() {
+ SetGlobalPoolAllocator(NULL);
+ if (mPushPopAllocator) mAllocator->pop();
+ }
+
+private:
+ TPoolAllocator* mAllocator;
+ bool mPushPopAllocator;
+};
+} // namespace
+
+TShHandleBase::TShHandleBase() {
+ allocator.push();
+ SetGlobalPoolAllocator(&allocator);
+}
+
+TShHandleBase::~TShHandleBase() {
+ SetGlobalPoolAllocator(NULL);
+ allocator.popAll();
+}
+
TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
: shaderType(type),
shaderSpec(spec)
@@ -61,11 +90,13 @@
bool TCompiler::Init(const ShBuiltInResources& resources)
{
+ TScopedPoolAllocator scopedAlloc(&allocator, false);
+
// Generate built-in symbol table.
if (!InitBuiltInSymbolTable(resources))
return false;
-
InitExtensionBehavior(resources, extensionBehavior);
+
return true;
}
@@ -73,6 +104,7 @@
const int numStrings,
int compileOptions)
{
+ TScopedPoolAllocator scopedAlloc(&allocator, true);
clearResults();
if (numStrings == 0)
diff --git a/src/compiler/PoolAlloc.cpp b/src/compiler/PoolAlloc.cpp
index 8cbe560..ff44353 100644
--- a/src/compiler/PoolAlloc.cpp
+++ b/src/compiler/PoolAlloc.cpp
@@ -22,14 +22,10 @@
if (globalPools)
return;
- TPoolAllocator *globalPoolAllocator = new TPoolAllocator(true);
-
TThreadGlobalPools* threadData = new TThreadGlobalPools();
-
- threadData->globalPoolAllocator = globalPoolAllocator;
-
- OS_SetTLSValue(PoolIndex, threadData);
- globalPoolAllocator->push();
+ threadData->globalPoolAllocator = 0;
+
+ OS_SetTLSValue(PoolIndex, threadData);
}
void FreeGlobalPools()
@@ -38,9 +34,7 @@
TThreadGlobalPools* globalPools= static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
if (!globalPools)
return;
-
- GlobalPoolAllocator.popAll();
- delete &GlobalPoolAllocator;
+
delete globalPools;
}
@@ -66,7 +60,7 @@
return *threadData->globalPoolAllocator;
}
-void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator)
+void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator)
{
TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
@@ -77,8 +71,7 @@
// Implement the functionality of the TPoolAllocator class, which
// is documented in PoolAlloc.h.
//
-TPoolAllocator::TPoolAllocator(bool g, int growthIncrement, int allocationAlignment) :
- global(g),
+TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) :
pageSize(growthIncrement),
alignment(allocationAlignment),
freeList(0),
@@ -124,24 +117,14 @@
TPoolAllocator::~TPoolAllocator()
{
- if (!global) {
- //
- // Then we know that this object is not being
- // allocated after other, globally scoped objects
- // that depend on it. So we can delete the "in use" memory.
- //
- while (inUseList) {
- tHeader* next = inUseList->nextPage;
- inUseList->~tHeader();
- delete [] reinterpret_cast<char*>(inUseList);
- inUseList = next;
- }
+ while (inUseList) {
+ tHeader* next = inUseList->nextPage;
+ inUseList->~tHeader();
+ delete [] reinterpret_cast<char*>(inUseList);
+ inUseList = next;
}
- //
- // Always delete the free list memory - it can't be being
- // (correctly) referenced, whether the pool allocator was
- // global or not. We should not check the guard blocks
+ // We should not check the guard blocks
// here, because we did it already when the block was
// placed into the free list.
//
diff --git a/src/compiler/PoolAlloc.h b/src/compiler/PoolAlloc.h
index 645db78..55e09db 100644
--- a/src/compiler/PoolAlloc.h
+++ b/src/compiler/PoolAlloc.h
@@ -115,7 +115,7 @@
//
class TPoolAllocator {
public:
- TPoolAllocator(bool global = false, int growthIncrement = 8*1024, int allocationAlignment = 16);
+ TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16);
//
// Don't call the destructor just to free up the memory, call pop()
@@ -194,7 +194,6 @@
return TAllocation::offsetAllocation(memory);
}
- bool global; // should be true if this object is globally scoped
size_t pageSize; // granularity of allocation from the OS
size_t alignment; // all returned allocations will be aligned at
// this granularity, which will be a power of 2
@@ -220,18 +219,15 @@
// different times. But a simple use is to have a global pop
// with everyone using the same global allocator.
//
-typedef TPoolAllocator* PoolAllocatorPointer;
extern TPoolAllocator& GetGlobalPoolAllocator();
+extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator);
#define GlobalPoolAllocator GetGlobalPoolAllocator()
-
struct TThreadGlobalPools
{
TPoolAllocator* globalPoolAllocator;
};
-void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator);
-
//
// This STL compatible allocator is intended to be used as the allocator
// parameter to templatized STL containers, like vector and map.
diff --git a/src/compiler/ShHandle.h b/src/compiler/ShHandle.h
index 385259e..4e2affe 100644
--- a/src/compiler/ShHandle.h
+++ b/src/compiler/ShHandle.h
@@ -28,9 +28,14 @@
//
class TShHandleBase {
public:
- TShHandleBase() { }
- virtual ~TShHandleBase() { }
+ TShHandleBase();
+ virtual ~TShHandleBase();
virtual TCompiler* getAsCompiler() { return 0; }
+
+protected:
+ // Memory allocator. Allocates and tracks memory required by the compiler.
+ // Deallocates all memory when compiler is destructed.
+ TPoolAllocator allocator;
};
//
diff --git a/src/compiler/ShaderLang.cpp b/src/compiler/ShaderLang.cpp
index c5eaf30..f4cccc6 100644
--- a/src/compiler/ShaderLang.cpp
+++ b/src/compiler/ShaderLang.cpp
@@ -161,15 +161,7 @@
if (compiler == 0)
return 0;
- GlobalPoolAllocator.push();
-
bool success = compiler->compile(shaderStrings, numStrings, compileOptions);
-
- //
- // Throw away all the temporary memory used by the compilation process.
- //
- GlobalPoolAllocator.pop();
-
return success ? 1 : 0;
}