diff options
author | David Malcolm <dmalcolm@redhat.com> | 2014-12-01 17:40:03 +0000 |
---|---|---|
committer | David Malcolm <dmalcolm@gcc.gnu.org> | 2014-12-01 17:40:03 +0000 |
commit | 52b9468f1575b87e490cc3fdcff4c51f25fb49c1 (patch) | |
tree | f16b19ca2feb631733943e067ce5d2a3f52f9b23 /gcc/jit | |
parent | 33b625ed6060fea016d99cf268cc68287a93ca0c (diff) | |
download | gcc-52b9468f1575b87e490cc3fdcff4c51f25fb49c1.zip gcc-52b9468f1575b87e490cc3fdcff4c51f25fb49c1.tar.gz gcc-52b9468f1575b87e490cc3fdcff4c51f25fb49c1.tar.bz2 |
PR jit/63854: Fix leaks in toyvm.c
gcc/jit/ChangeLog:
PR jit/63854
* docs/examples/tut04-toyvm/toyvm.c
(toyvm_compiled_function): New typedef.
(toyvm_compiled_func) Rename to...
(toyvm_compiled_code) ...this.
(struct toyvm_compiled_function): New struct.
(toyvm_function_compile): Return a toyvm_compiled_function *
rather than a toyvm_compiled_func, so that the caller can fully
clean things up. Free "funcname".
(test_script): Update for change to toyvm_function_compile.
Clean up the toyvm_compiled_function.
(main): Likewise.
(docs/intro/tutorial04.rst): Update to reflect the above changes,
and to better spell out the lifetime of the compiled code.
From-SVN: r218234
Diffstat (limited to 'gcc/jit')
-rw-r--r-- | gcc/jit/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/jit/docs/examples/tut04-toyvm/toyvm.c | 54 | ||||
-rw-r--r-- | gcc/jit/docs/intro/tutorial04.rst | 11 |
3 files changed, 72 insertions, 10 deletions
diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog index c103eb2..210dcb0 100644 --- a/gcc/jit/ChangeLog +++ b/gcc/jit/ChangeLog @@ -1,6 +1,23 @@ 2014-12-01 David Malcolm <dmalcolm@redhat.com> PR jit/63854 + * docs/examples/tut04-toyvm/toyvm.c + (toyvm_compiled_function): New typedef. + (toyvm_compiled_func) Rename to... + (toyvm_compiled_code) ...this. + (struct toyvm_compiled_function): New struct. + (toyvm_function_compile): Return a toyvm_compiled_function * + rather than a toyvm_compiled_func, so that the caller can fully + clean things up. Free "funcname". + (test_script): Update for change to toyvm_function_compile. + Clean up the toyvm_compiled_function. + (main): Likewise. + (docs/intro/tutorial04.rst): Update to reflect the above changes, + and to better spell out the lifetime of the compiled code. + +2014-12-01 David Malcolm <dmalcolm@redhat.com> + + PR jit/63854 * jit-builtins.c (gcc::jit::recording::builtins_manager::make_fn_type): Call the context's new_function_type method, rather than directly creating diff --git a/gcc/jit/docs/examples/tut04-toyvm/toyvm.c b/gcc/jit/docs/examples/tut04-toyvm/toyvm.c index 666bf2e..07de507 100644 --- a/gcc/jit/docs/examples/tut04-toyvm/toyvm.c +++ b/gcc/jit/docs/examples/tut04-toyvm/toyvm.c @@ -33,9 +33,10 @@ typedef struct toyvm_op toyvm_op; typedef struct toyvm_function toyvm_function; typedef struct toyvm_frame toyvm_frame; typedef struct compilation_state compilation_state; +typedef struct toyvm_compiled_function toyvm_compiled_function; /* Functions are compiled to this function ptr type. */ -typedef int (*toyvm_compiled_func) (int); +typedef int (*toyvm_compiled_code) (int); enum opcode { /* Ops taking no operand. */ @@ -440,9 +441,17 @@ add_pop (compilation_state *state, gcc_jit_lvalue_as_rvalue (state->stack_depth)))); } +/* A struct to hold the compilation results. */ + +struct toyvm_compiled_function +{ + gcc_jit_result *cf_jit_result; + toyvm_compiled_code cf_code; +}; + /* The main compilation hook. */ -static toyvm_compiled_func +static toyvm_compiled_function * toyvm_function_compile (toyvm_function *fn) { compilation_state state; @@ -724,12 +733,26 @@ toyvm_function_compile (toyvm_function *fn) } /* end of loop on PC locations. */ /* We've now finished populating the context. Compile it. */ - gcc_jit_result *result = gcc_jit_context_compile (state.ctxt); + gcc_jit_result *jit_result = gcc_jit_context_compile (state.ctxt); gcc_jit_context_release (state.ctxt); - return (toyvm_compiled_func)gcc_jit_result_get_code (result, - funcname); - /* (this leaks "result" and "funcname") */ + toyvm_compiled_function *toyvm_result = + (toyvm_compiled_function *)calloc (1, sizeof (toyvm_compiled_function)); + if (!toyvm_result) + { + fprintf (stderr, "out of memory allocating toyvm_compiled_function\n"); + gcc_jit_result_release (jit_result); + return NULL; + } + + toyvm_result->cf_jit_result = jit_result; + toyvm_result->cf_code = + (toyvm_compiled_code)gcc_jit_result_get_code (jit_result, + funcname); + + free (funcname); + + return toyvm_result; } char test[1024]; @@ -768,7 +791,8 @@ test_script (const char *scripts_dir, const char *script_name, int input, char *script_path; toyvm_function *fn; int interpreted_result; - toyvm_compiled_func code; + toyvm_compiled_function *compiled_fn; + toyvm_compiled_code code; int compiled_result; snprintf (test, sizeof (test), "toyvm.c: %s", script_name); @@ -784,12 +808,18 @@ test_script (const char *scripts_dir, const char *script_name, int input, interpreted_result = toyvm_function_interpret (fn, input, NULL); CHECK_VALUE (interpreted_result, expected_result); - code = toyvm_function_compile (fn); + compiled_fn = toyvm_function_compile (fn); + CHECK_NON_NULL (compiled_fn); + + code = (toyvm_compiled_code)compiled_fn->cf_code; CHECK_NON_NULL (code); compiled_result = code (input); CHECK_VALUE (compiled_result, expected_result); + gcc_jit_result_release (compiled_fn->cf_jit_result); + free (compiled_fn); + free (fn); free (script_path); } @@ -853,9 +883,15 @@ main (int argc, char **argv) toyvm_function_interpret (fn, atoi (argv[2]), NULL)); /* JIT-compilation. */ - toyvm_compiled_func code = toyvm_function_compile (fn); + toyvm_compiled_function *compiled_fn + = toyvm_function_compile (fn); + + toyvm_compiled_code code = compiled_fn->cf_code; printf ("compiler result: %d\n", code (atoi (argv[2]))); + gcc_jit_result_release (compiled_fn->cf_jit_result); + free (compiled_fn); + return 0; } diff --git a/gcc/jit/docs/intro/tutorial04.rst b/gcc/jit/docs/intro/tutorial04.rst index cafdddb..3aac670 100644 --- a/gcc/jit/docs/intro/tutorial04.rst +++ b/gcc/jit/docs/intro/tutorial04.rst @@ -101,6 +101,15 @@ then directly executed in-process: :end-before: enum opcode :language: c +The lifetime of the code is tied to that of a :c:type:`gcc_jit_result *`. +We'll handle this by bundling them up in a structure, so that we can +clean them up together by calling :c:func:`gcc_jit_result_release`: + + .. literalinclude:: ../examples/tut04-toyvm/toyvm.c + :start-after: /* A struct to hold the compilation results. */ + :end-before: /* The main compilation hook. */ + :language: c + Our compiler isn't very sophisticated; it takes the implementation of each opcode above, and maps it directly to the operations supported by the libgccjit API. @@ -155,7 +164,7 @@ a block, implementing pushing and popping values: .. literalinclude:: ../examples/tut04-toyvm/toyvm.c :start-after: /* Stack manipulation. */ - :end-before: /* The main compilation hook. */ + :end-before: /* A struct to hold the compilation results. */ :language: c We will support single-stepping through the generated code in the |