diff --git a/ChangeLog b/ChangeLog index 1322aacf7..2a4170ba2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2013-01-29 Paulo Andrade + + * 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 * check/Makefile.am: "make debug" target should pass only diff --git a/configure.ac b/configure.ac index 83a7805dd..9e9f939a4 100644 --- a/configure.ac +++ b/configure.ac @@ -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/])]) diff --git a/include/lightning/jit_private.h b/include/lightning/jit_private.h index c32f0b48a..b0be3d90c 100644 --- a/include/lightning/jit_private.h +++ b/include/lightning/jit_private.h @@ -18,6 +18,10 @@ #ifndef _jit_private_h #define _jit_private_h +#if HAVE_CONFIG_H +# include "config.h" +#endif + #include #include #include @@ -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); diff --git a/lib/jit_arm.c b/lib/jit_arm.c index db4d514b0..95cbfac30 100644 --- a/lib/jit_arm.c +++ b/lib/jit_arm.c @@ -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); } diff --git a/lib/jit_mips.c b/lib/jit_mips.c index f5cbdf53d..57be725e8 100644 --- a/lib/jit_mips.c +++ b/lib/jit_mips.c @@ -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); } diff --git a/lib/jit_ppc.c b/lib/jit_ppc.c index 443fcac02..aaa2035a1 100644 --- a/lib/jit_ppc.c +++ b/lib/jit_ppc.c @@ -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); } diff --git a/lib/jit_x86-cpu.c b/lib/jit_x86-cpu.c index 197f7800a..997855dde 100644 --- a/lib/jit_x86-cpu.c +++ b/lib/jit_x86-cpu.c @@ -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)); } diff --git a/lib/jit_x86.c b/lib/jit_x86.c index 3d9f0487f..4ff1dabbb 100644 --- a/lib/jit_x86.c +++ b/lib/jit_x86.c @@ -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); } diff --git a/lib/lightning.c b/lib/lightning.c index 9b20a1e44..e9de59d0a 100644 --- a/lib/lightning.c +++ b/lib/lightning.c @@ -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