summaryrefslogtreecommitdiffstats
path: root/src/glsl/glsl_parser_extras.cpp
diff options
context:
space:
mode:
authorIan Romanick <[email protected]>2014-07-14 15:48:34 -0700
committerKenneth Graunke <[email protected]>2014-08-04 15:48:09 -0700
commit7b1898314709e3e70571c491f7f62745c05e13e1 (patch)
tree6c0256572d9bb20d98a69aea1b11eb9b9c83e724 /src/glsl/glsl_parser_extras.cpp
parent3d051772c8ef0f14f5ab3ccd954b5b3bb65e6ba7 (diff)
glsl: Rebuild the symbol table without unreachable symbols
Previously we had to keep unreachable global symbols in the symbol table because the symbol table is used during linking. Having the symbol table retain pointers to freed memory... what could possibly go wrong? At the same time, this meant that we kept live references to tons of memory that was no longer needed. New strategy: destroy the old symbol table, and make a new one from the reachable symbols. Valgrind massif results for a trimmed apitrace of dota2: n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) Before (32-bit): 59 40,642,425,451 76,337,968 69,720,886 6,617,082 0 After (32-bit): 46 40,661,487,174 75,116,800 68,854,065 6,262,735 0 Before (64-bit): 79 37,179,441,771 106,986,512 98,112,095 8,874,417 0 After (64-bit): 64 37,200,329,700 104,872,672 96,514,546 8,358,126 0 A real savings of 846KiB on 32-bit and 1.5MiB on 64-bit. v2: (by Kenneth Graunke) Just add the ir_function from the IR stream, rather than looking it up in the symbol table; they're now identical. Signed-off-by: Ian Romanick <[email protected]> Reviewed-by: Kenneth Graunke <[email protected]>
Diffstat (limited to 'src/glsl/glsl_parser_extras.cpp')
-rw-r--r--src/glsl/glsl_parser_extras.cpp26
1 files changed, 25 insertions, 1 deletions
diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp
index e5c2dfee364..2d94d3554cd 100644
--- a/src/glsl/glsl_parser_extras.cpp
+++ b/src/glsl/glsl_parser_extras.cpp
@@ -1487,7 +1487,7 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
if (shader->InfoLog)
ralloc_free(shader->InfoLog);
- shader->symbols = state->symbols;
+ shader->symbols = new(shader->ir) glsl_symbol_table;
shader->CompileStatus = !state->error;
shader->InfoLog = state->info_log;
shader->Version = state->language_version;
@@ -1500,6 +1500,30 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader,
/* Retain any live IR, but trash the rest. */
reparent_ir(shader->ir, shader->ir);
+ /* Destroy the symbol table. Create a new symbol table that contains only
+ * the variables and functions that still exist in the IR. The symbol
+ * table will be used later during linking.
+ *
+ * There must NOT be any freed objects still referenced by the symbol
+ * table. That could cause the linker to dereference freed memory.
+ *
+ * We don't have to worry about types or interface-types here because those
+ * are fly-weights that are looked up by glsl_type.
+ */
+ foreach_in_list (ir_instruction, ir, shader->ir) {
+ switch (ir->ir_type) {
+ case ir_type_function:
+ shader->symbols->add_function((ir_function *) ir);
+ break;
+ case ir_type_variable:
+ shader->symbols->add_variable((ir_variable *) ir);
+ break;
+ default:
+ break;
+ }
+ }
+
+ delete state->symbols;
ralloc_free(state);
}