[Pcre-svn] [614] code/trunk/src/sljit: JIT compiler update.

Top Page
Delete this message
Author: Subversion repository
Date:  
To: pcre-svn
Subject: [Pcre-svn] [614] code/trunk/src/sljit: JIT compiler update.
Revision: 614
          http://www.exim.org/viewvc/pcre2?view=rev&revision=614
Author:   zherczeg
Date:     2016-12-09 14:22:11 +0000 (Fri, 09 Dec 2016)
Log Message:
-----------
JIT compiler update.


Modified Paths:
--------------
    code/trunk/src/sljit/sljitConfig.h
    code/trunk/src/sljit/sljitConfigInternal.h
    code/trunk/src/sljit/sljitLir.c
    code/trunk/src/sljit/sljitLir.h
    code/trunk/src/sljit/sljitNativeARM_32.c
    code/trunk/src/sljit/sljitNativeARM_64.c
    code/trunk/src/sljit/sljitNativeARM_T2_32.c
    code/trunk/src/sljit/sljitNativeMIPS_common.c
    code/trunk/src/sljit/sljitNativePPC_common.c
    code/trunk/src/sljit/sljitNativeSPARC_common.c
    code/trunk/src/sljit/sljitNativeTILEGX_64.c
    code/trunk/src/sljit/sljitNativeX86_common.c


Added Paths:
-----------
    code/trunk/src/sljit/sljitProtExecAllocator.c


Modified: code/trunk/src/sljit/sljitConfig.h
===================================================================
--- code/trunk/src/sljit/sljitConfig.h    2016-12-08 18:56:24 UTC (rev 613)
+++ code/trunk/src/sljit/sljitConfig.h    2016-12-09 14:22:11 UTC (rev 614)
@@ -90,12 +90,22 @@


 /* Executable code allocation:
    If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should
-   define both SLJIT_MALLOC_EXEC and SLJIT_FREE_EXEC. */
+   define SLJIT_MALLOC_EXEC, SLJIT_FREE_EXEC, and SLJIT_ENABLE_EXEC. */
 #ifndef SLJIT_EXECUTABLE_ALLOCATOR
 /* Enabled by default. */
 #define SLJIT_EXECUTABLE_ALLOCATOR 1
+
+/* When SLJIT_PROT_EXECUTABLE_ALLOCATOR is enabled SLJIT uses
+   an allocator which does not set writable and executable
+   permission flags at the same time. The trade-of is increased
+   memory consumption and disabled dynamic code modifications. */
+#ifndef SLJIT_PROT_EXECUTABLE_ALLOCATOR
+/* Disabled by default. */
+#define SLJIT_PROT_EXECUTABLE_ALLOCATOR 0
 #endif


+#endif
+
 /* Force cdecl calling convention even if a better calling
    convention (e.g. fastcall) is supported by the C compiler.
    If this option is enabled, C functions without


Modified: code/trunk/src/sljit/sljitConfigInternal.h
===================================================================
--- code/trunk/src/sljit/sljitConfigInternal.h    2016-12-08 18:56:24 UTC (rev 613)
+++ code/trunk/src/sljit/sljitConfigInternal.h    2016-12-09 14:22:11 UTC (rev 614)
@@ -545,8 +545,16 @@
 SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
 #define SLJIT_MALLOC_EXEC(size) sljit_malloc_exec(size)
 #define SLJIT_FREE_EXEC(ptr) sljit_free_exec(ptr)
+
+#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_enable_exec(void* from, void *to);
+#define SLJIT_ENABLE_EXEC(from, to) sljit_enable_exec((from), (to))
+#else
+#define SLJIT_ENABLE_EXEC(from, to)
 #endif


+#endif
+
/**********************************************/
/* Registers and locals offset determination. */
/**********************************************/

Modified: code/trunk/src/sljit/sljitLir.c
===================================================================
--- code/trunk/src/sljit/sljitLir.c    2016-12-08 18:56:24 UTC (rev 613)
+++ code/trunk/src/sljit/sljitLir.c    2016-12-09 14:22:11 UTC (rev 614)
@@ -242,9 +242,15 @@
 #if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)


#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
+
+#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)
+#include "sljitProtExecAllocator.c"
+#else
#include "sljitExecAllocator.c"
#endif

+#endif
+
/* Argument checking features. */

 #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
@@ -283,6 +289,13 @@
         } \
     } while (0)


+#define CHECK_DYN_CODE_MOD(extra_check) \
+    if ((extra_check) && !sljit_is_dyn_code_modification_enabled()) \
+    { \
+        compiler->error = SLJIT_ERR_DYN_CODE_MOD; \
+        return NULL; \
+    }
+
 #elif (defined SLJIT_DEBUG && SLJIT_DEBUG)


