[svn:parrot] r37993 - in trunk: config/gen/makefiles config/gen/platform/generic src src/jit/i386 tools/build
Infinoid at svn.parrot.org
Infinoid at svn.parrot.org
Thu Apr 9 02:03:25 UTC 2009
Author: Infinoid
Date: Thu Apr 9 02:03:24 2009
New Revision: 37993
URL: https://trac.parrot.org/parrot/changeset/37993
Log:
[jit] Allocate JIT buffers with mmap on linux. Set things up so they're freed properly using munmap().
Note that this currently only has an effect when PARROT_HAS_EXEC_PROTECT is defined.
Modified:
trunk/config/gen/makefiles/root.in
trunk/config/gen/platform/generic/memexec.c
trunk/src/jit.c
trunk/src/jit.h
trunk/src/jit/i386/jit_defs.c
trunk/src/jit/i386/jit_emit.h
trunk/tools/build/nativecall.pl
Modified: trunk/config/gen/makefiles/root.in
==============================================================================
--- trunk/config/gen/makefiles/root.in Thu Apr 9 02:03:17 2009 (r37992)
+++ trunk/config/gen/makefiles/root.in Thu Apr 9 02:03:24 2009 (r37993)
@@ -1054,7 +1054,7 @@
$(SRC_DIR)/exec$(O) : $(GENERAL_H_FILES) @TEMP_exec_h@ $(SRC_DIR)/jit_emit.h
-$(SRC_DIR)/exec_dep$(O) : $(GENERAL_H_FILES) @TEMP_exec_h@ $(SRC_DIR)/jit_emit.h
+$(SRC_DIR)/exec_dep$(O) : $(GENERAL_H_FILES) @TEMP_exec_h@ $(SRC_DIR)/jit_emit.h $(SRC_DIR)/pmc/managedstruct.c
$(SRC_DIR)/exec_cpu$(O) : $(GENERAL_H_FILES) @TEMP_exec_h@ $(SRC_DIR)/jit_emit.h
@@ -1187,7 +1187,7 @@
$(SRC_DIR)/exit$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/exit.c
-$(SRC_DIR)/nci$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/nci.c $(SRC_DIR)/nci.str
+$(SRC_DIR)/nci$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/nci.c $(SRC_DIR)/nci.str $(SRC_DIR)/pmc/pmc_managedstruct.h
$(SRC_DIR)/vtables$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/vtables.c
Modified: trunk/config/gen/platform/generic/memexec.c
==============================================================================
--- trunk/config/gen/platform/generic/memexec.c Thu Apr 9 02:03:17 2009 (r37992)
+++ trunk/config/gen/platform/generic/memexec.c Thu Apr 9 02:03:24 2009 (r37993)
@@ -22,6 +22,9 @@
*/
#ifdef PARROT_HAS_EXEC_PROTECT
+
+# define PARROT_EXEC_PERMS PROT_READ|PROT_WRITE|PROT_EXEC
+
/*
=item C<void * mem_alloc_executable(size_t size)>
@@ -39,9 +42,15 @@
void *p;
size_t pagesize = sysconf(_SC_PAGESIZE);
size = (size + pagesize - 1) & ~(pagesize-1);
+# ifdef WIN32
if (posix_memalign(&p, pagesize, size))
return NULL;
- mprotect(p, size, PROT_READ|PROT_WRITE|PROT_EXEC);
+ mprotect(p, size, PARROT_EXEC_PERMS);
+# else /* !WIN32 */
+ p = mmap(NULL, size, PARROT_EXEC_PERMS, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ if (!p)
+ return NULL;
+# endif /* WIN32 */
return p;
}
@@ -58,7 +67,11 @@
void
mem_free_executable(void *p, size_t size)
{
+# ifdef WIN32
free(p);
+# else /* !WIN32 */
+ munmap(p, size);
+# endif /* WIN32 */
}
/*
@@ -80,6 +93,7 @@
void *newp;
size_t pagesize = sysconf(_SC_PAGESIZE);
size_t roundup;
+# ifdef WIN32
temp = realloc(oldp, newsize);
if (temp == NULL)
return NULL;
@@ -88,10 +102,13 @@
if (posix_memalign(&newp, pagesize, roundup))
newp = NULL;
if (newp) {
- mprotect(newp, roundup, PROT_READ|PROT_WRITE|PROT_EXEC);
+ mprotect(newp, roundup, PARROT_EXEC_PERMS);
memcpy(newp, temp, newsize);
}
free(temp);
+# else /* !WIN32 */
+ temp = mremap(oldp, oldsize, newsize, PARROT_EXEC_PERMS);
+# endif /* WIN32 */
return newp;
}
#endif
Modified: trunk/src/jit.c
==============================================================================
--- trunk/src/jit.c Thu Apr 9 02:03:17 2009 (r37992)
+++ trunk/src/jit.c Thu Apr 9 02:03:24 2009 (r37993)
@@ -35,6 +35,7 @@
#include "parrot/packfile.h"
#include "parrot/oplib/ops.h"
#include "pmc/pmc_sub.h"
+#include "pmc/pmc_managedstruct.h"
#define JIT_SEGS 0
@@ -1753,6 +1754,79 @@
/*
+=item C<void Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv)>
+
+This is a callback to implement the proper freeing semantics. It is called by
+the ManagedStruct PMC as it is garbage collected.
+
+=cut
+
+*/
+
+void
+Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv)
+{
+ struct jit_buffer_private_data *jit = (struct jit_buffer_private_data*)priv;
+ mem_free_executable(ptr, jit->size);
+ free(priv);
+}
+
+/*
+
+=item C<PMC *Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv)>
+
+This is a callback to implement the proper cloning semantics for jit buffers.
+It is called by the ManagedStruct PMC's clone() function.
+
+=cut
+
+*/
+
+PMC *
+Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv)
+{
+ struct jit_buffer_private_data *jit = (struct jit_buffer_private_data*)priv;
+ PMC *rv = pmc_new(interp, pmc->vtable->base_type);
+ void *tmp, *freepriv, *clonepriv;
+
+ VTABLE_init(interp, rv);
+ /* copy the attributes */
+ GETATTR_ManagedStruct_custom_free_func(interp, pmc, tmp);
+ SETATTR_ManagedStruct_custom_free_func(interp, rv , tmp);
+ GETATTR_ManagedStruct_custom_clone_func(interp, pmc, tmp);
+ SETATTR_ManagedStruct_custom_clone_func(interp, rv , tmp);
+ GETATTR_ManagedStruct_custom_free_priv(interp , pmc, freepriv);
+ GETATTR_ManagedStruct_custom_clone_priv(interp, pmc, clonepriv);
+ if (freepriv) {
+ tmp = mem_sys_allocate(sizeof (struct jit_buffer_private_data));
+ memcpy(tmp, freepriv, sizeof (struct jit_buffer_private_data));
+ SETATTR_ManagedStruct_custom_free_priv(interp, rv , tmp);
+ if (clonepriv == freepriv) {
+ /* clonepriv is a copy of freepriv, make it a copy in the clone too. */
+ SETATTR_ManagedStruct_custom_clone_priv(interp, rv , tmp);
+ clonepriv = NULL; /* disable the clonepriv copying below */
+ }
+ }
+ if (clonepriv) {
+ tmp = mem_sys_allocate(sizeof (struct jit_buffer_private_data));
+ memcpy(tmp, clonepriv, sizeof (struct jit_buffer_private_data));
+ SETATTR_ManagedStruct_custom_clone_priv(interp, rv , tmp);
+ }
+
+ /* copy the execmem buffer */
+ if (PARROT_MANAGEDSTRUCT(pmc)->ptr) {
+ void *newptr, *ptr = PARROT_MANAGEDSTRUCT(pmc)->ptr;
+ newptr = mem_alloc_executable(jit->size);
+ memcpy(newptr, ptr, jit->size);
+ PARROT_MANAGEDSTRUCT(rv)->ptr = newptr;
+ }
+
+ return rv;
+}
+
+
+/*
+
=back
=head1 SEE ALSO
Modified: trunk/src/jit.h
==============================================================================
--- trunk/src/jit.h Thu Apr 9 02:03:17 2009 (r37992)
+++ trunk/src/jit.h Thu Apr 9 02:03:24 2009 (r37993)
@@ -321,7 +321,13 @@
/*
* NCI interface
*/
-void *Parrot_jit_build_call_func(Interp *, PMC *, STRING *);
+void *Parrot_jit_build_call_func(Interp *, PMC *, STRING *, int *);
+/* custom pmc callback functions */
+void Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv);
+PMC* Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv);
+struct jit_buffer_private_data {
+ int size;
+};
#endif /* PARROT_JIT_H_GUARD */
Modified: trunk/src/jit/i386/jit_defs.c
==============================================================================
--- trunk/src/jit/i386/jit_defs.c Thu Apr 9 02:03:17 2009 (r37992)
+++ trunk/src/jit/i386/jit_defs.c Thu Apr 9 02:03:24 2009 (r37993)
@@ -2116,10 +2116,13 @@
* The generate function for a specific signature looks quite similar to
* an optimized compile of src/nci.c:pcf_x_yy(). In case of any troubles
* just compare the disassembly.
+ *
+ * If a non-NULL sizeptr is passed, the integer it points to will be written
+ * with the size of the allocated execmem buffer.
*/
void *
-Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci, STRING *signature)
+Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci, STRING *signature, int *sizeptr)
{
Parrot_jit_info_t jit_info;
char *pc;
@@ -2453,6 +2456,8 @@
PARROT_ASSERT(pc - jit_info.arena.start <= JIT_ALLOC_SIZE);
/* could shrink arena.start here to used size */
PObj_active_destroy_SET(pmc_nci);
+ if (sizeptr)
+ *sizeptr = JIT_ALLOC_SIZE;
return (void *)D2FPTR(jit_info.arena.start);
}
Modified: trunk/src/jit/i386/jit_emit.h
==============================================================================
--- trunk/src/jit/i386/jit_emit.h Thu Apr 9 02:03:17 2009 (r37992)
+++ trunk/src/jit/i386/jit_emit.h Thu Apr 9 02:03:24 2009 (r37993)
@@ -1879,7 +1879,7 @@
size_t calc_signature_needs(const char *sig, int *strings);
void * Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci,
- STRING *signature);
+ STRING *signature, int *sizeptr);
/*
* register usage
Modified: trunk/tools/build/nativecall.pl
==============================================================================
--- trunk/tools/build/nativecall.pl Thu Apr 9 02:03:17 2009 (r37992)
+++ trunk/tools/build/nativecall.pl Thu Apr 9 02:03:24 2009 (r37993)
@@ -195,8 +195,10 @@
#include "parrot/parrot.h"
#include "parrot/hash.h"
#include "parrot/oplib/ops.h"
+#include "pmc/pmc_managedstruct.h"
#include "pmc/pmc_nci.h"
#include "nci.str"
+#include "jit.h"
/* HEADERIZER HFILE: none */
/* HEADERIZER STOP */
@@ -554,11 +556,22 @@
return F2DPTR(VTABLE_get_pointer(interp, b));
}
else {
- void * const result = Parrot_jit_build_call_func(interp, pmc_nci, signature);
+ int jit_size;
+ void * const result = Parrot_jit_build_call_func(interp, pmc_nci, signature, &jit_size);
if (result) {
+ struct jit_buffer_private_data *priv;
*jitted = 1;
temp_pmc = pmc_new(interp, enum_class_ManagedStruct);
VTABLE_set_pointer(interp, temp_pmc, (void *)result);
+#ifdef PARROT_HAS_EXEC_PROTECT
+ priv = (struct jit_buffer_private_data *)
+ mem_sys_allocate(sizeof(struct jit_buffer_private_data));
+ priv->size = jit_size;
+ SETATTR_ManagedStruct_custom_free_func(interp, temp_pmc, Parrot_jit_free_buffer);
+ SETATTR_ManagedStruct_custom_free_priv(interp, temp_pmc, priv);
+ SETATTR_ManagedStruct_custom_clone_func(interp, temp_pmc, Parrot_jit_clone_buffer);
+ SETATTR_ManagedStruct_custom_clone_priv(interp, temp_pmc, priv);
+#endif /* PARROT_HAS_EXEC_PROTECT */
VTABLE_set_pmc_keyed_str(interp, HashPointer, jit_key_name, temp_pmc);
return result;
}
More information about the parrot-commits
mailing list