1
Fork 0
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:
pcpa 2013-01-29 16:37:43 -02:00
parent 16d18f11d3
commit 44d4fa5444
9 changed files with 111 additions and 82 deletions

View file

@ -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

View file

@ -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/])])

View file

@ -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);

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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));
}

View file

@ -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);
}

View file

@ -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