Ticket #18: 03_mmap-jit.patch.txt

File 03_mmap-jit.patch.txt, 10.0 KB (added by Infinoid, 6 years ago)

Minor update to Makefile interdependencies (this fixes builds on non-jit architectures)

Line 
1[core] Allocate JIT buffers with mmap on linux.
2
3From: Mark Glines <mark@glines.org>
4
5
6---
7
8 config/gen/makefiles/root.in          |    4 ++-
9 config/gen/platform/generic/memexec.c |   21 ++++++++++++++--
10 src/jit.h                             |    8 +++++-
11 src/jit/i386/exec_dep.c               |   44 +++++++++++++++++++++++++++++++++
12 src/jit/i386/exec_dep.h               |    3 ++
13 src/jit/i386/jit_defs.c               |    7 +++++
14 src/jit/i386/jit_emit.h               |    2 +-
15 tools/build/nativecall.pl             |   15 +++++++++++
16 8 files changed, 96 insertions(+), 8 deletions(-)
17
18
19diff --git a/config/gen/makefiles/root.in b/config/gen/makefiles/root.in
20index 29e2c6f..7042889 100644
21--- a/config/gen/makefiles/root.in
22+++ b/config/gen/makefiles/root.in
23@@ -1054,7 +1054,7 @@ $(SRC_DIR)/jit_cpu$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/jit_emit.h
24 
25 $(SRC_DIR)/exec$(O) : $(GENERAL_H_FILES) @TEMP_exec_h@ $(SRC_DIR)/jit_emit.h
26 
27-$(SRC_DIR)/exec_dep$(O) : $(GENERAL_H_FILES) @TEMP_exec_h@ $(SRC_DIR)/jit_emit.h
28+$(SRC_DIR)/exec_dep$(O) : $(GENERAL_H_FILES) @TEMP_exec_h@ $(SRC_DIR)/jit_emit.h $(SRC_DIR)/pmc/managedstruct.c
29 
30 $(SRC_DIR)/exec_cpu$(O) : $(GENERAL_H_FILES) @TEMP_exec_h@ $(SRC_DIR)/jit_emit.h
31 
32@@ -1187,7 +1187,7 @@ $(SRC_DIR)/dataypes$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/dataypes.c
33 
34 $(SRC_DIR)/exit$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/exit.c
35 
36-$(SRC_DIR)/nci$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/nci.c $(SRC_DIR)/nci.str
37+$(SRC_DIR)/nci$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/nci.c $(SRC_DIR)/nci.str $(SRC_DIR)/pmc/pmc_managedstruct.h
38 
39 $(SRC_DIR)/vtables$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/vtables.c
40 
41diff --git a/config/gen/platform/generic/memexec.c b/config/gen/platform/generic/memexec.c
42index ebcb911..aa82081 100644
43--- a/config/gen/platform/generic/memexec.c
44+++ b/config/gen/platform/generic/memexec.c
45@@ -22,6 +22,9 @@ Memory protection stuff
46 */
47 
48 #ifdef PARROT_HAS_EXEC_PROTECT
49+
50+#define PARROT_EXEC_PERMS PROT_READ|PROT_WRITE|PROT_EXEC
51+
52 /*
53 
54 =item C<void * mem_alloc_executable(size_t size)>
55@@ -39,9 +42,15 @@ mem_alloc_executable(size_t size)
56     void *p;
57     size_t pagesize = sysconf(_SC_PAGESIZE);
58     size = (size + pagesize - 1) & ~(pagesize-1);
59+#ifdef WIN32
60     if (posix_memalign(&p, pagesize, size))
61         return NULL;
62-    mprotect(p, size, PROT_READ|PROT_WRITE|PROT_EXEC);
63+    mprotect(p, size, PARROT_EXEC_PERMS);
64+#else /* !WIN32 */
65+    p = mmap(NULL, size, PARROT_EXEC_PERMS, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
66+    if (!p)
67+        return NULL;
68+#endif /* WIN32 */
69     return p;
70 }
71 
72@@ -58,7 +67,11 @@ Free a buffer allocated with mem_alloc_executable().
73 void
74 mem_free_executable(void *p, size_t size)
75 {
76+#ifdef WIN32
77     free(p);
78+#else /* !WIN32 */
79+    munmap(p, size);
80+#endif /* WIN32 */
81 }
82 
83 /*
84@@ -80,6 +93,7 @@ mem_realloc_executable(void* oldp, size_t oldsize, size_t newsize)
85     void *newp;
86     size_t pagesize = sysconf(_SC_PAGESIZE);
87     size_t roundup;
88+#ifdef WIN32
89     temp = realloc(oldp, newsize);
90     if (temp == NULL)
91         return NULL;
92@@ -88,10 +102,13 @@ mem_realloc_executable(void* oldp, size_t oldsize, size_t newsize)
93     if (posix_memalign(&newp, pagesize, roundup))
94         newp = NULL;
95     if (newp) {
96-        mprotect(newp, roundup, PROT_READ|PROT_WRITE|PROT_EXEC);
97+        mprotect(newp, roundup, PARROT_EXEC_PERMS);
98         memcpy(newp, temp, newsize);
99     }
100     free(temp);
101+#else /* !WIN32 */
102+    temp = mremap(oldp, oldsize, newsize, PARROT_EXEC_PERMS);
103+#endif /* WIN32 */
104     return newp;
105 }
106 #endif
107diff --git a/src/jit.h b/src/jit.h
108index 39b444c..27fe7ac 100644
109--- a/src/jit.h
110+++ b/src/jit.h
111@@ -321,7 +321,13 @@ parrot_build_asm(PARROT_INTERP,
112 /*
113  * NCI interface
114  */
115-void *Parrot_jit_build_call_func(Interp *, PMC *, STRING *);
116+void *Parrot_jit_build_call_func(Interp *, PMC *, STRING *, int *);
117+/* custom pmc callback functions */
118+void Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv);
119+PMC* Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv);
120+struct jit_buffer_private_data {
121+    int size;
122+};
123 
124 #endif /* PARROT_JIT_H_GUARD */
125 
126diff --git a/src/jit/i386/exec_dep.c b/src/jit/i386/exec_dep.c
127index 0756ac3..d62dec8 100644
128--- a/src/jit/i386/exec_dep.c
129+++ b/src/jit/i386/exec_dep.c
130@@ -16,6 +16,7 @@
131  */
132 
133 #include "parrot/parrot.h"
134+#include "pmc/pmc_managedstruct.h"
135 #include "jit.h"
136 #define JIT_EMIT 1
137 #include "jit_emit.h"
138@@ -186,6 +187,49 @@ offset_fixup(Parrot_exec_objfile_t *obj)
139     }
140 }
141 
142+void
143+Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv) {
144+    struct jit_buffer_private_data *jit = (struct jit_buffer_private_data*)priv;
145+    mem_free_executable(ptr, jit->size);
146+    free(priv);
147+}
148+
149+PMC *
150+Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv) {
151+    struct jit_buffer_private_data *jit = (struct jit_buffer_private_data*)priv;
152+    PMC *rv = pmc_new(interp, pmc->vtable->base_type);
153+    void *tmp, *tmp2;
154+
155+    VTABLE_init(interp, rv);
156+    /* copy the attributes */
157+    GETATTR_ManagedStruct_custom_free_func(interp, pmc, tmp);
158+    SETATTR_ManagedStruct_custom_free_func(interp, rv , tmp);
159+    GETATTR_ManagedStruct_custom_clone_func(interp, pmc, tmp);
160+    SETATTR_ManagedStruct_custom_clone_func(interp, rv , tmp);
161+    GETATTR_ManagedStruct_custom_free_priv(interp, pmc, tmp);
162+    if(tmp) {
163+        tmp2 = mem_sys_allocate(sizeof(struct jit_buffer_private_data));
164+        memcpy(tmp2, tmp, sizeof(struct jit_buffer_private_data));
165+        SETATTR_ManagedStruct_custom_free_priv(interp, rv , tmp2);
166+    }
167+    GETATTR_ManagedStruct_custom_clone_priv(interp, pmc, tmp);
168+    if(tmp) {
169+        tmp2 = mem_sys_allocate(sizeof(struct jit_buffer_private_data));
170+        memcpy(tmp2, tmp, sizeof(struct jit_buffer_private_data));
171+        SETATTR_ManagedStruct_custom_clone_priv(interp, rv , tmp2);
172+    }
173+
174+    /* copy the execmem buffer */
175+    if (PARROT_MANAGEDSTRUCT(pmc)->ptr) {
176+        void *newptr, *ptr = PARROT_MANAGEDSTRUCT(pmc)->ptr;
177+        newptr = mem_alloc_executable(jit->size);
178+        memcpy(newptr, ptr, jit->size);
179+        PARROT_MANAGEDSTRUCT(rv)->ptr = newptr;
180+    }
181+
182+    return rv;
183+}
184+
185 /*
186  * Local variables:
187  *   c-file-style: "parrot"
188diff --git a/src/jit/i386/exec_dep.h b/src/jit/i386/exec_dep.h
189index d8a7d92..b081f1c 100644
190--- a/src/jit/i386/exec_dep.h
191+++ b/src/jit/i386/exec_dep.h
192@@ -33,6 +33,9 @@ void Parrot_exec_normal_op(Parrot_jit_info_t *jit_info, PARROT_INTERP)
193 void Parrot_exec_restart_op(Parrot_jit_info_t *jit_info, PARROT_INTERP)
194         __attribute__nonnull__(2);
195 
196+void Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv);
197+PMC* Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv);
198+
199 #define ASSERT_ARGS_offset_fixup __attribute__unused__ int _ASSERT_ARGS_CHECK = 0
200 #define ASSERT_ARGS_Parrot_exec_cpcf_op __attribute__unused__ int _ASSERT_ARGS_CHECK = \
201        PARROT_ASSERT_ARG(interp)
202diff --git a/src/jit/i386/jit_defs.c b/src/jit/i386/jit_defs.c
203index 0278a71..5d60a97 100644
204--- a/src/jit/i386/jit_defs.c
205+++ b/src/jit/i386/jit_defs.c
206@@ -2116,10 +2116,13 @@ calc_signature_needs(const char *sig, int *strings)
207  * The generate function for a specific signature looks quite similar to
208  * an optimized compile of src/nci.c:pcf_x_yy(). In case of any troubles
209  * just compare the disassembly.
210+ *
211+ * If a non-NULL sizeptr is passed, the integer it points to will be written
212+ * with the size of the allocated execmem buffer.
213  */
214 
215 void *
216-Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci, STRING *signature)
217+Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci, STRING *signature, int *sizeptr)
218 {
219     Parrot_jit_info_t jit_info;
220     char     *pc;
221@@ -2453,6 +2456,8 @@ Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci, STRING *signature)
222     PARROT_ASSERT(pc - jit_info.arena.start <= JIT_ALLOC_SIZE);
223     /* could shrink arena.start here to used size */
224     PObj_active_destroy_SET(pmc_nci);
225+    if (sizeptr)
226+        *sizeptr = JIT_ALLOC_SIZE;
227     return (void *)D2FPTR(jit_info.arena.start);
228 }
229 
230diff --git a/src/jit/i386/jit_emit.h b/src/jit/i386/jit_emit.h
231index f6f29fe..4ea814e 100644
232--- a/src/jit/i386/jit_emit.h
233+++ b/src/jit/i386/jit_emit.h
234@@ -1879,7 +1879,7 @@ int count_regs(PARROT_INTERP, char *sig, char *sig_start);
235 size_t calc_signature_needs(const char *sig, int *strings);
236 
237 void * Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci,
238-    STRING *signature);
239+    STRING *signature, int *sizeptr);
240 
241 /*
242  * register usage
243diff --git a/tools/build/nativecall.pl b/tools/build/nativecall.pl
244index 5d878d5..4c542f8 100644
245--- a/tools/build/nativecall.pl
246+++ b/tools/build/nativecall.pl
247@@ -195,8 +195,10 @@ sub print_head {
248 #include "parrot/parrot.h"
249 #include "parrot/hash.h"
250 #include "parrot/oplib/ops.h"
251+#include "pmc/pmc_managedstruct.h"
252 #include "pmc/pmc_nci.h"
253 #include "nci.str"
254+#include "jit.h"
255 
256 /* HEADERIZER HFILE: none */
257 /* HEADERIZER STOP */
258@@ -554,11 +556,22 @@ $put_pointer
259         return F2DPTR(VTABLE_get_pointer(interp, b));
260     }
261     else {
262-        void * const result = Parrot_jit_build_call_func(interp, pmc_nci, signature);
263+        int jit_size;
264+        void * const result = Parrot_jit_build_call_func(interp, pmc_nci, signature, &jit_size);
265         if (result) {
266+            struct jit_buffer_private_data *priv;
267             *jitted = 1;
268             temp_pmc = pmc_new(interp, enum_class_ManagedStruct);
269             VTABLE_set_pointer(interp, temp_pmc, (void *)result);
270+#ifdef PARROT_HAS_EXEC_PROTECT
271+            priv = (struct jit_buffer_private_data *)
272+                mem_sys_allocate(sizeof(struct jit_buffer_private_data));
273+            priv->size = jit_size;
274+            SETATTR_ManagedStruct_custom_free_func(interp, temp_pmc, Parrot_jit_free_buffer);
275+            SETATTR_ManagedStruct_custom_free_priv(interp, temp_pmc, priv);
276+            SETATTR_ManagedStruct_custom_clone_func(interp, temp_pmc, Parrot_jit_clone_buffer);
277+            SETATTR_ManagedStruct_custom_clone_priv(interp, temp_pmc, priv);
278+#endif /* PARROT_HAS_EXEC_PROTECT */
279             VTABLE_set_pmc_keyed_str(interp, HashPointer, jit_key_name, temp_pmc);
280             return result;
281         }