/* Assertion failure occures if an invalid argument is passed. */
@@ -295,6 +308,7 @@
#define CHECK(x) x
#define CHECK_PTR(x) x
#define CHECK_REG_INDEX(x) x
+#define CHECK_DYN_CODE_MOD(extra_check) SLJIT_ASSERT(!(extra_check) || sljit_is_dyn_code_modification_enabled())

#elif (defined SLJIT_VERBOSE && SLJIT_VERBOSE)

@@ -304,6 +318,7 @@
#define CHECK(x) x
#define CHECK_PTR(x) x
#define CHECK_REG_INDEX(x) x
+#define CHECK_DYN_CODE_MOD(extra_check)

#else

@@ -311,6 +326,7 @@
#define CHECK(x)
#define CHECK_PTR(x)
#define CHECK_REG_INDEX(x)
+#define CHECK_DYN_CODE_MOD(extra_check)

#endif /* SLJIT_ARGUMENT_CHECKS */

@@ -441,6 +457,15 @@
         compiler->error = SLJIT_ERR_ALLOC_FAILED;
 }


+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_dyn_code_modification_enabled(void)
+{
+#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) \
+        && (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)
+    return 0;
+#endif
+    return 1;
+}
+
 #if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
 SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code)
 {
@@ -1601,6 +1626,7 @@
     sljit_sw tmp_srcw;


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
     CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));


     condition = type & 0xff;
@@ -1681,6 +1707,7 @@
     sljit_s32 flags, condition;


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
     CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w));


     condition = type & 0xff;


Modified: code/trunk/src/sljit/sljitLir.h
===================================================================
--- code/trunk/src/sljit/sljitLir.h    2016-12-08 18:56:24 UTC (rev 613)
+++ code/trunk/src/sljit/sljitLir.h    2016-12-09 14:22:11 UTC (rev 614)
@@ -99,6 +99,8 @@
 #define SLJIT_ERR_UNSUPPORTED        4
 /* An ivalid argument is passed to any SLJIT function. */
 #define SLJIT_ERR_BAD_ARGUMENT        5
+/* Dynamic code modification is not enabled. */
+#define SLJIT_ERR_DYN_CODE_MOD        6


 /* --------------------------------------------------------------------- */
 /*  Registers                                                            */
@@ -455,7 +457,19 @@
 SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose);
 #endif


+/* Returns with non-zero if dynamic code modification is enabled. */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_is_dyn_code_modification_enabled(void);
+
+/*
+ Create executable code from the sljit instruction stream. This is the final step
+ of the code generation so no more instructions can be added after this call.
+*/
+
SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler);
+
+/* Free executable code. */
+
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code);

/*

Modified: code/trunk/src/sljit/sljitNativeARM_32.c
===================================================================
--- code/trunk/src/sljit/sljitNativeARM_32.c    2016-12-08 18:56:24 UTC (rev 613)
+++ code/trunk/src/sljit/sljitNativeARM_32.c    2016-12-09 14:22:11 UTC (rev 614)
@@ -793,6 +793,7 @@


     compiler->error = SLJIT_ERR_COMPILED;
     compiler->executable_size = (code_ptr - code) * sizeof(sljit_uw);
+    SLJIT_ENABLE_EXEC(code, code_ptr);
     SLJIT_CACHE_FLUSH(code, code_ptr);
     return code;
 }
@@ -2402,6 +2403,7 @@
     struct sljit_jump *jump;


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
     CHECK_PTR(check_sljit_emit_jump(compiler, type));


     jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
@@ -2534,6 +2536,7 @@
     sljit_s32 reg;


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(1);
     CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
     ADJUST_LOCAL_OFFSET(dst, dstw);



Modified: code/trunk/src/sljit/sljitNativeARM_64.c
===================================================================
--- code/trunk/src/sljit/sljitNativeARM_64.c    2016-12-08 18:56:24 UTC (rev 613)
+++ code/trunk/src/sljit/sljitNativeARM_64.c    2016-12-09 14:22:11 UTC (rev 614)
@@ -309,6 +309,7 @@


     compiler->error = SLJIT_ERR_COMPILED;
     compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
+    SLJIT_ENABLE_EXEC(code, code_ptr);
     SLJIT_CACHE_FLUSH(code, code_ptr);
     return code;
 }
@@ -1882,6 +1883,7 @@
     struct sljit_jump *jump;


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
     CHECK_PTR(check_sljit_emit_jump(compiler, type));


     jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
@@ -2020,6 +2022,7 @@
     sljit_s32 dst_r;


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(1);
     CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
     ADJUST_LOCAL_OFFSET(dst, dstw);



Modified: code/trunk/src/sljit/sljitNativeARM_T2_32.c
===================================================================
--- code/trunk/src/sljit/sljitNativeARM_T2_32.c    2016-12-08 18:56:24 UTC (rev 613)
+++ code/trunk/src/sljit/sljitNativeARM_T2_32.c    2016-12-09 14:22:11 UTC (rev 614)
@@ -415,6 +415,7 @@


     compiler->error = SLJIT_ERR_COMPILED;
     compiler->executable_size = (code_ptr - code) * sizeof(sljit_u16);
+    SLJIT_ENABLE_EXEC(code, code_ptr);
     SLJIT_CACHE_FLUSH(code, code_ptr);
     /* Set thumb mode flag. */
     return (void*)((sljit_uw)code | 0x1);
