1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-15 18:20:42 +02:00

Add code to release all memory used by the jit state.

* include/lightning.h, lib/lightning.c: Implement the new
	jit_clear_state and jit_destroy_state calls. jit_clear_state
	releases all memory not required during jit_execution; that
	is, leaves only the mmap'ed data and code buffers allocated.
	jit_destroy_state releases the mmap'ed buffers as well as
	the jit_state_t object itself, that holds pointers to the
	code and data buffers, as well as annotation pointers (for
	disassembly or backtrace) in the data buffer.

	* lib/jit_note.c: Correct invalid vector offset access.

	* check/ccall.c, check/lightning.c, doc/ifib.c, doc/incr.c,
	doc/printf.c, doc/rfib.c, doc/rpn.c: Use the new jit_clear_state
	and jit_destroy_state calls, to demonstrate the new code to
	release all jit memory.

	* doc/body.texi: Add basic documentation and usage description
	of jit_clear_state and jit_destroy_state.
This commit is contained in:
pcpa 2013-02-11 15:51:55 -02:00
parent 6039794ec3
commit 8f020fe044
12 changed files with 138 additions and 4 deletions

View file

@ -1,3 +1,24 @@
2013-02-11 Paulo Andrade <pcpa@gnu.org>
* include/lightning.h, lib/lightning.c: Implement the new
jit_clear_state and jit_destroy_state calls. jit_clear_state
releases all memory not required during jit_execution; that
is, leaves only the mmap'ed data and code buffers allocated.
jit_destroy_state releases the mmap'ed buffers as well as
the jit_state_t object itself, that holds pointers to the
code and data buffers, as well as annotation pointers (for
disassembly or backtrace) in the data buffer.
* lib/jit_note.c: Correct invalid vector offset access.
* check/ccall.c, check/lightning.c, doc/ifib.c, doc/incr.c,
doc/printf.c, doc/rfib.c, doc/rpn.c: Use the new jit_clear_state
and jit_destroy_state calls, to demonstrate the new code to
release all jit memory.
* doc/body.texi: Add basic documentation and usage description
of jit_clear_state and jit_destroy_state.
2013-02-11 Paulo Andrade <pcpa@gnu.org>
* include/lightning/jit_private.h, lib/jit_note.c, lib/lightning.c:

View file

@ -890,7 +890,11 @@ main(int argc, char *argv[])
jit_print();
jit_disassemble();
#endif
jit_clear_state();
(*function)();
jit_destroy_state();
finish_jit();
printf("ok\n");

View file

@ -3542,6 +3542,7 @@ parse(void)
static int
execute(int argc, char *argv[])
{
int result;
label_t *label;
function_t function;
patch_t *patch, *next;
@ -3573,9 +3574,15 @@ execute(int argc, char *argv[])
jit_disassemble();
fprintf(stdout, " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
}
jit_clear_state();
if (flag_disasm)
return (0);
return ((*function)(argc, argv));
result = 0;
else
result = (*function)(argc, argv);
jit_destroy_state();
return (result);
}
static void *

View file

@ -615,10 +615,12 @@ int main(int argc, char *argv[])
jit_retr(JIT_R0); @rem{/* @t{ retr R0 } */}
incr = jit_emit();
jit_clear_state();
@rem{/* call the generated code@comma{} passing 5 as an argument */}
printf("%d + 1 = %d\n", 5, incr(5));
jit_destroy_state();
finish_jit();
return 0;
@}
@ -682,11 +684,21 @@ This instruction is very important. It actually translates the
code area out of the processor's instruction cache and return a
pointer to the start of the code.
@item jit_clear_state();
This call cleanups any data not required for jit execution. Note
that it must be called after any call to @code{jit_print} or
@code{jit_address}, as this call destroy the @lightning{}
intermediate representation.
@item printf("%d + 1 = %d", 5, incr(5));
Calling our function is this simple---it is not distinguishable from
a normal C function call, the only difference being that @code{incr}
is a variable.
@item jit_destroy_state();
Releases all memory associated with the jit context. It should be
called after known the jit will no longer be called.
@item finish_jit();
This call cleanups any global state hold by @lightning{}, and is
advisable to call it once jit code will no longer be generated.
@ -765,6 +777,7 @@ int main(int argc, char *argv[])
@rem{/* call the generated code@comma{} passing its size as argument */}
myFunction((char*)jit_address(end) - (char*)jit_address(start));
jit_clear_state();
jit_disassemble();
@ -822,6 +835,11 @@ call must be done after the @code{emit} call or either a fatal error
will happen (if @lightning{} is built with assertions enable) or an
undefined value will be returned.
@item jit_clear_state();
Note that @code{jit_clear_state} was called after executing jit in
this example. It was done because it must be called after any call
to @code{jit_address} or @code{jit_print}.
@item jit_disassemble();
@code{disassemble} will dump the generated code to standard output,
unless @lightning{} was built with the disassembler disabled, in which
@ -948,6 +966,7 @@ int main(int argc, char *argv[])
(void)jit_emit();
c2f = (pifi)jit_address(nc);
f2c = (pifi)jit_address(nf);
jit_clear_state();
printf("\nC:");
for (i = 0; i <= 100; i += 10) printf("%3d ", i);
@ -961,6 +980,7 @@ int main(int argc, char *argv[])
for (i = 32; i <= 212; i += 18) printf("%3d ", f2c(i));
printf("\n");
jit_destroy_state();
finish_jit();
return 0;
@}
@ -1049,7 +1069,9 @@ int main(int argc, char *argv[])
@rem{/* call the generated code@comma{} passing 32 as an argument */}
fib = jit_emit();
jit_clear_state();
printf("fib(%d) = %d\n", 32, fib(32));
jit_destroy_state();
finish_jit();
return 0;
@}
@ -1117,7 +1139,9 @@ int main(int argc, char *argv[])
@rem{/* call the generated code@comma{} passing 36 as an argument */}
fib = jit_emit();
jit_clear_state();
printf("fib(%d) = %d\n", 36, fib(36));
jit_destroy_state();
finish_jit();
return 0;
@}

