36#include <mach/vm_statistics.h>
41#include <sys/procctl.h>
44#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
45# define MAP_ANONYMOUS MAP_ANON
47#if defined(MAP_ALIGNED_SUPER)
48# include <sys/types.h>
49# include <sys/sysctl.h>
51# define MAP_HUGETLB MAP_ALIGNED_SUPER
54#if defined(HAVE_JIT) && (defined(__linux__) || defined(__FreeBSD__)) && (defined(__x86_64__) || defined (__aarch64__)) && !defined(__SANITIZE_ADDRESS__)
55static void *find_prefered_mmap_base(
size_t requested_size)
57 size_t huge_page_size = 2 * 1024 * 1024;
58 uintptr_t last_free_addr = huge_page_size;
59 uintptr_t last_candidate = (uintptr_t)
MAP_FAILED;
60 uintptr_t
start,
end, text_start = 0;
65 f =
fopen(
"/proc/self/maps",
"r");
77 uintptr_t start_base =
start & ~(huge_page_size - 1);
78 if (last_free_addr + requested_size >= start_base) {
87 if (last_free_addr + requested_size <=
start) {
89 if (last_candidate + requested_size >
start) {
90 last_candidate -= huge_page_size;
106 if (last_free_addr + requested_size - text_start >
UINT32_MAX) {
110 if (last_free_addr + requested_size <=
start) {
111 last_candidate = last_free_addr;
117 last_free_addr += huge_page_size;
121#elif defined(__FreeBSD__)
123 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid()};
124 if (sysctl(mib, 4,
NULL, &
s,
NULL, 0) == 0) {
128 if (sysctl(mib, 4,
addr, &
s,
NULL, 0) == 0) {
132 struct kinfo_vmentry *entry = (
struct kinfo_vmentry *)
start;
133 size_t sz = entry->kve_structsize;
137 uintptr_t e_start = entry->kve_start;
138 uintptr_t e_end = entry->kve_end;
141 if (last_free_addr + requested_size <= e_start) {
143 if (last_candidate + requested_size > e_start) {
144 last_candidate -= huge_page_size;
149 if (last_candidate != (uintptr_t)
MAP_FAILED) {
156 text_start = e_start;
160 if (last_free_addr + requested_size - text_start >
UINT32_MAX) {
164 if (last_free_addr + requested_size <= e_start) {
165 last_candidate = last_free_addr;
178 return (
void*)last_candidate;
182static int create_segments(
size_t requested_size,
zend_shared_segment ***shared_segments_p,
int *shared_segments_count,
const char **error_in)
187#if defined(HAVE_PROCCTL) && defined(PROC_WXMAP_CTL)
188 int enable_wxmap = PROC_WX_MAPPINGS_PERMIT;
189 if (procctl(
P_PID, getpid(), PROC_WXMAP_CTL, &enable_wxmap) == -1) {
194 flags |= PROT_MPROTECT(PROT_EXEC);
198 fd = VM_MAKE_TAG(251U);
203#if defined(HAVE_JIT) && (defined(__linux__) || defined(__FreeBSD__)) && (defined(__x86_64__) || defined (__aarch64__)) && !defined(__SANITIZE_ADDRESS__)
207 hint = find_prefered_mmap_base(requested_size);
216 size_t huge_page_size = 2 * 1024 * 1024;
217 if (requested_size >= huge_page_size && requested_size % huge_page_size == 0) {
218 p = mmap(hint, requested_size,
flags, MAP_SHARED|MAP_ANONYMOUS|MAP_HUGETLB|MAP_FIXED, -1, 0);
224 p = mmap(hint, requested_size,
flags, MAP_SHARED|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
231 size_t huge_page_size = 2 * 1024 * 1024;
243 if (requested_size >= huge_page_size && requested_size % huge_page_size == 0) {
244# if defined(__x86_64__) && defined(MAP_32BIT)
248 p = mmap(
NULL, requested_size,
flags, MAP_SHARED|MAP_ANONYMOUS|MAP_32BIT,
fd, 0);
250 munmap(
p, requested_size);
252 p = mmap(
p, requested_size,
flags, MAP_SHARED|MAP_ANONYMOUS|MAP_32BIT|MAP_HUGETLB|MAP_FIXED, -1, 0);
256 p = mmap(
NULL, requested_size,
flags, MAP_SHARED|MAP_ANONYMOUS|MAP_32BIT,
fd, 0);
263 p = mmap(0, requested_size,
flags, MAP_SHARED|MAP_ANONYMOUS|MAP_HUGETLB,
fd, 0);
268#elif defined(PREFER_MAP_32BIT) && defined(__x86_64__) && defined(MAP_32BIT)
269 p = mmap(
NULL, requested_size,
flags, MAP_SHARED|MAP_ANONYMOUS|MAP_32BIT,
fd, 0);
275 p = mmap(0, requested_size,
flags, MAP_SHARED|MAP_ANONYMOUS,
fd, 0);
282 *shared_segments_count = 1;
284 if (!*shared_segments_p) {
285 munmap(
p, requested_size);
286 *error_in =
"calloc";
290 (*shared_segments_p)[0] = shared_segment;
292 shared_segment->
p =
p;
293 shared_segment->
pos = 0;
294 shared_segment->
size = requested_size;
301 munmap(shared_segment->
p, shared_segment->
size);
305static size_t segment_type_size(
void)
sscanf(string $string, string $format, mixed &... $vars)
fopen(string $filename, string $mode, bool $use_include_path=false, $context=null)
strstr(string $haystack, string $needle, bool $before_needle=false)
fgets($stream, ?int $length=null)
unsigned const char * end
#define ZEND_MM_ALIGNED_SIZE_EX(size, alignment)
ZEND_API void execute_ex(zend_execute_data *execute_data)
int zend_jit_check_support(void)
#define ZEND_ATTRIBUTE_UNUSED
struct _zend_shared_segment zend_shared_segment