[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