mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-06 12:10:28 +02:00
Add heuristic code to estimate space and resize if required jit buffer.
This commit is contained in:
parent
16d18f11d3
commit
44d4fa5444
9 changed files with 111 additions and 82 deletions
18
ChangeLog
18
ChangeLog
|
@ -1,3 +1,21 @@
|
|||
2013-01-29 Paulo Andrade <pcpa@gnu.org>
|
||||
|
||||
* configure.ac: Use AC_CONFIG_HEADERS instead of AC_CONFIG_HEADER
|
||||
to have HAVE_CONFIG_H defined with latest aclocal.
|
||||
|
||||
* include/lightning/jit_private.h, lib/lightning.c: Add new
|
||||
abstraction to use an heuristic to calculate amount of space
|
||||
required for jit generation, and code to reallocate buffer if
|
||||
did miscalculate it.
|
||||
|
||||
* lib/jit_arm.c, lib/jit_mips.c, lib/jit_ppc.c, lib/jit_x86.c:
|
||||
Update to use new code to estimate and resize of required buffer
|
||||
for jit code.
|
||||
|
||||
* lib/jit_x86-cpu.c: Minor cosmetic change to avoid adding a
|
||||
non required rex prefix when calling a function pointer stored
|
||||
in a register.
|
||||
|
||||
2013-01-24 Paulo Andrade <pcpa@gnu.org>
|
||||
|
||||
* check/Makefile.am: "make debug" target should pass only
|
||||
|
|
|
@ -19,12 +19,14 @@ AC_CONFIG_SRCDIR([Makefile.am])
|
|||
AM_INIT_AUTOMAKE([dist-bzip2])
|
||||
AC_CONFIG_MACRO_DIR(m4)
|
||||
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
AC_CHECK_FUNCS(mremap,,)
|
||||
|
||||
AC_CHECK_LIB(gmp, __gmpz_init, ,
|
||||
[AC_MSG_ERROR([GNU MP not found, see http://gmplib.org/])])
|
||||
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
#ifndef _jit_private_h
|
||||
#define _jit_private_h
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
@ -277,6 +281,7 @@ struct jit_state {
|
|||
mpz_t blockmask; /* mask of visited basic blocks */
|
||||
struct {
|
||||
jit_uint8_t *ptr;
|
||||
jit_uint8_t *end;
|
||||
jit_word_t length;
|
||||
} code;
|
||||
struct {
|
||||
|
@ -408,6 +413,10 @@ _jit_classify(jit_state_t*, jit_code_t);
|
|||
extern jit_bool_t
|
||||
_jit_regarg_p(jit_state_t*, jit_node_t*, jit_int32_t);
|
||||
|
||||
#define emit_code() _emit_code(_jit)
|
||||
extern jit_pointer_t
|
||||
_emit_code(jit_state_t*);
|
||||
|
||||
#define emit_ldxi(r0, r1, i0) _emit_ldxi(_jit, r0, r1, i0)
|
||||
extern void
|
||||
_emit_ldxi(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
|
||||
|
|
|
@ -784,7 +784,7 @@ _jit_retval_d(jit_state_t *_jit, jit_int32_t r0)
|
|||
}
|
||||
|
||||
jit_pointer_t
|
||||
_jit_emit(jit_state_t *_jit)
|
||||
_emit_code(jit_state_t *_jit)
|
||||
{
|
||||
jit_node_t *node;
|
||||
jit_node_t *temp;
|
||||
|
@ -801,23 +801,6 @@ _jit_emit(jit_state_t *_jit)
|
|||
jit_int32_t patch_offset;
|
||||
} undo;
|
||||
|
||||
if (_jit->function)
|
||||
jit_epilog();
|
||||
jit_optimize();
|
||||
|
||||
_jit->emit = 1;
|
||||
|
||||
_jit->code.length = 16 * 1024 * 1024;
|
||||
_jit->code.ptr = mmap(NULL, _jit->code.length,
|
||||
PROT_EXEC | PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
assert(_jit->code.ptr != MAP_FAILED);
|
||||
_jit->pc.uc = _jit->code.ptr;
|
||||
|
||||
/* clear jit_flag_patch from label nodes if reallocating buffer
|
||||
* and starting over
|
||||
*/
|
||||
|
||||
_jit->function = NULL;
|
||||
|
||||
jit_reglive_setup();
|
||||
|
@ -1025,6 +1008,9 @@ _jit_emit(jit_state_t *_jit)
|
|||
} \
|
||||
break
|
||||
for (node = _jit->head; node; node = node->next) {
|
||||
if (_jit->pc.uc >= _jit->code.end)
|
||||
return (NULL);
|
||||
|
||||
value = jit_classify(node->code);
|
||||
jit_regarg_set(node, value);
|
||||
switch (node->code) {
|
||||
|
@ -1542,8 +1528,6 @@ _jit_emit(jit_state_t *_jit)
|
|||
}
|
||||
|
||||
__clear_cache(_jit->code.ptr, _jit->pc.uc);
|
||||
_jit->done = 1;
|
||||
jit_annotate();
|
||||
|
||||
return (_jit->code.ptr);
|
||||
}
|
||||
|
|
|
@ -663,7 +663,7 @@ _jit_retval_d(jit_state_t *_jit, jit_int32_t r0)
|
|||
}
|
||||
|
||||
jit_pointer_t
|
||||
_jit_emit(jit_state_t *_jit)
|
||||
_emit_code(jit_state_t *_jit)
|
||||
{
|
||||
jit_node_t *node;
|
||||
jit_node_t *temp;
|
||||
|
@ -676,23 +676,6 @@ _jit_emit(jit_state_t *_jit)
|
|||
jit_int32_t patch_offset;
|
||||
} undo;
|
||||
|
||||
if (_jit->function)
|
||||
jit_epilog();
|
||||
jit_optimize();
|
||||
|
||||
_jit->emit = 1;
|
||||
|
||||
_jit->code.length = 16 * 1024 * 1024;
|
||||
_jit->code.ptr = mmap(NULL, _jit->code.length,
|
||||
PROT_EXEC | PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
assert(_jit->code.ptr != MAP_FAILED);
|
||||
_jit->pc.uc = _jit->code.ptr;
|
||||
|
||||
/* clear jit_flag_patch from label nodes if reallocating buffer
|
||||
* and starting over
|
||||
*/
|
||||
|
||||
_jit->function = NULL;
|
||||
|
||||
jit_reglive_setup();
|
||||
|
@ -774,6 +757,9 @@ _jit_emit(jit_state_t *_jit)
|
|||
} \
|
||||
break
|
||||
for (node = _jit->head; node; node = node->next) {
|
||||
if (_jit->pc.uc >= _jit->code.end)
|
||||
return (NULL);
|
||||
|
||||
value = jit_classify(node->code);
|
||||
jit_regarg_set(node, value);
|
||||
switch (node->code) {
|
||||
|
@ -1249,8 +1235,6 @@ _jit_emit(jit_state_t *_jit)
|
|||
#if defined(__linux__)
|
||||
_flush_cache((char *)_jit->code.ptr, _jit->pc.uc - _jit->code.ptr, ICACHE);
|
||||
#endif
|
||||
_jit->done = 1;
|
||||
jit_annotate();
|
||||
|
||||
return (_jit->code.ptr);
|
||||
}
|
||||
|
|
|
@ -685,7 +685,7 @@ _jit_retval_d(jit_state_t *_jit, jit_int32_t r0)
|
|||
}
|
||||
|
||||
jit_pointer_t
|
||||
_jit_emit(jit_state_t *_jit)
|
||||
_emit_code(jit_state_t *_jit)
|
||||
{
|
||||
jit_node_t *node;
|
||||
jit_node_t *temp;
|
||||
|
@ -698,23 +698,6 @@ _jit_emit(jit_state_t *_jit)
|
|||
jit_int32_t patch_offset;
|
||||
} undo;
|
||||
|
||||
if (_jit->function)
|
||||
jit_epilog();
|
||||
jit_optimize();
|
||||
|
||||
_jit->emit = 1;
|
||||
|
||||
_jit->code.length = 16 * 1024 * 1024;
|
||||
_jit->code.ptr = mmap(NULL, _jit->code.length,
|
||||
PROT_EXEC | PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
assert(_jit->code.ptr != MAP_FAILED);
|
||||
_jit->pc.uc = _jit->code.ptr;
|
||||
|
||||
/* clear jit_flag_patch from label nodes if reallocating buffer
|
||||
* and starting over
|
||||
*/
|
||||
|
||||
_jit->function = NULL;
|
||||
|
||||
jit_reglive_setup();
|
||||
|
@ -797,6 +780,9 @@ _jit_emit(jit_state_t *_jit)
|
|||
} \
|
||||
break
|
||||
for (node = _jit->head; node; node = node->next) {
|
||||
if (_jit->pc.uc >= _jit->code.end)
|
||||
return (NULL);
|
||||
|
||||
value = jit_classify(node->code);
|
||||
jit_regarg_set(node, value);
|
||||
switch (node->code) {
|
||||
|
@ -1212,8 +1198,6 @@ _jit_emit(jit_state_t *_jit)
|
|||
}
|
||||
|
||||
__clear_cache(_jit->code.ptr, _jit->pc.uc);
|
||||
_jit->done = 1;
|
||||
jit_annotate();
|
||||
|
||||
return (_jit->code.ptr);
|
||||
}
|
||||
|
|
|
@ -3023,7 +3023,7 @@ _bxsubi_u(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_word_t i1)
|
|||
static void
|
||||
_callr(jit_state_t *_jit, jit_int32_t r0)
|
||||
{
|
||||
rex(0, 1, _NOREG, _NOREG, r0);
|
||||
rex(0, 0, _NOREG, _NOREG, r0);
|
||||
ic(0xff);
|
||||
mrm(0x03, 0x02, r7(r0));
|
||||
}
|
||||
|
|
|
@ -868,7 +868,7 @@ _jit_retval_d(jit_state_t *_jit, jit_int32_t r0)
|
|||
}
|
||||
|
||||
jit_pointer_t
|
||||
_jit_emit(jit_state_t *_jit)
|
||||
_emit_code(jit_state_t *_jit)
|
||||
{
|
||||
jit_node_t *node;
|
||||
jit_node_t *temp;
|
||||
|
@ -881,23 +881,6 @@ _jit_emit(jit_state_t *_jit)
|
|||
jit_int32_t patch_offset;
|
||||
} undo;
|
||||
|
||||
if (_jit->function)
|
||||
jit_epilog();
|
||||
jit_optimize();
|
||||
|
||||
_jit->emit = 1;
|
||||
|
||||
_jit->code.length = 16 * 1024 * 1024;
|
||||
_jit->code.ptr = mmap(NULL, _jit->code.length,
|
||||
PROT_EXEC | PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
assert(_jit->code.ptr != MAP_FAILED);
|
||||
_jit->pc.uc = _jit->code.ptr;
|
||||
|
||||
/* clear jit_flag_patch from label nodes if reallocating buffer
|
||||
* and starting over
|
||||
*/
|
||||
|
||||
_jit->function = NULL;
|
||||
|
||||
jit_reglive_setup();
|
||||
|
@ -1125,6 +1108,9 @@ _jit_emit(jit_state_t *_jit)
|
|||
} \
|
||||
break
|
||||
for (node = _jit->head; node; node = node->next) {
|
||||
if (_jit->pc.uc >= _jit->code.end)
|
||||
return (NULL);
|
||||
|
||||
value = jit_classify(node->code);
|
||||
jit_regarg_set(node, value);
|
||||
switch (node->code) {
|
||||
|
@ -1629,8 +1615,6 @@ _jit_emit(jit_state_t *_jit)
|
|||
word = node->code == jit_code_movi ? node->v.n->u.w : node->u.n->u.w;
|
||||
patch_at(node, _jit->patches.ptr[offset].inst, word);
|
||||
}
|
||||
_jit->done = 1;
|
||||
jit_annotate();
|
||||
|
||||
return (_jit->code.ptr);
|
||||
}
|
||||
|
|
|
@ -1238,6 +1238,70 @@ _jit_regarg_clr(jit_state_t *_jit, jit_node_t *node, jit_int32_t value)
|
|||
jit_regset_clrbit(_jit->regarg, jit_regno(node->w.w));
|
||||
}
|
||||
|
||||
jit_pointer_t
|
||||
_jit_emit(jit_state_t *_jit)
|
||||
{
|
||||
jit_pointer_t code;
|
||||
jit_node_t *node;
|
||||
jit_int32_t mult;
|
||||
size_t length;
|
||||
|
||||
if (_jit->function)
|
||||
jit_epilog();
|
||||
jit_optimize();
|
||||
|
||||
/* Heuristic to guess code buffer size */
|
||||
mult = 4;
|
||||
|
||||
_jit->emit = 1;
|
||||
|
||||
_jit->code.length = _jit->pool.length * 1024 * mult;
|
||||
|
||||
_jit->code.ptr = mmap(NULL, _jit->code.length,
|
||||
PROT_EXEC | PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
assert(_jit->code.ptr != MAP_FAILED);
|
||||
_jit->code.end = _jit->code.ptr + _jit->code.length - 64;
|
||||
_jit->pc.uc = _jit->code.ptr;
|
||||
|
||||
for (;;) {
|
||||
if ((code = emit_code()) == NULL) {
|
||||
for (node = _jit->head; node; node = node->next) {
|
||||
if (node->code == jit_code_label && node->link)
|
||||
node->flag &= ~jit_flag_patch;
|
||||
}
|
||||
++mult;
|
||||
length = _jit->pool.length * 1024 * mult;
|
||||
|
||||
#if !HAVE_MREMAP
|
||||
munmap(_jit->code.ptr, _jit->code.length);
|
||||
#endif
|
||||
|
||||
#if HAVE_MREMAP
|
||||
_jit->code.ptr = mremap(_jit->code.ptr, _jit->code.length,
|
||||
length, MREMAP_MAYMOVE, NULL);
|
||||
#else
|
||||
_jit->code.ptr = mmap(NULL, length,
|
||||
PROT_EXEC | PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
#endif
|
||||
|
||||
assert(_jit->code.ptr != MAP_FAILED);
|
||||
_jit->code.length = length;
|
||||
_jit->code.end = _jit->code.ptr + _jit->code.length - 64;
|
||||
_jit->pc.uc = _jit->code.ptr;
|
||||
_jit->patches.offset = 0;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
_jit->done = 1;
|
||||
jit_annotate();
|
||||
|
||||
return (code);
|
||||
}
|
||||
|
||||
/* Compute initial reglive and regmask set values of a basic block.
|
||||
* reglive is the set of known live registers
|
||||
* regmask is the set of registers not referenced in the block
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue