mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-07 04:30:18 +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>
|
2013-01-24 Paulo Andrade <pcpa@gnu.org>
|
||||||
|
|
||||||
* check/Makefile.am: "make debug" target should pass only
|
* check/Makefile.am: "make debug" target should pass only
|
||||||
|
|
|
@ -19,12 +19,14 @@ AC_CONFIG_SRCDIR([Makefile.am])
|
||||||
AM_INIT_AUTOMAKE([dist-bzip2])
|
AM_INIT_AUTOMAKE([dist-bzip2])
|
||||||
AC_CONFIG_MACRO_DIR(m4)
|
AC_CONFIG_MACRO_DIR(m4)
|
||||||
|
|
||||||
AC_CONFIG_HEADER(config.h)
|
AC_CONFIG_HEADERS(config.h)
|
||||||
|
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
AC_PROG_INSTALL
|
AC_PROG_INSTALL
|
||||||
AC_PROG_LIBTOOL
|
AC_PROG_LIBTOOL
|
||||||
|
|
||||||
|
AC_CHECK_FUNCS(mremap,,)
|
||||||
|
|
||||||
AC_CHECK_LIB(gmp, __gmpz_init, ,
|
AC_CHECK_LIB(gmp, __gmpz_init, ,
|
||||||
[AC_MSG_ERROR([GNU MP not found, see http://gmplib.org/])])
|
[AC_MSG_ERROR([GNU MP not found, see http://gmplib.org/])])
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,10 @@
|
||||||
#ifndef _jit_private_h
|
#ifndef _jit_private_h
|
||||||
#define _jit_private_h
|
#define _jit_private_h
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -277,6 +281,7 @@ struct jit_state {
|
||||||
mpz_t blockmask; /* mask of visited basic blocks */
|
mpz_t blockmask; /* mask of visited basic blocks */
|
||||||
struct {
|
struct {
|
||||||
jit_uint8_t *ptr;
|
jit_uint8_t *ptr;
|
||||||
|
jit_uint8_t *end;
|
||||||
jit_word_t length;
|
jit_word_t length;
|
||||||
} code;
|
} code;
|
||||||
struct {
|
struct {
|
||||||
|
@ -408,6 +413,10 @@ _jit_classify(jit_state_t*, jit_code_t);
|
||||||
extern jit_bool_t
|
extern jit_bool_t
|
||||||
_jit_regarg_p(jit_state_t*, jit_node_t*, jit_int32_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)
|
#define emit_ldxi(r0, r1, i0) _emit_ldxi(_jit, r0, r1, i0)
|
||||||
extern void
|
extern void
|
||||||
_emit_ldxi(jit_state_t*, jit_int32_t, jit_int32_t, jit_word_t);
|
_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_pointer_t
|
||||||
_jit_emit(jit_state_t *_jit)
|
_emit_code(jit_state_t *_jit)
|
||||||
{
|
{
|
||||||
jit_node_t *node;
|
jit_node_t *node;
|
||||||
jit_node_t *temp;
|
jit_node_t *temp;
|
||||||
|
@ -801,23 +801,6 @@ _jit_emit(jit_state_t *_jit)
|
||||||
jit_int32_t patch_offset;
|
jit_int32_t patch_offset;
|
||||||
} undo;
|
} 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->function = NULL;
|
||||||
|
|
||||||
jit_reglive_setup();
|
jit_reglive_setup();
|
||||||
|
@ -1025,6 +1008,9 @@ _jit_emit(jit_state_t *_jit)
|
||||||
} \
|
} \
|
||||||
break
|
break
|
||||||
for (node = _jit->head; node; node = node->next) {
|
for (node = _jit->head; node; node = node->next) {
|
||||||
|
if (_jit->pc.uc >= _jit->code.end)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
value = jit_classify(node->code);
|
value = jit_classify(node->code);
|
||||||
jit_regarg_set(node, value);
|
jit_regarg_set(node, value);
|
||||||
switch (node->code) {
|
switch (node->code) {
|
||||||
|
@ -1542,8 +1528,6 @@ _jit_emit(jit_state_t *_jit)
|
||||||
}
|
}
|
||||||
|
|
||||||
__clear_cache(_jit->code.ptr, _jit->pc.uc);
|
__clear_cache(_jit->code.ptr, _jit->pc.uc);
|
||||||
_jit->done = 1;
|
|
||||||
jit_annotate();
|
|
||||||
|
|
||||||
return (_jit->code.ptr);
|
return (_jit->code.ptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -663,7 +663,7 @@ _jit_retval_d(jit_state_t *_jit, jit_int32_t r0)
|
||||||
}
|
}
|
||||||
|
|
||||||
jit_pointer_t
|
jit_pointer_t
|
||||||
_jit_emit(jit_state_t *_jit)
|
_emit_code(jit_state_t *_jit)
|
||||||
{
|
{
|
||||||
jit_node_t *node;
|
jit_node_t *node;
|
||||||
jit_node_t *temp;
|
jit_node_t *temp;
|
||||||
|
@ -676,23 +676,6 @@ _jit_emit(jit_state_t *_jit)
|
||||||
jit_int32_t patch_offset;
|
jit_int32_t patch_offset;
|
||||||
} undo;
|
} 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->function = NULL;
|
||||||
|
|
||||||
jit_reglive_setup();
|
jit_reglive_setup();
|
||||||
|
@ -774,6 +757,9 @@ _jit_emit(jit_state_t *_jit)
|
||||||
} \
|
} \
|
||||||
break
|
break
|
||||||
for (node = _jit->head; node; node = node->next) {
|
for (node = _jit->head; node; node = node->next) {
|
||||||
|
if (_jit->pc.uc >= _jit->code.end)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
value = jit_classify(node->code);
|
value = jit_classify(node->code);
|
||||||
jit_regarg_set(node, value);
|
jit_regarg_set(node, value);
|
||||||
switch (node->code) {
|
switch (node->code) {
|
||||||
|
@ -1249,8 +1235,6 @@ _jit_emit(jit_state_t *_jit)
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
_flush_cache((char *)_jit->code.ptr, _jit->pc.uc - _jit->code.ptr, ICACHE);
|
_flush_cache((char *)_jit->code.ptr, _jit->pc.uc - _jit->code.ptr, ICACHE);
|
||||||
#endif
|
#endif
|
||||||
_jit->done = 1;
|
|
||||||
jit_annotate();
|
|
||||||
|
|
||||||
return (_jit->code.ptr);
|
return (_jit->code.ptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -685,7 +685,7 @@ _jit_retval_d(jit_state_t *_jit, jit_int32_t r0)
|
||||||
}
|
}
|
||||||
|
|
||||||
jit_pointer_t
|
jit_pointer_t
|
||||||
_jit_emit(jit_state_t *_jit)
|
_emit_code(jit_state_t *_jit)
|
||||||
{
|
{
|
||||||
jit_node_t *node;
|
jit_node_t *node;
|
||||||
jit_node_t *temp;
|
jit_node_t *temp;
|
||||||
|
@ -698,23 +698,6 @@ _jit_emit(jit_state_t *_jit)
|
||||||
jit_int32_t patch_offset;
|
jit_int32_t patch_offset;
|
||||||
} undo;
|
} 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->function = NULL;
|
||||||
|
|
||||||
jit_reglive_setup();
|
jit_reglive_setup();
|
||||||
|
@ -797,6 +780,9 @@ _jit_emit(jit_state_t *_jit)
|
||||||
} \
|
} \
|
||||||
break
|
break
|
||||||
for (node = _jit->head; node; node = node->next) {
|
for (node = _jit->head; node; node = node->next) {
|
||||||
|
if (_jit->pc.uc >= _jit->code.end)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
value = jit_classify(node->code);
|
value = jit_classify(node->code);
|
||||||
jit_regarg_set(node, value);
|
jit_regarg_set(node, value);
|
||||||
switch (node->code) {
|
switch (node->code) {
|
||||||
|
@ -1212,8 +1198,6 @@ _jit_emit(jit_state_t *_jit)
|
||||||
}
|
}
|
||||||
|
|
||||||
__clear_cache(_jit->code.ptr, _jit->pc.uc);
|
__clear_cache(_jit->code.ptr, _jit->pc.uc);
|
||||||
_jit->done = 1;
|
|
||||||
jit_annotate();
|
|
||||||
|
|
||||||
return (_jit->code.ptr);
|
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
|
static void
|
||||||
_callr(jit_state_t *_jit, jit_int32_t r0)
|
_callr(jit_state_t *_jit, jit_int32_t r0)
|
||||||
{
|
{
|
||||||
rex(0, 1, _NOREG, _NOREG, r0);
|
rex(0, 0, _NOREG, _NOREG, r0);
|
||||||
ic(0xff);
|
ic(0xff);
|
||||||
mrm(0x03, 0x02, r7(r0));
|
mrm(0x03, 0x02, r7(r0));
|
||||||
}
|
}
|
||||||
|
|
|
@ -868,7 +868,7 @@ _jit_retval_d(jit_state_t *_jit, jit_int32_t r0)
|
||||||
}
|
}
|
||||||
|
|
||||||
jit_pointer_t
|
jit_pointer_t
|
||||||
_jit_emit(jit_state_t *_jit)
|
_emit_code(jit_state_t *_jit)
|
||||||
{
|
{
|
||||||
jit_node_t *node;
|
jit_node_t *node;
|
||||||
jit_node_t *temp;
|
jit_node_t *temp;
|
||||||
|
@ -881,23 +881,6 @@ _jit_emit(jit_state_t *_jit)
|
||||||
jit_int32_t patch_offset;
|
jit_int32_t patch_offset;
|
||||||
} undo;
|
} 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->function = NULL;
|
||||||
|
|
||||||
jit_reglive_setup();
|
jit_reglive_setup();
|
||||||
|
@ -1125,6 +1108,9 @@ _jit_emit(jit_state_t *_jit)
|
||||||
} \
|
} \
|
||||||
break
|
break
|
||||||
for (node = _jit->head; node; node = node->next) {
|
for (node = _jit->head; node; node = node->next) {
|
||||||
|
if (_jit->pc.uc >= _jit->code.end)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
value = jit_classify(node->code);
|
value = jit_classify(node->code);
|
||||||
jit_regarg_set(node, value);
|
jit_regarg_set(node, value);
|
||||||
switch (node->code) {
|
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;
|
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);
|
patch_at(node, _jit->patches.ptr[offset].inst, word);
|
||||||
}
|
}
|
||||||
_jit->done = 1;
|
|
||||||
jit_annotate();
|
|
||||||
|
|
||||||
return (_jit->code.ptr);
|
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_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.
|
/* Compute initial reglive and regmask set values of a basic block.
|
||||||
* reglive is the set of known live registers
|
* reglive is the set of known live registers
|
||||||
* regmask is the set of registers not referenced in the block
|
* regmask is the set of registers not referenced in the block
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue