[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Guile-commits] 280/437: Implement the new jit_set_code interface.
From: |
Andy Wingo |
Subject: |
[Guile-commits] 280/437: Implement the new jit_set_code interface. |
Date: |
Mon, 2 Jul 2018 05:14:36 -0400 (EDT) |
wingo pushed a commit to branch lightning
in repository guile.
commit 79bc3d03dd1c76d8a37ed3c12becbd9b71c142be
Author: pcpa <address@hidden>
Date: Tue Mar 11 11:40:42 2014 -0300
Implement the new jit_set_code interface.
* include/lightning.h, include/lightning/jit_private.h,
lib/lightning.c: Implement the new jit_set_code() interface,
that allows instructing lightning to use an alternate code
buffer. The new jit_realize() function should be called
before jit_set_code(), and usually call jit_get_code()
to query the amount of bytes expected to be required for
the code.
* lib/jit_size.c: Minor update to have less chances of
miscalculating the code buffer by starting the counter
with the size of the longest instruction instead of zero,
as code emit fails if at any moment less than the longest
instruction bytes are available.
* check/setcode.c: New file implementing some basic tests
of the new jit_set_code() interface.
* check/Makefile.am: Update for newer test case.
---
ChangeLog | 21 +++++++
check/Makefile.am | 8 ++-
check/ccall.ok | 1 -
check/self.ok | 1 -
check/setcode.c | 89 +++++++++++++++++++++++++++++
include/lightning.h | 6 ++
include/lightning/jit_private.h | 3 +
lib/jit_size.c | 2 +-
lib/lightning.c | 123 +++++++++++++++++++++++++++-------------
9 files changed, 209 insertions(+), 45 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 1acc32f..1477289 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2014-11-03 Paulo Andrade <address@hidden>
+
+ * include/lightning.h, include/lightning/jit_private.h,
+ lib/lightning.c: Implement the new jit_set_code() interface,
+ that allows instructing lightning to use an alternate code
+ buffer. The new jit_realize() function should be called
+ before jit_set_code(), and usually call jit_get_code()
+ to query the amount of bytes expected to be required for
+ the code.
+
+ * lib/jit_size.c: Minor update to have less chances of
+ miscalculating the code buffer by starting the counter
+ with the size of the longest instruction instead of zero,
+ as code emit fails if at any moment less than the longest
+ instruction bytes are available.
+
+ * check/setcode.c: New file implementing some basic tests
+ of the new jit_set_code() interface.
+
+ * check/Makefile.am: Update for newer test case.
+
2014-06-03 Paulo Andrade <address@hidden>
* include/lightning.h, lib/lightning.c: Add the new
diff --git a/check/Makefile.am b/check/Makefile.am
index 48cd9fa..22a2035 100644
--- a/check/Makefile.am
+++ b/check/Makefile.am
@@ -16,7 +16,7 @@
AM_CFLAGS = -I$(top_srcdir)/include -D_GNU_SOURCE
-check_PROGRAMS = lightning ccall self
+check_PROGRAMS = lightning ccall self setcode
lightning_LDADD = $(top_builddir)/lib/liblightning.la -lm $(SHLIB)
lightning_SOURCES = lightning.c
@@ -27,6 +27,9 @@ ccall_SOURCES = ccall.c
self_LDADD = $(top_builddir)/lib/liblightning.la -lm $(SHLIB)
self_SOURCES = self.c
+setcode_LDADD = $(top_builddir)/lib/liblightning.la -lm $(SHLIB)
+setcode_SOURCES = setcode.c
+
$(top_builddir)/lib/liblightning.la:
cd $(top_builddir)/lib; $(MAKE) $(AM_MAKEFLAGS) liblightning.la
@@ -75,7 +78,6 @@ EXTRA_DIST = \
qalu_mul.tst qalu_mul.ok \
qalu_div.tst qalu_div.ok \
ret.tst ret.ok \
- ccall.ok \
check.sh \
check.x87.sh \
check.arm.sh check.swf.sh \
@@ -178,7 +180,7 @@ $(swf_TESTS): check.swf.sh
TESTS += $(swf_TESTS)
endif
-TESTS += ccall self
+TESTS += ccall self setcode
CLEANFILES = $(TESTS)
#TESTS_ENVIRONMENT=$(srcdir)/run-test;
diff --git a/check/ccall.ok b/check/ccall.ok
deleted file mode 100644
index 9766475..0000000
--- a/check/ccall.ok
+++ /dev/null
@@ -1 +0,0 @@
-ok
diff --git a/check/self.ok b/check/self.ok
deleted file mode 100644
index 9766475..0000000
--- a/check/self.ok
+++ /dev/null
@@ -1 +0,0 @@
-ok
diff --git a/check/setcode.c b/check/setcode.c
new file mode 100644
index 0000000..0047f34
--- /dev/null
+++ b/check/setcode.c
@@ -0,0 +1,89 @@
+/*
+ * Simple test of using an alternate buffer for the code.
+ */
+
+#include <lightning.h>
+#include <stdio.h>
+#include <assert.h>
+#include <sys/mman.h>
+#if defined(__sgi)
+# include <fcntl.h>
+#endif
+
+#ifndef MAP_ANON
+# define MAP_ANON MAP_ANONYMOUS
+# ifndef MAP_ANONYMOUS
+# define MAP_ANONYMOUS 0
+# endif
+#endif
+
+#if !defined(__sgi)
+#define mmap_fd -1
+#endif
+
+int
+main(int argc, char *argv[])
+{
+ jit_uint8_t *ptr;
+ jit_state_t *_jit;
+ jit_word_t length;
+#if defined(__sgi)
+ int mmap_fd;
+#endif
+ void (*function)(void);
+
+#if defined(__sgi)
+ mmap_fd = open("/dev/zero", O_RDWR);
+#endif
+
+ ptr = mmap(NULL, 1024 * 1024,
+ PROT_EXEC | PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON, mmap_fd, 0);
+ assert(ptr != MAP_FAILED);
+#if defined(__sgi)
+ close(mmap_fd);
+#endif
+
+ init_jit(argv[0]);
+ _jit = jit_new_state();
+
+ jit_prolog();
+ jit_prepare();
+ jit_pushargi((jit_word_t)"%s\n");
+ jit_ellipsis();
+ jit_pushargi((jit_word_t)"ok");
+ jit_finishi(printf);
+
+ /* call to jit_realize() is only required when using an alternate
+ * code buffer. Note that not using mmap'ed memory may not work
+ * on several ports and/or operating system versions */
+ jit_realize();
+
+ length = 0;
+ if (jit_get_code(&length) != NULL)
+ abort();
+
+ if (length <= 4)
+ abort();
+
+ /* check that a too small buffer fails */
+ jit_set_code(ptr, 4);
+ function = jit_emit();
+ if (function != NULL)
+ abort();
+
+ /* and calling again with enough space works */
+ jit_set_code(ptr, 1024 * 1024);
+ function = jit_emit();
+ if (function == NULL)
+ abort();
+
+ jit_clear_state();
+ (*function)();
+ jit_destroy_state();
+ finish_jit();
+
+ munmap(ptr, 1024 * 1024);
+
+ return (0);
+}
diff --git a/include/lightning.h b/include/lightning.h
index 758f760..84521c3 100644
--- a/include/lightning.h
+++ b/include/lightning.h
@@ -887,6 +887,12 @@ extern void _jit_patch(jit_state_t*, jit_node_t*);
extern void _jit_patch_at(jit_state_t*, jit_node_t*, jit_node_t*);
#define jit_patch_abs(u,v) _jit_patch_abs(_jit,u,v)
extern void _jit_patch_abs(jit_state_t*, jit_node_t*, jit_pointer_t);
+#define jit_realize() _jit_realize(_jit)
+extern void _jit_realize(jit_state_t*);
+#define jit_get_code(u) _jit_get_code(_jit,u)
+extern jit_pointer_t _jit_get_code(jit_state_t*, jit_word_t*);
+#define jit_set_code(u,v) _jit_set_code(_jit,u,v)
+extern void _jit_set_code(jit_state_t*, jit_pointer_t, jit_word_t);
#define jit_emit() _jit_emit(_jit)
extern jit_pointer_t _jit_emit(jit_state_t*);
diff --git a/include/lightning/jit_private.h b/include/lightning/jit_private.h
index 7172994..1759bbe 100644
--- a/include/lightning/jit_private.h
+++ b/include/lightning/jit_private.h
@@ -336,6 +336,7 @@ struct jit_compiler {
#endif
jit_node_t *head;
jit_node_t *tail;
+ jit_uint32_t realize : 1; /* jit_realize() called? */
jit_uint32_t done : 1; /* emit state finished */
jit_uint32_t emit : 1; /* emit state entered */
jit_uint32_t again : 1; /* start over emiting function */
@@ -464,6 +465,8 @@ struct jit_state {
jit_word_t length;
} note;
jit_compiler_t *comp;
+ /* Flags to know if user did set the code and data buffers */
+ jit_uint32_t user_code : 1;
};
struct jit_register {
diff --git a/lib/jit_size.c b/lib/jit_size.c
index 6efad61..6678915 100644
--- a/lib/jit_size.c
+++ b/lib/jit_size.c
@@ -98,7 +98,7 @@ _jit_get_size(jit_state_t *_jit)
jit_word_t size;
jit_node_t *node;
- for (size = 0, node = _jitc->head; node; node = node->next)
+ for (size = JIT_INSTR_MAX, node = _jitc->head; node; node = node->next)
size += _szs[node->code];
return ((size + 4095) & -4096);
diff --git a/lib/lightning.c b/lib/lightning.c
index e0adeda..ee21b12 100644
--- a/lib/lightning.c
+++ b/lib/lightning.c
@@ -514,7 +514,7 @@ void
_jit_save(jit_state_t *_jit, jit_int32_t reg)
{
reg = jit_regno(reg);
- assert(!_jitc->emit);
+ assert(!_jitc->realize);
_jitc->spill[reg] = jit_new_node_w(jit_code_save, reg);
}
@@ -524,7 +524,7 @@ _jit_load(jit_state_t *_jit, jit_int32_t reg)
jit_node_t *node;
reg = jit_regno(reg);
- assert(!_jitc->emit);
+ assert(!_jitc->realize);
assert(_jitc->spill[reg]);
node = jit_new_node_w(jit_code_load, reg);
/* create a path to flag the save/load is not required */
@@ -562,7 +562,7 @@ _jit_data(jit_state_t *_jit, jit_pointer_t data,
jit_word_t key;
jit_node_t *node;
- assert(!_jitc->emit);
+ assert(!_jitc->realize);
/* Ensure there is space even if asking for a duplicate */
if (((_jitc->data.offset + 7) & -8) + length > _jit->data.length) {
@@ -887,7 +887,8 @@ _jit_clear_state(jit_state_t *_jit)
void
_jit_destroy_state(jit_state_t *_jit)
{
- munmap(_jit->code.ptr, _jit->code.length);
+ if (!_jit->user_code)
+ munmap(_jit->code.ptr, _jit->code.length);
munmap(_jit->data.ptr, _jit->data.length);
jit_free((jit_pointer_t *)&_jit);
}
@@ -895,21 +896,21 @@ _jit_destroy_state(jit_state_t *_jit)
jit_node_t *
_jit_new_node(jit_state_t *_jit, jit_code_t code)
{
- assert(!_jitc->emit);
+ assert(!_jitc->realize);
return (link_node(new_node(code)));
}
jit_node_t *
_jit_new_node_no_link(jit_state_t *_jit, jit_code_t code)
{
- assert(!_jitc->emit);
+ assert(!_jitc->realize);
return (new_node(code));
}
void
_jit_link_node(jit_state_t *_jit, jit_node_t *node)
{
- assert(!_jitc->emit);
+ assert(!_jitc->realize);
link_node(node);
}
@@ -918,7 +919,7 @@ _jit_new_node_w(jit_state_t *_jit, jit_code_t code,
jit_word_t u)
{
jit_node_t *node = new_node(code);
- assert(!_jitc->emit);
+ assert(!_jitc->realize);
node->u.w = u;
return (link_node(node));
}
@@ -928,7 +929,7 @@ _jit_new_node_p(jit_state_t *_jit, jit_code_t code,
jit_pointer_t u)
{
jit_node_t *node = new_node(code);
- assert(!_jitc->emit);
+ assert(!_jitc->realize);
node->u.p = u;
return (link_node(node));
}
@@ -938,7 +939,7 @@ _jit_new_node_ww(jit_state_t *_jit, jit_code_t code,
jit_word_t u, jit_word_t v)
{
jit_node_t *node = new_node(code);
- assert(!_jitc->emit);
+ assert(!_jitc->realize);
node->u.w = u;
node->v.w = v;
return (link_node(node));
@@ -963,7 +964,7 @@ _jit_new_node_wf(jit_state_t *_jit, jit_code_t code,
jit_word_t u, jit_float32_t v)
{
jit_node_t *node = new_node(code);
- assert(!_jitc->emit);
+ assert(!_jitc->realize);
node->u.w = u;
node->v.f = v;
return (link_node(node));
@@ -974,7 +975,7 @@ _jit_new_node_wd(jit_state_t *_jit, jit_code_t code,
jit_word_t u, jit_float64_t v)
{
jit_node_t *node = new_node(code);
- assert(!_jitc->emit);
+ assert(!_jitc->realize);
node->u.w = u;
node->v.d = v;
return (link_node(node));
@@ -985,7 +986,7 @@ _jit_new_node_www(jit_state_t *_jit, jit_code_t code,
jit_word_t u, jit_word_t v, jit_word_t w)
{
jit_node_t *node = new_node(code);
- assert(!_jitc->emit);
+ assert(!_jitc->realize);
node->u.w = u;
node->v.w = v;
node->w.w = w;
@@ -998,7 +999,7 @@ _jit_new_node_qww(jit_state_t *_jit, jit_code_t code,
jit_word_t v, jit_word_t w)
{
jit_node_t *node = new_node(code);
- assert(!_jitc->emit);
+ assert(!_jitc->realize);
assert(l != h);
node->u.q.l = l;
node->u.q.h = h;
@@ -1012,7 +1013,7 @@ _jit_new_node_wwf(jit_state_t *_jit, jit_code_t code,
jit_word_t u, jit_word_t v, jit_float32_t w)
{
jit_node_t *node = new_node(code);
- assert(!_jitc->emit);
+ assert(!_jitc->realize);
node->u.w = u;
node->v.w = v;
node->w.f = w;
@@ -1024,7 +1025,7 @@ _jit_new_node_wwd(jit_state_t *_jit, jit_code_t code,
jit_word_t u, jit_word_t v, jit_float64_t w)
{
jit_node_t *node = new_node(code);
- assert(!_jitc->emit);
+ assert(!_jitc->realize);
node->u.w = u;
node->v.w = v;
node->w.d = w;
@@ -1036,7 +1037,7 @@ _jit_new_node_pww(jit_state_t *_jit, jit_code_t code,
jit_pointer_t u, jit_word_t v, jit_word_t w)
{
jit_node_t *node = new_node(code);
- assert(!_jitc->emit);
+ assert(!_jitc->realize);
node->u.p = u;
node->v.w = v;
node->w.w = w;
@@ -1048,7 +1049,7 @@ _jit_new_node_pwf(jit_state_t *_jit, jit_code_t code,
jit_pointer_t u, jit_word_t v, jit_float32_t w)
{
jit_node_t *node = new_node(code);
- assert(!_jitc->emit);
+ assert(!_jitc->realize);
node->u.p = u;
node->v.w = v;
node->w.f = w;
@@ -1060,7 +1061,7 @@ _jit_new_node_pwd(jit_state_t *_jit, jit_code_t code,
jit_pointer_t u, jit_word_t v, jit_float64_t w)
{
jit_node_t *node = new_node(code);
- assert(!_jitc->emit);
+ assert(!_jitc->realize);
node->u.p = u;
node->v.w = v;
node->w.d = w;
@@ -1703,6 +1704,49 @@ _jit_regarg_clr(jit_state_t *_jit, jit_node_t *node,
jit_int32_t value)
jit_regset_clrbit(&_jitc->regarg, jit_regno(node->w.w));
}
+void
+_jit_realize(jit_state_t *_jit)
+{
+ assert(!_jitc->realize);
+ if (_jitc->function)
+ jit_epilog();
+ jit_optimize();
+ _jitc->realize = 1;
+
+#if GET_JIT_SIZE
+ /* Heuristic to guess code buffer size */
+ _jitc->mult = 4;
+ _jit->code.length = _jitc->pool.length * 1024 * _jitc->mult;
+#else
+ _jit->code.length = jit_get_size();
+#endif
+}
+
+jit_pointer_t
+_jit_get_code(jit_state_t *_jit, jit_word_t *length)
+{
+ assert(_jitc->realize);
+ if (length) {
+ if (_jitc->done)
+ /* If code already generated, return exact size of code */
+ *length = _jit->pc.uc - _jit->code.ptr;
+ else
+ /* Else return current size of the code buffer */
+ *length = _jit->code.length;
+ }
+
+ return (_jit->code.ptr);
+}
+
+void
+_jit_set_code(jit_state_t *_jit, jit_pointer_t ptr, jit_word_t length)
+{
+ assert(_jitc->realize);
+ _jit->code.ptr = ptr;
+ _jit->code.length = length;
+ _jit->user_code = 1;
+}
+
jit_pointer_t
_jit_emit(jit_state_t *_jit)
{
@@ -1714,39 +1758,35 @@ _jit_emit(jit_state_t *_jit)
int mmap_fd;
#endif
- if (_jitc->function)
- jit_epilog();
- jit_optimize();
+ if (!_jitc->realize)
+ jit_realize();
_jitc->emit = 1;
-#if GET_JIT_SIZE
- /* Heuristic to guess code buffer size */
- _jitc->mult = 4;
- _jit->code.length = _jitc->pool.length * 1024 * _jitc->mult;
-#else
- _jit->code.length = jit_get_size();
-#endif
-
+ if (!_jit->user_code) {
#if defined(__sgi)
- mmap_fd = open("/dev/zero", O_RDWR);
+ mmap_fd = open("/dev/zero", O_RDWR);
#endif
- _jit->code.ptr = mmap(NULL, _jit->code.length,
- PROT_EXEC | PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANON, mmap_fd, 0);
- assert(_jit->code.ptr != MAP_FAILED);
+ _jit->code.ptr = mmap(NULL, _jit->code.length,
+ PROT_EXEC | PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON, mmap_fd, 0);
+ assert(_jit->code.ptr != MAP_FAILED);
+ }
_jitc->code.end = _jit->code.ptr + _jit->code.length -
jit_get_max_instr();
_jit->pc.uc = _jit->code.ptr;
for (;;) {
if ((code = emit_code()) == NULL) {
+ _jitc->patches.offset = 0;
for (node = _jitc->head; node; node = node->next) {
if (node->link &&
(node->code == jit_code_label ||
node->code == jit_code_epilog))
node->flag &= ~jit_flag_patch;
}
+ if (_jit->user_code)
+ goto fail;
#if GET_JIT_SIZE
++_jitc->mult;
length = _jitc->pool.length * 1024 * _jitc->mult;
@@ -1778,14 +1818,14 @@ _jit_emit(jit_state_t *_jit)
_jitc->code.end = _jit->code.ptr + _jit->code.length -
jit_get_max_instr();
_jit->pc.uc = _jit->code.ptr;
- _jitc->patches.offset = 0;
}
else
break;
}
#if defined(__sgi)
- close(mmap_fd);
+ if (!_jit->user_code)
+ close(mmap_fd);
#endif
_jitc->done = 1;
@@ -1793,10 +1833,15 @@ _jit_emit(jit_state_t *_jit)
result = mprotect(_jit->data.ptr, _jit->data.length, PROT_READ);
assert(result == 0);
- result = mprotect(_jit->code.ptr, _jit->code.length, PROT_READ |
PROT_EXEC);
- assert(result == 0);
+ if (!_jit->user_code) {
+ result = mprotect(_jit->code.ptr, _jit->code.length,
+ PROT_READ | PROT_EXEC);
+ assert(result == 0);
+ }
return (_jit->code.ptr);
+fail:
+ return (NULL);
}
/* Compute initial reglive and regmask set values of a basic block.
- [Guile-commits] 414/437: Always set t12 to address of called function, (continued)
- [Guile-commits] 414/437: Always set t12 to address of called function, Andy Wingo, 2018/07/02
- [Guile-commits] 289/437: Remove the global but not advertised jit_progname variable, Andy Wingo, 2018/07/02
- [Guile-commits] 334/437: ARM: Correct several inconsistencies with ldrd and strd, Andy Wingo, 2018/07/02
- [Guile-commits] 210/437: Correct all ldst test cases., Andy Wingo, 2018/07/02
- [Guile-commits] 252/437: GNU lightning 2.0.1 release, Andy Wingo, 2018/07/02
- [Guile-commits] 327/437: Force creation of the m4 directory on a clean checkout, Andy Wingo, 2018/07/02
- [Guile-commits] 314/437: Add back files missed when reapplying patches, Andy Wingo, 2018/07/02
- [Guile-commits] 354/437: Implement the jit_arg_register_p predicate., Andy Wingo, 2018/07/02
- [Guile-commits] 381/437: Remove wrong comment after cut and paste, Andy Wingo, 2018/07/02
- [Guile-commits] 209/437: Correct float division and LX with stop code generation., Andy Wingo, 2018/07/02
- [Guile-commits] 280/437: Implement the new jit_set_code interface.,
Andy Wingo <=
- [Guile-commits] 284/437: ARM: Do not emit a nop stack adjust instruction., Andy Wingo, 2018/07/02
- [Guile-commits] 345/437: PPC: Implement and use mcrxr emulation by default, Andy Wingo, 2018/07/02
- [Guile-commits] 246/437: Use the logic to workaround float NaN and Inf Hercules bug conditional, Andy Wingo, 2018/07/02
- [Guile-commits] 363/437: Correct typo, Andy Wingo, 2018/07/02
- [Guile-commits] 383/437: ia64: Implement cache flush., Andy Wingo, 2018/07/02
- [Guile-commits] 371/437: Correct read of freed memory, Andy Wingo, 2018/07/02
- [Guile-commits] 342/437: x86: Implement support for the x32 abi, Andy Wingo, 2018/07/02
- [Guile-commits] 416/437: Build and pass all tests on 32 and 64 bit sparc, Andy Wingo, 2018/07/02
- [Guile-commits] 400/437: Correct missing jit_unget_reg calls, Andy Wingo, 2018/07/02
- [Guile-commits] 418/437: Correct typo and values in jit_sparc-sz.c, Andy Wingo, 2018/07/02