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> 2013-02-11 Paulo Andrade <pcpa@gnu.org>
* include/lightning/jit_private.h, lib/jit_note.c, lib/lightning.c: * 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_print();
jit_disassemble(); jit_disassemble();
#endif #endif
jit_clear_state();
(*function)(); (*function)();
jit_destroy_state();
finish_jit(); finish_jit();
printf("ok\n"); printf("ok\n");

View file

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

View file

@ -615,10 +615,12 @@ int main(int argc, char *argv[])
jit_retr(JIT_R0); @rem{/* @t{ retr R0 } */} jit_retr(JIT_R0); @rem{/* @t{ retr R0 } */}
incr = jit_emit(); incr = jit_emit();
jit_clear_state();
@rem{/* call the generated code@comma{} passing 5 as an argument */} @rem{/* call the generated code@comma{} passing 5 as an argument */}
printf("%d + 1 = %d\n", 5, incr(5)); printf("%d + 1 = %d\n", 5, incr(5));
jit_destroy_state();
finish_jit(); finish_jit();
return 0; 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 code area out of the processor's instruction cache and return a
pointer to the start of the code. 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)); @item printf("%d + 1 = %d", 5, incr(5));
Calling our function is this simple---it is not distinguishable from Calling our function is this simple---it is not distinguishable from
a normal C function call, the only difference being that @code{incr} a normal C function call, the only difference being that @code{incr}
is a variable. 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(); @item finish_jit();
This call cleanups any global state hold by @lightning{}, and is This call cleanups any global state hold by @lightning{}, and is
advisable to call it once jit code will no longer be generated. 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 */} @rem{/* call the generated code@comma{} passing its size as argument */}
myFunction((char*)jit_address(end) - (char*)jit_address(start)); myFunction((char*)jit_address(end) - (char*)jit_address(start));
jit_clear_state();
jit_disassemble(); 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 will happen (if @lightning{} is built with assertions enable) or an
undefined value will be returned. 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(); @item jit_disassemble();
@code{disassemble} will dump the generated code to standard output, @code{disassemble} will dump the generated code to standard output,
unless @lightning{} was built with the disassembler disabled, in which unless @lightning{} was built with the disassembler disabled, in which
@ -948,6 +966,7 @@ int main(int argc, char *argv[])
(void)jit_emit(); (void)jit_emit();
c2f = (pifi)jit_address(nc); c2f = (pifi)jit_address(nc);
f2c = (pifi)jit_address(nf); f2c = (pifi)jit_address(nf);
jit_clear_state();
printf("\nC:"); printf("\nC:");
for (i = 0; i <= 100; i += 10) printf("%3d ", i); 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)); for (i = 32; i <= 212; i += 18) printf("%3d ", f2c(i));
printf("\n"); printf("\n");
jit_destroy_state();
finish_jit(); finish_jit();
return 0; return 0;
@} @}
@ -1049,7 +1069,9 @@ int main(int argc, char *argv[])
@rem{/* call the generated code@comma{} passing 32 as an argument */} @rem{/* call the generated code@comma{} passing 32 as an argument */}
fib = jit_emit(); fib = jit_emit();
jit_clear_state();
printf("fib(%d) = %d\n", 32, fib(32)); printf("fib(%d) = %d\n", 32, fib(32));
jit_destroy_state();
finish_jit(); finish_jit();
return 0; return 0;
@} @}
@ -1117,7 +1139,9 @@ int main(int argc, char *argv[])
@rem{/* call the generated code@comma{} passing 36 as an argument */} @rem{/* call the generated code@comma{} passing 36 as an argument */}
fib = jit_emit(); fib = jit_emit();
jit_clear_state();
printf("fib(%d) = %d\n", 36, fib(36)); printf("fib(%d) = %d\n", 36, fib(36));
jit_destroy_state();
finish_jit(); finish_jit();
return 0; return 0;
@} @}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -752,6 +752,10 @@ extern void init_jit(char*);
extern void finish_jit(void); extern void finish_jit(void);
extern jit_state_t *jit_new_state(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) #define jit_address(node) _jit_address(_jit, node)
extern jit_pointer_t _jit_address(jit_state_t*, jit_node_t*); 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 { else {
line = note->lines + index; line = note->lines + index;
index = offset_insert_index(line, offset); 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 */ /* common case if no code was generated for several source lines */
if (line->linenos[index] < lineno) if (line->linenos[index] < lineno)
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 */ /* common case of extending entry */
if (line->offsets[index] > offset) if (line->offsets[index] > offset)
line->offsets[index] = offset; line->offsets[index] = offset;

View file

@ -539,6 +539,70 @@ jit_new_state(void)
return (_jit); 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_node_t *
_jit_new_node(jit_state_t *_jit, jit_code_t code) _jit_new_node(jit_state_t *_jit, jit_code_t code)
{ {