@@ -1917,6 +1918,7 @@
     sljit_ins cc;


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
     CHECK_PTR(check_sljit_emit_jump(compiler, type));


     jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
@@ -2060,6 +2062,7 @@
     sljit_s32 dst_r;


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(1);
     CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
     ADJUST_LOCAL_OFFSET(dst, dstw);



Modified: code/trunk/src/sljit/sljitNativeMIPS_common.c
===================================================================
--- code/trunk/src/sljit/sljitNativeMIPS_common.c    2016-12-08 18:56:24 UTC (rev 613)
+++ code/trunk/src/sljit/sljitNativeMIPS_common.c    2016-12-09 14:22:11 UTC (rev 614)
@@ -477,6 +477,7 @@


     compiler->error = SLJIT_ERR_COMPILED;
     compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
+    SLJIT_ENABLE_EXEC(code, code_ptr);
 #ifndef __GNUC__
     SLJIT_CACHE_FLUSH(code, code_ptr);
 #else
@@ -1625,6 +1626,7 @@
     sljit_s32 delay_check = UNMOVABLE_INS;


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
     CHECK_PTR(check_sljit_emit_jump(compiler, type));


     jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
@@ -1742,6 +1744,7 @@
     sljit_ins inst;


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
     CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));
     ADJUST_LOCAL_OFFSET(src1, src1w);
     ADJUST_LOCAL_OFFSET(src2, src2w);
@@ -1863,6 +1866,7 @@
     sljit_s32 if_true;


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
     CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w));


     compiler->cache_arg = 0;
@@ -2121,6 +2125,7 @@
     sljit_s32 reg;


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(1);
     CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
     ADJUST_LOCAL_OFFSET(dst, dstw);



Modified: code/trunk/src/sljit/sljitNativePPC_common.c
===================================================================
--- code/trunk/src/sljit/sljitNativePPC_common.c    2016-12-08 18:56:24 UTC (rev 613)
+++ code/trunk/src/sljit/sljitNativePPC_common.c    2016-12-09 14:22:11 UTC (rev 614)
@@ -493,6 +493,7 @@


     compiler->error = SLJIT_ERR_COMPILED;
     compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
+    SLJIT_ENABLE_EXEC(code, code_ptr);
     SLJIT_CACHE_FLUSH(code, code_ptr);


 #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
@@ -2138,6 +2139,7 @@
     sljit_ins bo_bi_flags;


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
     CHECK_PTR(check_sljit_emit_jump(compiler, type));


     bo_bi_flags = get_bo_bi_flags(type & 0xff);
@@ -2362,6 +2364,7 @@
     sljit_s32 reg;


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(1);
     CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
     ADJUST_LOCAL_OFFSET(dst, dstw);



Modified: code/trunk/src/sljit/sljitNativeSPARC_common.c
===================================================================
--- code/trunk/src/sljit/sljitNativeSPARC_common.c    2016-12-08 18:56:24 UTC (rev 613)
+++ code/trunk/src/sljit/sljitNativeSPARC_common.c    2016-12-09 14:22:11 UTC (rev 614)
@@ -379,6 +379,7 @@


     compiler->error = SLJIT_ERR_COMPILED;
     compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
+    SLJIT_ENABLE_EXEC(code, code_ptr);
     SLJIT_CACHE_FLUSH(code, code_ptr);
     return code;
 }
@@ -1295,6 +1296,7 @@
     struct sljit_jump *jump;


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
     CHECK_PTR(check_sljit_emit_jump(compiler, type));


     jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
@@ -1422,6 +1424,7 @@
     struct sljit_const *const_;


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(1);
     CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
     ADJUST_LOCAL_OFFSET(dst, dstw);



