Properly free the slang_ir_node->Store data (use ref counting).
authorBrian <brian@yutani.localnet.net>
Sat, 24 Mar 2007 16:18:14 +0000 (10:18 -0600)
committerBrian <brian@yutani.localnet.net>
Sat, 24 Mar 2007 16:18:14 +0000 (10:18 -0600)
src/mesa/shader/slang/slang_ir.c
src/mesa/shader/slang/slang_ir.h

index 5790d0ab7f5d2e17bd4bd39e18430c53b50a268d..11c09d33a21bf1582236600588c5c4c9ccec70f6 100644 (file)
@@ -106,33 +106,65 @@ _slang_ir_info(slang_ir_opcode opcode)
    return NULL;
 }
 
+
 static const char *
-slang_ir_name(slang_ir_opcode opcode)
+_slang_ir_name(slang_ir_opcode opcode)
 {
    return _slang_ir_info(opcode)->IrName;
 }
 
 
-
 /**
- * Recursively free an IR tree.
+ * Since many IR nodes might point to the same IR storage info, we need
+ * to be careful when deleting things.
+ * Before deleting an IR tree, traverse it and do refcounting on the
+ * IR storage nodes.  Use the refcount info during delete to free things
+ * properly.
  */
-void
-_slang_free_ir_tree(slang_ir_node *n)
+static void
+_slang_refcount_storage(slang_ir_node *n)
 {
-#if 1
    GLuint i;
    if (!n)
       return;
+   if (n->Store)
+      n->Store->RefCount++;
+   for (i = 0; i < 3; i++)
+      _slang_refcount_storage(n->Children[i]);
+}
+
+
+static void
+_slang_free_ir(slang_ir_node *n)
+{
+   GLuint i;
+   if (!n)
+      return;
+
+   if (n->Store) {
+      n->Store->RefCount--;
+      if (n->Store->RefCount == 0) {
+         free(n->Store);
+         n->Store = NULL;
+      }
+   }
+
    for (i = 0; i < 3; i++)
       _slang_free_ir_tree(n->Children[i]);
    /* Do not free n->List since it's a child elsewhere */
    free(n);
-#endif
 }
 
 
-
+/**
+ * Recursively free an IR tree.
+ */
+void
+_slang_free_ir_tree(slang_ir_node *n)
+{
+   _slang_refcount_storage(n);
+   _slang_free_ir(n);
+}
 
 
 
@@ -149,6 +181,7 @@ swizzle_string(GLuint swizzle)
    return s;
 }
 
+
 static const char *
 writemask_string(GLuint writemask)
 {
@@ -163,6 +196,7 @@ writemask_string(GLuint writemask)
    return s;
 }
 
+
 static const char *
 storage_string(const slang_ir_storage *st)
 {
@@ -204,12 +238,11 @@ spaces(int n)
 }
 
 
-#define IND 0
-
-
 void
 _slang_print_ir_tree(const slang_ir_node *n, int indent)
 {
+#define IND 0
+
    if (!n)
       return;
 #if !IND
@@ -346,7 +379,7 @@ _slang_print_ir_tree(const slang_ir_node *n, int indent)
       _slang_print_ir_tree(n->Children[0], indent + 3);
       break;
    default:
-      printf("%s (%p, %p)  (store %p)\n", slang_ir_name(n->Opcode),
+      printf("%s (%p, %p)  (store %p)\n", _slang_ir_name(n->Opcode),
              (void*) n->Children[0], (void*) n->Children[1], (void*) n->Store);
       _slang_print_ir_tree(n->Children[0], indent+3);
       _slang_print_ir_tree(n->Children[1], indent+3);
index 2b7d8229326c73cf68354acdd2dbd2f80d205707..2e90409cafdd9da838994c609c7cbd341d4c81a5 100644 (file)
@@ -147,6 +147,7 @@ struct _slang_ir_storage
    GLint Index;  /**< -1 means unallocated */
    GLint Size;  /**< number of floats */
    GLuint Swizzle;
+   GLint RefCount; /**< Used during IR tree delete */
 };
 
 typedef struct _slang_ir_storage slang_ir_storage;