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:
parent
6039794ec3
commit
8f020fe044
12 changed files with 138 additions and 4 deletions
21
ChangeLog
21
ChangeLog
|
@ -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:
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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;
|
||||
@}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue