glsl_symbol_table: Add new talloc-based new()
authorCarl Worth <cworth@cworth.org>
Wed, 23 Jun 2010 22:47:04 +0000 (15:47 -0700)
committerCarl Worth <cworth@cworth.org>
Wed, 23 Jun 2010 23:35:45 +0000 (16:35 -0700)
We take advantage of overloading of the new operator (with an
additional parameter!) to make this look as "C++ like" as possible.

This closes 507 memory leaks when compiling glsl-orangebook-ch06-bump.frag
when measured with:

valgrind ./glsl glsl-orangebook-ch06-bump.frag

as seen here:

total heap usage: 55,623 allocs, 14,389 frees
(was 13,882 frees before)

glsl_symbol_table.h
ir.h
main.cpp

index 26b90fdb7c69346ca5c3af717bb9a938e24e517b..ae2fd3f4f1fef7dc592d40f01bdf05bb722c87f5 100644 (file)
@@ -26,6 +26,8 @@
 #ifndef GLSL_SYMBOL_TABLE
 #define GLSL_SYMBOL_TABLE
 
+#include <new>
+
 #include "symbol_table.h"
 #include "ir.h"
 #include "glsl_types.h"
@@ -44,7 +46,38 @@ private:
       glsl_function_name_space = 2
    };
 
+   static int
+   _glsl_symbol_table_destructor (glsl_symbol_table *table)
+   {
+      table->~glsl_symbol_table();
+
+      return 0;
+   }
+
 public:
+   /* Callers of this talloc-based new need not call delete. It's
+    * easier to just talloc_free 'ctx' (or any of its ancestors). */
+   static void* operator new(size_t size, void *ctx)
+   {
+      void *table;
+
+      table = talloc_size(ctx, size);
+      assert(table != NULL);
+
+      talloc_set_destructor(table, (int (*)(void*)) _glsl_symbol_table_destructor);
+
+      return table;
+   }
+
+   /* If the user *does* call delete, that's OK, we will just
+    * talloc_free in that case. Here, C++ will have already called the
+    * destructor so tell talloc not to do that again. */
+   static void operator delete(void *table)
+   {
+      talloc_set_destructor(table, NULL);
+      talloc_free(table);
+   }
+   
    glsl_symbol_table()
    {
       table = _mesa_symbol_table_ctor();
diff --git a/ir.h b/ir.h
index 9277f762042a96e4cddde348e0114994e321fd81..68e90653ed7ea1971891c8df7f1e4dba60aea07e 100644 (file)
--- a/ir.h
+++ b/ir.h
 #include <cstdio>
 #include <cstdlib>
 
+extern "C" {
+#include <talloc.h>
+}
+
 #include "list.h"
 #include "ir_visitor.h"
 #include "ir_hierarchical_visitor.h"
index f56e6f6142e6f8c79dcc66815473c2248907f115..dcd4b8f672557cf70b217905482fb97500a45ac8 100644 (file)
--- a/main.cpp
+++ b/main.cpp
 #include <fcntl.h>
 #include <unistd.h>
 
-extern "C" {
-#include <talloc.h>
-}
-
 #include "ast.h"
 #include "glsl_parser_extras.h"
 #include "glsl_parser.h"
@@ -118,7 +114,7 @@ compile_shader(struct glsl_shader *shader)
 
    state->scanner = NULL;
    state->translation_unit.make_empty();
-   state->symbols = new glsl_symbol_table;
+   state->symbols = new(shader) glsl_symbol_table;
    state->info_log = talloc_strdup(shader, "");
    state->error = false;
    state->temp_index = 0;