Modified: code/trunk/src/sljit/sljitNativeTILEGX_64.c
===================================================================
--- code/trunk/src/sljit/sljitNativeTILEGX_64.c    2016-12-08 18:56:24 UTC (rev 613)
+++ code/trunk/src/sljit/sljitNativeTILEGX_64.c    2016-12-09 14:22:11 UTC (rev 614)
@@ -1113,6 +1113,7 @@


     compiler->error = SLJIT_ERR_COMPILED;
     compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
+    SLJIT_ENABLE_EXEC(code, code_ptr);
     SLJIT_CACHE_FLUSH(code, code_ptr);
     return code;
 }
@@ -2412,6 +2413,7 @@
     flush_buffer(compiler);


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
     CHECK_PTR(check_sljit_emit_jump(compiler, type));


     jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump));
@@ -2510,6 +2512,7 @@
     flush_buffer(compiler);


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(1);
     CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
     ADJUST_LOCAL_OFFSET(dst, dstw);



Modified: code/trunk/src/sljit/sljitNativeX86_common.c
===================================================================
--- code/trunk/src/sljit/sljitNativeX86_common.c    2016-12-08 18:56:24 UTC (rev 613)
+++ code/trunk/src/sljit/sljitNativeX86_common.c    2016-12-09 14:22:11 UTC (rev 614)
@@ -581,6 +581,7 @@
     SLJIT_ASSERT(code_ptr <= code + compiler->size);
     compiler->error = SLJIT_ERR_COMPILED;
     compiler->executable_size = code_ptr - code;
+    SLJIT_ENABLE_EXEC(code, code_ptr);
     return (void*)code;
 }


@@ -2580,6 +2581,7 @@
     struct sljit_jump *jump;


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(type & SLJIT_REWRITABLE_JUMP);
     CHECK_PTR(check_sljit_emit_jump(compiler, type));


     if (SLJIT_UNLIKELY(compiler->flags_saved)) {
@@ -2908,6 +2910,7 @@
 #endif


     CHECK_ERROR_PTR();
+    CHECK_DYN_CODE_MOD(1);
     CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
     ADJUST_LOCAL_OFFSET(dst, dstw);



Added: code/trunk/src/sljit/sljitProtExecAllocator.c
===================================================================
--- code/trunk/src/sljit/sljitProtExecAllocator.c                            (rev 0)
+++ code/trunk/src/sljit/sljitProtExecAllocator.c    2016-12-09 14:22:11 UTC (rev 614)
@@ -0,0 +1,113 @@
+/*
+ *    Stack-less Just-In-Time compiler
+ *
+ *    Copyright 2009-2012 Zoltan Herczeg (hzmester@???). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright notice, this list of
+ *      conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright notice, this list
+ *      of conditions and the following disclaimer in the documentation and/or other materials
+ *      provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+   This file contains a simple executable memory allocator where the
+   allocated regions are not writable and executable in the same time.
+
+   This allocator usually uses more memory than sljitExecAllocator.
+*/
+
+#ifdef _WIN32
+
+static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
+{
+    return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+}
+
+static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
+{
+    SLJIT_UNUSED_ARG(size);
+    VirtualFree(chunk, 0, MEM_RELEASE);
+}
+
+static SLJIT_INLINE void enable_exec_permission(void* chunk, sljit_uw size)
+{
+    sljit_uw *uw_ptr = (sljit_uw *)ptr;
+
+    VirtualProtect(chunk, size, PAGE_EXECUTE_READ, NULL);
+}
+
+#else
+
+static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
+{
+    void* retval;
+
+#ifdef MAP_ANON
+    retval = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+#else
+    if (dev_zero < 0) {
+        if (open_dev_zero())
+            return NULL;
+    }
+    retval = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);
+#endif
+
+    return (retval != MAP_FAILED) ? retval : NULL;
+}
+
+static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
+{
+    munmap(chunk, size);
+}
+
+static SLJIT_INLINE void enable_exec_permission(void* chunk, sljit_uw size)
+{
+    sljit_uw *uw_ptr = (sljit_uw *)chunk;
+
+    mprotect(uw_ptr - 1, size + sizeof(sljit_uw), PROT_READ | PROT_EXEC);
+}
+
+#endif
+
+/* --------------------------------------------------------------------- */
+/*  Common functions                                                     */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
+{
+    sljit_uw *ptr = (sljit_uw *)alloc_chunk(size + sizeof (sljit_uw));
+
+    *ptr = size;
+    return (void*)(ptr + 1);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
+{
+    sljit_uw *uw_ptr = (sljit_uw *)ptr;
+
+    free_chunk(uw_ptr - 1, uw_ptr[-1]);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_enable_exec(void* from, void *to)
+{
+    enable_exec_permission(from, ((sljit_u8 *)to) - ((sljit_u8 *)from));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
+{
+}