[Mesa-dev] [PATCH 02/26] glsl: Rebuild the symbol table without unreachable symbols

Kenneth Graunke kenneth at whitecape.org
Tue Jul 15 20:05:31 PDT 2014


On Monday, July 14, 2014 03:48:34 PM Ian Romanick wrote:
> From: Ian Romanick <ian.d.romanick at intel.com>
> 
> 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.
> 
> Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
> Cc: Kenneth Graunke <kenneth at whitecape.org>
> ---
>  src/glsl/glsl_parser_extras.cpp | 37 ++++++++++++++++++++++++++++++++++++-
>  1 file changed, 36 insertions(+), 1 deletion(-)
> 
> diff --git a/src/glsl/glsl_parser_extras.cpp 
b/src/glsl/glsl_parser_extras.cpp
> index b327c2b..2962407 100644
> --- a/src/glsl/glsl_parser_extras.cpp
> +++ b/src/glsl/glsl_parser_extras.cpp
> @@ -1485,7 +1485,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;
> @@ -1498,6 +1498,41 @@ _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: {
> +         /* If the function is a built-in that is partially overridden in 
the
> +          * shader, the ir_function stored in the symbol table may not be 
the
> +          * same as the one that appears in the shader.  The one in the 
shader
> +          * will only include definitions from inside the shader.  We need 
the
> +          * one from the symbol table because it will include built-in
> +          * defintions and definitions from the shader.
> +          */
> +         ir_function *const def = (ir_function *) ir;
> +         ir_function *const decl = state->symbols->get_function(def->name);

Huh.  This doesn't match my understanding of the code.  I believe there 
should only be one ir_function with a given name, and it should be both in the 
shader's instruction stream and in the symbol table.

That single ir_function should contain any definitions and prototypes created 
in the shader's GLSL code, and also prototypes (but not definitions) for any 
built-in signatures called.

If you look at match_function_by_name(), it always uses the existing function, 
if there is one, or creates a new one and adds it in both places...walking 
through a couple scenarios, I haven't seen what's going wrong.

I suppose I should try the obvious

   shader->symobls->add_function((ir_function *) ir);

and see what breaks.  It sure doesn't seem like anything should.  I'll try to 
look into it soon.

> +         shader->symbols->add_function(decl);
> +         break;
> +      }
> +      case ir_type_variable:
> +         shader->symbols->add_variable((ir_variable *) ir);
> +         break;
> +      default:
> +         break;
> +      }
> +   }
> +
> +   delete state->symbols;
>     ralloc_free(state);
>  }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20140715/7e0f3720/attachment.sig>


More information about the mesa-dev mailing list