View file

@ -38,7 +38,9 @@ int main(int argc, char *argv[])
/* call the generated code, passing 36 as an argument */
fib = jit_emit();
jit_clear_state();
printf("fib(%d) = %d\n", 36, fib(36));
jit_destroy_state();
finish_jit();
return 0;
}

View file

@ -20,10 +20,12 @@ int main(int argc, char *argv[])
jit_retr(JIT_R0); /* @t{ retr R0 } */
incr = jit_emit();
jit_clear_state();
/* call the generated code\, passing 5 as an argument */
printf("%d + 1 = %d\n", 5, incr(5));
jit_destroy_state();
finish_jit();
return 0;
}

View file

@ -30,9 +30,11 @@ int main(int argc, char *argv[])
/* call the generated code, passing its size as argument */
myFunction((char*)jit_address(end) - (char*)jit_address(start));
jit_clear_state();
jit_disassemble();
jit_destroy_state();
finish_jit();
return 0;
}

View file

@ -43,7 +43,9 @@ int main(int argc, char *argv[])
/* call the generated code, passing 32 as an argument */
fib = jit_emit();
jit_clear_state();
printf("fib(%d) = %d\n", 32, fib(32));
jit_destroy_state();
finish_jit();
return 0;
}

View file

@ -76,6 +76,7 @@ int main(int argc, char *argv[])
(void)jit_emit();
c2f = (pifi)jit_address(nc);
f2c = (pifi)jit_address(nf);
jit_clear_state();
printf("\nC:");
for (i = 0; i <= 100; i += 10) printf("%3d ", i);
@ -89,6 +90,7 @@ int main(int argc, char *argv[])
for (i = 32; i <= 212; i += 18) printf("%3d ", f2c(i));
printf("\n");
jit_destroy_state();
finish_jit();
return 0;
}

View file

@ -752,6 +752,10 @@ extern void init_jit(char*);
extern void finish_jit(void);
extern jit_state_t *jit_new_state(void);
#define jit_clear_state() _jit_clear_state(_jit)
extern void _jit_clear_state(jit_state_t*);
#define jit_destroy_state() _jit_destroy_state(_jit)
extern void _jit_destroy_state(jit_state_t*);
#define jit_address(node) _jit_address(_jit, node)
extern jit_pointer_t _jit_address(jit_state_t*, jit_node_t*);

View file

@ -177,12 +177,12 @@ _jit_set_note(jit_state_t *_jit, jit_note_t *note,
else {
line = note->lines + index;
index = offset_insert_index(line, offset);
if (line->offsets[index] == offset) {
if (index < line->length && line->offsets[index] == offset) {
/* common case if no code was generated for several source lines */
if (line->linenos[index] < lineno)
line->linenos[index] = lineno;
}
else if (line->linenos[index] == lineno) {
else if (index < line->length && line->linenos[index] == lineno) {
/* common case of extending entry */
if (line->offsets[index] > offset)
line->offsets[index] = offset;

View file

@ -539,6 +539,70 @@ jit_new_state(void)
return (_jit);
}
void
_jit_clear_state(jit_state_t *_jit)
{
jit_word_t offset;
jit_function_t *function;
/* release memory not required at jit execution time and set
* pointers to NULL to explicitly know they are released */
_jit->head = _jit->tail = NULL;
mpz_clear(_jit->blockmask);
free(_jit->data.table);
_jit->data.table = NULL;
_jit->data.size = _jit->data.count = 0;
free(_jit->spill);
_jit->spill = NULL;
free(_jit->gen);
_jit->gen = NULL;
free(_jit->values);
_jit->values = NULL;
free(_jit->blocks.ptr);
_jit->blocks.ptr = NULL;
free(_jit->patches.ptr);
_jit->patches.ptr = NULL;
_jit->patches.offset = _jit->patches.length = 0;
for (offset = 0; offset < _jit->functions.offset; offset++) {
function = _jit->functions.ptr + offset;
free(function->regoff);
function->regoff = NULL;
}
free(_jit->functions.ptr);
_jit->functions.offset = _jit->functions.length = 0;
_jit->function = NULL;
for (offset = 0; offset < _jit->pool.length; offset++)
free(_jit->pool.ptr[offset]);
free(_jit->pool.ptr);
_jit->pool.ptr = NULL;
_jit->pool.offset = _jit->pool.length = 0;
_jit->list = NULL;
_jit->note.head = _jit->note.tail =
_jit->note.name = _jit->note.note = NULL;
_jit->note.base = NULL;
#if __arm__ && DISASSEMBLER
free(_jit->data_info.ptr);
_jit->data_info.ptr = NULL;
#endif
}
void
_jit_destroy_state(jit_state_t *_jit)
{
munmap(_jit->code.ptr, _jit->code.length);
munmap(_jit->data.ptr, _jit->data.length);
free(_jit);
}
jit_node_t *
_jit_new_node(jit_state_t *_jit, jit_code_t code)
{