Commit 52b9468f by David Malcolm Committed by David Malcolm

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
parent 33b625ed
2014-12-01 David Malcolm <dmalcolm@redhat.com> 2014-12-01 David Malcolm <dmalcolm@redhat.com>
PR jit/63854 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 * jit-builtins.c
(gcc::jit::recording::builtins_manager::make_fn_type): Call the (gcc::jit::recording::builtins_manager::make_fn_type): Call the
context's new_function_type method, rather than directly creating context's new_function_type method, rather than directly creating
......
...@@ -33,9 +33,10 @@ typedef struct toyvm_op toyvm_op; ...@@ -33,9 +33,10 @@ typedef struct toyvm_op toyvm_op;
typedef struct toyvm_function toyvm_function; typedef struct toyvm_function toyvm_function;
typedef struct toyvm_frame toyvm_frame; typedef struct toyvm_frame toyvm_frame;
typedef struct compilation_state compilation_state; typedef struct compilation_state compilation_state;
typedef struct toyvm_compiled_function toyvm_compiled_function;
/* Functions are compiled to this function ptr type. */ /* Functions are compiled to this function ptr type. */
typedef int (*toyvm_compiled_func) (int); typedef int (*toyvm_compiled_code) (int);
enum opcode { enum opcode {
/* Ops taking no operand. */ /* Ops taking no operand. */
...@@ -440,9 +441,17 @@ add_pop (compilation_state *state, ...@@ -440,9 +441,17 @@ add_pop (compilation_state *state,
gcc_jit_lvalue_as_rvalue (state->stack_depth)))); 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. */ /* The main compilation hook. */
static toyvm_compiled_func static toyvm_compiled_function *
toyvm_function_compile (toyvm_function *fn) toyvm_function_compile (toyvm_function *fn)
{ {
compilation_state state; compilation_state state;
...@@ -724,12 +733,26 @@ toyvm_function_compile (toyvm_function *fn) ...@@ -724,12 +733,26 @@ toyvm_function_compile (toyvm_function *fn)
} /* end of loop on PC locations. */ } /* end of loop on PC locations. */
/* We've now finished populating the context. Compile it. */ /* 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); gcc_jit_context_release (state.ctxt);
return (toyvm_compiled_func)gcc_jit_result_get_code (result, toyvm_compiled_function *toyvm_result =
funcname); (toyvm_compiled_function *)calloc (1, sizeof (toyvm_compiled_function));
/* (this leaks "result" and "funcname") */ 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]; char test[1024];
...@@ -768,7 +791,8 @@ test_script (const char *scripts_dir, const char *script_name, int input, ...@@ -768,7 +791,8 @@ test_script (const char *scripts_dir, const char *script_name, int input,
char *script_path; char *script_path;
toyvm_function *fn; toyvm_function *fn;
int interpreted_result; int interpreted_result;
toyvm_compiled_func code; toyvm_compiled_function *compiled_fn;
toyvm_compiled_code code;
int compiled_result; int compiled_result;
snprintf (test, sizeof (test), "toyvm.c: %s", script_name); 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, ...@@ -784,12 +808,18 @@ test_script (const char *scripts_dir, const char *script_name, int input,
interpreted_result = toyvm_function_interpret (fn, input, NULL); interpreted_result = toyvm_function_interpret (fn, input, NULL);
CHECK_VALUE (interpreted_result, expected_result); 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); CHECK_NON_NULL (code);
compiled_result = code (input); compiled_result = code (input);
CHECK_VALUE (compiled_result, expected_result); CHECK_VALUE (compiled_result, expected_result);
gcc_jit_result_release (compiled_fn->cf_jit_result);
free (compiled_fn);
free (fn);
free (script_path); free (script_path);
} }
...@@ -853,9 +883,15 @@ main (int argc, char **argv) ...@@ -853,9 +883,15 @@ main (int argc, char **argv)
toyvm_function_interpret (fn, atoi (argv[2]), NULL)); toyvm_function_interpret (fn, atoi (argv[2]), NULL));
/* JIT-compilation. */ /* 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", printf ("compiler result: %d\n",
code (atoi (argv[2]))); code (atoi (argv[2])));
gcc_jit_result_release (compiled_fn->cf_jit_result);
free (compiled_fn);
return 0; return 0;
} }
...@@ -101,6 +101,15 @@ then directly executed in-process: ...@@ -101,6 +101,15 @@ then directly executed in-process:
:end-before: enum opcode :end-before: enum opcode
:language: c :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 Our compiler isn't very sophisticated; it takes the implementation of
each opcode above, and maps it directly to the operations supported by each opcode above, and maps it directly to the operations supported by
the libgccjit API. the libgccjit API.
...@@ -155,7 +164,7 @@ a block, implementing pushing and popping values: ...@@ -155,7 +164,7 @@ a block, implementing pushing and popping values:
.. literalinclude:: ../examples/tut04-toyvm/toyvm.c .. literalinclude:: ../examples/tut04-toyvm/toyvm.c
:start-after: /* Stack manipulation. */ :start-after: /* Stack manipulation. */
:end-before: /* The main compilation hook. */ :end-before: /* A struct to hold the compilation results. */
:language: c :language: c
We will support single-stepping through the generated code in the We will support single-stepping through the generated code in the
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment